most stuff seem to work without errors

This commit is contained in:
Henry Jameson 2026-01-23 00:17:27 +02:00
commit 80e09efd71
22 changed files with 116 additions and 155 deletions

View file

@ -1,8 +1,10 @@
import { throttle } from 'lodash'
import { mapState } from 'pinia'
import { mapActions, mapState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import { mapGetters } from 'vuex'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useShoutStore } from 'src/stores/shout.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import DesktopNav from './components/desktop_nav/desktop_nav.vue'
import EditStatusModal from './components/edit_status_modal/edit_status_modal.vue'
@ -22,9 +24,6 @@ import UserReportingModal from './components/user_reporting_modal/user_reporting
import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue'
import { getOrCreateServiceWorker } from './services/sw/sw'
import { windowHeight, windowWidth } from './services/window_utils/window_utils'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useShoutStore } from 'src/stores/shout.js'
export default {
name: 'app',
@ -155,16 +154,7 @@ export default {
newPostButtonShown() {
if (this.isChats) return false
if (this.isListEdit) return false
return (
useSyncConfigStore().mergedConfig.alwaysShowNewPostButton ||
this.layoutType === 'mobile'
)
},
shoutboxPosition() {
return useSyncConfigStore().mergedConfig.alwaysShowNewPostButton || false
},
layoutType() {
return useInterfaceStore().layoutType
return (this.alwaysShowNewPostButton || this.layoutType === 'mobile')
},
reverseLayout() {
const { thirdColumnMode, sidebarRight: reverseSetting } =
@ -177,19 +167,23 @@ export default {
: !reverseSetting
}
},
noSticky() {
return useSyncConfigStore().mergedConfig.disableStickyHeaders
},
showScrollbars() {
return useSyncConfigStore().mergedConfig.showScrollbars
},
scrollParent() {
return window /* this.$refs.appContentRef */
},
...mapGetters(['mergedConfig']),
...mapState(useSyncConfigStore, {
shoutboxPosition: (store) => store.mergedConfig.alwaysShowSubjectInput || false,
alwaysShowSubjectInput: (store) => store.mergedConfig.alwaysShowSubjectInput,
}),
...mapState(useInterfaceStore, ['layoutType']),
...mapState(useSyncConfigStore, {
hideShoutbox: (store) => store.mergedConfig.hideShoutbox,
noSticky: (store) => store.mergedConfig.disableStickyHeaders,
showScrollbars: (store) => store.mergedConfig.showScrollbars,
}),
...mapState(useInstanceStore, {
instanceBackground: (store) =>
this.mergedConfig.hideInstanceWallpaper ? null : store.background,
@ -207,8 +201,8 @@ export default {
},
methods: {
resizeHandler() {
useInterfaceStore().setLayoutWidth(windowWidth())
useInterfaceStore().setLayoutHeight(windowHeight())
this.setLayoutWidth(windowWidth())
this.setLayoutHeight(windowHeight())
},
scrollHandler() {
const scrollPosition =
@ -255,5 +249,6 @@ export default {
splashscreenRoot.classList.add('hidden')
document.querySelector('#app').classList.remove('hidden')
},
...mapActions(useInterfaceStore, ['setLayoutWidth', 'setLayoutHeight']),
},
}

View file

@ -1,5 +1,5 @@
import { mapGetters } from 'vuex'
import { mapState } from 'pinia'
import { mapGetters } from 'vuex'
import { useInstanceStore } from 'src/stores/instance.js'
import { useMediaViewerStore } from 'src/stores/media_viewer'
@ -56,7 +56,8 @@ const Attachment = {
data() {
return {
localDescription: this.description || this.attachment.description,
nsfwImage: useInstanceStore().instanceIdentity.nsfwCensorImage || nsfwImage,
nsfwImage:
useInstanceStore().instanceIdentity.nsfwCensorImage || nsfwImage,
hideNsfwLocal: useSyncConfigStore().mergedConfig.hideNsfw,
preloadImage: useSyncConfigStore().mergedConfig.preloadImage,
loading: false,

View file

@ -3,8 +3,8 @@ import { defineAsyncComponent } from 'vue'
import Popover from 'src/components/popover/popover.vue'
import { ensureFinalFallback } from 'src/i18n/languages.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useEmojiStore } from 'src/stores/emoji.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import Checkbox from '../checkbox/checkbox.vue'
import StillImage from '../still-image/still-image.vue'

View file

@ -1,9 +1,9 @@
import { mapState as mapPiniaState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import { mapGetters, mapState } from 'vuex'
import { mapState as mapPiniaState } from 'pinia'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import {
highlightClass,
highlightStyle,
@ -99,7 +99,10 @@ const MentionLink = {
return this.user && this.user.screen_name_ui
},
highlight() {
return this.user && useSyncConfigStore().mergedConfig.highlight[this.user.screen_name]
return (
this.user &&
useSyncConfigStore().mergedConfig.highlight[this.user.screen_name]
)
},
highlightType() {
return this.highlight && '-' + this.highlight.type

View file

@ -117,8 +117,7 @@ const NavPanel = {
new Set(store.prefsStorage.collections.pinnedNavItems),
}),
...mapPiniaState(useInstanceStore, {
bubbleTimeline: (store) =>
store.featureSet.localBubble,
bubbleTimeline: (store) => store.featureSet.localBubble,
pleromaChatMessagesAvailable: (store) =>
store.featureSet.pleromaChatMessagesAvailable,
bookmarkFolders: (store) =>

View file

@ -77,8 +77,7 @@ const NavPanel = {
federating: (store) => store.featureSet.federating,
pleromaChatMessagesAvailable: (store) =>
store.featureSet.pleromaChatMessagesAvailable,
bubbleTimelinesSupported: (store) =>
store.featureSet.localBubble,
bubbleTimelinesSupported: (store) => store.featureSet.localBubble,
}),
...mapState({
currentUser: (state) => state.users.currentUser,

View file

@ -183,7 +183,7 @@ const PostStatusForm = {
}
const scope =
(this.copyMessageScope && this.scopeCopy) ||
(this.copyMessageScope && this.scopeCopy) ||
this.copyMessageScope === 'direct'
? this.copyMessageScope
: this.$store.state.users.currentUser.default_scope

View file

@ -228,8 +228,6 @@ export default {
},
configSource() {
switch (this.realSource) {
case 'server-side':
return useSyncConfigStore().mergedConfig
case 'profile':
return this.$store.state.profileConfig
case 'admin':
@ -242,14 +240,8 @@ export default {
if (this.path == null) {
return (k, v) => this.$emit('update:modelValue', v)
}
switch (this.realSource) {
case 'server-side': {
return (originalPath, value, operator) => {
const path = `simple.${originalPath}`
useSyncConfigStore().setPreference({ path, value })
useSyncConfigStore().pushSyncConfig()
}
}
case 'profile':
return (k, v) =>
this.$store.dispatch('setProfileOption', { name: k, value: v })
@ -257,15 +249,33 @@ export default {
return (k, v) =>
this.$store.dispatch('pushAdminSetting', { path: k, value: v })
default:
if (this.timedApplyMode) {
return (k, v) =>
this.$store.dispatch('setOptionTemporarily', {
name: k,
value: v,
})
} else {
return (k, v) =>
this.$store.dispatch('setOption', { name: k, value: v })
return (originalPath, value) => {
const path = `simple.${originalPath}`
if (!this.timedApplyMode) {
useSyncConfigStore().setPreference({ path, value })
useSyncConfigStore().pushSyncConfig()
} else {
if (useInterfaceStore().temporaryChangesTimeoutId !== null) {
console.error("Can't track more than one temporary change")
return
}
useSyncConfigStore().setPreference({ path, value })
const oldValue = get(this.configSource, path)
const confirm = () => {
useSyncConfigStore().pushSyncConfig()
useInterfaceStore().clearTemporaryChanges()
}
const revert = () => {
useSyncConfigStore().setPreference({ path, value: oldValue })
useInterfaceStore().clearTemporaryChanges()
}
useInterfaceStore().setTemporaryChanges({ confirm, revert })
}
}
}
},
@ -273,10 +283,8 @@ export default {
switch (this.realSource) {
case 'profile':
return {}
case 'server-side':
return get(useInstanceStore().prefsStorage, this.path)
default:
return get(this.$store.getters.defaultConfig, this.path)
return get(useInstanceStore().prefsStorage, this.path)
}
},
isProfileSetting() {

View file

@ -4,18 +4,15 @@ import { mapGetters, mapState } from 'vuex'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const SharedComputedObject = () => ({
...mapPiniaState(useSyncConfigStore, ['mergedConfig']),
...mapPiniaState(useSyncConfigStore, {
serverSide: (store) => store.state.prefsStorage,
expertLevel: (store) => store.mergedConfig.expertLevel,
}),
...mapGetters(['mergedConfig']),
...mapState({
adminConfig: (state) => state.adminSettings.config,
adminDraft: (state) => state.adminSettings.draft,
user: (state) => state.users.currentUser,
}),
expertLevel() {
return this.mergedConfig.expertLevel > 0
},
})
export default SharedComputedObject

View file

@ -4,57 +4,38 @@
<h3>{{ $t('settings.interface') }}</h3>
<ul class="setting-list">
<li>
<BooleanSetting
source="server-side"
path="alwaysShowSubjectInput"
>
<BooleanSetting path="alwaysShowSubjectInput">
{{ $t('settings.subject_input_always_show') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
source="server-side"
path="minimalScopesMode"
>
<BooleanSetting path="minimalScopesMode">
{{ $t('settings.minimal_scopes_mode') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
source="server-side"
path="hidePostStats"
>
<BooleanSetting path="hidePostStats">
{{ $t('settings.hide_post_stats') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="hideUserStats"
source="server-side"
>
<BooleanSetting path="hideUserStats">
{{ $t('settings.hide_user_stats') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
source="server-side"
path="hideBotIndication"
>
<BooleanSetting path="hideBotIndication">
{{ $t('settings.hide_actor_type_indication') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
source="server-side"
path="hideScrobbles"
>
<BooleanSetting path="hideScrobbles">
{{ $t('settings.hide_scrobbles') }}
</BooleanSetting>
<ul class="setting-list suboptions">
<li>
<UnitSetting
key="hideScrobblesAfter"
source="server-side"
path="hideScrobblesAfter"
:units="['m', 'h', 'd']"
unit-set="time"
@ -69,7 +50,6 @@
<ul class="setting-list">
<li>
<IntegerSetting
source="server-side"
path="maxThumbnails"
:min="0"
>
@ -77,32 +57,22 @@
</IntegerSetting>
</li>
<li>
<BooleanSetting
source="server-side"
path="hideAttachments"
>
<BooleanSetting path="hideAttachments">
{{ $t('settings.hide_attachments_in_tl') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
source="server-side"
path="hideAttachmentsInConv"
>
<BooleanSetting path="hideAttachmentsInConv">
{{ $t('settings.hide_attachments_in_convo') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
source="server-side"
path="userCardHidePersonalMarks"
>
<BooleanSetting path="userCardHidePersonalMarks">
{{ $t('settings.user_card_hide_personal_marks') }}
</BooleanSetting>
</li>
<li v-if="instanceShoutboxPresent">
<BooleanSetting
source="server-side"
path="hideShoutbox"
>
{{ $t('settings.hide_shoutbox') }}

View file

@ -1,4 +1,6 @@
import { mapState } from 'pinia'
import { cacheKey, clearCache, emojiCacheKey } from 'src/services/sw/sw.js'
import { useInstanceStore } from 'src/stores/instance.js'
import BooleanSetting from '../helpers/boolean_setting.vue'
import SharedComputedObject from '../helpers/shared_computed_object.js'
@ -6,14 +8,6 @@ const pleromaFeCommitUrl =
'https://git.pleroma.social/pleroma/pleroma-fe/commit/'
const VersionTab = {
data() {
const instance = this.$store.state.instance
return {
backendVersion: instance.backendVersion,
backendRepository: instance.backendRepository,
frontendVersion: instance.frontendVersion,
}
},
components: {
BooleanSetting,
},
@ -22,6 +16,11 @@ const VersionTab = {
return pleromaFeCommitUrl + this.frontendVersion
},
...SharedComputedObject(),
...mapState(useInstanceStore, [
'backendVersion',
'backendRepository',
'frontendVersion',
])
},
methods: {
clearAssetCache() {

View file

@ -1,7 +1,6 @@
import { cloneDeep } from 'lodash'
import { mapActions, mapState } from 'pinia'
import { v4 as uuidv4 } from 'uuid'
import { mapState as mapVuexState } from 'vuex'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Select from 'src/components/select/select.vue'
@ -90,18 +89,6 @@ const FilteringTab = {
HelpIndicator,
},
computed: {
instanceSpecificPanelPresent() {
return useInstanceStore().showInstanceSpecificPanel
},
...SharedComputedObject(),
...mapState(useSyncConfigStore, {
muteFilters: (store) =>
Object.entries(store.prefsStorage.simple.muteFilters),
muteFiltersObject: (store) => store.prefsStorage.simple.muteFilters,
}),
...mapVuexState({
blockExpirationSupported: (state) => state.instance.blockExpiration,
}),
onMuteDefaultActionLv1: {
get() {
const value = this.$store.state.config.onMuteDefaultAction
@ -151,6 +138,16 @@ const FilteringTab = {
([, { expires }]) => expires != null && expires <= now,
)
},
...mapState(useInstanceStore, {
instanceSpecificPanelPresent: (store) => store.showInstanceSpecificPanel,
blockExpirationSupported: (store) => store.blockExpiration,
}),
...SharedComputedObject(),
...mapState(useSyncConfigStore, {
muteFilters: (store) =>
Object.entries(store.prefsStorage.simple.muteFilters),
muteFiltersObject: (store) => store.prefsStorage.simple.muteFilters,
}),
},
methods: {
...mapActions(useSyncConfigStore, [

View file

@ -1,4 +1,4 @@
import { mapState } from 'vuex'
import { mapState } from 'pinia'
import FontControl from 'src/components/font_control/font_control.vue'
import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
@ -44,15 +44,18 @@ const GeneralTab = {
return useSyncConfigStore().mergedConfig.interfaceLanguage
},
set: function (val) {
this.$store.dispatch('setOption', {
name: 'interfaceLanguage',
useSyncConfigStore().setPreference({
path: 'simple.interfaceLanguage',
value: val,
})
},
},
...SharedComputedObject(),
...mapState({
blockExpirationSupported: (state) => state.instance.blockExpiration,
...mapState(useSyncConfigStore, {
theme3hacks: (store) => store.mergedConfig.theme3hacks,
}),
...mapState(useInstanceStore, {
blockExpirationSupported: (store) => store.featureSet.blockExpiration,
}),
},
methods: {
@ -71,15 +74,9 @@ const GeneralTab = {
})
},
updateFont(key, value) {
this.$store.dispatch('setOption', {
name: 'theme3hacks',
value: {
...this.mergedConfig.theme3hacks,
fonts: {
...this.mergedConfig.theme3hacks.fonts,
[key]: value,
},
},
useSyncConfigStore().setPreference({
path: `simple.theme3hacks.fonts.${key}`,
value
})
},
},

View file

@ -68,7 +68,7 @@
</li>
<li>
<FontControl
:model-value="mergedConfig.theme3hacks.fonts.interface"
:model-value="theme3hacks.fonts.interface"
name="ui"
:label="$t('settings.style.fonts.components_inline.interface')"
:fallback="{ family: 'sans-serif' }"
@ -78,7 +78,7 @@
</li>
<li>
<FontControl
:model-value="mergedConfig.theme3hacks.fonts.input"
:model-value="theme3hacks.fonts.input"
name="input"
:fallback="{ family: 'inherit' }"
:label="$t('settings.style.fonts.components_inline.input')"

View file

@ -50,7 +50,7 @@ const MutesAndBlocks = {
},
created() {
useOAuthTokensStore().fetchTokens()
this.$store.dispatch('getKnownDomains')
useInstanceStore().getKnownDomains()
},
components: {
TabSwitcher,

View file

@ -159,7 +159,7 @@ export const BUTTONS = [
icon: 'history',
label: 'status.status_history',
if({ status, instance }) {
return instance.editingAvailable && status.edited_at !== null
return instance.featureSet.editingAvailable && status.edited_at !== null
},
action({ status }) {
const originalStatus = { ...status }
@ -189,7 +189,7 @@ export const BUTTONS = [
if({ status, loggedIn, currentUser, instance }) {
return (
loggedIn &&
instance.editingAvailable &&
instance.featureSet.editingAvailable &&
status.user.id === currentUser.id
)
},

View file

@ -3,8 +3,8 @@ import { mapState } from 'pinia'
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
import Popover from 'src/components/popover/popover.vue'
import genRandomSeed from 'src/services/random_seed/random_seed.service.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import ActionButtonContainer from './action_button_container.vue'
import { BUTTONS } from './buttons_definitions.js'

View file

@ -66,8 +66,7 @@ const TimelineMenu = {
...mapPiniaState(useInstanceStore, {
bookmarkFolders: (state) =>
state.featureSet.pleromaBookmarkFoldersAvailable,
bubbleTimeline: (state) =>
state.featureSet.localBubble,
bubbleTimeline: (state) => state.featureSet.localBubble,
privateMode: (state) => state.private,
federating: (state) => state.federating,
}),

View file

@ -15,9 +15,10 @@ import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_ti
import { propsToNative } from 'src/services/attributes_helper/attributes_helper.service.js'
import localeService from 'src/services/locale/locale.service.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
import { useInstanceStore } from 'src/stores/instance.js'
import { usePostStatusStore } from 'src/stores/post_status'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useEmojiStore } from 'src/stores/emoji.js'
import { useInterfaceStore } from '../../stores/interface'
import { useMediaViewerStore } from '../../stores/media_viewer'
import AccountActions from '../account_actions/account_actions.vue'
@ -334,16 +335,10 @@ export default {
return this.newBanner === null ? currentUrl : newUrl
},
defaultAvatar() {
return (
useInstanceStore().server +
useInstanceStore().defaultAvatar
)
return useInstanceStore().server + useInstanceStore().defaultAvatar
},
defaultBanner() {
return (
useInstanceStore().server +
useInstanceStore().defaultBanner
)
return useInstanceStore().server + useInstanceStore().defaultBanner
},
isDefaultAvatar() {
const baseAvatar = useInstanceStore().defaultAvatar

View file

@ -10,11 +10,11 @@ import {
} from 'lodash'
import { declarations } from 'src/modules/config_declaration'
import { useEmojiStore } from 'src/stores/emoji.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { useEmojiStore } from 'src/stores/emoji.js'
import apiService from '../services/api/api.service.js'
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
import oauthApi from '../services/new_api/oauth.js'

View file

@ -213,7 +213,9 @@ export const useEmojiStore = defineStore('emoji', {
const imageUrl = value.image_url
return {
displayText: key,
imageUrl: imageUrl ? useInstanceStore().server + imageUrl : value,
imageUrl: imageUrl
? useInstanceStore().server + imageUrl
: value,
tags: imageUrl
? value.tags.sort((a, b) => (a > b ? 1 : 0))
: ['utf'],

View file

@ -575,7 +575,7 @@ export const useInterfaceStore = defineStore('interface', {
},
async applyTheme({ recompile = false } = {}) {
const { forceThemeRecompilation, themeDebug, theme3hacks } =
window.vuex.state.config
useSyncConfigStore().mergedConfig
this.themeChangeInProgress = true
// If we're not forced to recompile try using
// cache (tryLoadCache return true if load successful)