Merge branch 'themes3-cache' into 'develop'
implement a simple caching system for themes 3 See merge request pleroma/pleroma-fe!1911
This commit is contained in:
commit
3128ea57e1
|
@ -0,0 +1 @@
|
||||||
|
Add caching system for themes3
|
|
@ -32,6 +32,7 @@
|
||||||
"click-outside-vue3": "4.0.1",
|
"click-outside-vue3": "4.0.1",
|
||||||
"cropperjs": "1.5.13",
|
"cropperjs": "1.5.13",
|
||||||
"escape-html": "1.0.3",
|
"escape-html": "1.0.3",
|
||||||
|
"hash-sum": "^2.0.0",
|
||||||
"js-cookie": "3.0.5",
|
"js-cookie": "3.0.5",
|
||||||
"localforage": "1.10.0",
|
"localforage": "1.10.0",
|
||||||
"parse-link-header": "2.0.0",
|
"parse-link-header": "2.0.0",
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { windowWidth, windowHeight } from '../services/window_utils/window_utils
|
||||||
import { getOrCreateApp, getClientToken } from '../services/new_api/oauth.js'
|
import { getOrCreateApp, getClientToken } from '../services/new_api/oauth.js'
|
||||||
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
|
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
|
||||||
import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
|
import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
|
||||||
import { applyTheme, applyConfig } from '../services/style_setter/style_setter.js'
|
import { applyTheme, applyConfig, tryLoadCache } 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'
|
||||||
|
|
||||||
|
@ -353,21 +353,25 @@ const afterStoreSetup = async ({ store, i18n }) => {
|
||||||
|
|
||||||
await setConfig({ store })
|
await setConfig({ store })
|
||||||
|
|
||||||
const { customTheme, customThemeSource } = store.state.config
|
const { customTheme, customThemeSource, forceThemeRecompilation } = store.state.config
|
||||||
const { theme } = store.state.instance
|
const { theme } = store.state.instance
|
||||||
const customThemePresent = customThemeSource || customTheme
|
const customThemePresent = customThemeSource || customTheme
|
||||||
|
|
||||||
if (customThemePresent) {
|
if (!forceThemeRecompilation && tryLoadCache()) {
|
||||||
if (customThemeSource && customThemeSource.themeEngineVersion === CURRENT_VERSION) {
|
|
||||||
applyTheme(customThemeSource)
|
|
||||||
} else {
|
|
||||||
applyTheme(customTheme)
|
|
||||||
}
|
|
||||||
store.commit('setThemeApplied')
|
store.commit('setThemeApplied')
|
||||||
} else if (theme) {
|
|
||||||
// do nothing, it will load asynchronously
|
|
||||||
} else {
|
} else {
|
||||||
console.error('Failed to load any theme!')
|
if (customThemePresent) {
|
||||||
|
if (customThemeSource && customThemeSource.themeEngineVersion === CURRENT_VERSION) {
|
||||||
|
applyTheme(customThemeSource)
|
||||||
|
} else {
|
||||||
|
applyTheme(customTheme)
|
||||||
|
}
|
||||||
|
store.commit('setThemeApplied')
|
||||||
|
} else if (theme) {
|
||||||
|
// do nothing, it will load asynchronously
|
||||||
|
} else {
|
||||||
|
console.error('Failed to load any theme!')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyConfig(store.state.config)
|
applyConfig(store.state.config)
|
||||||
|
|
|
@ -200,6 +200,14 @@
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<h2>{{ $t('settings.post_look_feel') }}</h2>
|
<h2>{{ $t('settings.post_look_feel') }}</h2>
|
||||||
<ul class="setting-list">
|
<ul class="setting-list">
|
||||||
|
<li>
|
||||||
|
<BooleanSetting
|
||||||
|
path="forceThemeRecompilation"
|
||||||
|
:expert="1"
|
||||||
|
>
|
||||||
|
{{ $t('settings.force_theme_recompilation_debug') }}
|
||||||
|
</BooleanSetting>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<ChoiceSetting
|
<ChoiceSetting
|
||||||
id="conversationDisplay"
|
id="conversationDisplay"
|
||||||
|
|
|
@ -635,6 +635,7 @@
|
||||||
"subject_line_email": "Like email: \"re: subject\"",
|
"subject_line_email": "Like email: \"re: subject\"",
|
||||||
"subject_line_mastodon": "Like mastodon: copy as is",
|
"subject_line_mastodon": "Like mastodon: copy as is",
|
||||||
"subject_line_noop": "Do not copy",
|
"subject_line_noop": "Do not copy",
|
||||||
|
"force_theme_recompilation_debug": "Disable theme cahe, force recompile on each boot (DEBUG)",
|
||||||
"conversation_display": "Conversation display style",
|
"conversation_display": "Conversation display style",
|
||||||
"conversation_display_tree": "Tree-style",
|
"conversation_display_tree": "Tree-style",
|
||||||
"conversation_display_tree_quick": "Tree view",
|
"conversation_display_tree_quick": "Tree view",
|
||||||
|
|
|
@ -28,6 +28,7 @@ export const defaultState = {
|
||||||
theme: undefined,
|
theme: undefined,
|
||||||
customTheme: undefined,
|
customTheme: undefined,
|
||||||
customThemeSource: undefined,
|
customThemeSource: undefined,
|
||||||
|
forceThemeRecompilation: false,
|
||||||
hideISP: false,
|
hideISP: false,
|
||||||
hideInstanceWallpaper: false,
|
hideInstanceWallpaper: false,
|
||||||
hideShoutbox: false,
|
hideShoutbox: false,
|
||||||
|
|
|
@ -378,7 +378,8 @@ const instance = {
|
||||||
commit('setInstanceOption', { name: 'themeData', value: themeData })
|
commit('setInstanceOption', { name: 'themeData', value: themeData })
|
||||||
// No need to apply theme if there's user theme already
|
// No need to apply theme if there's user theme already
|
||||||
const { customTheme } = rootState.config
|
const { customTheme } = rootState.config
|
||||||
if (customTheme) return
|
const { themeApplied } = rootState.interface
|
||||||
|
if (customTheme || themeApplied) return
|
||||||
|
|
||||||
// New theme presets don't have 'theme' property, they use 'source'
|
// New theme presets don't have 'theme' property, they use 'source'
|
||||||
const themeSource = themeData.source
|
const themeSource = themeData.source
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { hex2rgb } from '../color_convert/color_convert.js'
|
import { hex2rgb } from '../color_convert/color_convert.js'
|
||||||
import { generatePreset } from '../theme_data/theme_data.service.js'
|
import { generatePreset } from '../theme_data/theme_data.service.js'
|
||||||
import { init } from '../theme_data/theme_data_3.service.js'
|
import { init, getEngineChecksum } from '../theme_data/theme_data_3.service.js'
|
||||||
import { convertTheme2To3 } from '../theme_data/theme2_to_theme3.js'
|
import { convertTheme2To3 } from '../theme_data/theme2_to_theme3.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 '../../modules/config.js'
|
||||||
|
@ -87,9 +87,37 @@ export const generateTheme = async (input, callbacks) => {
|
||||||
return { lazyProcessFunc: processChunk }
|
return { lazyProcessFunc: processChunk }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const applyTheme = async (input) => {
|
export const tryLoadCache = () => {
|
||||||
|
const json = localStorage.getItem('pleroma-fe-theme-cache')
|
||||||
|
if (!json) return null
|
||||||
|
let cache
|
||||||
|
try {
|
||||||
|
cache = JSON.parse(json)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to decode theme cache:', e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (cache.engineChecksum === getEngineChecksum()) {
|
||||||
|
const styleSheet = new CSSStyleSheet()
|
||||||
|
const lazyStyleSheet = new CSSStyleSheet()
|
||||||
|
|
||||||
|
cache.data[0].forEach(rule => styleSheet.insertRule(rule, 'index-max'))
|
||||||
|
cache.data[1].forEach(rule => lazyStyleSheet.insertRule(rule, 'index-max'))
|
||||||
|
|
||||||
|
document.adoptedStyleSheets = [styleSheet, lazyStyleSheet]
|
||||||
|
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
console.warn('Engine checksum doesn\'t match, cache not usable, clearing')
|
||||||
|
localStorage.removeItem('pleroma-fe-theme-cache')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const applyTheme = async (input, onFinish = (data) => {}) => {
|
||||||
const styleSheet = new CSSStyleSheet()
|
const styleSheet = new CSSStyleSheet()
|
||||||
|
const styleArray = []
|
||||||
const lazyStyleSheet = new CSSStyleSheet()
|
const lazyStyleSheet = new CSSStyleSheet()
|
||||||
|
const lazyStyleArray = []
|
||||||
|
|
||||||
const { lazyProcessFunc } = await generateTheme(
|
const { lazyProcessFunc } = await generateTheme(
|
||||||
input,
|
input,
|
||||||
|
@ -97,8 +125,10 @@ export const applyTheme = async (input) => {
|
||||||
onNewRule (rule, isLazy) {
|
onNewRule (rule, isLazy) {
|
||||||
if (isLazy) {
|
if (isLazy) {
|
||||||
lazyStyleSheet.insertRule(rule, 'index-max')
|
lazyStyleSheet.insertRule(rule, 'index-max')
|
||||||
|
lazyStyleArray.push(rule)
|
||||||
} else {
|
} else {
|
||||||
styleSheet.insertRule(rule, 'index-max')
|
styleSheet.insertRule(rule, 'index-max')
|
||||||
|
styleArray.push(rule)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onEagerFinished () {
|
onEagerFinished () {
|
||||||
|
@ -106,6 +136,9 @@ export const applyTheme = async (input) => {
|
||||||
},
|
},
|
||||||
onLazyFinished () {
|
onLazyFinished () {
|
||||||
document.adoptedStyleSheets = [styleSheet, lazyStyleSheet]
|
document.adoptedStyleSheets = [styleSheet, lazyStyleSheet]
|
||||||
|
const cache = { engineChecksum: getEngineChecksum(), data: [styleArray, lazyStyleArray] }
|
||||||
|
onFinish(cache)
|
||||||
|
localStorage.setItem('pleroma-fe-theme-cache', JSON.stringify(cache))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { convert, brightness } from 'chromatism'
|
import { convert, brightness } from 'chromatism'
|
||||||
|
import sum from 'hash-sum'
|
||||||
import { flattenDeep } from 'lodash'
|
import { flattenDeep } from 'lodash'
|
||||||
import {
|
import {
|
||||||
alphaBlend,
|
alphaBlend,
|
||||||
|
@ -142,8 +143,12 @@ componentsContext.keys().forEach(key => {
|
||||||
components[component.name] = component
|
components[component.name] = component
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const engineChecksum = sum(components)
|
||||||
|
|
||||||
const ruleToSelector = genericRuleToSelector(components)
|
const ruleToSelector = genericRuleToSelector(components)
|
||||||
|
|
||||||
|
export const getEngineChecksum = () => engineChecksum
|
||||||
|
|
||||||
export const init = (extraRuleset, ultimateBackgroundColor) => {
|
export const init = (extraRuleset, ultimateBackgroundColor) => {
|
||||||
const staticVars = {}
|
const staticVars = {}
|
||||||
const stacked = {}
|
const stacked = {}
|
||||||
|
@ -463,6 +468,7 @@ export const init = (extraRuleset, ultimateBackgroundColor) => {
|
||||||
return {
|
return {
|
||||||
lazy: result.filter(x => typeof x === 'function'),
|
lazy: result.filter(x => typeof x === 'function'),
|
||||||
eager: result.filter(x => typeof x !== 'function'),
|
eager: result.filter(x => typeof x !== 'function'),
|
||||||
staticVars
|
staticVars,
|
||||||
|
engineChecksum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue