commit: 96e3a1593ab6b45b2b6794e353623d0e87a7d8ff
parent 34e4dd0a79cdc03976c4137969beb4259ecdf500
Author: Henry Jameson <me@hjkos.com>
Date: Thu, 15 Feb 2024 20:20:27 +0200
more optimizations, execution is now split into eager (for main UI) and
lazy (for modals, popovers etc) parts
Diffstat:
13 files changed, 156 insertions(+), 51 deletions(-)
diff --git a/src/components/alert.style.js b/src/components/alert.style.js
@@ -0,0 +1,42 @@
+export default {
+ name: 'Alert',
+ selector: '.alert',
+ validInnerComponents: [
+ 'Text',
+ 'Icon',
+ 'Link',
+ 'Border'
+ ],
+ variants: {
+ normal: '.neutral',
+ error: '.error',
+ warning: '.warning',
+ success: '.success'
+ },
+ defaultRules: [
+ {
+ directives: {
+ background: '--text',
+ opacity: 0.8
+ }
+ },
+ {
+ variant: 'error',
+ directives: {
+ background: '--cRed'
+ }
+ },
+ {
+ variant: 'warning',
+ directives: {
+ background: '--cOrange'
+ }
+ },
+ {
+ variant: 'success',
+ directives: {
+ background: '--cGreen'
+ }
+ }
+ ]
+}
diff --git a/src/components/badge.style.js b/src/components/badge.style.js
@@ -0,0 +1,25 @@
+export default {
+ name: 'Badge',
+ selector: '.badge',
+ validInnerComponents: [
+ 'Text',
+ 'Icon'
+ ],
+ variants: {
+ normal: '.neutral',
+ notification: '.notification'
+ },
+ defaultRules: [
+ {
+ directives: {
+ background: '--cGreen'
+ }
+ },
+ {
+ variant: 'notification',
+ directives: {
+ background: '--cRed'
+ }
+ }
+ ]
+}
diff --git a/src/components/button.style.js b/src/components/button.style.js
@@ -38,11 +38,11 @@ export default {
// All states inherit from "normal" state, there is no other inheirtance, i.e. hover+disabled only inherits from "normal", not from hover nor disabled.
// However, cascading still works, so resulting state will be result of merging of all relevant states/variants
// normal: '' // normal state is implicitly added, it is always included
- disabled: ':disabled',
toggled: '.toggled',
pressed: ':active',
hover: ':hover',
- focused: ':focus-within'
+ focused: ':focus-within',
+ disabled: ':disabled'
},
// Variants are mutually exclusive, each component implicitly has "normal" variant, and all other variants inherit from it.
variants: {
@@ -108,13 +108,6 @@ export default {
}
},
{
- state: ['disabled', 'hover'],
- directives: {
- background: '$blend(--background, 0.25, --parent)',
- shadow: [...buttonInsetFakeBorders]
- }
- },
- {
component: 'Text',
parent: {
component: 'Button',
@@ -124,17 +117,6 @@ export default {
textOpacity: 0.25,
textOpacityMode: 'blend'
}
- },
- {
- component: 'Text',
- parent: {
- component: 'Button',
- state: ['disabled', 'hover']
- },
- directives: {
- textOpacity: 0.25,
- textOpacityMode: 'blend'
- }
}
]
}
diff --git a/src/components/button_unstyled.style.js b/src/components/button_unstyled.style.js
@@ -10,7 +10,8 @@ export default {
},
validInnerComponents: [
'Text',
- 'Icon'
+ 'Icon',
+ 'Badge'
],
defaultRules: [
{
diff --git a/src/components/menu_item.style.js b/src/components/menu_item.style.js
@@ -5,7 +5,8 @@ export default {
'Text',
'Icon',
'Input',
- 'Border'
+ 'Border',
+ 'ButtonUnstyled'
],
states: {
hover: ':hover',
diff --git a/src/components/modals.style.js b/src/components/modals.style.js
@@ -1,6 +1,7 @@
export default {
name: 'Modals',
selector: '.modal-view',
+ lazy: true,
validInnerComponents: [
'Panel'
],
diff --git a/src/components/panel.style.js b/src/components/panel.style.js
@@ -11,7 +11,8 @@ export default {
'PanelHeader',
'MenuItem',
'Post',
- 'Notification'
+ 'Notification',
+ 'Alert'
],
defaultRules: [
{
diff --git a/src/components/panel_header.style.js b/src/components/panel_header.style.js
@@ -6,7 +6,9 @@ export default {
'Link',
'Icon',
'Button',
- 'ButtonUnstyled'
+ 'ButtonUnstyled',
+ 'Badge',
+ 'Alert'
],
defaultRules: [
{
diff --git a/src/components/popover.style.js b/src/components/popover.style.js
@@ -1,8 +1,8 @@
export default {
name: 'Popover',
selector: '.popover',
+ lazy: true,
variants: {
- tooltip: '.tooltip',
modal: '.modal'
},
validInnerComponents: [
diff --git a/src/components/top_bar.style.js b/src/components/top_bar.style.js
@@ -7,7 +7,8 @@ export default {
'Icon',
'Button',
'ButtonUnstyled',
- 'Input'
+ 'Input',
+ 'Badge'
],
defaultRules: [
{
diff --git a/src/components/underlay.style.js b/src/components/underlay.style.js
@@ -6,7 +6,8 @@ export default {
// we are searching for underlay specifically or for whatever is laid on top of it.
outOfTreeSelector: '.underlay',
validInnerComponents: [
- 'Panel'
+ 'Panel',
+ 'Alert'
],
defaultRules: [
{
diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js
@@ -28,11 +28,17 @@ export const applyTheme = (input) => {
// styleSheet.insertRule(`:root { ${rules.colors} }`, 'index-max')
// styleSheet.insertRule(`:root { ${rules.shadows} }`, 'index-max')
styleSheet.insertRule(`:root { ${rules.fonts} }`, 'index-max')
- themes3.css.forEach(rule => {
- console.log(rule)
+ themes3.css(themes3.eager).forEach(rule => {
styleSheet.insertRule(rule, 'index-max')
})
body.classList.remove('hidden')
+ themes3.lazy.then(lazyRules => {
+ themes3.css(lazyRules).forEach(rule => {
+ styleSheet.insertRule(rule, 'index-max')
+ })
+ const t3 = performance.now()
+ console.log('Themes 3 finalization took ' + (t3 - t2) + 'ms')
+ })
}
const configColumns = ({ sidebarColumnWidth, contentColumnWidth, notifsColumnWidth, emojiReactionsScale }) =>
diff --git a/src/services/theme_data/theme_data_3.service.js b/src/services/theme_data/theme_data_3.service.js
@@ -27,6 +27,8 @@ import Post from 'src/components/post.style.js'
import Notification from 'src/components/notification.style.js'
import RichContent from 'src/components/rich_content.style.js'
import Avatar from 'src/components/avatar.style.js'
+import Badge from 'src/components/badge.style.js'
+import Alert from 'src/components/alert.style.js'
const DEBUG = false
@@ -50,7 +52,9 @@ const components = {
Post,
Notification,
RichContent,
- Avatar
+ Avatar,
+ Alert,
+ Badge
}
// "Unrolls" a tree structure of item: { parent: { ...item2, parent: { ...item3, parent: {...} } }}
@@ -59,9 +63,8 @@ const unroll = (item) => {
const out = []
let currentParent = item
while (currentParent) {
- const { parent: newParent, ...rest } = currentParent
- out.push(rest)
- currentParent = newParent
+ out.push(currentParent)
+ currentParent = currentParent.parent
}
return out
}
@@ -173,7 +176,8 @@ export const init = (extraRuleset, palette) => {
const stacked = {}
const computed = {}
- const rules = []
+ const eagerRules = []
+ const lazyRules = []
const normalizeCombination = rule => {
rule.variant = rule.variant ?? 'normal'
@@ -211,10 +215,6 @@ export const init = (extraRuleset, palette) => {
const virtualComponents = new Set(Object.values(components).filter(c => c.virtual).map(c => c.name))
- const addRule = (rule) => {
- rules.push(rule)
- }
-
const findColor = (color, dynamicVars) => {
if (typeof color !== 'string' || (!color.startsWith('--') && !color.startsWith('$'))) return color
let targetColor = null
@@ -346,7 +346,14 @@ export const init = (extraRuleset, palette) => {
.join(' ')
}
- const processInnerComponent = (component, parent) => {
+ let counter = 0
+ const promises = []
+ const processInnerComponent = (component, rules, parent) => {
+ const addRule = (rule) => {
+ rules.push(rule)
+ }
+
+ const parentSelector = ruleToSelector(parent, true)
// const parentList = parent ? unroll(parent).reverse().map(c => c.component) : []
// if (!component.virtual) {
// const path = [...parentList, component.name].join(' > ')
@@ -367,18 +374,36 @@ export const init = (extraRuleset, palette) => {
// Optimization: we only really need combinations without "normal" because all states implicitly have it
const permutationStateKeys = Object.keys(states).filter(s => s !== 'normal')
- const stateCombinations = [['normal'], ...getAllPossibleCombinations(permutationStateKeys).map(combination => ['normal', ...combination])]
+ const stateCombinations = [
+ ['normal'],
+ ...getAllPossibleCombinations(permutationStateKeys)
+ .map(combination => ['normal', ...combination])
+ .filter(combo => {
+ // Optimization: filter out some hard-coded combinations that don't make sense
+ if (combo.indexOf('disabled') >= 0) {
+ return !(
+ combo.indexOf('hover') >= 0 ||
+ combo.indexOf('focused') >= 0 ||
+ combo.indexOf('pressed') >= 0
+ )
+ }
+ return true
+ })
+ ]
const stateVariantCombination = Object.keys(variants).map(variant => {
return stateCombinations.map(state => ({ variant, state }))
}).reduce((acc, x) => [...acc, ...x], [])
stateVariantCombination.forEach(combination => {
+ counter++
// const tt0 = performance.now()
- const soloSelector = ruleToSelector({ component: component.name, ...combination }, true)
- const selector = ruleToSelector({ component: component.name, ...combination, parent }, true)
- const lowerLevelSelector = selector.split(/ /g).slice(0, -1).join(' ')
+ combination.component = component.name
+ const soloSelector = ruleToSelector(combination, true)
+ const selector = [parentSelector, soloSelector].filter(x => x).join(' ')
+
+ const lowerLevelSelector = parentSelector
const lowerLevelBackground = computed[lowerLevelSelector]?.background
const lowerLevelVirtualDirectives = computed[lowerLevelSelector]?.virtualDirectives
const lowerLevelVirtualDirectivesRaw = computed[lowerLevelSelector]?.virtualDirectivesRaw
@@ -489,10 +514,7 @@ export const init = (extraRuleset, palette) => {
// TODO: DEFAULT TEXT COLOR
const lowerLevelComputedBackground = computed[lowerLevelSelector]?.background || convert('#FFFFFF').rgb
- if (
- computedDirectives.shadow != null ||
- computedDirectives.roundness != null
- ) {
+ if (computedDirectives.shadow != null || computedDirectives.roundness != null) {
addRuleNeeded = true
}
@@ -549,7 +571,22 @@ export const init = (extraRuleset, palette) => {
}
}
- innerComponents.forEach(innerComponent => processInnerComponent(innerComponent, { parent, component: name, ...combination }))
+ innerComponents.forEach(innerComponent => {
+ if (innerComponent.lazy) {
+ promises.push(new Promise((resolve, reject) => {
+ setTimeout(() => {
+ try {
+ processInnerComponent(innerComponent, lazyRules, { parent, component: name, ...combination })
+ resolve()
+ } catch (e) {
+ reject(e)
+ }
+ }, 0)
+ }))
+ } else {
+ processInnerComponent(innerComponent, rules, { parent, component: name, ...combination })
+ }
+ })
// const tt1 = performance.now()
// if (!component.virtual) {
// console.log('State-variant ' + combination.variant + ' : ' + combination.state.join('+') + ' procession time: ' + (tt1 - tt0) + 'ms')
@@ -563,11 +600,16 @@ export const init = (extraRuleset, palette) => {
// }
}
- processInnerComponent(components.Root)
+ processInnerComponent(components.Root, eagerRules)
+ console.log('TOTAL COMBOS: ' + counter)
+ const lazyExec = Promise.all(promises).then(() => {
+ console.log('TOTAL COMBOS: ' + counter)
+ }).then(() => lazyRules)
return {
- raw: rules,
- css: rules.map(rule => {
+ lazy: lazyExec,
+ eager: eagerRules,
+ css: rules => rules.map(rule => {
let selector = rule.selector
if (!selector) {
selector = 'body'