From e4a819a0e2ed9c57dc2191428d86a33bb5918862 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 22 May 2024 19:54:19 +0300 Subject: initial Appearance Tab implementation, added text size/UI scale option --- src/modules/config.js | 33 ++++++++++++++++++++++++++++++++- src/modules/instance.js | 2 ++ src/modules/interface.js | 14 ++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) (limited to 'src/modules') diff --git a/src/modules/config.js b/src/modules/config.js index 8001b854..4d5e8efc 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -115,7 +115,8 @@ export const defaultState = { sidebarColumnWidth: '25rem', contentColumnWidth: '45rem', notifsColumnWidth: '25rem', - emojiReactionsScale: 1.0, + emojiReactionsScale: undefined, + textSize: undefined, // instance default navbarColumnStretch: false, greentext: undefined, // instance default useAtIcon: undefined, // instance default @@ -173,6 +174,10 @@ const config = { } }, mutations: { + setOptionTemporarily (state, { name, value }) { + set(state, name, value) + applyConfig(state) + }, setOption (state, { name, value }) { set(state, name, value) }, @@ -203,6 +208,31 @@ const config = { setHighlight ({ commit, dispatch }, { user, color, type }) { 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 + }) + }, setOption ({ commit, dispatch, state }, { name, value }) { const exceptions = new Set([ 'useStreamingApi' @@ -231,6 +261,7 @@ const config = { case 'sidebarColumnWidth': case 'contentColumnWidth': case 'notifsColumnWidth': + case 'textSize': case 'emojiReactionsScale': applyConfig(state) break diff --git a/src/modules/instance.js b/src/modules/instance.js index 0a5c1ae7..4a75d948 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -98,6 +98,8 @@ const defaultState = { sidebarRight: false, subjectLineBehavior: 'email', theme: 'pleroma-dark', + emojiReactionsScale: 1.0, + textSize: '14px', virtualScrolling: true, sensitiveByDefault: false, conversationDisplay: 'linear', diff --git a/src/modules/interface.js b/src/modules/interface.js index 39242b9d..e21b4204 100644 --- a/src/modules/interface.js +++ b/src/modules/interface.js @@ -1,5 +1,8 @@ const defaultState = { themeApplied: false, + temporaryChangesTimeoutId: null, // used for temporary options that revert after a timeout + temporaryChangesConfirm: () => {}, // used for applying temporary options + temporaryChangesRevert: () => {}, // used for reverting temporary options settingsModalState: 'hidden', settingsModalLoadedUser: false, settingsModalLoadedAdmin: false, @@ -36,6 +39,17 @@ const interfaceMod = { state.settings.currentSaveStateNotice = { error: true, errorData: error } } }, + 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 = () => {} + }, setThemeApplied (state) { state.themeApplied = true }, -- cgit v1.2.3-70-g09d2 From 6343b91abf7fbad1cdd8b4648d1fc825d8e9b03c Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 13 Jun 2024 02:22:47 +0300 Subject: more scaling options --- src/App.scss | 5 +- src/components/emoji_reactions/emoji_reactions.vue | 2 +- .../settings_modal/tabs/appearance_tab.js | 32 +++++- .../settings_modal/tabs/appearance_tab.vue | 116 ++++++++++++++++++--- src/components/settings_modal/tabs/general_tab.js | 33 +----- src/components/settings_modal/tabs/general_tab.vue | 60 ----------- src/i18n/en.json | 4 + src/modules/config.js | 5 + src/modules/instance.js | 3 + src/panel.scss | 6 +- src/services/style_setter/style_setter.js | 20 ++-- 11 files changed, 165 insertions(+), 121 deletions(-) (limited to 'src/modules') diff --git a/src/App.scss b/src/App.scss index 32ca9189..a2710436 100644 --- a/src/App.scss +++ b/src/App.scss @@ -5,7 +5,7 @@ :root { --fontSize: 14px; --status-margin: 0.75em; - --navbar-height: 3.5rem; + --navbar-height: var(--navbarSize, 3.5rem); --post-line-height: 1.4; // Z-Index stuff --ZI_media_modal: 9000; @@ -21,6 +21,9 @@ html { font-size: var(--textSize); + + --navbar-height: var(--navbarSize, 3.5rem); + --emoji-size: var(--emojiSize, 32px); // overflow-x: clip causes my browser's tab to crash with SIGILL lul } diff --git a/src/components/emoji_reactions/emoji_reactions.vue b/src/components/emoji_reactions/emoji_reactions.vue index ad4a3c0b..3ab4c125 100644 --- a/src/components/emoji_reactions/emoji_reactions.vue +++ b/src/components/emoji_reactions/emoji_reactions.vue @@ -79,7 +79,7 @@ margin-top: 0.25em; flex-wrap: wrap; - --emoji-size: calc(1.25em * var(--emojiReactionsScale, 1)); + --emoji-size: calc(var(--emojiSize, 1.25em) * var(--emojiReactionsScale, 1)); .emoji-reaction-container { display: flex; diff --git a/src/components/settings_modal/tabs/appearance_tab.js b/src/components/settings_modal/tabs/appearance_tab.js index b96106bd..542ab0c1 100644 --- a/src/components/settings_modal/tabs/appearance_tab.js +++ b/src/components/settings_modal/tabs/appearance_tab.js @@ -2,7 +2,7 @@ import BooleanSetting from '../helpers/boolean_setting.vue' import ChoiceSetting from '../helpers/choice_setting.vue' import IntegerSetting from '../helpers/integer_setting.vue' import FloatSetting from '../helpers/float_setting.vue' -import UnitSetting from '../helpers/unit_setting.vue' +import UnitSetting, { defaultHorizontalUnits } from '../helpers/unit_setting.vue' import SharedComputedObject from '../helpers/shared_computed_object.js' import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue' @@ -17,7 +17,13 @@ library.add( const AppearanceTab = { data () { - return {} + return { + thirdColumnModeOptions: ['none', 'notifications', 'postform'].map(mode => ({ + key: mode, + value: mode, + label: this.$t(`settings.third_column_mode_${mode}`) + })) + } }, components: { BooleanSetting, @@ -28,10 +34,32 @@ const AppearanceTab = { ProfileSettingIndicator }, computed: { + horizontalUnits () { + return defaultHorizontalUnits + }, + columns () { + const mode = this.$store.getters.mergedConfig.thirdColumnMode + + const notif = mode === 'none' ? [] : ['notifs'] + + if (this.$store.getters.mergedConfig.sidebarRight || mode === 'postform') { + return [...notif, 'content', 'sidebar'] + } else { + return ['sidebar', 'content', ...notif] + } + }, + instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel }, instanceWallpaperUsed () { return this.$store.state.instance.background && !this.$store.state.users.currentUser.background_image }, + instanceShoutboxPresent () { return this.$store.state.instance.shoutAvailable }, + language: { + get: function () { return this.$store.getters.mergedConfig.interfaceLanguage }, + set: function (val) { + this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val }) + } + }, ...SharedComputedObject() } } diff --git a/src/components/settings_modal/tabs/appearance_tab.vue b/src/components/settings_modal/tabs/appearance_tab.vue index 7730b701..75126df7 100644 --- a/src/components/settings_modal/tabs/appearance_tab.vue +++ b/src/components/settings_modal/tabs/appearance_tab.vue @@ -1,23 +1,8 @@ diff --git a/src/i18n/en.json b/src/i18n/en.json index 4b216165..d995163a 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -748,17 +748,21 @@ "themes3": { "define": "Override", "font": { - "local": "Local font (must be installed on computer)", - "serif": "Serif (browser default)", - "sans-serif": "Sans-serif (browser default)", - "monospace": "Monospace (browser default)", - "inherit": "Same as parent component", - "invalid_custom_reserved": "Empty or reserved font name, it will not be saved as custom font - use dropdown instead", + "group-builtin": "Browser default fonts", + "builtin" : { + "serif": "Serif", + "sans-serif": "Sans-serif", + "monospace": "Monospace", + "inherit": "Unchanged" + }, + "group-local": "Locally installed fonts", + "local-unavailable1": "List of locally installed fonts unavailalbe", + "local-unavailable2": "Use manual entry to specify custom font", "font_list_unavailable": "Couldn't get locally installed fonts: {error}", "lookup_local_fonts": "Load list of fonts installed on this computer", "enter_manually": "Enter font name family manually", - "entry": "Font's {fontFamily}", - "select": "Select local font" + "entry": "Enter {fontFamily}", + "select": "Select font" } }, "switcher": { diff --git a/src/modules/interface.js b/src/modules/interface.js index bee503c5..2ccfeef3 100644 --- a/src/modules/interface.js +++ b/src/modules/interface.js @@ -108,7 +108,6 @@ const interfaceMod = { state.lastTimeline = value }, setFontsList (state, value) { - console.log(value) state.localFonts = new Set(value.map(font => font.family)) } }, @@ -184,10 +183,16 @@ const interfaceMod = { commit('setLayoutType', wideLayout ? 'wide' : normalOrMobile) } }, - queryLocalFonts ({ commit, dispatch }) { + queryLocalFonts ({ commit, dispatch, state }) { + if (state.localFonts !== null) return + commit('setFontsList', []) + if (!state.browserSupport.localFonts) { + return + } window .queryLocalFonts() .then((fonts) => { + console.log(fonts) commit('setFontsList', fonts) }) .catch((e) => { -- cgit v1.2.3-70-g09d2 From 80cbf29bdf7c6cd3695d1e4cf49a8e38bff847ed Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 27 Jun 2024 00:59:24 +0300 Subject: fields for user font overrides --- src/components/font_control/font_control.js | 2 +- .../settings_modal/tabs/appearance_tab.js | 8 +++- .../settings_modal/tabs/appearance_tab.vue | 45 ++++++++++++++++++++++ src/i18n/en.json | 1 + src/modules/config.js | 2 + src/modules/instance.js | 1 + 6 files changed, 57 insertions(+), 2 deletions(-) (limited to 'src/modules') diff --git a/src/components/font_control/font_control.js b/src/components/font_control/font_control.js index f6f45c8c..08d0907e 100644 --- a/src/components/font_control/font_control.js +++ b/src/components/font_control/font_control.js @@ -30,7 +30,7 @@ export default { emits: ['update:modelValue'], data () { return { - manualEntry: true, + manualEntry: false, availableOptions: [ this.noInherit ? '' : 'inherit', 'serif', diff --git a/src/components/settings_modal/tabs/appearance_tab.js b/src/components/settings_modal/tabs/appearance_tab.js index d9a0429a..3776464a 100644 --- a/src/components/settings_modal/tabs/appearance_tab.js +++ b/src/components/settings_modal/tabs/appearance_tab.js @@ -4,6 +4,8 @@ import IntegerSetting from '../helpers/integer_setting.vue' import FloatSetting from '../helpers/float_setting.vue' import UnitSetting, { defaultHorizontalUnits } from '../helpers/unit_setting.vue' +import FontControl from 'src/components/font_control/font_control.vue' + import SharedComputedObject from '../helpers/shared_computed_object.js' import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue' import { library } from '@fortawesome/fontawesome-svg-core' @@ -36,12 +38,16 @@ const AppearanceTab = { IntegerSetting, FloatSetting, UnitSetting, - ProfileSettingIndicator + ProfileSettingIndicator, + FontControl }, computed: { horizontalUnits () { return defaultHorizontalUnits }, + fontsOverride () { + return this.$store.getters.mergedConfig.fontsOverride + }, columns () { const mode = this.$store.getters.mergedConfig.thirdColumnMode diff --git a/src/components/settings_modal/tabs/appearance_tab.vue b/src/components/settings_modal/tabs/appearance_tab.vue index 5356292e..fb24cc6b 100644 --- a/src/components/settings_modal/tabs/appearance_tab.vue +++ b/src/components/settings_modal/tabs/appearance_tab.vue @@ -34,6 +34,51 @@ +
  • +

    {{ $t('settings.style.interface_font_user_override') }}

    +
      +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    +
  • Date: Wed, 10 Jul 2024 22:49:56 +0300 Subject: MASSIVELY streamlined theme setting process, now EVERYTHING happens in a vuex action "setTheme" instead of several different applyTheme()s scattered around --- src/boot/after_store.js | 29 +----- .../settings_modal/tabs/appearance_tab.js | 5 + .../settings_modal/tabs/appearance_tab.vue | 9 ++ .../settings_modal/tabs/theme_tab/theme_tab.js | 9 +- src/modules/config.js | 44 +++++---- src/modules/instance.js | 101 ++++++++++++++++----- src/services/style_setter/style_setter.js | 23 +---- src/services/theme_data/theme2_to_theme3.js | 1 + src/services/theme_data/theme_data_3.service.js | 5 +- .../specs/services/theme_data/theme_data3.spec.js | 44 +++++---- 10 files changed, 159 insertions(+), 111 deletions(-) (limited to 'src/modules') diff --git a/src/boot/after_store.js b/src/boot/after_store.js index b93e28a3..a486bd4c 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -13,8 +13,7 @@ import VBodyScrollLock from 'src/directives/body_scroll_lock' 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, tryLoadCache } from '../services/style_setter/style_setter.js' +import { applyConfig } from '../services/style_setter/style_setter.js' import FaviconService from '../services/favicon_service/favicon_service.js' import { initServiceWorker, updateFocus } from '../services/sw/sw.js' @@ -160,8 +159,6 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => { copyInstanceOption('showFeaturesPanel') copyInstanceOption('hideSitename') copyInstanceOption('sidebarRight') - - return store.dispatch('setTheme', config.theme) } const getTOS = async ({ store }) => { @@ -352,29 +349,7 @@ const afterStoreSetup = async ({ store, i18n }) => { store.dispatch('setInstanceOption', { name: 'server', value: server }) await setConfig({ store }) - - const { customTheme, customThemeSource, forceThemeRecompilation, themeDebug } = store.state.config - const { theme } = store.state.instance - const customThemePresent = customThemeSource || customTheme - - console.log('DEBUG INITIAL', themeDebug, forceThemeRecompilation) - - if (!forceThemeRecompilation && !themeDebug && tryLoadCache()) { - store.commit('setThemeApplied') - } else { - if (customThemePresent) { - if (customThemeSource && customThemeSource.themeEngineVersion === CURRENT_VERSION) { - applyTheme(customThemeSource, () => {}, themeDebug) - } else { - applyTheme(customTheme, () => {}, themeDebug) - } - store.commit('setThemeApplied') - } else if (theme) { - // do nothing, it will load asynchronously - } else { - console.error('Failed to load any theme!') - } - } + await store.dispatch('setTheme') applyConfig(store.state.config) diff --git a/src/components/settings_modal/tabs/appearance_tab.js b/src/components/settings_modal/tabs/appearance_tab.js index 3776464a..d340fd00 100644 --- a/src/components/settings_modal/tabs/appearance_tab.js +++ b/src/components/settings_modal/tabs/appearance_tab.js @@ -29,6 +29,11 @@ const AppearanceTab = { key: mode, value: i - 1, label: this.$t(`settings.forced_roundness_mode_${mode}`) + })), + underlayOverrideModes: ['none', 'opaque', 'transparent'].map((mode, i) => ({ + key: mode, + value: mode, + label: this.$t(`settings.underlay_override_mode_${mode}`) })) } }, diff --git a/src/components/settings_modal/tabs/appearance_tab.vue b/src/components/settings_modal/tabs/appearance_tab.vue index fb24cc6b..d3df76a1 100644 --- a/src/components/settings_modal/tabs/appearance_tab.vue +++ b/src/components/settings_modal/tabs/appearance_tab.vue @@ -182,6 +182,15 @@ {{ $t('settings.force_interface_roundness') }}
  • +
  • + + {{ $t('settings.underlay_overrides') }} + +
  • {{ $t('settings.hide_wallpaper') }} diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.js b/src/components/settings_modal/tabs/theme_tab/theme_tab.js index 72e2b625..7ca3b066 100644 --- a/src/components/settings_modal/tabs/theme_tab/theme_tab.js +++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.js @@ -502,6 +502,7 @@ export default { this.$store.dispatch('setOption', { name: 'customTheme', value: { + ignore: true, themeFileVersion: this.selectedVersion, themeEngineVersion: CURRENT_VERSION, ...this.previewTheme @@ -699,13 +700,13 @@ export default { } }, updateTheme3Preview () { - console.log(this.previewTheme) const theme2 = convertTheme2To3(this.previewTheme) const theme3 = init({ - extraRuleset: theme2, + inputRuleset: theme2, ultimateBackgroundColor: '#000000', liteMode: true }) + this.themeV3Preview = getCssRules(theme3.eager) .map(x => { if (x.startsWith('html')) { @@ -722,7 +723,7 @@ export default { watch: { currentRadii () { try { - this.previewTheme.radii = generateRadii({ radii: this.currentRadii }).theme + this.previewTheme.radii = generateRadii({ radii: this.currentRadii }).theme.radii this.radiiInvalid = false } catch (e) { this.radiiInvalid = true @@ -744,7 +745,7 @@ export default { fontsLocal: { handler () { try { - this.previewTheme.fonts = generateFonts({ fonts: this.fontsLocal }).theme + this.previewTheme.fonts = generateFonts({ fonts: this.fontsLocal }).theme.fonts this.fontsInvalid = false } catch (e) { this.fontsInvalid = true diff --git a/src/modules/config.js b/src/modules/config.js index 59d056d9..56151d2a 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -1,10 +1,21 @@ import Cookies from 'js-cookie' -import { setPreset, applyTheme, applyConfig } from '../services/style_setter/style_setter.js' +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] @@ -81,6 +92,11 @@ export const defaultState = { chatMention: true, polls: true }, + palette: null, + theme3hacks: { + underlay: 'none', + badgeColor: null + }, webPushNotifications: false, webPushAlwaysShowNotifications: false, muteWords: [], @@ -185,7 +201,6 @@ const config = { applyConfig(state) }, setOption (state, { name, value }) { - console.log('SET OPTION', state, name, value) set(state, name, value) }, setHighlight (state, { user, color, type }) { @@ -261,30 +276,23 @@ const config = { } } else { commit('setOption', { name, value }) + if ( + name.startsWith('theme3hacks') || + APPEARANCE_SETTINGS_KEYS.has(name) + ) { + applyConfig(state) + } switch (name) { case 'theme': - setPreset(value) - break - case 'sidebarColumnWidth': - case 'contentColumnWidth': - case 'notifsColumnWidth': - case 'textSize': - case 'navbarSize': - case 'panelHeaderSize': - case 'forcedRoundness': - case 'emojiSize': - case 'emojiReactionsScale': - applyConfig(state) + dispatch('setTheme', { themeName: value, recompile: true }) break case 'customTheme': case 'customThemeSource': { - const { themeDebug } = state - applyTheme(value, () => {}, themeDebug) + if (!value.ignore) dispatch('setTheme', { themeData: value }) break } case 'themeDebug': { - const { customTheme, customThemeSource } = state - applyTheme(customTheme || customThemeSource, () => {}, value) + dispatch('setTheme', { recompile: true }) break } case 'interfaceLanguage': diff --git a/src/modules/instance.js b/src/modules/instance.js index 602503ed..85a966b8 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -1,5 +1,6 @@ -import { getPreset, applyTheme } from '../services/style_setter/style_setter.js' -import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js' +import { getPreset, applyTheme, tryLoadCache } from '../services/style_setter/style_setter.js' +import { CURRENT_VERSION, generatePreset } from 'src/services/theme_data/theme_data.service.js' +import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js' import apiService from '../services/api/api.service.js' import { instanceDefaultProperties } from './config.js' import { langCodeToCldrName, ensureFinalFallback } from '../i18n/languages.js' @@ -286,9 +287,6 @@ const instance = { dispatch('initializeSocket') } break - case 'theme': - dispatch('setTheme', value) - break } }, async getStaticEmoji ({ commit }) { @@ -378,25 +376,86 @@ const instance = { } }, - setTheme ({ commit, rootState }, themeName) { - commit('setInstanceOption', { name: 'theme', value: themeName }) - getPreset(themeName) - .then(themeData => { - commit('setInstanceOption', { name: 'themeData', value: themeData }) - // No need to apply theme if there's user theme already - const { customTheme, themeDebug } = rootState.config - const { themeApplied } = rootState.interface - if (customTheme || themeApplied) return - - // New theme presets don't have 'theme' property, they use 'source' - const themeSource = themeData.source - if (!themeData.theme || (themeSource && themeSource.themeEngineVersion === CURRENT_VERSION)) { - applyTheme(themeSource, null, themeDebug) + setTheme ({ commit, state, rootState }, { themeName, themeData, recompile } = {}) { + // const { + // themeApplied + // } = rootState.interface + const { + theme: instanceThemeName + } = state + + const { + customTheme: userThemeSnapshot, + customThemeSource: userThemeSource, + forceThemeRecompilation, + themeDebug + } = rootState.config + + const forceRecompile = forceThemeRecompilation || recompile + + // If we're not not forced to recompile try using + // cache (tryLoadCache return true if load successful) + if (!forceRecompile && !themeDebug && tryLoadCache()) { + commit('setThemeApplied') + } + + const normalizeThemeData = (themeData) => { + console.log('NORMAL', themeData) + if (themeData.themeFileVerison === 1) { + return generatePreset(themeData).theme + } + // New theme presets don't have 'theme' property, they use 'source' + const themeSource = themeData.source + + let out // shout, shout let it all out + if (!themeData.theme || (themeSource && themeSource.themeEngineVersion === CURRENT_VERSION)) { + out = themeSource || themeData + } else { + out = themeData.theme + } + + // generatePreset here basically creates/updates "snapshot", + // while also fixing the 2.2 -> 2.3 colors/shadows/etc + return generatePreset(out).theme + } + + let promise = null + + if (themeName) { + // commit('setInstanceOption', { name: 'theme', value: themeName }) + promise = getPreset(themeName) + .then(themeData => { + // commit('setInstanceOption', { name: 'themeData', value: themeData }) + return normalizeThemeData(themeData) + }) + } else if (themeData) { + promise = Promise.resolve(normalizeThemeData(themeData)) + } else { + if (userThemeSource || userThemeSnapshot) { + if (userThemeSource && userThemeSource.themeEngineVersion === CURRENT_VERSION) { + promise = Promise.resolve(normalizeThemeData(userThemeSource)) } else { - applyTheme(themeData.theme, null, themeDebug) + promise = Promise.resolve(normalizeThemeData(userThemeSnapshot)) } - commit('setThemeApplied') + } else if (instanceThemeName) { + promise = getPreset(themeName).then(themeData => normalizeThemeData(themeData)) + } + } + + promise + .then(realThemeData => { + console.log('FR FR 1', realThemeData) + const ruleset = convertTheme2To3(realThemeData) + console.log('FR FR 2', ruleset) + + applyTheme( + ruleset, + () => commit('setThemeApplied'), + themeDebug + ) }) + + return promise }, fetchEmoji ({ dispatch, state }) { if (!state.customEmojiFetched) { diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js index 78e7428d..e54a95bf 100644 --- a/src/services/style_setter/style_setter.js +++ b/src/services/style_setter/style_setter.js @@ -1,7 +1,5 @@ import { hex2rgb } from '../color_convert/color_convert.js' -import { generatePreset } from '../theme_data/theme_data.service.js' import { init, getEngineChecksum } 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' import { chunk } from 'lodash' @@ -45,30 +43,20 @@ const adoptStyleSheets = (styles) => { // is nothing to do here. } -export const generateTheme = async (input, callbacks, debug) => { +export const generateTheme = async (inputRuleset, callbacks, debug) => { const { onNewRule = (rule, isLazy) => {}, onLazyFinished = () => {}, onEagerFinished = () => {} } = callbacks - let extraRules - if (input.themeFileVersion === 1) { - extraRules = convertTheme2To3(input) - } else { - const { theme } = generatePreset(input) - extraRules = convertTheme2To3(theme) - } - // Assuming that "worst case scenario background" is panel background since it's the most likely one const themes3 = init({ - extraRules, - ultimateBackgroundColor: extraRules[0].directives['--bg'].split('|')[1].trim(), + inputRuleset, + ultimateBackgroundColor: inputRuleset[0].directives['--bg'].split('|')[1].trim(), debug }) - console.log('DEBUG 2 IS', debug) - getCssRules(themes3.eager, debug).forEach(rule => { // Hacks to support multiple selectors on same component if (rule.match(/::-webkit-scrollbar-button/)) { @@ -162,8 +150,6 @@ export const applyTheme = async (input, onFinish = (data) => {}, debug) => { const eagerStyles = createStyleSheet(EAGER_STYLE_ID) const lazyStyles = createStyleSheet(LAZY_STYLE_ID) - console.log('DEBUG IS', debug) - const { lazyProcessFunc } = await generateTheme( input, { @@ -216,7 +202,6 @@ const extractStyleConfig = ({ textSize } - console.log(forcedRoundness) switch (forcedRoundness) { case 'disable': break @@ -325,5 +310,3 @@ export const getPreset = (val) => { return { theme: data, source: theme.source } }) } - -export const setPreset = (val) => getPreset(val).then(data => applyTheme(data)) diff --git a/src/services/theme_data/theme2_to_theme3.js b/src/services/theme_data/theme2_to_theme3.js index 2c97d18b..b54366bd 100644 --- a/src/services/theme_data/theme2_to_theme3.js +++ b/src/services/theme_data/theme2_to_theme3.js @@ -265,6 +265,7 @@ export const convertTheme2To3 = (data) => { const newRules = [] Object.keys(data.fonts || {}).forEach(key => { if (!fontsKeys.has(key)) return + if (!data.fonts[key]) return const originalFont = data.fonts[key].family const rule = { source: '2to3' } diff --git a/src/services/theme_data/theme_data_3.service.js b/src/services/theme_data/theme_data_3.service.js index e98b19a7..e802a893 100644 --- a/src/services/theme_data/theme_data_3.service.js +++ b/src/services/theme_data/theme_data_3.service.js @@ -150,12 +150,13 @@ const ruleToSelector = genericRuleToSelector(components) export const getEngineChecksum = () => engineChecksum export const init = ({ - extraRuleset, + inputRuleset, ultimateBackgroundColor, debug = false, liteMode = false, rootComponentName = 'Root' }) => { + if (!inputRuleset) throw new Error('Ruleset is null or undefined!') const staticVars = {} const stacked = {} const computed = {} @@ -164,7 +165,7 @@ export const init = ({ ...Object.values(components) .map(c => (c.defaultRules || []).map(r => ({ component: c.name, ...r, source: 'Built-in' }))) .reduce((acc, arr) => [...acc, ...arr], []), - ...extraRuleset + ...inputRuleset ].map(rule => { normalizeCombination(rule) let currentParent = rule.parent diff --git a/test/unit/specs/services/theme_data/theme_data3.spec.js b/test/unit/specs/services/theme_data/theme_data3.spec.js index bb8d785c..92a87de9 100644 --- a/test/unit/specs/services/theme_data/theme_data3.spec.js +++ b/test/unit/specs/services/theme_data/theme_data3.spec.js @@ -66,7 +66,7 @@ describe('Theme Data 3', () => { this.timeout(5000) it('Test initialization without anything', () => { - const out = init([], '#DEADAF') + const out = init({ ruleset: [], ultimateBackgroundColor: '#DEADAF' }) expect(out).to.have.property('eager') expect(out).to.have.property('lazy') @@ -85,13 +85,16 @@ describe('Theme Data 3', () => { }) it('Test initialization with a basic palette', () => { - const out = init([{ - component: 'Root', - directives: { - '--bg': 'color | #008080', - '--fg': 'color | #00C0A0' - } - }], '#DEADAF') + const out = init({ + ruleset: [{ + component: 'Root', + directives: { + '--bg': 'color | #008080', + '--fg': 'color | #00C0A0' + } + }], + ultimateBackgroundColor: '#DEADAF' + }) expect(out.staticVars).to.have.property('bg').equal('#008080') expect(out.staticVars).to.have.property('fg').equal('#00C0A0') @@ -105,17 +108,20 @@ describe('Theme Data 3', () => { }) it('Test initialization with opacity', () => { - const out = init([{ - component: 'Root', - directives: { - '--bg': 'color | #008080' - } - }, { - component: 'Panel', - directives: { - opacity: 0.5 - } - }], '#DEADAF') + const out = init({ + ruleset: [{ + component: 'Root', + directives: { + '--bg': 'color | #008080' + } + }, { + component: 'Panel', + directives: { + opacity: 0.5 + } + }], + ultimateBackgroundColor: '#DEADAF' + }) expect(out.staticVars).to.have.property('bg').equal('#008080') -- cgit v1.2.3-70-g09d2 From 115335e98a675aa9caff747053ea23820ff8e27a Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Fri, 12 Jul 2024 02:13:08 +0300 Subject: move theme application to interface module --- src/modules/instance.js | 85 ------------------------------------------------ src/modules/interface.js | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 85 deletions(-) (limited to 'src/modules') diff --git a/src/modules/instance.js b/src/modules/instance.js index 85a966b8..76661a2a 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -1,6 +1,3 @@ -import { getPreset, applyTheme, tryLoadCache } from '../services/style_setter/style_setter.js' -import { CURRENT_VERSION, generatePreset } from 'src/services/theme_data/theme_data.service.js' -import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js' import apiService from '../services/api/api.service.js' import { instanceDefaultProperties } from './config.js' import { langCodeToCldrName, ensureFinalFallback } from '../i18n/languages.js' @@ -375,88 +372,6 @@ const instance = { console.warn(e) } }, - - setTheme ({ commit, state, rootState }, { themeName, themeData, recompile } = {}) { - // const { - // themeApplied - // } = rootState.interface - const { - theme: instanceThemeName - } = state - - const { - customTheme: userThemeSnapshot, - customThemeSource: userThemeSource, - forceThemeRecompilation, - themeDebug - } = rootState.config - - const forceRecompile = forceThemeRecompilation || recompile - - // If we're not not forced to recompile try using - // cache (tryLoadCache return true if load successful) - if (!forceRecompile && !themeDebug && tryLoadCache()) { - commit('setThemeApplied') - } - - const normalizeThemeData = (themeData) => { - console.log('NORMAL', themeData) - if (themeData.themeFileVerison === 1) { - return generatePreset(themeData).theme - } - // New theme presets don't have 'theme' property, they use 'source' - const themeSource = themeData.source - - let out // shout, shout let it all out - if (!themeData.theme || (themeSource && themeSource.themeEngineVersion === CURRENT_VERSION)) { - out = themeSource || themeData - } else { - out = themeData.theme - } - - // generatePreset here basically creates/updates "snapshot", - // while also fixing the 2.2 -> 2.3 colors/shadows/etc - return generatePreset(out).theme - } - - let promise = null - - if (themeName) { - // commit('setInstanceOption', { name: 'theme', value: themeName }) - promise = getPreset(themeName) - .then(themeData => { - // commit('setInstanceOption', { name: 'themeData', value: themeData }) - return normalizeThemeData(themeData) - }) - } else if (themeData) { - promise = Promise.resolve(normalizeThemeData(themeData)) - } else { - if (userThemeSource || userThemeSnapshot) { - if (userThemeSource && userThemeSource.themeEngineVersion === CURRENT_VERSION) { - promise = Promise.resolve(normalizeThemeData(userThemeSource)) - } else { - promise = Promise.resolve(normalizeThemeData(userThemeSnapshot)) - } - } else if (instanceThemeName) { - promise = getPreset(themeName).then(themeData => normalizeThemeData(themeData)) - } - } - - promise - .then(realThemeData => { - console.log('FR FR 1', realThemeData) - const ruleset = convertTheme2To3(realThemeData) - console.log('FR FR 2', ruleset) - - applyTheme( - ruleset, - () => commit('setThemeApplied'), - themeDebug - ) - }) - - return promise - }, fetchEmoji ({ dispatch, state }) { if (!state.customEmojiFetched) { state.customEmojiFetched = true diff --git a/src/modules/interface.js b/src/modules/interface.js index 2ccfeef3..d1607919 100644 --- a/src/modules/interface.js +++ b/src/modules/interface.js @@ -1,3 +1,7 @@ +import { getPreset, applyTheme, tryLoadCache } from '../services/style_setter/style_setter.js' +import { CURRENT_VERSION, generatePreset } from 'src/services/theme_data/theme_data.service.js' +import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js' + const defaultState = { localFonts: null, themeApplied: false, @@ -207,6 +211,84 @@ const interfaceMod = { }, setLastTimeline ({ commit }, value) { commit('setLastTimeline', value) + }, + setTheme ({ commit, rootState }, { themeName, themeData, recompile } = {}) { + // const { + // themeApplied + // } = rootState.interface + const { + theme: instanceThemeName + } = rootState.instance + + const { + customTheme: userThemeSnapshot, + customThemeSource: userThemeSource, + forceThemeRecompilation, + themeDebug + } = rootState.config + + const forceRecompile = forceThemeRecompilation || recompile + + // If we're not not forced to recompile try using + // cache (tryLoadCache return true if load successful) + if (!forceRecompile && !themeDebug && tryLoadCache()) { + commit('setThemeApplied') + } + + const normalizeThemeData = (themeData) => { + if (themeData.themeFileVerison === 1) { + return generatePreset(themeData).theme + } + // New theme presets don't have 'theme' property, they use 'source' + const themeSource = themeData.source + + let out // shout, shout let it all out + if (!themeData.theme || (themeSource && themeSource.themeEngineVersion === CURRENT_VERSION)) { + out = themeSource || themeData + } else { + out = themeData.theme + } + + // generatePreset here basically creates/updates "snapshot", + // while also fixing the 2.2 -> 2.3 colors/shadows/etc + return generatePreset(out).theme + } + + let promise = null + + if (themeName) { + // commit('setInstanceOption', { name: 'theme', value: themeName }) + promise = getPreset(themeName) + .then(themeData => { + // commit('setInstanceOption', { name: 'themeData', value: themeData }) + return normalizeThemeData(themeData) + }) + } else if (themeData) { + promise = Promise.resolve(normalizeThemeData(themeData)) + } else { + if (userThemeSource || userThemeSnapshot) { + if (userThemeSource && userThemeSource.themeEngineVersion === CURRENT_VERSION) { + promise = Promise.resolve(normalizeThemeData(userThemeSource)) + } else { + promise = Promise.resolve(normalizeThemeData(userThemeSnapshot)) + } + } else if (instanceThemeName) { + promise = getPreset(themeName).then(themeData => normalizeThemeData(themeData)) + } + } + + promise + .then(realThemeData => { + const ruleset = convertTheme2To3(realThemeData) + + applyTheme( + ruleset, + () => commit('setThemeApplied'), + themeDebug + ) + }) + + return promise } } } -- cgit v1.2.3-70-g09d2 From 82ca01ef71c57bcae2c06525c3f43a8713941933 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Fri, 12 Jul 2024 02:14:31 +0300 Subject: cleanup --- src/modules/instance.js | 1 - src/modules/interface.js | 3 --- 2 files changed, 4 deletions(-) (limited to 'src/modules') diff --git a/src/modules/instance.js b/src/modules/instance.js index 76661a2a..49ef391a 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -42,7 +42,6 @@ const defaultState = { registrationOpen: true, server: 'http://localhost:4040/', textlimit: 5000, - themeData: undefined, vapidPublicKey: undefined, // Stuff from static/config.json diff --git a/src/modules/interface.js b/src/modules/interface.js index d1607919..23d6c552 100644 --- a/src/modules/interface.js +++ b/src/modules/interface.js @@ -213,9 +213,6 @@ const interfaceMod = { commit('setLastTimeline', value) }, setTheme ({ commit, rootState }, { themeName, themeData, recompile } = {}) { - // const { - // themeApplied - // } = rootState.interface const { theme: instanceThemeName } = rootState.instance -- cgit v1.2.3-70-g09d2 From cd92eb56e097cbc9a42b31ceb9cf2f0bd94967db Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Fri, 12 Jul 2024 02:19:38 +0300 Subject: don't recompile if cache exists --- src/modules/interface.js | 1 + 1 file changed, 1 insertion(+) (limited to 'src/modules') diff --git a/src/modules/interface.js b/src/modules/interface.js index 23d6c552..a2a7728a 100644 --- a/src/modules/interface.js +++ b/src/modules/interface.js @@ -230,6 +230,7 @@ const interfaceMod = { // cache (tryLoadCache return true if load successful) if (!forceRecompile && !themeDebug && tryLoadCache()) { commit('setThemeApplied') + return } const normalizeThemeData = (themeData) => { -- cgit v1.2.3-70-g09d2 From e029732021f67e13ca20c1b80c1315c4935b9f2b Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Fri, 12 Jul 2024 02:40:57 +0300 Subject: use separate action for setting Theme V2 --- src/components/settings_modal/tabs/theme_tab/theme_tab.js | 12 ++++-------- src/modules/config.js | 11 ++++++----- src/modules/interface.js | 2 -- 3 files changed, 10 insertions(+), 15 deletions(-) (limited to 'src/modules') diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.js b/src/components/settings_modal/tabs/theme_tab/theme_tab.js index 7ca3b066..8d025ea4 100644 --- a/src/components/settings_modal/tabs/theme_tab/theme_tab.js +++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.js @@ -499,18 +499,14 @@ export default { } }, setCustomTheme () { - this.$store.dispatch('setOption', { - name: 'customTheme', - value: { + this.$store.dispatch('setThemeV2', { + customTheme: { ignore: true, themeFileVersion: this.selectedVersion, themeEngineVersion: CURRENT_VERSION, ...this.previewTheme - } - }) - this.$store.dispatch('setOption', { - name: 'customThemeSource', - value: { + }, + customThemeSource: { themeFileVersion: this.selectedVersion, themeEngineVersion: CURRENT_VERSION, shadows: this.shadowsLocal, diff --git a/src/modules/config.js b/src/modules/config.js index 56151d2a..109f2742 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -255,6 +255,11 @@ const config = { revert }) }, + setThemeV2 ({ commit, dispatch }, { customTheme, customThemeSource }) { + 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' @@ -272,6 +277,7 @@ const config = { dispatch('disableMastoSockets') dispatch('setOption', { name: 'useStreamingApi', value: false }) }) + break } } } else { @@ -286,11 +292,6 @@ const config = { case 'theme': dispatch('setTheme', { themeName: value, recompile: true }) break - case 'customTheme': - case 'customThemeSource': { - if (!value.ignore) dispatch('setTheme', { themeData: value }) - break - } case 'themeDebug': { dispatch('setTheme', { recompile: true }) break diff --git a/src/modules/interface.js b/src/modules/interface.js index a2a7728a..6a749bc3 100644 --- a/src/modules/interface.js +++ b/src/modules/interface.js @@ -255,10 +255,8 @@ const interfaceMod = { let promise = null if (themeName) { - // commit('setInstanceOption', { name: 'theme', value: themeName }) promise = getPreset(themeName) .then(themeData => { - // commit('setInstanceOption', { name: 'themeData', value: themeData }) return normalizeThemeData(themeData) }) } else if (themeData) { -- cgit v1.2.3-70-g09d2 From a378c999b78c9138abb8ea1982dca2f976381f10 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Tue, 16 Jul 2024 21:01:20 +0300 Subject: add ability to override underlay color/opacity regardless of theme --- .../settings_modal/tabs/appearance_tab.js | 4 +-- .../settings_modal/tabs/appearance_tab.vue | 4 +-- src/i18n/en.json | 16 ++++++---- src/modules/config.js | 8 ++--- src/modules/interface.js | 34 ++++++++++++++++++++-- src/services/theme_data/theme2_to_theme3.js | 4 ++- 6 files changed, 54 insertions(+), 16 deletions(-) (limited to 'src/modules') diff --git a/src/components/settings_modal/tabs/appearance_tab.js b/src/components/settings_modal/tabs/appearance_tab.js index d340fd00..4f988508 100644 --- a/src/components/settings_modal/tabs/appearance_tab.js +++ b/src/components/settings_modal/tabs/appearance_tab.js @@ -28,12 +28,12 @@ const AppearanceTab = { forcedRoundnessOptions: ['disabled', 'sharp', 'nonsharp', 'round'].map((mode, i) => ({ key: mode, value: i - 1, - label: this.$t(`settings.forced_roundness_mode_${mode}`) + label: this.$t(`settings.style.themes3.hacks.forced_roundness_mode_${mode}`) })), underlayOverrideModes: ['none', 'opaque', 'transparent'].map((mode, i) => ({ key: mode, value: mode, - label: this.$t(`settings.underlay_override_mode_${mode}`) + label: this.$t(`settings.style.themes3.hacks.underlay_override_mode_${mode}`) })) } }, diff --git a/src/components/settings_modal/tabs/appearance_tab.vue b/src/components/settings_modal/tabs/appearance_tab.vue index d3df76a1..85084e29 100644 --- a/src/components/settings_modal/tabs/appearance_tab.vue +++ b/src/components/settings_modal/tabs/appearance_tab.vue @@ -179,7 +179,7 @@ path="forcedRoundness" :options="forcedRoundnessOptions" > - {{ $t('settings.force_interface_roundness') }} + {{ $t('settings.style.themes3.hacks.force_interface_roundness') }}
  • @@ -188,7 +188,7 @@ path="theme3hacks.underlay" :options="underlayOverrideModes" > - {{ $t('settings.underlay_overrides') }} + {{ $t('settings.style.themes3.hacks.underlay_overrides') }}
  • diff --git a/src/i18n/en.json b/src/i18n/en.json index 770a4a65..a1946aed 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -386,11 +386,6 @@ "navbar_size": "Top bar size", "panel_header_size": "Panel header size", "visual_tweaks": "Minor visual tweaks", - "force_interface_roundness": "Override interface roundness/sharpness", - "forced_roundness_mode_disabled": "Use theme defaults", - "forced_roundness_mode_sharp": "Force sharp edges", - "forced_roundness_mode_nonsharp": "Force not-so-sharp (1px roundness) edges", - "forced_roundness_mode_round": "Force round edges", "theme_debug": "Show what background theme engine assumes when dealing with transparancy (DEBUG)", "scale_and_layout": "Interface scale and layout", "mfa": { @@ -749,6 +744,17 @@ "update_preview": "Update preview", "themes3": { "define": "Override", + "hacks": { + "underlay_overrides": "Change underlay", + "underlay_override_mode_none": "Theme default", + "underlay_override_mode_opaque": "Replace with solid color", + "underlay_override_mode_transparent": "Remove entirely (might break some themes)", + "force_interface_roundness": "Override interface roundness/sharpness", + "forced_roundness_mode_disabled": "Use theme defaults", + "forced_roundness_mode_sharp": "Force sharp edges", + "forced_roundness_mode_nonsharp": "Force not-so-sharp (1px roundness) edges", + "forced_roundness_mode_round": "Force round edges" + }, "font": { "group-builtin": "Browser default fonts", "builtin" : { diff --git a/src/modules/config.js b/src/modules/config.js index 109f2742..906a64b0 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -282,12 +282,12 @@ const config = { } } else { commit('setOption', { name, value }) - if ( - name.startsWith('theme3hacks') || - APPEARANCE_SETTINGS_KEYS.has(name) - ) { + if (APPEARANCE_SETTINGS_KEYS.has(name)) { applyConfig(state) } + if (name.startsWith('theme3hacks')) { + dispatch('setTheme', { recompile: true }) + } switch (name) { case 'theme': dispatch('setTheme', { themeName: value, recompile: true }) diff --git a/src/modules/interface.js b/src/modules/interface.js index 6a749bc3..a9cd70e5 100644 --- a/src/modules/interface.js +++ b/src/modules/interface.js @@ -221,7 +221,8 @@ const interfaceMod = { customTheme: userThemeSnapshot, customThemeSource: userThemeSource, forceThemeRecompilation, - themeDebug + themeDebug, + theme3hacks } = rootState.config const forceRecompile = forceThemeRecompilation || recompile @@ -275,7 +276,36 @@ const interfaceMod = { promise .then(realThemeData => { - const ruleset = convertTheme2To3(realThemeData) + const theme2ruleset = convertTheme2To3(realThemeData) + const hacks = [] + + Object.entries(theme3hacks).forEach(([key, value]) => { + switch (key) { + case 'underlay': { + if (value !== 'none') { + const newRule = { + component: 'Underlay', + directives: {} + } + if (value === 'opaque') { + newRule.directives.opacity = 1 + newRule.directives.background = '--wallpaper' + } + if (value === 'transparent') { + newRule.directives.opacity = 0 + } + console.log('NEW RULE', newRule) + hacks.push(newRule) + } + break + } + } + }) + + const ruleset = [ + ...theme2ruleset, + ...hacks + ] applyTheme( ruleset, diff --git a/src/services/theme_data/theme2_to_theme3.js b/src/services/theme_data/theme2_to_theme3.js index b54366bd..95eb03c1 100644 --- a/src/services/theme_data/theme2_to_theme3.js +++ b/src/services/theme_data/theme2_to_theme3.js @@ -12,7 +12,9 @@ export const basePaletteKeys = new Set([ 'cBlue', 'cRed', 'cGreen', - 'cOrange' + 'cOrange', + + 'wallpaper' ]) export const fontsKeys = new Set([ -- cgit v1.2.3-70-g09d2 From 40c9163d215b5ac7b69437f3585586b2174211ca Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 17 Jul 2024 17:19:57 +0300 Subject: optimizations, WIP theme selector --- src/components/panel.style.js | 10 ++ src/components/root.style.js | 5 + .../settings_modal/tabs/appearance_tab.js | 61 +++++++++++- .../settings_modal/tabs/appearance_tab.vue | 30 ++++++ .../settings_modal/tabs/theme_tab/preview.vue | 104 +++++++++++++++++++- .../settings_modal/tabs/theme_tab/theme_tab.js | 20 ++-- .../settings_modal/tabs/theme_tab/theme_tab.scss | 105 --------------------- src/components/status/post.style.js | 9 ++ src/modules/interface.js | 54 +++++++---- src/services/theme_data/css_utils.js | 12 +++ src/services/theme_data/iss_utils.js | 39 +++++++- src/services/theme_data/theme_data_3.service.js | 70 ++++++++++---- 12 files changed, 361 insertions(+), 158 deletions(-) (limited to 'src/modules') diff --git a/src/components/panel.style.js b/src/components/panel.style.js index ad16c18f..1bba4766 100644 --- a/src/components/panel.style.js +++ b/src/components/panel.style.js @@ -20,6 +20,16 @@ export default { 'Tab', 'ListItem' ], + validInnerComponentsLite: [ + 'Text', + 'Link', + 'Icon', + 'Border', + 'Button', + 'Input', + 'PanelHeader', + 'Alert' + ], defaultRules: [ { directives: { diff --git a/src/components/root.style.js b/src/components/root.style.js index f9bdf16e..4bd735aa 100644 --- a/src/components/root.style.js +++ b/src/components/root.style.js @@ -12,6 +12,11 @@ export default { 'Alert', 'Button' // mobile post button ], + validInnerComponentsLite: [ + 'Underlay', + 'Scrollbar', + 'ScrollbarElement' + ], defaultRules: [ { directives: { diff --git a/src/components/settings_modal/tabs/appearance_tab.js b/src/components/settings_modal/tabs/appearance_tab.js index 4f988508..10de0397 100644 --- a/src/components/settings_modal/tabs/appearance_tab.js +++ b/src/components/settings_modal/tabs/appearance_tab.js @@ -6,6 +6,18 @@ import UnitSetting, { defaultHorizontalUnits } from '../helpers/unit_setting.vue import FontControl from 'src/components/font_control/font_control.vue' +import { normalizeThemeData } from 'src/modules/interface' + +import { + getThemes +} from 'src/services/style_setter/style_setter.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 { + getCssRules, + getScopedVersion +} from 'src/services/theme_data/css_utils.js' + import SharedComputedObject from '../helpers/shared_computed_object.js' import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue' import { library } from '@fortawesome/fontawesome-svg-core' @@ -13,6 +25,8 @@ import { faGlobe } from '@fortawesome/free-solid-svg-icons' +import Preview from './theme_tab/preview.vue' + library.add( faGlobe ) @@ -20,6 +34,7 @@ library.add( const AppearanceTab = { data () { return { + availableStyles: [], thirdColumnModeOptions: ['none', 'notifications', 'postform'].map(mode => ({ key: mode, value: mode, @@ -44,7 +59,32 @@ const AppearanceTab = { FloatSetting, UnitSetting, ProfileSettingIndicator, - FontControl + FontControl, + Preview + }, + created () { + const self = this + + getThemes() + .then((promises) => { + return Promise.all( + Object.entries(promises) + .map(([k, v]) => v.then(res => [k, res])) + ) + }) + .then(themes => themes.reduce((acc, [k, v]) => { + if (v) { + return { + ...acc, + [k]: v + } + } else { + return acc + } + }, {})) + .then((themesComplete) => { + self.availableStyles = themesComplete + }) }, computed: { horizontalUnits () { @@ -77,6 +117,25 @@ const AppearanceTab = { } }, ...SharedComputedObject() + }, + methods: { + previewTheme (input) { + const style = normalizeThemeData(input) + const x = 2 + if (x === 1) return + const theme2 = convertTheme2To3(style) + const theme3 = init({ + inputRuleset: theme2, + ultimateBackgroundColor: '#000000', + liteMode: true, + onlyNormalState: true + }) + + return getScopedVersion( + getCssRules(theme3.eager), + '#theme-preview-' + (input.name || input[0]).replace(/ /g, '_') + ).join('\n') + } } } diff --git a/src/components/settings_modal/tabs/appearance_tab.vue b/src/components/settings_modal/tabs/appearance_tab.vue index 85084e29..2488720d 100644 --- a/src/components/settings_modal/tabs/appearance_tab.vue +++ b/src/components/settings_modal/tabs/appearance_tab.vue @@ -1,5 +1,21 @@