Simply and improve core client library logic

This commit is contained in:
Andrew Kingston 2022-02-01 16:32:37 +00:00
parent 5aa52f4b9d
commit ae9a5b19c0
1 changed files with 40 additions and 43 deletions

View File

@ -9,7 +9,7 @@
<script> <script>
import { getContext, setContext } from "svelte" import { getContext, setContext } from "svelte"
import { writable } from "svelte/store" import { writable, get } from "svelte/store"
import * as AppComponents from "components/app" import * as AppComponents from "components/app"
import Router from "./Router.svelte" import Router from "./Router.svelte"
import { enrichProps, propsAreSame } from "utils/componentProps" import { enrichProps, propsAreSame } from "utils/componentProps"
@ -24,6 +24,14 @@
export let isScreen = false export let isScreen = false
export let isBlock = false export let isBlock = false
// Get parent contexts
const context = getContext("context")
const insideScreenslot = !!getContext("screenslot")
// Create component context
const componentStore = writable({})
setContext("component", componentStore)
// Ref to the svelte component // Ref to the svelte component
let ref let ref
@ -34,13 +42,11 @@
// would happen if we spread cachedSettings directly to the component. // would happen if we spread cachedSettings directly to the component.
let initialSettings let initialSettings
// Component settings are the un-enriched settings for this component that // Dynamic settings contain bindings and need enriched
// need to be enriched at this level.
// Nested settings are the un-enriched block settings that are to be passed on
// and enriched at a deeper level.
let dynamicSettings let dynamicSettings
// Static settings do not contain any bindings and can be passed on down
let staticSettings let staticSettings
let nestedSettings
// The enriched component settings // The enriched component settings
let enrichedSettings let enrichedSettings
@ -65,17 +71,11 @@
// Visibility flag used by conditional UI // Visibility flag used by conditional UI
let visible = true let visible = true
// Get contexts // Component information derived during initialisation
const context = getContext("context")
const insideScreenslot = !!getContext("screenslot")
// Create component context
const componentStore = writable({})
setContext("component", componentStore)
//
let constructor let constructor
let definition let definition
// Set up initial state for each new component instance
$: initialise(instance) $: initialise(instance)
// Extract component instance info // Extract component instance info
@ -113,19 +113,16 @@
$: emptyState = empty && showEmptyState $: emptyState = empty && showEmptyState
// Enrich component settings // Enrich component settings
$: enrichComponentSettings(dynamicSettings, $context) $: enrichComponentSettings($context)
// Evaluate conditional UI settings and store any component setting changes // Evaluate conditional UI settings and store any component setting changes
// which need to be made // which need to be made. This is broken into 2 lines to avoid svelte
$: evaluateConditions(enrichedSettings?._conditions) // reactivity re-evaluating conditions more often than necessary.
$: conditions = enrichedSettings?._conditions
$: evaluateConditions(conditions)
// Build up the final settings object to be passed to the component // Determine and apply settings to the component
$: cacheSettings( $: applySettings(staticSettings, enrichedSettings, conditionalSettings)
staticSettings,
enrichedSettings,
nestedSettings,
conditionalSettings
)
// Update component context // Update component context
$: componentStore.set({ $: componentStore.set({
@ -183,10 +180,12 @@
InstanceSettingsCache[instanceKey] = instanceSettings InstanceSettingsCache[instanceKey] = instanceSettings
} }
// Update the settings type in the component // Update the settings types
staticSettings = instanceSettings.staticSettings staticSettings = instanceSettings.staticSettings
dynamicSettings = instanceSettings.dynamicSettings dynamicSettings = instanceSettings.dynamicSettings
nestedSettings = instanceSettings.nestedSettings
// Force an initial enrichment of the new settings
enrichComponentSettings(get(context), { force: true })
} }
// Gets the component constructor for the specified component // Gets the component constructor for the specified component
@ -234,25 +233,21 @@
// Derive static, dynamic and nested settings if the instance changed // Derive static, dynamic and nested settings if the instance changed
let newStaticSettings = { ...settings } let newStaticSettings = { ...settings }
let newDynamicSettings = { ...settings } let newDynamicSettings = { ...settings }
let newNestedSettings = { ...settings }
settingsDefinition?.forEach(setting => { settingsDefinition?.forEach(setting => {
if (setting.nested) { if (setting.nested) {
delete newStaticSettings[setting.key]
delete newDynamicSettings[setting.key] delete newDynamicSettings[setting.key]
} else { } else {
delete newNestedSettings[setting.key]
// This is a non-nested setting, but we need to find out if it is
// static or dynamic
const value = settings[setting.key] const value = settings[setting.key]
if (value == null) { if (value == null) {
delete newDynamicSettings[setting.key] delete newDynamicSettings[setting.key]
} else if (typeof value === "string" && value.includes("{{")) { } else if (typeof value === "string" && value.includes("{{")) {
// Strings can be trivially checked
delete newStaticSettings[setting.key] delete newStaticSettings[setting.key]
} else if (value[0]?.["##eventHandlerType"] != null) { } else if (value[0]?.["##eventHandlerType"] != null) {
// Always treat button actions as dynamic // Always treat button actions as dynamic
delete newStaticSettings[setting.key] delete newStaticSettings[setting.key]
} else if (typeof value === "object") { } else if (typeof value === "object") {
// Stringify and check objects
const stringified = JSON.stringify(value) const stringified = JSON.stringify(value)
if (stringified.includes("{{")) { if (stringified.includes("{{")) {
delete newStaticSettings[setting.key] delete newStaticSettings[setting.key]
@ -260,6 +255,7 @@
delete newDynamicSettings[setting.key] delete newDynamicSettings[setting.key]
} }
} else { } else {
// For other types, we can safely assume they are static
delete newDynamicSettings[setting.key] delete newDynamicSettings[setting.key]
} }
} }
@ -268,25 +264,23 @@
return { return {
staticSettings: newStaticSettings, staticSettings: newStaticSettings,
dynamicSettings: newDynamicSettings, dynamicSettings: newDynamicSettings,
nestedSettings: newNestedSettings,
} }
} }
// Enriches any string component props using handlebars // Enriches any string component props using handlebars
const enrichComponentSettings = (settings, context) => { const enrichComponentSettings = (context, options = { force: false }) => {
const contextChanged = context.key !== lastContextKey const contextChanged = context.key !== lastContextKey
if (!contextChanged) { if (!contextChanged && !options?.force) {
return return
} else {
lastContextKey = context.key
} }
lastContextKey = context.key
// Record the timestamp so we can reference it after enrichment // Record the timestamp so we can reference it after enrichment
latestUpdateTime = Date.now() latestUpdateTime = Date.now()
const enrichmentTime = latestUpdateTime const enrichmentTime = latestUpdateTime
// Enrich settings with context // Enrich settings with context
const newEnrichedSettings = enrichProps(settings, context) const newEnrichedSettings = enrichProps(dynamicSettings, context)
// Abandon this update if a newer update has started // Abandon this update if a newer update has started
if (enrichmentTime !== latestUpdateTime) { if (enrichmentTime !== latestUpdateTime) {
@ -321,12 +315,15 @@
// Combines and caches all settings which will be passed to the component // Combines and caches all settings which will be passed to the component
// instance. Settings are aggressively memoized to avoid triggering svelte // instance. Settings are aggressively memoized to avoid triggering svelte
// reactive statements as much as possible. // reactive statements as much as possible.
const cacheSettings = (staticSettings, enriched, nested, conditional) => { const applySettings = (
staticSettings,
enrichedSettings,
conditionalSettings
) => {
const allSettings = { const allSettings = {
...staticSettings, ...staticSettings,
...enriched, ...enrichedSettings,
...nested, ...conditionalSettings,
...conditional,
} }
if (!cachedSettings) { if (!cachedSettings) {
cachedSettings = { ...allSettings } cachedSettings = { ...allSettings }