fixed the racecondition of the composite services renderer
This commit is contained in:
parent
460deb3be1
commit
e2ea57e89f
@ -6,7 +6,7 @@
|
|||||||
import { createMessage } from '$lib/services/messages/messages';
|
import { createMessage } from '$lib/services/messages/messages';
|
||||||
import { createLitSession } from '$lib/services/createLitSession/createLitSession';
|
import { createLitSession } from '$lib/services/createLitSession/createLitSession';
|
||||||
|
|
||||||
const redirectUri = 'http://localhost:5173/login';
|
const redirectUri = 'http://localhost:5173/login/';
|
||||||
|
|
||||||
export let services;
|
export let services;
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
export let store;
|
export let store;
|
||||||
|
|
||||||
let isStoreLoaded = false;
|
let isStoreLoaded = false;
|
||||||
|
$: console.log('store: ' + JSON.stringify($store));
|
||||||
|
|
||||||
$: if (services && services.helloEarthAlert) {
|
$: if (services && services.helloEarthAlert) {
|
||||||
// services.helloEarthAlert.alertMe();
|
// services.helloEarthAlert.alertMe();
|
||||||
|
@ -6,6 +6,14 @@
|
|||||||
import { dataStore } from '$lib/core/dataLoader';
|
import { dataStore } from '$lib/core/dataLoader';
|
||||||
import { createCompositeStore, getCompositeStore } from '$lib/core/compositeStores';
|
import { createCompositeStore, getCompositeStore } from '$lib/core/compositeStores';
|
||||||
|
|
||||||
|
interface ICompositeLayout {
|
||||||
|
areas: string;
|
||||||
|
columns?: string;
|
||||||
|
rows?: string;
|
||||||
|
gap?: string;
|
||||||
|
tailwindClasses?: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface IComposite {
|
interface IComposite {
|
||||||
layout?: ICompositeLayout;
|
layout?: ICompositeLayout;
|
||||||
id: string;
|
id: string;
|
||||||
@ -15,14 +23,7 @@
|
|||||||
map?: Record<string, string>;
|
map?: Record<string, string>;
|
||||||
store?: Record<string, any>;
|
store?: Record<string, any>;
|
||||||
children?: IComposite[];
|
children?: IComposite[];
|
||||||
}
|
servicesLoaded?: boolean;
|
||||||
|
|
||||||
interface ICompositeLayout {
|
|
||||||
areas: string;
|
|
||||||
columns?: string;
|
|
||||||
rows?: string;
|
|
||||||
gap?: string;
|
|
||||||
tailwindClasses?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export let composite: IComposite;
|
export let composite: IComposite;
|
||||||
@ -30,39 +31,49 @@
|
|||||||
let layoutStyle = '';
|
let layoutStyle = '';
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
// Create layout style reactively
|
|
||||||
layoutStyle = computeLayoutStyle(composite?.layout);
|
layoutStyle = computeLayoutStyle(composite?.layout);
|
||||||
|
|
||||||
// Load services reactively
|
initializeAndLoadServices(composite);
|
||||||
if (composite?.services) {
|
initializeCompositeState(composite);
|
||||||
for (const serviceName of composite.services) {
|
mapAndSubscribe(composite);
|
||||||
if (!loadedServices[serviceName]) {
|
|
||||||
// Note: We're ignoring async operation here, you might want to handle it if needed
|
|
||||||
loadService(serviceName).then((service) => {
|
|
||||||
loadedServices[serviceName] = service;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize composite state reactively
|
|
||||||
if (composite?.children) {
|
if (composite?.children) {
|
||||||
composite.children.forEach((child) => {
|
composite.children.forEach((child) => {
|
||||||
initializeCompositeState(child);
|
initializeAndLoadServices(child);
|
||||||
mapAndSubscribe(child);
|
mapAndSubscribe(child);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function computeLayoutStyle(layout?: ICompositeLayout) {
|
function computeLayoutStyle(layout?: ICompositeLayout): string {
|
||||||
if (!layout) return '';
|
if (!layout) return '';
|
||||||
|
|
||||||
return `
|
return `
|
||||||
grid-template-areas: ${layout.areas};
|
grid-template-areas: ${layout.areas};
|
||||||
${layout.gap ? `gap: ${layout.gap};` : ''}
|
${layout.gap ? `gap: ${layout.gap};` : ''}
|
||||||
${layout.columns ? `grid-template-columns: ${layout.columns};` : ''}
|
${layout.columns ? `grid-template-columns: ${layout.columns};` : ''}
|
||||||
${layout.rows ? `grid-template-rows: ${layout.rows};` : ''}
|
${layout.rows ? `grid-template-rows: ${layout.rows};` : ''}
|
||||||
`;
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeAndLoadServices(component: IComposite) {
|
||||||
|
if (!component) return;
|
||||||
|
|
||||||
|
if (component.services) {
|
||||||
|
let servicePromises = component.services.map((serviceName) =>
|
||||||
|
loadedServices[serviceName]
|
||||||
|
? Promise.resolve(loadedServices[serviceName])
|
||||||
|
: loadService(serviceName)
|
||||||
|
);
|
||||||
|
|
||||||
|
Promise.all(servicePromises).then((loaded) => {
|
||||||
|
loaded.forEach((service, index) => {
|
||||||
|
loadedServices[component.services[index]] = service;
|
||||||
|
});
|
||||||
|
component.servicesLoaded = true;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
component.servicesLoaded = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeCompositeState(child: IComposite) {
|
function initializeCompositeState(child: IComposite) {
|
||||||
@ -78,8 +89,6 @@
|
|||||||
let unsubscribers = [];
|
let unsubscribers = [];
|
||||||
|
|
||||||
function mapAndSubscribe(component: IComposite) {
|
function mapAndSubscribe(component: IComposite) {
|
||||||
console.log('Mapping and subscribing for:', component.id);
|
|
||||||
|
|
||||||
if (component.map) {
|
if (component.map) {
|
||||||
const localStore = getCompositeStore(component.id);
|
const localStore = getCompositeStore(component.id);
|
||||||
|
|
||||||
@ -91,15 +100,14 @@
|
|||||||
if (externalKey in store) {
|
if (externalKey in store) {
|
||||||
if (store[externalKey] && typeof store[externalKey].subscribe === 'function') {
|
if (store[externalKey] && typeof store[externalKey].subscribe === 'function') {
|
||||||
let innerUnsub = store[externalKey].subscribe((value) => {
|
let innerUnsub = store[externalKey].subscribe((value) => {
|
||||||
localStore.update((storeValue) => {
|
localStore.update((storeValue) => ({ ...storeValue, [localKey]: value }));
|
||||||
return { ...storeValue, [localKey]: value };
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
unsubscribers.push(innerUnsub);
|
unsubscribers.push(innerUnsub);
|
||||||
} else {
|
} else {
|
||||||
localStore.update((storeValue) => {
|
localStore.update((storeValue) => ({
|
||||||
return { ...storeValue, [localKey]: store[externalKey] };
|
...storeValue,
|
||||||
});
|
[localKey]: store[externalKey]
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -110,9 +118,10 @@
|
|||||||
if (externalStore) {
|
if (externalStore) {
|
||||||
const unsubscribe = externalStore.subscribe((externalState) => {
|
const unsubscribe = externalStore.subscribe((externalState) => {
|
||||||
if (externalState && externalKey in externalState) {
|
if (externalState && externalKey in externalState) {
|
||||||
localStore.update((storeValue) => {
|
localStore.update((storeValue) => ({
|
||||||
return { ...storeValue, [localKey]: externalState[externalKey] };
|
...storeValue,
|
||||||
});
|
[localKey]: externalState[externalKey]
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -127,7 +136,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call all unsubscribe methods when the component is destroyed.
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
unsubscribers.forEach((unsub) => unsub());
|
unsubscribers.forEach((unsub) => unsub());
|
||||||
});
|
});
|
||||||
@ -148,27 +156,14 @@
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getServiceProps(component: IComposite) {
|
|
||||||
const loadedServices = {};
|
|
||||||
if (component.services) {
|
|
||||||
for (const serviceName of component.services) {
|
|
||||||
const loadedService = await loadService(serviceName);
|
|
||||||
if (loadedService) {
|
|
||||||
loadedServices[serviceName] = loadedService;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return loadedServices;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadComponentAndService(component: IComposite) {
|
async function loadComponentAndService(component: IComposite) {
|
||||||
return await Promise.all([getComponent(component.component), getServiceProps(component)]);
|
return await getComponent(component.component);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class={`grid w-full h-full ${composite?.layout?.tailwindClasses || ''}`} style={layoutStyle}>
|
<div class={`grid w-full h-full ${composite?.layout?.tailwindClasses || ''}`} style={layoutStyle}>
|
||||||
{#if composite && 'component' in composite}
|
{#if composite?.servicesLoaded}
|
||||||
{#await loadComponentAndService(composite) then [Component]}
|
{#await loadComponentAndService(composite) then Component}
|
||||||
{#if Component}
|
{#if Component}
|
||||||
<svelte:component
|
<svelte:component
|
||||||
this={Component}
|
this={Component}
|
||||||
@ -176,7 +171,7 @@
|
|||||||
store={getCompositeStore(composite.id)}
|
store={getCompositeStore(composite.id)}
|
||||||
services={loadedServices}
|
services={loadedServices}
|
||||||
/>
|
/>
|
||||||
{:else if composite.component}
|
{:else}
|
||||||
<p>Component {composite.component} not found.</p>
|
<p>Component {composite.component} not found.</p>
|
||||||
{/if}
|
{/if}
|
||||||
{/await}
|
{/await}
|
||||||
@ -185,21 +180,25 @@
|
|||||||
{#if composite?.children}
|
{#if composite?.children}
|
||||||
{#each composite.children as child (child.id)}
|
{#each composite.children as child (child.id)}
|
||||||
<div class="w-full h-full overflow-hidden" style={`grid-area: ${child.slot}`}>
|
<div class="w-full h-full overflow-hidden" style={`grid-area: ${child.slot}`}>
|
||||||
{#await loadComponentAndService(child) then [ChildComponent]}
|
{#if child.servicesLoaded}
|
||||||
{#if ChildComponent}
|
{#await loadComponentAndService(child) then ChildComponent}
|
||||||
<svelte:component
|
{#if ChildComponent}
|
||||||
this={ChildComponent}
|
<svelte:component
|
||||||
id={child.id}
|
this={ChildComponent}
|
||||||
store={getCompositeStore(child.id)}
|
id={child.id}
|
||||||
services={loadedServices}
|
store={getCompositeStore(child.id)}
|
||||||
/>
|
services={loadedServices}
|
||||||
{#if child.children && child.children.length}
|
/>
|
||||||
<Composite composite={child} />
|
{#if child.children && child.children.length}
|
||||||
|
<Composite composite={child} />
|
||||||
|
{/if}
|
||||||
|
{:else}
|
||||||
|
<p>Component {child.component} not found.</p>
|
||||||
{/if}
|
{/if}
|
||||||
{:else if child.component}
|
{/await}
|
||||||
<p>Component {child.component} not found.</p>
|
{:else}
|
||||||
{/if}
|
<p>Loading services for child {child.id}...</p>
|
||||||
{/await}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -10,6 +10,10 @@
|
|||||||
import { Drawer, drawerStore } from '@skeletonlabs/skeleton';
|
import { Drawer, drawerStore } from '@skeletonlabs/skeleton';
|
||||||
import Composite from '$lib/core/Composite.svelte';
|
import Composite from '$lib/core/Composite.svelte';
|
||||||
|
|
||||||
|
const providerData = {
|
||||||
|
walletConnectId: import.meta.env.VITE_WALLETCONNECT_ID
|
||||||
|
};
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
initChainProvider(providerData);
|
initChainProvider(providerData);
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user