diff --git a/changelog.d/instance-store-migration.skip b/changelog.d/instance-store-migration.skip new file mode 100644 index 000000000..e69de29bb diff --git a/src/App.js b/src/App.js index 8574455a3..0714ced1d 100644 --- a/src/App.js +++ b/src/App.js @@ -1,36 +1,31 @@ import { throttle } from 'lodash' -import { mapActions, mapState } from 'pinia' +import { mapState } from 'pinia' import { defineAsyncComponent } from 'vue' +import { mapGetters } from 'vuex' -import DesktopNav from 'src/components/desktop_nav/desktop_nav.vue' -import EditStatusModal from 'src/components/edit_status_modal/edit_status_modal.vue' -import FeaturesPanel from 'src/components/features_panel/features_panel.vue' -import GlobalNoticeList from 'src/components/global_notice_list/global_notice_list.vue' -import InstanceSpecificPanel from 'src/components/instance_specific_panel/instance_specific_panel.vue' -import MediaModal from 'src/components/media_modal/media_modal.vue' -import MobileNav from 'src/components/mobile_nav/mobile_nav.vue' -import MobilePostStatusButton from 'src/components/mobile_post_status_button/mobile_post_status_button.vue' -import NavPanel from 'src/components/nav_panel/nav_panel.vue' -import PostStatusModal from 'src/components/post_status_modal/post_status_modal.vue' -import ShoutPanel from 'src/components/shout_panel/shout_panel.vue' -import SideDrawer from 'src/components/side_drawer/side_drawer.vue' -import StatusHistoryModal from 'src/components/status_history_modal/status_history_modal.vue' -import UserPanel from 'src/components/user_panel/user_panel.vue' -import UserReportingModal from 'src/components/user_reporting_modal/user_reporting_modal.vue' -import WhoToFollowPanel from 'src/components/who_to_follow_panel/who_to_follow_panel.vue' +import DesktopNav from './components/desktop_nav/desktop_nav.vue' +import EditStatusModal from './components/edit_status_modal/edit_status_modal.vue' +import FeaturesPanel from './components/features_panel/features_panel.vue' +import GlobalNoticeList from './components/global_notice_list/global_notice_list.vue' +import InstanceSpecificPanel from './components/instance_specific_panel/instance_specific_panel.vue' +import MediaModal from './components/media_modal/media_modal.vue' +import MobileNav from './components/mobile_nav/mobile_nav.vue' +import MobilePostStatusButton from './components/mobile_post_status_button/mobile_post_status_button.vue' +import NavPanel from './components/nav_panel/nav_panel.vue' +import PostStatusModal from './components/post_status_modal/post_status_modal.vue' +import ShoutPanel from './components/shout_panel/shout_panel.vue' +import SideDrawer from './components/side_drawer/side_drawer.vue' +import StatusHistoryModal from './components/status_history_modal/status_history_modal.vue' +import UserPanel from './components/user_panel/user_panel.vue' +import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue' +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 { useI18nStore } from 'src/stores/i18n.js' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInterfaceStore } from 'src/stores/interface.js' import { useShoutStore } from 'src/stores/shout.js' -import { useSyncConfigStore } from 'src/stores/sync_config.js' - -import { applyStyleConfig } from 'src/services/style_setter/style_setter.js' -import { getOrCreateServiceWorker } from 'src/services/sw/sw' -import { - windowHeight, - windowWidth, -} from 'src/services/window_utils/window_utils' export default { name: 'app', @@ -76,11 +71,11 @@ export default { }, }, created() { + // Load the locale from the storage + const val = this.$store.getters.mergedConfig.interfaceLanguage + this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val }) document.getElementById('modal').classList = ['-' + this.layoutType] - useI18nStore().setLanguage() - applyStyleConfig(useSyncConfigStore().mergedConfig) - // Create bound handlers this.updateScrollState = throttle(this.scrollHandler, 200) this.updateMobileState = throttle(this.resizeHandler, 200) @@ -89,7 +84,7 @@ export default { window.addEventListener('resize', this.updateMobileState) this.scrollParent.addEventListener('scroll', this.updateScrollState) - if (useInterfaceStore().themeApplied) { + if (this.themeApplied) { this.setThemeBodyClass() this.removeSplash() } @@ -100,12 +95,9 @@ export default { this.scrollParent.removeEventListener('scroll', this.updateScrollState) }, computed: { - themeApplied() { - return useInterfaceStore().themeApplied - }, currentTheme() { - if (useInterfaceStore().styleDataUsed) { - const styleMeta = useInterfaceStore().styleDataUsed.find( + if (this.styleDataUsed) { + const styleMeta = this.styleDataUsed.find( (x) => x.component === '@meta', ) @@ -130,7 +122,7 @@ export default { ] }, navClasses() { - const { navbarColumnStretch } = useSyncConfigStore().mergedConfig + const { navbarColumnStretch } = this.$store.getters.mergedConfig return [ '-' + this.layoutType, ...(navbarColumnStretch ? ['-column-stretch'] : []), @@ -142,6 +134,9 @@ export default { userBackground() { return this.currentUser.background_image }, + instanceBackground() { + return this.mergedConfig.hideInstanceWallpaper ? null : this.background + }, background() { return this.userBackground || this.instanceBackground }, @@ -164,11 +159,20 @@ export default { newPostButtonShown() { if (this.isChats) return false if (this.isListEdit) return false - return this.alwaysShowNewPostButton || this.layoutType === 'mobile' + return ( + this.$store.getters.mergedConfig.alwaysShowNewPostButton || + this.layoutType === 'mobile' + ) + }, + shoutboxPosition() { + return this.$store.getters.mergedConfig.alwaysShowNewPostButton || false + }, + hideShoutbox() { + return this.$store.getters.mergedConfig.hideShoutbox }, reverseLayout() { const { thirdColumnMode, sidebarRight: reverseSetting } = - useSyncConfigStore().mergedConfig + this.$store.getters.mergedConfig if (this.layoutType !== 'wide') { return reverseSetting } else { @@ -177,46 +181,44 @@ export default { : !reverseSetting } }, + noSticky() { + return this.$store.getters.mergedConfig.disableStickyHeaders + }, + showScrollbars() { + return this.$store.getters.mergedConfig.showScrollbars + }, scrollParent() { return window /* this.$refs.appContentRef */ }, - - ...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) => - useSyncConfigStore().mergedConfig.hideInstanceWallpaper - ? null - : store.background, - showInstanceSpecificPanel: (store) => - store.showInstanceSpecificPanel && - !useSyncConfigStore().mergedConfig.hideISP && - store.instanceSpecificPanelContent, - }), - ...mapState(useInstanceStore, [ - 'editingAvailable', - 'showFeaturesPanel', - 'private', - 'suggestionsEnabled', + showInstanceSpecificPanel() { + return ( + this.instanceSpecificPanelPresent && + !this.$store.getters.mergedConfig.hideISP + ) + }, + ...mapGetters(['mergedConfig']), + ...mapState(useInterfaceStore, [ + 'themeApplied', + 'styleDataUsed', + 'layoutType', ]), + ...mapState(useInstanceStore, ['styleDataUsed']), + ...mapState(useInstanceCapabilitiesStore, [ + 'suggestionsEnabled', + 'editingAvailable', + ]), + ...mapState(useInstanceStore, { + background: (store) => store.instanceIdentity.background, + showFeaturesPanel: (store) => store.instanceIdentity.showFeaturesPanel, + instanceSpecificPanelPresent: (store) => + store.instanceIdentity.showInstanceSpecificPanel && + store.instanceIdentity.instanceSpecificPanelContent, + }), }, methods: { resizeHandler() { - this.setLayoutWidth(windowWidth()) - this.setLayoutHeight(windowHeight()) + useInterfaceStore().setLayoutWidth(windowWidth()) + useInterfaceStore().setLayoutHeight(windowHeight()) }, scrollHandler() { const scrollPosition = @@ -263,6 +265,5 @@ export default { splashscreenRoot.classList.add('hidden') document.querySelector('#app').classList.remove('hidden') }, - ...mapActions(useInterfaceStore, ['setLayoutWidth', 'setLayoutHeight']), }, } diff --git a/src/boot/after_store.js b/src/boot/after_store.js index c6ea61300..b7e97cf45 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -1,7 +1,6 @@ /* global process */ import vClickOutside from 'click-outside-vue3' -import { get, set } from 'lodash' import { createApp } from 'vue' import { createRouter, createWebHistory } from 'vue-router' import VueVirtualScroller from 'vue-virtual-scroller' @@ -18,7 +17,7 @@ config.autoAddCss = false import App from '../App.vue' import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js' import FaviconService from '../services/favicon_service/favicon_service.js' -import { applyStyleConfig } from '../services/style_setter/style_setter.js' +import { applyConfig } from '../services/style_setter/style_setter.js' import { initServiceWorker, updateFocus } from '../services/sw/sw.js' import { windowHeight, @@ -26,13 +25,14 @@ import { } from '../services/window_utils/window_utils' import routes from './routes' -import { useAnnouncementsStore } from 'src/stores/announcements.js' -import { useAuthFlowStore } from 'src/stores/auth_flow.js' -import { useI18nStore } from 'src/stores/i18n.js' +import { useAnnouncementsStore } from 'src/stores/announcements' +import { useAuthFlowStore } from 'src/stores/auth_flow' +import { useEmojiStore } from 'src/stores/emoji.js' +import { useI18nStore } from 'src/stores/i18n' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInterfaceStore } from 'src/stores/interface.js' -import { useOAuthStore } from 'src/stores/oauth.js' -import { useSyncConfigStore } from 'src/stores/sync_config.js' +import { useOAuthStore } from 'src/stores/oauth' import VBodyScrollLock from 'src/directives/body_scroll_lock' import { @@ -83,30 +83,30 @@ const getInstanceConfig = async ({ store }) => { const textlimit = data.max_toot_chars const vapidPublicKey = data.pleroma.vapid_public_key + useInstanceCapabilitiesStore().set( + 'pleromaExtensionsAvailable', + data.pleroma, + ) useInstanceStore().set({ - path: 'featureSet.pleromaExtensionsAvailable', - value: data.pleroma, - }) - useInstanceStore().set({ - path: 'textlimit', + name: 'textlimit', value: textlimit, }) useInstanceStore().set({ - path: 'accountApprovalRequired', + name: 'accountApprovalRequired', value: data.approval_required, }) useInstanceStore().set({ - path: 'birthdayRequired', + name: 'birthdayRequired', value: !!data.pleroma?.metadata.birthday_required, }) useInstanceStore().set({ - path: 'birthdayMinAge', + name: 'birthdayMinAge', value: data.pleroma?.metadata.birthday_min_age || 0, }) if (vapidPublicKey) { useInstanceStore().set({ - path: 'vapidPublicKey', + name: 'vapidPublicKey', value: vapidPublicKey, }) } @@ -161,31 +161,23 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => { let config = {} if (overrides.staticConfigPreference && env === 'development') { console.warn('OVERRIDING API CONFIG WITH STATIC CONFIG') - config = { ...apiConfig, ...staticConfig } + config = Object.assign({}, apiConfig, staticConfig) } else { - config = { ...staticConfig, ...apiConfig } + config = Object.assign({}, staticConfig, apiConfig) } - const copyInstanceIdentityOption = (path) => { - if (get(config, path) !== undefined) { - useInstanceStore().set({ - path: `instanceIdentity.${path}`, - value: get(config, path), - }) + const copyInstanceOption = ({ source, destination }) => { + if (typeof config[source] !== 'undefined') { + useInstanceStore().set({ path: destination, value: config[source] }) } } - const copyInstancePrefOption = (path) => { - if (get(config, path) !== undefined) { - useInstanceStore().set({ - path: `prefsStorage.${path}`, - value: get(config, path), - }) - } - } - - Object.keys(staticOrApiConfigDefault).forEach(copyInstanceIdentityOption) - Object.keys(instanceDefaultConfig).forEach(copyInstancePrefOption) + Object.keys(staticOrApiConfigDefault) + .map((k) => ({ source: k, destination: `instanceIdentity.${k}` })) + .forEach(copyInstanceOption) + Object.keys(instanceDefaultConfig) + .map((k) => ({ source: k, destination: `prefsStorage.${k}` })) + .forEach(copyInstanceOption) useAuthFlowStore().setInitialStrategy(config.loginMethod) } @@ -195,7 +187,7 @@ const getTOS = async ({ store }) => { const res = await window.fetch('/static/terms-of-service.html') if (res.ok) { const html = await res.text() - useInstanceStore().set({ path: 'tos', value: html }) + useInstanceStore().set({ name: 'instanceIdentity.tos', value: html }) } else { throw res } @@ -210,7 +202,7 @@ const getInstancePanel = async ({ store }) => { if (res.ok) { const html = await res.text() useInstanceStore().set({ - path: 'instanceSpecificPanelContent', + path: 'instanceIdentity.instanceSpecificPanelContent', value: html, }) } else { @@ -244,7 +236,7 @@ const getStickers = async ({ store }) => { ).sort((a, b) => { return a.meta.title.localeCompare(b.meta.title) }) - useInstanceStore().set({ path: 'stickers', value: stickers }) + useEmojiStore().setStickers(stickers) } else { throw res } @@ -266,7 +258,7 @@ const getAppSecret = async ({ store }) => { const resolveStaffAccounts = ({ store, accounts }) => { const nicknames = accounts.map((uri) => uri.split('/').pop()) useInstanceStore().set({ - path: 'staffAccounts', + name: 'staffAccounts', value: nicknames, }) } @@ -279,85 +271,81 @@ const getNodeInfo = async ({ store }) => { const data = await res.json() const metadata = data.metadata const features = metadata.features - useInstanceStore().set({ - path: 'localBubbleInstances', - value: metadata.localBubbleInstances ?? [], - }) - - useInstanceStore().set({ - path: 'instanceIdentity.name', + path: 'name', value: metadata.nodeName, }) - useInstanceStore().set({ path: 'registrationOpen', value: data.openRegistrations, }) - useInstanceStore().set({ - path: 'restrictedNicknames', - value: metadata.restrictedNicknames, - }) + useInstanceCapabilitiesStore().set( + 'mediaProxyAvailable', + features.includes('media_proxy'), + ) + useInstanceCapabilitiesStore().set( + 'safeDM', + features.includes('safe_dm_mentions'), + ) + useInstanceCapabilitiesStore().set( + 'shoutAvailable', + features.includes('chat'), + ) + useInstanceCapabilitiesStore().set( + 'pleromaChatMessagesAvailable', + features.includes('pleroma_chat_messages'), + ) + useInstanceCapabilitiesStore().set( + 'pleromaCustomEmojiReactionsAvailable', - useInstanceStore().set({ - path: 'featureSet.mediaProxyAvailable', - value: features.includes('media_proxy'), - }) - useInstanceStore().set({ - path: 'featureSet.safeDM', - value: features.includes('safe_dm_mentions'), - }) - useInstanceStore().set({ - path: 'featureSet.shoutAvailable', - value: features.includes('chat'), - }) - useInstanceStore().set({ - path: 'featureSet.pleromaChatMessagesAvailable', - value: features.includes('pleroma_chat_messages'), - }) - useInstanceStore().set({ - path: 'featureSet.pleromaCustomEmojiReactionsAvailable', - value: - features.includes('pleroma_custom_emoji_reactions') || + features.includes('pleroma_custom_emoji_reactions') || features.includes('custom_emoji_reactions'), - }) + ) + useInstanceCapabilitiesStore().set( + 'pleromaBookmarkFoldersAvailable', + features.includes('pleroma:bookmark_folders'), + ) + useInstanceCapabilitiesStore().set( + 'gopherAvailable', + features.includes('gopher'), + ) + useInstanceCapabilitiesStore().set( + 'pollsAvailable', + features.includes('polls'), + ) + useInstanceCapabilitiesStore().set( + 'editingAvailable', + features.includes('editing'), + ) + useInstanceCapabilitiesStore().set( + 'mailerEnabled', + metadata.mailerEnabled, + ) + useInstanceCapabilitiesStore().set( + 'quotingAvailable', + features.includes('quote_posting'), + ) + useInstanceCapabilitiesStore().set( + 'groupActorAvailable', + features.includes('pleroma:group_actors'), + ) + useInstanceCapabilitiesStore().set( + 'blockExpiration', + features.includes('pleroma:block_expiration'), + ) useInstanceStore().set({ - path: 'featureSet.pleromaBookmarkFoldersAvailable', - value: features.includes('pleroma:bookmark_folders'), - }) - useInstanceStore().set({ - path: 'featureSet.gopherAvailable', - value: features.includes('gopher'), - }) - useInstanceStore().set({ - path: 'featureSet.pollsAvailable', - value: features.includes('polls'), - }) - useInstanceStore().set({ - path: 'featureSet.editingAvailable', - value: features.includes('editing'), - }) - useInstanceStore().set({ - path: 'featureSet.mailerEnabled', - value: metadata.mailerEnabled, - }) - useInstanceStore().set({ - path: 'featureSet.quotingAvailable', - value: features.includes('quote_posting'), - }) - useInstanceStore().set({ - path: 'featureSet.groupActorAvailable', - value: features.includes('pleroma:group_actors'), - }) - useInstanceStore().set({ - path: 'featureSet.blockExpiration', - value: features.includes('pleroma:block_expiration'), - }) - useInstanceStore().set({ - path: 'featureSet.localBubble', - value: Array.isArray(metadata.localBubbleInstances), + path: 'localBubbleInstances', + value: metadata.localBubbleInstances ?? [], }) + useInstanceCapabilitiesStore().set( + 'localBubble', + (metadata.localBubbleInstances ?? []).length > 0, + ) + useInstanceStore().set({ + path: 'limits.pollLimits', + value: metadata.pollLimits, + }) const uploadLimits = metadata.uploadLimits useInstanceStore().set({ path: 'limits.uploadlimit', @@ -379,60 +367,53 @@ const getNodeInfo = async ({ store }) => { path: 'limits.fieldsLimits', value: metadata.fieldsLimits, }) + useInstanceStore().set({ - path: 'limits.pollLimits', - value: metadata.pollLimits, - }) - useInstanceStore().set({ - path: 'featureSet.postFormats', - value: metadata.postFormats, + path: 'restrictedNicknames', + value: metadata.restrictedNicknames, }) + useInstanceCapabilitiesStore().set('postFormats', metadata.postFormats) const suggestions = metadata.suggestions - useInstanceStore().set({ - path: 'featureSet.suggestionsEnabled', - value: suggestions.enabled, - }) - useInstanceStore().set({ - path: 'featureSet.suggestionsWeb', - value: suggestions.web, - }) - - // + useInstanceCapabilitiesStore().set( + 'suggestionsEnabled', + suggestions.enabled, + ) + // this is unused, why? + useInstanceCapabilitiesStore().set('suggestionsWeb', suggestions.web) const software = data.software useInstanceStore().set({ - path: 'backendVersion', + name: 'backendVersion', value: software.version, }) useInstanceStore().set({ - path: 'backendRepository', + name: 'backendRepository', value: software.repository, }) - useInstanceStore().set({ path: 'private', value: metadata.private }) + const priv = metadata.private + useInstanceStore().set({ name: 'privateMode', value: priv }) const frontendVersion = window.___pleromafe_commit_hash useInstanceStore().set({ - path: 'frontendVersion', + name: 'frontendVersion', value: frontendVersion, }) const federation = metadata.federation - useInstanceStore().set({ - path: 'featureSet.tagPolicyAvailable', - value: - typeof federation.mrf_policies === 'undefined' - ? false - : metadata.federation.mrf_policies.includes('TagPolicy'), - }) + useInstanceCapabilitiesStore().set( + 'tagPolicyAvailable', + typeof federation.mrf_policies === 'undefined' + ? false + : metadata.federation.mrf_policies.includes('TagPolicy'), + ) useInstanceStore().set({ path: 'federationPolicy', value: federation, }) - useInstanceStore().set({ path: 'federating', value: @@ -471,8 +452,8 @@ const setConfig = async ({ store }) => { const checkOAuthToken = async ({ store }) => { const oauth = useOAuthStore() - if (oauth.userToken) { - return store.dispatch('loginUser', oauth.userToken) + if (oauth.getUserToken) { + return store.dispatch('loginUser', oauth.getUserToken) } return Promise.resolve() } @@ -552,7 +533,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => { typeof overrides.target !== 'undefined' ? overrides.target : window.location.origin - useInstanceStore().set({ path: 'server', value: server }) + useInstanceStore().set({ name: 'server', value: server }) await setConfig({ store }) try { @@ -566,7 +547,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => { return Promise.reject(e) } - applyStyleConfig(useSyncConfigStore().mergedConfig) + applyConfig(store.state.config, i18n.global) // Now we can try getting the server settings and logging in // Most of these are preloaded into the index.html so blocking is minimized diff --git a/src/boot/routes.js b/src/boot/routes.js index 0d135981d..193daf4a7 100644 --- a/src/boot/routes.js +++ b/src/boot/routes.js @@ -33,13 +33,16 @@ import BookmarkFolders from '../components/bookmark_folders/bookmark_folders.vue import QuotesTimeline from '../components/quotes_timeline/quotes_timeline.vue' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' export default (store) => { const validateAuthenticatedRoute = (to, from, next) => { if (store.state.users.currentUser) { next() } else { - next(useInstanceStore().redirectRootNoLogin || '/main/all') + next( + useInstanceStore().instanceIdentity.redirectRootNoLogin || '/main/all', + ) } } @@ -50,8 +53,9 @@ export default (store) => { redirect: () => { return ( (store.state.users.currentUser - ? useInstanceStore().redirectRootLogin - : useInstanceStore().redirectRootNoLogin) || '/main/all' + ? useInstanceStore().instanceIdentity.redirectRootLogin + : useInstanceStore().instanceIdentity.redirectRootNoLogin) || + '/main/all' ) }, }, @@ -202,7 +206,7 @@ export default (store) => { }, ] - if (useInstanceStore().featureSet.pleromaChatMessagesAvailable) { + if (useInstanceCapabilitiesStore().pleromaChatMessagesAvailable) { routes = routes.concat([ { name: 'chat', diff --git a/src/components/about/about.js b/src/components/about/about.js index b4a33505b..f52d5c797 100644 --- a/src/components/about/about.js +++ b/src/components/about/about.js @@ -5,7 +5,6 @@ import StaffPanel from '../staff_panel/staff_panel.vue' import TermsOfServicePanel from '../terms_of_service_panel/terms_of_service_panel.vue' import { useInstanceStore } from 'src/stores/instance.js' -import { useSyncConfigStore } from 'src/stores/sync_config.js' const About = { components: { @@ -17,13 +16,13 @@ const About = { }, computed: { showFeaturesPanel() { - return useInstanceStore().showFeaturesPanel + return useInstanceStore().instanceIdentity.showFeaturesPanel }, showInstanceSpecificPanel() { return ( - useInstanceStore().showInstanceSpecificPanel && - !useSyncConfigStore().mergedConfig.hideISP && - useInstanceStore().instanceSpecificPanelContent + useInstanceStore().instanceIdentity.showInstanceSpecificPanel && + !this.$store.getters.mergedConfig.hideISP && + useInstanceStore().instanceIdentity.instanceSpecificPanelContent ) }, }, diff --git a/src/components/account_actions/account_actions.js b/src/components/account_actions/account_actions.js index 1bd4620b1..8fce4b5af 100644 --- a/src/components/account_actions/account_actions.js +++ b/src/components/account_actions/account_actions.js @@ -1,5 +1,4 @@ -import { mapState as mapPiniaState } from 'pinia' -import { mapState } from 'vuex' +import { mapState } from 'pinia' import UserListMenu from 'src/components/user_list_menu/user_list_menu.vue' import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_timed_filter_modal.vue' @@ -7,9 +6,8 @@ import ConfirmModal from '../confirm_modal/confirm_modal.vue' import Popover from '../popover/popover.vue' import ProgressButton from '../progress_button/progress_button.vue' -import { useInstanceStore } from 'src/stores/instance' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useReportsStore } from 'src/stores/reports' -import { useSyncConfigStore } from 'src/stores/sync_config.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faEllipsisV } from '@fortawesome/free-solid-svg-icons' @@ -91,18 +89,15 @@ const AccountActions = { }, computed: { shouldConfirmBlock() { - return useSyncConfigStore().mergedConfig.modalOnBlock + return this.$store.getters.mergedConfig.modalOnBlock }, shouldConfirmRemoveUserFromFollowers() { - return useSyncConfigStore().mergedConfig.modalOnRemoveUserFromFollowers + return this.$store.getters.mergedConfig.modalOnRemoveUserFromFollowers }, - ...mapPiniaState(useInstanceStore, (store) => ({ - blockExpirationSupported: (store) => store.featureSet.blockExpiration, - })), - ...mapState({ - pleromaChatMessagesAvailable: (state) => - state.instance.pleromaChatMessagesAvailable, - }), + ...mapState(useInstanceCapabilitiesStore, [ + 'blockExpiration', + 'pleromaChatMessagesAvailable', + ]), }, } diff --git a/src/components/account_actions/account_actions.vue b/src/components/account_actions/account_actions.vue index cc00a735d..94cb91ee0 100644 --- a/src/components/account_actions/account_actions.vue +++ b/src/components/account_actions/account_actions.vue @@ -95,7 +95,7 @@ state.mergedConfig.useContainFit, - playVideosInModal: (state) => state.mergedConfig.playVideosInModal, - useOneClickNsfw: (state) => state.mergedConfig.useOneClickNsfw, - }), + ...mapGetters(['mergedConfig']), }, watch: { 'attachment.description'(newVal) { @@ -190,9 +190,9 @@ const Attachment = { }, toggleHidden(event) { if ( - this.useOneClickNsfw && + this.mergedConfig.useOneClickNsfw && !this.showHidden && - (this.type !== 'video' || this.playVideosInModal) + (this.type !== 'video' || this.mergedConfig.playVideosInModal) ) { this.openModal(event) return diff --git a/src/components/auth_form/auth_form.js b/src/components/auth_form/auth_form.js index db721b307..9e05095ca 100644 --- a/src/components/auth_form/auth_form.js +++ b/src/components/auth_form/auth_form.js @@ -5,7 +5,7 @@ import LoginForm from '../login_form/login_form.vue' import MFARecoveryForm from '../mfa_form/recovery_form.vue' import MFATOTPForm from '../mfa_form/totp_form.vue' -import { useAuthFlowStore } from 'src/stores/auth_flow' +import { useAuthFlowStore } from 'src/stores/auth_flow.js' const AuthForm = { name: 'AuthForm', diff --git a/src/components/block_card/block_card.js b/src/components/block_card/block_card.js index 7301bf0c7..967ce2a3c 100644 --- a/src/components/block_card/block_card.js +++ b/src/components/block_card/block_card.js @@ -1,7 +1,10 @@ -import { mapState } from 'vuex' +import { mapState } from 'pinia' +import UserTimedFilterModal from 'src/components/user_timed_filter_modal/user_timed_filter_modal.vue' import BasicUserCard from '../basic_user_card/basic_user_card.vue' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' + const BlockCard = { props: ['userId'], computed: { @@ -24,19 +27,18 @@ const BlockCard = { new Date(this.user.mute_expires_at).toLocaleString(), ]) }, - ...mapState({ - blockExpirationSupported: (state) => state.instance.blockExpiration, - }), + ...mapState(useInstanceCapabilitiesStore, ['blockExpiration']), }, components: { BasicUserCard, + UserTimedFilterModal, }, methods: { unblockUser() { this.$store.dispatch('unblockUser', this.user.id) }, blockUser() { - if (this.blockExpirationSupported) { + if (this.blockExpiration) { this.$refs.timedBlockDialog.optionallyPrompt() } else { this.$store.dispatch('blockUser', { id: this.user.id }) diff --git a/src/components/bookmark_folder_edit/bookmark_folder_edit.js b/src/components/bookmark_folder_edit/bookmark_folder_edit.js index 002fd688f..a036895bf 100644 --- a/src/components/bookmark_folder_edit/bookmark_folder_edit.js +++ b/src/components/bookmark_folder_edit/bookmark_folder_edit.js @@ -1,8 +1,8 @@ import apiService from '../../services/api/api.service' import EmojiPicker from '../emoji_picker/emoji_picker.vue' -import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders' -import { useInterfaceStore } from 'src/stores/interface' +import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js' +import { useInterfaceStore } from 'src/stores/interface.js' const BookmarkFolderEdit = { data() { diff --git a/src/components/bookmark_folders/bookmark_folders.js b/src/components/bookmark_folders/bookmark_folders.js index c558f0812..1147fd3a5 100644 --- a/src/components/bookmark_folders/bookmark_folders.js +++ b/src/components/bookmark_folders/bookmark_folders.js @@ -1,6 +1,6 @@ import BookmarkFolderCard from '../bookmark_folder_card/bookmark_folder_card.vue' -import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders' +import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js' const BookmarkFolders = { data() { diff --git a/src/components/bookmark_folders_menu/bookmark_folders_menu_content.js b/src/components/bookmark_folders_menu/bookmark_folders_menu_content.js index 73139eb08..be1fb06ea 100644 --- a/src/components/bookmark_folders_menu/bookmark_folders_menu_content.js +++ b/src/components/bookmark_folders_menu/bookmark_folders_menu_content.js @@ -3,7 +3,7 @@ import { mapState } from 'pinia' import { getBookmarkFolderEntries } from 'src/components/navigation/filter.js' import NavigationEntry from 'src/components/navigation/navigation_entry.vue' -import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders' +import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js' export const BookmarkFoldersMenuContent = { props: ['showPin'], diff --git a/src/components/chat/chat.js b/src/components/chat/chat.js index 8295e6bcb..caeb2aea7 100644 --- a/src/components/chat/chat.js +++ b/src/components/chat/chat.js @@ -17,7 +17,6 @@ import { } from './chat_layout_utils.js' import { useInterfaceStore } from 'src/stores/interface.js' -import { useSyncConfigStore } from 'src/stores/sync_config.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faChevronDown, faChevronLeft } from '@fortawesome/free-solid-svg-icons' @@ -110,11 +109,11 @@ const Chat = { 'currentChat', 'currentChatMessageService', 'findOpenedChatByRecipientId', + 'mergedConfig', ]), ...mapPiniaState(useInterfaceStore, { mobileLayout: (store) => store.layoutType === 'mobile', }), - ...mapPiniaState(useSyncConfigStore, ['mergedConfig']), ...mapState({ backendInteractor: (state) => state.api.backendInteractor, mastoUserSocketStatus: (state) => state.api.mastoUserSocketStatus, diff --git a/src/components/chat_message/chat_message.js b/src/components/chat_message/chat_message.js index 983159bcb..af3701ebf 100644 --- a/src/components/chat_message/chat_message.js +++ b/src/components/chat_message/chat_message.js @@ -10,8 +10,8 @@ import Popover from '../popover/popover.vue' import StatusContent from '../status_content/status_content.vue' import UserAvatar from '../user_avatar/user_avatar.vue' -import { useInterfaceStore } from 'src/stores/interface.js' -import { useSyncConfigStore } from 'src/stores/sync_config.js' +import { useInstanceStore } from 'src/stores/instance.js' +import { useInterfaceStore } from 'src/stores/interface' import { library } from '@fortawesome/fontawesome-svg-core' import { faEllipsisH, faTimes } from '@fortawesome/free-solid-svg-icons' @@ -76,7 +76,7 @@ const ChatMessage = { }), ...mapState({ currentUser: (state) => state.users.currentUser, - restrictedNicknames: (state) => state.instance.restrictedNicknames, + restrictedNicknames: (state) => useInstanceStore().restrictedNicknames, }), popoverMarginStyle() { if (this.isCurrentUser) { @@ -85,8 +85,7 @@ const ChatMessage = { return { left: 50 } } }, - ...mapGetters(['findUser']), - ...mapPiniaState(useSyncConfigStore, ['mergedConfig']), + ...mapGetters(['mergedConfig', 'findUser']), }, data() { return { diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index fab1cb38f..cb7cf4782 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -8,9 +8,7 @@ import QuickViewSettings from '../quick_view_settings/quick_view_settings.vue' import Status from '../status/status.vue' import ThreadTree from '../thread_tree/thread_tree.vue' -import { useInstanceStore } from 'src/stores/instance.js' import { useInterfaceStore } from 'src/stores/interface' -import { useSyncConfigStore } from 'src/stores/sync_config.js' import { library } from '@fortawesome/fontawesome-svg-core' import { @@ -79,12 +77,37 @@ const conversation = { } }, computed: { + maxDepthToShowByDefault() { + // maxDepthInThread = max number of depths that is *visible* + // since our depth starts with 0 and "showing" means "showing children" + // there is a -2 here + const maxDepth = this.$store.getters.mergedConfig.maxDepthInThread - 2 + return maxDepth >= 1 ? maxDepth : 1 + }, + streamingEnabled() { + return ( + this.mergedConfig.useStreamingApi && + this.mastoUserSocketStatus === WSConnectionStatus.JOINED + ) + }, + displayStyle() { + return this.$store.getters.mergedConfig.conversationDisplay + }, isTreeView() { return !this.isLinearView }, + treeViewIsSimple() { + return !this.$store.getters.mergedConfig.conversationTreeAdvanced + }, isLinearView() { return this.displayStyle === 'linear' }, + shouldFadeAncestors() { + return this.$store.getters.mergedConfig.conversationTreeFadeAncestors + }, + otherRepliesButtonPosition() { + return this.$store.getters.mergedConfig.conversationOtherRepliesButton + }, showOtherRepliesButtonBelowStatus() { return this.otherRepliesButtonPosition === 'below' }, @@ -369,28 +392,7 @@ const conversation = { maybeHighlight() { return this.isExpanded ? this.highlight : null }, - ...mapPiniaState(useSyncConfigStore, ['mergedConfig']), - ...mapPiniaState(useSyncConfigStore, { - maxDepthToShowByDefault: (store) => { - // maxDepthInThread = max number of depths that is *visible* - // since our depth starts with 0 and "showing" means "showing children" - // there is a -2 here - const maxDepth = store.mergedConfig.maxDepthInThread - 2 - return maxDepth >= 1 ? maxDepth : 1 - }, - streamingEnabled: (store) => { - return ( - store.mergedConfig.useStreamingApi && - this.mastoUserSocketStatus === WSConnectionStatus.JOINED - ) - }, - displayStyle: (store) => store.mergedConfig.conversationDisplay, - treeViewIsSimple: (store) => !store.mergedConfig.conversationTreeAdvanced, - shouldFadeAncestors: (store) => - store.mergedConfig.conversationTreeFadeAncestors, - otherRepliesButtonPosition: (store) => - store.mergedConfig.conversationOtherRepliesButton, - }), + ...mapGetters(['mergedConfig']), ...mapState({ mastoUserSocketStatus: (state) => state.api.mastoUserSocketStatus, }), diff --git a/src/components/desktop_nav/desktop_nav.js b/src/components/desktop_nav/desktop_nav.js index a912e7fb6..943c66d1e 100644 --- a/src/components/desktop_nav/desktop_nav.js +++ b/src/components/desktop_nav/desktop_nav.js @@ -1,11 +1,10 @@ import SearchBar from 'components/search_bar/search_bar.vue' -import { mapState } from 'pinia' +import { mapActions, mapState } from 'pinia' import ConfirmModal from '../confirm_modal/confirm_modal.vue' import { useInstanceStore } from 'src/stores/instance.js' -import { useInterfaceStore } from 'src/stores/interface.js' -import { useSyncConfigStore } from 'src/stores/sync_config.js' +import { useInterfaceStore } from 'src/stores/interface' import { library } from '@fortawesome/fontawesome-svg-core' import { @@ -35,14 +34,6 @@ library.add( faCog, faInfoCircle, ) -const supportsMask = - window.CSS && - window.CSS.supports && - (window.CSS.supports('mask-size', 'contain') || - window.CSS.supports('-webkit-mask-size', 'contain') || - window.CSS.supports('-moz-mask-size', 'contain') || - window.CSS.supports('-ms-mask-size', 'contain') || - window.CSS.supports('-o-mask-size', 'contain')) export default { components: { @@ -51,21 +42,32 @@ export default { }, data: () => ({ searchBarHidden: true, + supportsMask: + window.CSS && + window.CSS.supports && + (window.CSS.supports('mask-size', 'contain') || + window.CSS.supports('-webkit-mask-size', 'contain') || + window.CSS.supports('-moz-mask-size', 'contain') || + window.CSS.supports('-ms-mask-size', 'contain') || + window.CSS.supports('-o-mask-size', 'contain')), showingConfirmLogout: false, }), computed: { + enableMask() { + return this.supportsMask && this.logoMask + }, logoStyle() { return { - visibility: this.logoMask ? 'hidden' : 'visible', + visibility: this.enableMask ? 'hidden' : 'visible', } }, logoMaskStyle() { - return this.logoMask + return this.enableMask ? { 'mask-image': `url(${this.logo})`, } : { - 'background-color': this.logoMask ? '' : 'transparent', + 'background-color': this.enableMask ? '' : 'transparent', } }, logoBgStyle() { @@ -74,28 +76,28 @@ export default { margin: `${this.logoMargin} 0`, opacity: this.searchBarHidden ? 1 : 0, }, - this.logoMask + this.enableMask ? {} : { - 'background-color': this.logoMask ? '' : 'transparent', + 'background-color': this.enableMask ? '' : 'transparent', }, ) }, + ...mapState(useInstanceStore, ['privateMode']), + ...mapState(useInstanceStore, { + logoMask: (store) => store.instanceIdentity.logoMask, + logo: (store) => store.instanceIdentity.logo, + logoLeft: (store) => store.instanceIdentity.logoLeft, + logoMargin: (store) => store.instanceIdentity.logoMargin, + sitename: (store) => store.instanceIdentity.name, + hideSitename: (store) => store.instanceIdentity.hideSitename, + }), currentUser() { return this.$store.state.users.currentUser }, shouldConfirmLogout() { - return useSyncConfigStore().mergedConfig.modalOnLogout + return this.$store.getters.mergedConfig.modalOnLogout }, - ...mapState(useInstanceStore, { - logo: (state) => state.instanceIdentity.logo, - logoMask: (state) => supportsMask && state.instanceIdentity.logoMask, - logoLeft: (state) => state.instanceIdentity.logoLeft, - logoMargin: (state) => state.instanceIdentity.logoMargin, - sitename: (state) => state.instanceIdentity.name, - privateMode: (state) => state.private, - hideSitename: (state) => state.instanceIdentity.hideSitename, - }), }, methods: { scrollToTop() { @@ -122,11 +124,6 @@ export default { onSearchBarToggled(hidden) { this.searchBarHidden = hidden }, - openSettingsModal() { - useInterfaceStore().openSettingsModal('user') - }, - openAdminModal() { - useInterfaceStore().openSettingsModal('admin') - }, + ...mapActions(useInterfaceStore, ['openSettingsModal']), }, } diff --git a/src/components/desktop_nav/desktop_nav.vue b/src/components/desktop_nav/desktop_nav.vue index 49382f8ee..da427f2a1 100644 --- a/src/components/desktop_nav/desktop_nav.vue +++ b/src/components/desktop_nav/desktop_nav.vue @@ -40,7 +40,7 @@