Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3

This commit is contained in:
Henry Jameson 2024-11-15 00:40:24 +02:00
commit 89b0ed83f2
17 changed files with 346 additions and 256 deletions

View file

@ -35,6 +35,7 @@
"hash-sum": "^2.0.0", "hash-sum": "^2.0.0",
"js-cookie": "3.0.5", "js-cookie": "3.0.5",
"localforage": "1.10.0", "localforage": "1.10.0",
"pako": "^2.1.0",
"parse-link-header": "2.0.0", "parse-link-header": "2.0.0",
"phoenix": "1.7.7", "phoenix": "1.7.7",
"punycode.js": "2.3.0", "punycode.js": "2.3.0",

View file

@ -1,6 +1,7 @@
export default { export default {
name: 'Attachment', name: 'Attachment',
selector: '.Attachment', selector: '.Attachment',
notEditable: true,
validInnerComponents: [ validInnerComponents: [
'Border', 'Border',
'ButtonUnstyled', 'ButtonUnstyled',

View file

@ -1,5 +1,8 @@
<template> <template>
<div class="PaletteEditor"> <div
class="PaletteEditor"
:class="{ '-compact': compact, '-apply': apply }"
>
<ColorInput <ColorInput
v-for="key in paletteKeys" v-for="key in paletteKeys"
:key="key" :key="key"
@ -22,6 +25,13 @@
<FAIcon icon="file-export" /> <FAIcon icon="file-export" />
{{ $t('settings.style.themes3.palette.export') }} {{ $t('settings.style.themes3.palette.export') }}
</button> </button>
<button
v-if="apply"
class="btn button-default palette-apply-button"
@click="applyPalette"
>
{{ $t('settings.style.themes3.palette.apply') }}
</button>
</div> </div>
</template> </template>
@ -43,12 +53,34 @@ library.add(
faFileExport faFileExport
) )
const props = defineProps(['modelValue']) const paletteKeys = [
const emit = defineEmits(['update:modelValue']) 'bg',
'fg',
'text',
'link',
'accent',
'cRed',
'cBlue',
'cGreen',
'cOrange',
'wallpaper'
]
const props = defineProps(['modelValue', 'compact', 'apply'])
const emit = defineEmits(['update:modelValue', 'applyPalette'])
const getExportedObject = () => paletteKeys.reduce((acc, key) => {
const value = props.modelValue[key]
if (value == null) {
return acc
} else {
return { ...acc, [key]: props.modelValue[key] }
}
}, {})
const paletteExporter = newExporter({ const paletteExporter = newExporter({
filename: 'pleroma_palette', filename: 'pleroma_palette',
extension: 'json', extension: 'json',
getExportedObject: () => props.modelValue getExportedObject
}) })
const paletteImporter = newImporter({ const paletteImporter = newImporter({
accept: '.json', accept: '.json',
@ -65,18 +97,9 @@ const importPalette = () => {
paletteImporter.importData() paletteImporter.importData()
} }
const paletteKeys = [ const applyPalette = (data) => {
'bg', emit('applyPalette', getExportedObject())
'fg', }
'text',
'link',
'accent',
'cRed',
'cBlue',
'cGreen',
'cOrange',
'wallpaper'
]
const fallback = (key) => { const fallback = (key) => {
if (key === 'accent') { if (key === 'accent') {
@ -118,8 +141,33 @@ const updatePalette = (paletteKey, value) => {
grid-column: 3 / span 2; grid-column: 3 / span 2;
} }
.palette-apply-button {
grid-column: 1 / span 2;
}
.color-input.style-control { .color-input.style-control {
margin: 0; margin: 0;
} }
&.-compact {
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(5, 1fr) auto;
.palette-import-button {
grid-column: 1;
}
.palette-export-button {
grid-column: 2;
}
&.-apply {
grid-template-rows: repeat(5, 1fr) auto auto;
.palette-apply-button {
grid-column: 1 / span 2;
}
}
}
} }
</style> </style>

View file

@ -1,6 +1,7 @@
export default { export default {
name: 'RichContent', name: 'RichContent',
selector: '.RichContent', selector: '.RichContent',
notEditable: true,
validInnerComponents: [ validInnerComponents: [
'Text', 'Text',
'FunText', 'FunText',

View file

@ -1,6 +1,21 @@
.settings_tab-switcher { .settings_tab-switcher {
height: 100%; height: 100%;
h1 {
margin-bottom: 0.5em;
margin-top: 0.5em;
}
h4 {
margin-bottom: 0;
margin-top: 0.25em;
}
h5 {
margin-bottom: 0;
margin-top: 0.25em;
}
.setting-item { .setting-item {
border-bottom: 2px solid var(--border); border-bottom: 2px solid var(--border);
margin: 1em 1em 1.4em; margin: 1em 1em 1.4em;

View file

@ -3,6 +3,7 @@ import ChoiceSetting from '../helpers/choice_setting.vue'
import IntegerSetting from '../helpers/integer_setting.vue' import IntegerSetting from '../helpers/integer_setting.vue'
import FloatSetting from '../helpers/float_setting.vue' import FloatSetting from '../helpers/float_setting.vue'
import UnitSetting, { defaultHorizontalUnits } from '../helpers/unit_setting.vue' import UnitSetting, { defaultHorizontalUnits } from '../helpers/unit_setting.vue'
import PaletteEditor from 'src/components/palette_editor/palette_editor.vue'
import FontControl from 'src/components/font_control/font_control.vue' import FontControl from 'src/components/font_control/font_control.vue'
@ -50,6 +51,7 @@ const AppearanceTab = {
'cBlue', 'cBlue',
'cOrange' 'cOrange'
], ],
userPalette: {},
intersectionObserver: null, intersectionObserver: null,
thirdColumnModeOptions: ['none', 'notifications', 'postform'].map(mode => ({ thirdColumnModeOptions: ['none', 'notifications', 'postform'].map(mode => ({
key: mode, key: mode,
@ -76,7 +78,8 @@ const AppearanceTab = {
UnitSetting, UnitSetting,
ProfileSettingIndicator, ProfileSettingIndicator,
FontControl, FontControl,
Preview Preview,
PaletteEditor
}, },
mounted () { mounted () {
const updateIndex = (resource) => { const updateIndex = (resource) => {
@ -105,6 +108,7 @@ const AppearanceTab = {
updateIndex('palette').then(bundledPalettes => { updateIndex('palette').then(bundledPalettes => {
bundledPalettes.forEach(([key, palettePromise]) => palettePromise.then(v => { bundledPalettes.forEach(([key, palettePromise]) => palettePromise.then(v => {
let palette
if (Array.isArray(v)) { if (Array.isArray(v)) {
const [ const [
name, name,
@ -117,9 +121,15 @@ const AppearanceTab = {
cBlue = '#0000FF', cBlue = '#0000FF',
cOrange = '#E3FF00' cOrange = '#E3FF00'
] = v ] = v
this.bundledPalettes.push({ key, name, bg, fg, text, link, cRed, cBlue, cGreen, cOrange }) palette = { key, name, bg, fg, text, link, cRed, cBlue, cGreen, cOrange }
this.bundledPalettes.push()
} else { } else {
this.bundledPalettes.push({ key, ...v }) palette = { key, ...v }
}
this.bundledPalettes.push(palette)
if (this.isPaletteActive(key)) {
this.userPalette = palette
} }
})) }))
}) })
@ -283,30 +293,21 @@ const AppearanceTab = {
return key === palette return key === palette
}, },
setStyle (name) { setStyle (name) {
this.$store.dispatch('resetThemeV2')
this.$store.dispatch('setTheme', name) this.$store.dispatch('setTheme', name)
this.$store.dispatch('applyTheme')
}, },
setTheme (name) { setTheme (name) {
this.$store.dispatch('resetThemeV3')
this.$store.dispatch('setTheme', name) this.$store.dispatch('setTheme', name)
this.$store.dispatch('applyTheme')
}, },
setPalette (name) { setPalette (name, data) {
this.$store.dispatch('resetThemeV2')
this.$store.dispatch('setPalette', name) this.$store.dispatch('setPalette', name)
this.$store.dispatch('applyTheme') this.userPalette = data
}, },
setPaletteCustom (p) { setPaletteCustom (data) {
this.$store.dispatch('resetThemeV2') this.$store.dispatch('setPaletteCustom', data)
this.$store.dispatch('setPaletteCustom', p) this.userPalette = data
this.$store.dispatch('applyTheme')
}, },
resetTheming (name) { resetTheming (name) {
this.$store.dispatch('resetThemeV2')
this.$store.dispatch('resetThemeV3')
this.$store.dispatch('setStyle', 'stock') this.$store.dispatch('setStyle', 'stock')
this.$store.dispatch('applyTheme')
}, },
previewTheme (key, input) { previewTheme (key, input) {
let theme3 let theme3

View file

@ -26,7 +26,8 @@
grid-gap: 0.5em; grid-gap: 0.5em;
h4, h4,
.unsupported-theme-v2 { .unsupported-theme-v2,
.userPalette {
grid-column: 1 / span 2; grid-column: 1 / span 2;
} }
} }
@ -71,6 +72,7 @@
border-radius: var(--roundness); border-radius: var(--roundness);
border: 1px solid var(--border); border: 1px solid var(--border);
padding: 0; padding: 0;
margin-bottom: 1em;
.theme-preview { .theme-preview {
font-size: 1rem; // fix for firefox font-size: 1rem; // fix for firefox

View file

@ -3,17 +3,8 @@
class="appearance-tab" class="appearance-tab"
:label="$t('settings.general')" :label="$t('settings.general')"
> >
<div class="setting-item heading">
<h2>{{ $t('settings.theme') }}</h2>
<button
class="btn button-default"
@click="importFile"
>
<FAIcon icon="folder-open" />
{{ $t('settings.style.themes3.editor.load_style') }}
</button>
</div>
<div class="setting-item"> <div class="setting-item">
<h2>{{ $t('settings.theme') }}</h2>
<ul <ul
ref="themeList" ref="themeList"
class="theme-list" class="theme-list"
@ -69,60 +60,81 @@
</h4> </h4>
</button> </button>
</ul> </ul>
<h3>{{ $t('settings.style.themes3.palette.label') }}</h3> <div class="import-file-container">
<div class="palettes"> <button
<template v-if="customThemeVersion === 'v3'"> class="btn button-default"
<h4>{{ $t('settings.style.themes3.palette.bundled') }}</h4> @click="importFile"
<button >
v-for="p in bundledPalettes" <FAIcon icon="folder-open" />
:key="p.name" {{ $t('settings.style.themes3.editor.load_style') }}
class="btn button-default palette-entry" </button>
:class="{ toggled: isPaletteActive(p.key) }" </div>
@click="() => setPalette(p.key)" <div class="setting-item">
> <h2>{{ $t('settings.style.themes3.palette.label') }}</h2>
<label> <div class="palettes">
{{ p.name }} <template v-if="customThemeVersion === 'v3'">
</label> <h4>{{ $t('settings.style.themes3.palette.bundled') }}</h4>
<span <button
v-for="c in palettesKeys" v-for="p in bundledPalettes"
:key="c" :key="p.name"
class="palette-square" class="btn button-default palette-entry"
:style="{ backgroundColor: p[c], border: '1px solid ' + (p[c] ?? 'var(--text)') }" :class="{ toggled: isPaletteActive(p.key) }"
/> @click="() => setPalette(p.key, p)"
</button> >
<h4 v-if="stylePalettes?.length > 0"> <label>
{{ $t('settings.style.themes3.palette.style') }} {{ p.name }}
</h4> </label>
<button <span
v-for="p in stylePalettes || []" v-for="c in palettesKeys"
:key="p.name" :key="c"
class="btn button-default palette-entry" class="palette-square"
:class="{ toggled: isPaletteActive(p.key) }" :style="{ backgroundColor: p[c], border: '1px solid ' + (p[c] ?? 'var(--text)') }"
@click="() => setPaletteCustom(p)" />
> </button>
<label> <h4 v-if="stylePalettes?.length > 0">
{{ p.name }} {{ $t('settings.style.themes3.palette.style') }}
</label> </h4>
<span <button
v-for="c in palettesKeys" v-for="p in stylePalettes || []"
:key="c" :key="p.name"
class="palette-square" class="btn button-default palette-entry"
:style="{ backgroundColor: p[c], border: '1px solid ' + (p[c] ?? 'var(--text)') }" :class="{ toggled: isPaletteActive(p.key) }"
/> @click="() => setPaletteCustom(p)"
</button> >
</template> <label>
<template v-else-if="customThemeVersion === 'v2'"> {{ p.name }}
<div class="alert neutral theme-notice unsupported-theme-v2"> </label>
{{ $t('settings.style.themes3.palette.v2_unsupported') }} <span
</div> v-for="c in palettesKeys"
</template> :key="c"
class="palette-square"
:style="{ backgroundColor: p[c], border: '1px solid ' + (p[c] ?? 'var(--text)') }"
/>
</button>
<h4>
{{ $t('settings.style.themes3.palette.user') }}
</h4>
<PaletteEditor
class="userPalette"
v-model="userPalette"
:compact="true"
:apply="true"
@applyPalette="data => setPaletteCustom(data)"
/>
</template>
<template v-else-if="customThemeVersion === 'v2'">
<div class="alert neutral theme-notice unsupported-theme-v2">
{{ $t('settings.style.themes3.palette.v2_unsupported') }}
</div>
</template>
</div>
</div> </div>
</div>
<div class="alert neutral theme-notice">
{{ $t("settings.style.appearance_tab_note") }}
</div> </div>
<div class="setting-item"> <div class="setting-item">
<h2>{{ $t('settings.scale_and_layout') }}</h2> <h2>{{ $t('settings.scale_and_layout') }}</h2>
<div class="alert neutral theme-notice">
{{ $t("settings.style.appearance_tab_note") }}
</div>
<ul class="setting-list"> <ul class="setting-list">
<li> <li>
<UnitSetting <UnitSetting

View file

@ -1,4 +1,4 @@
import { ref, reactive, computed, watch, watchEffect, provide } from 'vue' import { ref, reactive, computed, watch, watchEffect, provide, getCurrentInstance } from 'vue'
import { useStore } from 'vuex' import { useStore } from 'vuex'
import { get, set, unset, throttle } from 'lodash' import { get, set, unset, throttle } from 'lodash'
@ -84,6 +84,12 @@ export default {
// All rules that are made by editor // All rules that are made by editor
const allEditedRules = reactive({}) const allEditedRules = reactive({})
exports.isActive = computed(() => {
const tabSwitcher = getCurrentInstance().parent.ctx
console.log('TABSW', tabSwitcher)
return tabSwitcher ? tabSwitcher.isActive('style') : false
})
// ## Meta stuff // ## Meta stuff
exports.name = ref('') exports.name = ref('')
exports.author = ref('') exports.author = ref('')
@ -374,7 +380,7 @@ export default {
exports.editedOpacity = getEditedElement(null, 'opacity') exports.editedOpacity = getEditedElement(null, 'opacity')
exports.isOpacityPresent = isElementPresent(null, 'opacity', 1) exports.isOpacityPresent = isElementPresent(null, 'opacity', 1)
exports.editedRoundness = getEditedElement(null, 'roundness') exports.editedRoundness = getEditedElement(null, 'roundness')
exports.isRoundnessPresent = isElementPresent(null, 'roundness', 0) exports.isRoundnessPresent = isElementPresent(null, 'roundness', '0')
exports.editedTextColor = getEditedElement('Text', 'textColor') exports.editedTextColor = getEditedElement('Text', 'textColor')
exports.isTextColorPresent = isElementPresent('Text', 'textColor', '#000000') exports.isTextColorPresent = isElementPresent('Text', 'textColor', '#000000')
exports.editedTextAuto = getEditedElement('Text', 'textAuto') exports.editedTextAuto = getEditedElement('Text', 'textAuto')

View file

@ -48,6 +48,42 @@
} }
} }
.meta-preview {
display: grid;
grid-template:
"meta meta preview preview"
"meta meta preview preview"
"meta meta preview preview"
"meta meta preview preview";
grid-gap: 0.5em;
grid-template-columns: min-content min-content 6fr max-content;
ul.setting-list {
padding: 0;
margin: 0;
display: grid;
grid-template-rows: subgrid;
grid-area: meta;
> li {
margin: 0;
}
.meta-field {
margin: 0;
.setting-label {
display: inline-block;
margin-bottom: 0.5em;
}
}
}
#edited-style-preview {
grid-area: preview;
}
}
.setting-item { .setting-item {
padding-bottom: 0; padding-bottom: 0;
@ -62,65 +98,6 @@
&:not(:last-child) { &:not(:last-child) {
margin-bottom: 0.5em; margin-bottom: 0.5em;
} }
&.heading {
display: grid;
grid-template:
"meta meta preview preview"
"meta meta preview preview"
"meta meta preview preview"
"meta meta preview preview"
"new new preview preview"
"load save refresh apply";
grid-gap: 0.5em;
grid-template-columns: min-content min-content 6fr max-content;
grid-template-rows: repeat(4, min-content) repeat(2, 2em);
ul.setting-list {
padding: 0;
margin: 0;
display: grid;
grid-template-rows: subgrid;
grid-area: meta;
> li {
margin: 0;
}
.meta-field {
margin: 0;
.setting-label {
display: inline-block;
margin-bottom: 0.5em;
}
}
}
#edited-style-preview {
grid-area: preview;
}
.button-save {
grid-area: save;
}
.button-load {
grid-area: load;
}
.button-new {
grid-area: new;
}
.button-refresh {
grid-area: refresh;
}
.button-apply {
grid-area: apply;
}
}
} }
.list-editor { .list-editor {
@ -271,3 +248,17 @@
} }
} }
} }
.extra-content {
.style-actions-container {
width: 100%;
display: flex;
justify-content: end;
.style-actions {
display: grid;
grid-template-columns: repeat(4, minmax(7em, 1fr));
grid-gap: 0.25em;
}
}
}

View file

@ -4,70 +4,75 @@
<template> <template>
<div class="StyleTab"> <div class="StyleTab">
<div class="setting-item heading"> <div class="setting-item heading">
<!-- eslint-disable vue/no-v-text-v-html-on-component --> <h2> {{ $t('settings.style.themes3.editor.title') }} </h2>
<component <div class="meta-preview">
:is="'style'" <!-- eslint-disable vue/no-v-text-v-html-on-component -->
v-html="overallPreviewCssRules" <component
/> :is="'style'"
<!-- eslint-enable vue/no-v-text-v-html-on-component --> v-html="overallPreviewCssRules"
<Preview id="edited-style-preview" /> />
<button <!-- eslint-enable vue/no-v-text-v-html-on-component -->
class="btn button-default button-new" <Preview id="edited-style-preview" />
@click="clearTheme" <teleport
> v-if="isActive"
<FAIcon icon="file" /> to="#unscrolled-content"
{{ $t('settings.style.themes3.editor.new_style') }} >
</button> <div class="style-actions-container">
<button <div class="style-actions">
class="btn button-default button-load" <button
@click="importStyle" class="btn button-default button-new"
> @click="clearTheme"
<FAIcon icon="folder-open" /> >
{{ $t('settings.style.themes3.editor.load_style') }} <FAIcon icon="arrows-rotate" />
</button> {{ $t('settings.style.themes3.editor.reset_style') }}
<button </button>
class="btn button-default button-save" <button
@click="exportStyle" class="btn button-default button-load"
> @click="importStyle"
<FAIcon icon="floppy-disk" /> >
{{ $t('settings.style.themes3.editor.save_style') }} <FAIcon icon="folder-open" />
</button> {{ $t('settings.style.themes3.editor.load_style') }}
<button </button>
class="btn button-default button-refresh" <button
@click="updateOverallPreview" class="btn button-default button-save"
> @click="exportStyle"
<FAIcon icon="arrows-rotate" /> >
{{ $t('settings.style.themes3.editor.refresh_preview') }} <FAIcon icon="floppy-disk" />
</button> {{ $t('settings.style.themes3.editor.save_style') }}
<button </button>
class="btn button-default button-apply" <button
@click="applyStyle" class="btn button-default button-apply"
> @click="applyStyle"
<FAIcon icon="check" /> >
{{ $t('settings.style.themes3.editor.apply_preview') }} <FAIcon icon="check" />
</button> {{ $t('settings.style.themes3.editor.apply_preview') }}
<ul class="setting-list style-metadata"> </button>
<li> </div>
<StringSetting class="meta-field" v-model="name"> </div>
{{ $t('settings.style.themes3.editor.style_name') }} </teleport>
</StringSetting> <ul class="setting-list style-metadata">
</li> <li>
<li> <StringSetting class="meta-field" v-model="name">
<StringSetting class="meta-field" v-model="author"> {{ $t('settings.style.themes3.editor.style_name') }}
{{ $t('settings.style.themes3.editor.style_author') }} </StringSetting>
</StringSetting> </li>
</li> <li>
<li> <StringSetting class="meta-field" v-model="author">
<StringSetting class="meta-field" v-model="license"> {{ $t('settings.style.themes3.editor.style_author') }}
{{ $t('settings.style.themes3.editor.style_license') }} </StringSetting>
</StringSetting> </li>
</li> <li>
<li> <StringSetting class="meta-field" v-model="license">
<StringSetting class="meta-field" v-model="website"> {{ $t('settings.style.themes3.editor.style_license') }}
{{ $t('settings.style.themes3.editor.style_website') }} </StringSetting>
</StringSetting> </li>
</li> <li>
</ul> <StringSetting class="meta-field" v-model="website">
{{ $t('settings.style.themes3.editor.style_website') }}
</StringSetting>
</li>
</ul>
</div>
</div> </div>
<tab-switcher> <tab-switcher>
<div <div

View file

@ -145,8 +145,8 @@
<input <input
id="spread" id="spread"
:value="selected?.spread" :value="selected?.spread"
:disabled="disabled || !present || (separateInset && !selected?.inset)"
:class="{ disabled: disabled || !present || (separateInset && !selected?.inset) }" :class="{ disabled: disabled || !present || (separateInset && !selected?.inset) }"
:disabled="disabled || !present || (separateInset && !selected?.inset)"
name="spread" name="spread"
class="input input-range" class="input input-range"
type="range" type="range"
@ -158,7 +158,7 @@
:value="selected?.spread" :value="selected?.spread"
class="input input-number -small" class="input input-number -small"
:class="{ disabled: disabled || !present || (separateInset && !selected?.inset) }" :class="{ disabled: disabled || !present || (separateInset && !selected?.inset) }"
:disabled="{ disabled: disabled || !present || (separateInset && !selected?.inset) }" :disabled="disabled || !present || (separateInset && !selected?.inset)"
type="number" type="number"
@input="e => updateProperty('spread', e.target.value)" @input="e => updateProperty('spread', e.target.value)"
> >

View file

@ -1,6 +1,7 @@
export default { export default {
name: 'UserCard', name: 'UserCard',
selector: '.user-card', selector: '.user-card',
notEditable: true,
validInnerComponents: [ validInnerComponents: [
'Text', 'Text',
'Link', 'Link',

View file

@ -759,8 +759,9 @@
"palette": { "palette": {
"label": "Color schemes", "label": "Color schemes",
"name_label": "Color scheme name", "name_label": "Color scheme name",
"import": "Import", "import": "Import palette",
"export": "Export", "export": "Export palette",
"apply": "Apply palette",
"bg": "Panel background", "bg": "Panel background",
"fg": "Buttons etc.", "fg": "Buttons etc.",
"text": "Text", "text": "Text",
@ -773,12 +774,13 @@
"wallpaper": "Wallpaper", "wallpaper": "Wallpaper",
"v2_unsupported": "Older v2 themes don't support palettes. Switch to v3 theme to make use of palettes", "v2_unsupported": "Older v2 themes don't support palettes. Switch to v3 theme to make use of palettes",
"bundled": "Bundled palettes", "bundled": "Bundled palettes",
"style": "Palettes provided by selected style" "style": "Palettes provided by selected style",
"user": "Custom palette"
}, },
"editor": { "editor": {
"title": "Style", "title": "Style",
"new_style": "New", "reset_style": "Reset",
"load_style": "Open", "load_style": "Open from file",
"save_style": "Save", "save_style": "Save",
"style_name": "Stylesheet name", "style_name": "Stylesheet name",
"style_author": "Made by", "style_author": "Made by",

View file

@ -230,7 +230,7 @@ const interfaceMod = {
commit('setOption', { name: 'palette', value }) commit('setOption', { name: 'palette', value })
dispatch('applyTheme') dispatch('applyTheme', { recompile: true })
}, },
setPaletteCustom ({ dispatch, commit }, value) { setPaletteCustom ({ dispatch, commit }, value) {
dispatch('resetThemeV3Palette') dispatch('resetThemeV3Palette')
@ -238,7 +238,7 @@ const interfaceMod = {
commit('setOption', { name: 'paletteCustomData', value }) commit('setOption', { name: 'paletteCustomData', value })
dispatch('applyTheme') dispatch('applyTheme', { recompile: true })
}, },
async fetchStylesIndex ({ commit, state }) { async fetchStylesIndex ({ commit, state }) {
try { try {
@ -257,7 +257,7 @@ const interfaceMod = {
commit('setOption', { name: 'style', value }) commit('setOption', { name: 'style', value })
dispatch('applyTheme') dispatch('applyTheme', { recompile: true })
}, },
setStyleCustom ({ dispatch, commit }, value) { setStyleCustom ({ dispatch, commit }, value) {
dispatch('resetThemeV3') dispatch('resetThemeV3')
@ -265,7 +265,7 @@ const interfaceMod = {
commit('setOption', { name: 'styleCustomData', value }) commit('setOption', { name: 'styleCustomData', value })
dispatch('applyTheme') dispatch('applyTheme', { recompile: true })
}, },
async fetchThemesIndex ({ commit, state }) { async fetchThemesIndex ({ commit, state }) {
try { try {
@ -285,7 +285,7 @@ const interfaceMod = {
commit('setOption', { name: 'theme', value }) commit('setOption', { name: 'theme', value })
dispatch('applyTheme') dispatch('applyTheme', { recompile: true })
}, },
setThemeCustom ({ dispatch, commit }, value) { setThemeCustom ({ dispatch, commit }, value) {
dispatch('resetThemeV3') dispatch('resetThemeV3')
@ -295,7 +295,7 @@ const interfaceMod = {
commit('setOption', { name: 'customTheme', value }) commit('setOption', { name: 'customTheme', value })
commit('setOption', { name: 'customThemeSource', value }) commit('setOption', { name: 'customThemeSource', value })
dispatch('applyTheme') dispatch('applyTheme', { recompile: true })
}, },
resetThemeV3 ({ dispatch, commit }) { resetThemeV3 ({ dispatch, commit }) {
commit('setOption', { name: 'style', value: null }) commit('setOption', { name: 'style', value: null })
@ -312,7 +312,7 @@ const interfaceMod = {
}, },
async applyTheme ( async applyTheme (
{ dispatch, commit, rootState, state }, { dispatch, commit, rootState, state },
{ recompile = true } = {} { recompile = false } = {}
) { ) {
// If we're not not forced to recompile try using // If we're not not forced to recompile try using
// cache (tryLoadCache return true if load successful) // cache (tryLoadCache return true if load successful)
@ -350,15 +350,15 @@ const interfaceMod = {
let majorVersionUsed let majorVersionUsed
console.log( console.debug(
`USER V3 palette: ${userPaletteName}, style: ${userStyleName} , custom: ${!!userStyleCustomData}` `User V3 palette: ${userPaletteName}, style: ${userStyleName} , custom: ${!!userStyleCustomData}`
) )
console.log( console.debug(
`USER V2 name: ${userThemeV2Name}, source: ${!!userThemeV2Source}, snapshot: ${!!userThemeV2Snapshot}` `User V2 name: ${userThemeV2Name}, source: ${!!userThemeV2Source}, snapshot: ${!!userThemeV2Snapshot}`
) )
console.log(`INST V3 palette: ${instancePaletteName}, style: ${instanceStyleName}`) console.debug(`Instance V3 palette: ${instancePaletteName}, style: ${instanceStyleName}`)
console.log('INST V2 theme: ' + instanceThemeV2Name) console.debug('Instance V2 theme: ' + instanceThemeV2Name)
if (userPaletteName || userPaletteCustomData || if (userPaletteName || userPaletteCustomData ||
userStyleName || userStyleCustomData || userStyleName || userStyleCustomData ||
@ -446,7 +446,7 @@ const interfaceMod = {
return result return result
} }
console.log('VERSION', majorVersionUsed) console.debug('Version used', majorVersionUsed)
if (majorVersionUsed === 'v3') { if (majorVersionUsed === 'v3') {
const palette = await getData( const palette = await getData(
@ -471,7 +471,7 @@ const interfaceMod = {
] = paletteDataUsed ] = paletteDataUsed
paletteDataUsed = { name, bg, fg, text, link, cRed, cBlue, cGreen, cOrange } paletteDataUsed = { name, bg, fg, text, link, cRed, cBlue, cGreen, cOrange }
} }
console.log(paletteDataUsed) console.debug('Palette data used', paletteDataUsed)
const style = await getData( const style = await getData(
'style', 'style',
@ -506,7 +506,6 @@ const interfaceMod = {
directives: {} directives: {}
} }
console.log('PALETTE', paletteDataUsed)
Object Object
.entries(paletteDataUsed) .entries(paletteDataUsed)
.filter(([k]) => k !== 'name') .filter(([k]) => k !== 'name')

View file

@ -2,6 +2,8 @@ import { init, getEngineChecksum } from '../theme_data/theme_data_3.service.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'
import { chunk } from 'lodash' import { chunk } from 'lodash'
import pako from 'pako'
import localforage from 'localforage'
// On platforms where this is not supported, it will return undefined // On platforms where this is not supported, it will return undefined
// Otherwise it will return an array // Otherwise it will return an array
@ -87,12 +89,15 @@ export const generateTheme = (inputRuleset, callbacks, debug) => {
return { lazyProcessFunc: processChunk } return { lazyProcessFunc: processChunk }
} }
export const tryLoadCache = () => { export const tryLoadCache = async () => {
const json = localStorage.getItem('pleroma-fe-theme-cache') console.info('Trying to load compiled theme data from cache')
if (!json) return null const data = await localforage.getItem('pleromafe-theme-cache')
if (!data) return null
let cache let cache
try { try {
cache = JSON.parse(json) const decoded = new TextDecoder().decode(pako.inflate(data))
cache = JSON.parse(decoded)
console.info(`Loaded theme from cache, size=${cache}`)
} catch (e) { } catch (e) {
console.error('Failed to decode theme cache:', e) console.error('Failed to decode theme cache:', e)
return false return false
@ -136,16 +141,10 @@ export const applyTheme = (input, onFinish = (data) => {}, debug) => {
adoptStyleSheets([eagerStyles, lazyStyles]) adoptStyleSheets([eagerStyles, lazyStyles])
const cache = { engineChecksum: getEngineChecksum(), data: [eagerStyles.rules, lazyStyles.rules] } const cache = { engineChecksum: getEngineChecksum(), data: [eagerStyles.rules, lazyStyles.rules] }
onFinish(cache) onFinish(cache)
try { const compress = (js) => {
localStorage.setItem('pleroma-fe-theme-cache', JSON.stringify(cache)) return pako.deflate(JSON.stringify(js))
} catch (e) {
localStorage.removeItem('pleroma-fe-theme-cache')
try {
localStorage.setItem('pleroma-fe-theme-cache', JSON.stringify(cache))
} catch (e) {
console.warn('cannot save cache!', e)
}
} }
localforage.setItem('pleromafe-theme-cache', compress(cache))
} }
}, },
debug debug
@ -219,8 +218,9 @@ export const applyConfig = (input, i18n) => {
styleSheet.toString() styleSheet.toString()
styleSheet.insertRule(`:root { ${rules} }`, 'index-max') styleSheet.insertRule(`:root { ${rules} }`, 'index-max')
// TODO find a way to make this not apply to theme previews
if (Object.prototype.hasOwnProperty.call(config, 'forcedRoundness')) { if (Object.prototype.hasOwnProperty.call(config, 'forcedRoundness')) {
styleSheet.insertRule(` * { styleSheet.insertRule(` *:not(.preview-block) {
--roundness: var(--forcedRoundness) !important; --roundness: var(--forcedRoundness) !important;
}`, 'index-max') }`, 'index-max')
} }

View file

@ -7201,6 +7201,11 @@ p-try@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1"
pako@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86"
integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==
pako@~1.0.2: pako@~1.0.2:
version "1.0.11" version "1.0.11"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"