2024-10-02 02:35:52 +03:00
|
|
|
import { getResourcesIndex, applyTheme, tryLoadCache } from '../services/style_setter/style_setter.js'
|
2024-07-12 02:13:08 +03:00
|
|
|
import { CURRENT_VERSION, generatePreset } from 'src/services/theme_data/theme_data.service.js'
|
|
|
|
|
import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
|
|
|
|
|
|
2018-09-09 19:36:13 +03:00
|
|
|
const defaultState = {
|
2024-06-26 17:05:59 +03:00
|
|
|
localFonts: null,
|
2024-04-03 22:52:12 +03:00
|
|
|
themeApplied: false,
|
2024-10-03 23:03:33 +03:00
|
|
|
themeVersion: 'v3',
|
2024-05-22 19:54:19 +03:00
|
|
|
temporaryChangesTimeoutId: null, // used for temporary options that revert after a timeout
|
|
|
|
|
temporaryChangesConfirm: () => {}, // used for applying temporary options
|
|
|
|
|
temporaryChangesRevert: () => {}, // used for reverting temporary options
|
2020-05-03 17:36:12 +03:00
|
|
|
settingsModalState: 'hidden',
|
2023-03-14 21:50:43 +02:00
|
|
|
settingsModalLoadedUser: false,
|
|
|
|
|
settingsModalLoadedAdmin: false,
|
2020-09-03 15:45:13 +03:00
|
|
|
settingsModalTargetTab: null,
|
2023-03-14 21:50:43 +02:00
|
|
|
settingsModalMode: 'user',
|
2018-09-09 19:36:13 +03:00
|
|
|
settings: {
|
|
|
|
|
currentSaveStateNotice: null,
|
2018-12-13 18:04:09 +07:00
|
|
|
noticeClearTimeout: null,
|
|
|
|
|
notificationPermission: null
|
2018-11-30 16:39:07 +03:00
|
|
|
},
|
|
|
|
|
browserSupport: {
|
|
|
|
|
cssFilter: window.CSS && window.CSS.supports && (
|
|
|
|
|
window.CSS.supports('filter', 'drop-shadow(0 0)') ||
|
2018-12-13 18:22:15 +07:00
|
|
|
window.CSS.supports('-webkit-filter', 'drop-shadow(0 0)')
|
2024-06-26 17:05:59 +03:00
|
|
|
),
|
|
|
|
|
localFonts: typeof window.queryLocalFonts === 'function'
|
2019-03-03 16:33:40 +02:00
|
|
|
},
|
2022-04-05 18:38:05 +03:00
|
|
|
layoutType: 'normal',
|
2020-05-07 16:10:53 +03:00
|
|
|
globalNotices: [],
|
2020-07-23 15:09:32 +03:00
|
|
|
layoutHeight: 0,
|
|
|
|
|
lastTimeline: null
|
2018-09-09 19:36:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const interfaceMod = {
|
|
|
|
|
state: defaultState,
|
|
|
|
|
mutations: {
|
|
|
|
|
settingsSaved (state, { success, error }) {
|
|
|
|
|
if (success) {
|
|
|
|
|
if (state.noticeClearTimeout) {
|
|
|
|
|
clearTimeout(state.noticeClearTimeout)
|
|
|
|
|
}
|
2021-04-25 13:24:08 +03:00
|
|
|
state.settings.currentSaveStateNotice = { error: false, data: success }
|
|
|
|
|
state.settings.noticeClearTimeout = setTimeout(() => delete state.settings.currentSaveStateNotice, 2000)
|
2018-09-09 19:36:13 +03:00
|
|
|
} else {
|
2021-04-25 13:24:08 +03:00
|
|
|
state.settings.currentSaveStateNotice = { error: true, errorData: error }
|
2018-09-09 19:36:13 +03:00
|
|
|
}
|
2018-12-13 18:04:09 +07:00
|
|
|
},
|
2024-05-22 19:54:19 +03:00
|
|
|
setTemporaryChanges (state, { timeoutId, confirm, revert }) {
|
|
|
|
|
state.temporaryChangesTimeoutId = timeoutId
|
|
|
|
|
state.temporaryChangesConfirm = confirm
|
|
|
|
|
state.temporaryChangesRevert = revert
|
|
|
|
|
},
|
|
|
|
|
clearTemporaryChanges (state) {
|
|
|
|
|
clearTimeout(state.temporaryChangesTimeoutId)
|
|
|
|
|
state.temporaryChangesTimeoutId = null
|
|
|
|
|
state.temporaryChangesConfirm = () => {}
|
|
|
|
|
state.temporaryChangesRevert = () => {}
|
|
|
|
|
},
|
2024-04-03 22:52:12 +03:00
|
|
|
setThemeApplied (state) {
|
|
|
|
|
state.themeApplied = true
|
|
|
|
|
},
|
2018-12-13 18:04:09 +07:00
|
|
|
setNotificationPermission (state, permission) {
|
|
|
|
|
state.notificationPermission = permission
|
2019-03-03 16:33:40 +02:00
|
|
|
},
|
2022-04-05 18:38:05 +03:00
|
|
|
setLayoutType (state, value) {
|
|
|
|
|
state.layoutType = value
|
2020-05-03 17:36:12 +03:00
|
|
|
},
|
|
|
|
|
closeSettingsModal (state) {
|
|
|
|
|
state.settingsModalState = 'hidden'
|
|
|
|
|
},
|
|
|
|
|
togglePeekSettingsModal (state) {
|
|
|
|
|
switch (state.settingsModalState) {
|
|
|
|
|
case 'minimized':
|
|
|
|
|
state.settingsModalState = 'visible'
|
|
|
|
|
return
|
|
|
|
|
case 'visible':
|
|
|
|
|
state.settingsModalState = 'minimized'
|
|
|
|
|
return
|
|
|
|
|
default:
|
|
|
|
|
throw new Error('Illegal minimization state of settings modal')
|
|
|
|
|
}
|
|
|
|
|
},
|
2023-03-14 21:50:43 +02:00
|
|
|
openSettingsModal (state, value) {
|
|
|
|
|
state.settingsModalMode = value
|
2020-05-03 17:36:12 +03:00
|
|
|
state.settingsModalState = 'visible'
|
2023-03-14 21:50:43 +02:00
|
|
|
if (value === 'user') {
|
|
|
|
|
if (!state.settingsModalLoadedUser) {
|
|
|
|
|
state.settingsModalLoadedUser = true
|
|
|
|
|
}
|
|
|
|
|
} else if (value === 'admin') {
|
|
|
|
|
if (!state.settingsModalLoadedAdmin) {
|
|
|
|
|
state.settingsModalLoadedAdmin = true
|
|
|
|
|
}
|
2020-06-02 01:10:52 +03:00
|
|
|
}
|
2020-07-01 19:15:28 +03:00
|
|
|
},
|
2020-09-03 15:45:13 +03:00
|
|
|
setSettingsModalTargetTab (state, value) {
|
|
|
|
|
state.settingsModalTargetTab = value
|
|
|
|
|
},
|
2020-07-02 10:40:41 +03:00
|
|
|
pushGlobalNotice (state, notice) {
|
|
|
|
|
state.globalNotices.push(notice)
|
|
|
|
|
},
|
|
|
|
|
removeGlobalNotice (state, notice) {
|
|
|
|
|
state.globalNotices = state.globalNotices.filter(n => n !== notice)
|
2020-05-07 16:10:53 +03:00
|
|
|
},
|
|
|
|
|
setLayoutHeight (state, value) {
|
|
|
|
|
state.layoutHeight = value
|
2020-07-23 15:09:32 +03:00
|
|
|
},
|
2022-04-12 21:18:06 +03:00
|
|
|
setLayoutWidth (state, value) {
|
|
|
|
|
state.layoutWidth = value
|
|
|
|
|
},
|
2020-07-23 15:09:32 +03:00
|
|
|
setLastTimeline (state, value) {
|
|
|
|
|
state.lastTimeline = value
|
2024-06-26 17:05:59 +03:00
|
|
|
},
|
|
|
|
|
setFontsList (state, value) {
|
2024-07-21 23:45:21 +03:00
|
|
|
// 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()]
|
2018-09-09 19:36:13 +03:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
actions: {
|
2018-09-09 21:21:23 +03:00
|
|
|
setPageTitle ({ rootState }, option = '') {
|
|
|
|
|
document.title = `${option} ${rootState.instance.name}`
|
2018-09-09 19:36:13 +03:00
|
|
|
},
|
|
|
|
|
settingsSaved ({ commit, dispatch }, { success, error }) {
|
|
|
|
|
commit('settingsSaved', { success, error })
|
2018-12-13 18:04:09 +07:00
|
|
|
},
|
|
|
|
|
setNotificationPermission ({ commit }, permission) {
|
|
|
|
|
commit('setNotificationPermission', permission)
|
2019-03-03 16:33:40 +02:00
|
|
|
},
|
2020-05-03 17:36:12 +03:00
|
|
|
closeSettingsModal ({ commit }) {
|
|
|
|
|
commit('closeSettingsModal')
|
|
|
|
|
},
|
2023-03-14 21:50:43 +02:00
|
|
|
openSettingsModal ({ commit }, value = 'user') {
|
|
|
|
|
commit('openSettingsModal', value)
|
2020-05-03 17:36:12 +03:00
|
|
|
},
|
|
|
|
|
togglePeekSettingsModal ({ commit }) {
|
|
|
|
|
commit('togglePeekSettingsModal')
|
2020-07-01 19:15:28 +03:00
|
|
|
},
|
2020-09-03 15:45:13 +03:00
|
|
|
clearSettingsModalTargetTab ({ commit }) {
|
|
|
|
|
commit('setSettingsModalTargetTab', null)
|
|
|
|
|
},
|
|
|
|
|
openSettingsModalTab ({ commit }, value) {
|
|
|
|
|
commit('setSettingsModalTargetTab', value)
|
2023-06-13 14:00:20 -04:00
|
|
|
commit('openSettingsModal', 'user')
|
2020-09-03 15:45:13 +03:00
|
|
|
},
|
2020-07-02 10:40:41 +03:00
|
|
|
pushGlobalNotice (
|
2022-03-27 12:21:33 +03:00
|
|
|
{ commit, dispatch, state },
|
2020-07-02 10:40:41 +03:00
|
|
|
{
|
|
|
|
|
messageKey,
|
|
|
|
|
messageArgs = {},
|
|
|
|
|
level = 'error',
|
|
|
|
|
timeout = 0
|
|
|
|
|
}) {
|
|
|
|
|
const notice = {
|
|
|
|
|
messageKey,
|
|
|
|
|
messageArgs,
|
|
|
|
|
level
|
|
|
|
|
}
|
2022-03-27 12:21:33 +03:00
|
|
|
commit('pushGlobalNotice', notice)
|
|
|
|
|
// 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?
|
|
|
|
|
const newNotice = state.globalNotices[state.globalNotices.length - 1]
|
2020-07-02 10:40:41 +03:00
|
|
|
if (timeout) {
|
2022-03-27 12:21:33 +03:00
|
|
|
setTimeout(() => dispatch('removeGlobalNotice', newNotice), timeout)
|
2020-07-02 10:40:41 +03:00
|
|
|
}
|
2022-03-27 12:21:33 +03:00
|
|
|
return newNotice
|
2020-07-02 10:40:41 +03:00
|
|
|
},
|
|
|
|
|
removeGlobalNotice ({ commit }, notice) {
|
|
|
|
|
commit('removeGlobalNotice', notice)
|
2020-05-07 16:10:53 +03:00
|
|
|
},
|
|
|
|
|
setLayoutHeight ({ commit }, value) {
|
|
|
|
|
commit('setLayoutHeight', value)
|
2020-07-23 15:09:32 +03:00
|
|
|
},
|
2022-04-12 21:18:06 +03:00
|
|
|
// value is optional, assuming it was cached prior
|
2022-05-09 23:24:35 +03:00
|
|
|
setLayoutWidth ({ commit, state, rootGetters, rootState }, value) {
|
2022-04-12 21:18:06 +03:00
|
|
|
let width = value
|
|
|
|
|
if (value !== undefined) {
|
|
|
|
|
commit('setLayoutWidth', value)
|
|
|
|
|
} else {
|
|
|
|
|
width = state.layoutWidth
|
|
|
|
|
}
|
|
|
|
|
const mobileLayout = width <= 800
|
|
|
|
|
const normalOrMobile = mobileLayout ? 'mobile' : 'normal'
|
|
|
|
|
const { thirdColumnMode } = rootGetters.mergedConfig
|
2022-05-09 23:24:35 +03:00
|
|
|
if (thirdColumnMode === 'none' || !rootState.users.currentUser) {
|
2022-04-12 21:18:06 +03:00
|
|
|
commit('setLayoutType', normalOrMobile)
|
|
|
|
|
} else {
|
|
|
|
|
const wideLayout = width >= 1300
|
|
|
|
|
commit('setLayoutType', wideLayout ? 'wide' : normalOrMobile)
|
|
|
|
|
}
|
|
|
|
|
},
|
2024-06-27 00:34:25 +03:00
|
|
|
queryLocalFonts ({ commit, dispatch, state }) {
|
|
|
|
|
if (state.localFonts !== null) return
|
|
|
|
|
commit('setFontsList', [])
|
|
|
|
|
if (!state.browserSupport.localFonts) {
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-06-26 17:05:59 +03:00
|
|
|
window
|
|
|
|
|
.queryLocalFonts()
|
|
|
|
|
.then((fonts) => {
|
|
|
|
|
commit('setFontsList', fonts)
|
|
|
|
|
})
|
|
|
|
|
.catch((e) => {
|
|
|
|
|
dispatch('pushGlobalNotice', {
|
|
|
|
|
messageKey: 'settings.style.themes3.font.font_list_unavailable',
|
|
|
|
|
messageArgs: {
|
|
|
|
|
error: e
|
|
|
|
|
},
|
|
|
|
|
level: 'error'
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
},
|
2020-07-23 15:09:32 +03:00
|
|
|
setLastTimeline ({ commit }, value) {
|
|
|
|
|
commit('setLastTimeline', value)
|
2024-07-12 02:13:08 +03:00
|
|
|
},
|
2024-10-02 02:35:52 +03:00
|
|
|
async fetchPalettesIndex ({ commit, state }) {
|
|
|
|
|
try {
|
|
|
|
|
const value = await getResourcesIndex('/static/palettes/index.json')
|
|
|
|
|
commit('setInstanceOption', { name: 'palettesIndex', value })
|
|
|
|
|
return value
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('Could not fetch palettes index', e)
|
2024-10-05 18:45:38 +03:00
|
|
|
commit('setInstanceOption', { name: 'palettesIndex', value: { _error: e } })
|
|
|
|
|
return Promise.resolve({})
|
2024-10-02 02:35:52 +03:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
setPalette ({ dispatch, commit }, value) {
|
2024-10-02 16:22:28 +03:00
|
|
|
dispatch('resetThemeV3Palette')
|
|
|
|
|
dispatch('resetThemeV2')
|
2024-10-02 02:35:52 +03:00
|
|
|
|
|
|
|
|
commit('setOption', { name: 'palette', value })
|
|
|
|
|
|
|
|
|
|
dispatch('applyTheme')
|
|
|
|
|
},
|
|
|
|
|
setPaletteCustom ({ dispatch, commit }, value) {
|
2024-10-02 16:22:28 +03:00
|
|
|
dispatch('resetThemeV3Palette')
|
|
|
|
|
dispatch('resetThemeV2')
|
2024-10-02 02:35:52 +03:00
|
|
|
|
|
|
|
|
commit('setOption', { name: 'paletteCustomData', value })
|
|
|
|
|
|
|
|
|
|
dispatch('applyTheme')
|
|
|
|
|
},
|
|
|
|
|
async fetchStylesIndex ({ commit, state }) {
|
|
|
|
|
try {
|
|
|
|
|
const value = await getResourcesIndex('/static/styles/index.json')
|
|
|
|
|
commit('setInstanceOption', { name: 'stylesIndex', value })
|
|
|
|
|
return value
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('Could not fetch styles index', e)
|
2024-10-05 18:45:38 +03:00
|
|
|
commit('setInstanceOption', { name: 'stylesIndex', value: { _error: e } })
|
2024-10-02 02:35:52 +03:00
|
|
|
return Promise.resolve({})
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
setStyle ({ dispatch, commit }, value) {
|
2024-10-02 16:22:28 +03:00
|
|
|
dispatch('resetThemeV3')
|
|
|
|
|
dispatch('resetThemeV2')
|
2024-10-02 02:35:52 +03:00
|
|
|
|
|
|
|
|
commit('setOption', { name: 'style', value })
|
|
|
|
|
|
|
|
|
|
dispatch('applyTheme')
|
|
|
|
|
},
|
|
|
|
|
setStyleCustom ({ dispatch, commit }, value) {
|
2024-10-02 16:22:28 +03:00
|
|
|
dispatch('resetThemeV3')
|
|
|
|
|
dispatch('resetThemeV2')
|
2024-10-02 02:35:52 +03:00
|
|
|
|
|
|
|
|
commit('setOption', { name: 'styleCustomData', value })
|
|
|
|
|
|
|
|
|
|
dispatch('applyTheme')
|
|
|
|
|
},
|
|
|
|
|
async fetchThemesIndex ({ commit, state }) {
|
|
|
|
|
try {
|
|
|
|
|
const value = await getResourcesIndex('/static/styles.json')
|
|
|
|
|
commit('setInstanceOption', { name: 'themesIndex', value })
|
|
|
|
|
return value
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('Could not fetch themes index', e)
|
2024-10-05 18:45:38 +03:00
|
|
|
commit('setInstanceOption', { name: 'themesIndex', value: { _error: e } })
|
2024-10-02 02:35:52 +03:00
|
|
|
return Promise.resolve({})
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
setTheme ({ dispatch, commit }, value) {
|
2024-10-02 16:22:28 +03:00
|
|
|
dispatch('resetThemeV3')
|
|
|
|
|
dispatch('resetThemeV3Palette')
|
|
|
|
|
dispatch('resetThemeV2')
|
2024-10-02 02:35:52 +03:00
|
|
|
|
|
|
|
|
commit('setOption', { name: 'theme', value })
|
|
|
|
|
|
|
|
|
|
dispatch('applyTheme')
|
2024-10-01 00:42:33 +03:00
|
|
|
},
|
2024-10-02 02:35:52 +03:00
|
|
|
setThemeCustom ({ dispatch, commit }, value) {
|
2024-10-02 16:22:28 +03:00
|
|
|
dispatch('resetThemeV3')
|
|
|
|
|
dispatch('resetThemeV3Palette')
|
|
|
|
|
dispatch('resetThemeV2')
|
2024-10-02 02:35:52 +03:00
|
|
|
|
|
|
|
|
commit('setOption', { name: 'customTheme', value })
|
|
|
|
|
commit('setOption', { name: 'customThemeSource', value })
|
|
|
|
|
|
|
|
|
|
dispatch('applyTheme')
|
|
|
|
|
},
|
2024-10-02 16:22:28 +03:00
|
|
|
resetThemeV3 ({ dispatch, commit }) {
|
2024-10-02 02:35:52 +03:00
|
|
|
commit('setOption', { name: 'style', value: null })
|
|
|
|
|
commit('setOption', { name: 'styleCustomData', value: null })
|
2024-10-02 16:22:28 +03:00
|
|
|
},
|
|
|
|
|
resetThemeV3Palette ({ dispatch, commit }) {
|
2024-10-02 02:35:52 +03:00
|
|
|
commit('setOption', { name: 'palette', value: null })
|
|
|
|
|
commit('setOption', { name: 'paletteCustomData', value: null })
|
|
|
|
|
},
|
2024-10-02 16:22:28 +03:00
|
|
|
resetThemeV2 ({ dispatch, commit }) {
|
2024-10-02 02:35:52 +03:00
|
|
|
commit('setOption', { name: 'theme', value: null })
|
|
|
|
|
commit('setOption', { name: 'customTheme', value: null })
|
|
|
|
|
commit('setOption', { name: 'customThemeSource', value: null })
|
|
|
|
|
},
|
|
|
|
|
async applyTheme (
|
2024-10-03 23:03:33 +03:00
|
|
|
{ dispatch, commit, rootState, state },
|
2024-10-02 02:35:52 +03:00
|
|
|
{ recompile = true } = {}
|
|
|
|
|
) {
|
|
|
|
|
// If we're not not forced to recompile try using
|
|
|
|
|
// cache (tryLoadCache return true if load successful)
|
|
|
|
|
|
2024-07-12 02:13:08 +03:00
|
|
|
const {
|
2024-10-02 02:35:52 +03:00
|
|
|
style: instanceStyleName,
|
|
|
|
|
palette: instancePaletteName
|
|
|
|
|
} = rootState.instance
|
|
|
|
|
let {
|
|
|
|
|
theme: instanceThemeV2Name,
|
|
|
|
|
themesIndex,
|
|
|
|
|
stylesIndex,
|
|
|
|
|
palettesIndex
|
2024-07-12 02:13:08 +03:00
|
|
|
} = rootState.instance
|
|
|
|
|
|
|
|
|
|
const {
|
2024-10-02 02:35:52 +03:00
|
|
|
style: userStyleName,
|
|
|
|
|
styleCustomData: userStyleCustomData,
|
|
|
|
|
palette: userPaletteName,
|
|
|
|
|
paletteCustomData: userPaletteCustomData,
|
2024-07-12 02:13:08 +03:00
|
|
|
forceThemeRecompilation,
|
2024-07-16 21:01:20 +03:00
|
|
|
themeDebug,
|
|
|
|
|
theme3hacks
|
2024-07-12 02:13:08 +03:00
|
|
|
} = rootState.config
|
2024-10-02 02:35:52 +03:00
|
|
|
let {
|
|
|
|
|
theme: userThemeV2Name,
|
|
|
|
|
customTheme: userThemeV2Snapshot,
|
|
|
|
|
customThemeSource: userThemeV2Source
|
|
|
|
|
} = rootState.config
|
|
|
|
|
|
|
|
|
|
const forceRecompile = forceThemeRecompilation || recompile
|
|
|
|
|
if (!forceRecompile && !themeDebug && tryLoadCache()) {
|
|
|
|
|
return commit('setThemeApplied')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let majorVersionUsed
|
|
|
|
|
|
2024-10-02 16:22:28 +03:00
|
|
|
console.log(
|
2024-10-03 02:16:55 +03:00
|
|
|
`USER V3 palette: ${userPaletteName}, style: ${userStyleName} `
|
2024-10-02 16:22:28 +03:00
|
|
|
)
|
|
|
|
|
console.log(
|
2024-10-03 02:16:55 +03:00
|
|
|
`USER V2 name: ${userThemeV2Name}, source: ${userThemeV2Source}, snapshot: ${userThemeV2Snapshot}`
|
2024-10-02 16:22:28 +03:00
|
|
|
)
|
|
|
|
|
|
2024-10-03 02:16:55 +03:00
|
|
|
console.log(`INST V3 palette: ${instancePaletteName}, style: ${instanceStyleName}`)
|
|
|
|
|
console.log('INST V2 theme: ' + instanceThemeV2Name)
|
2024-10-02 16:22:28 +03:00
|
|
|
|
2024-10-02 02:35:52 +03:00
|
|
|
if (userPaletteName || userPaletteCustomData ||
|
|
|
|
|
userStyleName || userStyleCustomData ||
|
2024-10-03 02:16:55 +03:00
|
|
|
(
|
|
|
|
|
// User V2 overrides instance V3
|
|
|
|
|
(instancePaletteName ||
|
|
|
|
|
instanceStyleName) &&
|
|
|
|
|
instanceThemeV2Name == null &&
|
|
|
|
|
userThemeV2Name == null
|
|
|
|
|
)
|
2024-10-02 02:35:52 +03:00
|
|
|
) {
|
|
|
|
|
// Palette and/or style overrides V2 themes
|
|
|
|
|
instanceThemeV2Name = null
|
|
|
|
|
userThemeV2Name = null
|
|
|
|
|
userThemeV2Source = null
|
|
|
|
|
userThemeV2Snapshot = null
|
|
|
|
|
|
|
|
|
|
majorVersionUsed = 'v3'
|
2024-10-02 16:22:28 +03:00
|
|
|
} else if (
|
2024-10-05 18:45:38 +03:00
|
|
|
(userThemeV2Name ||
|
2024-10-02 16:22:28 +03:00
|
|
|
userThemeV2Snapshot ||
|
|
|
|
|
userThemeV2Source ||
|
2024-10-05 18:45:38 +03:00
|
|
|
instanceThemeV2Name)
|
2024-10-02 16:22:28 +03:00
|
|
|
) {
|
2024-10-02 02:35:52 +03:00
|
|
|
majorVersionUsed = 'v2'
|
2024-10-05 18:45:38 +03:00
|
|
|
} else {
|
|
|
|
|
// if all fails fallback to v3
|
|
|
|
|
majorVersionUsed = 'v3'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (majorVersionUsed === 'v3') {
|
|
|
|
|
const result = await Promise.all([
|
|
|
|
|
dispatch('fetchPalettesIndex'),
|
|
|
|
|
dispatch('fetchStylesIndex')
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
palettesIndex = result[0]
|
|
|
|
|
stylesIndex = result[1]
|
|
|
|
|
} else {
|
2024-10-02 02:35:52 +03:00
|
|
|
// Promise.all just to be uniform with v3
|
|
|
|
|
const result = await Promise.all([
|
|
|
|
|
dispatch('fetchThemesIndex')
|
|
|
|
|
])
|
2024-10-05 18:45:38 +03:00
|
|
|
|
2024-10-02 02:35:52 +03:00
|
|
|
themesIndex = result[0]
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-03 23:03:33 +03:00
|
|
|
state.themeVersion = majorVersionUsed
|
|
|
|
|
|
2024-10-02 02:35:52 +03:00
|
|
|
let styleDataUsed = null
|
|
|
|
|
let styleNameUsed = null
|
|
|
|
|
let paletteDataUsed = null
|
|
|
|
|
let paletteNameUsed = null
|
|
|
|
|
let themeNameUsed = null
|
|
|
|
|
let themeDataUsed = null
|
|
|
|
|
|
2024-10-02 16:22:28 +03:00
|
|
|
const getData = async (resource, index, customData, name) => {
|
|
|
|
|
const capitalizedResource = resource[0].toUpperCase() + resource.slice(1)
|
|
|
|
|
const result = {}
|
|
|
|
|
|
|
|
|
|
if (customData) {
|
|
|
|
|
result.nameUsed = 'custom' // custom data overrides name
|
|
|
|
|
result.dataUsed = customData
|
2024-10-02 02:35:52 +03:00
|
|
|
} else {
|
2024-10-02 16:22:28 +03:00
|
|
|
result.nameUsed = name
|
|
|
|
|
|
|
|
|
|
if (result.nameUsed === 'stock') {
|
|
|
|
|
result.dataUsed = null
|
|
|
|
|
return result
|
2024-10-02 02:35:52 +03:00
|
|
|
}
|
|
|
|
|
|
2024-10-02 16:22:28 +03:00
|
|
|
let fetchFunc = index[result.nameUsed]
|
|
|
|
|
// Fallbacks
|
|
|
|
|
if (!fetchFunc) {
|
|
|
|
|
const newName = Object.keys(index)[0]
|
|
|
|
|
fetchFunc = index[newName]
|
|
|
|
|
console.warn(`${capitalizedResource} with id '${styleNameUsed}' not found, trying back to '${newName}'`)
|
|
|
|
|
if (!fetchFunc) {
|
|
|
|
|
console.warn(`${capitalizedResource} doesn't have a fallback, defaulting to stock.`)
|
|
|
|
|
fetchFunc = () => Promise.resolve(null)
|
|
|
|
|
}
|
2024-10-02 02:35:52 +03:00
|
|
|
}
|
2024-10-02 16:22:28 +03:00
|
|
|
result.dataUsed = await fetchFunc()
|
2024-10-02 02:35:52 +03:00
|
|
|
}
|
2024-10-02 16:22:28 +03:00
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('VERSION', majorVersionUsed)
|
|
|
|
|
|
|
|
|
|
if (majorVersionUsed === 'v3') {
|
|
|
|
|
const palette = await getData(
|
|
|
|
|
'palette',
|
|
|
|
|
palettesIndex,
|
|
|
|
|
userPaletteCustomData,
|
|
|
|
|
userPaletteName || instancePaletteName
|
|
|
|
|
)
|
|
|
|
|
paletteNameUsed = palette.nameUsed
|
|
|
|
|
paletteDataUsed = palette.dataUsed
|
|
|
|
|
if (Array.isArray(paletteDataUsed)) {
|
|
|
|
|
const [
|
|
|
|
|
name,
|
|
|
|
|
background,
|
|
|
|
|
foreground,
|
|
|
|
|
text,
|
|
|
|
|
link,
|
|
|
|
|
cRed = '#FF0000',
|
|
|
|
|
cGreen = '#00FF00',
|
2024-10-02 16:29:33 +03:00
|
|
|
cBlue = '#0000FF',
|
2024-10-02 16:22:28 +03:00
|
|
|
cOrange = '#E3FF00'
|
|
|
|
|
] = paletteDataUsed
|
|
|
|
|
paletteDataUsed = { name, background, foreground, text, link, cRed, cBlue, cGreen, cOrange }
|
2024-10-02 02:35:52 +03:00
|
|
|
}
|
2024-10-02 16:22:28 +03:00
|
|
|
console.log('PAL', userPaletteName, paletteNameUsed)
|
|
|
|
|
console.log('PAL', paletteDataUsed)
|
|
|
|
|
|
|
|
|
|
const style = await getData(
|
|
|
|
|
'style',
|
|
|
|
|
stylesIndex,
|
|
|
|
|
userStyleCustomData,
|
|
|
|
|
userStyleName || instanceStyleName
|
|
|
|
|
)
|
|
|
|
|
styleNameUsed = style.nameUsed
|
|
|
|
|
styleDataUsed = style.dataUsed
|
|
|
|
|
} else {
|
|
|
|
|
const theme = await getData(
|
|
|
|
|
'theme',
|
|
|
|
|
themesIndex,
|
|
|
|
|
userThemeV2Source || userThemeV2Snapshot,
|
|
|
|
|
userThemeV2Name || instanceThemeV2Name
|
|
|
|
|
)
|
|
|
|
|
themeNameUsed = theme.nameUsed
|
2024-10-05 18:45:38 +03:00
|
|
|
themeDataUsed = theme.dataUsed
|
2024-10-02 16:22:28 +03:00
|
|
|
|
2024-10-02 02:35:52 +03:00
|
|
|
// Themes v2 editor support
|
|
|
|
|
commit('setInstanceOption', { name: 'themeData', value: themeDataUsed })
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-02 16:22:28 +03:00
|
|
|
console.log('STYLE', styleNameUsed, paletteNameUsed, themeNameUsed)
|
|
|
|
|
|
|
|
|
|
// commit('setOption', { name: 'palette', value: paletteNameUsed })
|
|
|
|
|
// commit('setOption', { name: 'style', value: styleNameUsed })
|
|
|
|
|
// commit('setOption', { name: 'theme', value: themeNameUsed })
|
|
|
|
|
|
2024-10-02 02:35:52 +03:00
|
|
|
const paletteIss = (() => {
|
|
|
|
|
if (!paletteDataUsed) return null
|
2024-10-01 00:42:33 +03:00
|
|
|
const result = {
|
|
|
|
|
component: 'Root',
|
|
|
|
|
directives: {}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-02 16:22:28 +03:00
|
|
|
console.log('PALETTE', paletteDataUsed)
|
2024-10-01 00:42:33 +03:00
|
|
|
Object
|
2024-10-02 02:35:52 +03:00
|
|
|
.entries(paletteDataUsed)
|
2024-10-01 00:42:33 +03:00
|
|
|
.filter(([k]) => k !== 'name')
|
|
|
|
|
.forEach(([k, v]) => {
|
|
|
|
|
let issRootDirectiveName
|
|
|
|
|
switch (k) {
|
|
|
|
|
case 'background':
|
|
|
|
|
issRootDirectiveName = 'bg'
|
|
|
|
|
break
|
|
|
|
|
case 'foreground':
|
|
|
|
|
issRootDirectiveName = 'fg'
|
|
|
|
|
break
|
|
|
|
|
default:
|
|
|
|
|
issRootDirectiveName = k
|
|
|
|
|
}
|
|
|
|
|
result.directives['--' + issRootDirectiveName] = 'color | ' + v
|
|
|
|
|
})
|
|
|
|
|
return result
|
|
|
|
|
})()
|
2024-07-17 22:25:14 +03:00
|
|
|
|
2024-10-05 19:24:32 +03:00
|
|
|
const theme2ruleset = themeDataUsed && convertTheme2To3(normalizeThemeData(themeDataUsed))
|
2024-10-02 02:35:52 +03:00
|
|
|
const hacks = []
|
2024-07-17 22:10:11 +03:00
|
|
|
|
2024-10-02 02:35:52 +03:00
|
|
|
Object.entries(theme3hacks).forEach(([key, value]) => {
|
|
|
|
|
switch (key) {
|
|
|
|
|
case 'fonts': {
|
|
|
|
|
Object.entries(theme3hacks.fonts).forEach(([fontKey, font]) => {
|
|
|
|
|
if (!font?.family) return
|
|
|
|
|
switch (fontKey) {
|
|
|
|
|
case 'interface':
|
|
|
|
|
hacks.push({
|
|
|
|
|
component: 'Root',
|
|
|
|
|
directives: {
|
|
|
|
|
'--font': 'generic | ' + font.family
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
break
|
|
|
|
|
case 'input':
|
|
|
|
|
hacks.push({
|
|
|
|
|
component: 'Input',
|
|
|
|
|
directives: {
|
|
|
|
|
'--font': 'generic | ' + font.family
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
break
|
|
|
|
|
case 'post':
|
|
|
|
|
hacks.push({
|
|
|
|
|
component: 'RichContent',
|
|
|
|
|
directives: {
|
|
|
|
|
'--font': 'generic | ' + font.family
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
break
|
|
|
|
|
case 'monospace':
|
|
|
|
|
hacks.push({
|
|
|
|
|
component: 'Root',
|
|
|
|
|
directives: {
|
|
|
|
|
'--monoFont': 'generic | ' + font.family
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
break
|
2024-07-17 22:10:11 +03:00
|
|
|
}
|
2024-10-02 02:35:52 +03:00
|
|
|
case 'underlay': {
|
|
|
|
|
if (value !== 'none') {
|
|
|
|
|
const newRule = {
|
|
|
|
|
component: 'Underlay',
|
|
|
|
|
directives: {}
|
2024-07-21 23:27:11 +03:00
|
|
|
}
|
2024-10-02 02:35:52 +03:00
|
|
|
if (value === 'opaque') {
|
|
|
|
|
newRule.directives.opacity = 1
|
|
|
|
|
newRule.directives.background = '--wallpaper'
|
|
|
|
|
}
|
|
|
|
|
if (value === 'transparent') {
|
|
|
|
|
newRule.directives.opacity = 0
|
2024-07-16 21:01:20 +03:00
|
|
|
}
|
2024-10-02 02:35:52 +03:00
|
|
|
hacks.push(newRule)
|
2024-07-16 21:01:20 +03:00
|
|
|
}
|
2024-10-02 02:35:52 +03:00
|
|
|
break
|
2024-10-01 00:42:33 +03:00
|
|
|
}
|
2024-10-02 02:35:52 +03:00
|
|
|
}
|
|
|
|
|
})
|
2024-07-12 02:13:08 +03:00
|
|
|
|
2024-10-02 02:35:52 +03:00
|
|
|
const rulesetArray = [
|
|
|
|
|
theme2ruleset,
|
|
|
|
|
styleDataUsed,
|
|
|
|
|
paletteIss,
|
|
|
|
|
hacks
|
|
|
|
|
].filter(x => x)
|
2024-07-12 02:13:08 +03:00
|
|
|
|
2024-10-02 02:35:52 +03:00
|
|
|
return applyTheme(
|
|
|
|
|
rulesetArray.flat(),
|
|
|
|
|
() => commit('setThemeApplied'),
|
|
|
|
|
themeDebug
|
|
|
|
|
)
|
2018-09-09 19:36:13 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default interfaceMod
|
2024-07-17 17:19:57 +03:00
|
|
|
|
|
|
|
|
export const normalizeThemeData = (input) => {
|
2024-07-25 19:19:46 +03:00
|
|
|
let themeData, themeSource
|
2024-07-17 17:19:57 +03:00
|
|
|
|
2024-07-25 19:19:46 +03:00
|
|
|
if (input.themeFileVerison === 1) {
|
|
|
|
|
// this might not be even used at all, some leftover of unimplemented code in V2 editor
|
|
|
|
|
return generatePreset(input).theme
|
|
|
|
|
} else if (
|
|
|
|
|
Object.prototype.hasOwnProperty.call(input, '_pleroma_theme_version') ||
|
|
|
|
|
Object.prototype.hasOwnProperty.call(input, 'source') ||
|
|
|
|
|
Object.prototype.hasOwnProperty.call(input, 'theme')
|
|
|
|
|
) {
|
|
|
|
|
// We got passed a full theme file
|
|
|
|
|
themeData = input.theme
|
|
|
|
|
themeSource = input.source
|
2024-10-07 12:21:36 +03:00
|
|
|
} else if (
|
|
|
|
|
Object.prototype.hasOwnProperty.call(input, 'themeEngineVersion') ||
|
2024-10-07 12:29:47 +03:00
|
|
|
Object.prototype.hasOwnProperty.call(input, 'colors')
|
2024-10-07 12:21:36 +03:00
|
|
|
) {
|
2024-07-25 19:19:46 +03:00
|
|
|
// We got passed a source/snapshot
|
|
|
|
|
themeData = input
|
|
|
|
|
themeSource = input
|
|
|
|
|
}
|
2024-07-17 17:19:57 +03:00
|
|
|
// New theme presets don't have 'theme' property, they use 'source'
|
|
|
|
|
|
|
|
|
|
let out // shout, shout let it all out
|
2024-07-25 19:19:46 +03:00
|
|
|
if (themeSource && themeSource.themeEngineVersion === CURRENT_VERSION) {
|
|
|
|
|
// There are some themes in wild that have completely broken source
|
|
|
|
|
out = { ...(themeData || {}), ...themeSource }
|
2024-07-17 17:19:57 +03:00
|
|
|
} else {
|
2024-07-25 19:19:46 +03:00
|
|
|
out = themeData
|
2024-07-17 17:19:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// generatePreset here basically creates/updates "snapshot",
|
|
|
|
|
// while also fixing the 2.2 -> 2.3 colors/shadows/etc
|
|
|
|
|
return generatePreset(out).theme
|
|
|
|
|
}
|