diff --git a/src/App.js b/src/App.js index 220f563f8..a65b5e52a 100644 --- a/src/App.js +++ b/src/App.js @@ -23,6 +23,7 @@ import { getOrCreateServiceWorker } from './services/sw/sw' import { windowHeight, windowWidth } from './services/window_utils/window_utils' 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' @@ -203,13 +204,15 @@ export default { 'layoutType', ]), ...mapState(useInstanceStore, ['styleDataUsed', 'private']), + ...mapState(useInstanceCapabilitiesStore, [ + 'suggestionsEnabled', + 'editingAvailable', + ]), ...mapState(useInstanceStore, { background: (store) => store.instanceIdentity.background, showFeaturesPanel: (store) => store.instanceIdentity.showFeaturesPanel, showInstanceSpecificPanel: (store) => store.instanceIdentity.showInstanceSpecificPanel, - suggestionsEnabled: (store) => store.featureSet.suggestionsEnabled, - editingAvailable: (store) => store.featureSet.editingAvailable, instanceSpecificPanelContent: (store) => store.instanceIdentity.instanceSpecificPanelContent, }), diff --git a/src/boot/after_store.js b/src/boot/after_store.js index 79ff631ca..40eda50f5 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -30,6 +30,7 @@ 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' @@ -82,10 +83,10 @@ const getInstanceConfig = async ({ store }) => { const textlimit = data.max_toot_chars const vapidPublicKey = data.pleroma.vapid_public_key - useInstanceStore().set({ - name: 'featureSet.pleromaExtensionsAvailable', - value: data.pleroma, - }) + useInstanceCapabilitiesStore().set( + 'pleromaExtensionsAvailable', + data.pleroma, + ) useInstanceStore().set({ name: 'textlimit', value: textlimit, @@ -278,68 +279,68 @@ const getNodeInfo = async ({ store }) => { path: 'registrationOpen', value: data.openRegistrations, }) - 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') || + 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', + + features.includes('pleroma_custom_emoji_reactions') || features.includes('custom_emoji_reactions'), - }) - 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'), - }) + ) + 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: 'localBubbleInstances', value: metadata.localBubbleInstances ?? [], }) - useInstanceStore().set({ - path: 'featureSet.localBubble', - value: (metadata.localBubbleInstances ?? []).length > 0, - }) + useInstanceCapabilitiesStore().set( + 'localBubble', + (metadata.localBubbleInstances ?? []).length > 0, + ) useInstanceStore().set({ path: 'limits.pollLimits', @@ -347,44 +348,39 @@ const getNodeInfo = async ({ store }) => { }) const uploadLimits = metadata.uploadLimits useInstanceStore().set({ - name: 'limits.uploadlimit', + path: 'limits.uploadlimit', value: parseInt(uploadLimits.general), }) useInstanceStore().set({ - name: 'limits.avatarlimit', + path: 'limits.avatarlimit', value: parseInt(uploadLimits.avatar), }) useInstanceStore().set({ - name: 'limits.backgroundlimit', + path: 'limits.backgroundlimit', value: parseInt(uploadLimits.background), }) useInstanceStore().set({ - name: 'limits.bannerlimit', + path: 'limits.bannerlimit', value: parseInt(uploadLimits.banner), }) useInstanceStore().set({ - name: 'limits.fieldsLimits', + path: 'limits.fieldsLimits', value: metadata.fieldsLimits, }) useInstanceStore().set({ - name: 'restrictedNicknames', + path: 'restrictedNicknames', value: metadata.restrictedNicknames, }) - useInstanceStore().set({ - name: 'featureSet.postFormats', - value: metadata.postFormats, - }) + useInstanceCapabilitiesStore().set('postFormats', metadata.postFormats) const suggestions = metadata.suggestions - useInstanceStore().set({ - name: 'featureSet.suggestionsEnabled', - value: suggestions.enabled, - }) - useInstanceStore().set({ - name: '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({ @@ -407,27 +403,26 @@ const getNodeInfo = async ({ store }) => { const federation = metadata.federation - useInstanceStore().set({ - name: '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({ - name: 'federationPolicy', + path: 'federationPolicy', value: federation, }) useInstanceStore().set({ - name: 'federating', + path: 'federating', value: typeof federation.enabled === 'undefined' ? true : federation.enabled, }) const accountActivationRequired = metadata.accountActivationRequired useInstanceStore().set({ - name: 'accountActivationRequired', + path: 'accountActivationRequired', value: accountActivationRequired, }) diff --git a/src/boot/routes.js b/src/boot/routes.js index c5876a3d4..193daf4a7 100644 --- a/src/boot/routes.js +++ b/src/boot/routes.js @@ -33,6 +33,7 @@ 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) => { @@ -205,7 +206,7 @@ export default (store) => { }, ] - if (useInstanceStore().featureSet.pleromaChatMessagesAvailable) { + if (useInstanceCapabilitiesStore().pleromaChatMessagesAvailable) { routes = routes.concat([ { name: 'chat', diff --git a/src/components/account_actions/account_actions.js b/src/components/account_actions/account_actions.js index 1910d3544..8fce4b5af 100644 --- a/src/components/account_actions/account_actions.js +++ b/src/components/account_actions/account_actions.js @@ -6,7 +6,7 @@ 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.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useReportsStore } from 'src/stores/reports' import { library } from '@fortawesome/fontawesome-svg-core' @@ -94,11 +94,10 @@ const AccountActions = { shouldConfirmRemoveUserFromFollowers() { return this.$store.getters.mergedConfig.modalOnRemoveUserFromFollowers }, - ...mapState(useInstanceStore, { - blockExpirationSupported: (store) => store.featureSet.blockExpiration, - pleromaChatMessagesAvailable: (store) => - store.featureSet.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 @@ store.featureSet.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/lists_menu/lists_menu_content.js b/src/components/lists_menu/lists_menu_content.js index 49b413b4f..4dae0bff4 100644 --- a/src/components/lists_menu/lists_menu_content.js +++ b/src/components/lists_menu/lists_menu_content.js @@ -16,7 +16,7 @@ export const ListsMenuContent = { ...mapPiniaState(useListsStore, { lists: getListEntries, }), - ...mapPiniaState(useInstanceStore, ['private','federating']), + ...mapPiniaState(useInstanceStore, ['private', 'federating']), ...mapState({ currentUser: (state) => state.users.currentUser, }), diff --git a/src/components/moderation_tools/moderation_tools.js b/src/components/moderation_tools/moderation_tools.js index 6628e02f8..4149fd6d0 100644 --- a/src/components/moderation_tools/moderation_tools.js +++ b/src/components/moderation_tools/moderation_tools.js @@ -2,6 +2,7 @@ import DialogModal from '../dialog_modal/dialog_modal.vue' import Popover from '../popover/popover.vue' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faChevronDown } from '@fortawesome/free-solid-svg-icons' @@ -56,7 +57,7 @@ const ModerationTools = { }, canUseTagPolicy() { return ( - useInstanceStore().featureSet.tagPolicyAvailable && + useInstanceCapabilitiesStore().tagPolicyAvailable && this.privileged('users_manage_tags') ) }, diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js index eb10c8148..8aff31f02 100644 --- a/src/components/nav_panel/nav_panel.js +++ b/src/components/nav_panel/nav_panel.js @@ -11,6 +11,7 @@ import NavigationPins from 'src/components/navigation/navigation_pins.vue' import { useAnnouncementsStore } from 'src/stores/announcements' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useServerSideStorageStore } from 'src/stores/serverSideStorage' import { library } from '@fortawesome/fontawesome-svg-core' @@ -112,14 +113,14 @@ const NavPanel = { unreadAnnouncementCount: 'unreadAnnouncementCount', supportsAnnouncements: (store) => store.supportsAnnouncements, }), + ...mapPiniaState(useInstanceCapabilitiesStore, [ + 'pleromaChatMessagesAvailable', + 'pleromaBookmarkFoldersAvailable', + 'localBubble', + ]), ...mapPiniaState(useInstanceStore, ['federating']), ...mapPiniaState(useInstanceStore, { privateMode: (store) => store.private, - pleromaChatMessagesAvailable: (store) => - store.featureSet.pleromaChatMessagesAvailable, - bookmarkFolders: (store) => - store.featureSet.pleromaBookmarkFoldersAvailable, - bubbleTimeline: (store) => store.featureSet.localBubble, }), ...mapPiniaState(useServerSideStorageStore, { collapsed: (store) => store.prefsStorage.simple.collapseNav, @@ -142,8 +143,8 @@ const NavPanel = { isFederating: this.federating, isPrivate: this.privateMode, currentUser: this.currentUser, - supportsBubbleTimeline: this.bubbleTimeline, - supportsBookmarkFolders: this.bookmarkFolders, + supportsBubbleTimeline: this.localBubble, + supportsBookmarkFolders: this.pleromaBookmarkFoldersAvailable, }, ) }, @@ -156,8 +157,8 @@ const NavPanel = { isFederating: this.federating, isPrivate: this.privateMode, currentUser: this.currentUser, - supportsBubbleTimeline: this.bubbleTimeline, - supportsBookmarkFolders: this.bookmarkFolders, + supportsBubbleTimeline: this.localBubble, + supportsBookmarkFolders: this.pleromaBookmarkFoldersAvailable, }, ) }, diff --git a/src/components/nav_panel/nav_panel.vue b/src/components/nav_panel/nav_panel.vue index 10903bcae..ae5c6eae4 100644 --- a/src/components/nav_panel/nav_panel.vue +++ b/src/components/nav_panel/nav_panel.vue @@ -84,7 +84,7 @@ /> new Set(store.prefsStorage.collections.pinnedNavItems), }), - ...mapPiniaState(useInstanceStore, { - pleromaChatMessagesAvailable: (store) => - store.featureSet.pleromaChatMessagesAvailable, - bubbleTimeline: (store) => store.featureSet.localBubble, - }), ...mapPiniaState(useInstanceStore, ['private', 'federating']), + ...mapPiniaState(useInstanceCapabilitiesStore, [ + 'pleromaChatMessagesAvailable', + 'localBubble', + ]), ...mapState({ currentUser: (state) => state.users.currentUser, followRequestCount: (state) => state.api.followRequests.length, @@ -97,13 +97,11 @@ const NavPanel = { isFederating: this.federating, isPrivate: this.private, currentUser: this.currentUser, - supportsBubbleTimeline: this.bubbleTimeline, + supportsBubbleTimeline: this.localBubble, supportsBookmarkFolders: this.bookmarks, }, ) } - console.log([...this.pinnedItems]) - console.log([...this.bookmarks]) return filterNavigation( [ ...Object.entries({ ...TIMELINES }) @@ -118,7 +116,7 @@ const NavPanel = { { hasChats: this.pleromaChatMessagesAvailable, hasAnnouncements: this.supportsAnnouncements, - supportsBubbleTimeline: this.bubbleTimeline, + supportsBubbleTimeline: this.localBubble, supportsBookmarkFolders: this.bookmarks, isFederating: this.federating, isPrivate: this.private, diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 7b9512456..802d340ab 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -22,6 +22,7 @@ import StatusContent from '../status_content/status_content.vue' import { useEmojiStore } from 'src/stores/emoji.js' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInterfaceStore } from 'src/stores/interface.js' import { useMediaViewerStore } from 'src/stores/media_viewer.js' @@ -309,14 +310,14 @@ const PostStatusForm = { return this.mergedConfig.alwaysShowSubjectInput }, postFormats() { - return useInstanceStore().featureSet.postFormats || [] + return useInstanceCapabilitiesStore().postFormats || [] }, safeDMEnabled() { - return useInstanceStore().featureSet.safeDM + return useInstanceCapabilitiesStore().safeDM }, pollsAvailable() { return ( - useInstanceStore().featureSet.pollsAvailable && + useInstanceCapabilitiesStore().pollsAvailable && useInstanceStore().limits.pollLimits.max_options >= 2 && this.disablePolls !== true ) @@ -346,7 +347,7 @@ const PostStatusForm = { return typeof this.statusId !== 'undefined' && this.statusId.trim() !== '' }, quotable() { - if (!useInstanceStore().featureSet.quotingAvailable) { + if (!useInstanceCapabilitiesStore().quotingAvailable) { return false } diff --git a/src/components/settings_modal/helpers/setting.js b/src/components/settings_modal/helpers/setting.js index c77de92b1..2884d92b4 100644 --- a/src/components/settings_modal/helpers/setting.js +++ b/src/components/settings_modal/helpers/setting.js @@ -15,6 +15,10 @@ export default { type: String, default: null, }, + description: { + type: String, + default: null, + }, path: { type: [String, Array], required: false, diff --git a/src/components/settings_modal/helpers/vertical_tab_switcher.jsx b/src/components/settings_modal/helpers/vertical_tab_switcher.jsx index 1a8e13e18..f8ffc99ec 100644 --- a/src/components/settings_modal/helpers/vertical_tab_switcher.jsx +++ b/src/components/settings_modal/helpers/vertical_tab_switcher.jsx @@ -35,11 +35,6 @@ export default { type: Boolean, default: false, }, - parentCollapsed: { - required: false, - type: Boolean, - default: null, - }, }, data() { return { @@ -202,7 +197,6 @@ export default {
diff --git a/src/components/settings_modal/settings_modal_user_content.vue b/src/components/settings_modal/settings_modal_user_content.vue index 44460adfb..139622781 100644 --- a/src/components/settings_modal/settings_modal_user_content.vue +++ b/src/components/settings_modal/settings_modal_user_content.vue @@ -3,7 +3,6 @@ ref="tabSwitcher" class="settings_tab-switcher" :scrollable-tabs="true" - :child-collapsed="childCollapsed" :body-scroll-lock="bodyLock" :hide-header="navHideHeader" > diff --git a/src/components/settings_modal/tabs/clutter_tab.js b/src/components/settings_modal/tabs/clutter_tab.js index 903ffe540..7aef996c8 100644 --- a/src/components/settings_modal/tabs/clutter_tab.js +++ b/src/components/settings_modal/tabs/clutter_tab.js @@ -10,7 +10,7 @@ import IntegerSetting from '../helpers/integer_setting.vue' import SharedComputedObject from '../helpers/shared_computed_object.js' import UnitSetting from '../helpers/unit_setting.vue' -import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useServerSideStorageStore } from 'src/stores/serverSideStorage' const ClutterTab = { @@ -25,14 +25,12 @@ const ClutterTab = { }, computed: { ...SharedComputedObject(), + ...mapState(useInstanceCapabilitiesStore, ['shoutAvailable']), ...mapState(useServerSideStorageStore, { muteFilters: (store) => Object.entries(store.prefsStorage.simple.muteFilters), muteFiltersObject: (store) => store.prefsStorage.simple.muteFilters, }), - ...mapState(useInstanceStore, { - blockExpirationSupported: (store) => store.featureSet.blockExpiration, - }), onMuteDefaultActionLv1: { get() { const value = this.$store.state.config.onMuteDefaultAction diff --git a/src/components/settings_modal/tabs/clutter_tab.vue b/src/components/settings_modal/tabs/clutter_tab.vue index daf098f5a..5cd66dccd 100644 --- a/src/components/settings_modal/tabs/clutter_tab.vue +++ b/src/components/settings_modal/tabs/clutter_tab.vue @@ -73,7 +73,7 @@ {{ $t('settings.user_card_hide_personal_marks') }} -
  • +
  • diff --git a/src/components/settings_modal/tabs/composing_tab.js b/src/components/settings_modal/tabs/composing_tab.js index ba3ddaca8..9d55d1f4f 100644 --- a/src/components/settings_modal/tabs/composing_tab.js +++ b/src/components/settings_modal/tabs/composing_tab.js @@ -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' @@ -29,12 +29,6 @@ import { library.add(faGlobe, faMessage, faPenAlt, faDatabase, faSliders) const ComposingTab = { - props: { - parentCollapsed: { - required: true, - type: Boolean, - }, - }, data() { return { subjectLineOptions: ['email', 'noop', 'masto'].map((mode) => ({ @@ -132,9 +126,7 @@ const ComposingTab = { }, }, ...SharedComputedObject(), - ...mapState(useInstanceStore, { - blockExpirationSupported: (store) => store.featureSet.blockExpiration, - }), + ...mapState(useInstanceStore, ['blockExpiration']), }, methods: { changeDefaultScope(value) { diff --git a/src/components/settings_modal/tabs/filtering_tab.js b/src/components/settings_modal/tabs/filtering_tab.js index fc1d4da4c..68efbe762 100644 --- a/src/components/settings_modal/tabs/filtering_tab.js +++ b/src/components/settings_modal/tabs/filtering_tab.js @@ -11,7 +11,7 @@ import IntegerSetting from '../helpers/integer_setting.vue' import SharedComputedObject from '../helpers/shared_computed_object.js' import UnitSetting from '../helpers/unit_setting.vue' -import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInterfaceStore } from 'src/stores/interface' import { useServerSideStorageStore } from 'src/stores/serverSideStorage' @@ -97,9 +97,7 @@ const FilteringTab = { Object.entries(store.prefsStorage.simple.muteFilters), muteFiltersObject: (store) => store.prefsStorage.simple.muteFilters, }), - ...mapState(useInstanceStore, { - blockExpirationSupported: (store) => store.featureSet.blockExpiration, - }), + ...mapState(useInstanceCapabilitiesStore, ['blockExpiration']), onMuteDefaultActionLv1: { get() { const value = this.$store.state.config.onMuteDefaultAction diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue index ff7498656..bb0dccb85 100644 --- a/src/components/settings_modal/tabs/filtering_tab.vue +++ b/src/components/settings_modal/tabs/filtering_tab.vue @@ -47,7 +47,7 @@
  • -
  • +
  • {{ $t('user_card.default_block_expiration') }} diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js index 3f2530278..0d8f9a786 100644 --- a/src/components/settings_modal/tabs/general_tab.js +++ b/src/components/settings_modal/tabs/general_tab.js @@ -10,16 +10,11 @@ import SharedComputedObject from '../helpers/shared_computed_object.js' import UnitSetting from '../helpers/unit_setting.vue' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import localeService from 'src/services/locale/locale.service.js' const GeneralTab = { - props: { - parentCollapsed: { - required: true, - type: Boolean, - }, - }, data() { return { absoluteTime12hOptions: ['24h', '12h'].map((mode) => ({ @@ -52,9 +47,7 @@ const GeneralTab = { }, }, ...SharedComputedObject(), - ...mapState(useInstanceStore, { - blockExpirationSupported: (store) => store.featureSet.blockExpiration, - }), + ...mapState(useInstanceCapabilitiesStore, ['blockExpiration']), }, methods: { updateProfile() { diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index ceb073a48..c44e558b5 100644 --- a/src/components/settings_modal/tabs/general_tab.vue +++ b/src/components/settings_modal/tabs/general_tab.vue @@ -157,7 +157,7 @@
  • store.featureSet.postFormats || [], - instanceSpecificPanelPresent: (store) => - store.instanceIdentity.instanceSpecificPanelPresent, - instanceShoutboxPresent: (store) => store.featureSet.shoutAvailable, - }), + ...mapState(useInstanceCapabilitiesStore, [ + 'instanceSpecificPanelPresent', + 'postFormats', + 'suggestionsEnabled', + ]), columns() { const mode = this.$store.getters.mergedConfig.thirdColumnMode diff --git a/src/components/settings_modal/tabs/posts_tab.js b/src/components/settings_modal/tabs/posts_tab.js index dfc4d4f8b..268a0a56f 100644 --- a/src/components/settings_modal/tabs/posts_tab.js +++ b/src/components/settings_modal/tabs/posts_tab.js @@ -6,12 +6,6 @@ import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue' import SharedComputedObject from '../helpers/shared_computed_object.js' const GeneralTab = { - props: { - parentCollapsed: { - required: true, - type: Boolean, - }, - }, data() { return { conversationDisplayOptions: ['tree', 'linear'].map((mode) => ({ diff --git a/src/components/settings_modal/tabs/security_tab/security_tab.js b/src/components/settings_modal/tabs/security_tab/security_tab.js index c24ff8b6f..96510edcf 100644 --- a/src/components/settings_modal/tabs/security_tab/security_tab.js +++ b/src/components/settings_modal/tabs/security_tab/security_tab.js @@ -3,6 +3,7 @@ import ProgressButton from 'src/components/progress_button/progress_button.vue' import Mfa from './mfa.vue' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useOAuthTokensStore } from 'src/stores/oauth_tokens' import localeService from 'src/services/locale/locale.service.js' @@ -45,7 +46,7 @@ const SecurityTab = { return this.$store.state.users.currentUser }, pleromaExtensionsAvailable() { - return useInstanceStore().featureSet.pleromaExtensionsAvailable + return useInstanceCapabilitiesStore().pleromaExtensionsAvailable }, oauthTokens() { return useOAuthTokensStore().tokens.map((oauthToken) => { diff --git a/src/components/side_drawer/side_drawer.js b/src/components/side_drawer/side_drawer.js index 40fcdc23d..628d8d33f 100644 --- a/src/components/side_drawer/side_drawer.js +++ b/src/components/side_drawer/side_drawer.js @@ -8,6 +8,7 @@ import UserCard from '../user_card/user_card.vue' import { useAnnouncementsStore } from 'src/stores/announcements' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInterfaceStore } from 'src/stores/interface' import { useShoutStore } from 'src/stores/shout' @@ -95,14 +96,15 @@ const SideDrawer = { 'supportsAnnouncements', 'unreadAnnouncementCount', ]), + ...mapState(useInstanceCapabilitiesStore, [ + 'pleromaChatMessagesAvailable', + 'suggestionsEnabled', + ]), ...mapState(useInstanceStore, ['private', 'federating']), ...mapState(useInstanceStore, { logo: (store) => store.instanceIdentity.logo, sitename: (store) => store.instanceIdentity.name, hideSitename: (store) => store.instanceIdentity.hideSitename, - pleromaChatMessagesAvailable: (store) => - store.featureSet.pleromaChatMessagesAvailable, - suggestionsEnabled: (store) => store.featureSet.suggestionsEnabled, }), ...mapGetters(['unreadChatCount', 'draftCount']), }, diff --git a/src/components/status/status.js b/src/components/status/status.js index 66acae0d3..fbea34b4b 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -21,6 +21,7 @@ import UserListPopover from '../user_list_popover/user_list_popover.vue' import UserPopover from '../user_popover/user_popover.vue' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useServerSideStorageStore } from 'src/stores/serverSideStorage' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' @@ -497,7 +498,7 @@ const Status = { return this.status.edited_at !== null }, editingAvailable() { - return useInstanceStore().featureSet.editingAvailable + return useInstanceCapabilitiesStore().editingAvailable }, hasVisibleQuote() { return this.status.quote_url && this.status.quote_visible diff --git a/src/components/status_action_buttons/buttons_definitions.js b/src/components/status_action_buttons/buttons_definitions.js index 4e0baaa61..20db7aa45 100644 --- a/src/components/status_action_buttons/buttons_definitions.js +++ b/src/components/status_action_buttons/buttons_definitions.js @@ -1,5 +1,6 @@ import { useEditStatusStore } from 'src/stores/editStatus.js' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useReportsStore } from 'src/stores/reports.js' import { useStatusHistoryStore } from 'src/stores/statusHistory.js' @@ -161,7 +162,7 @@ export const BUTTONS = [ label: 'status.status_history', if({ status, state }) { return ( - useInstanceStore().featureSet.editingAvailable && + useInstanceCapabilitiesStore().editingAvailable && status.edited_at !== null ) }, @@ -193,7 +194,7 @@ export const BUTTONS = [ if({ status, loggedIn, currentUser, state }) { return ( loggedIn && - useInstanceStore().featureSet.editingAvailable && + useInstanceCapabilitiesStore().editingAvailable && status.user.id === currentUser.id ) }, diff --git a/src/components/timeline_menu/timeline_menu.js b/src/components/timeline_menu/timeline_menu.js index ebbe803c7..b309a93ff 100644 --- a/src/components/timeline_menu/timeline_menu.js +++ b/src/components/timeline_menu/timeline_menu.js @@ -10,6 +10,7 @@ import Popover from '../popover/popover.vue' import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInterfaceStore } from 'src/stores/interface' import { useListsStore } from 'src/stores/lists' @@ -61,14 +62,13 @@ const TimelineMenu = { (route === 'bookmark-folder' || route === 'bookmarks') ) }, + ...mapPiniaState(useInstanceCapabilitiesStore, [ + 'pleromaChatMessagesAvailable', + 'pleromaBookmarkFoldersAvailable', + 'bookmarkFolders', + 'localBubble', + ]), ...mapPiniaState(useInstanceStore, ['private', 'federating']), - ...mapPiniaState(useInstanceStore, { - pleromaChatMessagesAvailable: (store) => - store.featureSet.pleromaChatMessagesAvailable, - bookmarkFolders: (store) => - store.featureSet.pleromaBookmarkFoldersAvailable, - bubbleTimeline: (store) => store.featureSet.localBubble, - }), ...mapState({ currentUser: (state) => state.users.currentUser, }), @@ -80,8 +80,8 @@ const TimelineMenu = { isFederating: this.federating, isPrivate: this.private, currentUser: this.currentUser, - supportsBookmarkFolders: this.bookmarkFolders, - supportsBubbleTimeline: this.bubbleTimeline, + supportsBookmarkFolders: this.pleromaBookmarkFoldersAvailable, + supportsBubbleTimeline: this.localBubble, }, ) }, diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js index 5cbb8b6d7..0df27e6cb 100644 --- a/src/components/user_card/user_card.js +++ b/src/components/user_card/user_card.js @@ -25,6 +25,7 @@ import UserNote from '../user_note/user_note.vue' import { useEmojiStore } from 'src/stores/emoji.js' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { usePostStatusStore } from 'src/stores/post_status' import { propsToNative } from 'src/services/attributes_helper/attributes_helper.service.js' @@ -180,7 +181,7 @@ export default { return false }, groupActorAvailable() { - return useInstanceStore().featureSet.groupActorAvailable + return useInstanceCapabilitiesStore().groupActorAvailable }, availableActorTypes() { return this.groupActorAvailable diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index d40103293..25f71fba8 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -10,6 +10,7 @@ import Timeline from '../timeline/timeline.vue' import UserCard from '../user_card/user_card.vue' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' @@ -89,7 +90,7 @@ const UserProfile = { favoritesTabVisible() { return ( this.isUs || - (useInstanceStore().featureSet.pleromaPublicFavouritesAvailable && + (useInstanceCapabilitiesStore().pleromaPublicFavouritesAvailable && !this.user.hide_favorites) ) }, diff --git a/src/components/who_to_follow_panel/who_to_follow_panel.js b/src/components/who_to_follow_panel/who_to_follow_panel.js index 13787000e..e364dcf80 100644 --- a/src/components/who_to_follow_panel/who_to_follow_panel.js +++ b/src/components/who_to_follow_panel/who_to_follow_panel.js @@ -3,6 +3,7 @@ import { shuffle } from 'lodash' import apiService from '../../services/api/api.service.js' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' @@ -49,7 +50,7 @@ const WhoToFollowPanel = { return this.$store.state.users.currentUser.screen_name }, suggestionsEnabled() { - return useInstanceStore().featureSet.suggestionsEnabled + return useInstanceCapabilitiesStore().suggestionsEnabled }, }, methods: { diff --git a/src/modules/api.js b/src/modules/api.js index d658433fe..d6bf27f23 100644 --- a/src/modules/api.js +++ b/src/modules/api.js @@ -5,6 +5,7 @@ import backendInteractorService from '../services/backend_interactor_service/bac import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.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' @@ -239,7 +240,7 @@ const api = { ) { if ( timeline === 'favourites' && - !useInstanceStore().featureSet.pleromaPublicFavouritesAvailable + !useInstanceCapabilitiesStore().pleromaPublicFavouritesAvailable ) return if (store.state.fetchers[timeline]) return @@ -324,7 +325,8 @@ const api = { // Bookmark folders startFetchingBookmarkFolders(store) { if (store.state.fetchers.bookmarkFolders) return - if (!useInstanceStore().featureSet.pleromaBookmarkFoldersAvailable) return + if (!useInstanceCapabilitiesStore().pleromaBookmarkFoldersAvailable) + return const fetcher = store.state.backendInteractor.startFetchingBookmarkFolders({ store }) store.commit('addFetcher', { fetcherName: 'bookmarkFolders', fetcher }) diff --git a/src/modules/config.js b/src/modules/config.js index 508ddafc6..82acf8162 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -59,7 +59,6 @@ const config = { }, mergedConfig(state) { const instancePrefs = useInstanceStore().prefsStorage - console.log(state) const result = Object.fromEntries( Object.keys(defaultState).map((key) => [ key, diff --git a/src/modules/users.js b/src/modules/users.js index 04c444071..b0febcd3a 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -23,6 +23,7 @@ import { import { useEmojiStore } from 'src/stores/emoji.js' 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 { useServerSideStorageStore } from 'src/stores/serverSideStorage' @@ -766,7 +767,7 @@ const users = { dispatch('startFetchingNotifications') if ( - useInstanceStore().featureSet.pleromaChatMessagesAvailable + useInstanceCapabilitiesStore().pleromaChatMessagesAvailable ) { // Start fetching chats dispatch('startFetchingChats') diff --git a/src/services/notifications_fetcher/notifications_fetcher.service.js b/src/services/notifications_fetcher/notifications_fetcher.service.js index f82f98130..73411b6a5 100644 --- a/src/services/notifications_fetcher/notifications_fetcher.service.js +++ b/src/services/notifications_fetcher/notifications_fetcher.service.js @@ -2,6 +2,7 @@ import apiService from '../api/api.service.js' import { promiseInterval } from '../promise_interval/promise_interval.js' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInterfaceStore } from 'src/stores/interface.js' const update = ({ store, notifications, older }) => { @@ -30,7 +31,7 @@ const fetchAndUpdate = ({ store, credentials, older = false, since }) => { const timelineData = rootState.notifications const hideMutedPosts = getters.mergedConfig.hideMutedPosts - if (useInstanceStore().featureSet.pleromaChatMessagesAvailable) { + if (useInstanceCapabilitiesStore().pleromaChatMessagesAvailable) { mastoApiNotificationTypes.add('pleroma:chat_mention') } diff --git a/src/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js index 0d993a1e3..da62f8b37 100644 --- a/src/services/timeline_fetcher/timeline_fetcher.service.js +++ b/src/services/timeline_fetcher/timeline_fetcher.service.js @@ -4,6 +4,7 @@ import apiService from '../api/api.service.js' import { promiseInterval } from '../promise_interval/promise_interval.js' import { useInstanceStore } from 'src/stores/instance.js' +import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js' import { useInterfaceStore } from 'src/stores/interface.js' const update = ({ @@ -78,7 +79,7 @@ const fetchAndUpdate = ({ .then((response) => { if (response.errors) { if (timeline === 'favorites') { - useInstanceStore().featureSet.pleromaPublicFavouritesAvailable = false + useInstanceCapabilitiesStore().pleromaPublicFavouritesAvailable = false return } throw new Error(`${response.status} ${response.statusText}`) diff --git a/src/stores/instance.js b/src/stores/instance.js index 87bb00d12..8caca3552 100644 --- a/src/stores/instance.js +++ b/src/stores/instance.js @@ -69,31 +69,6 @@ const defaultState = { restrictedNicknames: [], localBubbleInstances: [], // Akkoma - // Feature-set, apparently, not everything here is reported... - featureSet: { - postFormats: [], - mailerEnabled: false, - safeDM: true, - shoutAvailable: false, - pleromaExtensionsAvailable: true, - pleromaChatMessagesAvailable: false, - pleromaCustomEmojiReactionsAvailable: false, - pleromaBookmarkFoldersAvailable: false, - pleromaPublicFavouritesAvailable: true, - statusNotificationTypeAvailable: true, - gopherAvailable: false, - editingAvailable: false, - mediaProxyAvailable: false, - suggestionsEnabled: false, - suggestionsWeb: '', - quotingAvailable: false, - groupActorAvailable: false, - blockExpiration: false, - tagPolicyAvailable: false, - pollsAvailable: false, - localBubble: false, // Akkoma - }, - // Version Information backendVersion: '', backendRepository: '', @@ -118,17 +93,10 @@ export const useInstanceStore = defineStore('instance', { console.error( `Unknown instance option ${path ?? name}, value: ${value}`, ) + set(this, path ?? name, value) - switch (name) { - case 'name': - useInterfaceStore().setPageTitle() - break - case 'shoutAvailable': - if (value) { - window.vuex.dispatch('initializeSocket') - } - break - } + + if ((path ?? name) === 'name') useInterfaceStore().setPageTitle() }, async getKnownDomains() { try { diff --git a/src/stores/instance_capabilities.js b/src/stores/instance_capabilities.js new file mode 100644 index 000000000..35d472178 --- /dev/null +++ b/src/stores/instance_capabilities.js @@ -0,0 +1,47 @@ +import { defineStore } from 'pinia' + +const defaultState = { + postFormats: [], + mailerEnabled: false, + safeDM: true, + shoutAvailable: false, + pleromaExtensionsAvailable: true, + pleromaChatMessagesAvailable: false, + pleromaCustomEmojiReactionsAvailable: false, + pleromaBookmarkFoldersAvailable: false, + pleromaPublicFavouritesAvailable: true, + statusNotificationTypeAvailable: true, + gopherAvailable: false, + editingAvailable: false, + mediaProxyAvailable: false, + suggestionsEnabled: false, + suggestionsWeb: '', + quotingAvailable: false, + groupActorAvailable: false, + blockExpiration: false, + tagPolicyAvailable: false, + pollsAvailable: false, + localBubble: false, // Akkoma +} + +export const useInstanceCapabilitiesStore = defineStore( + 'instance-capabilities', + { + state: () => ({ ...defaultState }), + actions: { + set(capability, value) { + if (!Object.hasOwn(defaultState, capability)) { + console.error( + `Unknown instance capability ${capability}, value: ${value}`, + ) + } + + this[capability] = value + + if (capability === 'shoutAvailable') { + window.vuex.dispatch('initializeSocket') + } + }, + }, + }, +)