pleroma-fe/src/modules/config.js

333 lines
11 KiB
JavaScript
Raw Normal View History

import Cookies from 'js-cookie'
import { applyConfig } from '../services/style_setter/style_setter.js'
import messages from '../i18n/messages'
import { set } from 'lodash'
import localeService from '../services/locale/locale.service.js'
const BACKEND_LANGUAGE_COOKIE_NAME = 'userLanguage'
const APPEARANCE_SETTINGS_KEYS = new Set([
'sidebarColumnWidth',
'contentColumnWidth',
'notifsColumnWidth',
'textSize',
'navbarSize',
'panelHeaderSize',
'forcedRoundness',
'emojiSize',
'emojiReactionsScale'
])
const browserLocale = (window.navigator.language || 'en').split('-')[0]
/* TODO this is a bit messy.
* We need to declare settings with their types and also deal with
* instance-default settings in some way, hopefully try to avoid copy-pasta
* in general.
*/
export const multiChoiceProperties = [
'postContentType',
'subjectLineBehavior',
2021-08-07 00:18:27 +00:00
'conversationDisplay', // tree | linear
'conversationOtherRepliesButton', // below | inside
'mentionLinkDisplay', // short | full_for_remote | full
'userPopoverAvatarAction' // close | zoom | open
]
export const defaultState = {
expertLevel: 0, // used to track which settings to show and hide
2024-07-17 19:10:11 +00:00
// 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
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
}
2024-07-17 19:10:11 +00:00
},
hideISP: false,
2020-12-16 16:25:07 +00:00
hideInstanceWallpaper: false,
2021-06-14 19:42:56 +00:00
hideShoutbox: false,
// bad name: actually hides posts of muted USERS
hideMutedPosts: undefined, // instance default
hideMutedThreads: undefined, // instance default
hideWordFilteredPosts: undefined, // instance default
2022-02-28 20:07:20 +00:00
muteBotStatuses: undefined, // instance default
muteSensitiveStatuses: undefined, // instance default
2018-09-25 11:47:02 +00:00
collapseMessageWithSubject: undefined, // instance default
padEmoji: true,
2017-02-22 23:38:05 +00:00
hideAttachments: false,
hideAttachmentsInConv: false,
hideScrobbles: false,
2024-03-25 21:34:19 +00:00
hideScrobblesAfter: '2d',
maxThumbnails: 16,
hideNsfw: true,
preloadImage: true,
loopVideo: true,
loopVideoSilentOnly: true,
streaming: false,
emojiReactionsOnTimeline: true,
2021-06-14 20:41:34 +00:00
alwaysShowNewPostButton: false,
2019-04-25 16:32:21 +00:00
autohideFloatingPostButton: false,
pauseOnUnfocused: true,
2022-02-22 21:32:12 +00:00
stopGifs: true,
replyVisibility: 'all',
thirdColumnMode: 'notifications',
notificationVisibility: {
follows: true,
mentions: true,
statuses: true,
likes: true,
2019-12-10 15:00:10 +00:00
repeats: true,
moves: true,
2021-03-01 14:21:35 +00:00
emojiReactions: true,
2020-05-07 13:10:53 +00:00
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: {},
2018-09-25 11:47:02 +00:00
interfaceLanguage: browserLocale,
hideScopeNotice: false,
2019-12-10 19:30:27 +00:00
useStreamingApi: false,
sidebarRight: undefined, // instance default
2018-09-25 11:47:02 +00:00
scopeCopy: undefined, // instance default
subjectLineBehavior: undefined, // instance default
2019-02-05 11:57:11 +00:00
alwaysShowSubjectInput: undefined, // instance default
postContentType: undefined, // instance default
minimalScopesMode: undefined, // instance default
// This hides statuses filtered via a word filter
hideFilteredStatuses: undefined, // instance default
2022-02-09 20:04:53 +00:00
modalOnRepeat: undefined, // instance default
modalOnUnfollow: undefined, // instance default
modalOnBlock: undefined, // instance default
modalOnMute: undefined, // instance default
modalOnDelete: undefined, // instance default
modalOnLogout: undefined, // instance default
modalOnApproveFollow: undefined, // instance default
modalOnDenyFollow: undefined, // instance default
2022-09-27 22:47:50 +00:00
modalOnRemoveUserFromFollowers: undefined, // instance default
playVideosInModal: false,
useOneClickNsfw: false,
2022-02-22 21:32:12 +00:00
useContainFit: true,
disableStickyHeaders: false,
showScrollbars: false,
userPopoverAvatarAction: 'open',
userPopoverOverlay: false,
2022-08-06 14:26:43 +00:00
sidebarColumnWidth: '25rem',
contentColumnWidth: '45rem',
notifsColumnWidth: '25rem',
emojiReactionsScale: undefined,
textSize: undefined, // instance default
2024-06-12 23:22:47 +00:00
emojiSize: undefined, // instance default
navbarSize: undefined, // instance default
2024-06-21 19:46:01 +00:00
panelHeaderSize: undefined, // instance default
forcedRoundness: undefined, // instance default
navbarColumnStretch: false,
2019-11-13 22:47:20 +00:00
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
2020-09-29 10:18:37 +00:00
hideUserStats: undefined, // instance default
2021-02-23 08:00:23 +00:00
virtualScrolling: undefined, // instance default
2021-08-07 00:18:27 +00:00
sensitiveByDefault: undefined, // instance default
2021-08-08 00:14:14 +00:00
conversationDisplay: undefined, // instance default
conversationTreeAdvanced: undefined, // instance default
conversationOtherRepliesButton: undefined, // instance default
2022-03-06 19:13:35 +00:00
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
2023-11-19 13:24:34 +00:00
autocompleteSelect: undefined, // instance default
closingDrawerMarksAsSeen: undefined, // instance default
unseenAtTop: undefined, // instance default
ignoreInactionableSeen: undefined // instance default
}
// caching the instance default properties
export const instanceDefaultProperties = Object.entries(defaultState)
.filter(([key, value]) => value === undefined)
.map(([key, value]) => key)
const config = {
state: { ...defaultState },
getters: {
defaultConfig (state, getters, rootState, rootGetters) {
const { instance } = rootState
return {
...defaultState,
...Object.fromEntries(
instanceDefaultProperties.map(key => [key, instance[key]])
)
}
},
mergedConfig (state, getters, rootState, rootGetters) {
const { defaultConfig } = rootGetters
return {
...defaultConfig,
// Do not override with undefined
...Object.fromEntries(Object.entries(state).filter(([k, v]) => v !== undefined))
}
}
},
mutations: {
setOptionTemporarily (state, { name, value }) {
set(state, name, value)
applyConfig(state)
},
setOption (state, { name, value }) {
set(state, name, value)
},
setHighlight (state, { user, color, type }) {
const data = this.state.config.highlight[user]
if (color || type) {
2021-04-25 10:24:08 +00:00
state.highlight[user] = { color: color || data.color, type: type || data.type }
} else {
2021-04-25 10:24:08 +00:00
delete state.highlight[user]
}
}
},
actions: {
2021-03-08 17:53:30 +00:00
loadSettings ({ dispatch }, data) {
2021-03-08 19:56:20 +00:00
const knownKeys = new Set(Object.keys(defaultState))
const presentKeys = new Set(Object.keys(data))
const intersection = new Set()
2022-07-31 09:35:48 +00:00
for (const elem of presentKeys) {
if (knownKeys.has(elem)) {
intersection.add(elem)
}
}
2021-03-08 19:56:20 +00:00
intersection.forEach(
2021-03-08 17:53:30 +00:00
name => dispatch('setOption', { name, value: data[name] })
)
},
setHighlight ({ commit, dispatch }, { user, color, type }) {
2019-07-05 07:02:14 +00:00
commit('setHighlight', { user, color, type })
},
setOptionTemporarily ({ commit, dispatch, state, rootState }, { name, value }) {
if (rootState.interface.temporaryChangesTimeoutId !== null) {
console.warn('Can\'t track more than one temporary change')
return
}
const oldValue = state[name]
commit('setOptionTemporarily', { name, value })
const confirm = () => {
dispatch('setOption', { name, value })
commit('clearTemporaryChanges')
}
const revert = () => {
commit('setOptionTemporarily', { name, value: oldValue })
commit('clearTemporaryChanges')
}
commit('setTemporaryChanges', {
timeoutId: setTimeout(revert, 10000),
confirm,
revert
})
},
setThemeV2 ({ commit, dispatch }, { customTheme, customThemeSource }) {
2024-07-17 19:10:11 +00:00
commit('setOption', { name: 'theme', value: 'custom' })
commit('setOption', { name: 'customTheme', value: customTheme })
commit('setOption', { name: 'customThemeSource', value: customThemeSource })
dispatch('setTheme', { themeData: customThemeSource, recompile: true })
},
setOption ({ commit, dispatch, state }, { name, value }) {
const exceptions = new Set([
'useStreamingApi'
])
if (exceptions.has(name)) {
switch (name) {
case 'useStreamingApi': {
const action = value ? 'enableMastoSockets' : 'disableMastoSockets'
dispatch(action).then(() => {
commit('setOption', { name: 'useStreamingApi', value })
}).catch((e) => {
console.error('Failed starting MastoAPI Streaming socket', e)
dispatch('disableMastoSockets')
dispatch('setOption', { name: 'useStreamingApi', value: false })
})
break
}
}
} else {
commit('setOption', { name, value })
if (APPEARANCE_SETTINGS_KEYS.has(name)) {
applyConfig(state)
}
if (name.startsWith('theme3hacks')) {
dispatch('setTheme', { recompile: true })
}
switch (name) {
case 'theme':
2024-07-17 19:10:11 +00:00
if (value === 'custom') break
dispatch('setTheme', { themeName: value, recompile: true, saveData: true })
break
case 'themeDebug': {
dispatch('setTheme', { recompile: true })
break
}
case 'interfaceLanguage':
messages.setLanguage(this.getters.i18n, value)
dispatch('loadUnicodeEmojiData', value)
Cookies.set(
BACKEND_LANGUAGE_COOKIE_NAME,
localeService.internalToBackendLocaleMulti(value)
)
break
case 'thirdColumnMode':
dispatch('setLayoutWidth', undefined)
break
}
}
}
}
}
export default config