Merge branch 'themes3-fixes' into 'develop'

Themes 3 fixes

Closes #1301 and #1303

See merge request pleroma/pleroma-fe!1906
This commit is contained in:
HJ 2024-04-06 14:53:53 +00:00
commit 0635a6c131
17 changed files with 142 additions and 48 deletions

View File

@ -0,0 +1 @@
fix color inputs and some in-development themes3 issues

View File

@ -14,6 +14,9 @@
--ZI_navbar_popovers: 7500; --ZI_navbar_popovers: 7500;
--ZI_navbar: 7000; --ZI_navbar: 7000;
--ZI_popovers: 6000; --ZI_popovers: 6000;
// Fallback for when stuff is loading
--background: var(--bg);
} }
html { html {
@ -370,6 +373,7 @@ nav {
border: none; border: none;
border-radius: var(--roundness); border-radius: var(--roundness);
cursor: pointer; cursor: pointer;
background-color: var(--background);
box-shadow: var(--shadow); box-shadow: var(--shadow);
font-size: 1em; font-size: 1em;
font-family: sans-serif; font-family: sans-serif;
@ -406,6 +410,7 @@ nav {
width: 100%; width: 100%;
line-height: var(--__line-height); line-height: var(--__line-height);
padding: var(--__vertical-gap) var(--__horizontal-gap); padding: var(--__vertical-gap) var(--__horizontal-gap);
background: transparent;
--__line-height: 1.5em; --__line-height: 1.5em;
--__horizontal-gap: 0.75em; --__horizontal-gap: 0.75em;
@ -470,6 +475,7 @@ nav {
font-size: 100%; font-size: 100%;
font-family: inherit; font-family: inherit;
box-shadow: var(--shadow); box-shadow: var(--shadow);
background-color: transparent;
padding: 0; padding: 0;
line-height: unset; line-height: unset;
cursor: pointer; cursor: pointer;
@ -502,6 +508,8 @@ textarea {
border: none; border: none;
border-radius: var(--roundness); border-radius: var(--roundness);
background-color: var(--background);
color: var(--text);
box-shadow: var(--shadow); box-shadow: var(--shadow);
font-family: var(--font); font-family: var(--font);
font-size: 1em; font-size: 1em;

View File

@ -1,5 +1,6 @@
<template> <template>
<div <div
v-show="$store.state.interface.themeApplied"
id="app-loaded" id="app-loaded"
:style="bgStyle" :style="bgStyle"
> >

View File

@ -363,6 +363,7 @@ const afterStoreSetup = async ({ store, i18n }) => {
} else { } else {
applyTheme(customTheme) applyTheme(customTheme)
} }
store.commit('setThemeApplied')
} else if (theme) { } else if (theme) {
// do nothing, it will load asynchronously // do nothing, it will load asynchronously
} else { } else {

View File

@ -9,6 +9,7 @@
padding: 0.2em 8px; padding: 0.2em 8px;
input { input {
color: var(--text);
background: none; background: none;
border: none; border: none;
padding: 0; padding: 0;
@ -19,21 +20,38 @@
min-width: 3em; min-width: 3em;
padding: 0; padding: 0;
} }
}
&.nativeColor { .nativeColor {
flex: 0 0 2em; cursor: pointer;
min-width: 2em; flex: 0 0 auto;
align-self: stretch;
min-height: 100%; input {
appearance: none;
max-width: 0;
min-width: 0;
max-height: 0;
/* stylelint-disable-next-line declaration-no-important */
opacity: 0 !important;
} }
} }
.computedIndicator, .computedIndicator,
.validIndicator,
.invalidIndicator,
.transparentIndicator { .transparentIndicator {
flex: 0 0 2em; flex: 0 0 2em;
margin: 0 0.5em;
min-width: 2em; min-width: 2em;
align-self: stretch; align-self: stretch;
min-height: 100%; min-height: 1.5em;
border-radius: var(--roundness);
}
.invalidIndicator {
background: transparent;
box-sizing: border-box;
border: 2px solid var(--cRed);
} }
.transparentIndicator { .transparentIndicator {
@ -54,11 +72,13 @@
&::after { &::after {
top: 0; top: 0;
left: 0; left: 0;
border-top-left-radius: var(--roundness);
} }
&::before { &::before {
bottom: 0; bottom: 0;
right: 0; right: 0;
border-bottom-right-radius: var(--roundness);
} }
} }
} }

View File

@ -25,30 +25,51 @@
:disabled="!present || disabled" :disabled="!present || disabled"
@input="$emit('update:modelValue', $event.target.value)" @input="$emit('update:modelValue', $event.target.value)"
> >
<input <div
v-if="validColor" v-if="validColor"
class="validIndicator"
:style="{backgroundColor: modelValue || fallback}"
/>
<div
v-else-if="transparentColor"
class="transparentIndicator"
/>
<div
v-else-if="computedColor"
class="computedIndicator"
:style="{backgroundColor: fallback}"
/>
<div
v-else
class="invalidIndicator"
/>
<label class="nativeColor">
<FAIcon icon="eye-dropper" />
<input
:id="name" :id="name"
class="nativeColor unstyled" class="unstyled"
type="color" type="color"
:value="modelValue || fallback" :value="modelValue || fallback"
:disabled="!present || disabled" :disabled="!present || disabled"
@input="$emit('update:modelValue', $event.target.value)" @input="$emit('update:modelValue', $event.target.value)"
> >
<div </label>
v-if="transparentColor"
class="transparentIndicator"
/>
<div
v-if="computedColor"
class="computedIndicator"
:style="{backgroundColor: fallback}"
/>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import Checkbox from '../checkbox/checkbox.vue' import Checkbox from '../checkbox/checkbox.vue'
import { hex2rgb } from '../../services/color_convert/color_convert.js' import { hex2rgb } from '../../services/color_convert/color_convert.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faEyeDropper
} from '@fortawesome/free-solid-svg-icons'
library.add(
faEyeDropper
)
export default { export default {
components: { components: {
Checkbox Checkbox
@ -108,12 +129,3 @@ export default {
} }
</script> </script>
<style lang="scss" src="./color_input.scss"></style> <style lang="scss" src="./color_input.scss"></style>
<style lang="scss">
.color-control {
input.text-input {
max-width: 7em;
flex: 1;
}
}
</style>

View File

@ -81,7 +81,7 @@
:replies="getReplies(status.id)" :replies="getReplies(status.id)"
:in-profile="inProfile" :in-profile="inProfile"
:profile-user-id="profileUserId" :profile-user-id="profileUserId"
class="conversation-status status-fadein" class="conversation-status status-fadein panel-body"
:simple-tree="treeViewIsSimple" :simple-tree="treeViewIsSimple"
:toggle-thread-display="toggleThreadDisplay" :toggle-thread-display="toggleThreadDisplay"
@ -186,7 +186,7 @@
:replies="getReplies(status.id)" :replies="getReplies(status.id)"
:in-profile="inProfile" :in-profile="inProfile"
:profile-user-id="profileUserId" :profile-user-id="profileUserId"
class="conversation-status status-fadein" class="conversation-status status-fadein panel-body"
:toggle-thread-display="toggleThreadDisplay" :toggle-thread-display="toggleThreadDisplay"
:thread-display-status="threadDisplayStatus" :thread-display-status="threadDisplayStatus"

View File

@ -71,6 +71,7 @@
border-color: var(--border); border-color: var(--border);
border-style: solid; border-style: solid;
border-width: 1px; border-width: 1px;
background-color: var(--background);
} }
.dropdown-menu { .dropdown-menu {
@ -82,6 +83,7 @@
max-width: 100vw; max-width: 100vw;
z-index: var(--ZI_popover_override, var(--ZI_popovers)); z-index: var(--ZI_popover_override, var(--ZI_popovers));
white-space: nowrap; white-space: nowrap;
background-color: var(--background);
.dropdown-divider { .dropdown-divider {
height: 0; height: 0;

View File

@ -83,3 +83,8 @@
color: var(--funtextCyantext); color: var(--funtextCyantext);
} }
} }
a .RichContent {
/* stylelint-disable-next-line declaration-no-important */
color: var(--link) !important;
}

View File

@ -5,7 +5,7 @@
> >
<div class="panel panel-default"> <div class="panel panel-default">
<div <div
class="panel-heading timeline-heading" class="panel-heading"
:class="{ 'shout-heading': floating }" :class="{ 'shout-heading': floating }"
@click.stop.prevent="togglePanel" @click.stop.prevent="togglePanel"
> >
@ -18,7 +18,7 @@
/> />
</div> </div>
</div> </div>
<div class="shout-window"> <div class="panel-body shout-window">
<div <div
v-for="message in messages" v-for="message in messages"
:key="message.id" :key="message.id"
@ -41,10 +41,10 @@
</div> </div>
</div> </div>
</div> </div>
<div class="shout-input"> <div class="panel-body shout-input">
<textarea <textarea
v-model="currentMessage" v-model="currentMessage"
class="shout-input-textarea" class="shout-input-textarea input"
rows="1" rows="1"
@keyup.enter="submit(currentMessage)" @keyup.enter="submit(currentMessage)"
/> />

View File

@ -174,6 +174,7 @@
font-size: 1em; font-size: 1em;
font-family: var(--font); font-family: var(--font);
border-radius: var(--roundness); border-radius: var(--roundness);
background-color: var(--background);
position: relative; position: relative;
white-space: nowrap; white-space: nowrap;
padding: 6px 1em; padding: 6px 1em;

View File

@ -204,6 +204,11 @@
--emoji-size: 1.7em; --emoji-size: 1.7em;
.RichContent {
/* stylelint-disable-next-line declaration-no-important */
--link: var(--text) !important;
}
.top-line, .top-line,
.bottom-line { .bottom-line {
display: flex; display: flex;

View File

@ -386,6 +386,7 @@ const instance = {
} else { } else {
applyTheme(themeData.theme) applyTheme(themeData.theme)
} }
commit('setThemeApplied')
}) })
}, },
fetchEmoji ({ dispatch, state }) { fetchEmoji ({ dispatch, state }) {

View File

@ -1,4 +1,5 @@
const defaultState = { const defaultState = {
themeApplied: false,
settingsModalState: 'hidden', settingsModalState: 'hidden',
settingsModalLoadedUser: false, settingsModalLoadedUser: false,
settingsModalLoadedAdmin: false, settingsModalLoadedAdmin: false,
@ -35,6 +36,9 @@ const interfaceMod = {
state.settings.currentSaveStateNotice = { error: true, errorData: error } state.settings.currentSaveStateNotice = { error: true, errorData: error }
} }
}, },
setThemeApplied (state) {
state.themeApplied = true
},
setNotificationPermission (state, permission) { setNotificationPermission (state, permission) {
state.notificationPermission = permission state.notificationPermission = permission
}, },

View File

@ -6,7 +6,13 @@ 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'
export const applyTheme = async (input) => { export const generateTheme = async (input, callbacks) => {
const {
onNewRule = (rule, isLazy) => {},
onLazyFinished = () => {},
onEagerFinished = () => {}
} = callbacks
let extraRules let extraRules
if (input.themeFileVersion === 1) { if (input.themeFileVersion === 1) {
extraRules = convertTheme2To3(input) extraRules = convertTheme2To3(input)
@ -17,11 +23,6 @@ export const applyTheme = async (input) => {
// Assuming that "worst case scenario background" is panel background since it's the most likely one // Assuming that "worst case scenario background" is panel background since it's the most likely one
const themes3 = init(extraRules, extraRules[0].directives['--bg'].split('|')[1].trim()) const themes3 = init(extraRules, extraRules[0].directives['--bg'].split('|')[1].trim())
const body = document.body
const styleSheet = new CSSStyleSheet()
document.adoptedStyleSheets = [styleSheet]
body.classList.add('hidden')
getCssRules(themes3.eager, themes3.staticVars).forEach(rule => { getCssRules(themes3.eager, themes3.staticVars).forEach(rule => {
// Hacks to support multiple selectors on same component // Hacks to support multiple selectors on same component
@ -37,13 +38,12 @@ export const applyTheme = async (input) => {
parts[1], parts[1],
'}' '}'
].join('') ].join('')
styleSheet.insertRule(newRule, 'index-max') onNewRule(newRule, false)
} else { } else {
styleSheet.insertRule(rule, 'index-max') onNewRule(rule, false)
} }
}) })
onEagerFinished()
body.classList.remove('hidden')
// Optimization - instead of processing all lazy rules in one go, process them in small chunks // Optimization - instead of processing all lazy rules in one go, process them in small chunks
// so that UI can do other things and be somewhat responsive while less important rules are being // so that UI can do other things and be somewhat responsive while less important rules are being
@ -61,13 +61,15 @@ export const applyTheme = async (input) => {
parts[0], parts[0],
', ', ', ',
parts[0].replace(/\.modal-view/, '#modal'), parts[0].replace(/\.modal-view/, '#modal'),
', ',
parts[0].replace(/\.modal-view/, '.shout-panel'),
' {', ' {',
parts[1], parts[1],
'}' '}'
].join('') ].join('')
styleSheet.insertRule(newRule, 'index-max') onNewRule(newRule, true)
} else { } else {
styleSheet.insertRule(rule, 'index-max') onNewRule(rule, true)
} }
}) })
// const t1 = performance.now() // const t1 = performance.now()
@ -76,10 +78,39 @@ export const applyTheme = async (input) => {
counter += 1 counter += 1
if (counter < chunks.length) { if (counter < chunks.length) {
setTimeout(processChunk, 0) setTimeout(processChunk, 0)
} else {
onLazyFinished()
} }
}) })
} }
setTimeout(processChunk, 0)
return { lazyProcessFunc: processChunk }
}
export const applyTheme = async (input) => {
const styleSheet = new CSSStyleSheet()
const lazyStyleSheet = new CSSStyleSheet()
const { lazyProcessFunc } = await generateTheme(
input,
{
onNewRule (rule, isLazy) {
if (isLazy) {
lazyStyleSheet.insertRule(rule, 'index-max')
} else {
styleSheet.insertRule(rule, 'index-max')
}
},
onEagerFinished () {
document.adoptedStyleSheets = [styleSheet]
},
onLazyFinished () {
document.adoptedStyleSheets = [styleSheet, lazyStyleSheet]
}
}
)
setTimeout(lazyProcessFunc, 0)
return Promise.resolve() return Promise.resolve()
} }

View File

@ -158,12 +158,12 @@ export default [
'alertPopupNeutral', 'alertPopupNeutral',
'alertPopupNeutralText', 'alertPopupNeutralText',
'badgeNotification',
'badgeNotificationText',
'badgeNeutral', 'badgeNeutral',
'badgeNeutralText', 'badgeNeutralText',
'badgeNotification',
'badgeNotificationText',
'chatBg', 'chatBg',
'chatMessageIncomingBg', 'chatMessageIncomingBg',

View File

@ -517,6 +517,8 @@ export const convertTheme2To3 = (data) => {
} else if (newRule.component === 'Badge') { } else if (newRule.component === 'Badge') {
if (newRule.variant === 'notification') { if (newRule.variant === 'notification') {
return [newRule, { component: 'Root', directives: { '--badgeNotification': 'color | ' + newRule.directives.background } }] return [newRule, { component: 'Root', directives: { '--badgeNotification': 'color | ' + newRule.directives.background } }]
} else if (newRule.variant === 'neutral') {
return [{ ...newRule, variant: 'normal' }]
} else { } else {
return [newRule] return [newRule]
} }