diff --git a/package.json b/package.json
index 20c01a0b3..1d0382d46 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
"ci-eslint": "yarn exec eslint",
"ci-stylelint": "yarn exec stylelint '**/*.scss' '**/*.vue'",
"lint": "yarn ci-biome; yarn ci-eslint; yarn ci-stylelint",
- "lint-fix": "yarn exec eslint --fix; yarn exec stylelint '**/*.scss' '**/*.vue' --fix; biome check --write"
+ "lint-fix": "yarn exec eslint -- --fix; yarn exec stylelint '**/*.scss' '**/*.vue' --fix; biome check --write"
},
"dependencies": {
"@babel/runtime": "7.28.4",
diff --git a/src/App.js b/src/App.js
index 6dcd80a73..0128fc198 100644
--- a/src/App.js
+++ b/src/App.js
@@ -26,6 +26,7 @@ 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'
export default {
name: 'app',
@@ -72,7 +73,7 @@ export default {
},
created() {
// Load the locale from the storage
- const val = this.$store.getters.mergedConfig.interfaceLanguage
+ const val = useSyncConfigStore().mergedConfig.interfaceLanguage
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
document.getElementById('modal').classList = ['-' + this.layoutType]
@@ -122,7 +123,7 @@ export default {
]
},
navClasses() {
- const { navbarColumnStretch } = this.$store.getters.mergedConfig
+ const { navbarColumnStretch } = useSyncConfigStore().mergedConfig
return [
'-' + this.layoutType,
...(navbarColumnStretch ? ['-column-stretch'] : []),
@@ -157,19 +158,19 @@ export default {
if (this.isChats) return false
if (this.isListEdit) return false
return (
- this.$store.getters.mergedConfig.alwaysShowNewPostButton ||
+ useSyncConfigStore().mergedConfig.alwaysShowNewPostButton ||
this.layoutType === 'mobile'
)
},
shoutboxPosition() {
- return this.$store.getters.mergedConfig.alwaysShowNewPostButton || false
+ return useSyncConfigStore().mergedConfig.alwaysShowNewPostButton || false
},
hideShoutbox() {
- return this.$store.getters.mergedConfig.hideShoutbox
+ return useSyncConfigStore().mergedConfig.hideShoutbox
},
reverseLayout() {
const { thirdColumnMode, sidebarRight: reverseSetting } =
- this.$store.getters.mergedConfig
+ useSyncConfigStore().mergedConfig
if (this.layoutType !== 'wide') {
return reverseSetting
} else {
@@ -179,10 +180,10 @@ export default {
}
},
noSticky() {
- return this.$store.getters.mergedConfig.disableStickyHeaders
+ return useSyncConfigStore().mergedConfig.disableStickyHeaders
},
showScrollbars() {
- return this.$store.getters.mergedConfig.showScrollbars
+ return useSyncConfigStore().mergedConfig.showScrollbars
},
scrollParent() {
return window /* this.$refs.appContentRef */
@@ -190,7 +191,7 @@ export default {
showInstanceSpecificPanel() {
return (
this.instanceSpecificPanelPresent &&
- !this.$store.getters.mergedConfig.hideISP
+ !useSyncConfigStore().mergedConfig.hideISP
)
},
...mapGetters(['mergedConfig']),
diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index b7e97cf45..97f9b8a42 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -17,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 { applyConfig } from '../services/style_setter/style_setter.js'
+import { applyStyleConfig } from '../services/style_setter/style_setter.js'
import { initServiceWorker, updateFocus } from '../services/sw/sw.js'
import {
windowHeight,
@@ -88,25 +88,25 @@ const getInstanceConfig = async ({ store }) => {
data.pleroma,
)
useInstanceStore().set({
- name: 'textlimit',
+ path: 'textlimit',
value: textlimit,
})
useInstanceStore().set({
- name: 'accountApprovalRequired',
+ path: 'accountApprovalRequired',
value: data.approval_required,
})
useInstanceStore().set({
- name: 'birthdayRequired',
+ path: 'birthdayRequired',
value: !!data.pleroma?.metadata.birthday_required,
})
useInstanceStore().set({
- name: 'birthdayMinAge',
+ path: 'birthdayMinAge',
value: data.pleroma?.metadata.birthday_min_age || 0,
})
if (vapidPublicKey) {
useInstanceStore().set({
- name: 'vapidPublicKey',
+ path: 'vapidPublicKey',
value: vapidPublicKey,
})
}
@@ -258,7 +258,7 @@ const getAppSecret = async ({ store }) => {
const resolveStaffAccounts = ({ store, accounts }) => {
const nicknames = accounts.map((uri) => uri.split('/').pop())
useInstanceStore().set({
- name: 'staffAccounts',
+ path: 'staffAccounts',
value: nicknames,
})
}
@@ -384,20 +384,20 @@ const getNodeInfo = async ({ store }) => {
const software = data.software
useInstanceStore().set({
- name: 'backendVersion',
+ path: 'backendVersion',
value: software.version,
})
useInstanceStore().set({
- name: 'backendRepository',
+ path: 'backendRepository',
value: software.repository,
})
const priv = metadata.private
- useInstanceStore().set({ name: 'privateMode', value: priv })
+ useInstanceStore().set({ path: 'privateMode', value: priv })
const frontendVersion = window.___pleromafe_commit_hash
useInstanceStore().set({
- name: 'frontendVersion',
+ path: 'frontendVersion',
value: frontendVersion,
})
@@ -547,7 +547,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
return Promise.reject(e)
}
- applyConfig(store.state.config, i18n.global)
+ applyStyleConfig(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/components/about/about.js b/src/components/about/about.js
index f52d5c797..ab1ace320 100644
--- a/src/components/about/about.js
+++ b/src/components/about/about.js
@@ -5,6 +5,7 @@ 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: {
@@ -21,7 +22,7 @@ const About = {
showInstanceSpecificPanel() {
return (
useInstanceStore().instanceIdentity.showInstanceSpecificPanel &&
- !this.$store.getters.mergedConfig.hideISP &&
+ !useSyncConfigStore().mergedConfig.hideISP &&
useInstanceStore().instanceIdentity.instanceSpecificPanelContent
)
},
diff --git a/src/components/account_actions/account_actions.js b/src/components/account_actions/account_actions.js
index 8fce4b5af..38f585675 100644
--- a/src/components/account_actions/account_actions.js
+++ b/src/components/account_actions/account_actions.js
@@ -8,6 +8,7 @@ import ProgressButton from '../progress_button/progress_button.vue'
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'
@@ -89,10 +90,10 @@ const AccountActions = {
},
computed: {
shouldConfirmBlock() {
- return this.$store.getters.mergedConfig.modalOnBlock
+ return useSyncConfigStore().mergedConfig.modalOnBlock
},
shouldConfirmRemoveUserFromFollowers() {
- return this.$store.getters.mergedConfig.modalOnRemoveUserFromFollowers
+ return useSyncConfigStore().mergedConfig.modalOnRemoveUserFromFollowers
},
...mapState(useInstanceCapabilitiesStore, [
'blockExpiration',
diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js
index db5171c80..a67bd475e 100644
--- a/src/components/attachment/attachment.js
+++ b/src/components/attachment/attachment.js
@@ -9,6 +9,7 @@ import VideoAttachment from '../video_attachment/video_attachment.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useMediaViewerStore } from 'src/stores/media_viewer'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@@ -58,8 +59,8 @@ const Attachment = {
localDescription: this.description || this.attachment.description,
nsfwImage:
useInstanceStore().instanceIdentity.nsfwCensorImage || nsfwImage,
- hideNsfwLocal: this.$store.getters.mergedConfig.hideNsfw,
- preloadImage: this.$store.getters.mergedConfig.preloadImage,
+ hideNsfwLocal: useSyncConfigStore().mergedConfig.hideNsfw,
+ preloadImage: useSyncConfigStore().mergedConfig.preloadImage,
loading: false,
img:
fileTypeService.fileType(this.attachment.mimetype) === 'image' &&
@@ -93,7 +94,7 @@ const Attachment = {
return this.size === 'hide'
},
useContainFit() {
- return this.$store.getters.mergedConfig.useContainFit
+ return useSyncConfigStore().mergedConfig.useContainFit
},
placeholderName() {
if (this.attachment.description === '' || !this.attachment.description) {
diff --git a/src/components/confirm_modal/mute_confirm.js b/src/components/confirm_modal/mute_confirm.js
index c486ad7e4..888aa017b 100644
--- a/src/components/confirm_modal/mute_confirm.js
+++ b/src/components/confirm_modal/mute_confirm.js
@@ -1,8 +1,10 @@
-import { mapGetters } from 'vuex'
+import { mapState } from 'pinia'
import Select from 'src/components/select/select.vue'
import ConfirmModal from './confirm_modal.vue'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
+
export default {
props: ['type', 'user', 'status'],
emits: ['hide', 'show', 'muted'],
@@ -43,7 +45,7 @@ export default {
}
}
},
- ...mapGetters(['mergedConfig']),
+ ...mapState(useSyncConfigStore, ['mergedConfig']),
},
methods: {
optionallyPrompt() {
diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js
index cb7cf4782..76dd26352 100644
--- a/src/components/conversation/conversation.js
+++ b/src/components/conversation/conversation.js
@@ -9,6 +9,7 @@ import Status from '../status/status.vue'
import ThreadTree from '../thread_tree/thread_tree.vue'
import { useInterfaceStore } from 'src/stores/interface'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@@ -81,7 +82,7 @@ const conversation = {
// 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
+ const maxDepth = useSyncConfigStore().mergedConfig.maxDepthInThread - 2
return maxDepth >= 1 ? maxDepth : 1
},
streamingEnabled() {
@@ -91,22 +92,22 @@ const conversation = {
)
},
displayStyle() {
- return this.$store.getters.mergedConfig.conversationDisplay
+ return useSyncConfigStore().mergedConfig.conversationDisplay
},
isTreeView() {
return !this.isLinearView
},
treeViewIsSimple() {
- return !this.$store.getters.mergedConfig.conversationTreeAdvanced
+ return !useSyncConfigStore().mergedConfig.conversationTreeAdvanced
},
isLinearView() {
return this.displayStyle === 'linear'
},
shouldFadeAncestors() {
- return this.$store.getters.mergedConfig.conversationTreeFadeAncestors
+ return useSyncConfigStore().mergedConfig.conversationTreeFadeAncestors
},
otherRepliesButtonPosition() {
- return this.$store.getters.mergedConfig.conversationOtherRepliesButton
+ return useSyncConfigStore().mergedConfig.conversationOtherRepliesButton
},
showOtherRepliesButtonBelowStatus() {
return this.otherRepliesButtonPosition === 'below'
diff --git a/src/components/desktop_nav/desktop_nav.js b/src/components/desktop_nav/desktop_nav.js
index 943c66d1e..0871e0bd3 100644
--- a/src/components/desktop_nav/desktop_nav.js
+++ b/src/components/desktop_nav/desktop_nav.js
@@ -5,6 +5,7 @@ import ConfirmModal from '../confirm_modal/confirm_modal.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 {
@@ -96,7 +97,7 @@ export default {
return this.$store.state.users.currentUser
},
shouldConfirmLogout() {
- return this.$store.getters.mergedConfig.modalOnLogout
+ return useSyncConfigStore().mergedConfig.modalOnLogout
},
},
methods: {
diff --git a/src/components/dialog_modal/dialog_modal.js b/src/components/dialog_modal/dialog_modal.js
index 8070d3429..e5c399086 100644
--- a/src/components/dialog_modal/dialog_modal.js
+++ b/src/components/dialog_modal/dialog_modal.js
@@ -1,3 +1,5 @@
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
+
const DialogModal = {
props: {
darkOverlay: {
@@ -13,7 +15,7 @@ const DialogModal = {
},
computed: {
mobileCenter() {
- return this.$store.getters.mergedConfig.modalMobileCenter
+ return useSyncConfigStore().mergedConfig.modalMobileCenter
},
},
}
diff --git a/src/components/draft/draft.js b/src/components/draft/draft.js
index 971a75b10..5ee85dff4 100644
--- a/src/components/draft/draft.js
+++ b/src/components/draft/draft.js
@@ -6,6 +6,8 @@ import Gallery from 'src/components/gallery/gallery.vue'
import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
import StatusContent from 'src/components/status_content/status_content.vue'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
+
import { library } from '@fortawesome/fontawesome-svg-core'
import { faPollH } from '@fortawesome/free-solid-svg-icons'
@@ -57,7 +59,7 @@ const Draft = {
: undefined
},
localCollapseSubjectDefault() {
- return this.$store.getters.mergedConfig.collapseMessageWithSubject
+ return useSyncConfigStore().mergedConfig.collapseMessageWithSubject
},
nsfwClickthrough() {
if (!this.draft.nsfw) {
diff --git a/src/components/draft_closer/draft_closer.js b/src/components/draft_closer/draft_closer.js
index d724ab4ac..5f297bf4c 100644
--- a/src/components/draft_closer/draft_closer.js
+++ b/src/components/draft_closer/draft_closer.js
@@ -1,5 +1,7 @@
import DialogModal from 'src/components/dialog_modal/dialog_modal.vue'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
+
const DraftCloser = {
data() {
return {
@@ -12,10 +14,10 @@ const DraftCloser = {
emits: ['save', 'discard'],
computed: {
action() {
- if (this.$store.getters.mergedConfig.autoSaveDraft) {
+ if (useSyncConfigStore().mergedConfig.autoSaveDraft) {
return 'save'
} else {
- return this.$store.getters.mergedConfig.unsavedPostAction
+ return useSyncConfigStore().mergedConfig.unsavedPostAction
}
},
shouldConfirm() {
diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js
index 24794640e..4917a11fb 100644
--- a/src/components/emoji_input/emoji_input.js
+++ b/src/components/emoji_input/emoji_input.js
@@ -2,13 +2,16 @@ import { take } from 'lodash'
import Popover from 'src/components/popover/popover.vue'
import ScreenReaderNotice from 'src/components/screen_reader_notice/screen_reader_notice.vue'
-import { ensureFinalFallback } from '../../i18n/languages.js'
import Completion from '../../services/completion/completion.js'
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
import genRandomSeed from '../../services/random_seed/random_seed.service.js'
import EmojiPicker from '../emoji_picker/emoji_picker.vue'
import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
+
+import { ensureFinalFallback } from 'src/i18n/languages.js'
+
import { library } from '@fortawesome/fontawesome-svg-core'
import { faSmileBeam } from '@fortawesome/free-regular-svg-icons'
@@ -131,10 +134,10 @@ const EmojiInput = {
},
computed: {
padEmoji() {
- return this.$store.getters.mergedConfig.padEmoji
+ return useSyncConfigStore().mergedConfig.padEmoji
},
defaultCandidateIndex() {
- return this.$store.getters.mergedConfig.autocompleteSelect ? 0 : -1
+ return useSyncConfigStore().mergedConfig.autocompleteSelect ? 0 : -1
},
preText() {
return this.modelValue.slice(0, this.caret)
@@ -163,7 +166,7 @@ const EmojiInput = {
},
languages() {
return ensureFinalFallback(
- this.$store.getters.mergedConfig.interfaceLanguage,
+ useSyncConfigStore().mergedConfig.interfaceLanguage,
)
},
maybeLocalizedEmojiNamesAndKeywords() {
@@ -331,7 +334,6 @@ const EmojiInput = {
if (!this.pickerShown) {
this.scrollIntoView()
this.$refs.picker.showPicker()
- this.$refs.picker.startEmojiLoad()
} else {
this.$refs.picker.hidePicker()
}
diff --git a/src/components/emoji_input/suggestor.js b/src/components/emoji_input/suggestor.js
index c478fea67..c0d8f7ca1 100644
--- a/src/components/emoji_input/suggestor.js
+++ b/src/components/emoji_input/suggestor.js
@@ -1,3 +1,5 @@
+import { useEmojiStore } from 'src/stores/emoji.js'
+
/**
* suggest - generates a suggestor function to be used by emoji-input
* data: object providing source information for specific types of suggestions:
diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js
index 79c0ab47e..1e4594b2c 100644
--- a/src/components/emoji_picker/emoji_picker.js
+++ b/src/components/emoji_picker/emoji_picker.js
@@ -8,6 +8,7 @@ import StillImage from '../still-image/still-image.vue'
import { useEmojiStore } from 'src/stores/emoji.js'
import { useInstanceStore } from 'src/stores/instance.js'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@@ -340,7 +341,7 @@ const EmojiPicker = {
this.$nextTick(() => {
this.updateEmojiSize()
})
- return this.$store.getters.mergedConfig.fontSize
+ return useSyncConfigStore().mergedConfig.fontSize
},
emojiHeight() {
return this.emojiSize
@@ -405,7 +406,7 @@ const EmojiPicker = {
},
languages() {
return ensureFinalFallback(
- this.$store.getters.mergedConfig.interfaceLanguage,
+ useSyncConfigStore().mergedConfig.interfaceLanguage,
)
},
maybeLocalizedEmojiName() {
diff --git a/src/components/follow_button/follow_button.js b/src/components/follow_button/follow_button.js
index eb545b28d..539749bc8 100644
--- a/src/components/follow_button/follow_button.js
+++ b/src/components/follow_button/follow_button.js
@@ -3,6 +3,8 @@ import {
requestUnfollow,
} from '../../services/follow_manipulate/follow_manipulate'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
+
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
export default {
props: ['relationship', 'user', 'labelFollowing', 'buttonClass'],
components: {
@@ -16,7 +18,7 @@ export default {
},
computed: {
shouldConfirmUnfollow() {
- return this.$store.getters.mergedConfig.modalOnUnfollow
+ return useSyncConfigStore().mergedConfig.modalOnUnfollow
},
isPressed() {
return this.inProgress || this.relationship.following
diff --git a/src/components/follow_request_card/follow_request_card.js b/src/components/follow_request_card/follow_request_card.js
index c037ddf42..b7959a2d3 100644
--- a/src/components/follow_request_card/follow_request_card.js
+++ b/src/components/follow_request_card/follow_request_card.js
@@ -2,6 +2,8 @@ import { notificationsFromStore } from '../../services/notification_utils/notifi
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
+
const FollowRequestCard = {
props: ['user'],
components: {
@@ -76,7 +78,7 @@ const FollowRequestCard = {
},
computed: {
mergedConfig() {
- return this.$store.getters.mergedConfig
+ return useSyncConfigStore().mergedConfig
},
shouldConfirmApprove() {
return this.mergedConfig.modalOnApproveFollow
diff --git a/src/components/link-preview/link-preview.js b/src/components/link-preview/link-preview.js
index ac91f916d..a465cc213 100644
--- a/src/components/link-preview/link-preview.js
+++ b/src/components/link-preview/link-preview.js
@@ -1,4 +1,6 @@
-import { mapGetters } from 'vuex'
+import { mapState } from 'pinia'
+
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
const LinkPreview = {
name: 'LinkPreview',
@@ -24,7 +26,7 @@ const LinkPreview = {
hideNsfwConfig() {
return this.mergedConfig.hideNsfw
},
- ...mapGetters(['mergedConfig']),
+ ...mapState(useSyncConfigStore, ['mergedConfig']),
},
created() {
if (this.useImage) {
diff --git a/src/components/media_upload/media_upload.js b/src/components/media_upload/media_upload.js
index ee61fa369..be62142c6 100644
--- a/src/components/media_upload/media_upload.js
+++ b/src/components/media_upload/media_upload.js
@@ -2,6 +2,7 @@ import fileSizeFormatService from '../../services/file_size_format/file_size_for
import statusPosterService from '../../services/status_poster/status_poster.service.js'
import { useInstanceStore } from 'src/stores/instance.js'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faCircleNotch, faUpload } from '@fortawesome/free-solid-svg-icons'
@@ -33,7 +34,7 @@ const mediaUpload = {
}
// Skip if image compression is disabled
- if (!this.$store.getters.mergedConfig.imageCompression) {
+ if (!useSyncConfigStore().mergedConfig.imageCompression) {
return file
}
@@ -78,7 +79,7 @@ const mediaUpload = {
// Convert to WebP if supported and alwaysUseJpeg is false, otherwise JPEG
const type =
- !this.$store.getters.mergedConfig.alwaysUseJpeg && supportsWebP
+ !useSyncConfigStore().mergedConfig.alwaysUseJpeg && supportsWebP
? 'image/webp'
: 'image/jpeg'
const extension = type === 'image/webp' ? '.webp' : '.jpg'
diff --git a/src/components/mentions_line/mentions_line.js b/src/components/mentions_line/mentions_line.js
index e6aa392a0..bd3882866 100644
--- a/src/components/mentions_line/mentions_line.js
+++ b/src/components/mentions_line/mentions_line.js
@@ -1,7 +1,9 @@
-import { mapGetters } from 'vuex'
+import { mapState } from 'pinia'
import MentionLink from 'src/components/mention_link/mention_link.vue'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
+
export const MENTIONS_LIMIT = 5
const MentionsLine = {
@@ -26,7 +28,7 @@ const MentionsLine = {
manyMentions() {
return this.extraMentions.length > 0
},
- ...mapGetters(['mergedConfig']),
+ ...mapState(useSyncConfigStore, ['mergedConfig']),
},
methods: {
toggleShowMore() {
diff --git a/src/components/mobile_nav/mobile_nav.js b/src/components/mobile_nav/mobile_nav.js
index c5b1d66f6..6242344ce 100644
--- a/src/components/mobile_nav/mobile_nav.js
+++ b/src/components/mobile_nav/mobile_nav.js
@@ -13,7 +13,7 @@ import SideDrawer from '../side_drawer/side_drawer.vue'
import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useInstanceStore } from 'src/stores/instance.js'
-import { useServerSideStorageStore } from 'src/stores/serverSideStorage.js'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@@ -75,15 +75,15 @@ const MobileNav = {
return this.$route.name === 'chat'
},
...mapState(useAnnouncementsStore, ['unreadAnnouncementCount']),
- ...mapState(useServerSideStorageStore, {
+ ...mapState(useSyncConfigStore, {
pinnedItems: (store) =>
new Set(store.prefsStorage.collections.pinnedNavItems).has('chats'),
}),
shouldConfirmLogout() {
- return this.$store.getters.mergedConfig.modalOnLogout
+ return useSyncConfigStore().mergedConfig.modalOnLogout
},
closingDrawerMarksAsSeen() {
- return this.$store.getters.mergedConfig.closingDrawerMarksAsSeen
+ return useSyncConfigStore().mergedConfig.closingDrawerMarksAsSeen
},
...mapGetters(['unreadChatCount']),
},
diff --git a/src/components/mobile_post_status_button/mobile_post_status_button.js b/src/components/mobile_post_status_button/mobile_post_status_button.js
index 83103c827..594cd6688 100644
--- a/src/components/mobile_post_status_button/mobile_post_status_button.js
+++ b/src/components/mobile_post_status_button/mobile_post_status_button.js
@@ -1,6 +1,7 @@
import { debounce } from 'lodash'
import { usePostStatusStore } from 'src/stores/post_status.js'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faPen } from '@fortawesome/free-solid-svg-icons'
@@ -45,10 +46,10 @@ const MobilePostStatusButton = {
)
},
isPersistent() {
- return !!this.$store.getters.mergedConfig.alwaysShowNewPostButton
+ return !!useSyncConfigStore().mergedConfig.alwaysShowNewPostButton
},
autohideFloatingPostButton() {
- return !!this.$store.getters.mergedConfig.autohideFloatingPostButton
+ return !!useSyncConfigStore().mergedConfig.autohideFloatingPostButton
},
},
watch: {
diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js
index 8aff31f02..9e5901f24 100644
--- a/src/components/nav_panel/nav_panel.js
+++ b/src/components/nav_panel/nav_panel.js
@@ -12,7 +12,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 { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@@ -84,28 +84,28 @@ const NavPanel = {
this.editMode = !this.editMode
},
toggleCollapse() {
- useServerSideStorageStore().setPreference({
+ useSyncConfigStore().setPreference({
path: 'simple.collapseNav',
value: !this.collapsed,
})
- useServerSideStorageStore().pushServerSideStorage()
+ useSyncConfigStore().pushSyncConfig()
},
isPinned(item) {
return this.pinnedItems.has(item)
},
togglePin(item) {
if (this.isPinned(item)) {
- useServerSideStorageStore().removeCollectionPreference({
+ useSyncConfigStore().removeCollectionPreference({
path: 'collections.pinnedNavItems',
value: item,
})
} else {
- useServerSideStorageStore().addCollectionPreference({
+ useSyncConfigStore().addCollectionPreference({
path: 'collections.pinnedNavItems',
value: item,
})
}
- useServerSideStorageStore().pushServerSideStorage()
+ useSyncConfigStore().pushSyncConfig()
},
},
computed: {
@@ -122,7 +122,7 @@ const NavPanel = {
...mapPiniaState(useInstanceStore, {
privateMode: (store) => store.private,
}),
- ...mapPiniaState(useServerSideStorageStore, {
+ ...mapPiniaState(useSyncConfigStore, {
collapsed: (store) => store.prefsStorage.simple.collapseNav,
pinnedItems: (store) =>
new Set(store.prefsStorage.collections.pinnedNavItems),
diff --git a/src/components/navigation/navigation_entry.js b/src/components/navigation/navigation_entry.js
index 3384534be..7a43000ce 100644
--- a/src/components/navigation/navigation_entry.js
+++ b/src/components/navigation/navigation_entry.js
@@ -5,7 +5,7 @@ import { routeTo } from 'src/components/navigation/navigation.js'
import OptionalRouterLink from 'src/components/optional_router_link/optional_router_link.vue'
import { useAnnouncementsStore } from 'src/stores/announcements.js'
-import { useServerSideStorageStore } from 'src/stores/serverSideStorage.js'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faThumbtack } from '@fortawesome/free-solid-svg-icons'
@@ -23,17 +23,17 @@ const NavigationEntry = {
},
togglePin(value) {
if (this.isPinned(value)) {
- useServerSideStorageStore().removeCollectionPreference({
+ useSyncConfigStore().removeCollectionPreference({
path: 'collections.pinnedNavItems',
value,
})
} else {
- useServerSideStorageStore().addCollectionPreference({
+ useSyncConfigStore().addCollectionPreference({
path: 'collections.pinnedNavItems',
value,
})
}
- useServerSideStorageStore().pushServerSideStorage()
+ useSyncConfigStore().pushSyncConfig()
},
},
computed: {
@@ -47,7 +47,7 @@ const NavigationEntry = {
...mapState({
currentUser: (state) => state.users.currentUser,
}),
- ...mapPiniaState(useServerSideStorageStore, {
+ ...mapPiniaState(useSyncConfigStore, {
pinnedItems: (store) =>
new Set(store.prefsStorage.collections.pinnedNavItems),
}),
diff --git a/src/components/navigation/navigation_pins.js b/src/components/navigation/navigation_pins.js
index 698bf5d59..85f6fafee 100644
--- a/src/components/navigation/navigation_pins.js
+++ b/src/components/navigation/navigation_pins.js
@@ -18,7 +18,7 @@ import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useListsStore } from 'src/stores/lists'
-import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@@ -70,7 +70,7 @@ const NavPanel = {
...mapPiniaState(useBookmarkFoldersStore, {
bookmarks: getBookmarkFolderEntries,
}),
- ...mapPiniaState(useServerSideStorageStore, {
+ ...mapPiniaState(useSyncConfigStore, {
pinnedItems: (store) =>
new Set(store.prefsStorage.collections.pinnedNavItems),
}),
diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js
index 16084dee4..f3f5b76da 100644
--- a/src/components/notification/notification.js
+++ b/src/components/notification/notification.js
@@ -17,6 +17,7 @@ import UserLink from '../user_link/user_link.vue'
import UserPopover from '../user_popover/user_popover.vue'
import { useInstanceStore } from 'src/stores/instance.js'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
@@ -181,7 +182,7 @@ const Notification = {
return highlightClass(this.notification.from_profile)
},
userStyle() {
- const highlight = this.$store.getters.mergedConfig.highlight
+ const highlight = useSyncConfigStore().mergedConfig.highlight
const user = this.notification.from_profile
return highlightStyle(highlight[user.screen_name])
},
@@ -209,7 +210,7 @@ const Notification = {
return isStatusNotification(this.notification.type)
},
mergedConfig() {
- return this.$store.getters.mergedConfig
+ return useSyncConfigStore().mergedConfig
},
shouldConfirmApprove() {
return this.mergedConfig.modalOnApproveFollow
diff --git a/src/components/notifications/notification_filters.vue b/src/components/notifications/notification_filters.vue
index 7be8eb76b..5508e03ac 100644
--- a/src/components/notifications/notification_filters.vue
+++ b/src/components/notifications/notification_filters.vue
@@ -108,6 +108,8 @@
+
diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js
index 4616a4111..4a27c468c 100644
--- a/src/components/timeline/timeline.js
+++ b/src/components/timeline/timeline.js
@@ -9,6 +9,7 @@ import Status from '../status/status.vue'
import TimelineMenu from '../timeline_menu/timeline_menu.vue'
import { useInterfaceStore } from 'src/stores/interface.js'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
import timelineFetcher from 'src/services/timeline_fetcher/timeline_fetcher.service.js'
@@ -125,7 +126,7 @@ const Timeline = {
return this.timeline.visibleStatuses.slice(min, max).map((_) => _.id)
},
virtualScrollingEnabled() {
- return this.$store.getters.mergedConfig.virtualScrolling
+ return useSyncConfigStore().mergedConfig.virtualScrolling
},
...mapState(useInterfaceStore, {
mobileLayout: (store) => store.layoutType === 'mobile',
@@ -313,7 +314,7 @@ const Timeline = {
},
watch: {
newStatusCount(count) {
- if (!this.$store.getters.mergedConfig.streaming) {
+ if (!useSyncConfigStore().mergedConfig.streaming) {
return
}
if (count > 0) {
@@ -323,7 +324,9 @@ const Timeline = {
if (
top < 15 &&
!this.paused &&
- !(this.unfocused && this.$store.getters.mergedConfig.pauseOnUnfocused)
+ !(
+ this.unfocused && useSyncConfigStore().mergedConfig.pauseOnUnfocused
+ )
) {
this.showNewStatuses()
} else {
diff --git a/src/components/update_notification/update_notification.js b/src/components/update_notification/update_notification.js
index a8bc60676..78aaa79e8 100644
--- a/src/components/update_notification/update_notification.js
+++ b/src/components/update_notification/update_notification.js
@@ -1,7 +1,7 @@
import Modal from 'src/components/modal/modal.vue'
import { useInstanceStore } from 'src/stores/instance.js'
-import { useServerSideStorageStore } from 'src/stores/serverSideStorage.js'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
import pleromaTanFoxMask from 'src/assets/pleromatan_apology_fox_mask.png'
import pleromaTanMask from 'src/assets/pleromatan_apology_mask.png'
@@ -41,9 +41,9 @@ const UpdateNotification = {
return (
!useInstanceStore().disableUpdateNotification &&
this.$store.state.users.currentUser &&
- useServerSideStorageStore().flagStorage.updateCounter <
+ useSyncConfigStore().flagStorage.updateCounter <
CURRENT_UPDATE_COUNTER &&
- !useServerSideStorageStore().prefsStorage.simple.dontShowUpdateNotifs
+ !useSyncConfigStore().prefsStorage.simple.dontShowUpdateNotifs
)
},
},
@@ -53,22 +53,22 @@ const UpdateNotification = {
},
neverShowAgain() {
this.toggleShow()
- useServerSideStorageStore().setFlag({
+ useSyncConfigStore().setFlag({
flag: 'updateCounter',
value: CURRENT_UPDATE_COUNTER,
})
- useServerSideStorageStore().setPreference({
+ useSyncConfigStore().setPreference({
path: 'simple.dontShowUpdateNotifs',
value: true,
})
- useServerSideStorageStore().pushServerSideStorage()
+ useSyncConfigStore().pushSyncConfig()
},
dismiss() {
- useServerSideStorageStore().setFlag({
+ useSyncConfigStore().setFlag({
flag: 'updateCounter',
value: CURRENT_UPDATE_COUNTER,
})
- useServerSideStorageStore().pushServerSideStorage()
+ useSyncConfigStore().pushSyncConfig()
},
},
mounted() {
diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js
index 0df27e6cb..b94a9ab9a 100644
--- a/src/components/user_card/user_card.js
+++ b/src/components/user_card/user_card.js
@@ -27,6 +27,7 @@ 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 { useSyncConfigStore } from 'src/stores/sync_config.js'
import { propsToNative } from 'src/services/attributes_helper/attributes_helper.service.js'
import localeService from 'src/services/locale/locale.service.js'
@@ -223,12 +224,12 @@ export default {
userHighlightType: {
get() {
const data =
- this.$store.getters.mergedConfig.highlight[this.user.screen_name]
+ useSyncConfigStore().mergedConfig.highlight[this.user.screen_name]
return (data && data.type) || 'disabled'
},
set(type) {
const data =
- this.$store.getters.mergedConfig.highlight[this.user.screen_name]
+ useSyncConfigStore().mergedConfig.highlight[this.user.screen_name]
if (type !== 'disabled') {
this.$store.dispatch('setHighlight', {
user: this.user.screen_name,
@@ -247,7 +248,7 @@ export default {
userHighlightColor: {
get() {
const data =
- this.$store.getters.mergedConfig.highlight[this.user.screen_name]
+ useSyncConfigStore().mergedConfig.highlight[this.user.screen_name]
return data && data.color
},
set(color) {
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index 66529f59b..111b6b999 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -293,7 +293,7 @@
@@ -505,11 +505,11 @@
class="user-extras"
>
- {{ user.statuses_count }}
diff --git a/src/components/user_popover/user_popover.js b/src/components/user_popover/user_popover.js
index 6d83aaa21..8134f29e1 100644
--- a/src/components/user_popover/user_popover.js
+++ b/src/components/user_popover/user_popover.js
@@ -1,7 +1,10 @@
+import { mapState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import UserCard from '../user_card/user_card.vue'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
+
const UserPopover = {
name: 'UserPopover',
props: ['userId', 'overlayCenters', 'disabled', 'overlayCentersSelector'],
@@ -9,14 +12,11 @@ const UserPopover = {
UserCard,
Popover: defineAsyncComponent(() => import('../popover/popover.vue')),
},
- computed: {
- userPopoverAvatarAction() {
- return this.$store.getters.mergedConfig.userPopoverAvatarAction
- },
- userPopoverOverlay() {
- return this.$store.getters.mergedConfig.userPopoverOverlay
- },
- },
+ computed: mapState(useSyncConfigStore, {
+ userPopoverAvatarAction: (state) =>
+ state.mergedConfig.userPopoverAvatarAction,
+ userPopoverOverlay: (state) => state.mergedConfig.userPopoverOverlay,
+ }),
}
export default UserPopover
diff --git a/src/components/user_timed_filter_modal/user_timed_filter_modal.js b/src/components/user_timed_filter_modal/user_timed_filter_modal.js
index 6c005ab4b..a06c5db59 100644
--- a/src/components/user_timed_filter_modal/user_timed_filter_modal.js
+++ b/src/components/user_timed_filter_modal/user_timed_filter_modal.js
@@ -2,13 +2,15 @@ import Checkbox from 'src/components/checkbox/checkbox.vue'
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
import Select from 'src/components/select/select.vue'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
+
import { durationStrToMs } from 'src/services/date_utils/date_utils.js'
const UserTimedFilterModal = {
data() {
const action = this.isMute
- ? this.$store.getters.mergedConfig.onMuteDefaultAction
- : this.$store.getters.mergedConfig.onBlockDefaultAction
+ ? useSyncConfigStore().mergedConfig.onMuteDefaultAction
+ : useSyncConfigStore().mergedConfig.onBlockDefaultAction
const doAsk = action === 'ask'
const defaultValues = {}
@@ -44,9 +46,9 @@ const UserTimedFilterModal = {
computed: {
shouldConfirm() {
if (this.isMute) {
- return this.$store.getters.mergedConfig.onMuteDefaultAction === 'ask'
+ return useSyncConfigStore().mergedConfig.onMuteDefaultAction === 'ask'
} else {
- return this.$store.getters.mergedConfig.onBlockDefaultAction === 'ask'
+ return useSyncConfigStore().mergedConfig.onBlockDefaultAction === 'ask'
}
},
expiryString() {
diff --git a/src/components/video_attachment/video_attachment.js b/src/components/video_attachment/video_attachment.js
index 92e915da8..1feb1b9fa 100644
--- a/src/components/video_attachment/video_attachment.js
+++ b/src/components/video_attachment/video_attachment.js
@@ -1,3 +1,5 @@
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
+
const VideoAttachment = {
props: ['attachment', 'controls'],
data() {
@@ -9,10 +11,10 @@ const VideoAttachment = {
},
computed: {
loopVideo() {
- if (this.$store.getters.mergedConfig.loopVideoSilentOnly) {
+ if (useSyncConfigStore().mergedConfig.loopVideoSilentOnly) {
return !this.hasAudio
}
- return this.$store.getters.mergedConfig.loopVideo
+ return useSyncConfigStore().mergedConfig.loopVideo
},
},
methods: {
diff --git a/src/components/who_to_follow/who_to_follow.js b/src/components/who_to_follow/who_to_follow.js
index d90d626eb..720b15041 100644
--- a/src/components/who_to_follow/who_to_follow.js
+++ b/src/components/who_to_follow/who_to_follow.js
@@ -1,6 +1,8 @@
import apiService from '../../services/api/api.service.js'
import FollowCard from '../follow_card/follow_card.vue'
+import { useInstanceStore } from 'src/stores/instance.js'
+
const WhoToFollow = {
components: {
FollowCard,
diff --git a/src/lib/language.js b/src/lib/language.js
new file mode 100644
index 000000000..f8904dd07
--- /dev/null
+++ b/src/lib/language.js
@@ -0,0 +1,14 @@
+import { useI18nStore } from 'src/stores/i18n.js'
+
+export const piniaLanguagePlugin = ({ store, options }) => {
+ if (store.$id === 'sync_config') {
+ store.$onAction(({ name, args }) => {
+ if (name === 'setPreference') {
+ const { path, value } = args[0]
+ if (path === 'simple.interfaceLanguage') {
+ useI18nStore().setLanguage(value)
+ }
+ }
+ })
+ }
+}
diff --git a/src/lib/push_notifications_plugin.js b/src/lib/push_notifications_plugin.js
index 9732a82c9..0dfe9588b 100644
--- a/src/lib/push_notifications_plugin.js
+++ b/src/lib/push_notifications_plugin.js
@@ -1,37 +1,96 @@
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
-export default (store) => {
+export const piniaPushNotificationsPlugin = ({ store }) => {
+ if (
+ store.$id !== 'sync_config' &&
+ store.$id !== 'instance' &&
+ store.$id !== 'interface'
+ )
+ return
+
+ store.$onAction(({ name: actionName, args }) => {
+ if (
+ store.$id === 'interface' &&
+ actionName !== 'setNotificationPermission' &&
+ actionName !== 'setLoginStatus'
+ )
+ return
+
+ // Initial state
+ let vapidPublicKey = useInstanceStore().vapidPublicKey
+ let enabled = useSyncConfigStore().mergedConfig.webPushNotifications
+ let permissionGranted =
+ useInterfaceStore().notificationPermission === 'granted'
+ let permissionPresent =
+ useInterfaceStore().notificationPermission !== undefined
+ let user = !!window.vuex.state.users.currentUser
+
+ if (store.$id === 'instance') {
+ if (actionName === 'set' && args[0].path === 'vapidPublicKey') {
+ const { value } = args[0]
+ vapidPublicKey = value
+ }
+ }
+
+ if (!vapidPublicKey || !permissionPresent) {
+ return
+ }
+
+ if (store.$id === 'interface') {
+ if (actionName === 'setNotificationPermission') {
+ permissionGranted = args[0] === 'granted'
+ } else if (actionName === 'setLoginStatus') {
+ user = args[0]
+ } else {
+ return
+ }
+ } else if (store.$id === 'sync_config') {
+ if (
+ actionName === 'setPreference' &&
+ args[0].path === 'simple.webPushNotifications'
+ ) {
+ const { value } = args[0]
+ enabled = value
+ } else {
+ return
+ }
+ }
+
+ if (permissionGranted && enabled && user) {
+ console.log('piniaReg')
+ return window.vuex.dispatch('registerPushNotifications')
+ } else {
+ console.log('piniaUnreg')
+ return window.vuex.dispatch('unregisterPushNotifications')
+ }
+ })
+}
+
+export const vuexPushNotificationsPlugin = (store) => {
store.subscribe((mutation, state) => {
+ // Initial state
const vapidPublicKey = useInstanceStore().vapidPublicKey
- const webPushNotification = state.config.webPushNotifications
- const permission = useInterfaceStore().notificationPermission === 'granted'
+ const enabled = useSyncConfigStore().mergedConfig.webPushNotifications
+ const permissionGranted =
+ useInterfaceStore().notificationPermission === 'granted'
+ const permissionPresent =
+ useInterfaceStore().notificationPermission !== undefined
const user = state.users.currentUser
- const isUserMutation = mutation.type === 'setCurrentUser'
- const isVapidMutation =
- mutation.type === 'setInstanceOption' &&
- mutation.payload.name === 'vapidPublicKey'
- const isPermMutation =
- mutation.type === 'setNotificationPermission' &&
- mutation.payload === 'granted'
- const isUserConfigMutation =
- mutation.type === 'setOption' &&
- mutation.payload.name === 'webPushNotifications'
- const isVisibilityMutation =
- mutation.type === 'setOption' &&
- mutation.payload.name === 'notificationVisibility'
+ if (!permissionPresent || !vapidPublicKey) return
if (
- isUserMutation ||
- isVapidMutation ||
- isPermMutation ||
- isUserConfigMutation ||
- isVisibilityMutation
+ mutation.type === 'setCurrentUser' ||
+ mutation.type === 'clearCurrentUser'
) {
- if (user && vapidPublicKey && permission && webPushNotification) {
+ console.log(!!user, permissionGranted, enabled)
+ if (user && permissionGranted && enabled) {
+ console.log('vuexReg')
return store.dispatch('registerPushNotifications')
- } else if (isUserConfigMutation && !webPushNotification) {
+ } else {
+ console.log('vuexUnreg')
return store.dispatch('unregisterPushNotifications')
}
}
diff --git a/src/lib/style.js b/src/lib/style.js
new file mode 100644
index 000000000..96603925a
--- /dev/null
+++ b/src/lib/style.js
@@ -0,0 +1,29 @@
+import { applyStyleConfig } from 'src/services/style_setter/style_setter.js'
+
+const APPEARANCE_SETTINGS_KEYS = new Set(
+ [
+ 'sidebarColumnWidth',
+ 'contentColumnWidth',
+ 'notifsColumnWidth',
+ 'themeEditorMinWidth',
+ 'textSize',
+ 'navbarSize',
+ 'panelHeaderSize',
+ 'forcedRoundness',
+ 'emojiSize',
+ 'emojiReactionsScale',
+ ].map((x) => 'simple.' + x),
+)
+
+export const piniaStylePlugin = ({ store, options }) => {
+ if (store.$id === 'sync_config') {
+ store.$onAction(({ name, args, after }) => {
+ if (name === 'setPreference') {
+ const { path } = args[0]
+ if (APPEARANCE_SETTINGS_KEYS.has(path)) {
+ after(() => applyStyleConfig(store.mergedConfig))
+ }
+ }
+ })
+ }
+}
diff --git a/src/main.js b/src/main.js
index 91653973d..a4269b4a7 100644
--- a/src/main.js
+++ b/src/main.js
@@ -20,9 +20,15 @@ import messages from './i18n/messages.js'
import createPersistedState, {
piniaPersistPlugin,
} from './lib/persisted_state.js'
-import pushNotifications from './lib/push_notifications_plugin.js'
+import {
+ piniaPushNotificationsPlugin,
+ vuexPushNotificationsPlugin,
+} from './lib/push_notifications_plugin.js'
import vuexModules from './modules/index.js'
+import { piniaLanguagePlugin } from 'src/lib/language.js'
+import { piniaStylePlugin } from 'src/lib/style.js'
+
const currentLocale = (window.navigator.language || 'en').split('-')[0]
const i18n = createI18n({
@@ -35,7 +41,7 @@ const i18n = createI18n({
messages.setLanguage(i18n.global, currentLocale)
const persistedStateOptions = {
- paths: ['serverSideStorage.cache', 'config', 'users.lastLoginName', 'oauth'],
+ paths: ['syncConfig.cache', 'config', 'users.lastLoginName', 'oauth'],
}
;(async () => {
@@ -66,9 +72,12 @@ const persistedStateOptions = {
try {
let storageError
- const plugins = [pushNotifications]
+ const plugins = [vuexPushNotificationsPlugin]
const pinia = createPinia()
pinia.use(piniaPersistPlugin())
+ pinia.use(piniaLanguagePlugin)
+ pinia.use(piniaStylePlugin)
+ pinia.use(piniaPushNotificationsPlugin)
try {
const persistedState = await createPersistedState(persistedStateOptions)
diff --git a/src/modules/config.js b/src/modules/config.js
index 82acf8162..b68d547df 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -3,7 +3,7 @@ import { set } from 'lodash'
import messages from '../i18n/messages'
import localeService from '../services/locale/locale.service.js'
-import { applyConfig } from '../services/style_setter/style_setter.js'
+import { applyStyleConfig } from '../services/style_setter/style_setter.js'
import { defaultState, instanceDefaultConfig } from './default_config_state.js'
import { useEmojiStore } from 'src/stores/emoji.js'
@@ -71,7 +71,7 @@ const config = {
mutations: {
setOptionTemporarily(state, { name, value }) {
set(state, name, value)
- applyConfig(state)
+ applyStyleConfig(state)
},
setOption(state, { name, value }) {
set(state, name, value)
@@ -162,7 +162,7 @@ const config = {
} else {
commit('setOption', { name, value })
if (APPEARANCE_SETTINGS_KEYS.has(name)) {
- applyConfig(state)
+ applyStyleConfig(state)
}
if (name.startsWith('theme3hacks')) {
dispatch('applyTheme', { recompile: true })
diff --git a/src/modules/default_config_state.js b/src/modules/default_config_state.js
index 3e39fb1fc..2f18fe9a5 100644
--- a/src/modules/default_config_state.js
+++ b/src/modules/default_config_state.js
@@ -1,9 +1,10 @@
-const browserLocale = (window.navigator.language || 'en').split('-')[0]
+const browserLocale = (navigator.language || 'en').split('-')[0]
/// Instance config entries provided by static config or pleroma api
/// Put settings here only if it does not make sense for a normal user
/// to override it.
export const staticOrApiConfigDefault = {
+ name: 'PleromaFE',
theme: 'pleroma-dark',
palette: null,
style: null,
diff --git a/src/modules/notifications.js b/src/modules/notifications.js
index cb3d430db..9507177a2 100644
--- a/src/modules/notifications.js
+++ b/src/modules/notifications.js
@@ -10,7 +10,7 @@ import {
} from '../services/notification_utils/notification_utils.js'
import { useReportsStore } from 'src/stores/reports.js'
-import { useServerSideStorageStore } from 'src/stores/serverSideStorage.js'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
const emptyNotifications = () => ({
desktopNotificationSilence: true,
@@ -119,9 +119,7 @@ export const notifications = {
maybeShowNotification(
store,
- Object.values(
- useServerSideStorageStore().prefsStorage.simple.muteFilters,
- ),
+ Object.values(useSyncConfigStore().prefsStorage.simple.muteFilters),
notification,
)
} else if (notification.seen) {
diff --git a/src/modules/users.js b/src/modules/users.js
index b0febcd3a..ea2a0ccb4 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -26,7 +26,7 @@ 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'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { declarations } from 'src/modules/config_declaration'
@@ -682,7 +682,7 @@ const users = {
useInterfaceStore().setLastTimeline('public-timeline')
useInterfaceStore().setLayoutWidth(windowWidth())
useInterfaceStore().setLayoutHeight(windowHeight())
- store.commit('clearServerSideStorage')
+ //useSyncConfigStore().clearSyncConfig()
})
},
loginUser(store, accessToken) {
@@ -702,7 +702,7 @@ const users = {
user.domainMutes = []
commit('setCurrentUser', user)
- useServerSideStorageStore().setServerSideStorage(user)
+ useSyncConfigStore().setSyncConfig(user)
commit('addNewUsers', [user])
useEmojiStore().fetchEmoji()
@@ -723,17 +723,16 @@ const users = {
/*
// Reset wordfilter
Object.keys(
- useServerSideStorageStore().prefsStorage.simple.muteFilters
+ useSyncConfigStore().prefsStorage.simple.muteFilters
).forEach(key => {
- useServerSideStorageStore().unsetPreference({ path: 'simple.muteFilters.' + key, value: null })
+ useSyncConfigStore().unsetPreference({ path: 'simple.muteFilters.' + key, value: null })
})
// Reset flag to 0 to re-run migrations
- useServerSideStorageStore().setFlag({ flag: 'configMigration', value: 0 })
+ useSyncConfigStore().setFlag({ flag: 'configMigration', value: 0 })
/**/
- const { configMigration } =
- useServerSideStorageStore().flagStorage
+ const { configMigration } = useSyncConfigStore().flagStorage
declarations
.filter((x) => {
return (
@@ -744,12 +743,12 @@ const users = {
})
.toSorted((a, b) => a.configMigration - b.configMigration)
.forEach((value) => {
- value.migration(useServerSideStorageStore(), store.rootState)
- useServerSideStorageStore().setFlag({
+ value.migration(useSyncConfigStore(), store.rootState)
+ useSyncConfigStore().setFlag({
flag: 'configMigration',
value: value.migrationNum,
})
- useServerSideStorageStore().pushServerSideStorage()
+ useSyncConfigStore().pushSyncConfig()
})
if (user.token) {
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 90886b4c5..48f8b9e8a 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -318,9 +318,7 @@ const updateProfileJSON = ({ credentials, params }) => {
credentials,
payload: params,
method: 'PATCH',
- })
- .then((data) => data.json())
- .then((data) => parseUser(data))
+ }).then((data) => parseUser(data))
}
// Params needed:
diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js
index 08034d485..495070b0d 100644
--- a/src/services/style_setter/style_setter.js
+++ b/src/services/style_setter/style_setter.js
@@ -255,7 +255,7 @@ const extractStyleConfig = ({
const defaultStyleConfig = extractStyleConfig(defaultState)
-export const applyConfig = (input) => {
+export const applyStyleConfig = (input) => {
const config = extractStyleConfig(input)
if (config === defaultStyleConfig) {
diff --git a/src/services/sw/sw.js b/src/services/sw/sw.js
index 72d78384c..e744e37aa 100644
--- a/src/services/sw/sw.js
+++ b/src/services/sw/sw.js
@@ -41,7 +41,7 @@ function subscribePush(registration, isEnabled, vapidPublicKey) {
function unsubscribePush(registration) {
return registration.pushManager.getSubscription().then((subscription) => {
if (subscription === null) {
- return
+ return Promise.resolve('No subscription')
}
return subscription.unsubscribe()
})
@@ -158,23 +158,23 @@ export function registerPushNotifications(
export function unregisterPushNotifications(token) {
if (isPushSupported()) {
- Promise.all([
- deleteSubscriptionFromBackEnd(token),
- getOrCreateServiceWorker()
- .then((registration) => {
- return unsubscribePush(registration).then((result) => [
- registration,
- result,
- ])
- })
- .then(([, unsubResult]) => {
- if (!unsubResult) {
- console.warn("Push subscription cancellation wasn't successful")
- }
- }),
- ]).catch((e) =>
- console.warn(`Failed to disable Web Push Notifications: ${e.message}`),
- )
+ getOrCreateServiceWorker()
+ .then((registration) => {
+ return unsubscribePush(registration).then((result) => [
+ registration,
+ result,
+ ])
+ })
+ .then(([, unsubResult]) => {
+ if (unsubResult === 'No subscription') return
+ if (!unsubResult) {
+ console.warn("Push subscription cancellation wasn't successful")
+ }
+ return deleteSubscriptionFromBackEnd(token)
+ })
+ .catch((e) => {
+ console.warn(`Failed to disable Web Push Notifications: ${e.message}`)
+ })
}
}
diff --git a/src/stores/i18n.js b/src/stores/i18n.js
index 4e7c7c5d3..a18b1d4d2 100644
--- a/src/stores/i18n.js
+++ b/src/stores/i18n.js
@@ -1,5 +1,14 @@
+import Cookies from 'js-cookie'
import { defineStore } from 'pinia'
+import { useEmojiStore } from 'src/stores/emoji.js'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
+
+import messages from 'src/i18n/messages'
+import localeService from 'src/services/locale/locale.service.js'
+
+const BACKEND_LANGUAGE_COOKIE_NAME = 'userLanguage'
+
export const useI18nStore = defineStore('i18n', {
state: () => ({
i18n: null,
@@ -10,5 +19,16 @@ export const useI18nStore = defineStore('i18n', {
i18n: newI18n.global,
})
},
+ setLanguage(originalValue) {
+ const value =
+ originalValue || useSyncConfigStore().mergedConfig.interfaceLanguage
+
+ messages.setLanguage(this.i18n, value)
+ useEmojiStore().loadUnicodeEmojiData(value)
+ Cookies.set(
+ BACKEND_LANGUAGE_COOKIE_NAME,
+ localeService.internalToBackendLocaleMulti(value),
+ )
+ },
},
})
diff --git a/src/stores/serverSideStorage.js b/src/stores/sync_config.js
similarity index 87%
rename from src/stores/serverSideStorage.js
rename to src/stores/sync_config.js
index 99f5045f7..009ccbce4 100644
--- a/src/stores/serverSideStorage.js
+++ b/src/stores/sync_config.js
@@ -17,7 +17,11 @@ import { toRaw } from 'vue'
import { CURRENT_UPDATE_COUNTER } from 'src/components/update_notification/update_notification.js'
-export const VERSION = 1
+import { useInstanceStore } from 'src/stores/instance'
+
+import { defaultState as configDefaultState } from 'src/modules/default_config_state'
+
+export const VERSION = 2
export const NEW_USER_DATE = new Date('2022-08-04') // date of writing this, basically
export const COMMAND_TRIM_FLAGS = 1000
@@ -41,6 +45,7 @@ export const defaultState = {
dontShowUpdateNotifs: false,
collapseNav: false,
muteFilters: {},
+ ...configDefaultState,
},
collections: {
pinnedStatusActions: ['reply', 'retweet', 'favorite', 'emoji'],
@@ -128,13 +133,13 @@ export const _getRecentData = (cache, live, isTest) => {
live._version === cache._version
) {
console.debug(
- 'Same version/timestamp on both source, source of truth irrelevant',
+ 'Same version/timestamp on both sources, source of truth irrelevant',
)
result.recent = cache
result.stale = live
} else {
console.debug(
- 'Different timestamp, figuring out which one is more recent',
+ 'Different timestamp or version, figuring out which one is more recent',
)
if (live._timestamp < cache._timestamp) {
result.recent = cache
@@ -208,7 +213,7 @@ const _mergeJournal = (...journals) => {
// side effect
journal.sort((a, b) => (a.timestamp > b.timestamp ? 1 : -1))
- if (path.startsWith('collections')) {
+ if (path.startsWith('collections') || path.startsWith('objectCollection')) {
const lastRemoveIndex = findLastIndex(
journal,
({ operation }) => operation === 'removeFromCollection',
@@ -229,6 +234,7 @@ const _mergeJournal = (...journals) => {
return false
}
if (a.operation === 'addToCollection') {
+ // TODO check how objectCollections behaves here
return a.args[0] === b.args[0]
}
return false
@@ -368,21 +374,21 @@ export const _resetFlags = (
return result
}
-export const _doMigrations = (cache) => {
- if (!cache) return cache
+export const _doMigrations = (cache, live) => {
+ const data = cache ?? live
- if (cache._version < VERSION) {
+ if (data._version < VERSION) {
console.debug(
- 'Local cached data has older version, seeing if there any migrations that can be applied',
+ 'Data has older version, seeing if there any migrations that can be applied',
)
// no migrations right now since we only have one version
console.debug('No migrations found')
}
- if (cache._version > VERSION) {
+ if (data._version > VERSION) {
console.debug(
- 'Local cached data has newer version, seeing if there any reverse migrations that can be applied',
+ 'Data has newer version, seeing if there any reverse migrations that can be applied',
)
// no reverse migrations right now but we leave a possibility of loading a hotpatch if need be
@@ -391,9 +397,9 @@ export const _doMigrations = (cache) => {
console.debug('Found hotpatch migration, applying')
return window._PLEROMA_HOTPATCH.reverseMigrations.call(
{},
- 'serverSideStorage',
- { from: cache._version, to: VERSION },
- cache,
+ 'syncConfigStore',
+ { from: data._version, to: VERSION },
+ data,
)
}
}
@@ -402,7 +408,7 @@ export const _doMigrations = (cache) => {
return cache
}
-export const useServerSideStorageStore = defineStore('serverSideStorage', {
+export const useSyncConfigStore = defineStore('sync_config', {
state() {
return cloneDeep(defaultState)
},
@@ -510,19 +516,40 @@ export const useServerSideStorageStore = defineStore('serverSideStorage', {
`tried to edit internal (starts with _) field '${path}', ignoring.`,
)
}
- const collection = new Set(get(this.prefsStorage, path))
- collection.delete(value)
- set(this.prefsStorage, path, [...collection])
- this.prefsStorage._journal = [
- ...this.prefsStorage._journal,
- {
- operation: 'removeFromCollection',
- path,
- args: [value],
- timestamp: Date.now(),
- },
- ]
- this.dirty = true
+
+ const { _key } = value
+ if (path.startsWith('collection')) {
+ const collection = new Set(get(this.prefsStorage, path))
+ collection.delete(value)
+ set(this.prefsStorage, path, [...collection])
+
+ this.prefsStorage._journal = [
+ ...this.prefsStorage._journal,
+ {
+ operation: 'removeFromCollection',
+ path,
+ args: [value],
+ timestamp: Date.now(),
+ },
+ ]
+ this.dirty = true
+ } else if (path.startsWith('objectCollection')) {
+ const collection = new Set(get(this.prefsStorage, path + '.index'))
+ collection.delete(_key)
+ set(this.prefsStorage, path + '.index', [...collection])
+ const data = get(this.prefsStorage, path + '.data')
+ delete data[_key]
+
+ this.prefsStorage._journal = [
+ ...this.prefsStorage._journal,
+ {
+ operation: 'removeFromCollection',
+ path,
+ args: [{ _key }],
+ timestamp: Date.now(),
+ },
+ ]
+ }
},
reorderCollectionPreference({ path, value, movement }) {
if (path.startsWith('_')) {
@@ -554,24 +581,23 @@ export const useServerSideStorageStore = defineStore('serverSideStorage', {
username,
)
},
- clearServerSideStorage() {
+ clearSyncConfig() {
const blankState = { ...cloneDeep(defaultState) }
Object.keys(this).forEach((k) => {
this[k] = blankState[k]
})
},
- setServerSideStorage(userData) {
+ setSyncConfig(userData) {
const live = userData.storage
this.raw = live
let cache = this.cache
- if (cache && cache._user !== userData.fqn) {
+ if (cache?._user !== userData.fqn) {
console.warn(
'Cache belongs to another user! reinitializing local cache!',
)
cache = null
}
-
- cache = _doMigrations(cache)
+ console.log(cache, live)
let { recent, stale, needUpload } = _getRecentData(cache, live)
@@ -589,6 +615,9 @@ export const useServerSideStorageStore = defineStore('serverSideStorage', {
})
}
+ recent = recent && _doMigrations(recent)
+ stale = stale && _doMigrations(stale)
+
if (!needUpload && recent && stale) {
console.debug('Checking if data needs merging...')
// discarding timestamps and versions
@@ -627,7 +656,7 @@ export const useServerSideStorageStore = defineStore('serverSideStorage', {
this.flagStorage = this.cache.flagStorage
this.prefsStorage = this.cache.prefsStorage
},
- pushServerSideStorage({ force = false } = {}) {
+ pushSyncConfig({ force = false } = {}) {
const needPush = this.dirty || force
if (!needPush) return
this.updateCache({ username: window.vuex.state.users.currentUser.fqn })
@@ -635,9 +664,26 @@ export const useServerSideStorageStore = defineStore('serverSideStorage', {
window.vuex.state.api.backendInteractor
.updateProfileJSON({ params })
.then((user) => {
- this.setServerSideStorage(user)
+ this.setSyncConfig(user)
this.dirty = false
})
},
},
+ getters: {
+ mergedConfig: (state) => {
+ const instancePrefs = useInstanceStore().prefsStorage
+ const result = Object.fromEntries(
+ Object.entries(state.prefsStorage.simple).map(([k, v]) => [
+ k,
+ v ?? instancePrefs[k],
+ ]),
+ )
+ return result
+ },
+ },
+ persist: {
+ afterLoad(state) {
+ return state
+ },
+ },
})
diff --git a/test/unit/specs/boot/routes.spec.js b/test/unit/specs/boot/routes.spec.js
index 8795ea04e..f4be28a65 100644
--- a/test/unit/specs/boot/routes.spec.js
+++ b/test/unit/specs/boot/routes.spec.js
@@ -1,5 +1,7 @@
import { createTestingPinia } from '@pinia/testing'
- createTestingPinia()
+
+createTestingPinia()
+
import { createMemoryHistory, createRouter } from 'vue-router'
import { createStore } from 'vuex'
diff --git a/test/unit/specs/components/draft.spec.js b/test/unit/specs/components/draft.spec.js
index eb35cb58f..7bc053f52 100644
--- a/test/unit/specs/components/draft.spec.js
+++ b/test/unit/specs/components/draft.spec.js
@@ -1,6 +1,6 @@
+import { createTestingPinia } from '@pinia/testing'
import { flushPromises, mount } from '@vue/test-utils'
import { nextTick } from 'vue'
-import { createTestingPinia } from '@pinia/testing'
import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
import { $t, mountOpts, waitForEvent } from '../../../fixtures/setup_test'
diff --git a/test/unit/specs/components/emoji_input.spec.js b/test/unit/specs/components/emoji_input.spec.js
index 83ffd13d2..62f90caa4 100644
--- a/test/unit/specs/components/emoji_input.spec.js
+++ b/test/unit/specs/components/emoji_input.spec.js
@@ -1,23 +1,19 @@
+import { createTestingPinia } from '@pinia/testing'
import { shallowMount } from '@vue/test-utils'
import vClickOutside from 'click-outside-vue3'
import { h } from 'vue'
-import { createTestingPinia } from '@pinia/testing'
- createTestingPinia()
+
+createTestingPinia()
import EmojiInput from 'src/components/emoji_input/emoji_input.vue'
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
+
const generateInput = (value, padEmoji = true) => {
const wrapper = shallowMount(EmojiInput, {
global: {
renderStubDefaultSlot: true,
mocks: {
- $store: {
- getters: {
- mergedConfig: {
- padEmoji,
- },
- },
- },
$t: (msg) => msg,
},
stubs: {
@@ -48,6 +44,12 @@ const generateInput = (value, padEmoji = true) => {
}
describe('EmojiInput', () => {
+ beforeEach(() => {
+ const store = useSyncConfigStore(createTestingPinia())
+ store.mergedConfig = {
+ padEmoji: true,
+ }
+ })
describe('insertion mechanism', () => {
it('inserts string at the end with trailing space', () => {
const initialString = 'Testing'
@@ -111,6 +113,10 @@ describe('EmojiInput', () => {
it('inserts string without any padding if padEmoji setting is set to false', () => {
const initialString = 'Eat some spam!'
const wrapper = generateInput(initialString, false)
+ const store = useSyncConfigStore(createTestingPinia())
+ store.mergedConfig = {
+ padEmoji: false,
+ }
const input = wrapper.find('input')
input.setValue(initialString)
wrapper.setData({ caret: initialString.length, keepOpen: false })
@@ -146,6 +152,10 @@ describe('EmojiInput', () => {
it('correctly sets caret after insertion if padEmoji setting is set to false', async () => {
const initialString = '1234'
const wrapper = generateInput(initialString, false)
+ const store = useSyncConfigStore(createTestingPinia())
+ store.mergedConfig = {
+ padEmoji: false,
+ }
const input = wrapper.find('input')
input.setValue(initialString)
wrapper.setData({ caret: initialString.length })
diff --git a/test/unit/specs/modules/statuses.spec.js b/test/unit/specs/modules/statuses.spec.js
index 3d1027ad4..1315724da 100644
--- a/test/unit/specs/modules/statuses.spec.js
+++ b/test/unit/specs/modules/statuses.spec.js
@@ -1,10 +1,12 @@
+import { createTestingPinia } from '@pinia/testing'
+
import {
defaultState,
mutations,
prepareStatus,
} from '../../../../src/modules/statuses.js'
-import { createTestingPinia } from '@pinia/testing'
- createTestingPinia()
+
+createTestingPinia()
const makeMockStatus = ({ id, text, type = 'status' }) => {
return {
diff --git a/test/unit/specs/services/notification_utils/notification_utils.spec.js b/test/unit/specs/services/notification_utils/notification_utils.spec.js
index baafd8961..2bfd3c4a1 100644
--- a/test/unit/specs/services/notification_utils/notification_utils.spec.js
+++ b/test/unit/specs/services/notification_utils/notification_utils.spec.js
@@ -1,6 +1,21 @@
+import { createTestingPinia } from '@pinia/testing'
+
+import { useSyncConfigStore } from 'src/stores/sync_config.js'
+
import * as NotificationUtils from 'src/services/notification_utils/notification_utils.js'
describe('NotificationUtils', () => {
+ beforeEach(() => {
+ const store = useSyncConfigStore(createTestingPinia())
+ store.mergedConfig = {
+ notificationVisibility: {
+ likes: true,
+ repeats: true,
+ mentions: false,
+ },
+ }
+ })
+
describe('filteredNotificationsFromStore', () => {
it('should return sorted notifications with configured types', () => {
const store = {
@@ -26,13 +41,7 @@ describe('NotificationUtils', () => {
},
},
getters: {
- mergedConfig: {
- notificationVisibility: {
- likes: true,
- repeats: true,
- mentions: false,
- },
- },
+ mergedConfig: {},
},
}
const expected = [
diff --git a/test/unit/specs/stores/oauth.spec.js b/test/unit/specs/stores/oauth.spec.js
index 977b15432..4664bba02 100644
--- a/test/unit/specs/stores/oauth.spec.js
+++ b/test/unit/specs/stores/oauth.spec.js
@@ -1,6 +1,6 @@
-import { HttpResponse, http } from 'msw'
-import { setActivePinia, createPinia } from 'pinia'
import { createTestingPinia } from '@pinia/testing'
+import { HttpResponse, http } from 'msw'
+import { createPinia, setActivePinia } from 'pinia'
import {
authApis,
@@ -8,8 +8,8 @@ import {
testServer,
} from '/test/fixtures/mock_api.js'
-import { useOAuthStore } from 'src/stores/oauth.js'
import { useInstanceStore } from 'src/stores/instance.js'
+import { useOAuthStore } from 'src/stores/oauth.js'
const test = injectMswToTest(authApis)
@@ -61,7 +61,6 @@ describe('oauth store', () => {
}),
)
-
const store = useOAuthStore()
store.clientId = 'another-id'
store.clientSecret = 'another-secret'
@@ -183,7 +182,9 @@ describe('oauth store', () => {
await expect(store.ensureAppToken()).rejects.toThrowError('Throttled')
})
- test('it should throw if we cannot obtain app token', async ({ worker }) => {
+ test('it should throw if we cannot obtain app token', async ({
+ worker,
+ }) => {
worker.use(
http.post(`${testServer}/oauth/token`, () => {
return HttpResponse.text('Throttled', { status: 429 })
diff --git a/test/unit/specs/modules/serverSideStorage.spec.js b/test/unit/specs/stores/sync_config.spec.js
similarity index 87%
rename from test/unit/specs/modules/serverSideStorage.spec.js
rename to test/unit/specs/stores/sync_config.spec.js
index bd2028ea3..abcddbeb1 100644
--- a/test/unit/specs/modules/serverSideStorage.spec.js
+++ b/test/unit/specs/stores/sync_config.spec.js
@@ -12,25 +12,25 @@ import {
COMMAND_TRIM_FLAGS_AND_RESET,
defaultState,
newUserFlags,
- useServerSideStorageStore,
+ useSyncConfigStore,
VERSION,
-} from 'src/stores/serverSideStorage.js'
+} from 'src/stores/sync_config.js'
-describe('The serverSideStorage module', () => {
+describe('The SyncConfig module', () => {
beforeEach(() => {
setActivePinia(createPinia())
})
describe('mutations', () => {
- describe('setServerSideStorage', () => {
+ describe('setSyncConfig', () => {
const user = {
created_at: new Date('1999-02-09'),
storage: {},
}
it('should initialize storage if none present', () => {
- const store = useServerSideStorageStore()
- store.setServerSideStorage(store, user)
+ const store = useSyncConfigStore()
+ store.setSyncConfig({ ...user })
expect(store.cache._version).to.eql(VERSION)
expect(store.cache._timestamp).to.be.a('number')
expect(store.cache.flagStorage).to.eql(defaultState.flagStorage)
@@ -38,8 +38,8 @@ describe('The serverSideStorage module', () => {
})
it('should initialize storage with proper flags for new users if none present', () => {
- const store = useServerSideStorageStore()
- store.setServerSideStorage({ ...user, created_at: new Date() })
+ const store = useSyncConfigStore()
+ store.setSyncConfig({ ...user, created_at: new Date() })
expect(store.cache._version).to.eql(VERSION)
expect(store.cache._timestamp).to.be.a('number')
expect(store.cache.flagStorage).to.eql(newUserFlags)
@@ -47,14 +47,14 @@ describe('The serverSideStorage module', () => {
})
it('should merge flags even if remote timestamp is older', () => {
- const store = useServerSideStorageStore()
+ const store = useSyncConfigStore()
store.cache = {
_timestamp: Date.now(),
_version: VERSION,
...cloneDeep(defaultState),
}
- store.setServerSideStorage({
+ store.setSyncConfig({
...user,
storage: {
_timestamp: 123,
@@ -76,10 +76,10 @@ describe('The serverSideStorage module', () => {
})
it('should reset local timestamp to remote if contents are the same', () => {
- const store = useServerSideStorageStore()
+ const store = useSyncConfigStore()
store.cache = null
- store.setServerSideStorage({
+ store.setSyncConfig({
...user,
storage: {
_timestamp: 123,
@@ -95,9 +95,9 @@ describe('The serverSideStorage module', () => {
expect(store.cache.flagStorage.updateCounter).to.eql(999)
})
- it('should remote version if local missing', () => {
- const store = useServerSideStorageStore()
- store.setServerSideStorage(store, user)
+ it('should use remote version if local missing', () => {
+ const store = useSyncConfigStore()
+ store.setSyncConfig(store, user)
expect(store.cache._version).to.eql(VERSION)
expect(store.cache._timestamp).to.be.a('number')
expect(store.cache.flagStorage).to.eql(defaultState.flagStorage)
@@ -105,7 +105,7 @@ describe('The serverSideStorage module', () => {
})
describe('setPreference', () => {
it('should set preference and update journal log accordingly', () => {
- const store = useServerSideStorageStore()
+ const store = useSyncConfigStore()
store.setPreference({ path: 'simple.testing', value: 1 })
expect(store.prefsStorage.simple.testing).to.eql(1)
expect(store.prefsStorage._journal.length).to.eql(1)
@@ -119,18 +119,34 @@ describe('The serverSideStorage module', () => {
})
it('should keep journal to a minimum', () => {
- const store = useServerSideStorageStore()
+ const store = useSyncConfigStore()
store.setPreference({ path: 'simple.testing', value: 1 })
store.setPreference({ path: 'simple.testing', value: 2 })
store.addCollectionPreference({ path: 'collections.testing', value: 2 })
+ store.addCollectionPreference({
+ path: 'objectCollections.testing',
+ value: { _key: 'a', foo: 1 },
+ })
+ expect(store.prefsStorage.objectCollections.testing).to.eql({
+ data: { a: { _key: 'a', foo: 1 } },
+ index: ['a'],
+ })
store.removeCollectionPreference({
path: 'collections.testing',
value: 2,
})
+ store.removeCollectionPreference({
+ path: 'objectCollections.testing',
+ value: { _key: 'a' },
+ })
store.updateCache({ username: 'test' })
expect(store.prefsStorage.simple.testing).to.eql(2)
expect(store.prefsStorage.collections.testing).to.eql([])
- expect(store.prefsStorage._journal.length).to.eql(2)
+ expect(store.prefsStorage.objectCollections.testing).to.eql({
+ data: {},
+ index: [],
+ })
+ expect(store.prefsStorage._journal.length).to.eql(3)
expect(store.prefsStorage._journal[0]).to.eql({
path: 'simple.testing',
operation: 'set',
@@ -145,22 +161,41 @@ describe('The serverSideStorage module', () => {
// should have A timestamp, we don't really care what it is
timestamp: store.prefsStorage._journal[1].timestamp,
})
+ expect(store.prefsStorage._journal[2]).to.eql({
+ path: 'objectCollections.testing',
+ operation: 'removeFromCollection',
+ args: [{ _key: 'a' }],
+ // should have A timestamp, we don't really care what it is
+ timestamp: store.prefsStorage._journal[2].timestamp,
+ })
})
it('should remove duplicate entries from journal', () => {
- const store = useServerSideStorageStore()
+ const store = useSyncConfigStore()
store.setPreference({ path: 'simple.testing', value: 1 })
store.setPreference({ path: 'simple.testing', value: 1 })
store.addCollectionPreference({ path: 'collections.testing', value: 2 })
store.addCollectionPreference({ path: 'collections.testing', value: 2 })
+ store.addCollectionPreference({
+ path: 'objectCollections.testing',
+ value: { _key: 'a', foo: 1 },
+ })
+ store.addCollectionPreference({
+ path: 'objectCollections.testing',
+ value: { _key: 'a', foo: 1 },
+ })
store.updateCache({ username: 'test' })
expect(store.prefsStorage.simple.testing).to.eql(1)
expect(store.prefsStorage.collections.testing).to.eql([2])
- expect(store.prefsStorage._journal.length).to.eql(2)
+ expect(store.prefsStorage.objectCollections.testing).to.eql({
+ data: { a: { _key: 'a', foo: 1 } },
+ index: ['a'],
+ })
+ expect(store.prefsStorage._journal.length).to.eql(4)
})
it('should remove depth = 3 set/unset entries from journal', () => {
- const store = useServerSideStorageStore()
+ const store = useSyncConfigStore()
store.setPreference({ path: 'simple.object.foo', value: 1 })
store.unsetPreference({ path: 'simple.object.foo' })
store.updateCache(store, { username: 'test' })
@@ -169,7 +204,7 @@ describe('The serverSideStorage module', () => {
})
it('should not allow unsetting depth <= 2', () => {
- const store = useServerSideStorageStore()
+ const store = useSyncConfigStore()
store.setPreference({ path: 'simple.object.foo', value: 1 })
expect(() => store.unsetPreference({ path: 'simple' })).to.throw()
expect(() =>
@@ -178,7 +213,7 @@ describe('The serverSideStorage module', () => {
})
it('should not allow (un)setting depth > 3', () => {
- const store = useServerSideStorageStore()
+ const store = useSyncConfigStore()
store.setPreference({ path: 'simple.object', value: {} })
expect(() =>
store.setPreference({ path: 'simple.object.lv3', value: 1 }),