Merge branch 'migrate/vuex-to-pinia' into 'develop'
Migrate from vuex to pinia Closes #1202 See merge request pleroma/pleroma-fe!1807
This commit is contained in:
commit
1f56401a8e
100 changed files with 1323 additions and 1354 deletions
1
changelog.d/pinia.change
Normal file
1
changelog.d/pinia.change
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Partially migrated from vuex to pinia
|
|
@ -38,6 +38,7 @@
|
||||||
"pako": "^2.1.0",
|
"pako": "^2.1.0",
|
||||||
"parse-link-header": "2.0.0",
|
"parse-link-header": "2.0.0",
|
||||||
"phoenix": "1.7.19",
|
"phoenix": "1.7.19",
|
||||||
|
"pinia": "^2.0.33",
|
||||||
"punycode.js": "2.3.1",
|
"punycode.js": "2.3.1",
|
||||||
"qrcode": "1.5.4",
|
"qrcode": "1.5.4",
|
||||||
"querystring-es3": "0.2.1",
|
"querystring-es3": "0.2.1",
|
||||||
|
|
14
src/App.js
14
src/App.js
|
@ -17,6 +17,8 @@ import GlobalNoticeList from './components/global_notice_list/global_notice_list
|
||||||
import { windowWidth, windowHeight } from './services/window_utils/window_utils'
|
import { windowWidth, windowHeight } from './services/window_utils/window_utils'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import { defineAsyncComponent } from 'vue'
|
import { defineAsyncComponent } from 'vue'
|
||||||
|
import { useShoutStore } from './stores/shout'
|
||||||
|
import { useInterfaceStore } from './stores/interface'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'app',
|
name: 'app',
|
||||||
|
@ -60,7 +62,7 @@ export default {
|
||||||
document.getElementById('modal').classList = ['-' + this.layoutType]
|
document.getElementById('modal').classList = ['-' + this.layoutType]
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
if (this.$store.state.interface.themeApplied) {
|
if (useInterfaceStore().themeApplied) {
|
||||||
this.removeSplash()
|
this.removeSplash()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -69,7 +71,7 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
themeApplied () {
|
themeApplied () {
|
||||||
return this.$store.state.interface.themeApplied
|
return useInterfaceStore().themeApplied
|
||||||
},
|
},
|
||||||
layoutModalClass () {
|
layoutModalClass () {
|
||||||
return '-' + this.layoutType
|
return '-' + this.layoutType
|
||||||
|
@ -106,7 +108,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
shout () { return this.$store.state.shout.joined },
|
shout () { return useShoutStore().joined },
|
||||||
suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled },
|
suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled },
|
||||||
showInstanceSpecificPanel () {
|
showInstanceSpecificPanel () {
|
||||||
return this.$store.state.instance.showInstanceSpecificPanel &&
|
return this.$store.state.instance.showInstanceSpecificPanel &&
|
||||||
|
@ -132,7 +134,7 @@ export default {
|
||||||
hideShoutbox () {
|
hideShoutbox () {
|
||||||
return this.$store.getters.mergedConfig.hideShoutbox
|
return this.$store.getters.mergedConfig.hideShoutbox
|
||||||
},
|
},
|
||||||
layoutType () { return this.$store.state.interface.layoutType },
|
layoutType () { return useInterfaceStore().layoutType },
|
||||||
privateMode () { return this.$store.state.instance.private },
|
privateMode () { return this.$store.state.instance.private },
|
||||||
reverseLayout () {
|
reverseLayout () {
|
||||||
const { thirdColumnMode, sidebarRight: reverseSetting } = this.$store.getters.mergedConfig
|
const { thirdColumnMode, sidebarRight: reverseSetting } = this.$store.getters.mergedConfig
|
||||||
|
@ -148,8 +150,8 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateMobileState () {
|
updateMobileState () {
|
||||||
this.$store.dispatch('setLayoutWidth', windowWidth())
|
useInterfaceStore().setLayoutWidth(windowWidth())
|
||||||
this.$store.dispatch('setLayoutHeight', windowHeight())
|
useInterfaceStore().setLayoutHeight(windowHeight())
|
||||||
},
|
},
|
||||||
removeSplash () {
|
removeSplash () {
|
||||||
document.querySelector('#status').textContent = this.$t('splash.fun_' + Math.ceil(Math.random() * 4))
|
document.querySelector('#status').textContent = this.$t('splash.fun_' + Math.ceil(Math.random() * 4))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-show="$store.state.interface.themeApplied"
|
v-show="themeApplied"
|
||||||
id="app-loaded"
|
id="app-loaded"
|
||||||
:style="bgStyle"
|
:style="bgStyle"
|
||||||
>
|
>
|
||||||
|
|
|
@ -17,6 +17,10 @@ import { applyConfig } from '../services/style_setter/style_setter.js'
|
||||||
import FaviconService from '../services/favicon_service/favicon_service.js'
|
import FaviconService from '../services/favicon_service/favicon_service.js'
|
||||||
import { initServiceWorker, updateFocus } from '../services/sw/sw.js'
|
import { initServiceWorker, updateFocus } from '../services/sw/sw.js'
|
||||||
|
|
||||||
|
import { useI18nStore } from 'src/stores/i18n'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
import { useAnnouncementsStore } from 'src/stores/announcements'
|
||||||
|
|
||||||
let staticInitialResults = null
|
let staticInitialResults = null
|
||||||
|
|
||||||
const parsedInitialResults = () => {
|
const parsedInitialResults = () => {
|
||||||
|
@ -333,9 +337,16 @@ const checkOAuthToken = async ({ store }) => {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
const afterStoreSetup = async ({ store, i18n }) => {
|
const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
|
||||||
store.dispatch('setLayoutWidth', windowWidth())
|
const app = createApp(App)
|
||||||
store.dispatch('setLayoutHeight', windowHeight())
|
app.use(pinia)
|
||||||
|
|
||||||
|
if (storageError) {
|
||||||
|
useInterfaceStore().pushGlobalNotice({ messageKey: 'errors.storage_unavailable', level: 'error' })
|
||||||
|
}
|
||||||
|
|
||||||
|
useInterfaceStore().setLayoutWidth(windowWidth())
|
||||||
|
useInterfaceStore().setLayoutHeight(windowHeight())
|
||||||
|
|
||||||
FaviconService.initFaviconService()
|
FaviconService.initFaviconService()
|
||||||
initServiceWorker(store)
|
initServiceWorker(store)
|
||||||
|
@ -348,7 +359,7 @@ const afterStoreSetup = async ({ store, i18n }) => {
|
||||||
|
|
||||||
await setConfig({ store })
|
await setConfig({ store })
|
||||||
try {
|
try {
|
||||||
await store.dispatch('applyTheme').catch((e) => { console.error('Error setting theme', e) })
|
await useInterfaceStore().applyTheme().catch((e) => { console.error('Error setting theme', e) })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
window.splashError(e)
|
window.splashError(e)
|
||||||
return Promise.reject(e)
|
return Promise.reject(e)
|
||||||
|
@ -369,7 +380,7 @@ const afterStoreSetup = async ({ store, i18n }) => {
|
||||||
|
|
||||||
// Start fetching things that don't need to block the UI
|
// Start fetching things that don't need to block the UI
|
||||||
store.dispatch('fetchMutes')
|
store.dispatch('fetchMutes')
|
||||||
store.dispatch('startFetchingAnnouncements')
|
useAnnouncementsStore().startFetchingAnnouncements()
|
||||||
getTOS({ store })
|
getTOS({ store })
|
||||||
getStickers({ store })
|
getStickers({ store })
|
||||||
|
|
||||||
|
@ -384,7 +395,7 @@ const afterStoreSetup = async ({ store, i18n }) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const app = createApp(App)
|
useI18nStore().setI18n(i18n)
|
||||||
|
|
||||||
app.use(router)
|
app.use(router)
|
||||||
app.use(store)
|
app.use(store)
|
||||||
|
@ -392,9 +403,9 @@ const afterStoreSetup = async ({ store, i18n }) => {
|
||||||
|
|
||||||
// Little thing to get out of invalid theme state
|
// Little thing to get out of invalid theme state
|
||||||
window.resetThemes = () => {
|
window.resetThemes = () => {
|
||||||
store.dispatch('resetThemeV3')
|
useInterfaceStore().resetThemeV3()
|
||||||
store.dispatch('resetThemeV3Palette')
|
useInterfaceStore().resetThemeV3Palette()
|
||||||
store.dispatch('resetThemeV2')
|
useInterfaceStore().resetThemeV2()
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use(vClickOutside)
|
app.use(vClickOutside)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faEllipsisV
|
faEllipsisV
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useReportsStore } from 'src/stores/reports'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faEllipsisV
|
faEllipsisV
|
||||||
|
@ -73,7 +74,7 @@ const AccountActions = {
|
||||||
this.hideConfirmRemoveUserFromFollowers()
|
this.hideConfirmRemoveUserFromFollowers()
|
||||||
},
|
},
|
||||||
reportUser () {
|
reportUser () {
|
||||||
this.$store.dispatch('openUserReportingModal', { userId: this.user.id })
|
useReportsStore().openUserReportingModal({ userId: this.user.id })
|
||||||
},
|
},
|
||||||
openChat () {
|
openChat () {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { mapState } from 'vuex'
|
||||||
import AnnouncementEditor from '../announcement_editor/announcement_editor.vue'
|
import AnnouncementEditor from '../announcement_editor/announcement_editor.vue'
|
||||||
import RichContent from '../rich_content/rich_content.jsx'
|
import RichContent from '../rich_content/rich_content.jsx'
|
||||||
import localeService from '../../services/locale/locale.service.js'
|
import localeService from '../../services/locale/locale.service.js'
|
||||||
|
import { useAnnouncementsStore } from 'src/stores/announcements'
|
||||||
|
|
||||||
const Announcement = {
|
const Announcement = {
|
||||||
components: {
|
components: {
|
||||||
|
@ -67,11 +68,11 @@ const Announcement = {
|
||||||
methods: {
|
methods: {
|
||||||
markAsRead () {
|
markAsRead () {
|
||||||
if (!this.isRead) {
|
if (!this.isRead) {
|
||||||
return this.$store.dispatch('markAnnouncementAsRead', this.announcement.id)
|
return useAnnouncementsStore().markAnnouncementAsRead(this.announcement.id)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deleteAnnouncement () {
|
deleteAnnouncement () {
|
||||||
return this.$store.dispatch('deleteAnnouncement', this.announcement.id)
|
return useAnnouncementsStore().deleteAnnouncement(this.announcement.id)
|
||||||
},
|
},
|
||||||
formatTimeOrDate (time, locale) {
|
formatTimeOrDate (time, locale) {
|
||||||
const d = new Date(time)
|
const d = new Date(time)
|
||||||
|
@ -85,7 +86,7 @@ const Announcement = {
|
||||||
this.editing = true
|
this.editing = true
|
||||||
},
|
},
|
||||||
submitEdit () {
|
submitEdit () {
|
||||||
this.$store.dispatch('editAnnouncement', {
|
useAnnouncementsStore().editAnnouncement({
|
||||||
id: this.announcement.id,
|
id: this.announcement.id,
|
||||||
...this.editedAnnouncement
|
...this.editedAnnouncement
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
import Announcement from '../announcement/announcement.vue'
|
import Announcement from '../announcement/announcement.vue'
|
||||||
import AnnouncementEditor from '../announcement_editor/announcement_editor.vue'
|
import AnnouncementEditor from '../announcement_editor/announcement_editor.vue'
|
||||||
|
import { useAnnouncementsStore } from 'src/stores/announcements'
|
||||||
|
|
||||||
const AnnouncementsPage = {
|
const AnnouncementsPage = {
|
||||||
components: {
|
components: {
|
||||||
|
@ -20,14 +21,14 @@ const AnnouncementsPage = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$store.dispatch('fetchAnnouncements')
|
useAnnouncementsStore().fetchAnnouncements()
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({
|
...mapState({
|
||||||
currentUser: state => state.users.currentUser
|
currentUser: state => state.users.currentUser
|
||||||
}),
|
}),
|
||||||
announcements () {
|
announcements () {
|
||||||
return this.$store.state.announcements.announcements
|
return useAnnouncementsStore().announcements
|
||||||
},
|
},
|
||||||
canPostAnnouncement () {
|
canPostAnnouncement () {
|
||||||
return this.currentUser && this.currentUser.privileges.includes('announcements_manage_announcements')
|
return this.currentUser && this.currentUser.privileges.includes('announcements_manage_announcements')
|
||||||
|
@ -36,7 +37,7 @@ const AnnouncementsPage = {
|
||||||
methods: {
|
methods: {
|
||||||
postAnnouncement () {
|
postAnnouncement () {
|
||||||
this.posting = true
|
this.posting = true
|
||||||
this.$store.dispatch('postAnnouncement', this.newAnnouncement)
|
useAnnouncementsStore().postAnnouncement(this.newAnnouncement)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.newAnnouncement.content = ''
|
this.newAnnouncement.content = ''
|
||||||
this.startsAt = undefined
|
this.startsAt = undefined
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
faPencilAlt,
|
faPencilAlt,
|
||||||
faAlignRight
|
faAlignRight
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useMediaViewerStore } from 'src/stores/media_viewer'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faFile,
|
faFile,
|
||||||
|
@ -147,14 +148,14 @@ const Attachment = {
|
||||||
openModal (event) {
|
openModal (event) {
|
||||||
if (this.useModal) {
|
if (this.useModal) {
|
||||||
this.$emit('setMedia')
|
this.$emit('setMedia')
|
||||||
this.$store.dispatch('setCurrentMedia', this.attachment)
|
useMediaViewerStore().setCurrentMedia(this.attachment)
|
||||||
} else if (this.type === 'unknown') {
|
} else if (this.type === 'unknown') {
|
||||||
window.open(this.attachment.url)
|
window.open(this.attachment.url)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openModalForce (event) {
|
openModalForce (event) {
|
||||||
this.$emit('setMedia')
|
this.$emit('setMedia')
|
||||||
this.$store.dispatch('setCurrentMedia', this.attachment)
|
useMediaViewerStore().setCurrentMedia(this.attachment)
|
||||||
},
|
},
|
||||||
onEdit (event) {
|
onEdit (event) {
|
||||||
this.edit && this.edit(this.attachment, event)
|
this.edit && this.edit(this.attachment, event)
|
||||||
|
|
|
@ -63,7 +63,7 @@ const BookmarkFolderEdit = {
|
||||||
this.$router.push({ name: 'bookmark-folders' })
|
this.$router.push({ name: 'bookmark-folders' })
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
this.$store.dispatch('pushGlobalNotice', {
|
this.$store.useInterfaceStore().pushGlobalNotice({
|
||||||
messageKey: 'bookmark_folders.error',
|
messageKey: 'bookmark_folders.error',
|
||||||
messageArgs: [e.message],
|
messageArgs: [e.message],
|
||||||
level: 'error'
|
level: 'error'
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { WSConnectionStatus } from '../../services/api/api.service.js'
|
import { WSConnectionStatus } from '../../services/api/api.service.js'
|
||||||
import { mapGetters, mapState } from 'vuex'
|
import { mapGetters, mapState } from 'vuex'
|
||||||
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
import ChatMessage from '../chat_message/chat_message.vue'
|
import ChatMessage from '../chat_message/chat_message.vue'
|
||||||
import PostStatusForm from '../post_status_form/post_status_form.vue'
|
import PostStatusForm from '../post_status_form/post_status_form.vue'
|
||||||
import ChatTitle from '../chat_title/chat_title.vue'
|
import ChatTitle from '../chat_title/chat_title.vue'
|
||||||
|
@ -13,6 +14,7 @@ import {
|
||||||
faChevronLeft
|
faChevronLeft
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
import { buildFakeMessage } from '../../services/chat_utils/chat_utils.js'
|
import { buildFakeMessage } from '../../services/chat_utils/chat_utils.js'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faChevronDown,
|
faChevronDown,
|
||||||
|
@ -90,10 +92,12 @@ const Chat = {
|
||||||
'findOpenedChatByRecipientId',
|
'findOpenedChatByRecipientId',
|
||||||
'mergedConfig'
|
'mergedConfig'
|
||||||
]),
|
]),
|
||||||
|
...mapPiniaState(useInterfaceStore, {
|
||||||
|
mobileLayout: store => store.layoutType === 'mobile'
|
||||||
|
}),
|
||||||
...mapState({
|
...mapState({
|
||||||
backendInteractor: state => state.api.backendInteractor,
|
backendInteractor: state => state.api.backendInteractor,
|
||||||
mastoUserSocketStatus: state => state.api.mastoUserSocketStatus,
|
mastoUserSocketStatus: state => state.api.mastoUserSocketStatus,
|
||||||
mobileLayout: state => state.interface.layoutType === 'mobile',
|
|
||||||
currentUser: state => state.users.currentUser
|
currentUser: state => state.users.currentUser
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { mapState, mapGetters } from 'vuex'
|
import { mapState, mapGetters } from 'vuex'
|
||||||
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
import Popover from '../popover/popover.vue'
|
import Popover from '../popover/popover.vue'
|
||||||
import Attachment from '../attachment/attachment.vue'
|
import Attachment from '../attachment/attachment.vue'
|
||||||
import UserAvatar from '../user_avatar/user_avatar.vue'
|
import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
|
@ -12,6 +13,7 @@ import {
|
||||||
faTimes,
|
faTimes,
|
||||||
faEllipsisH
|
faEllipsisH
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faTimes,
|
faTimes,
|
||||||
|
@ -65,6 +67,9 @@ const ChatMessage = {
|
||||||
hasAttachment () {
|
hasAttachment () {
|
||||||
return this.message.attachments.length > 0
|
return this.message.attachments.length > 0
|
||||||
},
|
},
|
||||||
|
...mapPiniaState(useInterfaceStore, {
|
||||||
|
betterShadow: store => store.browserSupport.cssFilter
|
||||||
|
}),
|
||||||
...mapState({
|
...mapState({
|
||||||
currentUser: state => state.users.currentUser,
|
currentUser: state => state.users.currentUser,
|
||||||
restrictedNicknames: state => state.instance.restrictedNicknames
|
restrictedNicknames: state => state.instance.restrictedNicknames
|
||||||
|
|
|
@ -3,8 +3,10 @@ import Status from '../status/status.vue'
|
||||||
import ThreadTree from '../thread_tree/thread_tree.vue'
|
import ThreadTree from '../thread_tree/thread_tree.vue'
|
||||||
import { WSConnectionStatus } from '../../services/api/api.service.js'
|
import { WSConnectionStatus } from '../../services/api/api.service.js'
|
||||||
import { mapGetters, mapState } from 'vuex'
|
import { mapGetters, mapState } from 'vuex'
|
||||||
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
import QuickFilterSettings from '../quick_filter_settings/quick_filter_settings.vue'
|
import QuickFilterSettings from '../quick_filter_settings/quick_filter_settings.vue'
|
||||||
import QuickViewSettings from '../quick_view_settings/quick_view_settings.vue'
|
import QuickViewSettings from '../quick_view_settings/quick_view_settings.vue'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
|
@ -350,8 +352,10 @@ const conversation = {
|
||||||
},
|
},
|
||||||
...mapGetters(['mergedConfig']),
|
...mapGetters(['mergedConfig']),
|
||||||
...mapState({
|
...mapState({
|
||||||
mobileLayout: state => state.interface.layoutType === 'mobile',
|
|
||||||
mastoUserSocketStatus: state => state.api.mastoUserSocketStatus
|
mastoUserSocketStatus: state => state.api.mastoUserSocketStatus
|
||||||
|
}),
|
||||||
|
...mapPiniaState(useInterfaceStore, {
|
||||||
|
mobileLayout: store => store.layoutType === 'mobile'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import {
|
||||||
faCog,
|
faCog,
|
||||||
faInfoCircle
|
faInfoCircle
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faSignInAlt,
|
faSignInAlt,
|
||||||
|
@ -107,10 +108,10 @@ export default {
|
||||||
this.searchBarHidden = hidden
|
this.searchBarHidden = hidden
|
||||||
},
|
},
|
||||||
openSettingsModal () {
|
openSettingsModal () {
|
||||||
this.$store.dispatch('openSettingsModal', 'user')
|
useInterfaceStore().openSettingsModal('user')
|
||||||
},
|
},
|
||||||
openAdminModal () {
|
openAdminModal () {
|
||||||
this.$store.dispatch('openSettingsModal', 'admin')
|
useInterfaceStore().openSettingsModal('admin')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import EditStatusForm from '../edit_status_form/edit_status_form.vue'
|
import EditStatusForm from '../edit_status_form/edit_status_form.vue'
|
||||||
import Modal from '../modal/modal.vue'
|
import Modal from '../modal/modal.vue'
|
||||||
import get from 'lodash/get'
|
import get from 'lodash/get'
|
||||||
|
import { useEditStatusStore } from 'src/stores/editStatus'
|
||||||
|
|
||||||
const EditStatusModal = {
|
const EditStatusModal = {
|
||||||
components: {
|
components: {
|
||||||
|
@ -17,13 +18,13 @@ const EditStatusModal = {
|
||||||
return !!this.$store.state.users.currentUser
|
return !!this.$store.state.users.currentUser
|
||||||
},
|
},
|
||||||
modalActivated () {
|
modalActivated () {
|
||||||
return this.$store.state.editStatus.modalActivated
|
return useEditStatusStore().modalActivated
|
||||||
},
|
},
|
||||||
isFormVisible () {
|
isFormVisible () {
|
||||||
return this.isLoggedIn && !this.resettingForm && this.modalActivated
|
return this.isLoggedIn && !this.resettingForm && this.modalActivated
|
||||||
},
|
},
|
||||||
params () {
|
params () {
|
||||||
return this.$store.state.editStatus.params || {}
|
return useEditStatusStore().params || {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -46,7 +47,7 @@ const EditStatusModal = {
|
||||||
this.$refs.editStatusForm.requestClose()
|
this.$refs.editStatusForm.requestClose()
|
||||||
},
|
},
|
||||||
doCloseModal () {
|
doCloseModal () {
|
||||||
this.$store.dispatch('closeEditStatusModal')
|
useEditStatusStore().closeEditStatusModal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
|
import { useAnnouncementsStore } from 'src/stores/announcements'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
|
@ -7,6 +9,8 @@ import {
|
||||||
faBullhorn
|
faBullhorn
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faUserPlus,
|
faUserPlus,
|
||||||
faComments,
|
faComments,
|
||||||
|
@ -33,11 +37,14 @@ const ExtraNotifications = {
|
||||||
currentUser () {
|
currentUser () {
|
||||||
return this.$store.state.users.currentUser
|
return this.$store.state.users.currentUser
|
||||||
},
|
},
|
||||||
...mapGetters(['unreadChatCount', 'unreadAnnouncementCount', 'followRequestCount', 'mergedConfig'])
|
...mapGetters(['unreadChatCount', 'followRequestCount', 'mergedConfig']),
|
||||||
|
...mapPiniaState(useAnnouncementsStore, {
|
||||||
|
unreadAnnouncementCount: 'unreadAnnouncementCount'
|
||||||
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openNotificationSettings () {
|
openNotificationSettings () {
|
||||||
return this.$store.dispatch('openSettingsModalTab', 'notifications')
|
return useInterfaceStore().openSettingsModalTab('notifications')
|
||||||
},
|
},
|
||||||
dismissConfigurationTip () {
|
dismissConfigurationTip () {
|
||||||
return this.$store.dispatch('setOption', { name: 'showExtraNotificationsTip', value: false })
|
return this.$store.dispatch('setOption', { name: 'showExtraNotificationsTip', value: false })
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import Select from '../select/select.vue'
|
import Select from '../select/select.vue'
|
||||||
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
import Popover from 'src/components/popover/popover.vue'
|
import Popover from 'src/components/popover/popover.vue'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
|
@ -25,7 +26,7 @@ export default {
|
||||||
'name', 'label', 'modelValue', 'fallback', 'options', 'no-inherit'
|
'name', 'label', 'modelValue', 'fallback', 'options', 'no-inherit'
|
||||||
],
|
],
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$store.dispatch('queryLocalFonts')
|
useInterfaceStore().queryLocalFonts()
|
||||||
},
|
},
|
||||||
emits: ['update:modelValue'],
|
emits: ['update:modelValue'],
|
||||||
data () {
|
data () {
|
||||||
|
@ -50,10 +51,10 @@ export default {
|
||||||
return typeof this.modelValue !== 'undefined'
|
return typeof this.modelValue !== 'undefined'
|
||||||
},
|
},
|
||||||
localFontsList () {
|
localFontsList () {
|
||||||
return this.$store.state.interface.localFonts
|
return useInterfaceStore().localFonts
|
||||||
},
|
},
|
||||||
localFontsSize () {
|
localFontsSize () {
|
||||||
return this.$store.state.interface.localFonts?.length
|
return useInterfaceStore().localFonts?.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { useMediaViewerStore } from 'src/stores/media_viewer'
|
||||||
import Attachment from '../attachment/attachment.vue'
|
import Attachment from '../attachment/attachment.vue'
|
||||||
import { sumBy, set } from 'lodash'
|
import { sumBy, set } from 'lodash'
|
||||||
|
|
||||||
|
@ -107,11 +108,11 @@ const Gallery = {
|
||||||
this.hidingLong = event
|
this.hidingLong = event
|
||||||
},
|
},
|
||||||
openGallery () {
|
openGallery () {
|
||||||
this.$store.dispatch('setMedia', this.attachments)
|
useMediaViewerStore().setMedia(this.attachments)
|
||||||
this.$store.dispatch('setCurrentMedia', this.attachments[0])
|
useMediaViewerStore().setCurrentMedia(this.attachments[0])
|
||||||
},
|
},
|
||||||
onMedia () {
|
onMedia () {
|
||||||
this.$store.dispatch('setMedia', this.attachments)
|
useMediaViewerStore().setMedia(this.attachments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faTimes
|
faTimes
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faTimes
|
faTimes
|
||||||
|
@ -10,12 +11,12 @@ library.add(
|
||||||
const GlobalNoticeList = {
|
const GlobalNoticeList = {
|
||||||
computed: {
|
computed: {
|
||||||
notices () {
|
notices () {
|
||||||
return this.$store.state.interface.globalNotices
|
return useInterfaceStore().globalNotices
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
closeNotice (notice) {
|
closeNotice (notice) {
|
||||||
this.$store.dispatch('removeGlobalNotice', notice)
|
useInterfaceStore().removeGlobalNotice(notice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { useListsStore } from 'src/stores/lists'
|
||||||
import ListsCard from '../lists_card/lists_card.vue'
|
import ListsCard from '../lists_card/lists_card.vue'
|
||||||
|
|
||||||
const Lists = {
|
const Lists = {
|
||||||
|
@ -11,7 +12,7 @@ const Lists = {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
lists () {
|
lists () {
|
||||||
return this.$store.state.lists.allLists
|
return useListsStore().allLists
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { mapState, mapGetters } from 'vuex'
|
import { mapState, mapGetters } from 'vuex'
|
||||||
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
|
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
|
||||||
import ListsUserSearch from '../lists_user_search/lists_user_search.vue'
|
import ListsUserSearch from '../lists_user_search/lists_user_search.vue'
|
||||||
import PanelLoading from 'src/components/panel_loading/panel_loading.vue'
|
import PanelLoading from 'src/components/panel_loading/panel_loading.vue'
|
||||||
|
@ -9,6 +10,8 @@ import {
|
||||||
faSearch,
|
faSearch,
|
||||||
faChevronLeft
|
faChevronLeft
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
import { useListsStore } from 'src/stores/lists'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faSearch,
|
faSearch,
|
||||||
|
@ -37,12 +40,12 @@ const ListsNew = {
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
if (!this.id) return
|
if (!this.id) return
|
||||||
this.$store.dispatch('fetchList', { listId: this.id })
|
useListsStore().fetchList({ listId: this.id })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.title = this.findListTitle(this.id)
|
this.title = this.findListTitle(this.id)
|
||||||
this.titleDraft = this.title
|
this.titleDraft = this.title
|
||||||
})
|
})
|
||||||
this.$store.dispatch('fetchListAccounts', { listId: this.id })
|
useListsStore().fetchListAccounts({ listId: this.id })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.membersUserIds = this.findListAccounts(this.id)
|
this.membersUserIds = this.findListAccounts(this.id)
|
||||||
this.membersUserIds.forEach(userId => {
|
this.membersUserIds.forEach(userId => {
|
||||||
|
@ -64,7 +67,8 @@ const ListsNew = {
|
||||||
...mapState({
|
...mapState({
|
||||||
currentUser: state => state.users.currentUser
|
currentUser: state => state.users.currentUser
|
||||||
}),
|
}),
|
||||||
...mapGetters(['findUser', 'findListTitle', 'findListAccounts'])
|
...mapPiniaState(useListsStore, ['findListTitle', 'findListAccounts']),
|
||||||
|
...mapGetters(['findUser'])
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onInput () {
|
onInput () {
|
||||||
|
@ -95,10 +99,10 @@ const ListsNew = {
|
||||||
return this.addedUserIds.has(user.id)
|
return this.addedUserIds.has(user.id)
|
||||||
},
|
},
|
||||||
addUser (user) {
|
addUser (user) {
|
||||||
this.$store.dispatch('addListAccount', { accountId: user.id, listId: this.id })
|
useListsStore().addListAccount({ accountId: user.id, listId: this.id })
|
||||||
},
|
},
|
||||||
removeUser (userId) {
|
removeUser (userId) {
|
||||||
this.$store.dispatch('removeListAccount', { accountId: userId, listId: this.id })
|
useListsStore().removeListAccount({ accountId: userId, listId: this.id })
|
||||||
},
|
},
|
||||||
onSearchLoading (results) {
|
onSearchLoading (results) {
|
||||||
this.searchLoading = true
|
this.searchLoading = true
|
||||||
|
@ -111,24 +115,23 @@ const ListsNew = {
|
||||||
this.searchUserIds = results
|
this.searchUserIds = results
|
||||||
},
|
},
|
||||||
updateListTitle () {
|
updateListTitle () {
|
||||||
this.$store.dispatch('setList', { listId: this.id, title: this.titleDraft })
|
useListsStore().setList({ listId: this.id, title: this.titleDraft })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.title = this.findListTitle(this.id)
|
this.title = this.findListTitle(this.id)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
createList () {
|
createList () {
|
||||||
this.$store.dispatch('createList', { title: this.titleDraft })
|
useListsStore().createList({ title: this.titleDraft })
|
||||||
.then((list) => {
|
.then((list) => {
|
||||||
return this
|
return useListsStore()
|
||||||
.$store
|
.setListAccounts({ listId: list.id, accountIds: [...this.addedUserIds] })
|
||||||
.dispatch('setListAccounts', { listId: list.id, accountIds: [...this.addedUserIds] })
|
|
||||||
.then(() => list.id)
|
.then(() => list.id)
|
||||||
})
|
})
|
||||||
.then((listId) => {
|
.then((listId) => {
|
||||||
this.$router.push({ name: 'lists-timeline', params: { id: listId } })
|
this.$router.push({ name: 'lists-timeline', params: { id: listId } })
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
this.$store.dispatch('pushGlobalNotice', {
|
useInterfaceStore().pushGlobalNotice({
|
||||||
messageKey: 'lists.error',
|
messageKey: 'lists.error',
|
||||||
messageArgs: [e.message],
|
messageArgs: [e.message],
|
||||||
level: 'error'
|
level: 'error'
|
||||||
|
@ -136,7 +139,7 @@ const ListsNew = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
deleteList () {
|
deleteList () {
|
||||||
this.$store.dispatch('deleteList', { listId: this.id })
|
useListsStore().deleteList({ listId: this.id })
|
||||||
this.$router.push({ name: 'lists' })
|
this.$router.push({ name: 'lists' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
import NavigationEntry from 'src/components/navigation/navigation_entry.vue'
|
import NavigationEntry from 'src/components/navigation/navigation_entry.vue'
|
||||||
import { getListEntries } from 'src/components/navigation/filter.js'
|
import { getListEntries } from 'src/components/navigation/filter.js'
|
||||||
|
import { useListsStore } from 'src/stores/lists'
|
||||||
|
|
||||||
export const ListsMenuContent = {
|
export const ListsMenuContent = {
|
||||||
props: [
|
props: [
|
||||||
|
@ -10,8 +12,10 @@ export const ListsMenuContent = {
|
||||||
NavigationEntry
|
NavigationEntry
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapPiniaState(useListsStore, {
|
||||||
|
lists: getListEntries
|
||||||
|
}),
|
||||||
...mapState({
|
...mapState({
|
||||||
lists: getListEntries,
|
|
||||||
currentUser: state => state.users.currentUser,
|
currentUser: state => state.users.currentUser,
|
||||||
privateMode: state => state.instance.private,
|
privateMode: state => state.instance.private,
|
||||||
federating: state => state.instance.federating
|
federating: state => state.instance.federating
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { useListsStore } from 'src/stores/lists'
|
||||||
import Timeline from '../timeline/timeline.vue'
|
import Timeline from '../timeline/timeline.vue'
|
||||||
const ListsTimeline = {
|
const ListsTimeline = {
|
||||||
data () {
|
data () {
|
||||||
|
@ -17,14 +18,14 @@ const ListsTimeline = {
|
||||||
this.listId = route.params.id
|
this.listId = route.params.id
|
||||||
this.$store.dispatch('stopFetchingTimeline', 'list')
|
this.$store.dispatch('stopFetchingTimeline', 'list')
|
||||||
this.$store.commit('clearTimeline', { timeline: 'list' })
|
this.$store.commit('clearTimeline', { timeline: 'list' })
|
||||||
this.$store.dispatch('fetchList', { listId: this.listId })
|
useListsStore().fetchList({ listId: this.listId })
|
||||||
this.$store.dispatch('startFetchingTimeline', { timeline: 'list', listId: this.listId })
|
this.$store.dispatch('startFetchingTimeline', { timeline: 'list', listId: this.listId })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
this.listId = this.$route.params.id
|
this.listId = this.$route.params.id
|
||||||
this.$store.dispatch('fetchList', { listId: this.listId })
|
useListsStore().fetchList({ listId: this.listId })
|
||||||
this.$store.dispatch('startFetchingTimeline', { timeline: 'list', listId: this.listId })
|
this.$store.dispatch('startFetchingTimeline', { timeline: 'list', listId: this.listId })
|
||||||
},
|
},
|
||||||
unmounted () {
|
unmounted () {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
faCircleNotch,
|
faCircleNotch,
|
||||||
faTimes
|
faTimes
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useMediaViewerStore } from 'src/stores/media_viewer'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faChevronLeft,
|
faChevronLeft,
|
||||||
|
@ -44,16 +45,16 @@ const MediaModal = {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
showing () {
|
showing () {
|
||||||
return this.$store.state.mediaViewer.activated
|
return useMediaViewerStore().activated
|
||||||
},
|
},
|
||||||
media () {
|
media () {
|
||||||
return this.$store.state.mediaViewer.media
|
return useMediaViewerStore().media
|
||||||
},
|
},
|
||||||
description () {
|
description () {
|
||||||
return this.currentMedia.description
|
return this.currentMedia.description
|
||||||
},
|
},
|
||||||
currentIndex () {
|
currentIndex () {
|
||||||
return this.$store.state.mediaViewer.currentIndex
|
return useMediaViewerStore().currentIndex
|
||||||
},
|
},
|
||||||
currentMedia () {
|
currentMedia () {
|
||||||
return this.media[this.currentIndex]
|
return this.media[this.currentIndex]
|
||||||
|
@ -79,7 +80,7 @@ const MediaModal = {
|
||||||
// to be processed on the content below the overlay
|
// to be processed on the content below the overlay
|
||||||
const transitionTime = 100 // ms
|
const transitionTime = 100 // ms
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$store.dispatch('closeMediaViewer')
|
useMediaViewerStore().closeMediaViewer()
|
||||||
}, transitionTime)
|
}, transitionTime)
|
||||||
},
|
},
|
||||||
hideIfNotSwiped (event) {
|
hideIfNotSwiped (event) {
|
||||||
|
@ -98,7 +99,7 @@ const MediaModal = {
|
||||||
if (this.getType(newMedia) === 'image') {
|
if (this.getType(newMedia) === 'image') {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
}
|
}
|
||||||
this.$store.dispatch('setCurrentMedia', newMedia)
|
useMediaViewerStore().setCurrentMedia(newMedia)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
goNext () {
|
goNext () {
|
||||||
|
@ -108,7 +109,7 @@ const MediaModal = {
|
||||||
if (this.getType(newMedia) === 'image') {
|
if (this.getType(newMedia) === 'image') {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
}
|
}
|
||||||
this.$store.dispatch('setCurrentMedia', newMedia)
|
useMediaViewerStore().setCurrentMedia(newMedia)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onImageLoaded () {
|
onImageLoaded () {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
import GestureService from '../../services/gesture_service/gesture_service'
|
import GestureService from '../../services/gesture_service/gesture_service'
|
||||||
import NavigationPins from 'src/components/navigation/navigation_pins.vue'
|
import NavigationPins from 'src/components/navigation/navigation_pins.vue'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
import { mapState } from 'pinia'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faTimes,
|
faTimes,
|
||||||
|
@ -17,6 +18,7 @@ import {
|
||||||
faMinus,
|
faMinus,
|
||||||
faCheckDouble
|
faCheckDouble
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useAnnouncementsStore } from 'src/stores/announcements'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faTimes,
|
faTimes,
|
||||||
|
@ -68,7 +70,8 @@ const MobileNav = {
|
||||||
isChat () {
|
isChat () {
|
||||||
return this.$route.name === 'chat'
|
return this.$route.name === 'chat'
|
||||||
},
|
},
|
||||||
...mapGetters(['unreadChatCount', 'unreadAnnouncementCount']),
|
...mapState(useAnnouncementsStore, ['unreadAnnouncementCount']),
|
||||||
|
...mapGetters(['unreadChatCount']),
|
||||||
chatsPinned () {
|
chatsPinned () {
|
||||||
return new Set(this.$store.state.serverSideStorage.prefsStorage.collections.pinnedNavItems).has('chats')
|
return new Set(this.$store.state.serverSideStorage.prefsStorage.collections.pinnedNavItems).has('chats')
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faPen
|
faPen
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { usePostStatusStore } from 'src/stores/postStatus'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faPen
|
faPen
|
||||||
|
@ -71,7 +72,7 @@ const MobilePostStatusButton = {
|
||||||
window.removeEventListener('scroll', this.handleScrollEnd)
|
window.removeEventListener('scroll', this.handleScrollEnd)
|
||||||
},
|
},
|
||||||
openPostForm () {
|
openPostForm () {
|
||||||
this.$store.dispatch('openPostStatusModal')
|
usePostStatusStore().openPostStatusModal()
|
||||||
},
|
},
|
||||||
handleOSK () {
|
handleOSK () {
|
||||||
// This is a big hack: we're guessing from changed window sizes if the
|
// This is a big hack: we're guessing from changed window sizes if the
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import BookmarkFoldersMenuContent from 'src/components/bookmark_folders_menu/bookmark_folders_menu_content.vue'
|
import BookmarkFoldersMenuContent from 'src/components/bookmark_folders_menu/bookmark_folders_menu_content.vue'
|
||||||
import ListsMenuContent from 'src/components/lists_menu/lists_menu_content.vue'
|
import ListsMenuContent from 'src/components/lists_menu/lists_menu_content.vue'
|
||||||
import { mapState, mapGetters } from 'vuex'
|
import { mapState, mapGetters } from 'vuex'
|
||||||
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
import { TIMELINES, ROOT_ITEMS } from 'src/components/navigation/navigation.js'
|
import { TIMELINES, ROOT_ITEMS } from 'src/components/navigation/navigation.js'
|
||||||
import { filterNavigation } from 'src/components/navigation/filter.js'
|
import { filterNavigation } from 'src/components/navigation/filter.js'
|
||||||
import NavigationEntry from 'src/components/navigation/navigation_entry.vue'
|
import NavigationEntry from 'src/components/navigation/navigation_entry.vue'
|
||||||
import NavigationPins from 'src/components/navigation/navigation_pins.vue'
|
import NavigationPins from 'src/components/navigation/navigation_pins.vue'
|
||||||
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
|
import { useAnnouncementsStore } from 'src/stores/announcements'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
|
@ -90,13 +92,16 @@ const NavPanel = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapPiniaState(useAnnouncementsStore, {
|
||||||
|
unreadAnnouncementCount: 'unreadAnnouncementCount',
|
||||||
|
supportsAnnouncements: store => store.supportsAnnouncements
|
||||||
|
}),
|
||||||
...mapState({
|
...mapState({
|
||||||
currentUser: state => state.users.currentUser,
|
currentUser: state => state.users.currentUser,
|
||||||
followRequestCount: state => state.api.followRequests.length,
|
followRequestCount: state => state.api.followRequests.length,
|
||||||
privateMode: state => state.instance.private,
|
privateMode: state => state.instance.private,
|
||||||
federating: state => state.instance.federating,
|
federating: state => state.instance.federating,
|
||||||
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable,
|
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable,
|
||||||
supportsAnnouncements: state => state.announcements.supportsAnnouncements,
|
|
||||||
pinnedItems: state => new Set(state.serverSideStorage.prefsStorage.collections.pinnedNavItems),
|
pinnedItems: state => new Set(state.serverSideStorage.prefsStorage.collections.pinnedNavItems),
|
||||||
collapsed: state => state.serverSideStorage.prefsStorage.simple.collapseNav,
|
collapsed: state => state.serverSideStorage.prefsStorage.simple.collapseNav,
|
||||||
bookmarkFolders: state => state.instance.pleromaBookmarkFoldersAvailable
|
bookmarkFolders: state => state.instance.pleromaBookmarkFoldersAvailable
|
||||||
|
@ -131,7 +136,7 @@ const NavPanel = {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
...mapGetters(['unreadChatCount', 'unreadAnnouncementCount'])
|
...mapGetters(['unreadChatCount'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ export const filterNavigation = (list = [], { hasChats, hasAnnouncements, isFede
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getListEntries = state => state.lists.allLists.map(list => ({
|
export const getListEntries = store => store.allLists.map(list => ({
|
||||||
name: 'list-' + list.id,
|
name: 'list-' + list.id,
|
||||||
routeObject: { name: 'lists-timeline', params: { id: list.id } },
|
routeObject: { name: 'lists-timeline', params: { id: list.id } },
|
||||||
labelRaw: list.title,
|
labelRaw: list.title,
|
||||||
|
|
|
@ -84,6 +84,7 @@ export const ROOT_ITEMS = {
|
||||||
route: 'announcements',
|
route: 'announcements',
|
||||||
icon: 'bullhorn',
|
icon: 'bullhorn',
|
||||||
label: 'nav.announcements',
|
label: 'nav.announcements',
|
||||||
|
store: 'announcements',
|
||||||
badgeStyle: 'notification',
|
badgeStyle: 'notification',
|
||||||
badgeGetter: 'unreadAnnouncementCount',
|
badgeGetter: 'unreadAnnouncementCount',
|
||||||
criteria: ['announcements']
|
criteria: ['announcements']
|
||||||
|
|
|
@ -3,6 +3,8 @@ import { routeTo } from 'src/components/navigation/navigation.js'
|
||||||
import OptionalRouterLink from 'src/components/optional_router_link/optional_router_link.vue'
|
import OptionalRouterLink from 'src/components/optional_router_link/optional_router_link.vue'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faThumbtack } from '@fortawesome/free-solid-svg-icons'
|
import { faThumbtack } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { mapStores } from 'pinia'
|
||||||
|
import { useAnnouncementsStore } from 'src/stores/announcements'
|
||||||
|
|
||||||
library.add(faThumbtack)
|
library.add(faThumbtack)
|
||||||
|
|
||||||
|
@ -31,6 +33,7 @@ const NavigationEntry = {
|
||||||
getters () {
|
getters () {
|
||||||
return this.$store.getters
|
return this.$store.getters
|
||||||
},
|
},
|
||||||
|
...mapStores(useAnnouncementsStore),
|
||||||
...mapState({
|
...mapState({
|
||||||
currentUser: state => state.users.currentUser,
|
currentUser: state => state.users.currentUser,
|
||||||
pinnedItems: state => new Set(state.serverSideStorage.prefsStorage.collections.pinnedNavItems)
|
pinnedItems: state => new Set(state.serverSideStorage.prefsStorage.collections.pinnedNavItems)
|
||||||
|
|
|
@ -53,6 +53,12 @@
|
||||||
>
|
>
|
||||||
{{ getters[item.badgeGetter] }}
|
{{ getters[item.badgeGetter] }}
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="item.badgeGetter && item.store && this[`${item.store}Store`][item.badgeGetter]"
|
||||||
|
class="badge badge-notification"
|
||||||
|
>
|
||||||
|
{{ this[`${item.store}Store`][item.badgeGetter] }}
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
v-if="showPin && currentUser"
|
v-if="showPin && currentUser"
|
||||||
type="button"
|
type="button"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'vuex'
|
||||||
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
import { TIMELINES, ROOT_ITEMS, routeTo } from 'src/components/navigation/navigation.js'
|
import { TIMELINES, ROOT_ITEMS, routeTo } from 'src/components/navigation/navigation.js'
|
||||||
import { getBookmarkFolderEntries, getListEntries, filterNavigation } from 'src/components/navigation/filter.js'
|
import { getBookmarkFolderEntries, getListEntries, filterNavigation } from 'src/components/navigation/filter.js'
|
||||||
|
|
||||||
|
@ -16,6 +17,8 @@ import {
|
||||||
faStream,
|
faStream,
|
||||||
faList
|
faList
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useListsStore } from 'src/stores/lists'
|
||||||
|
import { useAnnouncementsStore } from 'src/stores/announcements'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faUsers,
|
faUsers,
|
||||||
|
@ -43,15 +46,19 @@ const NavPanel = {
|
||||||
getters () {
|
getters () {
|
||||||
return this.$store.getters
|
return this.$store.getters
|
||||||
},
|
},
|
||||||
|
...mapPiniaState(useListsStore, {
|
||||||
|
lists: getListEntries
|
||||||
|
}),
|
||||||
|
...mapPiniaState(useAnnouncementsStore, {
|
||||||
|
supportsAnnouncements: store => store.supportsAnnouncements
|
||||||
|
}),
|
||||||
...mapState({
|
...mapState({
|
||||||
lists: getListEntries,
|
|
||||||
bookmarks: getBookmarkFolderEntries,
|
bookmarks: getBookmarkFolderEntries,
|
||||||
currentUser: state => state.users.currentUser,
|
currentUser: state => state.users.currentUser,
|
||||||
followRequestCount: state => state.api.followRequests.length,
|
followRequestCount: state => state.api.followRequests.length,
|
||||||
privateMode: state => state.instance.private,
|
privateMode: state => state.instance.private,
|
||||||
federating: state => state.instance.federating,
|
federating: state => state.instance.federating,
|
||||||
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable,
|
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable,
|
||||||
supportsAnnouncements: state => state.announcements.supportsAnnouncements,
|
|
||||||
pinnedItems: state => new Set(state.serverSideStorage.prefsStorage.collections.pinnedNavItems)
|
pinnedItems: state => new Set(state.serverSideStorage.prefsStorage.collections.pinnedNavItems)
|
||||||
}),
|
}),
|
||||||
pinnedList () {
|
pinnedList () {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
import { mapState } from 'pinia'
|
||||||
import Notification from '../notification/notification.vue'
|
import Notification from '../notification/notification.vue'
|
||||||
import ExtraNotifications from '../extra_notifications/extra_notifications.vue'
|
import ExtraNotifications from '../extra_notifications/extra_notifications.vue'
|
||||||
import NotificationFilters from './notification_filters.vue'
|
import NotificationFilters from './notification_filters.vue'
|
||||||
|
@ -14,6 +15,8 @@ import {
|
||||||
import FaviconService from '../../services/favicon_service/favicon_service.js'
|
import FaviconService from '../../services/favicon_service/favicon_service.js'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faCircleNotch, faArrowUp, faMinus } from '@fortawesome/free-solid-svg-icons'
|
import { faCircleNotch, faArrowUp, faMinus } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
import { useAnnouncementsStore } from 'src/stores/announcements'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faCircleNotch,
|
faCircleNotch,
|
||||||
|
@ -98,11 +101,11 @@ const Notifications = {
|
||||||
return this.$store.state.notifications.loading
|
return this.$store.state.notifications.loading
|
||||||
},
|
},
|
||||||
noHeading () {
|
noHeading () {
|
||||||
const { layoutType } = this.$store.state.interface
|
const { layoutType } = useInterfaceStore()
|
||||||
return this.minimalMode || layoutType === 'mobile'
|
return this.minimalMode || layoutType === 'mobile'
|
||||||
},
|
},
|
||||||
teleportTarget () {
|
teleportTarget () {
|
||||||
const { layoutType } = this.$store.state.interface
|
const { layoutType } = useInterfaceStore()
|
||||||
const map = {
|
const map = {
|
||||||
wide: '#notifs-column',
|
wide: '#notifs-column',
|
||||||
mobile: '#mobile-notifications'
|
mobile: '#mobile-notifications'
|
||||||
|
@ -110,7 +113,7 @@ const Notifications = {
|
||||||
return map[layoutType] || '#notifs-sidebar'
|
return map[layoutType] || '#notifs-sidebar'
|
||||||
},
|
},
|
||||||
popoversZLayer () {
|
popoversZLayer () {
|
||||||
const { layoutType } = this.$store.state.interface
|
const { layoutType } = useInterfaceStore()
|
||||||
return layoutType === 'mobile' ? 'navbar' : null
|
return layoutType === 'mobile' ? 'navbar' : null
|
||||||
},
|
},
|
||||||
notificationsToDisplay () {
|
notificationsToDisplay () {
|
||||||
|
@ -121,7 +124,8 @@ const Notifications = {
|
||||||
showExtraNotifications () {
|
showExtraNotifications () {
|
||||||
return !this.noExtra
|
return !this.noExtra
|
||||||
},
|
},
|
||||||
...mapGetters(['unreadChatCount', 'unreadAnnouncementCount'])
|
...mapState(useAnnouncementsStore, ['unreadAnnouncementCount']),
|
||||||
|
...mapGetters(['unreadChatCount'])
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.scrollerRef = this.$refs.root.closest('.column.-scrollable')
|
this.scrollerRef = this.$refs.root.closest('.column.-scrollable')
|
||||||
|
@ -141,10 +145,10 @@ const Notifications = {
|
||||||
unseenCountTitle (count) {
|
unseenCountTitle (count) {
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
FaviconService.drawFaviconBadge()
|
FaviconService.drawFaviconBadge()
|
||||||
this.$store.dispatch('setPageTitle', `(${count})`)
|
useInterfaceStore().setPageTitle(`(${count})`)
|
||||||
} else {
|
} else {
|
||||||
FaviconService.clearFaviconBadge()
|
FaviconService.clearFaviconBadge()
|
||||||
this.$store.dispatch('setPageTitle', '')
|
useInterfaceStore().setPageTitle('')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
teleportTarget () {
|
teleportTarget () {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import Timeago from 'components/timeago/timeago.vue'
|
||||||
import genRandomSeed from '../../services/random_seed/random_seed.service.js'
|
import genRandomSeed from '../../services/random_seed/random_seed.service.js'
|
||||||
import RichContent from 'components/rich_content/rich_content.jsx'
|
import RichContent from 'components/rich_content/rich_content.jsx'
|
||||||
import { forEach, map } from 'lodash'
|
import { forEach, map } from 'lodash'
|
||||||
|
import { usePollsStore } from 'src/stores/polls'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Poll',
|
name: 'Poll',
|
||||||
|
@ -18,20 +19,20 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
if (!this.$store.state.polls.pollsObject[this.pollId]) {
|
if (!usePollsStore().pollsObject[this.pollId]) {
|
||||||
this.$store.dispatch('mergeOrAddPoll', this.basePoll)
|
usePollsStore().mergeOrAddPoll(this.basePoll)
|
||||||
}
|
}
|
||||||
this.$store.dispatch('trackPoll', this.pollId)
|
usePollsStore().trackPoll(this.pollId)
|
||||||
},
|
},
|
||||||
unmounted () {
|
unmounted () {
|
||||||
this.$store.dispatch('untrackPoll', this.pollId)
|
usePollsStore().untrackPoll(this.pollId)
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
pollId () {
|
pollId () {
|
||||||
return this.basePoll.id
|
return this.basePoll.id
|
||||||
},
|
},
|
||||||
poll () {
|
poll () {
|
||||||
const storePoll = this.$store.state.polls.pollsObject[this.pollId]
|
const storePoll = usePollsStore().pollsObject[this.pollId]
|
||||||
return storePoll || {}
|
return storePoll || {}
|
||||||
},
|
},
|
||||||
options () {
|
options () {
|
||||||
|
@ -77,9 +78,6 @@ export default {
|
||||||
resultTitle (option) {
|
resultTitle (option) {
|
||||||
return `${option.votes_count}/${this.totalVotesCount} ${this.$t('polls.votes')}`
|
return `${option.votes_count}/${this.totalVotesCount} ${this.$t('polls.votes')}`
|
||||||
},
|
},
|
||||||
fetchPoll () {
|
|
||||||
this.$store.dispatch('refreshPoll', { id: this.statusId, pollId: this.poll.id })
|
|
||||||
},
|
|
||||||
activateOption (index) {
|
activateOption (index) {
|
||||||
// forgive me father: doing checking the radio/checkboxes
|
// forgive me father: doing checking the radio/checkboxes
|
||||||
// in code because of customized input elements need either
|
// in code because of customized input elements need either
|
||||||
|
@ -107,8 +105,7 @@ export default {
|
||||||
vote () {
|
vote () {
|
||||||
if (this.choiceIndices.length === 0) return
|
if (this.choiceIndices.length === 0) return
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.$store.dispatch(
|
usePollsStore().votePoll(
|
||||||
'votePoll',
|
|
||||||
{ id: this.statusId, pollId: this.poll.id, choices: this.choiceIndices }
|
{ id: this.statusId, pollId: this.poll.id, choices: this.choiceIndices }
|
||||||
).then(poll => {
|
).then(poll => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
|
|
@ -14,7 +14,8 @@ import { propsToNative } from '../../services/attributes_helper/attributes_helpe
|
||||||
import { pollFormToMasto } from 'src/services/poll/poll.service.js'
|
import { pollFormToMasto } from 'src/services/poll/poll.service.js'
|
||||||
import { reject, map, uniqBy, debounce } from 'lodash'
|
import { reject, map, uniqBy, debounce } from 'lodash'
|
||||||
import suggestor from '../emoji_input/suggestor.js'
|
import suggestor from '../emoji_input/suggestor.js'
|
||||||
import { mapGetters, mapState } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
import { mapState, mapActions } from 'pinia'
|
||||||
import Checkbox from '../checkbox/checkbox.vue'
|
import Checkbox from '../checkbox/checkbox.vue'
|
||||||
import Select from '../select/select.vue'
|
import Select from '../select/select.vue'
|
||||||
import DraftCloser from 'src/components/draft_closer/draft_closer.vue'
|
import DraftCloser from 'src/components/draft_closer/draft_closer.vue'
|
||||||
|
@ -32,6 +33,9 @@ import {
|
||||||
faChevronRight
|
faChevronRight
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||||
|
import { useMediaViewerStore } from 'src/stores/media_viewer.js'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faSmileBeam,
|
faSmileBeam,
|
||||||
faPollH,
|
faPollH,
|
||||||
|
@ -367,8 +371,8 @@ const PostStatusForm = {
|
||||||
) && this.saveable
|
) && this.saveable
|
||||||
},
|
},
|
||||||
...mapGetters(['mergedConfig']),
|
...mapGetters(['mergedConfig']),
|
||||||
...mapState({
|
...mapState(useInterfaceStore, {
|
||||||
mobileLayout: state => state.interface.mobileLayout
|
mobileLayout: store => store.mobileLayout
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -393,6 +397,7 @@ const PostStatusForm = {
|
||||||
this.removeBeforeUnloadListener()
|
this.removeBeforeUnloadListener()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
...mapActions(useMediaViewerStore, ['increment']),
|
||||||
statusChanged () {
|
statusChanged () {
|
||||||
this.autoPreview()
|
this.autoPreview()
|
||||||
this.updateIdempotencyKey()
|
this.updateIdempotencyKey()
|
||||||
|
@ -753,7 +758,7 @@ const PostStatusForm = {
|
||||||
this.idempotencyKey = Date.now().toString()
|
this.idempotencyKey = Date.now().toString()
|
||||||
},
|
},
|
||||||
openProfileTab () {
|
openProfileTab () {
|
||||||
this.$store.dispatch('openSettingsModalTab', 'profile')
|
useInterfaceStore().openSettingsModalTab('profile')
|
||||||
},
|
},
|
||||||
propsToNative (props) {
|
propsToNative (props) {
|
||||||
return propsToNative(props)
|
return propsToNative(props)
|
||||||
|
|
|
@ -386,7 +386,7 @@
|
||||||
:nsfw="false"
|
:nsfw="false"
|
||||||
:attachments="newStatus.files"
|
:attachments="newStatus.files"
|
||||||
:descriptions="newStatus.mediaDescriptions"
|
:descriptions="newStatus.mediaDescriptions"
|
||||||
:set-media="() => $store.dispatch('setMedia', newStatus.files)"
|
:set-media="() => setMedia()"
|
||||||
:editable="true"
|
:editable="true"
|
||||||
:edit-attachment="editAttachment"
|
:edit-attachment="editAttachment"
|
||||||
:remove-attachment="removeMediaFile"
|
:remove-attachment="removeMediaFile"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import PostStatusForm from '../post_status_form/post_status_form.vue'
|
import PostStatusForm from '../post_status_form/post_status_form.vue'
|
||||||
import Modal from '../modal/modal.vue'
|
import Modal from '../modal/modal.vue'
|
||||||
import get from 'lodash/get'
|
import get from 'lodash/get'
|
||||||
|
import { usePostStatusStore } from 'src/stores/postStatus'
|
||||||
|
|
||||||
const PostStatusModal = {
|
const PostStatusModal = {
|
||||||
components: {
|
components: {
|
||||||
|
@ -17,13 +18,13 @@ const PostStatusModal = {
|
||||||
return !!this.$store.state.users.currentUser
|
return !!this.$store.state.users.currentUser
|
||||||
},
|
},
|
||||||
modalActivated () {
|
modalActivated () {
|
||||||
return this.$store.state.postStatus.modalActivated
|
return usePostStatusStore().modalActivated
|
||||||
},
|
},
|
||||||
isFormVisible () {
|
isFormVisible () {
|
||||||
return this.isLoggedIn && !this.resettingForm && this.modalActivated
|
return this.isLoggedIn && !this.resettingForm && this.modalActivated
|
||||||
},
|
},
|
||||||
params () {
|
params () {
|
||||||
return this.$store.state.postStatus.params || {}
|
return usePostStatusStore().params || {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -43,11 +44,11 @@ const PostStatusModal = {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
closeModal () {
|
closeModal () {
|
||||||
this.$store.dispatch('closePostStatusModal')
|
usePostStatusStore().closePostStatusModal()
|
||||||
},
|
},
|
||||||
resetAndClose () {
|
resetAndClose () {
|
||||||
this.$store.dispatch('resetPostStatusModal')
|
usePostStatusStore().resetPostStatusModal()
|
||||||
this.$store.dispatch('closePostStatusModal')
|
usePostStatusStore().closePostStatusModal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import Popover from '../popover/popover.vue'
|
import Popover from '../popover/popover.vue'
|
||||||
import { mapGetters, mapState } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
import { mapState } from 'pinia'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faFilter, faFont, faWrench } from '@fortawesome/free-solid-svg-icons'
|
import { faFilter, faFont, faWrench } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faFilter,
|
faFilter,
|
||||||
|
@ -23,13 +25,13 @@ const QuickFilterSettings = {
|
||||||
this.$store.dispatch('queueFlushAll')
|
this.$store.dispatch('queueFlushAll')
|
||||||
},
|
},
|
||||||
openTab (tab) {
|
openTab (tab) {
|
||||||
this.$store.dispatch('openSettingsModalTab', tab)
|
useInterfaceStore().openSettingsModalTab(tab)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['mergedConfig']),
|
...mapGetters(['mergedConfig']),
|
||||||
...mapState({
|
...mapState(useInterfaceStore, {
|
||||||
mobileLayout: state => state.interface.layoutType === 'mobile'
|
mobileLayout: state => state.layoutType === 'mobile'
|
||||||
}),
|
}),
|
||||||
triggerAttrs () {
|
triggerAttrs () {
|
||||||
if (this.mobileLayout) {
|
if (this.mobileLayout) {
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import Popover from 'src/components/popover/popover.vue'
|
import Popover from 'src/components/popover/popover.vue'
|
||||||
import QuickFilterSettings from 'src/components/quick_filter_settings/quick_filter_settings.vue'
|
import QuickFilterSettings from 'src/components/quick_filter_settings/quick_filter_settings.vue'
|
||||||
import { mapGetters, mapState } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
import { mapState } from 'pinia'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faList, faFolderTree, faBars, faWrench } from '@fortawesome/free-solid-svg-icons'
|
import { faList, faFolderTree, faBars, faWrench } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faList,
|
faList,
|
||||||
|
@ -24,13 +26,13 @@ const QuickViewSettings = {
|
||||||
this.$store.dispatch('setOption', { name: 'conversationDisplay', value: visibility })
|
this.$store.dispatch('setOption', { name: 'conversationDisplay', value: visibility })
|
||||||
},
|
},
|
||||||
openTab (tab) {
|
openTab (tab) {
|
||||||
this.$store.dispatch('openSettingsModalTab', tab)
|
useInterfaceStore().openSettingsModalTab(tab)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['mergedConfig']),
|
...mapGetters(['mergedConfig']),
|
||||||
...mapState({
|
...mapState(useInterfaceStore, {
|
||||||
mobileLayout: state => state.interface.layoutType === 'mobile'
|
mobileLayout: state => state.layoutType === 'mobile'
|
||||||
}),
|
}),
|
||||||
loggedIn () {
|
loggedIn () {
|
||||||
return !!this.$store.state.users.currentUser
|
return !!this.$store.state.users.currentUser
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { useReportsStore } from 'src/stores/reports'
|
||||||
import Select from '../select/select.vue'
|
import Select from '../select/select.vue'
|
||||||
import StatusContent from '../status_content/status_content.vue'
|
import StatusContent from '../status_content/status_content.vue'
|
||||||
import Timeago from '../timeago/timeago.vue'
|
import Timeago from '../timeago/timeago.vue'
|
||||||
|
@ -16,7 +17,7 @@ const Report = {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
report () {
|
report () {
|
||||||
return this.$store.state.reports.reports[this.reportId] || {}
|
return useReportsStore().reports[this.reportId] || {}
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
get: function () { return this.report.state },
|
get: function () { return this.report.state },
|
||||||
|
@ -28,7 +29,7 @@ const Report = {
|
||||||
return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
|
return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
|
||||||
},
|
},
|
||||||
setReportState (state) {
|
setReportState (state) {
|
||||||
return this.$store.dispatch('setReportState', { id: this.report.id, state })
|
return useReportsStore().setReportState({ id: this.report.id, state })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,7 +232,7 @@ const EmojiTab = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
displayError (msg) {
|
displayError (msg) {
|
||||||
this.$store.dispatch('pushGlobalNotice', {
|
this.$store.useInterfaceStore().pushGlobalNotice({
|
||||||
messageKey: 'admin_dash.emoji.error',
|
messageKey: 'admin_dash.emoji.error',
|
||||||
messageArgs: [msg],
|
messageArgs: [msg],
|
||||||
level: 'error'
|
level: 'error'
|
||||||
|
|
|
@ -80,7 +80,7 @@ const FrontendsTab = {
|
||||||
this.$store.dispatch('loadFrontendsStuff')
|
this.$store.dispatch('loadFrontendsStuff')
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
const reason = await response.error.json()
|
const reason = await response.error.json()
|
||||||
this.$store.dispatch('pushGlobalNotice', {
|
this.$store.useInterfaceStore().pushGlobalNotice({
|
||||||
level: 'error',
|
level: 'error',
|
||||||
messageKey: 'admin_dash.frontend.failure_installing_frontend',
|
messageKey: 'admin_dash.frontend.failure_installing_frontend',
|
||||||
messageArgs: {
|
messageArgs: {
|
||||||
|
@ -90,7 +90,7 @@ const FrontendsTab = {
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.$store.dispatch('pushGlobalNotice', {
|
this.$store.useInterfaceStore().pushGlobalNotice({
|
||||||
level: 'success',
|
level: 'success',
|
||||||
messageKey: 'admin_dash.frontend.success_installing_frontend',
|
messageKey: 'admin_dash.frontend.success_installing_frontend',
|
||||||
messageArgs: {
|
messageArgs: {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
|
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { cloneDeep, isEqual } from 'lodash'
|
import { cloneDeep, isEqual } from 'lodash'
|
||||||
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
import {
|
import {
|
||||||
newImporter,
|
newImporter,
|
||||||
newExporter
|
newExporter
|
||||||
|
@ -20,6 +21,7 @@ import {
|
||||||
import {
|
import {
|
||||||
faWindowMinimize
|
faWindowMinimize
|
||||||
} from '@fortawesome/free-regular-svg-icons'
|
} from '@fortawesome/free-regular-svg-icons'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
const PLEROMAFE_SETTINGS_MAJOR_VERSION = 1
|
const PLEROMAFE_SETTINGS_MAJOR_VERSION = 1
|
||||||
const PLEROMAFE_SETTINGS_MINOR_VERSION = 0
|
const PLEROMAFE_SETTINGS_MINOR_VERSION = 0
|
||||||
|
@ -74,10 +76,10 @@ const SettingsModal = {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
closeModal () {
|
closeModal () {
|
||||||
this.$store.dispatch('closeSettingsModal')
|
useInterfaceStore().closeSettingsModal()
|
||||||
},
|
},
|
||||||
peekModal () {
|
peekModal () {
|
||||||
this.$store.dispatch('togglePeekSettingsModal')
|
useInterfaceStore().togglePeekSettingsModal()
|
||||||
},
|
},
|
||||||
importValidator (data) {
|
importValidator (data) {
|
||||||
if (!Array.isArray(data._pleroma_settings_version)) {
|
if (!Array.isArray(data._pleroma_settings_version)) {
|
||||||
|
@ -109,7 +111,7 @@ const SettingsModal = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minor > PLEROMAFE_SETTINGS_MINOR_VERSION) {
|
if (minor > PLEROMAFE_SETTINGS_MINOR_VERSION) {
|
||||||
this.$store.dispatch('pushGlobalNotice', {
|
useInterfaceStore().pushGlobalNotice({
|
||||||
level: 'warning',
|
level: 'warning',
|
||||||
messageKey: 'settings.file_export_import.errors.file_slightly_new'
|
messageKey: 'settings.file_export_import.errors.file_slightly_new'
|
||||||
})
|
})
|
||||||
|
@ -119,9 +121,9 @@ const SettingsModal = {
|
||||||
},
|
},
|
||||||
onImportFailure (result) {
|
onImportFailure (result) {
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
this.$store.dispatch('pushGlobalNotice', { messageKey: 'settings.invalid_settings_imported', level: 'error' })
|
useInterfaceStore().pushGlobalNotice({ messageKey: 'settings.invalid_settings_imported', level: 'error' })
|
||||||
} else {
|
} else {
|
||||||
this.$store.dispatch('pushGlobalNotice', { ...result.validationResult, level: 'error' })
|
useInterfaceStore().pushGlobalNotice({ ...result.validationResult, level: 'error' })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onImport (data) {
|
onImport (data) {
|
||||||
|
@ -166,24 +168,15 @@ const SettingsModal = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
currentSaveStateNotice () {
|
...mapPiniaState(useInterfaceStore, {
|
||||||
return this.$store.state.interface.settings.currentSaveStateNotice
|
temporaryChangesTimeoutId: store => store.layoutType === 'mobile',
|
||||||
},
|
currentSaveStateNotice: store => store.settings.currentSaveStateNotice,
|
||||||
modalActivated () {
|
modalActivated: store => store.settingsModalState !== 'hidden',
|
||||||
return this.$store.state.interface.settingsModalState !== 'hidden'
|
modalMode: store => store.settingsModalMode,
|
||||||
},
|
modalOpenedOnceUser: store => store.settingsModalLoadedUser,
|
||||||
modalMode () {
|
modalOpenedOnceAdmin: store => store.settingsModalLoadedAdmin,
|
||||||
return this.$store.state.interface.settingsModalMode
|
modalPeeked: store => store.settingsModalState === 'minimized'
|
||||||
},
|
}),
|
||||||
modalOpenedOnceUser () {
|
|
||||||
return this.$store.state.interface.settingsModalLoadedUser
|
|
||||||
},
|
|
||||||
modalOpenedOnceAdmin () {
|
|
||||||
return this.$store.state.interface.settingsModalLoadedAdmin
|
|
||||||
},
|
|
||||||
modalPeeked () {
|
|
||||||
return this.$store.state.interface.settingsModalState === 'minimized'
|
|
||||||
},
|
|
||||||
expertLevel: {
|
expertLevel: {
|
||||||
get () {
|
get () {
|
||||||
return this.$store.state.config.expertLevel > 0
|
return this.$store.state.config.expertLevel > 0
|
||||||
|
|
|
@ -158,7 +158,7 @@
|
||||||
</div>
|
</div>
|
||||||
<teleport to="#modal">
|
<teleport to="#modal">
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
v-if="$store.state.interface.temporaryChangesTimeoutId"
|
v-if="temporaryChangesTimeoutId"
|
||||||
:title="$t('settings.confirm_new_setting')"
|
:title="$t('settings.confirm_new_setting')"
|
||||||
:cancel-text="$t('settings.revert')"
|
:cancel-text="$t('settings.revert')"
|
||||||
:confirm-text="$t('settings.confirm')"
|
:confirm-text="$t('settings.confirm')"
|
||||||
|
|
|
@ -4,6 +4,7 @@ import InstanceTab from './admin_tabs/instance_tab.vue'
|
||||||
import LimitsTab from './admin_tabs/limits_tab.vue'
|
import LimitsTab from './admin_tabs/limits_tab.vue'
|
||||||
import FrontendsTab from './admin_tabs/frontends_tab.vue'
|
import FrontendsTab from './admin_tabs/frontends_tab.vue'
|
||||||
import EmojiTab from './admin_tabs/emoji_tab.vue'
|
import EmojiTab from './admin_tabs/emoji_tab.vue'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
|
@ -45,10 +46,10 @@ const SettingsModalAdminContent = {
|
||||||
return !!this.$store.state.users.currentUser
|
return !!this.$store.state.users.currentUser
|
||||||
},
|
},
|
||||||
open () {
|
open () {
|
||||||
return this.$store.state.interface.settingsModalState !== 'hidden'
|
return useInterfaceStore().settingsModalState !== 'hidden'
|
||||||
},
|
},
|
||||||
bodyLock () {
|
bodyLock () {
|
||||||
return this.$store.state.interface.settingsModalState === 'visible'
|
return useInterfaceStore().settingsModalState === 'visible'
|
||||||
},
|
},
|
||||||
adminDbLoaded () {
|
adminDbLoaded () {
|
||||||
return this.$store.state.adminSettings.loaded
|
return this.$store.state.adminSettings.loaded
|
||||||
|
@ -67,7 +68,7 @@ const SettingsModalAdminContent = {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onOpen () {
|
onOpen () {
|
||||||
const targetTab = this.$store.state.interface.settingsModalTargetTab
|
const targetTab = useInterfaceStore().settingsModalTargetTab
|
||||||
// We're being told to open in specific tab
|
// We're being told to open in specific tab
|
||||||
if (targetTab) {
|
if (targetTab) {
|
||||||
const tabIndex = this.$refs.tabSwitcher.$slots.default().findIndex(elm => {
|
const tabIndex = this.$refs.tabSwitcher.$slots.default().findIndex(elm => {
|
||||||
|
@ -79,7 +80,7 @@ const SettingsModalAdminContent = {
|
||||||
}
|
}
|
||||||
// Clear the state of target tab, so that next time settings is opened
|
// Clear the state of target tab, so that next time settings is opened
|
||||||
// it doesn't force it.
|
// it doesn't force it.
|
||||||
this.$store.dispatch('clearSettingsModalTargetTab')
|
useInterfaceStore().clearSettingsModalTargetTab()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {
|
||||||
faInfo,
|
faInfo,
|
||||||
faWindowRestore
|
faWindowRestore
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faWrench,
|
faWrench,
|
||||||
|
@ -60,21 +61,21 @@ const SettingsModalContent = {
|
||||||
return !!this.$store.state.users.currentUser
|
return !!this.$store.state.users.currentUser
|
||||||
},
|
},
|
||||||
open () {
|
open () {
|
||||||
return this.$store.state.interface.settingsModalState !== 'hidden'
|
return useInterfaceStore().settingsModalState !== 'hidden'
|
||||||
},
|
},
|
||||||
bodyLock () {
|
bodyLock () {
|
||||||
return this.$store.state.interface.settingsModalState === 'visible'
|
return useInterfaceStore().settingsModalState === 'visible'
|
||||||
},
|
},
|
||||||
expertLevel () {
|
expertLevel () {
|
||||||
return this.$store.state.config.expertLevel
|
return this.$store.state.config.expertLevel
|
||||||
},
|
},
|
||||||
isMobileLayout () {
|
isMobileLayout () {
|
||||||
return this.$store.state.interface.layoutType === 'mobile'
|
return useInterfaceStore().layoutType === 'mobile'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onOpen () {
|
onOpen () {
|
||||||
const targetTab = this.$store.state.interface.settingsModalTargetTab
|
const targetTab = useInterfaceStore().settingsModalTargetTab
|
||||||
// We're being told to open in specific tab
|
// We're being told to open in specific tab
|
||||||
if (targetTab) {
|
if (targetTab) {
|
||||||
const tabIndex = this.$refs.tabSwitcher.$slots.default().findIndex(elm => {
|
const tabIndex = this.$refs.tabSwitcher.$slots.default().findIndex(elm => {
|
||||||
|
@ -86,7 +87,7 @@ const SettingsModalContent = {
|
||||||
}
|
}
|
||||||
// Clear the state of target tab, so that next time settings is opened
|
// Clear the state of target tab, so that next time settings is opened
|
||||||
// it doesn't force it.
|
// it doesn't force it.
|
||||||
this.$store.dispatch('clearSettingsModalTargetTab')
|
useInterfaceStore().clearSettingsModalTargetTab()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
|
|
@ -4,11 +4,9 @@ import IntegerSetting from '../helpers/integer_setting.vue'
|
||||||
import FloatSetting from '../helpers/float_setting.vue'
|
import FloatSetting from '../helpers/float_setting.vue'
|
||||||
import UnitSetting, { defaultHorizontalUnits } from '../helpers/unit_setting.vue'
|
import UnitSetting, { defaultHorizontalUnits } from '../helpers/unit_setting.vue'
|
||||||
import PaletteEditor from 'src/components/palette_editor/palette_editor.vue'
|
import PaletteEditor from 'src/components/palette_editor/palette_editor.vue'
|
||||||
|
import Preview from './theme_tab/theme_preview.vue'
|
||||||
import FontControl from 'src/components/font_control/font_control.vue'
|
import FontControl from 'src/components/font_control/font_control.vue'
|
||||||
|
|
||||||
import { normalizeThemeData } from 'src/modules/interface'
|
|
||||||
|
|
||||||
import { newImporter } from 'src/services/export_import/export_import.js'
|
import { newImporter } from 'src/services/export_import/export_import.js'
|
||||||
import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
|
import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
|
||||||
import { init } from 'src/services/theme_data/theme_data_3.service.js'
|
import { init } from 'src/services/theme_data/theme_data_3.service.js'
|
||||||
|
@ -20,17 +18,15 @@ import { deserialize } from 'src/services/theme_data/iss_deserializer.js'
|
||||||
|
|
||||||
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
||||||
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
|
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
|
||||||
|
|
||||||
|
import { mapActions } from 'pinia'
|
||||||
|
import { useInterfaceStore, normalizeThemeData } from 'src/stores/interface'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faGlobe
|
faGlobe
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
import Preview from './theme_tab/theme_preview.vue'
|
|
||||||
|
|
||||||
// helper for debugging
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const toValue = (x) => JSON.parse(JSON.stringify(x === undefined ? 'null' : x))
|
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faGlobe
|
faGlobe
|
||||||
)
|
)
|
||||||
|
@ -90,7 +86,7 @@ const AppearanceTab = {
|
||||||
PaletteEditor
|
PaletteEditor
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$store.dispatch('getThemeData')
|
useInterfaceStore().getThemeData()
|
||||||
|
|
||||||
const updateIndex = (resource) => {
|
const updateIndex = (resource) => {
|
||||||
const capitalizedResource = resource[0].toUpperCase() + resource.slice(1)
|
const capitalizedResource = resource[0].toUpperCase() + resource.slice(1)
|
||||||
|
@ -100,7 +96,7 @@ const AppearanceTab = {
|
||||||
if (currentIndex) {
|
if (currentIndex) {
|
||||||
promise = Promise.resolve(currentIndex)
|
promise = Promise.resolve(currentIndex)
|
||||||
} else {
|
} else {
|
||||||
promise = this.$store.dispatch(`fetch${capitalizedResource}sIndex`)
|
promise = useInterfaceStore()[`fetch${capitalizedResource}sIndex`]()
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise.then(index => {
|
return promise.then(index => {
|
||||||
|
@ -131,7 +127,7 @@ const AppearanceTab = {
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
this.userPalette = this.$store.state.interface.paletteDataUsed || {}
|
this.userPalette = useInterfaceStore().paletteDataUsed || {}
|
||||||
|
|
||||||
updateIndex('palette').then(bundledPalettes => {
|
updateIndex('palette').then(bundledPalettes => {
|
||||||
bundledPalettes.forEach(([key, palettePromise]) => palettePromise.then(v => {
|
bundledPalettes.forEach(([key, palettePromise]) => palettePromise.then(v => {
|
||||||
|
@ -187,10 +183,10 @@ const AppearanceTab = {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
switchInProgress () {
|
switchInProgress () {
|
||||||
return this.$store.state.interface.themeChangeInProgress
|
return useInterfaceStore().themeChangeInProgress
|
||||||
},
|
},
|
||||||
paletteDataUsed () {
|
paletteDataUsed () {
|
||||||
return this.$store.state.interface.paletteDataUsed
|
return useInterfaceStore().paletteDataUsed
|
||||||
},
|
},
|
||||||
availableStyles () {
|
availableStyles () {
|
||||||
return [
|
return [
|
||||||
|
@ -205,7 +201,7 @@ const AppearanceTab = {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
stylePalettes () {
|
stylePalettes () {
|
||||||
const ruleset = this.$store.state.interface.styleDataUsed || []
|
const ruleset = useInterfaceStore().styleDataUsed || []
|
||||||
if (!ruleset && ruleset.length === 0) return
|
if (!ruleset && ruleset.length === 0) return
|
||||||
const meta = ruleset.find(x => x.component === '@meta')
|
const meta = ruleset.find(x => x.component === '@meta')
|
||||||
const result = ruleset.filter(x => x.component.startsWith('@palette'))
|
const result = ruleset.filter(x => x.component.startsWith('@palette'))
|
||||||
|
@ -273,7 +269,7 @@ const AppearanceTab = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
customThemeVersion () {
|
customThemeVersion () {
|
||||||
const { themeVersion } = this.$store.state.interface
|
const { themeVersion } = useInterfaceStore()
|
||||||
return themeVersion
|
return themeVersion
|
||||||
},
|
},
|
||||||
isCustomThemeUsed () {
|
isCustomThemeUsed () {
|
||||||
|
@ -311,14 +307,14 @@ const AppearanceTab = {
|
||||||
},
|
},
|
||||||
onImport (parsed, filename) {
|
onImport (parsed, filename) {
|
||||||
if (filename.endsWith('.json')) {
|
if (filename.endsWith('.json')) {
|
||||||
this.$store.dispatch('setThemeCustom', parsed.source || parsed.theme)
|
useInterfaceStore().setThemeCustom(parsed.source || parsed.theme)
|
||||||
} else if (filename.endsWith('.iss')) {
|
} else if (filename.endsWith('.iss')) {
|
||||||
this.$store.dispatch('setStyleCustom', parsed)
|
useInterfaceStore().setStyleCustom(parsed)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onImportFailure (result) {
|
onImportFailure (result) {
|
||||||
console.error('Failure importing theme:', result)
|
console.error('Failure importing theme:', result)
|
||||||
this.$store.dispatch('pushGlobalNotice', { messageKey: 'settings.invalid_theme_imported', level: 'error' })
|
this.$store.useInterfaceStore().pushGlobalNotice({ messageKey: 'settings.invalid_theme_imported', level: 'error' })
|
||||||
},
|
},
|
||||||
importValidator (parsed, filename) {
|
importValidator (parsed, filename) {
|
||||||
if (filename.endsWith('.json')) {
|
if (filename.endsWith('.json')) {
|
||||||
|
@ -340,22 +336,20 @@ const AppearanceTab = {
|
||||||
isPaletteActive (key) {
|
isPaletteActive (key) {
|
||||||
return key === (this.mergedConfig.palette || this.$store.state.instance.palette)
|
return key === (this.mergedConfig.palette || this.$store.state.instance.palette)
|
||||||
},
|
},
|
||||||
setStyle (name) {
|
...mapActions(useInterfaceStore, [
|
||||||
this.$store.dispatch('setStyle', name)
|
'setStyle',
|
||||||
},
|
'setTheme'
|
||||||
setTheme (name) {
|
]),
|
||||||
this.$store.dispatch('setTheme', name)
|
|
||||||
},
|
|
||||||
setPalette (name, data) {
|
setPalette (name, data) {
|
||||||
this.$store.dispatch('setPalette', name)
|
useInterfaceStore().setPalette(name)
|
||||||
this.userPalette = data
|
this.userPalette = data
|
||||||
},
|
},
|
||||||
setPaletteCustom (data) {
|
setPaletteCustom (data) {
|
||||||
this.$store.dispatch('setPaletteCustom', data)
|
useInterfaceStore().setPaletteCustom(data)
|
||||||
this.userPalette = data
|
this.userPalette = data
|
||||||
},
|
},
|
||||||
resetTheming (name) {
|
resetTheming (name) {
|
||||||
this.$store.dispatch('setStyle', 'stock')
|
useInterfaceStore().setStyle('stock')
|
||||||
},
|
},
|
||||||
previewTheme (key, version, input) {
|
previewTheme (key, version, input) {
|
||||||
let theme3
|
let theme3
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
faPlus,
|
faPlus,
|
||||||
faCircleNotch
|
faCircleNotch
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faTimes,
|
faTimes,
|
||||||
|
@ -175,7 +176,7 @@ const ProfileTab = {
|
||||||
if (file.size > this.$store.state.instance[slot + 'limit']) {
|
if (file.size > this.$store.state.instance[slot + 'limit']) {
|
||||||
const filesize = fileSizeFormatService.fileSizeFormat(file.size)
|
const filesize = fileSizeFormatService.fileSizeFormat(file.size)
|
||||||
const allowedsize = fileSizeFormatService.fileSizeFormat(this.$store.state.instance[slot + 'limit'])
|
const allowedsize = fileSizeFormatService.fileSizeFormat(this.$store.state.instance[slot + 'limit'])
|
||||||
this.$store.dispatch('pushGlobalNotice', {
|
useInterfaceStore().pushGlobalNotice({
|
||||||
messageKey: 'upload.error.message',
|
messageKey: 'upload.error.message',
|
||||||
messageArgs: [
|
messageArgs: [
|
||||||
this.$t('upload.error.file_too_big', {
|
this.$t('upload.error.file_too_big', {
|
||||||
|
@ -266,7 +267,7 @@ const ProfileTab = {
|
||||||
.finally(() => { this.backgroundUploading = false })
|
.finally(() => { this.backgroundUploading = false })
|
||||||
},
|
},
|
||||||
displayUploadError (error) {
|
displayUploadError (error) {
|
||||||
this.$store.dispatch('pushGlobalNotice', {
|
useInterfaceStore().pushGlobalNotice({
|
||||||
messageKey: 'upload.error.message',
|
messageKey: 'upload.error.message',
|
||||||
messageArgs: [error.message],
|
messageArgs: [error.message],
|
||||||
level: 'error'
|
level: 'error'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ref, reactive, computed, watch, watchEffect, provide, getCurrentInstance } from 'vue'
|
import { ref, reactive, computed, watch, watchEffect, provide, getCurrentInstance } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
import { get, set, unset, throttle } from 'lodash'
|
import { get, set, unset, throttle } from 'lodash'
|
||||||
|
|
||||||
import Select from 'src/components/select/select.vue'
|
import Select from 'src/components/select/select.vue'
|
||||||
|
@ -80,13 +80,13 @@ export default {
|
||||||
},
|
},
|
||||||
setup (props, context) {
|
setup (props, context) {
|
||||||
const exports = {}
|
const exports = {}
|
||||||
const store = useStore()
|
const interfaceStore = useInterfaceStore()
|
||||||
// All rules that are made by editor
|
// All rules that are made by editor
|
||||||
const allEditedRules = ref(store.state.interface.styleDataUsed || {})
|
const allEditedRules = ref(interfaceStore.styleDataUsed || {})
|
||||||
const styleDataUsed = computed(() => store.state.interface.styleDataUsed)
|
const styleDataUsed = computed(() => interfaceStore.styleDataUsed)
|
||||||
|
|
||||||
watch([styleDataUsed], (value) => {
|
watch([styleDataUsed], (value) => {
|
||||||
onImport(store.state.interface.styleDataUsed)
|
onImport(interfaceStore.styleDataUsed)
|
||||||
}, { once: true })
|
}, { once: true })
|
||||||
|
|
||||||
exports.isActive = computed(() => {
|
exports.isActive = computed(() => {
|
||||||
|
@ -640,7 +640,7 @@ export default {
|
||||||
parser (string) { return deserialize(string) },
|
parser (string) { return deserialize(string) },
|
||||||
onImportFailure (result) {
|
onImportFailure (result) {
|
||||||
console.error('Failure importing style:', result)
|
console.error('Failure importing style:', result)
|
||||||
this.$store.dispatch('pushGlobalNotice', { messageKey: 'settings.invalid_theme_imported', level: 'error' })
|
this.$store.useInterfaceStore().pushGlobalNotice({ messageKey: 'settings.invalid_theme_imported', level: 'error' })
|
||||||
},
|
},
|
||||||
onImport
|
onImport
|
||||||
})
|
})
|
||||||
|
@ -664,7 +664,7 @@ export default {
|
||||||
})
|
})
|
||||||
|
|
||||||
exports.clearStyle = () => {
|
exports.clearStyle = () => {
|
||||||
onImport(store.state.interface.styleDataUsed)
|
onImport(interfaceStore().styleDataUsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.exportStyle = () => {
|
exports.exportStyle = () => {
|
||||||
|
@ -676,7 +676,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.applyStyle = () => {
|
exports.applyStyle = () => {
|
||||||
store.dispatch('setStyleCustom', exportRules.value)
|
useInterfaceStore().setStyleCustom(exportRules.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const overallPreviewRules = ref([])
|
const overallPreviewRules = ref([])
|
||||||
|
|
|
@ -43,6 +43,7 @@ import Checkbox from 'src/components/checkbox/checkbox.vue'
|
||||||
import Select from 'src/components/select/select.vue'
|
import Select from 'src/components/select/select.vue'
|
||||||
|
|
||||||
import Preview from './theme_preview.vue'
|
import Preview from './theme_preview.vue'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
// List of color values used in v1
|
// List of color values used in v1
|
||||||
const v1OnlyNames = [
|
const v1OnlyNames = [
|
||||||
|
@ -126,7 +127,7 @@ export default {
|
||||||
if (currentIndex) {
|
if (currentIndex) {
|
||||||
promise = Promise.resolve(currentIndex)
|
promise = Promise.resolve(currentIndex)
|
||||||
} else {
|
} else {
|
||||||
promise = this.$store.dispatch('fetchThemesIndex')
|
promise = useInterfaceStore().fetchThemesIndex()
|
||||||
}
|
}
|
||||||
|
|
||||||
promise.then(themesIndex => {
|
promise.then(themesIndex => {
|
||||||
|
@ -296,7 +297,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
themeDataUsed () {
|
themeDataUsed () {
|
||||||
return this.$store.state.interface.themeDataUsed
|
return useInterfaceStore().themeDataUsed
|
||||||
},
|
},
|
||||||
shadowsAvailable () {
|
shadowsAvailable () {
|
||||||
return Object.keys(DEFAULT_SHADOWS).sort()
|
return Object.keys(DEFAULT_SHADOWS).sort()
|
||||||
|
@ -492,7 +493,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setCustomTheme () {
|
setCustomTheme () {
|
||||||
this.$store.dispatch('setThemeV2', {
|
useInterfaceStore().setThemeV2({
|
||||||
customTheme: {
|
customTheme: {
|
||||||
ignore: true,
|
ignore: true,
|
||||||
themeFileVersion: this.selectedVersion,
|
themeFileVersion: this.selectedVersion,
|
||||||
|
@ -536,7 +537,7 @@ export default {
|
||||||
this.loadTheme(parsed, 'file', forceSource)
|
this.loadTheme(parsed, 'file', forceSource)
|
||||||
},
|
},
|
||||||
onImportFailure (result) {
|
onImportFailure (result) {
|
||||||
this.$store.dispatch('pushGlobalNotice', { messageKey: 'settings.invalid_theme_imported', level: 'error' })
|
useInterfaceStore().pushGlobalNotice({ messageKey: 'settings.invalid_theme_imported', level: 'error' })
|
||||||
},
|
},
|
||||||
importValidator (parsed) {
|
importValidator (parsed) {
|
||||||
const version = parsed._pleroma_theme_version
|
const version = parsed._pleroma_theme_version
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
faBullhorn,
|
faBullhorn,
|
||||||
faTimes
|
faTimes
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useShoutStore } from 'src/stores/shout'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faBullhorn,
|
faBullhorn,
|
||||||
|
@ -21,12 +22,12 @@ const shoutPanel = {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
messages () {
|
messages () {
|
||||||
return this.$store.state.shout.messages
|
return useShoutStore().messages
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
submit (message) {
|
submit (message) {
|
||||||
this.$store.state.shout.channel.push('new_msg', { text: message }, 10000)
|
useShoutStore().channel.push('new_msg', { text: message }, 10000)
|
||||||
this.currentMessage = ''
|
this.currentMessage = ''
|
||||||
},
|
},
|
||||||
togglePanel () {
|
togglePanel () {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { mapState, mapGetters } from 'vuex'
|
import { mapState, mapGetters } from 'vuex'
|
||||||
|
import { mapState as mapPiniaState } from 'pinia'
|
||||||
import UserCard from '../user_card/user_card.vue'
|
import UserCard from '../user_card/user_card.vue'
|
||||||
import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils'
|
import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils'
|
||||||
import GestureService from '../../services/gesture_service/gesture_service'
|
import GestureService from '../../services/gesture_service/gesture_service'
|
||||||
|
@ -20,6 +21,9 @@ import {
|
||||||
faList,
|
faList,
|
||||||
faFilePen
|
faFilePen
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useShoutStore } from 'src/stores/shout'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
import { useAnnouncementsStore } from 'src/stores/announcements'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faSignInAlt,
|
faSignInAlt,
|
||||||
|
@ -56,7 +60,7 @@ const SideDrawer = {
|
||||||
currentUser () {
|
currentUser () {
|
||||||
return this.$store.state.users.currentUser
|
return this.$store.state.users.currentUser
|
||||||
},
|
},
|
||||||
shout () { return this.$store.state.shout.joined },
|
shout () { return useShoutStore().joined },
|
||||||
unseenNotifications () {
|
unseenNotifications () {
|
||||||
return unseenNotificationsFromStore(this.$store)
|
return unseenNotificationsFromStore(this.$store)
|
||||||
},
|
},
|
||||||
|
@ -86,8 +90,8 @@ const SideDrawer = {
|
||||||
},
|
},
|
||||||
timelinesRoute () {
|
timelinesRoute () {
|
||||||
let name
|
let name
|
||||||
if (this.$store.state.interface.lastTimeline) {
|
if (useInterfaceStore().lastTimeline) {
|
||||||
name = this.$store.state.interface.lastTimeline
|
name = useInterfaceStore().lastTimeline
|
||||||
}
|
}
|
||||||
name = this.currentUser ? 'friends' : 'public-timeline'
|
name = this.currentUser ? 'friends' : 'public-timeline'
|
||||||
if (USERNAME_ROUTES.has(name)) {
|
if (USERNAME_ROUTES.has(name)) {
|
||||||
|
@ -96,11 +100,14 @@ const SideDrawer = {
|
||||||
return { name }
|
return { name }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
...mapState({
|
...mapPiniaState(useAnnouncementsStore, {
|
||||||
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable,
|
supportsAnnouncements: store => store.supportsAnnouncements,
|
||||||
supportsAnnouncements: state => state.announcements.supportsAnnouncements
|
unreadAnnouncementCount: 'unreadAnnouncementCount'
|
||||||
}),
|
}),
|
||||||
...mapGetters(['unreadChatCount', 'unreadAnnouncementCount', 'draftCount'])
|
...mapState({
|
||||||
|
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable
|
||||||
|
}),
|
||||||
|
...mapGetters(['unreadChatCount', 'draftCount'])
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggleDrawer () {
|
toggleDrawer () {
|
||||||
|
@ -117,10 +124,10 @@ const SideDrawer = {
|
||||||
GestureService.updateSwipe(e, this.closeGesture)
|
GestureService.updateSwipe(e, this.closeGesture)
|
||||||
},
|
},
|
||||||
openSettingsModal () {
|
openSettingsModal () {
|
||||||
this.$store.dispatch('openSettingsModal', 'user')
|
useInterfaceStore().openSettingsModal('user')
|
||||||
},
|
},
|
||||||
openAdminModal () {
|
openAdminModal () {
|
||||||
this.$store.dispatch('openSettingsModal', 'admin')
|
useInterfaceStore().openSettingsModal('admin')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
faLink,
|
faLink,
|
||||||
faPollH
|
faPollH
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useMediaViewerStore } from 'src/stores/media_viewer'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faCircleNotch,
|
faCircleNotch,
|
||||||
|
@ -130,7 +131,7 @@ const StatusContent = {
|
||||||
},
|
},
|
||||||
setMedia () {
|
setMedia () {
|
||||||
const attachments = this.attachmentSize === 'hide' ? this.status.attachments : this.galleryAttachments
|
const attachments = this.attachmentSize === 'hide' ? this.status.attachments : this.galleryAttachments
|
||||||
return () => this.$store.dispatch('setMedia', attachments)
|
return () => useMediaViewerStore().setMedia(attachments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { get } from 'lodash'
|
import { get } from 'lodash'
|
||||||
import Modal from '../modal/modal.vue'
|
import Modal from '../modal/modal.vue'
|
||||||
import Status from '../status/status.vue'
|
import Status from '../status/status.vue'
|
||||||
|
import { useStatusHistoryStore } from 'src/stores/statusHistory'
|
||||||
|
|
||||||
const StatusHistoryModal = {
|
const StatusHistoryModal = {
|
||||||
components: {
|
components: {
|
||||||
|
@ -14,10 +15,10 @@ const StatusHistoryModal = {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
modalActivated () {
|
modalActivated () {
|
||||||
return this.$store.state.statusHistory.modalActivated
|
return useStatusHistoryStore().modalActivated
|
||||||
},
|
},
|
||||||
params () {
|
params () {
|
||||||
return this.$store.state.statusHistory.params
|
return useStatusHistoryStore().params
|
||||||
},
|
},
|
||||||
statusId () {
|
statusId () {
|
||||||
return this.params.id
|
return this.params.id
|
||||||
|
@ -52,7 +53,7 @@ const StatusHistoryModal = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
closeModal () {
|
closeModal () {
|
||||||
this.$store.dispatch('closeStatusHistoryModal')
|
useStatusHistoryStore().closeStatusHistoryModal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
// eslint-disable-next-line no-unused
|
// eslint-disable-next-line no-unused
|
||||||
import { h, Fragment } from 'vue'
|
import { h, Fragment } from 'vue'
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'pinia'
|
||||||
import { FontAwesomeIcon as FAIcon } from '@fortawesome/vue-fontawesome'
|
import { FontAwesomeIcon as FAIcon } from '@fortawesome/vue-fontawesome'
|
||||||
|
|
||||||
import './tab_switcher.scss'
|
import './tab_switcher.scss'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
const findFirstUsable = (slots) => slots.findIndex(_ => _.props)
|
const findFirstUsable = (slots) => slots.findIndex(_ => _.props)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import Status from '../status/status.vue'
|
import Status from '../status/status.vue'
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'pinia'
|
||||||
import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js'
|
import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js'
|
||||||
import Conversation from '../conversation/conversation.vue'
|
import Conversation from '../conversation/conversation.vue'
|
||||||
import TimelineMenu from '../timeline_menu/timeline_menu.vue'
|
import TimelineMenu from '../timeline_menu/timeline_menu.vue'
|
||||||
|
@ -8,6 +8,7 @@ import QuickViewSettings from '../quick_view_settings/quick_view_settings.vue'
|
||||||
import { debounce, throttle, keyBy } from 'lodash'
|
import { debounce, throttle, keyBy } from 'lodash'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faCircleNotch, faCirclePlus, faCog, faMinus, faArrowUp, faCheck } from '@fortawesome/free-solid-svg-icons'
|
import { faCircleNotch, faCirclePlus, faCog, faMinus, faArrowUp, faCheck } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faCircleNotch,
|
faCircleNotch,
|
||||||
|
@ -103,8 +104,8 @@ const Timeline = {
|
||||||
virtualScrollingEnabled () {
|
virtualScrollingEnabled () {
|
||||||
return this.$store.getters.mergedConfig.virtualScrolling
|
return this.$store.getters.mergedConfig.virtualScrolling
|
||||||
},
|
},
|
||||||
...mapState({
|
...mapState(useInterfaceStore, {
|
||||||
mobileLayout: state => state.interface.layoutType === 'mobile'
|
mobileLayout: store => store.layoutType === 'mobile'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
|
|
|
@ -9,6 +9,8 @@ import { filterNavigation } from 'src/components/navigation/filter.js'
|
||||||
import {
|
import {
|
||||||
faChevronDown
|
faChevronDown
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
import { useListsStore } from 'src/stores/lists'
|
||||||
|
|
||||||
library.add(faChevronDown)
|
library.add(faChevronDown)
|
||||||
|
|
||||||
|
@ -39,7 +41,7 @@ const TimelineMenu = {
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
if (timelineNames(this.bookmarkFolders)[this.$route.name]) {
|
if (timelineNames(this.bookmarkFolders)[this.$route.name]) {
|
||||||
this.$store.dispatch('setLastTimeline', this.$route.name)
|
useInterfaceStore().setLastTimeline(this.$route.name)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -95,7 +97,7 @@ const TimelineMenu = {
|
||||||
return '#' + this.$route.params.tag
|
return '#' + this.$route.params.tag
|
||||||
}
|
}
|
||||||
if (route === 'lists-timeline') {
|
if (route === 'lists-timeline') {
|
||||||
return this.$store.getters.findListTitle(this.$route.params.id)
|
return useListsStore().findListTitle(this.$route.params.id)
|
||||||
}
|
}
|
||||||
if (route === 'bookmark-folder') {
|
if (route === 'bookmark-folder') {
|
||||||
return this.$store.getters.findBookmarkFolderName(this.$route.params.id)
|
return this.$store.getters.findBookmarkFolderName(this.$route.params.id)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import StillImage from '../still-image/still-image.vue'
|
import StillImage from '../still-image/still-image.vue'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
|
|
||||||
|
@ -22,7 +23,7 @@ const UserAvatar = {
|
||||||
return {
|
return {
|
||||||
showPlaceholder: false,
|
showPlaceholder: false,
|
||||||
defaultAvatar: `${this.$store.state.instance.server + this.$store.state.instance.defaultAvatar}`,
|
defaultAvatar: `${this.$store.state.instance.server + this.$store.state.instance.defaultAvatar}`,
|
||||||
betterShadow: this.$store.state.interface.browserSupport.cssFilter
|
betterShadow: useInterfaceStore().browserSupport.cssFilter
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
import MuteConfirm from '../confirm_modal/mute_confirm.vue'
|
import MuteConfirm from '../confirm_modal/mute_confirm.vue'
|
||||||
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
|
import { usePostStatusStore } from 'src/stores/postStatus'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faBell,
|
faBell,
|
||||||
|
@ -22,6 +23,9 @@ import {
|
||||||
faExpandAlt
|
faExpandAlt
|
||||||
} from '@fortawesome/free-solid-svg-icons'
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
import { useMediaViewerStore } from '../../stores/media_viewer'
|
||||||
|
import { useInterfaceStore } from '../../stores/interface'
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
faRss,
|
faRss,
|
||||||
faBell,
|
faBell,
|
||||||
|
@ -188,18 +192,18 @@ export default {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
openProfileTab () {
|
openProfileTab () {
|
||||||
this.$store.dispatch('openSettingsModalTab', 'profile')
|
useInterfaceStore().openSettingsModalTab('profile')
|
||||||
},
|
},
|
||||||
zoomAvatar () {
|
zoomAvatar () {
|
||||||
const attachment = {
|
const attachment = {
|
||||||
url: this.user.profile_image_url_original,
|
url: this.user.profile_image_url_original,
|
||||||
mimetype: 'image'
|
mimetype: 'image'
|
||||||
}
|
}
|
||||||
this.$store.dispatch('setMedia', [attachment])
|
useMediaViewerStore().setMedia([attachment])
|
||||||
this.$store.dispatch('setCurrentMedia', attachment)
|
useMediaViewerStore().setCurrentMedia(attachment)
|
||||||
},
|
},
|
||||||
mentionUser () {
|
mentionUser () {
|
||||||
this.$store.dispatch('openPostStatusModal', { profileMention: true, repliedUser: this.user })
|
usePostStatusStore().openPostStatusModal({ profileMention: true, repliedUser: this.user })
|
||||||
},
|
},
|
||||||
onAvatarClickHandler (e) {
|
onAvatarClickHandler (e) {
|
||||||
if (this.onAvatarClick) {
|
if (this.onAvatarClick) {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faChevronRight } from '@fortawesome/free-solid-svg-icons'
|
import { faChevronRight } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { mapState } from 'vuex'
|
import { mapState } from 'pinia'
|
||||||
|
|
||||||
import DialogModal from '../dialog_modal/dialog_modal.vue'
|
import DialogModal from '../dialog_modal/dialog_modal.vue'
|
||||||
import Popover from '../popover/popover.vue'
|
import Popover from '../popover/popover.vue'
|
||||||
|
import { useListsStore } from 'src/stores/lists'
|
||||||
|
|
||||||
library.add(faChevronRight)
|
library.add(faChevronRight)
|
||||||
|
|
||||||
|
@ -22,8 +23,8 @@ const UserListMenu = {
|
||||||
this.$store.dispatch('fetchUserInLists', this.user.id)
|
this.$store.dispatch('fetchUserInLists', this.user.id)
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({
|
...mapState(useListsStore, {
|
||||||
allLists: state => state.lists.allLists
|
allLists: store => store.allLists
|
||||||
}),
|
}),
|
||||||
inListsSet () {
|
inListsSet () {
|
||||||
return new Set(this.user.inLists.map(x => x.id))
|
return new Set(this.user.inLists.map(x => x.id))
|
||||||
|
@ -44,12 +45,12 @@ const UserListMenu = {
|
||||||
methods: {
|
methods: {
|
||||||
toggleList (listId) {
|
toggleList (listId) {
|
||||||
if (this.inListsSet.has(listId)) {
|
if (this.inListsSet.has(listId)) {
|
||||||
this.$store.dispatch('removeListAccount', { accountId: this.user.id, listId }).then((response) => {
|
useListsStore().removeListAccount({ accountId: this.user.id, listId }).then((response) => {
|
||||||
if (!response.ok) { return }
|
if (!response.ok) { return }
|
||||||
this.$store.dispatch('fetchUserInLists', this.user.id)
|
this.$store.dispatch('fetchUserInLists', this.user.id)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.$store.dispatch('addListAccount', { accountId: this.user.id, listId }).then((response) => {
|
useListsStore().addListAccount({ accountId: this.user.id, listId }).then((response) => {
|
||||||
if (!response.ok) { return }
|
if (!response.ok) { return }
|
||||||
this.$store.dispatch('fetchUserInLists', this.user.id)
|
this.$store.dispatch('fetchUserInLists', this.user.id)
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,6 +3,7 @@ import List from '../list/list.vue'
|
||||||
import Checkbox from '../checkbox/checkbox.vue'
|
import Checkbox from '../checkbox/checkbox.vue'
|
||||||
import Modal from '../modal/modal.vue'
|
import Modal from '../modal/modal.vue'
|
||||||
import UserLink from '../user_link/user_link.vue'
|
import UserLink from '../user_link/user_link.vue'
|
||||||
|
import { useReportsStore } from 'src/stores/reports'
|
||||||
|
|
||||||
const UserReportingModal = {
|
const UserReportingModal = {
|
||||||
components: {
|
components: {
|
||||||
|
@ -23,7 +24,7 @@ const UserReportingModal = {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
reportModal () {
|
reportModal () {
|
||||||
return this.$store.state.reports.reportModal
|
return useReportsStore().reportModal
|
||||||
},
|
},
|
||||||
isLoggedIn () {
|
isLoggedIn () {
|
||||||
return !!this.$store.state.users.currentUser
|
return !!this.$store.state.users.currentUser
|
||||||
|
@ -63,7 +64,7 @@ const UserReportingModal = {
|
||||||
this.error = false
|
this.error = false
|
||||||
},
|
},
|
||||||
closeModal () {
|
closeModal () {
|
||||||
this.$store.dispatch('closeUserReportingModal')
|
useReportsStore().closeUserReportingModal()
|
||||||
},
|
},
|
||||||
reportUser () {
|
reportUser () {
|
||||||
this.processing = true
|
this.processing = true
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import merge from 'lodash.merge'
|
import merge from 'lodash.merge'
|
||||||
import { each, get, set, cloneDeep } from 'lodash'
|
import { each, get, set, cloneDeep } from 'lodash'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
import { storage } from './storage.js'
|
import { storage } from './storage.js'
|
||||||
|
|
||||||
let loaded = false
|
let loaded = false
|
||||||
|
@ -76,12 +77,12 @@ export default function createPersistedState ({
|
||||||
.then(success => {
|
.then(success => {
|
||||||
if (typeof success !== 'undefined') {
|
if (typeof success !== 'undefined') {
|
||||||
if (mutation.type === 'setOption' || mutation.type === 'setCurrentUser') {
|
if (mutation.type === 'setOption' || mutation.type === 'setCurrentUser') {
|
||||||
store.dispatch('settingsSaved', { success })
|
useInterfaceStore().settingsSaved({ success })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, error => {
|
}, error => {
|
||||||
if (mutation.type === 'setOption' || mutation.type === 'setCurrentUser') {
|
if (mutation.type === 'setOption' || mutation.type === 'setCurrentUser') {
|
||||||
store.dispatch('settingsSaved', { error })
|
useInterfaceStore().settingsSaved({ error })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
export default (store) => {
|
export default (store) => {
|
||||||
store.subscribe((mutation, state) => {
|
store.subscribe((mutation, state) => {
|
||||||
const vapidPublicKey = state.instance.vapidPublicKey
|
const vapidPublicKey = state.instance.vapidPublicKey
|
||||||
const webPushNotification = state.config.webPushNotifications
|
const webPushNotification = state.config.webPushNotifications
|
||||||
const permission = state.interface.notificationPermission === 'granted'
|
const permission = useInterfaceStore().notificationPermission === 'granted'
|
||||||
const user = state.users.currentUser
|
const user = state.users.currentUser
|
||||||
|
|
||||||
const isUserMutation = mutation.type === 'setCurrentUser'
|
const isUserMutation = mutation.type === 'setCurrentUser'
|
||||||
|
|
34
src/main.js
34
src/main.js
|
@ -1,32 +1,23 @@
|
||||||
import { createStore } from 'vuex'
|
import { createStore } from 'vuex'
|
||||||
|
import { createPinia } from 'pinia'
|
||||||
|
|
||||||
import 'custom-event-polyfill'
|
import 'custom-event-polyfill'
|
||||||
import './lib/event_target_polyfill.js'
|
import './lib/event_target_polyfill.js'
|
||||||
|
|
||||||
import interfaceModule from './modules/interface.js'
|
|
||||||
import instanceModule from './modules/instance.js'
|
import instanceModule from './modules/instance.js'
|
||||||
import statusesModule from './modules/statuses.js'
|
import statusesModule from './modules/statuses.js'
|
||||||
import notificationsModule from './modules/notifications.js'
|
import notificationsModule from './modules/notifications.js'
|
||||||
import listsModule from './modules/lists.js'
|
|
||||||
import usersModule from './modules/users.js'
|
import usersModule from './modules/users.js'
|
||||||
import apiModule from './modules/api.js'
|
import apiModule from './modules/api.js'
|
||||||
import configModule from './modules/config.js'
|
import configModule from './modules/config.js'
|
||||||
import profileConfigModule from './modules/profileConfig.js'
|
import profileConfigModule from './modules/profileConfig.js'
|
||||||
import serverSideStorageModule from './modules/serverSideStorage.js'
|
import serverSideStorageModule from './modules/serverSideStorage.js'
|
||||||
import adminSettingsModule from './modules/adminSettings.js'
|
import adminSettingsModule from './modules/adminSettings.js'
|
||||||
import shoutModule from './modules/shout.js'
|
|
||||||
import oauthModule from './modules/oauth.js'
|
import oauthModule from './modules/oauth.js'
|
||||||
import authFlowModule from './modules/auth_flow.js'
|
import authFlowModule from './modules/auth_flow.js'
|
||||||
import mediaViewerModule from './modules/media_viewer.js'
|
|
||||||
import oauthTokensModule from './modules/oauth_tokens.js'
|
import oauthTokensModule from './modules/oauth_tokens.js'
|
||||||
import reportsModule from './modules/reports.js'
|
|
||||||
import pollsModule from './modules/polls.js'
|
|
||||||
import postStatusModule from './modules/postStatus.js'
|
|
||||||
import editStatusModule from './modules/editStatus.js'
|
|
||||||
import statusHistoryModule from './modules/statusHistory.js'
|
|
||||||
import draftsModule from './modules/drafts.js'
|
import draftsModule from './modules/drafts.js'
|
||||||
import chatsModule from './modules/chats.js'
|
import chatsModule from './modules/chats.js'
|
||||||
import announcementsModule from './modules/announcements.js'
|
|
||||||
import bookmarkFoldersModule from './modules/bookmark_folders.js'
|
import bookmarkFoldersModule from './modules/bookmark_folders.js'
|
||||||
|
|
||||||
import { createI18n } from 'vue-i18n'
|
import { createI18n } from 'vue-i18n'
|
||||||
|
@ -85,6 +76,7 @@ const persistedStateOptions = {
|
||||||
try {
|
try {
|
||||||
let storageError
|
let storageError
|
||||||
const plugins = [pushNotifications]
|
const plugins = [pushNotifications]
|
||||||
|
const pinia = createPinia()
|
||||||
try {
|
try {
|
||||||
const persistedState = await createPersistedState(persistedStateOptions)
|
const persistedState = await createPersistedState(persistedStateOptions)
|
||||||
plugins.push(persistedState)
|
plugins.push(persistedState)
|
||||||
|
@ -98,36 +90,21 @@ const persistedStateOptions = {
|
||||||
document.querySelector('#splash-credit').textContent = i18n.global.t('update.art_by', { linkToArtist: 'pipivovott' })
|
document.querySelector('#splash-credit').textContent = i18n.global.t('update.art_by', { linkToArtist: 'pipivovott' })
|
||||||
const store = createStore({
|
const store = createStore({
|
||||||
modules: {
|
modules: {
|
||||||
i18n: {
|
|
||||||
getters: {
|
|
||||||
i18n: () => i18n.global
|
|
||||||
}
|
|
||||||
},
|
|
||||||
interface: interfaceModule,
|
|
||||||
instance: instanceModule,
|
instance: instanceModule,
|
||||||
// TODO refactor users/statuses modules, they depend on each other
|
// TODO refactor users/statuses modules, they depend on each other
|
||||||
users: usersModule,
|
users: usersModule,
|
||||||
statuses: statusesModule,
|
statuses: statusesModule,
|
||||||
notifications: notificationsModule,
|
notifications: notificationsModule,
|
||||||
lists: listsModule,
|
|
||||||
api: apiModule,
|
api: apiModule,
|
||||||
config: configModule,
|
config: configModule,
|
||||||
profileConfig: profileConfigModule,
|
profileConfig: profileConfigModule,
|
||||||
serverSideStorage: serverSideStorageModule,
|
serverSideStorage: serverSideStorageModule,
|
||||||
adminSettings: adminSettingsModule,
|
adminSettings: adminSettingsModule,
|
||||||
shout: shoutModule,
|
|
||||||
oauth: oauthModule,
|
oauth: oauthModule,
|
||||||
authFlow: authFlowModule,
|
authFlow: authFlowModule,
|
||||||
mediaViewer: mediaViewerModule,
|
|
||||||
oauthTokens: oauthTokensModule,
|
oauthTokens: oauthTokensModule,
|
||||||
reports: reportsModule,
|
|
||||||
polls: pollsModule,
|
|
||||||
postStatus: postStatusModule,
|
|
||||||
editStatus: editStatusModule,
|
|
||||||
statusHistory: statusHistoryModule,
|
|
||||||
drafts: draftsModule,
|
drafts: draftsModule,
|
||||||
chats: chatsModule,
|
chats: chatsModule,
|
||||||
announcements: announcementsModule,
|
|
||||||
bookmarkFolders: bookmarkFoldersModule
|
bookmarkFolders: bookmarkFoldersModule
|
||||||
},
|
},
|
||||||
plugins,
|
plugins,
|
||||||
|
@ -137,10 +114,9 @@ const persistedStateOptions = {
|
||||||
strict: false // Socket modifies itself, let's ignore this for now.
|
strict: false // Socket modifies itself, let's ignore this for now.
|
||||||
// strict: process.env.NODE_ENV !== 'production'
|
// strict: process.env.NODE_ENV !== 'production'
|
||||||
})
|
})
|
||||||
if (storageError) {
|
window.vuex = store
|
||||||
store.dispatch('pushGlobalNotice', { messageKey: 'errors.storage_unavailable', level: 'error' })
|
// Temporarily passing pinia and vuex stores along with storageError result until migration is fully complete.
|
||||||
}
|
return await afterStoreSetup({ pinia, store, storageError, i18n })
|
||||||
return await afterStoreSetup({ store, i18n })
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
splashError(i18n, e)
|
splashError(i18n, e)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,135 +0,0 @@
|
||||||
const FETCH_ANNOUNCEMENT_INTERVAL_MS = 1000 * 60 * 5
|
|
||||||
|
|
||||||
export const defaultState = {
|
|
||||||
announcements: [],
|
|
||||||
supportsAnnouncements: true,
|
|
||||||
fetchAnnouncementsTimer: undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
export const mutations = {
|
|
||||||
setAnnouncements (state, announcements) {
|
|
||||||
state.announcements = announcements
|
|
||||||
},
|
|
||||||
setAnnouncementRead (state, { id, read }) {
|
|
||||||
const index = state.announcements.findIndex(a => a.id === id)
|
|
||||||
|
|
||||||
if (index < 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
state.announcements[index].read = read
|
|
||||||
},
|
|
||||||
setFetchAnnouncementsTimer (state, timer) {
|
|
||||||
state.fetchAnnouncementsTimer = timer
|
|
||||||
},
|
|
||||||
setSupportsAnnouncements (state, supportsAnnouncements) {
|
|
||||||
state.supportsAnnouncements = supportsAnnouncements
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getters = {
|
|
||||||
unreadAnnouncementCount (state, _getters, rootState) {
|
|
||||||
if (!rootState.users.currentUser) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
const unread = state.announcements.filter(announcement => !(announcement.inactive || announcement.read))
|
|
||||||
return unread.length
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const announcements = {
|
|
||||||
state: defaultState,
|
|
||||||
mutations,
|
|
||||||
getters,
|
|
||||||
actions: {
|
|
||||||
fetchAnnouncements (store) {
|
|
||||||
if (!store.state.supportsAnnouncements) {
|
|
||||||
return Promise.resolve()
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentUser = store.rootState.users.currentUser
|
|
||||||
const isAdmin = currentUser && currentUser.privileges.includes('announcements_manage_announcements')
|
|
||||||
|
|
||||||
const getAnnouncements = async () => {
|
|
||||||
if (!isAdmin) {
|
|
||||||
return store.rootState.api.backendInteractor.fetchAnnouncements()
|
|
||||||
}
|
|
||||||
|
|
||||||
const all = await store.rootState.api.backendInteractor.adminFetchAnnouncements()
|
|
||||||
const visible = await store.rootState.api.backendInteractor.fetchAnnouncements()
|
|
||||||
const visibleObject = visible.reduce((a, c) => {
|
|
||||||
a[c.id] = c
|
|
||||||
return a
|
|
||||||
}, {})
|
|
||||||
const getWithinVisible = announcement => visibleObject[announcement.id]
|
|
||||||
|
|
||||||
all.forEach(announcement => {
|
|
||||||
const visibleAnnouncement = getWithinVisible(announcement)
|
|
||||||
if (!visibleAnnouncement) {
|
|
||||||
announcement.inactive = true
|
|
||||||
} else {
|
|
||||||
announcement.read = visibleAnnouncement.read
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return all
|
|
||||||
}
|
|
||||||
|
|
||||||
return getAnnouncements()
|
|
||||||
.then(announcements => {
|
|
||||||
store.commit('setAnnouncements', announcements)
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
// If and only if backend does not support announcements, it would return 404.
|
|
||||||
// In this case, silently ignores it.
|
|
||||||
if (error && error.statusCode === 404) {
|
|
||||||
store.commit('setSupportsAnnouncements', false)
|
|
||||||
} else {
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
markAnnouncementAsRead (store, id) {
|
|
||||||
return store.rootState.api.backendInteractor.dismissAnnouncement({ id })
|
|
||||||
.then(() => {
|
|
||||||
store.commit('setAnnouncementRead', { id, read: true })
|
|
||||||
})
|
|
||||||
},
|
|
||||||
startFetchingAnnouncements (store) {
|
|
||||||
if (store.state.fetchAnnouncementsTimer) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const interval = setInterval(() => store.dispatch('fetchAnnouncements'), FETCH_ANNOUNCEMENT_INTERVAL_MS)
|
|
||||||
store.commit('setFetchAnnouncementsTimer', interval)
|
|
||||||
|
|
||||||
return store.dispatch('fetchAnnouncements')
|
|
||||||
},
|
|
||||||
stopFetchingAnnouncements (store) {
|
|
||||||
const interval = store.state.fetchAnnouncementsTimer
|
|
||||||
store.commit('setFetchAnnouncementsTimer', undefined)
|
|
||||||
clearInterval(interval)
|
|
||||||
},
|
|
||||||
postAnnouncement (store, { content, startsAt, endsAt, allDay }) {
|
|
||||||
return store.rootState.api.backendInteractor.postAnnouncement({ content, startsAt, endsAt, allDay })
|
|
||||||
.then(() => {
|
|
||||||
return store.dispatch('fetchAnnouncements')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
editAnnouncement (store, { id, content, startsAt, endsAt, allDay }) {
|
|
||||||
return store.rootState.api.backendInteractor.editAnnouncement({ id, content, startsAt, endsAt, allDay })
|
|
||||||
.then(() => {
|
|
||||||
return store.dispatch('fetchAnnouncements')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
deleteAnnouncement (store, id) {
|
|
||||||
return store.rootState.api.backendInteractor.deleteAnnouncement({ id })
|
|
||||||
.then(() => {
|
|
||||||
return store.dispatch('fetchAnnouncements')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default announcements
|
|
|
@ -2,6 +2,8 @@ import backendInteractorService from '../services/backend_interactor_service/bac
|
||||||
import { WSConnectionStatus } from '../services/api/api.service.js'
|
import { WSConnectionStatus } from '../services/api/api.service.js'
|
||||||
import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js'
|
import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js'
|
||||||
import { Socket } from 'phoenix'
|
import { Socket } from 'phoenix'
|
||||||
|
import { useShoutStore } from 'src/stores/shout.js'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||||
|
|
||||||
const retryTimeout = (multiplier) => 1000 * multiplier
|
const retryTimeout = (multiplier) => 1000 * multiplier
|
||||||
|
|
||||||
|
@ -134,7 +136,7 @@ const api = {
|
||||||
state.mastoUserSocket.addEventListener('open', () => {
|
state.mastoUserSocket.addEventListener('open', () => {
|
||||||
// Do not show notification when we just opened up the page
|
// Do not show notification when we just opened up the page
|
||||||
if (state.mastoUserSocketStatus !== WSConnectionStatus.STARTING_INITIAL) {
|
if (state.mastoUserSocketStatus !== WSConnectionStatus.STARTING_INITIAL) {
|
||||||
dispatch('pushGlobalNotice', {
|
useInterfaceStore().pushGlobalNotice({
|
||||||
level: 'success',
|
level: 'success',
|
||||||
messageKey: 'timeline.socket_reconnected',
|
messageKey: 'timeline.socket_reconnected',
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
|
@ -176,7 +178,7 @@ const api = {
|
||||||
dispatch('startFetchingTimeline', { timeline: 'friends' })
|
dispatch('startFetchingTimeline', { timeline: 'friends' })
|
||||||
dispatch('startFetchingNotifications')
|
dispatch('startFetchingNotifications')
|
||||||
dispatch('startFetchingChats')
|
dispatch('startFetchingChats')
|
||||||
dispatch('pushGlobalNotice', {
|
useInterfaceStore().pushGlobalNotice({
|
||||||
level: 'error',
|
level: 'error',
|
||||||
messageKey: 'timeline.socket_broke',
|
messageKey: 'timeline.socket_broke',
|
||||||
messageArgs: [code],
|
messageArgs: [code],
|
||||||
|
@ -300,7 +302,7 @@ const api = {
|
||||||
socket.connect()
|
socket.connect()
|
||||||
|
|
||||||
commit('setSocket', socket)
|
commit('setSocket', socket)
|
||||||
dispatch('initializeShout', socket)
|
useShoutStore().initializeShout(socket)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
disconnectFromSocket ({ commit, state }) {
|
disconnectFromSocket ({ commit, state }) {
|
||||||
|
|
|
@ -3,6 +3,10 @@ import { applyConfig } from '../services/style_setter/style_setter.js'
|
||||||
import messages from '../i18n/messages'
|
import messages from '../i18n/messages'
|
||||||
import { set } from 'lodash'
|
import { set } from 'lodash'
|
||||||
import localeService from '../services/locale/locale.service.js'
|
import localeService from '../services/locale/locale.service.js'
|
||||||
|
import { useI18nStore } from 'src/stores/i18n.js'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||||
|
|
||||||
|
import { defaultState } from './default_config_state.js'
|
||||||
|
|
||||||
const BACKEND_LANGUAGE_COOKIE_NAME = 'userLanguage'
|
const BACKEND_LANGUAGE_COOKIE_NAME = 'userLanguage'
|
||||||
const APPEARANCE_SETTINGS_KEYS = new Set([
|
const APPEARANCE_SETTINGS_KEYS = new Set([
|
||||||
|
@ -17,8 +21,6 @@ const APPEARANCE_SETTINGS_KEYS = new Set([
|
||||||
'emojiReactionsScale'
|
'emojiReactionsScale'
|
||||||
])
|
])
|
||||||
|
|
||||||
const browserLocale = (window.navigator.language || 'en').split('-')[0]
|
|
||||||
|
|
||||||
/* TODO this is a bit messy.
|
/* TODO this is a bit messy.
|
||||||
* We need to declare settings with their types and also deal with
|
* We need to declare settings with their types and also deal with
|
||||||
* instance-default settings in some way, hopefully try to avoid copy-pasta
|
* instance-default settings in some way, hopefully try to avoid copy-pasta
|
||||||
|
@ -34,170 +36,6 @@ export const multiChoiceProperties = [
|
||||||
'unsavedPostAction' // save | discard | confirm
|
'unsavedPostAction' // save | discard | confirm
|
||||||
]
|
]
|
||||||
|
|
||||||
export const defaultState = {
|
|
||||||
expertLevel: 0, // used to track which settings to show and hide
|
|
||||||
|
|
||||||
// Theme stuff
|
|
||||||
theme: undefined, // Very old theme store, stores preset name, still in use
|
|
||||||
|
|
||||||
// V1
|
|
||||||
colors: {}, // VERY old theme store, just colors of V1, probably not even used anymore
|
|
||||||
|
|
||||||
// V2
|
|
||||||
customTheme: undefined, // "snapshot", previously was used as actual theme store for V2 so it's still used in case of PleromaFE downgrade event.
|
|
||||||
customThemeSource: undefined, // "source", stores original theme data
|
|
||||||
|
|
||||||
// V3
|
|
||||||
style: null,
|
|
||||||
styleCustomData: null,
|
|
||||||
palette: null,
|
|
||||||
paletteCustomData: null,
|
|
||||||
themeDebug: false, // debug mode that uses computed backgrounds instead of real ones to debug contrast functions
|
|
||||||
forceThemeRecompilation: false, // flag that forces recompilation on boot even if cache exists
|
|
||||||
theme3hacks: { // Hacks, user overrides that are independent of theme used
|
|
||||||
underlay: 'none',
|
|
||||||
fonts: {
|
|
||||||
interface: undefined,
|
|
||||||
input: undefined,
|
|
||||||
post: undefined,
|
|
||||||
monospace: undefined
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
hideISP: false,
|
|
||||||
hideInstanceWallpaper: false,
|
|
||||||
hideShoutbox: false,
|
|
||||||
// bad name: actually hides posts of muted USERS
|
|
||||||
hideMutedPosts: undefined, // instance default
|
|
||||||
hideMutedThreads: undefined, // instance default
|
|
||||||
hideWordFilteredPosts: undefined, // instance default
|
|
||||||
muteBotStatuses: undefined, // instance default
|
|
||||||
muteSensitiveStatuses: undefined, // instance default
|
|
||||||
collapseMessageWithSubject: undefined, // instance default
|
|
||||||
padEmoji: true,
|
|
||||||
hideAttachments: false,
|
|
||||||
hideAttachmentsInConv: false,
|
|
||||||
hideScrobbles: false,
|
|
||||||
hideScrobblesAfter: '2d',
|
|
||||||
maxThumbnails: 16,
|
|
||||||
hideNsfw: true,
|
|
||||||
preloadImage: true,
|
|
||||||
loopVideo: true,
|
|
||||||
loopVideoSilentOnly: true,
|
|
||||||
streaming: false,
|
|
||||||
emojiReactionsOnTimeline: true,
|
|
||||||
alwaysShowNewPostButton: false,
|
|
||||||
autohideFloatingPostButton: false,
|
|
||||||
pauseOnUnfocused: true,
|
|
||||||
stopGifs: true,
|
|
||||||
replyVisibility: 'all',
|
|
||||||
thirdColumnMode: 'notifications',
|
|
||||||
notificationVisibility: {
|
|
||||||
follows: true,
|
|
||||||
mentions: true,
|
|
||||||
statuses: true,
|
|
||||||
likes: true,
|
|
||||||
repeats: true,
|
|
||||||
moves: true,
|
|
||||||
emojiReactions: true,
|
|
||||||
followRequest: true,
|
|
||||||
reports: true,
|
|
||||||
chatMention: true,
|
|
||||||
polls: true
|
|
||||||
},
|
|
||||||
notificationNative: {
|
|
||||||
follows: true,
|
|
||||||
mentions: true,
|
|
||||||
statuses: true,
|
|
||||||
likes: false,
|
|
||||||
repeats: false,
|
|
||||||
moves: false,
|
|
||||||
emojiReactions: false,
|
|
||||||
followRequest: true,
|
|
||||||
reports: true,
|
|
||||||
chatMention: true,
|
|
||||||
polls: true
|
|
||||||
},
|
|
||||||
webPushNotifications: false,
|
|
||||||
webPushAlwaysShowNotifications: false,
|
|
||||||
muteWords: [],
|
|
||||||
highlight: {},
|
|
||||||
interfaceLanguage: browserLocale,
|
|
||||||
hideScopeNotice: false,
|
|
||||||
useStreamingApi: false,
|
|
||||||
sidebarRight: undefined, // instance default
|
|
||||||
scopeCopy: undefined, // instance default
|
|
||||||
subjectLineBehavior: undefined, // instance default
|
|
||||||
alwaysShowSubjectInput: undefined, // instance default
|
|
||||||
postContentType: undefined, // instance default
|
|
||||||
minimalScopesMode: undefined, // instance default
|
|
||||||
// This hides statuses filtered via a word filter
|
|
||||||
hideFilteredStatuses: undefined, // instance default
|
|
||||||
modalOnRepeat: undefined, // instance default
|
|
||||||
modalOnUnfollow: undefined, // instance default
|
|
||||||
modalOnBlock: undefined, // instance default
|
|
||||||
modalOnMute: undefined, // instance default
|
|
||||||
modalOnMuteConversation: undefined, // instance default
|
|
||||||
modalOnMuteDomain: undefined, // instance default
|
|
||||||
modalOnDelete: undefined, // instance default
|
|
||||||
modalOnLogout: undefined, // instance default
|
|
||||||
modalOnApproveFollow: undefined, // instance default
|
|
||||||
modalOnDenyFollow: undefined, // instance default
|
|
||||||
modalOnRemoveUserFromFollowers: undefined, // instance default
|
|
||||||
modalMobileCenter: undefined,
|
|
||||||
playVideosInModal: false,
|
|
||||||
useOneClickNsfw: false,
|
|
||||||
useContainFit: true,
|
|
||||||
disableStickyHeaders: false,
|
|
||||||
showScrollbars: false,
|
|
||||||
userPopoverAvatarAction: 'open',
|
|
||||||
userPopoverOverlay: false,
|
|
||||||
sidebarColumnWidth: '25rem',
|
|
||||||
contentColumnWidth: '45rem',
|
|
||||||
notifsColumnWidth: '25rem',
|
|
||||||
emojiReactionsScale: undefined,
|
|
||||||
textSize: undefined, // instance default
|
|
||||||
emojiSize: undefined, // instance default
|
|
||||||
navbarSize: undefined, // instance default
|
|
||||||
panelHeaderSize: undefined, // instance default
|
|
||||||
forcedRoundness: undefined, // instance default
|
|
||||||
navbarColumnStretch: false,
|
|
||||||
greentext: undefined, // instance default
|
|
||||||
useAtIcon: undefined, // instance default
|
|
||||||
mentionLinkDisplay: undefined, // instance default
|
|
||||||
mentionLinkShowTooltip: undefined, // instance default
|
|
||||||
mentionLinkShowAvatar: undefined, // instance default
|
|
||||||
mentionLinkFadeDomain: undefined, // instance default
|
|
||||||
mentionLinkShowYous: undefined, // instance default
|
|
||||||
mentionLinkBoldenYou: undefined, // instance default
|
|
||||||
hidePostStats: undefined, // instance default
|
|
||||||
hideBotIndication: undefined, // instance default
|
|
||||||
hideUserStats: undefined, // instance default
|
|
||||||
virtualScrolling: undefined, // instance default
|
|
||||||
sensitiveByDefault: undefined, // instance default
|
|
||||||
conversationDisplay: undefined, // instance default
|
|
||||||
conversationTreeAdvanced: undefined, // instance default
|
|
||||||
conversationOtherRepliesButton: undefined, // instance default
|
|
||||||
conversationTreeFadeAncestors: undefined, // instance default
|
|
||||||
showExtraNotifications: undefined, // instance default
|
|
||||||
showExtraNotificationsTip: undefined, // instance default
|
|
||||||
showChatsInExtraNotifications: undefined, // instance default
|
|
||||||
showAnnouncementsInExtraNotifications: undefined, // instance default
|
|
||||||
showFollowRequestsInExtraNotifications: undefined, // instance default
|
|
||||||
maxDepthInThread: undefined, // instance default
|
|
||||||
autocompleteSelect: undefined, // instance default
|
|
||||||
closingDrawerMarksAsSeen: undefined, // instance default
|
|
||||||
unseenAtTop: undefined, // instance default
|
|
||||||
ignoreInactionableSeen: undefined, // instance default
|
|
||||||
unsavedPostAction: undefined, // instance default
|
|
||||||
autoSaveDraft: undefined, // instance default
|
|
||||||
useAbsoluteTimeFormat: undefined, // instance default
|
|
||||||
absoluteTimeFormatMinAge: undefined, // instance default
|
|
||||||
absoluteTime12h: undefined, // instance default
|
|
||||||
imageCompression: true,
|
|
||||||
alwaysUseJpeg: false
|
|
||||||
}
|
|
||||||
|
|
||||||
// caching the instance default properties
|
// caching the instance default properties
|
||||||
export const instanceDefaultProperties = Object.entries(defaultState)
|
export const instanceDefaultProperties = Object.entries(defaultState)
|
||||||
.filter(([key, value]) => value === undefined)
|
.filter(([key, value]) => value === undefined)
|
||||||
|
@ -260,7 +98,7 @@ const config = {
|
||||||
commit('setHighlight', { user, color, type })
|
commit('setHighlight', { user, color, type })
|
||||||
},
|
},
|
||||||
setOptionTemporarily ({ commit, dispatch, state, rootState }, { name, value }) {
|
setOptionTemporarily ({ commit, dispatch, state, rootState }, { name, value }) {
|
||||||
if (rootState.interface.temporaryChangesTimeoutId !== null) {
|
if (useInterfaceStore().temporaryChangesTimeoutId !== null) {
|
||||||
console.warn('Can\'t track more than one temporary change')
|
console.warn('Can\'t track more than one temporary change')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -328,7 +166,7 @@ const config = {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'interfaceLanguage':
|
case 'interfaceLanguage':
|
||||||
messages.setLanguage(this.getters.i18n, value)
|
messages.setLanguage(useI18nStore().i18n, value)
|
||||||
dispatch('loadUnicodeEmojiData', value)
|
dispatch('loadUnicodeEmojiData', value)
|
||||||
Cookies.set(
|
Cookies.set(
|
||||||
BACKEND_LANGUAGE_COOKIE_NAME,
|
BACKEND_LANGUAGE_COOKIE_NAME,
|
||||||
|
@ -336,7 +174,7 @@ const config = {
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
case 'thirdColumnMode':
|
case 'thirdColumnMode':
|
||||||
dispatch('setLayoutWidth', undefined)
|
useInterfaceStore().setLayoutWidth(undefined)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
165
src/modules/default_config_state.js
Normal file
165
src/modules/default_config_state.js
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
const browserLocale = (window.navigator.language || 'en').split('-')[0]
|
||||||
|
|
||||||
|
export const defaultState = {
|
||||||
|
expertLevel: 0, // used to track which settings to show and hide
|
||||||
|
|
||||||
|
// Theme stuff
|
||||||
|
theme: undefined, // Very old theme store, stores preset name, still in use
|
||||||
|
|
||||||
|
// V1
|
||||||
|
colors: {}, // VERY old theme store, just colors of V1, probably not even used anymore
|
||||||
|
|
||||||
|
// V2
|
||||||
|
customTheme: undefined, // "snapshot", previously was used as actual theme store for V2 so it's still used in case of PleromaFE downgrade event.
|
||||||
|
customThemeSource: undefined, // "source", stores original theme data
|
||||||
|
|
||||||
|
// V3
|
||||||
|
style: null,
|
||||||
|
styleCustomData: null,
|
||||||
|
palette: null,
|
||||||
|
paletteCustomData: null,
|
||||||
|
themeDebug: false, // debug mode that uses computed backgrounds instead of real ones to debug contrast functions
|
||||||
|
forceThemeRecompilation: false, // flag that forces recompilation on boot even if cache exists
|
||||||
|
theme3hacks: { // Hacks, user overrides that are independent of theme used
|
||||||
|
underlay: 'none',
|
||||||
|
fonts: {
|
||||||
|
interface: undefined,
|
||||||
|
input: undefined,
|
||||||
|
post: undefined,
|
||||||
|
monospace: undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
hideISP: false,
|
||||||
|
hideInstanceWallpaper: false,
|
||||||
|
hideShoutbox: false,
|
||||||
|
// bad name: actually hides posts of muted USERS
|
||||||
|
hideMutedPosts: undefined, // instance default
|
||||||
|
hideMutedThreads: undefined, // instance default
|
||||||
|
hideWordFilteredPosts: undefined, // instance default
|
||||||
|
muteBotStatuses: undefined, // instance default
|
||||||
|
muteSensitiveStatuses: undefined, // instance default
|
||||||
|
collapseMessageWithSubject: undefined, // instance default
|
||||||
|
padEmoji: true,
|
||||||
|
hideAttachments: false,
|
||||||
|
hideAttachmentsInConv: false,
|
||||||
|
hideScrobbles: false,
|
||||||
|
hideScrobblesAfter: '2d',
|
||||||
|
maxThumbnails: 16,
|
||||||
|
hideNsfw: true,
|
||||||
|
preloadImage: true,
|
||||||
|
loopVideo: true,
|
||||||
|
loopVideoSilentOnly: true,
|
||||||
|
streaming: false,
|
||||||
|
emojiReactionsOnTimeline: true,
|
||||||
|
alwaysShowNewPostButton: false,
|
||||||
|
autohideFloatingPostButton: false,
|
||||||
|
pauseOnUnfocused: true,
|
||||||
|
stopGifs: true,
|
||||||
|
replyVisibility: 'all',
|
||||||
|
thirdColumnMode: 'notifications',
|
||||||
|
notificationVisibility: {
|
||||||
|
follows: true,
|
||||||
|
mentions: true,
|
||||||
|
statuses: true,
|
||||||
|
likes: true,
|
||||||
|
repeats: true,
|
||||||
|
moves: true,
|
||||||
|
emojiReactions: true,
|
||||||
|
followRequest: true,
|
||||||
|
reports: true,
|
||||||
|
chatMention: true,
|
||||||
|
polls: true
|
||||||
|
},
|
||||||
|
notificationNative: {
|
||||||
|
follows: true,
|
||||||
|
mentions: true,
|
||||||
|
statuses: true,
|
||||||
|
likes: false,
|
||||||
|
repeats: false,
|
||||||
|
moves: false,
|
||||||
|
emojiReactions: false,
|
||||||
|
followRequest: true,
|
||||||
|
reports: true,
|
||||||
|
chatMention: true,
|
||||||
|
polls: true
|
||||||
|
},
|
||||||
|
webPushNotifications: false,
|
||||||
|
webPushAlwaysShowNotifications: false,
|
||||||
|
muteWords: [],
|
||||||
|
highlight: {},
|
||||||
|
interfaceLanguage: browserLocale,
|
||||||
|
hideScopeNotice: false,
|
||||||
|
useStreamingApi: false,
|
||||||
|
sidebarRight: undefined, // instance default
|
||||||
|
scopeCopy: undefined, // instance default
|
||||||
|
subjectLineBehavior: undefined, // instance default
|
||||||
|
alwaysShowSubjectInput: undefined, // instance default
|
||||||
|
postContentType: undefined, // instance default
|
||||||
|
minimalScopesMode: undefined, // instance default
|
||||||
|
// This hides statuses filtered via a word filter
|
||||||
|
hideFilteredStatuses: undefined, // instance default
|
||||||
|
modalOnRepeat: undefined, // instance default
|
||||||
|
modalOnUnfollow: undefined, // instance default
|
||||||
|
modalOnBlock: undefined, // instance default
|
||||||
|
modalOnMute: undefined, // instance default
|
||||||
|
modalOnMuteConversation: undefined, // instance default
|
||||||
|
modalOnMuteDomain: undefined, // instance default
|
||||||
|
modalOnDelete: undefined, // instance default
|
||||||
|
modalOnLogout: undefined, // instance default
|
||||||
|
modalOnApproveFollow: undefined, // instance default
|
||||||
|
modalOnDenyFollow: undefined, // instance default
|
||||||
|
modalOnRemoveUserFromFollowers: undefined, // instance default
|
||||||
|
modalMobileCenter: undefined,
|
||||||
|
playVideosInModal: false,
|
||||||
|
useOneClickNsfw: false,
|
||||||
|
useContainFit: true,
|
||||||
|
disableStickyHeaders: false,
|
||||||
|
showScrollbars: false,
|
||||||
|
userPopoverAvatarAction: 'open',
|
||||||
|
userPopoverOverlay: false,
|
||||||
|
sidebarColumnWidth: '25rem',
|
||||||
|
contentColumnWidth: '45rem',
|
||||||
|
notifsColumnWidth: '25rem',
|
||||||
|
emojiReactionsScale: undefined,
|
||||||
|
textSize: undefined, // instance default
|
||||||
|
emojiSize: undefined, // instance default
|
||||||
|
navbarSize: undefined, // instance default
|
||||||
|
panelHeaderSize: undefined, // instance default
|
||||||
|
forcedRoundness: undefined, // instance default
|
||||||
|
navbarColumnStretch: false,
|
||||||
|
greentext: undefined, // instance default
|
||||||
|
useAtIcon: undefined, // instance default
|
||||||
|
mentionLinkDisplay: undefined, // instance default
|
||||||
|
mentionLinkShowTooltip: undefined, // instance default
|
||||||
|
mentionLinkShowAvatar: undefined, // instance default
|
||||||
|
mentionLinkFadeDomain: undefined, // instance default
|
||||||
|
mentionLinkShowYous: undefined, // instance default
|
||||||
|
mentionLinkBoldenYou: undefined, // instance default
|
||||||
|
hidePostStats: undefined, // instance default
|
||||||
|
hideBotIndication: undefined, // instance default
|
||||||
|
hideUserStats: undefined, // instance default
|
||||||
|
virtualScrolling: undefined, // instance default
|
||||||
|
sensitiveByDefault: undefined, // instance default
|
||||||
|
conversationDisplay: undefined, // instance default
|
||||||
|
conversationTreeAdvanced: undefined, // instance default
|
||||||
|
conversationOtherRepliesButton: undefined, // instance default
|
||||||
|
conversationTreeFadeAncestors: undefined, // instance default
|
||||||
|
showExtraNotifications: undefined, // instance default
|
||||||
|
showExtraNotificationsTip: undefined, // instance default
|
||||||
|
showChatsInExtraNotifications: undefined, // instance default
|
||||||
|
showAnnouncementsInExtraNotifications: undefined, // instance default
|
||||||
|
showFollowRequestsInExtraNotifications: undefined, // instance default
|
||||||
|
maxDepthInThread: undefined, // instance default
|
||||||
|
autocompleteSelect: undefined, // instance default
|
||||||
|
closingDrawerMarksAsSeen: undefined, // instance default
|
||||||
|
unseenAtTop: undefined, // instance default
|
||||||
|
ignoreInactionableSeen: undefined, // instance default
|
||||||
|
unsavedPostAction: undefined, // instance default
|
||||||
|
autoSaveDraft: undefined, // instance default
|
||||||
|
useAbsoluteTimeFormat: undefined, // instance default
|
||||||
|
absoluteTimeFormatMinAge: undefined, // instance default
|
||||||
|
absoluteTime12h: undefined, // instance default
|
||||||
|
imageCompression: true,
|
||||||
|
alwaysUseJpeg: false
|
||||||
|
}
|
|
@ -1,25 +0,0 @@
|
||||||
const editStatus = {
|
|
||||||
state: {
|
|
||||||
params: null,
|
|
||||||
modalActivated: false
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
openEditStatusModal (state, params) {
|
|
||||||
state.params = params
|
|
||||||
state.modalActivated = true
|
|
||||||
},
|
|
||||||
closeEditStatusModal (state) {
|
|
||||||
state.modalActivated = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
openEditStatusModal ({ commit }, params) {
|
|
||||||
commit('openEditStatusModal', params)
|
|
||||||
},
|
|
||||||
closeEditStatusModal ({ commit }) {
|
|
||||||
commit('closeEditStatusModal')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default editStatus
|
|
|
@ -1,6 +1,7 @@
|
||||||
import apiService from '../services/api/api.service.js'
|
import apiService from '../services/api/api.service.js'
|
||||||
import { instanceDefaultProperties } from './config.js'
|
import { instanceDefaultProperties } from './config.js'
|
||||||
import { langCodeToCldrName, ensureFinalFallback } from '../i18n/languages.js'
|
import { langCodeToCldrName, ensureFinalFallback } from '../i18n/languages.js'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||||
|
|
||||||
const SORTED_EMOJI_GROUP_IDS = [
|
const SORTED_EMOJI_GROUP_IDS = [
|
||||||
'smileys-and-emotion',
|
'smileys-and-emotion',
|
||||||
|
@ -292,7 +293,7 @@ const instance = {
|
||||||
commit('setInstanceOption', { name, value })
|
commit('setInstanceOption', { name, value })
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'name':
|
case 'name':
|
||||||
dispatch('setPageTitle')
|
useInterfaceStore().setPageTitle()
|
||||||
break
|
break
|
||||||
case 'shoutAvailable':
|
case 'shoutAvailable':
|
||||||
if (value) {
|
if (value) {
|
||||||
|
|
|
@ -1,130 +0,0 @@
|
||||||
import { remove, find } from 'lodash'
|
|
||||||
|
|
||||||
export const defaultState = {
|
|
||||||
allLists: [],
|
|
||||||
allListsObject: {}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const mutations = {
|
|
||||||
setLists (state, value) {
|
|
||||||
state.allLists = value
|
|
||||||
},
|
|
||||||
setList (state, { listId, title }) {
|
|
||||||
if (!state.allListsObject[listId]) {
|
|
||||||
state.allListsObject[listId] = { accountIds: [] }
|
|
||||||
}
|
|
||||||
state.allListsObject[listId].title = title
|
|
||||||
|
|
||||||
const entry = find(state.allLists, { id: listId })
|
|
||||||
if (!entry) {
|
|
||||||
state.allLists.push({ id: listId, title })
|
|
||||||
} else {
|
|
||||||
entry.title = title
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setListAccounts (state, { listId, accountIds }) {
|
|
||||||
if (!state.allListsObject[listId]) {
|
|
||||||
state.allListsObject[listId] = { accountIds: [] }
|
|
||||||
}
|
|
||||||
state.allListsObject[listId].accountIds = accountIds
|
|
||||||
},
|
|
||||||
addListAccount (state, { listId, accountId }) {
|
|
||||||
if (!state.allListsObject[listId]) {
|
|
||||||
state.allListsObject[listId] = { accountIds: [] }
|
|
||||||
}
|
|
||||||
state.allListsObject[listId].accountIds.push(accountId)
|
|
||||||
},
|
|
||||||
removeListAccount (state, { listId, accountId }) {
|
|
||||||
if (!state.allListsObject[listId]) {
|
|
||||||
state.allListsObject[listId] = { accountIds: [] }
|
|
||||||
}
|
|
||||||
const { accountIds } = state.allListsObject[listId]
|
|
||||||
const set = new Set(accountIds)
|
|
||||||
set.delete(accountId)
|
|
||||||
state.allListsObject[listId].accountIds = [...set]
|
|
||||||
},
|
|
||||||
deleteList (state, { listId }) {
|
|
||||||
delete state.allListsObject[listId]
|
|
||||||
remove(state.allLists, list => list.id === listId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const actions = {
|
|
||||||
setLists ({ commit }, value) {
|
|
||||||
commit('setLists', value)
|
|
||||||
},
|
|
||||||
createList ({ rootState, commit }, { title }) {
|
|
||||||
return rootState.api.backendInteractor.createList({ title })
|
|
||||||
.then((list) => {
|
|
||||||
commit('setList', { listId: list.id, title })
|
|
||||||
return list
|
|
||||||
})
|
|
||||||
},
|
|
||||||
fetchList ({ rootState, commit }, { listId }) {
|
|
||||||
return rootState.api.backendInteractor.getList({ listId })
|
|
||||||
.then((list) => commit('setList', { listId: list.id, title: list.title }))
|
|
||||||
},
|
|
||||||
fetchListAccounts ({ rootState, commit }, { listId }) {
|
|
||||||
return rootState.api.backendInteractor.getListAccounts({ listId })
|
|
||||||
.then((accountIds) => commit('setListAccounts', { listId, accountIds }))
|
|
||||||
},
|
|
||||||
setList ({ rootState, commit }, { listId, title }) {
|
|
||||||
rootState.api.backendInteractor.updateList({ listId, title })
|
|
||||||
commit('setList', { listId, title })
|
|
||||||
},
|
|
||||||
setListAccounts ({ rootState, commit }, { listId, accountIds }) {
|
|
||||||
const saved = rootState.lists.allListsObject[listId].accountIds || []
|
|
||||||
const added = accountIds.filter(id => !saved.includes(id))
|
|
||||||
const removed = saved.filter(id => !accountIds.includes(id))
|
|
||||||
commit('setListAccounts', { listId, accountIds })
|
|
||||||
if (added.length > 0) {
|
|
||||||
rootState.api.backendInteractor.addAccountsToList({ listId, accountIds: added })
|
|
||||||
}
|
|
||||||
if (removed.length > 0) {
|
|
||||||
rootState.api.backendInteractor.removeAccountsFromList({ listId, accountIds: removed })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
addListAccount ({ rootState, commit }, { listId, accountId }) {
|
|
||||||
return rootState
|
|
||||||
.api
|
|
||||||
.backendInteractor
|
|
||||||
.addAccountsToList({ listId, accountIds: [accountId] })
|
|
||||||
.then((result) => {
|
|
||||||
commit('addListAccount', { listId, accountId })
|
|
||||||
return result
|
|
||||||
})
|
|
||||||
},
|
|
||||||
removeListAccount ({ rootState, commit }, { listId, accountId }) {
|
|
||||||
return rootState
|
|
||||||
.api
|
|
||||||
.backendInteractor
|
|
||||||
.removeAccountsFromList({ listId, accountIds: [accountId] })
|
|
||||||
.then((result) => {
|
|
||||||
commit('removeListAccount', { listId, accountId })
|
|
||||||
return result
|
|
||||||
})
|
|
||||||
},
|
|
||||||
deleteList ({ rootState, commit }, { listId }) {
|
|
||||||
rootState.api.backendInteractor.deleteList({ listId })
|
|
||||||
commit('deleteList', { listId })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getters = {
|
|
||||||
findListTitle: state => id => {
|
|
||||||
if (!state.allListsObject[id]) return
|
|
||||||
return state.allListsObject[id].title
|
|
||||||
},
|
|
||||||
findListAccounts: state => id => {
|
|
||||||
return [...state.allListsObject[id].accountIds]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const lists = {
|
|
||||||
state: defaultState,
|
|
||||||
mutations,
|
|
||||||
actions,
|
|
||||||
getters
|
|
||||||
}
|
|
||||||
|
|
||||||
export default lists
|
|
|
@ -1,40 +0,0 @@
|
||||||
import fileTypeService from '../services/file_type/file_type.service.js'
|
|
||||||
const supportedTypes = new Set(['image', 'video', 'audio', 'flash'])
|
|
||||||
|
|
||||||
const mediaViewer = {
|
|
||||||
state: {
|
|
||||||
media: [],
|
|
||||||
currentIndex: 0,
|
|
||||||
activated: false
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
setMedia (state, media) {
|
|
||||||
state.media = media
|
|
||||||
},
|
|
||||||
setCurrentMedia (state, index) {
|
|
||||||
state.activated = true
|
|
||||||
state.currentIndex = index
|
|
||||||
},
|
|
||||||
close (state) {
|
|
||||||
state.activated = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
setMedia ({ commit }, attachments) {
|
|
||||||
const media = attachments.filter(attachment => {
|
|
||||||
const type = fileTypeService.fileType(attachment.mimetype)
|
|
||||||
return supportedTypes.has(type)
|
|
||||||
})
|
|
||||||
commit('setMedia', media)
|
|
||||||
},
|
|
||||||
setCurrentMedia ({ commit, state }, current) {
|
|
||||||
const index = state.media.indexOf(current)
|
|
||||||
commit('setCurrentMedia', index || 0)
|
|
||||||
},
|
|
||||||
closeMediaViewer ({ commit }) {
|
|
||||||
commit('close')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default mediaViewer
|
|
|
@ -11,6 +11,8 @@ import {
|
||||||
closeAllDesktopNotifications
|
closeAllDesktopNotifications
|
||||||
} from '../services/desktop_notification_utils/desktop_notification_utils.js'
|
} from '../services/desktop_notification_utils/desktop_notification_utils.js'
|
||||||
|
|
||||||
|
import { useReportsStore } from 'src/stores/reports.js'
|
||||||
|
|
||||||
const emptyNotifications = () => ({
|
const emptyNotifications = () => ({
|
||||||
desktopNotificationSilence: true,
|
desktopNotificationSilence: true,
|
||||||
maxId: 0,
|
maxId: 0,
|
||||||
|
@ -94,7 +96,7 @@ export const notifications = {
|
||||||
|
|
||||||
validNotifications.forEach(notification => {
|
validNotifications.forEach(notification => {
|
||||||
if (notification.type === 'pleroma:report') {
|
if (notification.type === 'pleroma:report') {
|
||||||
dispatch('addReport', notification.report)
|
useReportsStore().addReport(notification.report)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notification.type === 'pleroma:emoji_reaction') {
|
if (notification.type === 'pleroma:emoji_reaction') {
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
import { merge } from 'lodash'
|
|
||||||
|
|
||||||
const polls = {
|
|
||||||
state: {
|
|
||||||
// Contains key = id, value = number of trackers for this poll
|
|
||||||
trackedPolls: {},
|
|
||||||
pollsObject: {}
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
mergeOrAddPoll (state, poll) {
|
|
||||||
const existingPoll = state.pollsObject[poll.id]
|
|
||||||
// Make expired-state change trigger re-renders properly
|
|
||||||
poll.expired = Date.now() > Date.parse(poll.expires_at)
|
|
||||||
if (existingPoll) {
|
|
||||||
state.pollsObject[poll.id] = merge(existingPoll, poll)
|
|
||||||
} else {
|
|
||||||
state.pollsObject[poll.id] = poll
|
|
||||||
}
|
|
||||||
},
|
|
||||||
trackPoll (state, pollId) {
|
|
||||||
const currentValue = state.trackedPolls[pollId]
|
|
||||||
if (currentValue) {
|
|
||||||
state.trackedPolls[pollId] = currentValue + 1
|
|
||||||
} else {
|
|
||||||
state.trackedPolls[pollId] = 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
untrackPoll (state, pollId) {
|
|
||||||
const currentValue = state.trackedPolls[pollId]
|
|
||||||
if (currentValue) {
|
|
||||||
state.trackedPolls[pollId] = currentValue - 1
|
|
||||||
} else {
|
|
||||||
state.trackedPolls[pollId] = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
mergeOrAddPoll ({ commit }, poll) {
|
|
||||||
commit('mergeOrAddPoll', poll)
|
|
||||||
},
|
|
||||||
updateTrackedPoll ({ rootState, dispatch, commit }, pollId) {
|
|
||||||
rootState.api.backendInteractor.fetchPoll({ pollId }).then(poll => {
|
|
||||||
setTimeout(() => {
|
|
||||||
if (rootState.polls.trackedPolls[pollId]) {
|
|
||||||
dispatch('updateTrackedPoll', pollId)
|
|
||||||
}
|
|
||||||
}, 30 * 1000)
|
|
||||||
commit('mergeOrAddPoll', poll)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
trackPoll ({ rootState, commit, dispatch }, pollId) {
|
|
||||||
if (!rootState.polls.trackedPolls[pollId]) {
|
|
||||||
setTimeout(() => dispatch('updateTrackedPoll', pollId), 30 * 1000)
|
|
||||||
}
|
|
||||||
commit('trackPoll', pollId)
|
|
||||||
},
|
|
||||||
untrackPoll ({ commit }, pollId) {
|
|
||||||
commit('untrackPoll', pollId)
|
|
||||||
},
|
|
||||||
votePoll ({ rootState, commit }, { id, pollId, choices }) {
|
|
||||||
return rootState.api.backendInteractor.vote({ pollId, choices }).then(poll => {
|
|
||||||
commit('mergeOrAddPoll', poll)
|
|
||||||
return poll
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default polls
|
|
|
@ -1,31 +0,0 @@
|
||||||
const postStatus = {
|
|
||||||
state: {
|
|
||||||
params: null,
|
|
||||||
modalActivated: false
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
openPostStatusModal (state, params) {
|
|
||||||
state.params = params
|
|
||||||
state.modalActivated = true
|
|
||||||
},
|
|
||||||
closePostStatusModal (state) {
|
|
||||||
state.modalActivated = false
|
|
||||||
},
|
|
||||||
resetPostStatusModal (state) {
|
|
||||||
state.params = null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
openPostStatusModal ({ commit }, params) {
|
|
||||||
commit('openPostStatusModal', params)
|
|
||||||
},
|
|
||||||
closePostStatusModal ({ commit }) {
|
|
||||||
commit('closePostStatusModal')
|
|
||||||
},
|
|
||||||
resetPostStatusModal ({ commit }) {
|
|
||||||
commit('resetPostStatusModal')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default postStatus
|
|
|
@ -1,64 +0,0 @@
|
||||||
import filter from 'lodash/filter'
|
|
||||||
|
|
||||||
const reports = {
|
|
||||||
state: {
|
|
||||||
reportModal: {
|
|
||||||
userId: null,
|
|
||||||
statuses: [],
|
|
||||||
preTickedIds: [],
|
|
||||||
activated: false
|
|
||||||
},
|
|
||||||
reports: {}
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
openUserReportingModal (state, { userId, statuses, preTickedIds }) {
|
|
||||||
state.reportModal.userId = userId
|
|
||||||
state.reportModal.statuses = statuses
|
|
||||||
state.reportModal.preTickedIds = preTickedIds
|
|
||||||
state.reportModal.activated = true
|
|
||||||
},
|
|
||||||
closeUserReportingModal (state) {
|
|
||||||
state.reportModal.activated = false
|
|
||||||
},
|
|
||||||
setReportState (reportsState, { id, state }) {
|
|
||||||
reportsState.reports[id].state = state
|
|
||||||
},
|
|
||||||
addReport (state, report) {
|
|
||||||
state.reports[report.id] = report
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
openUserReportingModal ({ rootState, commit }, { userId, statusIds = [] }) {
|
|
||||||
const preTickedStatuses = statusIds.map(id => rootState.statuses.allStatusesObject[id])
|
|
||||||
const preTickedIds = statusIds
|
|
||||||
const statuses = preTickedStatuses.concat(
|
|
||||||
filter(rootState.statuses.allStatuses,
|
|
||||||
status => status.user.id === userId && !preTickedIds.includes(status.id)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
commit('openUserReportingModal', { userId, statuses, preTickedIds })
|
|
||||||
},
|
|
||||||
closeUserReportingModal ({ commit }) {
|
|
||||||
commit('closeUserReportingModal')
|
|
||||||
},
|
|
||||||
setReportState ({ commit, dispatch, rootState }, { id, state }) {
|
|
||||||
const oldState = rootState.reports.reports[id].state
|
|
||||||
commit('setReportState', { id, state })
|
|
||||||
rootState.api.backendInteractor.setReportState({ id, state }).catch(e => {
|
|
||||||
console.error('Failed to set report state', e)
|
|
||||||
dispatch('pushGlobalNotice', {
|
|
||||||
level: 'error',
|
|
||||||
messageKey: 'general.generic_error_message',
|
|
||||||
messageArgs: [e.message],
|
|
||||||
timeout: 5000
|
|
||||||
})
|
|
||||||
commit('setReportState', { id, state: oldState })
|
|
||||||
})
|
|
||||||
},
|
|
||||||
addReport ({ commit }, report) {
|
|
||||||
commit('addReport', report)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default reports
|
|
|
@ -1,46 +0,0 @@
|
||||||
const shout = {
|
|
||||||
state: {
|
|
||||||
messages: [],
|
|
||||||
channel: { state: '' },
|
|
||||||
joined: false
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
setChannel (state, channel) {
|
|
||||||
state.channel = channel
|
|
||||||
},
|
|
||||||
addMessage (state, message) {
|
|
||||||
state.messages.push(message)
|
|
||||||
state.messages = state.messages.slice(-19, 20)
|
|
||||||
},
|
|
||||||
setMessages (state, messages) {
|
|
||||||
state.messages = messages.slice(-19, 20)
|
|
||||||
},
|
|
||||||
setJoined (state, joined) {
|
|
||||||
state.joined = joined
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
initializeShout (store, socket) {
|
|
||||||
const channel = socket.channel('chat:public')
|
|
||||||
channel.joinPush.receive('ok', () => {
|
|
||||||
store.commit('setJoined', true)
|
|
||||||
})
|
|
||||||
channel.onClose(() => {
|
|
||||||
store.commit('setJoined', false)
|
|
||||||
})
|
|
||||||
channel.onError(() => {
|
|
||||||
store.commit('setJoined', false)
|
|
||||||
})
|
|
||||||
channel.on('new_msg', (msg) => {
|
|
||||||
store.commit('addMessage', msg)
|
|
||||||
})
|
|
||||||
channel.on('messages', ({ messages }) => {
|
|
||||||
store.commit('setMessages', messages)
|
|
||||||
})
|
|
||||||
channel.join()
|
|
||||||
store.commit('setChannel', channel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default shout
|
|
|
@ -1,25 +0,0 @@
|
||||||
const statusHistory = {
|
|
||||||
state: {
|
|
||||||
params: {},
|
|
||||||
modalActivated: false
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
openStatusHistoryModal (state, params) {
|
|
||||||
state.params = params
|
|
||||||
state.modalActivated = true
|
|
||||||
},
|
|
||||||
closeStatusHistoryModal (state) {
|
|
||||||
state.modalActivated = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
openStatusHistoryModal ({ commit }, params) {
|
|
||||||
commit('openStatusHistoryModal', params)
|
|
||||||
},
|
|
||||||
closeStatusHistoryModal ({ commit }) {
|
|
||||||
commit('closeStatusHistoryModal')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default statusHistory
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
omitBy
|
omitBy
|
||||||
} from 'lodash'
|
} from 'lodash'
|
||||||
import apiService from '../services/api/api.service.js'
|
import apiService from '../services/api/api.service.js'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
const emptyTl = (userId = 0) => ({
|
const emptyTl = (userId = 0) => ({
|
||||||
statuses: [],
|
statuses: [],
|
||||||
|
@ -510,7 +511,7 @@ const statuses = {
|
||||||
commit('setDeleted', { status })
|
commit('setDeleted', { status })
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
dispatch('pushGlobalNotice', {
|
useInterfaceStore().pushGlobalNotice({
|
||||||
level: 'error',
|
level: 'error',
|
||||||
messageKey: 'status.delete_error',
|
messageKey: 'status.delete_error',
|
||||||
messageArgs: [e.message],
|
messageArgs: [e.message],
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { windowWidth, windowHeight } from '../services/window_utils/window_utils
|
||||||
import oauthApi from '../services/new_api/oauth.js'
|
import oauthApi from '../services/new_api/oauth.js'
|
||||||
import { compact, map, each, mergeWith, last, concat, uniq, isArray } from 'lodash'
|
import { compact, map, each, mergeWith, last, concat, uniq, isArray } from 'lodash'
|
||||||
import { registerPushNotifications, unregisterPushNotifications } from '../services/sw/sw.js'
|
import { registerPushNotifications, unregisterPushNotifications } from '../services/sw/sw.js'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||||
|
|
||||||
// TODO: Unify with mergeOrAdd in statuses.js
|
// TODO: Unify with mergeOrAdd in statuses.js
|
||||||
export const mergeOrAdd = (arr, obj, item) => {
|
export const mergeOrAdd = (arr, obj, item) => {
|
||||||
|
@ -584,9 +585,9 @@ const users = {
|
||||||
store.commit('clearNotifications')
|
store.commit('clearNotifications')
|
||||||
store.commit('resetStatuses')
|
store.commit('resetStatuses')
|
||||||
store.dispatch('resetChats')
|
store.dispatch('resetChats')
|
||||||
store.dispatch('setLastTimeline', 'public-timeline')
|
useInterfaceStore().setLastTimeline('public-timeline')
|
||||||
store.dispatch('setLayoutWidth', windowWidth())
|
useInterfaceStore().setLayoutWidth(windowWidth())
|
||||||
store.dispatch('setLayoutHeight', windowHeight())
|
useInterfaceStore().setLayoutHeight(windowHeight())
|
||||||
store.commit('clearServerSideStorage')
|
store.commit('clearServerSideStorage')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -611,7 +612,7 @@ const users = {
|
||||||
dispatch('fetchEmoji')
|
dispatch('fetchEmoji')
|
||||||
|
|
||||||
getNotificationPermission()
|
getNotificationPermission()
|
||||||
.then(permission => commit('setNotificationPermission', permission))
|
.then(permission => useInterfaceStore().setNotificationPermission(permission))
|
||||||
|
|
||||||
// Set our new backend interactor
|
// Set our new backend interactor
|
||||||
commit('setBackendInteractor', backendInteractorService(accessToken))
|
commit('setBackendInteractor', backendInteractorService(accessToken))
|
||||||
|
@ -658,8 +659,8 @@ const users = {
|
||||||
// Get user mutes
|
// Get user mutes
|
||||||
dispatch('fetchMutes')
|
dispatch('fetchMutes')
|
||||||
|
|
||||||
dispatch('setLayoutWidth', windowWidth())
|
useInterfaceStore().setLayoutWidth(windowWidth())
|
||||||
dispatch('setLayoutHeight', windowHeight())
|
useInterfaceStore().setLayoutHeight(windowHeight())
|
||||||
|
|
||||||
// Fetch our friends
|
// Fetch our friends
|
||||||
store.rootState.api.backendInteractor.fetchFriends({ id: user.id })
|
store.rootState.api.backendInteractor.fetchFriends({ id: user.id })
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
import { useListsStore } from 'src/stores/lists.js'
|
||||||
import apiService from '../api/api.service.js'
|
import apiService from '../api/api.service.js'
|
||||||
import { promiseInterval } from '../promise_interval/promise_interval.js'
|
import { promiseInterval } from '../promise_interval/promise_interval.js'
|
||||||
|
|
||||||
const fetchAndUpdate = ({ store, credentials }) => {
|
const fetchAndUpdate = ({ store, credentials }) => {
|
||||||
return apiService.fetchLists({ credentials })
|
return apiService.fetchLists({ credentials })
|
||||||
.then(lists => {
|
.then(lists => {
|
||||||
store.commit('setLists', lists)
|
useListsStore().setLists(lists)
|
||||||
}, () => {})
|
}, () => {})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { muteWordHits } from '../status_parser/status_parser.js'
|
import { muteWordHits } from '../status_parser/status_parser.js'
|
||||||
import { showDesktopNotification } from '../desktop_notification_utils/desktop_notification_utils.js'
|
import { showDesktopNotification } from '../desktop_notification_utils/desktop_notification_utils.js'
|
||||||
|
import { useI18nStore } from 'src/stores/i18n.js'
|
||||||
|
import { useAnnouncementsStore } from 'src/stores/announcements'
|
||||||
|
|
||||||
import FaviconService from 'src/services/favicon_service/favicon_service.js'
|
import FaviconService from 'src/services/favicon_service/favicon_service.js'
|
||||||
|
|
||||||
|
@ -64,13 +66,12 @@ const isMutedNotification = (store, notification) => {
|
||||||
|
|
||||||
export const maybeShowNotification = (store, notification) => {
|
export const maybeShowNotification = (store, notification) => {
|
||||||
const rootState = store.rootState || store.state
|
const rootState = store.rootState || store.state
|
||||||
const rootGetters = store.rootGetters || store.getters
|
|
||||||
|
|
||||||
if (notification.seen) return
|
if (notification.seen) return
|
||||||
if (!visibleTypes(store).includes(notification.type)) return
|
if (!visibleTypes(store).includes(notification.type)) return
|
||||||
if (notification.type === 'mention' && isMutedNotification(store, notification)) return
|
if (notification.type === 'mention' && isMutedNotification(store, notification)) return
|
||||||
|
|
||||||
const notificationObject = prepareNotificationObject(notification, rootGetters.i18n)
|
const notificationObject = prepareNotificationObject(notification, useI18nStore().i18n)
|
||||||
showDesktopNotification(rootState, notificationObject)
|
showDesktopNotification(rootState, notificationObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +170,7 @@ export const countExtraNotifications = (store) => {
|
||||||
|
|
||||||
return [
|
return [
|
||||||
mergedConfig.showChatsInExtraNotifications ? rootGetters.unreadChatCount : 0,
|
mergedConfig.showChatsInExtraNotifications ? rootGetters.unreadChatCount : 0,
|
||||||
mergedConfig.showAnnouncementsInExtraNotifications ? rootGetters.unreadAnnouncementCount : 0,
|
mergedConfig.showAnnouncementsInExtraNotifications ? useAnnouncementsStore().unreadAnnouncementCount : 0,
|
||||||
mergedConfig.showFollowRequestsInExtraNotifications ? rootGetters.followRequestCount : 0
|
mergedConfig.showFollowRequestsInExtraNotifications ? rootGetters.followRequestCount : 0
|
||||||
].reduce((a, c) => a + c, 0)
|
].reduce((a, c) => a + c, 0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||||
import apiService from '../api/api.service.js'
|
import apiService from '../api/api.service.js'
|
||||||
import { promiseInterval } from '../promise_interval/promise_interval.js'
|
import { promiseInterval } from '../promise_interval/promise_interval.js'
|
||||||
|
|
||||||
|
@ -78,7 +79,7 @@ const fetchNotifications = ({ store, args, older }) => {
|
||||||
return notifications
|
return notifications
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
store.dispatch('pushGlobalNotice', {
|
useInterfaceStore().pushGlobalNotice({
|
||||||
level: 'error',
|
level: 'error',
|
||||||
messageKey: 'notifications.error',
|
messageKey: 'notifications.error',
|
||||||
messageArgs: [error.message],
|
messageArgs: [error.message],
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import { init, getEngineChecksum } from '../theme_data/theme_data_3.service.js'
|
import { init, getEngineChecksum } from '../theme_data/theme_data_3.service.js'
|
||||||
import { getCssRules } from '../theme_data/css_utils.js'
|
import { getCssRules } from '../theme_data/css_utils.js'
|
||||||
import { defaultState } from '../../modules/config.js'
|
import { defaultState } from 'src/modules/default_config_state.js'
|
||||||
import { chunk } from 'lodash'
|
import { chunk } from 'lodash'
|
||||||
import pako from 'pako'
|
import pako from 'pako'
|
||||||
import localforage from 'localforage'
|
import localforage from 'localforage'
|
||||||
|
|
||||||
|
console.log('CONFIG', defaultState)
|
||||||
|
|
||||||
// On platforms where this is not supported, it will return undefined
|
// On platforms where this is not supported, it will return undefined
|
||||||
// Otherwise it will return an array
|
// Otherwise it will return an array
|
||||||
const supportsAdoptedStyleSheets = !!document.adoptedStyleSheets
|
const supportsAdoptedStyleSheets = !!document.adoptedStyleSheets
|
||||||
|
@ -212,6 +214,7 @@ const extractStyleConfig = ({
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(defaultState)
|
||||||
const defaultStyleConfig = extractStyleConfig(defaultState)
|
const defaultStyleConfig = extractStyleConfig(defaultState)
|
||||||
|
|
||||||
export const applyConfig = (input, i18n) => {
|
export const applyConfig = (input, i18n) => {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { camelCase } from 'lodash'
|
||||||
|
|
||||||
import apiService from '../api/api.service.js'
|
import apiService from '../api/api.service.js'
|
||||||
import { promiseInterval } from '../promise_interval/promise_interval.js'
|
import { promiseInterval } from '../promise_interval/promise_interval.js'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface.js'
|
||||||
|
|
||||||
const update = ({ store, statuses, timeline, showImmediately, userId, listId, pagination }) => {
|
const update = ({ store, statuses, timeline, showImmediately, userId, listId, pagination }) => {
|
||||||
const ccTimeline = camelCase(timeline)
|
const ccTimeline = camelCase(timeline)
|
||||||
|
@ -73,7 +74,7 @@ const fetchAndUpdate = ({
|
||||||
return { statuses, pagination }
|
return { statuses, pagination }
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
store.dispatch('pushGlobalNotice', {
|
useInterfaceStore().pushGlobalNotice({
|
||||||
level: 'error',
|
level: 'error',
|
||||||
messageKey: 'timeline.error',
|
messageKey: 'timeline.error',
|
||||||
messageArgs: [error.message],
|
messageArgs: [error.message],
|
||||||
|
|
115
src/stores/announcements.js
Normal file
115
src/stores/announcements.js
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
const FETCH_ANNOUNCEMENT_INTERVAL_MS = 1000 * 60 * 5
|
||||||
|
|
||||||
|
export const useAnnouncementsStore = defineStore('announcements', {
|
||||||
|
state: () => ({
|
||||||
|
announcements: [],
|
||||||
|
supportsAnnouncements: true,
|
||||||
|
fetchAnnouncementsTimer: undefined
|
||||||
|
}),
|
||||||
|
getters: {
|
||||||
|
unreadAnnouncementCount () {
|
||||||
|
if (!window.vuex.state.users.currentUser) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
const unread = this.announcements.filter(announcement => !(announcement.inactive || announcement.read))
|
||||||
|
return unread.length
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
fetchAnnouncements () {
|
||||||
|
if (!this.supportsAnnouncements) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentUser = window.vuex.state.users.currentUser
|
||||||
|
const isAdmin = currentUser && currentUser.privileges.includes('announcements_manage_announcements')
|
||||||
|
|
||||||
|
const getAnnouncements = async () => {
|
||||||
|
if (!isAdmin) {
|
||||||
|
return window.vuex.state.api.backendInteractor.fetchAnnouncements()
|
||||||
|
}
|
||||||
|
|
||||||
|
const all = await window.vuex.state.api.backendInteractor.adminFetchAnnouncements()
|
||||||
|
const visible = await window.vuex.state.api.backendInteractor.fetchAnnouncements()
|
||||||
|
const visibleObject = visible.reduce((a, c) => {
|
||||||
|
a[c.id] = c
|
||||||
|
return a
|
||||||
|
}, {})
|
||||||
|
const getWithinVisible = announcement => visibleObject[announcement.id]
|
||||||
|
|
||||||
|
all.forEach(announcement => {
|
||||||
|
const visibleAnnouncement = getWithinVisible(announcement)
|
||||||
|
if (!visibleAnnouncement) {
|
||||||
|
announcement.inactive = true
|
||||||
|
} else {
|
||||||
|
announcement.read = visibleAnnouncement.read
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return all
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAnnouncements()
|
||||||
|
.then(announcements => {
|
||||||
|
this.announcements = announcements
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
// If and only if backend does not support announcements, it would return 404.
|
||||||
|
// In this case, silently ignores it.
|
||||||
|
if (error && error.statusCode === 404) {
|
||||||
|
this.supportsAnnouncements = false
|
||||||
|
} else {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
markAnnouncementAsRead (id) {
|
||||||
|
return window.vuex.state.api.backendInteractor.dismissAnnouncement({ id })
|
||||||
|
.then(() => {
|
||||||
|
const index = this.announcements.findIndex(a => a.id === id)
|
||||||
|
|
||||||
|
if (index < 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.announcements[index].read = true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
startFetchingAnnouncements () {
|
||||||
|
if (this.fetchAnnouncementsTimer) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const interval = setInterval(() => this.fetchAnnouncements(), FETCH_ANNOUNCEMENT_INTERVAL_MS)
|
||||||
|
this.fetchAnnouncementsTimer = interval
|
||||||
|
|
||||||
|
return this.fetchAnnouncements()
|
||||||
|
},
|
||||||
|
stopFetchingAnnouncements () {
|
||||||
|
const interval = this.fetchAnnouncementsTimer
|
||||||
|
this.fetchAnnouncementsTimer = undefined
|
||||||
|
clearInterval(interval)
|
||||||
|
},
|
||||||
|
postAnnouncement ({ content, startsAt, endsAt, allDay }) {
|
||||||
|
return window.vuex.state.api.backendInteractor.postAnnouncement({ content, startsAt, endsAt, allDay })
|
||||||
|
.then(() => {
|
||||||
|
return this.fetchAnnouncements()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
editAnnouncement ({ id, content, startsAt, endsAt, allDay }) {
|
||||||
|
return window.vuex.state.api.backendInteractor.editAnnouncement({ id, content, startsAt, endsAt, allDay })
|
||||||
|
.then(() => {
|
||||||
|
return this.fetchAnnouncements()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteAnnouncement (id) {
|
||||||
|
return window.vuex.state.api.backendInteractor.deleteAnnouncement({ id })
|
||||||
|
.then(() => {
|
||||||
|
return this.fetchAnnouncements()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
17
src/stores/editStatus.js
Normal file
17
src/stores/editStatus.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
export const useEditStatusStore = defineStore('editStatus', {
|
||||||
|
state: () => ({
|
||||||
|
params: null,
|
||||||
|
modalActivated: false
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
openEditStatusModal (params) {
|
||||||
|
this.params = params
|
||||||
|
this.modalActivated = true
|
||||||
|
},
|
||||||
|
closeEditStatusModal () {
|
||||||
|
this.modalActivated = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
14
src/stores/i18n.js
Normal file
14
src/stores/i18n.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
export const useI18nStore = defineStore('i18n', {
|
||||||
|
state: () => ({
|
||||||
|
i18n: null
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
setI18n (newI18n) {
|
||||||
|
this.$patch({
|
||||||
|
i18n: newI18n.global
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
|
@ -1,13 +1,12 @@
|
||||||
import { getResourcesIndex, applyTheme, tryLoadCache } from '../services/style_setter/style_setter.js'
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
import { CURRENT_VERSION, generatePreset } from 'src/services/theme_data/theme_data.service.js'
|
import { CURRENT_VERSION, generatePreset } from 'src/services/theme_data/theme_data.service.js'
|
||||||
|
import { getResourcesIndex, applyTheme, tryLoadCache } from '../services/style_setter/style_setter.js'
|
||||||
import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
|
import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
|
||||||
import { deserialize } from '../services/theme_data/iss_deserializer.js'
|
import { deserialize } from '../services/theme_data/iss_deserializer.js'
|
||||||
|
|
||||||
// helper for debugging
|
export const useInterfaceStore = defineStore('interface', {
|
||||||
// eslint-disable-next-line no-unused-vars
|
state: () => ({
|
||||||
const toValue = (x) => JSON.parse(JSON.stringify(x === undefined ? 'null' : x))
|
|
||||||
|
|
||||||
const defaultState = {
|
|
||||||
localFonts: null,
|
localFonts: null,
|
||||||
themeApplied: false,
|
themeApplied: false,
|
||||||
themeChangeInProgress: false,
|
themeChangeInProgress: false,
|
||||||
|
@ -43,121 +42,68 @@ const defaultState = {
|
||||||
globalNotices: [],
|
globalNotices: [],
|
||||||
layoutHeight: 0,
|
layoutHeight: 0,
|
||||||
lastTimeline: null
|
lastTimeline: null
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
setPageTitle (option = '') {
|
||||||
|
try {
|
||||||
|
document.title = `${option} ${window.vuex.state.instance.name}`
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`${error}`)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
const interfaceMod = {
|
settingsSaved ({ success, error }) {
|
||||||
state: defaultState,
|
|
||||||
mutations: {
|
|
||||||
settingsSaved (state, { success, error }) {
|
|
||||||
if (success) {
|
if (success) {
|
||||||
if (state.noticeClearTimeout) {
|
if (this.noticeClearTimeout) {
|
||||||
clearTimeout(state.noticeClearTimeout)
|
clearTimeout(this.noticeClearTimeout)
|
||||||
}
|
}
|
||||||
state.settings.currentSaveStateNotice = { error: false, data: success }
|
this.settings.currentSaveStateNotice = { error: false, data: success }
|
||||||
state.settings.noticeClearTimeout = setTimeout(() => delete state.settings.currentSaveStateNotice, 2000)
|
this.settings.noticeClearTimeout = setTimeout(() => delete this.settings.currentSaveStateNotice, 2000)
|
||||||
} else {
|
} else {
|
||||||
state.settings.currentSaveStateNotice = { error: true, errorData: error }
|
this.settings.currentSaveStateNotice = { error: true, errorData: error }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setTemporaryChanges (state, { timeoutId, confirm, revert }) {
|
setNotificationPermission (permission) {
|
||||||
state.temporaryChangesTimeoutId = timeoutId
|
this.notificationPermission = permission
|
||||||
state.temporaryChangesConfirm = confirm
|
|
||||||
state.temporaryChangesRevert = revert
|
|
||||||
},
|
},
|
||||||
clearTemporaryChanges (state) {
|
closeSettingsModal () {
|
||||||
clearTimeout(state.temporaryChangesTimeoutId)
|
this.settingsModalState = 'hidden'
|
||||||
state.temporaryChangesTimeoutId = null
|
|
||||||
state.temporaryChangesConfirm = () => {}
|
|
||||||
state.temporaryChangesRevert = () => {}
|
|
||||||
},
|
},
|
||||||
setThemeApplied (state) {
|
openSettingsModal (value) {
|
||||||
state.themeApplied = true
|
this.settingsModalMode = value
|
||||||
|
this.settingsModalState = 'visible'
|
||||||
|
if (value === 'user') {
|
||||||
|
if (!this.settingsModalLoadedUser) {
|
||||||
|
this.settingsModalLoadedUser = true
|
||||||
|
}
|
||||||
|
} else if (value === 'admin') {
|
||||||
|
if (!this.settingsModalLoadedAdmin) {
|
||||||
|
this.settingsModalLoadedAdmin = true
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setNotificationPermission (state, permission) {
|
togglePeekSettingsModal () {
|
||||||
state.notificationPermission = permission
|
switch (this.settingsModalState) {
|
||||||
},
|
|
||||||
setLayoutType (state, value) {
|
|
||||||
state.layoutType = value
|
|
||||||
},
|
|
||||||
closeSettingsModal (state) {
|
|
||||||
state.settingsModalState = 'hidden'
|
|
||||||
},
|
|
||||||
togglePeekSettingsModal (state) {
|
|
||||||
switch (state.settingsModalState) {
|
|
||||||
case 'minimized':
|
case 'minimized':
|
||||||
state.settingsModalState = 'visible'
|
this.settingsModalState = 'visible'
|
||||||
return
|
return
|
||||||
case 'visible':
|
case 'visible':
|
||||||
state.settingsModalState = 'minimized'
|
this.settingsModalState = 'minimized'
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
throw new Error('Illegal minimization state of settings modal')
|
throw new Error('Illegal minimization state of settings modal')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openSettingsModal (state, value) {
|
clearSettingsModalTargetTab () {
|
||||||
state.settingsModalMode = value
|
this.settingsModalTargetTab = null
|
||||||
state.settingsModalState = 'visible'
|
|
||||||
if (value === 'user') {
|
|
||||||
if (!state.settingsModalLoadedUser) {
|
|
||||||
state.settingsModalLoadedUser = true
|
|
||||||
}
|
|
||||||
} else if (value === 'admin') {
|
|
||||||
if (!state.settingsModalLoadedAdmin) {
|
|
||||||
state.settingsModalLoadedAdmin = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
setSettingsModalTargetTab (state, value) {
|
openSettingsModalTab (value, mode = 'user') {
|
||||||
state.settingsModalTargetTab = value
|
this.settingsModalTargetTab = value
|
||||||
|
this.openSettingsModal(mode)
|
||||||
},
|
},
|
||||||
pushGlobalNotice (state, notice) {
|
removeGlobalNotice (notice) {
|
||||||
state.globalNotices.push(notice)
|
this.globalNotices = this.globalNotices.filter(n => n !== notice)
|
||||||
},
|
|
||||||
removeGlobalNotice (state, notice) {
|
|
||||||
state.globalNotices = state.globalNotices.filter(n => n !== notice)
|
|
||||||
},
|
|
||||||
setLayoutHeight (state, value) {
|
|
||||||
state.layoutHeight = value
|
|
||||||
},
|
|
||||||
setLayoutWidth (state, value) {
|
|
||||||
state.layoutWidth = value
|
|
||||||
},
|
|
||||||
setLastTimeline (state, value) {
|
|
||||||
state.lastTimeline = value
|
|
||||||
},
|
|
||||||
setFontsList (state, value) {
|
|
||||||
// Set is used here so that we filter out duplicate fonts (possibly same font but with different weight)
|
|
||||||
state.localFonts = [...(new Set(value.map(font => font.family))).values()]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
setPageTitle ({ rootState }, option = '') {
|
|
||||||
document.title = `${option} ${rootState.instance.name}`
|
|
||||||
},
|
|
||||||
settingsSaved ({ commit, dispatch }, { success, error }) {
|
|
||||||
commit('settingsSaved', { success, error })
|
|
||||||
},
|
|
||||||
setNotificationPermission ({ commit }, permission) {
|
|
||||||
commit('setNotificationPermission', permission)
|
|
||||||
},
|
|
||||||
closeSettingsModal ({ commit }) {
|
|
||||||
commit('closeSettingsModal')
|
|
||||||
},
|
|
||||||
openSettingsModal ({ commit }, value = 'user') {
|
|
||||||
commit('openSettingsModal', value)
|
|
||||||
},
|
|
||||||
togglePeekSettingsModal ({ commit }) {
|
|
||||||
commit('togglePeekSettingsModal')
|
|
||||||
},
|
|
||||||
clearSettingsModalTargetTab ({ commit }) {
|
|
||||||
commit('setSettingsModalTargetTab', null)
|
|
||||||
},
|
|
||||||
openSettingsModalTab ({ commit }, value) {
|
|
||||||
commit('setSettingsModalTargetTab', value)
|
|
||||||
commit('openSettingsModal', 'user')
|
|
||||||
},
|
},
|
||||||
pushGlobalNotice (
|
pushGlobalNotice (
|
||||||
{ commit, dispatch, state },
|
|
||||||
{
|
{
|
||||||
messageKey,
|
messageKey,
|
||||||
messageArgs = {},
|
messageArgs = {},
|
||||||
|
@ -169,52 +115,56 @@ const interfaceMod = {
|
||||||
messageArgs,
|
messageArgs,
|
||||||
level
|
level
|
||||||
}
|
}
|
||||||
commit('pushGlobalNotice', notice)
|
|
||||||
|
this.globalNotices.push(notice)
|
||||||
|
|
||||||
// Adding a new element to array wraps it in a Proxy, which breaks the comparison
|
// Adding a new element to array wraps it in a Proxy, which breaks the comparison
|
||||||
// TODO: Generate UUID or something instead or relying on !== operator?
|
// TODO: Generate UUID or something instead or relying on !== operator?
|
||||||
const newNotice = state.globalNotices[state.globalNotices.length - 1]
|
const newNotice = this.globalNotices[this.globalNotices.length - 1]
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
setTimeout(() => dispatch('removeGlobalNotice', newNotice), timeout)
|
setTimeout(() => this.removeGlobalNotice(newNotice), timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newNotice
|
return newNotice
|
||||||
},
|
},
|
||||||
removeGlobalNotice ({ commit }, notice) {
|
setLayoutHeight (value) {
|
||||||
commit('removeGlobalNotice', notice)
|
this.layoutHeight = value
|
||||||
},
|
},
|
||||||
setLayoutHeight ({ commit }, value) {
|
setLayoutWidth (value) {
|
||||||
commit('setLayoutHeight', value)
|
|
||||||
},
|
|
||||||
// value is optional, assuming it was cached prior
|
|
||||||
setLayoutWidth ({ commit, state, rootGetters, rootState }, value) {
|
|
||||||
let width = value
|
let width = value
|
||||||
if (value !== undefined) {
|
if (value !== undefined) {
|
||||||
commit('setLayoutWidth', value)
|
this.layoutWidth = value
|
||||||
} else {
|
} else {
|
||||||
width = state.layoutWidth
|
width = this.layoutWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
const mobileLayout = width <= 800
|
const mobileLayout = width <= 800
|
||||||
const normalOrMobile = mobileLayout ? 'mobile' : 'normal'
|
const normalOrMobile = mobileLayout ? 'mobile' : 'normal'
|
||||||
const { thirdColumnMode } = rootGetters.mergedConfig
|
const { thirdColumnMode } = window.vuex.getters.mergedConfig
|
||||||
if (thirdColumnMode === 'none' || !rootState.users.currentUser) {
|
if (thirdColumnMode === 'none' || !window.vuex.state.users.currentUser) {
|
||||||
commit('setLayoutType', normalOrMobile)
|
this.layoutType = normalOrMobile
|
||||||
} else {
|
} else {
|
||||||
const wideLayout = width >= 1300
|
const wideLayout = width >= 1300
|
||||||
commit('setLayoutType', wideLayout ? 'wide' : normalOrMobile)
|
this.layoutType = wideLayout ? 'wide' : normalOrMobile
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
queryLocalFonts ({ commit, dispatch, state }) {
|
setFontsList (value) {
|
||||||
if (state.localFonts !== null) return
|
this.localFonts = [...(new Set(value.map(font => font.family))).values()]
|
||||||
commit('setFontsList', [])
|
},
|
||||||
if (!state.browserSupport.localFonts) {
|
queryLocalFonts () {
|
||||||
|
if (this.localFonts !== null) return
|
||||||
|
this.setFontsList([])
|
||||||
|
|
||||||
|
if (!this.browserSupport.localFonts) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
window
|
window
|
||||||
.queryLocalFonts()
|
.queryLocalFonts()
|
||||||
.then((fonts) => {
|
.then((fonts) => {
|
||||||
commit('setFontsList', fonts)
|
this.setFontsList(fonts)
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
dispatch('pushGlobalNotice', {
|
this.pushGlobalNotice({
|
||||||
messageKey: 'settings.style.themes3.font.font_list_unavailable',
|
messageKey: 'settings.style.themes3.font.font_list_unavailable',
|
||||||
messageArgs: {
|
messageArgs: {
|
||||||
error: e
|
error: e
|
||||||
|
@ -223,118 +173,118 @@ const interfaceMod = {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setLastTimeline ({ commit }, value) {
|
setLastTimeline (value) {
|
||||||
commit('setLastTimeline', value)
|
this.lastTimeline = value
|
||||||
},
|
},
|
||||||
async fetchPalettesIndex ({ commit, state }) {
|
async fetchPalettesIndex () {
|
||||||
try {
|
try {
|
||||||
const value = await getResourcesIndex('/static/palettes/index.json')
|
const value = await getResourcesIndex('/static/palettes/index.json')
|
||||||
commit('setInstanceOption', { name: 'palettesIndex', value })
|
window.vuex.commit('setInstanceOption', { name: 'palettesIndex', value })
|
||||||
return value
|
return value
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Could not fetch palettes index', e)
|
console.error('Could not fetch palettes index', e)
|
||||||
commit('setInstanceOption', { name: 'palettesIndex', value: { _error: e } })
|
window.vuex.commit('setInstanceOption', { name: 'palettesIndex', value: { _error: e } })
|
||||||
return Promise.resolve({})
|
return Promise.resolve({})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setPalette ({ dispatch, commit }, value) {
|
setPalette (value) {
|
||||||
dispatch('resetThemeV3Palette')
|
this.resetThemeV3Palette()
|
||||||
dispatch('resetThemeV2')
|
this.resetThemeV2()
|
||||||
|
|
||||||
commit('setOption', { name: 'palette', value })
|
window.vuex.commit('setOption', { name: 'palette', value })
|
||||||
|
|
||||||
dispatch('applyTheme', { recompile: true })
|
this.applyTheme({ recompile: true })
|
||||||
},
|
},
|
||||||
setPaletteCustom ({ dispatch, commit }, value) {
|
setPaletteCustom (value) {
|
||||||
dispatch('resetThemeV3Palette')
|
this.resetThemeV3Palette()
|
||||||
dispatch('resetThemeV2')
|
this.resetThemeV2()
|
||||||
|
|
||||||
commit('setOption', { name: 'paletteCustomData', value })
|
window.vuex.commit('setOption', { name: 'paletteCustomData', value })
|
||||||
|
|
||||||
dispatch('applyTheme', { recompile: true })
|
this.applyTheme({ recompile: true })
|
||||||
},
|
},
|
||||||
async fetchStylesIndex ({ commit, state }) {
|
async fetchStylesIndex () {
|
||||||
try {
|
try {
|
||||||
const value = await getResourcesIndex(
|
const value = await getResourcesIndex(
|
||||||
'/static/styles/index.json',
|
'/static/styles/index.json',
|
||||||
deserialize
|
deserialize
|
||||||
)
|
)
|
||||||
commit('setInstanceOption', { name: 'stylesIndex', value })
|
window.vuex.commit('setInstanceOption', { name: 'stylesIndex', value })
|
||||||
return value
|
return value
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Could not fetch styles index', e)
|
console.error('Could not fetch styles index', e)
|
||||||
commit('setInstanceOption', { name: 'stylesIndex', value: { _error: e } })
|
window.vuex.commit('setInstanceOption', { name: 'stylesIndex', value: { _error: e } })
|
||||||
return Promise.resolve({})
|
return Promise.resolve({})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setStyle ({ dispatch, commit, state }, value) {
|
setStyle (value) {
|
||||||
dispatch('resetThemeV3')
|
this.resetThemeV3()
|
||||||
dispatch('resetThemeV2')
|
this.resetThemeV2()
|
||||||
dispatch('resetThemeV3Palette')
|
this.resetThemeV3Palette()
|
||||||
|
|
||||||
commit('setOption', { name: 'style', value })
|
window.vuex.commit('setOption', { name: 'style', value })
|
||||||
state.useStylePalette = true
|
this.useStylePalette = true
|
||||||
|
|
||||||
dispatch('applyTheme', { recompile: true }).then(() => {
|
this.applyTheme({ recompile: true }).then(() => {
|
||||||
state.useStylePalette = false
|
this.useStylePalette = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setStyleCustom ({ dispatch, commit, state }, value) {
|
setStyleCustom (value) {
|
||||||
dispatch('resetThemeV3')
|
this.resetThemeV3()
|
||||||
dispatch('resetThemeV2')
|
this.resetThemeV2()
|
||||||
dispatch('resetThemeV3Palette')
|
this.resetThemeV3Palette()
|
||||||
|
|
||||||
commit('setOption', { name: 'styleCustomData', value })
|
window.vuex.commit('setOption', { name: 'styleCustomData', value })
|
||||||
|
|
||||||
state.useStylePalette = true
|
this.useStylePalette = true
|
||||||
dispatch('applyTheme', { recompile: true }).then(() => {
|
this.applyTheme({ recompile: true }).then(() => {
|
||||||
state.useStylePalette = false
|
this.useStylePalette = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async fetchThemesIndex ({ commit, state }) {
|
async fetchThemesIndex () {
|
||||||
try {
|
try {
|
||||||
const value = await getResourcesIndex('/static/styles.json')
|
const value = await getResourcesIndex('/static/styles.json')
|
||||||
commit('setInstanceOption', { name: 'themesIndex', value })
|
window.vuex.commit('setInstanceOption', { name: 'themesIndex', value })
|
||||||
return value
|
return value
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Could not fetch themes index', e)
|
console.error('Could not fetch themes index', e)
|
||||||
commit('setInstanceOption', { name: 'themesIndex', value: { _error: e } })
|
window.vuex.commit('setInstanceOption', { name: 'themesIndex', value: { _error: e } })
|
||||||
return Promise.resolve({})
|
return Promise.resolve({})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setTheme ({ dispatch, commit }, value) {
|
setTheme (value) {
|
||||||
dispatch('resetThemeV3')
|
this.resetThemeV3()
|
||||||
dispatch('resetThemeV3Palette')
|
this.resetThemeV3Palette()
|
||||||
dispatch('resetThemeV2')
|
this.resetThemeV2()
|
||||||
|
|
||||||
commit('setOption', { name: 'theme', value })
|
window.vuex.commit('setOption', { name: 'theme', value })
|
||||||
|
|
||||||
dispatch('applyTheme', { recompile: true })
|
this.applyTheme({ recompile: true })
|
||||||
},
|
},
|
||||||
setThemeCustom ({ dispatch, commit }, value) {
|
setThemeCustom (value) {
|
||||||
dispatch('resetThemeV3')
|
this.resetThemeV3()
|
||||||
dispatch('resetThemeV3Palette')
|
this.resetThemeV3Palette()
|
||||||
dispatch('resetThemeV2')
|
this.resetThemeV2()
|
||||||
|
|
||||||
commit('setOption', { name: 'customTheme', value })
|
window.vuex.commit('setOption', { name: 'customTheme', value })
|
||||||
commit('setOption', { name: 'customThemeSource', value })
|
window.vuex.commit('setOption', { name: 'customThemeSource', value })
|
||||||
|
|
||||||
dispatch('applyTheme', { recompile: true })
|
this.applyTheme({ recompile: true })
|
||||||
},
|
},
|
||||||
resetThemeV3 ({ dispatch, commit }) {
|
resetThemeV3 () {
|
||||||
commit('setOption', { name: 'style', value: null })
|
window.vuex.commit('setOption', { name: 'style', value: null })
|
||||||
commit('setOption', { name: 'styleCustomData', value: null })
|
window.vuex.commit('setOption', { name: 'styleCustomData', value: null })
|
||||||
},
|
},
|
||||||
resetThemeV3Palette ({ dispatch, commit }) {
|
resetThemeV3Palette () {
|
||||||
commit('setOption', { name: 'palette', value: null })
|
window.vuex.commit('setOption', { name: 'palette', value: null })
|
||||||
commit('setOption', { name: 'paletteCustomData', value: null })
|
window.vuex.commit('setOption', { name: 'paletteCustomData', value: null })
|
||||||
},
|
},
|
||||||
resetThemeV2 ({ dispatch, commit }) {
|
resetThemeV2 () {
|
||||||
commit('setOption', { name: 'theme', value: null })
|
window.vuex.commit('setOption', { name: 'theme', value: null })
|
||||||
commit('setOption', { name: 'customTheme', value: null })
|
window.vuex.commit('setOption', { name: 'customTheme', value: null })
|
||||||
commit('setOption', { name: 'customThemeSource', value: null })
|
window.vuex.commit('setOption', { name: 'customThemeSource', value: null })
|
||||||
},
|
},
|
||||||
async getThemeData ({ dispatch, commit, rootState, state }) {
|
async getThemeData () {
|
||||||
const getData = async (resource, index, customData, name) => {
|
const getData = async (resource, index, customData, name) => {
|
||||||
const capitalizedResource = resource[0].toUpperCase() + resource.slice(1)
|
const capitalizedResource = resource[0].toUpperCase() + resource.slice(1)
|
||||||
const result = {}
|
const result = {}
|
||||||
|
@ -358,7 +308,7 @@ const interfaceMod = {
|
||||||
}
|
}
|
||||||
const newName = Object.keys(index)[0]
|
const newName = Object.keys(index)[0]
|
||||||
fetchFunc = index[newName]
|
fetchFunc = index[newName]
|
||||||
console.warn(`${capitalizedResource} with id '${state.styleNameUsed}' not found, trying back to '${newName}'`)
|
console.warn(`${capitalizedResource} with id '${this.styleNameUsed}' not found, trying back to '${newName}'`)
|
||||||
if (!fetchFunc) {
|
if (!fetchFunc) {
|
||||||
console.warn(`${capitalizedResource} doesn't have a fallback, defaulting to stock.`)
|
console.warn(`${capitalizedResource} doesn't have a fallback, defaulting to stock.`)
|
||||||
fetchFunc = () => Promise.resolve(null)
|
fetchFunc = () => Promise.resolve(null)
|
||||||
|
@ -372,27 +322,27 @@ const interfaceMod = {
|
||||||
const {
|
const {
|
||||||
style: instanceStyleName,
|
style: instanceStyleName,
|
||||||
palette: instancePaletteName
|
palette: instancePaletteName
|
||||||
} = rootState.instance
|
} = window.vuex.state.instance
|
||||||
|
|
||||||
let {
|
let {
|
||||||
theme: instanceThemeV2Name,
|
theme: instanceThemeV2Name,
|
||||||
themesIndex,
|
themesIndex,
|
||||||
stylesIndex,
|
stylesIndex,
|
||||||
palettesIndex
|
palettesIndex
|
||||||
} = rootState.instance
|
} = window.vuex.state.instance
|
||||||
|
|
||||||
const {
|
const {
|
||||||
style: userStyleName,
|
style: userStyleName,
|
||||||
styleCustomData: userStyleCustomData,
|
styleCustomData: userStyleCustomData,
|
||||||
palette: userPaletteName,
|
palette: userPaletteName,
|
||||||
paletteCustomData: userPaletteCustomData
|
paletteCustomData: userPaletteCustomData
|
||||||
} = rootState.config
|
} = window.vuex.state.config
|
||||||
|
|
||||||
let {
|
let {
|
||||||
theme: userThemeV2Name,
|
theme: userThemeV2Name,
|
||||||
customTheme: userThemeV2Snapshot,
|
customTheme: userThemeV2Snapshot,
|
||||||
customThemeSource: userThemeV2Source
|
customThemeSource: userThemeV2Source
|
||||||
} = rootState.config
|
} = window.vuex.state.config
|
||||||
|
|
||||||
let majorVersionUsed
|
let majorVersionUsed
|
||||||
|
|
||||||
|
@ -437,8 +387,8 @@ const interfaceMod = {
|
||||||
|
|
||||||
if (majorVersionUsed === 'v3') {
|
if (majorVersionUsed === 'v3') {
|
||||||
const result = await Promise.all([
|
const result = await Promise.all([
|
||||||
dispatch('fetchPalettesIndex'),
|
this.fetchPalettesIndex(),
|
||||||
dispatch('fetchStylesIndex')
|
this.fetchStylesIndex()
|
||||||
])
|
])
|
||||||
|
|
||||||
palettesIndex = result[0]
|
palettesIndex = result[0]
|
||||||
|
@ -446,19 +396,19 @@ const interfaceMod = {
|
||||||
} else {
|
} else {
|
||||||
// Promise.all just to be uniform with v3
|
// Promise.all just to be uniform with v3
|
||||||
const result = await Promise.all([
|
const result = await Promise.all([
|
||||||
dispatch('fetchThemesIndex')
|
this.fetchThemesIndex()
|
||||||
])
|
])
|
||||||
|
|
||||||
themesIndex = result[0]
|
themesIndex = result[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
state.themeVersion = majorVersionUsed
|
this.themeVersion = majorVersionUsed
|
||||||
|
|
||||||
console.debug('Version used', majorVersionUsed)
|
console.debug('Version used', majorVersionUsed)
|
||||||
|
|
||||||
if (majorVersionUsed === 'v3') {
|
if (majorVersionUsed === 'v3') {
|
||||||
state.themeDataUsed = null
|
this.themeDataUsed = null
|
||||||
state.themeNameUsed = null
|
this.themeNameUsed = null
|
||||||
|
|
||||||
const style = await getData(
|
const style = await getData(
|
||||||
'style',
|
'style',
|
||||||
|
@ -466,8 +416,8 @@ const interfaceMod = {
|
||||||
userStyleCustomData,
|
userStyleCustomData,
|
||||||
userStyleName || instanceStyleName
|
userStyleName || instanceStyleName
|
||||||
)
|
)
|
||||||
state.styleNameUsed = style.nameUsed
|
this.styleNameUsed = style.nameUsed
|
||||||
state.styleDataUsed = style.dataUsed
|
this.styleDataUsed = style.dataUsed
|
||||||
|
|
||||||
let firstStylePaletteName = null
|
let firstStylePaletteName = null
|
||||||
style
|
style
|
||||||
|
@ -492,21 +442,21 @@ const interfaceMod = {
|
||||||
'palette',
|
'palette',
|
||||||
palettesIndex,
|
palettesIndex,
|
||||||
userPaletteCustomData,
|
userPaletteCustomData,
|
||||||
state.useStylePalette ? firstStylePaletteName : (userPaletteName || instancePaletteName)
|
this.useStylePalette ? firstStylePaletteName : (userPaletteName || instancePaletteName)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (state.useStylePalette) {
|
if (this.useStylePalette) {
|
||||||
commit('setOption', { name: 'palette', value: firstStylePaletteName })
|
window.vuex.commit('setOption', { name: 'palette', value: firstStylePaletteName })
|
||||||
}
|
}
|
||||||
|
|
||||||
state.paletteNameUsed = palette.nameUsed
|
this.paletteNameUsed = palette.nameUsed
|
||||||
state.paletteDataUsed = palette.dataUsed
|
this.paletteDataUsed = palette.dataUsed
|
||||||
|
|
||||||
if (state.paletteDataUsed) {
|
if (this.paletteDataUsed) {
|
||||||
state.paletteDataUsed.link = state.paletteDataUsed.link || state.paletteDataUsed.accent
|
this.paletteDataUsed.link = this.paletteDataUsed.link || this.paletteDataUsed.accent
|
||||||
state.paletteDataUsed.accent = state.paletteDataUsed.accent || state.paletteDataUsed.link
|
this.paletteDataUsed.accent = this.paletteDataUsed.accent || this.paletteDataUsed.link
|
||||||
}
|
}
|
||||||
if (Array.isArray(state.paletteDataUsed)) {
|
if (Array.isArray(this.paletteDataUsed)) {
|
||||||
const [
|
const [
|
||||||
name,
|
name,
|
||||||
bg,
|
bg,
|
||||||
|
@ -518,7 +468,7 @@ const interfaceMod = {
|
||||||
cBlue = '#0000FF',
|
cBlue = '#0000FF',
|
||||||
cOrange = '#E3FF00'
|
cOrange = '#E3FF00'
|
||||||
] = palette.dataUsed
|
] = palette.dataUsed
|
||||||
state.paletteDataUsed = {
|
this.paletteDataUsed = {
|
||||||
name,
|
name,
|
||||||
bg,
|
bg,
|
||||||
fg,
|
fg,
|
||||||
|
@ -533,10 +483,10 @@ const interfaceMod = {
|
||||||
}
|
}
|
||||||
console.debug('Palette data used', palette.dataUsed)
|
console.debug('Palette data used', palette.dataUsed)
|
||||||
} else {
|
} else {
|
||||||
state.styleNameUsed = null
|
this.styleNameUsed = null
|
||||||
state.styleDataUsed = null
|
this.styleDataUsed = null
|
||||||
state.paletteNameUsed = null
|
this.paletteNameUsed = null
|
||||||
state.paletteDataUsed = null
|
this.paletteDataUsed = null
|
||||||
|
|
||||||
const theme = await getData(
|
const theme = await getData(
|
||||||
'theme',
|
'theme',
|
||||||
|
@ -544,41 +494,43 @@ const interfaceMod = {
|
||||||
userThemeV2Source || userThemeV2Snapshot,
|
userThemeV2Source || userThemeV2Snapshot,
|
||||||
userThemeV2Name || instanceThemeV2Name
|
userThemeV2Name || instanceThemeV2Name
|
||||||
)
|
)
|
||||||
state.themeNameUsed = theme.nameUsed
|
this.themeNameUsed = theme.nameUsed
|
||||||
state.themeDataUsed = theme.dataUsed
|
this.themeDataUsed = theme.dataUsed
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async setThemeApplied () {
|
||||||
|
this.themeApplied = true
|
||||||
|
},
|
||||||
async applyTheme (
|
async applyTheme (
|
||||||
{ dispatch, commit, rootState, state },
|
|
||||||
{ recompile = false } = {}
|
{ recompile = false } = {}
|
||||||
) {
|
) {
|
||||||
const {
|
const {
|
||||||
forceThemeRecompilation,
|
forceThemeRecompilation,
|
||||||
themeDebug,
|
themeDebug,
|
||||||
theme3hacks
|
theme3hacks
|
||||||
} = rootState.config
|
} = window.vuex.state.config
|
||||||
state.themeChangeInProgress = true
|
this.themeChangeInProgress = true
|
||||||
// If we're not not forced to recompile try using
|
// If we're not not forced to recompile try using
|
||||||
// cache (tryLoadCache return true if load successful)
|
// cache (tryLoadCache return true if load successful)
|
||||||
|
|
||||||
const forceRecompile = forceThemeRecompilation || recompile
|
const forceRecompile = forceThemeRecompilation || recompile
|
||||||
if (!forceRecompile && !themeDebug && await tryLoadCache()) {
|
if (!forceRecompile && !themeDebug && await tryLoadCache()) {
|
||||||
state.themeChangeInProgress = false
|
this.themeChangeInProgress = false
|
||||||
return commit('setThemeApplied')
|
return this.setThemeApplied()
|
||||||
}
|
}
|
||||||
window.splashUpdate('splash.theme')
|
window.splashUpdate('splash.theme')
|
||||||
await dispatch('getThemeData')
|
await this.getThemeData()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const paletteIss = (() => {
|
const paletteIss = (() => {
|
||||||
if (!state.paletteDataUsed) return null
|
if (!this.paletteDataUsed) return null
|
||||||
const result = {
|
const result = {
|
||||||
component: 'Root',
|
component: 'Root',
|
||||||
directives: {}
|
directives: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Object
|
Object
|
||||||
.entries(state.paletteDataUsed)
|
.entries(this.paletteDataUsed)
|
||||||
.filter(([k]) => k !== 'name')
|
.filter(([k]) => k !== 'name')
|
||||||
.forEach(([k, v]) => {
|
.forEach(([k, v]) => {
|
||||||
let issRootDirectiveName
|
let issRootDirectiveName
|
||||||
|
@ -597,7 +549,7 @@ const interfaceMod = {
|
||||||
return result
|
return result
|
||||||
})()
|
})()
|
||||||
|
|
||||||
const theme2ruleset = state.themeDataUsed && convertTheme2To3(normalizeThemeData(state.themeDataUsed))
|
const theme2ruleset = this.themeDataUsed && convertTheme2To3(normalizeThemeData(this.themeDataUsed))
|
||||||
const hacks = []
|
const hacks = []
|
||||||
|
|
||||||
Object.entries(theme3hacks).forEach(([key, value]) => {
|
Object.entries(theme3hacks).forEach(([key, value]) => {
|
||||||
|
@ -664,16 +616,16 @@ const interfaceMod = {
|
||||||
|
|
||||||
const rulesetArray = [
|
const rulesetArray = [
|
||||||
theme2ruleset,
|
theme2ruleset,
|
||||||
state.styleDataUsed,
|
this.styleDataUsed,
|
||||||
paletteIss,
|
paletteIss,
|
||||||
hacks
|
hacks
|
||||||
].filter(x => x)
|
].filter(x => x)
|
||||||
|
|
||||||
return applyTheme(
|
return applyTheme(
|
||||||
rulesetArray.flat(),
|
rulesetArray.flat(),
|
||||||
() => commit('setThemeApplied'),
|
() => this.setThemeApplied(),
|
||||||
() => {
|
() => {
|
||||||
state.themeChangeInProgress = false
|
this.themeChangeInProgress = false
|
||||||
},
|
},
|
||||||
themeDebug
|
themeDebug
|
||||||
)
|
)
|
||||||
|
@ -682,9 +634,7 @@ const interfaceMod = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
export default interfaceMod
|
|
||||||
|
|
||||||
export const normalizeThemeData = (input) => {
|
export const normalizeThemeData = (input) => {
|
||||||
let themeData, themeSource
|
let themeData, themeSource
|
110
src/stores/lists.js
Normal file
110
src/stores/lists.js
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
import { remove, find } from 'lodash'
|
||||||
|
|
||||||
|
export const useListsStore = defineStore('lists', {
|
||||||
|
state: () => ({
|
||||||
|
allLists: [],
|
||||||
|
allListsObject: {}
|
||||||
|
}),
|
||||||
|
getters: {
|
||||||
|
findListTitle (state) {
|
||||||
|
return (id) => {
|
||||||
|
if (!this.allListsObject[id]) return
|
||||||
|
return this.allListsObject[id].title
|
||||||
|
}
|
||||||
|
},
|
||||||
|
findListAccounts (state) {
|
||||||
|
return (id) => [...this.allListsObject[id].accountIds]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setLists (value) {
|
||||||
|
this.allLists = value
|
||||||
|
},
|
||||||
|
createList ({ title }) {
|
||||||
|
return window.vuex.state.api.backendInteractor.createList({ title })
|
||||||
|
.then((list) => {
|
||||||
|
this.setList({ listId: list.id, title })
|
||||||
|
return list
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fetchList ({ listId }) {
|
||||||
|
return window.vuex.state.api.backendInteractor.getList({ listId })
|
||||||
|
.then((list) => this.setList({ listId: list.id, title: list.title }))
|
||||||
|
},
|
||||||
|
fetchListAccounts ({ listId }) {
|
||||||
|
return window.vuex.state.api.backendInteractor.getListAccounts({ listId })
|
||||||
|
.then((accountIds) => {
|
||||||
|
if (!this.allListsObject[listId]) {
|
||||||
|
this.allListsObject[listId] = { accountIds: [] }
|
||||||
|
}
|
||||||
|
this.allListsObject[listId].accountIds = accountIds
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setList ({ listId, title }) {
|
||||||
|
if (!this.allListsObject[listId]) {
|
||||||
|
this.allListsObject[listId] = { accountIds: [] }
|
||||||
|
}
|
||||||
|
this.allListsObject[listId].title = title
|
||||||
|
|
||||||
|
const entry = find(this.allLists, { id: listId })
|
||||||
|
if (!entry) {
|
||||||
|
this.allLists.push({ id: listId, title })
|
||||||
|
} else {
|
||||||
|
entry.title = title
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setListAccounts ({ listId, accountIds }) {
|
||||||
|
const saved = this.allListsObject[listId]?.accountIds || []
|
||||||
|
const added = accountIds.filter(id => !saved.includes(id))
|
||||||
|
const removed = saved.filter(id => !accountIds.includes(id))
|
||||||
|
if (!this.allListsObject[listId]) {
|
||||||
|
this.allListsObject[listId] = { accountIds: [] }
|
||||||
|
}
|
||||||
|
this.allListsObject[listId].accountIds = accountIds
|
||||||
|
if (added.length > 0) {
|
||||||
|
window.vuex.state.api.backendInteractor.addAccountsToList({ listId, accountIds: added })
|
||||||
|
}
|
||||||
|
if (removed.length > 0) {
|
||||||
|
window.vuex.state.api.backendInteractor.removeAccountsFromList({ listId, accountIds: removed })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addListAccount ({ listId, accountId }) {
|
||||||
|
return window.vuex.state
|
||||||
|
.api
|
||||||
|
.backendInteractor
|
||||||
|
.addAccountsToList({ listId, accountIds: [accountId] })
|
||||||
|
.then((result) => {
|
||||||
|
if (!this.allListsObject[listId]) {
|
||||||
|
this.allListsObject[listId] = { accountIds: [] }
|
||||||
|
}
|
||||||
|
this.allListsObject[listId].accountIds.push(accountId)
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
},
|
||||||
|
removeListAccount ({ listId, accountId }) {
|
||||||
|
return window.vuex.state
|
||||||
|
.api
|
||||||
|
.backendInteractor
|
||||||
|
.removeAccountsFromList({ listId, accountIds: [accountId] })
|
||||||
|
.then((result) => {
|
||||||
|
if (!this.allListsObject[listId]) {
|
||||||
|
this.allListsObject[listId] = { accountIds: [] }
|
||||||
|
}
|
||||||
|
const { accountIds } = this.allListsObject[listId]
|
||||||
|
const set = new Set(accountIds)
|
||||||
|
set.delete(accountId)
|
||||||
|
this.allListsObject[listId].accountIds = [...set]
|
||||||
|
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
},
|
||||||
|
deleteList ({ listId }) {
|
||||||
|
window.vuex.state.api.backendInteractor.deleteList({ listId })
|
||||||
|
|
||||||
|
delete this.allListsObject[listId]
|
||||||
|
remove(this.allLists, list => list.id === listId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
30
src/stores/media_viewer.js
Normal file
30
src/stores/media_viewer.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import fileTypeService from '../services/file_type/file_type.service.js'
|
||||||
|
|
||||||
|
const supportedTypes = new Set(['image', 'video', 'audio', 'flash'])
|
||||||
|
|
||||||
|
export const useMediaViewerStore = defineStore('mediaViewer', {
|
||||||
|
state: () => ({
|
||||||
|
media: [],
|
||||||
|
currentIndex: 0,
|
||||||
|
activated: false
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
setMedia (attachments) {
|
||||||
|
const media = attachments.filter(attachment => {
|
||||||
|
const type = fileTypeService.fileType(attachment.mimetype)
|
||||||
|
return supportedTypes.has(type)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.media = media
|
||||||
|
},
|
||||||
|
setCurrentMedia (current) {
|
||||||
|
const index = this.media.indexOf(current)
|
||||||
|
this.activated = true
|
||||||
|
this.currentIndex = index
|
||||||
|
},
|
||||||
|
closeMediaViewer () {
|
||||||
|
this.activated = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
57
src/stores/polls.js
Normal file
57
src/stores/polls.js
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { merge } from 'lodash'
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
export const usePollsStore = defineStore('polls', {
|
||||||
|
state: () => ({
|
||||||
|
// Contains key = id, value = number of trackers for this poll
|
||||||
|
trackedPolls: {},
|
||||||
|
pollsObject: {}
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
mergeOrAddPoll (poll) {
|
||||||
|
const existingPoll = this.pollsObject[poll.id]
|
||||||
|
// Make expired-state change trigger re-renders properly
|
||||||
|
poll.expired = Date.now() > Date.parse(poll.expires_at)
|
||||||
|
if (existingPoll) {
|
||||||
|
this.pollsObject[poll.id] = merge(existingPoll, poll)
|
||||||
|
} else {
|
||||||
|
this.pollsObject[poll.id] = poll
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateTrackedPoll (pollId) {
|
||||||
|
window.vuex.state.api.backendInteractor.fetchPoll({ pollId }).then(poll => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.trackedPolls[pollId]) {
|
||||||
|
this.updateTrackedPoll(pollId)
|
||||||
|
}
|
||||||
|
}, 30 * 1000)
|
||||||
|
this.mergeOrAddPoll(poll)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
trackPoll (pollId) {
|
||||||
|
if (!this.trackedPolls[pollId]) {
|
||||||
|
setTimeout(() => this.updateTrackedPoll(pollId), 30 * 1000)
|
||||||
|
}
|
||||||
|
const currentValue = this.trackedPolls[pollId]
|
||||||
|
if (currentValue) {
|
||||||
|
this.trackedPolls[pollId] = currentValue + 1
|
||||||
|
} else {
|
||||||
|
this.trackedPolls[pollId] = 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
untrackPoll (pollId) {
|
||||||
|
const currentValue = this.trackedPolls[pollId]
|
||||||
|
if (currentValue) {
|
||||||
|
this.trackedPolls[pollId] = currentValue - 1
|
||||||
|
} else {
|
||||||
|
this.trackedPolls[pollId] = 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
votePoll ({ id, pollId, choices }) {
|
||||||
|
return window.vuex.state.api.backendInteractor.vote({ pollId, choices }).then(poll => {
|
||||||
|
this.mergeOrAddPoll(poll)
|
||||||
|
return poll
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
17
src/stores/postStatus.js
Normal file
17
src/stores/postStatus.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
export const usePostStatusStore = defineStore('postStatus', {
|
||||||
|
state: () => ({
|
||||||
|
params: null,
|
||||||
|
modalActivated: false
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
openPostStatusModal (params) {
|
||||||
|
this.params = params
|
||||||
|
this.modalActivated = true
|
||||||
|
},
|
||||||
|
closePostStatusModal () {
|
||||||
|
this.modalActivated = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
52
src/stores/reports.js
Normal file
52
src/stores/reports.js
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
import filter from 'lodash/filter'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
|
export const useReportsStore = defineStore('reports', {
|
||||||
|
state: () => ({
|
||||||
|
reportModal: {
|
||||||
|
userId: null,
|
||||||
|
statuses: [],
|
||||||
|
preTickedIds: [],
|
||||||
|
activated: false
|
||||||
|
},
|
||||||
|
reports: {}
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
openUserReportingModal ({ userId, statusIds = [] }) {
|
||||||
|
const preTickedStatuses = statusIds.map(id => window.vuex.state.statuses.allStatusesObject[id])
|
||||||
|
const preTickedIds = statusIds
|
||||||
|
const statuses = preTickedStatuses.concat(
|
||||||
|
filter(window.vuex.state.statuses.allStatuses,
|
||||||
|
status => status.user.id === userId && !preTickedIds.includes(status.id)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
this.reportModal.userId = userId
|
||||||
|
this.reportModal.statuses = statuses
|
||||||
|
this.reportModal.preTickedIds = preTickedIds
|
||||||
|
this.reportModal.activated = true
|
||||||
|
},
|
||||||
|
closeUserReportingModal () {
|
||||||
|
this.reportModal.activated = false
|
||||||
|
},
|
||||||
|
setReportState ({ id, state }) {
|
||||||
|
const oldState = window.vuex.state.reports.reports[id].state
|
||||||
|
this.reports[id].state = state
|
||||||
|
window.vuex.state.api.backendInteractor.setReportState({ id, state }).catch(e => {
|
||||||
|
console.error('Failed to set report state', e)
|
||||||
|
useInterfaceStore().pushGlobalNotice({
|
||||||
|
level: 'error',
|
||||||
|
messageKey: 'general.generic_error_message',
|
||||||
|
messageArgs: [e.message],
|
||||||
|
timeout: 5000
|
||||||
|
})
|
||||||
|
this.reports[id].state = oldState
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addReport (report) {
|
||||||
|
this.reports[report.id] = report
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
32
src/stores/shout.js
Normal file
32
src/stores/shout.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
export const useShoutStore = defineStore('shout', {
|
||||||
|
state: () => ({
|
||||||
|
messages: [],
|
||||||
|
channel: { state: '' },
|
||||||
|
joined: false
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
initializeShout (socket) {
|
||||||
|
const channel = socket.channel('chat:public')
|
||||||
|
channel.joinPush.receive('ok', () => {
|
||||||
|
this.joined = true
|
||||||
|
})
|
||||||
|
channel.onClose(() => {
|
||||||
|
this.joined = false
|
||||||
|
})
|
||||||
|
channel.onError(() => {
|
||||||
|
this.joined = false
|
||||||
|
})
|
||||||
|
channel.on('new_msg', (msg) => {
|
||||||
|
this.messages.push(msg)
|
||||||
|
this.messages = this.messages.slice(-19, 20)
|
||||||
|
})
|
||||||
|
channel.on('messages', ({ messages }) => {
|
||||||
|
this.messages = messages.slice(-19, 20)
|
||||||
|
})
|
||||||
|
channel.join()
|
||||||
|
this.channel = channel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
17
src/stores/statusHistory.js
Normal file
17
src/stores/statusHistory.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
export const useStatusHistoryStore = defineStore('statusHistory', {
|
||||||
|
state: () => ({
|
||||||
|
params: {},
|
||||||
|
modalActivated: false
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
openStatusHistoryModal (params) {
|
||||||
|
this.params = params
|
||||||
|
this.modalActivated = true
|
||||||
|
},
|
||||||
|
closeStatusHistoryModal () {
|
||||||
|
this.modalActivated = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
|
@ -1,83 +0,0 @@
|
||||||
import { cloneDeep } from 'lodash'
|
|
||||||
import { defaultState, mutations, getters } from '../../../../src/modules/lists.js'
|
|
||||||
|
|
||||||
describe('The lists module', () => {
|
|
||||||
describe('mutations', () => {
|
|
||||||
it('updates array of all lists', () => {
|
|
||||||
const state = cloneDeep(defaultState)
|
|
||||||
const list = { id: '1', title: 'testList' }
|
|
||||||
|
|
||||||
mutations.setLists(state, [list])
|
|
||||||
expect(state.allLists).to.have.length(1)
|
|
||||||
expect(state.allLists).to.eql([list])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('adds a new list with a title, updating the title for existing lists', () => {
|
|
||||||
const state = cloneDeep(defaultState)
|
|
||||||
const list = { id: '1', title: 'testList' }
|
|
||||||
const modList = { id: '1', title: 'anotherTestTitle' }
|
|
||||||
|
|
||||||
mutations.setList(state, { listId: list.id, title: list.title })
|
|
||||||
expect(state.allListsObject[list.id]).to.eql({ title: list.title, accountIds: [] })
|
|
||||||
expect(state.allLists).to.have.length(1)
|
|
||||||
expect(state.allLists[0]).to.eql(list)
|
|
||||||
|
|
||||||
mutations.setList(state, { listId: modList.id, title: modList.title })
|
|
||||||
expect(state.allListsObject[modList.id]).to.eql({ title: modList.title, accountIds: [] })
|
|
||||||
expect(state.allLists).to.have.length(1)
|
|
||||||
expect(state.allLists[0]).to.eql(modList)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('adds a new list with an array of IDs, updating the IDs for existing lists', () => {
|
|
||||||
const state = cloneDeep(defaultState)
|
|
||||||
const list = { id: '1', accountIds: ['1', '2', '3'] }
|
|
||||||
const modList = { id: '1', accountIds: ['3', '4', '5'] }
|
|
||||||
|
|
||||||
mutations.setListAccounts(state, { listId: list.id, accountIds: list.accountIds })
|
|
||||||
expect(state.allListsObject[list.id]).to.eql({ accountIds: list.accountIds })
|
|
||||||
|
|
||||||
mutations.setListAccounts(state, { listId: modList.id, accountIds: modList.accountIds })
|
|
||||||
expect(state.allListsObject[modList.id]).to.eql({ accountIds: modList.accountIds })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('deletes a list', () => {
|
|
||||||
const state = {
|
|
||||||
allLists: [{ id: '1', title: 'testList' }],
|
|
||||||
allListsObject: {
|
|
||||||
1: { title: 'testList', accountIds: ['1', '2', '3'] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const listId = '1'
|
|
||||||
|
|
||||||
mutations.deleteList(state, { listId })
|
|
||||||
expect(state.allLists).to.have.length(0)
|
|
||||||
expect(state.allListsObject).to.eql({})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('getters', () => {
|
|
||||||
it('returns list title', () => {
|
|
||||||
const state = {
|
|
||||||
allLists: [{ id: '1', title: 'testList' }],
|
|
||||||
allListsObject: {
|
|
||||||
1: { title: 'testList', accountIds: ['1', '2', '3'] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const id = '1'
|
|
||||||
|
|
||||||
expect(getters.findListTitle(state)(id)).to.eql('testList')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('returns list accounts', () => {
|
|
||||||
const state = {
|
|
||||||
allLists: [{ id: '1', title: 'testList' }],
|
|
||||||
allListsObject: {
|
|
||||||
1: { title: 'testList', accountIds: ['1', '2', '3'] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const id = '1'
|
|
||||||
|
|
||||||
expect(getters.findListAccounts(state)(id)).to.eql(['1', '2', '3'])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -74,7 +74,7 @@ describe('The serverSideStorage module', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it.only('should reset local timestamp to remote if contents are the same', () => {
|
it('should reset local timestamp to remote if contents are the same', () => {
|
||||||
const state = {
|
const state = {
|
||||||
...cloneDeep(defaultState),
|
...cloneDeep(defaultState),
|
||||||
cache: null
|
cache: null
|
||||||
|
|
93
test/unit/specs/stores/lists.spec.js
Normal file
93
test/unit/specs/stores/lists.spec.js
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
import { createPinia, setActivePinia } from 'pinia'
|
||||||
|
import { useListsStore } from 'src/stores/lists.js'
|
||||||
|
import { createStore } from 'vuex'
|
||||||
|
import apiModule from 'src/modules/api.js'
|
||||||
|
|
||||||
|
setActivePinia(createPinia())
|
||||||
|
const store = useListsStore()
|
||||||
|
window.vuex = createStore({
|
||||||
|
modules: {
|
||||||
|
api: apiModule
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('The lists store', () => {
|
||||||
|
describe('actions', () => {
|
||||||
|
it('updates array of all lists', () => {
|
||||||
|
store.$reset()
|
||||||
|
const list = { id: '1', title: 'testList' }
|
||||||
|
|
||||||
|
store.setLists([list])
|
||||||
|
expect(store.allLists).to.have.length(1)
|
||||||
|
expect(store.allLists).to.eql([list])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('adds a new list with a title, updating the title for existing lists', () => {
|
||||||
|
store.$reset()
|
||||||
|
const list = { id: '1', title: 'testList' }
|
||||||
|
const modList = { id: '1', title: 'anotherTestTitle' }
|
||||||
|
|
||||||
|
store.setList({ listId: list.id, title: list.title })
|
||||||
|
expect(store.allListsObject[list.id]).to.eql({ title: list.title, accountIds: [] })
|
||||||
|
expect(store.allLists).to.have.length(1)
|
||||||
|
expect(store.allLists[0]).to.eql(list)
|
||||||
|
|
||||||
|
store.setList({ listId: modList.id, title: modList.title })
|
||||||
|
expect(store.allListsObject[modList.id]).to.eql({ title: modList.title, accountIds: [] })
|
||||||
|
expect(store.allLists).to.have.length(1)
|
||||||
|
expect(store.allLists[0]).to.eql(modList)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('adds a new list with an array of IDs, updating the IDs for existing lists', () => {
|
||||||
|
store.$reset()
|
||||||
|
const list = { id: '1', accountIds: ['1', '2', '3'] }
|
||||||
|
const modList = { id: '1', accountIds: ['3', '4', '5'] }
|
||||||
|
|
||||||
|
store.setListAccounts({ listId: list.id, accountIds: list.accountIds })
|
||||||
|
expect(store.allListsObject[list.id].accountIds).to.eql(list.accountIds)
|
||||||
|
|
||||||
|
store.setListAccounts({ listId: modList.id, accountIds: modList.accountIds })
|
||||||
|
expect(store.allListsObject[modList.id].accountIds).to.eql(modList.accountIds)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('deletes a list', () => {
|
||||||
|
store.$patch({
|
||||||
|
allLists: [{ id: '1', title: 'testList' }],
|
||||||
|
allListsObject: {
|
||||||
|
1: { title: 'testList', accountIds: ['1', '2', '3'] }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const listId = '1'
|
||||||
|
|
||||||
|
store.deleteList({ listId })
|
||||||
|
expect(store.allLists).to.have.length(0)
|
||||||
|
expect(store.allListsObject).to.eql({})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('getters', () => {
|
||||||
|
it('returns list title', () => {
|
||||||
|
store.$patch({
|
||||||
|
allLists: [{ id: '1', title: 'testList' }],
|
||||||
|
allListsObject: {
|
||||||
|
1: { title: 'testList', accountIds: ['1', '2', '3'] }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const id = '1'
|
||||||
|
|
||||||
|
expect(store.findListTitle(id)).to.eql('testList')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns list accounts', () => {
|
||||||
|
store.$patch({
|
||||||
|
allLists: [{ id: '1', title: 'testList' }],
|
||||||
|
allListsObject: {
|
||||||
|
1: { title: 'testList', accountIds: ['1', '2', '3'] }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const id = '1'
|
||||||
|
|
||||||
|
expect(store.findListAccounts(id)).to.eql(['1', '2', '3'])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
15
yarn.lock
15
yarn.lock
|
@ -1521,7 +1521,7 @@
|
||||||
"@vue/compiler-dom" "3.5.13"
|
"@vue/compiler-dom" "3.5.13"
|
||||||
"@vue/shared" "3.5.13"
|
"@vue/shared" "3.5.13"
|
||||||
|
|
||||||
"@vue/devtools-api@^6.0.0-beta.11", "@vue/devtools-api@^6.5.0", "@vue/devtools-api@^6.6.4":
|
"@vue/devtools-api@^6.0.0-beta.11", "@vue/devtools-api@^6.5.0", "@vue/devtools-api@^6.6.3", "@vue/devtools-api@^6.6.4":
|
||||||
version "6.6.4"
|
version "6.6.4"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz#cbe97fe0162b365edc1dba80e173f90492535343"
|
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz#cbe97fe0162b365edc1dba80e173f90492535343"
|
||||||
integrity sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==
|
integrity sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==
|
||||||
|
@ -6609,6 +6609,14 @@ pify@^4.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
|
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
|
||||||
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
|
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
|
||||||
|
|
||||||
|
pinia@^2.0.33:
|
||||||
|
version "2.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.3.1.tgz#54c476675b72f5abcfafa24a7582531ea8c23d94"
|
||||||
|
integrity sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==
|
||||||
|
dependencies:
|
||||||
|
"@vue/devtools-api" "^6.6.3"
|
||||||
|
vue-demi "^0.14.10"
|
||||||
|
|
||||||
pirates@^4.0.6:
|
pirates@^4.0.6:
|
||||||
version "4.0.6"
|
version "4.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
|
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
|
||||||
|
@ -8505,6 +8513,11 @@ vue-demi@^0.13.11:
|
||||||
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.13.11.tgz#7d90369bdae8974d87b1973564ad390182410d99"
|
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.13.11.tgz#7d90369bdae8974d87b1973564ad390182410d99"
|
||||||
integrity sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==
|
integrity sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==
|
||||||
|
|
||||||
|
vue-demi@^0.14.10:
|
||||||
|
version "0.14.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.10.tgz#afc78de3d6f9e11bf78c55e8510ee12814522f04"
|
||||||
|
integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==
|
||||||
|
|
||||||
vue-eslint-parser@^9.4.3:
|
vue-eslint-parser@^9.4.3:
|
||||||
version "9.4.3"
|
version "9.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz#9b04b22c71401f1e8bca9be7c3e3416a4bde76a8"
|
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz#9b04b22c71401f1e8bca9be7c3e3416a4bde76a8"
|
||||||
|
|
Loading…
Add table
Reference in a new issue