MASSIVE refactor, replacing instance module with store, separating emoji stuff into its own store, making sure everything refers to new stores (WIP)

This commit is contained in:
Henry Jameson 2026-01-22 17:16:51 +02:00
commit 5bdf341560
95 changed files with 801 additions and 833 deletions

View file

@ -6,6 +6,7 @@ import StillImage from 'components/still-image/still-image.vue'
import { assign, clone } from 'lodash'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface'
import EmojiEditingPopover from '../helpers/emoji_editing_popover.vue'
import ModifiedIndicator from '../helpers/modified_indicator.vue'
@ -102,7 +103,7 @@ const EmojiTab = {
// Remote pack
return `${this.pack.remote.instance}/emoji/${encodeURIComponent(this.pack.remote.baseName)}/${name}`
} else {
return `${this.$store.state.instance.server}/emoji/${encodeURIComponent(this.packName)}/${name}`
return `${useInstanceStore().server}/emoji/${encodeURIComponent(this.packName)}/${name}`
}
},

View file

@ -1,6 +1,7 @@
import Attachment from 'src/components/attachment/attachment.vue'
import MediaUpload from 'src/components/media_upload/media_upload.vue'
import { fileTypeExt } from 'src/services/file_type/file_type.service.js'
import { useInstanceStore } from 'src/stores/instance.js'
import Setting from './setting.js'
export default {
@ -24,9 +25,7 @@ export default {
attachment() {
const path = this.realDraftMode ? this.draft : this.state
// The "server" part is primarily for local dev, but could be useful for alt-domain or multiuser usage.
const url = path.includes('://')
? path
: this.$store.state.instance.server + path
const url = path.includes('://') ? path : useInstanceStore().server + path
return {
mimetype: fileTypeExt(url),
url,

View file

@ -4,6 +4,7 @@ import Attachment from 'src/components/attachment/attachment.vue'
import MediaUpload from 'src/components/media_upload/media_upload.vue'
import Select from 'src/components/select/select.vue'
import { fileTypeExt } from 'src/services/file_type/file_type.service.js'
import { useInstanceStore } from 'src/stores/instance.js'
import Setting from './setting.js'
export default {
@ -34,9 +35,7 @@ export default {
url: '',
}
}
const url = path.includes('://')
? path
: this.$store.state.instance.server + path
const url = path.includes('://') ? path : useInstanceStore().server + path
return {
mimetype: fileTypeExt(url),

View file

@ -1,7 +1,7 @@
import { cloneDeep, get, isEqual, set } from 'lodash'
import { useInstanceStore } from 'src/stores/instance'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import DraftButtons from './draft_buttons.vue'
import ModifiedIndicator from './modified_indicator.vue'
import ProfileSettingIndicator from './profile_setting_indicator.vue'
@ -229,13 +229,13 @@ export default {
configSource() {
switch (this.realSource) {
case 'server-side':
return useServerSideStorageStore().mergedConfig
return useSyncConfigStore().mergedConfig
case 'profile':
return this.$store.state.profileConfig
case 'admin':
return this.$store.state.adminSettings.config
default:
return this.$store.getters.mergedConfig
return useSyncConfigStore().mergedConfig
}
},
configSink() {
@ -246,8 +246,8 @@ export default {
case 'server-side': {
return (originalPath, value, operator) => {
const path = `simple.${originalPath}`
useServerSideStorageStore().setPreference({ path, value })
useServerSideStorageStore().pushServerSideStorage()
useSyncConfigStore().setPreference({ path, value })
useSyncConfigStore().pushSyncConfig()
}
}
case 'profile':
@ -353,7 +353,7 @@ export default {
this.draft = cloneDeep(this.state)
} else {
set(
this.$store.getters.mergedConfig,
useSyncConfigStore().mergedConfig,
this.path,
cloneDeep(this.defaultState),
)

View file

@ -1,10 +1,10 @@
import { mapState as mapPiniaState } from 'pinia'
import { mapGetters, mapState } from 'vuex'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const SharedComputedObject = () => ({
...mapPiniaState(useServerSideStorageStore, {
...mapPiniaState(useSyncConfigStore, {
serverSide: (store) => store.state.prefsStorage,
}),
...mapGetters(['mergedConfig']),

View file

@ -11,7 +11,9 @@ import { getCssRules } from 'src/services/theme_data/css_utils.js'
import { deserialize } from 'src/services/theme_data/iss_deserializer.js'
import { init } from 'src/services/theme_data/theme_data_3.service.js'
import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { normalizeThemeData, useInterfaceStore } from 'src/stores/interface'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
import FloatSetting from '../helpers/float_setting.vue'
@ -83,7 +85,7 @@ const AppearanceTab = {
const updateIndex = (resource) => {
const capitalizedResource = resource[0].toUpperCase() + resource.slice(1)
const currentIndex = this.$store.state.instance[`${resource}sIndex`]
const currentIndex = useInstanceStore()[`${resource}sIndex`]
let promise
if (currentIndex) {
@ -273,11 +275,11 @@ const AppearanceTab = {
return !window.IntersectionObserver
},
instanceWallpaper() {
this.$store.state.instance.background
useInstanceStore().background
},
instanceWallpaperUsed() {
return (
this.$store.state.instance.background &&
useInstanceStore().background &&
!this.$store.state.users.currentUser.background_image
)
},
@ -332,20 +334,13 @@ const AppearanceTab = {
}
},
isThemeActive(key) {
return (
key === (this.mergedConfig.theme || this.$store.state.instance.theme)
)
return key === (this.mergedConfig.theme || useInstanceStore().theme)
},
isStyleActive(key) {
return (
key === (this.mergedConfig.style || this.$store.state.instance.style)
)
return key === (this.mergedConfig.style || useInstanceStore().style)
},
isPaletteActive(key) {
return (
key ===
(this.mergedConfig.palette || this.$store.state.instance.palette)
)
return key === (this.mergedConfig.palette || useInstanceStore().palette)
},
...mapActions(useInterfaceStore, ['setStyle', 'setTheme']),
setPalette(name, data) {
@ -431,10 +426,10 @@ const AppearanceTab = {
if (!file) {
return
}
if (file.size > this.$store.state.instance[slot + 'limit']) {
if (file.size > useInstanceStore()[slot + 'limit']) {
const filesize = fileSizeFormatService.fileSizeFormat(file.size)
const allowedsize = fileSizeFormatService.fileSizeFormat(
this.$store.state.instance[slot + 'limit'],
useInstanceStore()[slot + 'limit'],
)
useInterfaceStore().pushGlobalNotice({
messageKey: 'upload.error.message',

View file

@ -4,7 +4,8 @@ import { mapState as mapVuexState } from 'vuex'
import Checkbox from 'src/components/checkbox/checkbox.vue'
import Select from 'src/components/select/select.vue'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
import HelpIndicator from '../helpers/help_indicator.vue'
@ -24,10 +25,10 @@ const ClutterTab = {
},
computed: {
instanceSpecificPanelPresent() {
return this.$store.state.instance.showInstanceSpecificPanel
return useInstanceStore().showInstanceSpecificPanel
},
...SharedComputedObject(),
...mapState(useServerSideStorageStore, {
...mapState(useSyncConfigStore, {
muteFilters: (store) =>
Object.entries(store.prefsStorage.simple.muteFilters),
muteFiltersObject: (store) => store.prefsStorage.simple.muteFilters,
@ -86,10 +87,10 @@ const ClutterTab = {
},
},
methods: {
...mapActions(useServerSideStorageStore, [
...mapActions(useSyncConfigStore, [
'setPreference',
'unsetPreference',
'pushServerSideStorage',
'pushSyncConfig',
]),
getDatetimeLocal(timestamp) {
const date = new Date(timestamp)
@ -136,7 +137,7 @@ const ClutterTab = {
filter.order = this.muteFilters.length + 2
this.muteFiltersDraftObject[newId] = filter
this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
this.pushServerSideStorage()
this.pushSyncConfig()
},
exportFilter(id) {
this.exportedFilter = { ...this.muteFiltersDraftObject[id] }
@ -152,19 +153,19 @@ const ClutterTab = {
this.muteFiltersDraftObject[newId] = filter
this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
this.pushServerSideStorage()
this.pushSyncConfig()
},
deleteFilter(id) {
delete this.muteFiltersDraftObject[id]
this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
this.pushServerSideStorage()
this.pushSyncConfig()
},
purgeExpiredFilters() {
this.muteFiltersExpired.forEach(([id]) => {
delete this.muteFiltersDraftObject[id]
this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
})
this.pushServerSideStorage()
this.pushSyncConfig()
},
updateFilter(id, field, value) {
const filter = { ...this.muteFiltersDraftObject[id] }
@ -190,7 +191,7 @@ const ClutterTab = {
path: 'simple.muteFilters.' + id,
value: this.muteFiltersDraftObject[id],
})
this.pushServerSideStorage()
this.pushSyncConfig()
this.muteFiltersDraftDirty[id] = false
},
},

View file

@ -6,6 +6,8 @@ import ScopeSelector from 'src/components/scope_selector/scope_selector.vue'
import Select from 'src/components/select/select.vue'
import localeService from 'src/services/locale/locale.service.js'
import { cacheKey, clearCache, emojiCacheKey } from 'src/services/sw/sw.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
import FloatSetting from '../helpers/float_setting.vue'
@ -108,7 +110,7 @@ const ComposingTab = {
},
computed: {
postFormats() {
return this.$store.state.instance.postFormats || []
return useInstanceStore().postFormats || []
},
postContentOptions() {
return this.postFormats.map((format) => ({
@ -119,7 +121,7 @@ const ComposingTab = {
},
language: {
get: function () {
return this.$store.getters.mergedConfig.interfaceLanguage
return useSyncConfigStore().mergedConfig.interfaceLanguage
},
set: function (val) {
this.$store.dispatch('setOption', {

View file

@ -9,8 +9,9 @@ import {
newExporter,
newImporter,
} from 'src/services/export_import/export_import.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
import HelpIndicator from '../helpers/help_indicator.vue'
@ -34,11 +35,11 @@ const FilteringTab = {
label: this.$t(`user_card.mute_block_${mode}`),
})),
muteFiltersDraftObject: cloneDeep(
useServerSideStorageStore().prefsStorage.simple.muteFilters,
useSyncConfigStore().prefsStorage.simple.muteFilters,
),
muteFiltersDraftDirty: Object.fromEntries(
Object.entries(
useServerSideStorageStore().prefsStorage.simple.muteFilters,
useSyncConfigStore().prefsStorage.simple.muteFilters,
).map(([k]) => [k, false]),
),
exportedFilter: null,
@ -90,10 +91,10 @@ const FilteringTab = {
},
computed: {
instanceSpecificPanelPresent() {
return this.$store.state.instance.showInstanceSpecificPanel
return useInstanceStore().showInstanceSpecificPanel
},
...SharedComputedObject(),
...mapState(useServerSideStorageStore, {
...mapState(useSyncConfigStore, {
muteFilters: (store) =>
Object.entries(store.prefsStorage.simple.muteFilters),
muteFiltersObject: (store) => store.prefsStorage.simple.muteFilters,
@ -152,10 +153,10 @@ const FilteringTab = {
},
},
methods: {
...mapActions(useServerSideStorageStore, [
...mapActions(useSyncConfigStore, [
'setPreference',
'unsetPreference',
'pushServerSideStorage',
'pushSyncConfig',
]),
getDatetimeLocal(timestamp) {
const date = new Date(timestamp)
@ -202,7 +203,7 @@ const FilteringTab = {
filter.order = this.muteFilters.length + 2
this.muteFiltersDraftObject[newId] = filter
this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
this.pushServerSideStorage()
this.pushSyncConfig()
},
exportFilter(id) {
this.exportedFilter = { ...this.muteFiltersDraftObject[id] }
@ -218,19 +219,19 @@ const FilteringTab = {
this.muteFiltersDraftObject[newId] = filter
this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
this.pushServerSideStorage()
this.pushSyncConfig()
},
deleteFilter(id) {
delete this.muteFiltersDraftObject[id]
this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
this.pushServerSideStorage()
this.pushSyncConfig()
},
purgeExpiredFilters() {
this.muteFiltersExpired.forEach(([id]) => {
delete this.muteFiltersDraftObject[id]
this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
})
this.pushServerSideStorage()
this.pushSyncConfig()
},
updateFilter(id, field, value) {
const filter = { ...this.muteFiltersDraftObject[id] }
@ -256,7 +257,7 @@ const FilteringTab = {
path: 'simple.muteFilters.' + id,
value: this.muteFiltersDraftObject[id],
})
this.pushServerSideStorage()
this.pushSyncConfig()
this.muteFiltersDraftDirty[id] = false
},
},

View file

@ -3,6 +3,8 @@ import { mapState } from 'vuex'
import FontControl from 'src/components/font_control/font_control.vue'
import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
import localeService from 'src/services/locale/locale.service.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
import FloatSetting from '../helpers/float_setting.vue'
@ -39,7 +41,7 @@ const GeneralTab = {
computed: {
language: {
get: function () {
return this.$store.getters.mergedConfig.interfaceLanguage
return useSyncConfigStore().mergedConfig.interfaceLanguage
},
set: function (val) {
this.$store.dispatch('setOption', {

View file

@ -1,3 +1,5 @@
import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import BooleanSetting from '../helpers/boolean_setting.vue'
import ChoiceSetting from '../helpers/choice_setting.vue'
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
@ -30,18 +32,18 @@ const GeneralTab = {
},
computed: {
postFormats() {
return this.$store.state.instance.postFormats || []
return useInstanceStore().postFormats || []
},
instanceShoutboxPresent() {
return this.$store.state.instance.shoutAvailable
return useInstanceStore().shoutAvailable
},
columns() {
const mode = this.$store.getters.mergedConfig.thirdColumnMode
const mode = useSyncConfigStore().mergedConfig.thirdColumnMode
const notif = mode === 'none' ? [] : ['notifs']
if (
this.$store.getters.mergedConfig.sidebarRight ||
useSyncConfigStore().mergedConfig.sidebarRight ||
mode === 'postform'
) {
return [...notif, 'content', 'sidebar']

View file

@ -12,7 +12,9 @@ import MuteCard from 'src/components/mute_card/mute_card.vue'
import ProgressButton from 'src/components/progress_button/progress_button.vue'
import SelectableList from 'src/components/selectable_list/selectable_list.vue'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import { useInstanceStore } from 'src/stores/instance.js'
import { useOAuthTokensStore } from 'src/stores/oauth_tokens'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const BlockList = withLoadMore({
fetch: (props, $store) => $store.dispatch('fetchBlocks'),
@ -64,7 +66,7 @@ const MutesAndBlocks = {
},
computed: {
knownDomains() {
return this.$store.state.instance.knownDomains
return useInstanceStore().knownDomains
},
user() {
return this.$store.state.users.currentUser

View file

@ -41,7 +41,9 @@ import {
} from 'src/services/theme_data/theme_data.service.js'
import { init } from 'src/services/theme_data/theme_data_3.service.js'
import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import Preview from './theme_preview.vue'
// List of color values used in v1
@ -78,7 +80,7 @@ export default {
}),
availableStyles: [],
selected: '',
selectedTheme: this.$store.getters.mergedConfig.theme,
selectedTheme: useSyncConfigStore().mergedConfig.theme,
themeWarning: undefined,
tempImportFile: undefined,
engineVersion: 0,
@ -125,7 +127,7 @@ export default {
}
},
created() {
const currentIndex = this.$store.state.instance.instanceThemesIndex
const currentIndex = useInstanceStore().instanceThemesIndex
let promise
if (currentIndex) {

View file

@ -1,6 +1,7 @@
import Checkbox from 'src/components/checkbox/checkbox.vue'
import ProgressButton from 'src/components/progress_button/progress_button.vue'
import localeService from 'src/services/locale/locale.service.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useOAuthTokensStore } from 'src/stores/oauth_tokens'
import Mfa from './mfa.vue'
@ -42,7 +43,7 @@ const SecurityTab = {
return this.$store.state.users.currentUser
},
pleromaExtensionsAvailable() {
return this.$store.state.instance.pleromaExtensionsAvailable
return useInstanceStore().pleromaExtensionsAvailable
},
oauthTokens() {
return useOAuthTokensStore().tokens.map((oauthToken) => {