diff --git a/changelog.d/akkoftermapth.skip b/changelog.d/akkoftermapth.skip
new file mode 100644
index 000000000..e69de29bb
diff --git a/index.html b/index.html
index 96c20c4b7..fb92252c5 100644
--- a/index.html
+++ b/index.html
@@ -11,9 +11,7 @@
-
-
-
+
diff --git a/package.json b/package.json
index 5e71a3996..eea94a10e 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
"@fortawesome/free-regular-svg-icons": "6.7.2",
"@fortawesome/free-solid-svg-icons": "6.7.2",
"@fortawesome/vue-fontawesome": "3.0.8",
- "@floatingghost/pinch-zoom-element": "1.3.1",
+ "@kazvmoe-infra/pinch-zoom-element": "1.3.0",
"@kazvmoe-infra/unicode-emoji-json": "0.4.0",
"@ruffle-rs/ruffle": "0.1.0-nightly.2025.1.13",
"@vuelidate/core": "2.0.3",
diff --git a/public/static/empty.css b/public/static/empty.css
deleted file mode 100644
index 3dfa88151..000000000
--- a/public/static/empty.css
+++ /dev/null
@@ -1 +0,0 @@
-// nothing here //
diff --git a/src/App.scss b/src/App.scss
index 6e837a0e7..1b3133a7c 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -3,7 +3,7 @@
@use "panel";
@import '@fortawesome/fontawesome-svg-core/styles.css';
-@import '@floatingghost/pinch-zoom-element/dist/pinch-zoom.css';
+@import '@kazvmoe-infra/pinch-zoom-element/dist/pinch-zoom.css';
:root {
--status-margin: 0.75em;
diff --git a/src/components/component_preview/component_preview.js b/src/components/component_preview/component_preview.js
new file mode 100644
index 000000000..c0a2aad72
--- /dev/null
+++ b/src/components/component_preview/component_preview.js
@@ -0,0 +1,82 @@
+import Checkbox from 'src/components/checkbox/checkbox.vue'
+import ColorInput from 'src/components/color_input/color_input.vue'
+
+import genRandomSeed from 'src/services/random_seed/random_seed.service.js'
+import { createStyleSheet, adoptStyleSheets } from 'src/services/style_setter/style_setter.js'
+
+export default {
+ components: {
+ Checkbox,
+ ColorInput
+ },
+ props: [
+ 'shadow',
+ 'shadowControl',
+ 'previewClass',
+ 'previewStyle',
+ 'previewCss',
+ 'disabled',
+ 'invalid',
+ 'noColorControl'
+ ],
+ emits: ['update:shadow'],
+ data () {
+ return {
+ colorOverride: undefined,
+ lightGrid: false,
+ zoom: 100,
+ randomSeed: genRandomSeed()
+ }
+ },
+ mounted () {
+ this.update()
+ },
+ computed: {
+ hideControls () {
+ return typeof this.shadow === 'string'
+ }
+ },
+ watch: {
+ previewCss () {
+ this.update()
+ },
+ previewStyle () {
+ this.update()
+ },
+ zoom () {
+ this.update()
+ }
+ },
+ methods: {
+ updateProperty (axis, value) {
+ this.$emit('update:shadow', { axis, value: Number(value) })
+ },
+ update () {
+ const sheet = createStyleSheet('style-component-preview')
+
+ sheet.clear()
+
+ const result = [this.previewCss]
+ if (this.colorOverride) result.push(`--background: ${this.colorOverride}`)
+
+ const styleRule = [
+ '#component-preview-', this.randomSeed, ' {\n',
+ '.preview-block {\n',
+ `zoom: ${this.zoom / 100};`,
+ this.previewStyle,
+ '\n}',
+ '\n}'
+ ].join('')
+
+ sheet.addRule(styleRule)
+ sheet.addRule([
+ '#component-preview-', this.randomSeed, ' {\n',
+ ...result,
+ '\n}'
+ ].join(''))
+
+ sheet.ready = true
+ adoptStyleSheets()
+ }
+ }
+}
diff --git a/src/components/component_preview/component_preview.scss b/src/components/component_preview/component_preview.scss
new file mode 100644
index 000000000..bb83b7908
--- /dev/null
+++ b/src/components/component_preview/component_preview.scss
@@ -0,0 +1,151 @@
+.ComponentPreview {
+ display: grid;
+ grid-template-columns: 1em 1fr 1fr 1em;
+ grid-template-rows: 2em 1fr 1fr 1fr 1em 2em max-content;
+ grid-template-areas:
+ "header header header header "
+ "preview preview preview y-slide"
+ "preview preview preview y-slide"
+ "preview preview preview y-slide"
+ "x-slide x-slide x-slide . "
+ "x-num x-num y-num y-num "
+ "assists assists assists assists";
+ grid-gap: 0.5em;
+
+ &:not(.-shadow-controls) {
+ grid-template-areas:
+ "header header header header "
+ "preview preview preview y-slide"
+ "preview preview preview y-slide"
+ "preview preview preview y-slide"
+ "assists assists assists assists";
+ grid-template-rows: 2em 1fr 1fr 1fr max-content;
+ }
+
+ .header {
+ grid-area: header;
+ place-self: baseline center;
+ line-height: 2;
+ }
+
+ .invalid-container {
+ position: absolute;
+ inset: 0;
+ display: grid;
+ place-items: center center;
+ background-color: rgb(100 0 0 / 50%);
+
+ .alert {
+ padding: 0.5em 1em;
+ }
+ }
+
+ .assists {
+ grid-area: assists;
+ display: grid;
+ grid-auto-flow: row;
+ grid-auto-rows: 2em;
+ grid-gap: 0.5em;
+ }
+
+ .input-light-grid {
+ justify-self: center;
+ }
+
+ .input-number {
+ min-width: 2em;
+ }
+
+ .x-shift-number {
+ grid-area: x-num;
+ justify-self: right;
+ }
+
+ .y-shift-number {
+ grid-area: y-num;
+ justify-self: left;
+ }
+
+ .x-shift-number,
+ .y-shift-number {
+ input {
+ max-width: 4em;
+ }
+ }
+
+ .x-shift-slider {
+ grid-area: x-slide;
+ height: auto;
+ align-self: start;
+ min-width: 10em;
+ }
+
+ .y-shift-slider {
+ grid-area: y-slide;
+ writing-mode: vertical-lr;
+ justify-self: left;
+ min-height: 10em;
+ }
+
+ .x-shift-slider,
+ .y-shift-slider {
+ padding: 0;
+ }
+
+ .preview-window {
+ --__grid-color1: rgb(102 102 102);
+ --__grid-color2: rgb(153 153 153);
+ --__grid-color1-disabled: rgb(102 102 102 / 20%);
+ --__grid-color2-disabled: rgb(153 153 153 / 20%);
+
+ &.-light-grid {
+ --__grid-color1: rgb(205 205 205);
+ --__grid-color2: rgb(255 255 255);
+ --__grid-color1-disabled: rgb(205 205 205 / 20%);
+ --__grid-color2-disabled: rgb(255 255 255 / 20%);
+ }
+
+ position: relative;
+ grid-area: preview;
+ aspect-ratio: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 10em;
+ min-height: 10em;
+ background-color: var(--__grid-color2);
+ background-image:
+ linear-gradient(45deg, var(--__grid-color1) 25%, transparent 25%),
+ linear-gradient(-45deg, var(--__grid-color1) 25%, transparent 25%),
+ linear-gradient(45deg, transparent 75%, var(--__grid-color1) 75%),
+ linear-gradient(-45deg, transparent 75%, var(--__grid-color1) 75%);
+ background-size: 20px 20px;
+ background-position: 0 0, 0 10px, 10px -10px, -10px 0;
+ border-radius: var(--roundness);
+
+ &.disabled {
+ background-color: var(--__grid-color2-disabled);
+ background-image:
+ linear-gradient(45deg, var(--__grid-color1-disabled) 25%, transparent 25%),
+ linear-gradient(-45deg, var(--__grid-color1-disabled) 25%, transparent 25%),
+ linear-gradient(45deg, transparent 75%, var(--__grid-color1-disabled) 75%),
+ linear-gradient(-45deg, transparent 75%, var(--__grid-color1-disabled) 75%);
+ }
+
+ .preview-block {
+ background: var(--background, var(--bg));
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ min-width: 33%;
+ min-height: 33%;
+ max-width: 80%;
+ max-height: 80%;
+ border-width: 0;
+ border-style: solid;
+ border-color: var(--border);
+ border-radius: var(--roundness);
+ box-shadow: var(--shadow);
+ }
+ }
+}
diff --git a/src/components/component_preview/component_preview.vue b/src/components/component_preview/component_preview.vue
index be9d25ac5..0d81128c7 100644
--- a/src/components/component_preview/component_preview.vue
+++ b/src/components/component_preview/component_preview.vue
@@ -1,14 +1,9 @@
-
-
-
@@ -116,203 +110,5 @@
-
-
+
+
diff --git a/src/components/pinch_zoom/pinch_zoom.js b/src/components/pinch_zoom/pinch_zoom.js
index b7e8f673e..82670ddfa 100644
--- a/src/components/pinch_zoom/pinch_zoom.js
+++ b/src/components/pinch_zoom/pinch_zoom.js
@@ -1,4 +1,4 @@
-import PinchZoom from '@floatingghost/pinch-zoom-element'
+import PinchZoom from '@kazvmoe-infra/pinch-zoom-element'
export default {
methods: {
diff --git a/src/components/settings_modal/tabs/appearance_tab.js b/src/components/settings_modal/tabs/appearance_tab.js
index 996f3a20c..e0f446a0e 100644
--- a/src/components/settings_modal/tabs/appearance_tab.js
+++ b/src/components/settings_modal/tabs/appearance_tab.js
@@ -15,6 +15,7 @@ import {
getCssRules
} from 'src/services/theme_data/css_utils.js'
import { deserialize } from 'src/services/theme_data/iss_deserializer.js'
+import { createStyleSheet, adoptStyleSheets } from 'src/services/style_setter/style_setter.js'
import SharedComputedObject from '../helpers/shared_computed_object.js'
import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue'
@@ -410,16 +411,17 @@ const AppearanceTab = {
this.compilationCache[key] = theme3
}
- const styleEl = document.getElementById('theme-holder')
- const styleSheet = styleEl.sheet
- styleSheet.insertRule([
+
+ const sheet = createStyleSheet('appearance-tab-previews')
+ sheet.addRule([
'#theme-preview-',
key,
' {\n',
getCssRules(theme3.eager).join('\n'),
'\n}'
- ].join(''), 'index-max')
-
+ ].join(''))
+ sheet.ready = true
+ adoptStyleSheets()
}
}
}
diff --git a/src/components/settings_modal/tabs/style_tab/style_tab.js b/src/components/settings_modal/tabs/style_tab/style_tab.js
index 82c63f503..f92579bb2 100644
--- a/src/components/settings_modal/tabs/style_tab/style_tab.js
+++ b/src/components/settings_modal/tabs/style_tab/style_tab.js
@@ -1,4 +1,4 @@
-import { ref, reactive, computed, watch, watchEffect, provide, getCurrentInstance } from 'vue'
+import { ref, reactive, computed, watch, provide, getCurrentInstance } from 'vue'
import { useInterfaceStore } from 'src/stores/interface'
import { get, set, unset, throttle } from 'lodash'
@@ -19,11 +19,9 @@ import Preview from '../theme_tab/theme_preview.vue'
import VirtualDirectivesTab from './virtual_directives_tab.vue'
+import { createStyleSheet, adoptStyleSheets } from 'src/services/style_setter/style_setter.js'
import { init, findColor } from 'src/services/theme_data/theme_data_3.service.js'
-import {
- getCssRules,
- getScopedVersion
-} from 'src/services/theme_data/css_utils.js'
+import { getCssRules } from 'src/services/theme_data/css_utils.js'
import { serialize } from 'src/services/theme_data/iss_serializer.js'
import { deserializeShadow, deserialize } from 'src/services/theme_data/iss_deserializer.js'
import {
@@ -670,7 +668,7 @@ export default {
})
exports.clearStyle = () => {
- onImport(interfaceStore().styleDataUsed)
+ onImport(interfaceStore.styleDataUsed)
}
exports.exportStyle = () => {
@@ -688,19 +686,26 @@ export default {
const overallPreviewRules = ref([])
exports.overallPreviewRules = overallPreviewRules
- const overallPreviewCssRules = ref([])
- watchEffect(throttle(() => {
+ watch([overallPreviewRules], () => {
+ let css = null
try {
- overallPreviewCssRules.value = getScopedVersion(
- getCssRules(overallPreviewRules.value),
- '#edited-style-preview'
- ).join('\n')
+ css = getCssRules(overallPreviewRules.value).map(r => r.replace('html', '&'))
} catch (e) {
console.error(e)
+ return
}
- }, 500))
- exports.overallPreviewCssRules = overallPreviewCssRules
+ const sheet = createStyleSheet('style-tab-overall-preview')
+
+ sheet.clear()
+ sheet.addRule([
+ '#edited-style-preview {\n',
+ css.join('\n'),
+ '\n}'
+ ].join(''))
+ sheet.ready = true
+ adoptStyleSheets()
+ })
const updateOverallPreview = throttle(() => {
try {
@@ -724,12 +729,12 @@ export default {
console.error('Could not compile preview theme', e)
return null
}
- }, 5000)
+ }, 1000)
//
// Apart from "hover" we can't really show how component looks like in
// certain states, so we have to fake them.
const simulatePseudoSelectors = (css, prefix) => css
- .replace(prefix, '.component-preview .preview-block')
+ .replace(prefix, '.preview-block')
.replace(':active', '.preview-active')
.replace(':hover', '.preview-hover')
.replace(':active', '.preview-active')
diff --git a/src/components/settings_modal/tabs/style_tab/style_tab.vue b/src/components/settings_modal/tabs/style_tab/style_tab.vue
index 5084b757c..a386822ee 100644
--- a/src/components/settings_modal/tabs/style_tab/style_tab.vue
+++ b/src/components/settings_modal/tabs/style_tab/style_tab.vue
@@ -6,14 +6,6 @@
{{ $t('settings.style.themes3.editor.title') }}
-
-
-
{
export default {
data () {
return {
- themeV3Preview: [],
themeImporter: newImporter({
validator: this.importValidator,
onImport: this.onImport,
@@ -697,10 +697,16 @@ export default {
liteMode: true
})
- this.themeV3Preview = getScopedVersion(
+ const sheet = createStyleSheet('theme-tab-overall-preview')
+ const rule = getScopedVersion(
getCssRules(theme3.eager),
- '#theme-preview'
+ '&'
).join('\n')
+
+ sheet.clear()
+ sheet.addRule('#theme-preview {\n' + rule + '\n}')
+ sheet.ready = true
+ adoptStyleSheets()
}
},
watch: {
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
index 886d97764..ec3f0cb5d 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
@@ -123,12 +123,6 @@
-
-
-
diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js
index 3d85db3aa..6312d5b89 100644
--- a/src/services/style_setter/style_setter.js
+++ b/src/services/style_setter/style_setter.js
@@ -1,47 +1,68 @@
import { init, getEngineChecksum } from '../theme_data/theme_data_3.service.js'
import { getCssRules } from '../theme_data/css_utils.js'
import { defaultState } from 'src/modules/default_config_state.js'
-import { chunk } from 'lodash'
+import { chunk, throttle } from 'lodash'
import localforage from 'localforage'
// On platforms where this is not supported, it will return undefined
// Otherwise it will return an array
const supportsAdoptedStyleSheets = !!document.adoptedStyleSheets
-const createStyleSheet = (id) => {
- if (supportsAdoptedStyleSheets) {
- return {
- el: null,
- sheet: new CSSStyleSheet(),
- rules: []
+const stylesheets = {}
+
+export const createStyleSheet = (id) => {
+ if (stylesheets[id]) return stylesheets[id]
+ const newStyleSheet = {
+ rules: [],
+ ready: false,
+ clear () {
+ this.rules = []
+ },
+ addRule (rule) {
+ let newRule = rule
+ if (!CSS.supports?.('backdrop-filter', 'blur()')) {
+ newRule = newRule.replace(/backdrop-filter:[^;]+;/g, '') // Remove backdrop-filter
+ }
+ this.rules.push(
+ newRule
+ .replace(/var\(--shadowFilter\)[^;]*;/g, '') // Remove shadowFilter references
+ )
}
}
- const el = document.getElementById(id)
- // Clear all rules in it
- for (let i = el.sheet.cssRules.length - 1; i >= 0; --i) {
- el.sheet.deleteRule(i)
- }
-
- return {
- el,
- sheet: el.sheet,
- rules: []
- }
+ stylesheets[id] = newStyleSheet
+ return newStyleSheet
}
-const EAGER_STYLE_ID = 'pleroma-eager-styles'
-const LAZY_STYLE_ID = 'pleroma-lazy-styles'
-const adoptStyleSheets = (styles) => {
+export const adoptStyleSheets = throttle(() => {
if (supportsAdoptedStyleSheets) {
- document.adoptedStyleSheets = styles.map(s => s.sheet)
+ document.adoptedStyleSheets = Object
+ .values(stylesheets)
+ .filter(x => x.ready)
+ .map(x => {
+ const css = new CSSStyleSheet()
+ x.rules.forEach(r => css.insertRule(r, css.cssRules.length))
+ return css
+ })
+ } else {
+ const holder = document.getElementById('custom-styles-holder')
+
+ Object
+ .values(stylesheets)
+ .forEach(sheet => {
+ sheet.rules.forEach(r => holder.sheet.insertRule(r))
+ })
}
// Some older browsers do not support document.adoptedStyleSheets.
// In this case, we use the