logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://hacktivis.me/git/pleroma-fe.git
commit: 5505a89e8aad717a0b4a7665b23a317110d38cb5
parent 15dde2d372419fd90c19de7a6f7b9b2458511adc
Author: Henry Jameson <me@hjkos.com>
Date:   Mon, 22 Apr 2024 23:40:39 +0300

implement a simple caching system for themes 3

Diffstat:

Mpackage.json1+
Msrc/boot/after_store.js26+++++++++++++++-----------
Msrc/components/settings_modal/tabs/general_tab.vue8++++++++
Msrc/i18n/en.json1+
Msrc/modules/config.js1+
Msrc/modules/instance.js3++-
Msrc/services/style_setter/style_setter.js37+++++++++++++++++++++++++++++++++++--
Msrc/services/theme_data/theme_data_3.service.js8+++++++-
8 files changed, 70 insertions(+), 15 deletions(-)

diff --git a/package.json b/package.json @@ -32,6 +32,7 @@ "click-outside-vue3": "4.0.1", "cropperjs": "1.5.13", "escape-html": "1.0.3", + "hash-sum": "^2.0.0", "js-cookie": "3.0.5", "localforage": "1.10.0", "parse-link-header": "2.0.0", diff --git a/src/boot/after_store.js b/src/boot/after_store.js @@ -14,7 +14,7 @@ import { windowWidth, windowHeight } from '../services/window_utils/window_utils import { getOrCreateApp, getClientToken } from '../services/new_api/oauth.js' import backendInteractorService from '../services/backend_interactor_service/backend_interactor_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 { initServiceWorker, updateFocus } from '../services/sw/sw.js' @@ -353,21 +353,25 @@ const afterStoreSetup = async ({ store, i18n }) => { await setConfig({ store }) - const { customTheme, customThemeSource } = store.state.config + const { customTheme, customThemeSource, forceThemeRecompilation } = store.state.config const { theme } = store.state.instance const customThemePresent = customThemeSource || customTheme - if (customThemePresent) { - if (customThemeSource && customThemeSource.themeEngineVersion === CURRENT_VERSION) { - applyTheme(customThemeSource) - } else { - applyTheme(customTheme) - } + if (!forceThemeRecompilation && tryLoadCache()) { store.commit('setThemeApplied') - } else if (theme) { - // do nothing, it will load asynchronously } 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) diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue @@ -201,6 +201,14 @@ <h2>{{ $t('settings.post_look_feel') }}</h2> <ul class="setting-list"> <li> + <BooleanSetting + path="forceThemeRecompilation" + :expert="1" + > + {{ $t('settings.force_theme_recompilation_debug') }} + </BooleanSetting> + </li> + <li> <ChoiceSetting id="conversationDisplay" path="conversationDisplay" diff --git a/src/i18n/en.json b/src/i18n/en.json @@ -634,6 +634,7 @@ "subject_line_email": "Like email: \"re: subject\"", "subject_line_mastodon": "Like mastodon: copy as is", "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_tree": "Tree-style", "conversation_display_tree_quick": "Tree view", diff --git a/src/modules/config.js b/src/modules/config.js @@ -28,6 +28,7 @@ export const defaultState = { theme: undefined, customTheme: undefined, customThemeSource: undefined, + forceThemeRecompilation: false, hideISP: false, hideInstanceWallpaper: false, hideShoutbox: false, diff --git a/src/modules/instance.js b/src/modules/instance.js @@ -377,7 +377,8 @@ const instance = { commit('setInstanceOption', { name: 'themeData', value: themeData }) // No need to apply theme if there's user theme already 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' const themeSource = themeData.source diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js @@ -1,6 +1,6 @@ import { hex2rgb } from '../color_convert/color_convert.js' import { generatePreset } from '../theme_data/theme_data.service.js' -import { init } from '../theme_data/theme_data_3.service.js' +import { init, getChecksum } from '../theme_data/theme_data_3.service.js' import { convertTheme2To3 } from '../theme_data/theme2_to_theme3.js' import { getCssRules } from '../theme_data/css_utils.js' import { defaultState } from '../../modules/config.js' @@ -87,9 +87,37 @@ export const generateTheme = async (input, callbacks) => { 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.checksum === getChecksum()) { + 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('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 styleArray = [] const lazyStyleSheet = new CSSStyleSheet() + const lazyStyleArray = [] const { lazyProcessFunc } = await generateTheme( input, @@ -97,8 +125,10 @@ export const applyTheme = async (input) => { onNewRule (rule, isLazy) { if (isLazy) { lazyStyleSheet.insertRule(rule, 'index-max') + lazyStyleArray.push(rule) } else { styleSheet.insertRule(rule, 'index-max') + styleArray.push(rule) } }, onEagerFinished () { @@ -106,6 +136,9 @@ export const applyTheme = async (input) => { }, onLazyFinished () { document.adoptedStyleSheets = [styleSheet, lazyStyleSheet] + const cache = { checksum: getChecksum(), data: [styleArray, lazyStyleArray] } + onFinish(cache) + localStorage.setItem('pleroma-fe-theme-cache', JSON.stringify(cache)) } } ) diff --git a/src/services/theme_data/theme_data_3.service.js b/src/services/theme_data/theme_data_3.service.js @@ -1,4 +1,5 @@ import { convert, brightness } from 'chromatism' +import sum from 'hash-sum' import { flattenDeep } from 'lodash' import { alphaBlend, @@ -142,8 +143,12 @@ componentsContext.keys().forEach(key => { components[component.name] = component }) +const checksum = sum(components) + const ruleToSelector = genericRuleToSelector(components) +export const getChecksum = () => checksum + export const init = (extraRuleset, ultimateBackgroundColor) => { const staticVars = {} const stacked = {} @@ -463,6 +468,7 @@ export const init = (extraRuleset, ultimateBackgroundColor) => { return { lazy: result.filter(x => typeof x === 'function'), eager: result.filter(x => typeof x !== 'function'), - staticVars + staticVars, + checksum } }