refactor: make Svelte prop lifetimes explicit

This commit is contained in:
vorotamoroz
2026-07-17 15:04:01 +00:00
parent 6e00b8195a
commit f6b03dc811
6 changed files with 27 additions and 23 deletions
+1 -1
View File
@@ -12,7 +12,7 @@
"buildDev": "node esbuild.config.mjs dev", "buildDev": "node esbuild.config.mjs dev",
"lint": "eslint --cache --concurrency auto src", "lint": "eslint --cache --concurrency auto src",
"lint:community": "eslint --config eslint.community.config.mjs --concurrency auto src", "lint:community": "eslint --config eslint.community.config.mjs --concurrency auto src",
"svelte-check": "svelte-check --tsconfig ./tsconfig.json", "svelte-check": "svelte-check --tsconfig ./tsconfig.json --fail-on-warnings",
"tsc-check": "tsc --noEmit", "tsc-check": "tsc --noEmit",
"tsc-check:apps": "tsc --noEmit -p src/apps/browser/tsconfig.json && tsc --noEmit -p src/apps/cli/tsconfig.json && tsc --noEmit -p src/apps/webapp/tsconfig.json && tsc --noEmit -p src/apps/webpeer/tsconfig.app.json && tsc --noEmit -p src/apps/webpeer/tsconfig.node.json", "tsc-check:apps": "tsc --noEmit -p src/apps/browser/tsconfig.json && tsc --noEmit -p src/apps/cli/tsconfig.json && tsc --noEmit -p src/apps/webapp/tsconfig.json && tsc --noEmit -p src/apps/webpeer/tsconfig.app.json && tsc --noEmit -p src/apps/webpeer/tsconfig.node.json",
"pretty:importpath": "cd utilsdeno && deno run -A ./normalise-imports.ts", "pretty:importpath": "cd utilsdeno && deno run -A ./normalise-imports.ts",
@@ -27,7 +27,7 @@
let serverInfo = $state<P2PServerInfo | undefined>(undefined); let serverInfo = $state<P2PServerInfo | undefined>(undefined);
let syncingPeerId = $state<string | null>(null); let syncingPeerId = $state<string | null>(null);
const logLevel = showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO; const logLevel = $derived(showResult ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO);
async function requestServerStatus() { async function requestServerStatus() {
await liveSyncReplicator.requestStatus(); await liveSyncReplicator.requestStatus();
eventHub.emitEvent(EVENT_REQUEST_STATUS); eventHub.emitEvent(EVENT_REQUEST_STATUS);
@@ -23,8 +23,11 @@
let { liveSyncReplicator, showBroadcastToggle = true, core }: Props = $props(); let { liveSyncReplicator, showBroadcastToggle = true, core }: Props = $props();
let serverInfo = $state<P2PServerInfo | undefined>(undefined); let serverInfo = $state<P2PServerInfo | undefined>(undefined);
let replicatorStatus = $state<P2PReplicatorStatus | undefined>(undefined); let replicatorStatus = $state<P2PReplicatorStatus | undefined>(undefined);
let roomSuffix = $state<string>(extractP2PRoomSuffix(core?.services.setting.currentSettings()?.P2P_roomID ?? "")); // Later setting changes arrive through EVENT_SETTING_SAVED; these values only seed local state at mount time.
let useDiagRTC = $state<boolean>(core?.services.setting.currentSettings()?.P2P_useDiagRTC ?? false); const readCurrentSettings = () => core?.services.setting.currentSettings();
const initialSettings = readCurrentSettings();
let roomSuffix = $state<string>(extractP2PRoomSuffix(initialSettings?.P2P_roomID ?? ""));
let useDiagRTC = $state<boolean>(initialSettings?.P2P_useDiagRTC ?? false);
async function requestServerStatus() { async function requestServerStatus() {
await Promise.resolve(liveSyncReplicator.requestStatus()); await Promise.resolve(liveSyncReplicator.requestStatus());
@@ -307,4 +310,4 @@
font-size: 0.85rem; font-size: 0.85rem;
gap: 0.5rem; gap: 0.5rem;
} }
</style> </style>
@@ -33,16 +33,17 @@
let replicatingPeerId = $state<string | null>(null); let replicatingPeerId = $state<string | null>(null);
let communicatingUntil = $state<Record<string, number>>({}); let communicatingUntil = $state<Record<string, number>>({});
const COMMUNICATION_HOLD_MS = 2500; const COMMUNICATION_HOLD_MS = 2500;
let syncOnReplicationSetting = $state(core.services.setting.currentSettings()?.P2P_SyncOnReplication ?? ""); // Later setting changes arrive through EVENT_SETTING_SAVED; these values only seed local state at mount time.
const readCurrentSettings = () => core.services.setting.currentSettings();
const initialSettings = readCurrentSettings();
let syncOnReplicationSetting = $state(initialSettings?.P2P_SyncOnReplication ?? "");
type P2PRemoteOption = { type P2PRemoteOption = {
id: string; id: string;
name: string; name: string;
roomSuffix: string; roomSuffix: string;
}; };
let p2pRemoteOptions = $state<P2PRemoteOption[]>([]); let p2pRemoteOptions = $state<P2PRemoteOption[]>([]);
let selectedP2PRemoteConfigurationId = $state( let selectedP2PRemoteConfigurationId = $state(initialSettings?.P2P_ActiveRemoteConfigurationId ?? "");
core.services.setting.currentSettings()?.P2P_ActiveRemoteConfigurationId ?? ""
);
let selectingP2PRemote = $state(false); let selectingP2PRemote = $state(false);
function addToList(item: string, list: string): string { function addToList(item: string, list: string): string {
@@ -12,33 +12,33 @@
// */ // */
// onSetupContext?(props: DialogSvelteComponentBaseProps): void; // onSetupContext?(props: DialogSvelteComponentBaseProps): void;
// }; // };
const { setTitle, closeDialog, setResult, mountComponent, getInitialData, onSetupContext }: DialogHostProps = const props: DialogHostProps = $props();
$props();
const contextProps = { const contextProps = {
setTitle, setTitle: (title: string) => props.setTitle(title),
closeDialog, closeDialog: () => props.closeDialog(),
setResult, setResult: (result: any) => props.setResult(result),
getInitialData, getInitialData: () => props.getInitialData?.(),
} satisfies DialogSvelteComponentBaseProps<any,any> } satisfies DialogSvelteComponentBaseProps<any, any>;
// Call the onSetupContext function to setup the dialog context // Context must be established during component initialisation. The callbacks retain live access to the host props.
onSetupContext?.(contextProps); const setupContext = () => props.onSetupContext?.(contextProps);
setupContext();
/** /**
* Wrapper around setResult to also close the dialog * Wrapper around setResult to also close the dialog
* @param result * @param result
*/ */
const setResultWrapper = (result: any) => { const setResultWrapper = (result: any) => {
setResult(result); props.setResult(result);
closeDialog(); props.closeDialog();
}; };
const Component = mountComponent; const Component = $derived(props.mountComponent);
let thisElement: HTMLElement; let thisElement: HTMLElement;
</script> </script>
<div class="dialog-host" bind:this={thisElement}> <div class="dialog-host" bind:this={thisElement}>
<Component setResult={setResultWrapper} {getInitialData}></Component> <Component setResult={setResultWrapper} getInitialData={props.getInitialData}></Component>
</div> </div>
<style> <style>
@@ -22,7 +22,7 @@
group, group,
children, children,
}: Props = $props(); }: Props = $props();
const actualGroup = group ?? definedGroupContext; const actualGroup = $derived(group ?? definedGroupContext);
const translatedTitle = $derived.by(() => translate(title)); const translatedTitle = $derived.by(() => translate(title));
</script> </script>