Better loading state mgmt

This commit is contained in:
Diego Imbert
2026-01-16 15:39:00 +01:00
parent ba037ebd84
commit 02eb644bcb
3 changed files with 36 additions and 64 deletions
@@ -13,7 +13,7 @@
import { Pane, Splitpanes } from 'svelte-splitpanes'
import SqlRepl from './SqlRepl.svelte'
import SimpleAgTable from './SimpleAgTable.svelte'
import { untrack, type Snippet } from 'svelte'
import { type Snippet } from 'svelte'
import type { DbInput } from './dbTypes'
import { getDbSchemas, loadAllTablesMetaData } from './apps/components/display/dbtable/metadata'
@@ -25,7 +25,6 @@
input?: DbInput
showRepl?: boolean
hasReplResult?: boolean
isRefreshing?: boolean
selectedSchemaKey?: string | undefined
selectedTableKey?: string | undefined
dbSelector?: Snippet<[]>
@@ -41,7 +40,6 @@
input,
showRepl = true,
hasReplResult = $bindable(false),
isRefreshing = $bindable(false),
selectedSchemaKey = $bindable(undefined),
selectedTableKey = $bindable(undefined),
dbSelector,
@@ -61,50 +59,40 @@
}
}
// `refreshCount` is a derived state. `refreshing` is the source of truth
let refreshCount = $state(0)
$effect(() => {
if (refreshing) untrack(() => (refreshCount += 1))
})
let refreshing = $state(false)
$effect(() => {
if (refreshing) getSchema()
})
// Sync refreshing state with bindable prop
$effect(() => {
isRefreshing = refreshing
})
export const refresh = () => !refreshing && (refreshing = true)
// Initial schema load
$effect(() => {
if (input) {
untrack(() => getSchema())
let colDefs = resource(
() => [input],
async () => {
if (!input) return
return await loadAllTablesMetaData($workspaceStore, input)
}
})
async function getSchema() {
if (!input) return
const dbSchemasPath = getDbSchemasPath(input)
if ($dbSchemas[dbSchemasPath] && !refreshing) return
$dbSchemas[dbSchemasPath]
if (input.type == 'database') {
$dbSchemas[dbSchemasPath] = await getDbSchemas(
input.resourceType,
input.resourcePath,
$workspaceStore,
(message: string) => sendUserToast(message, true)
)
} else if (input.type == 'ducklake') {
$dbSchemas[dbSchemasPath] = await getDucklakeSchema({
workspace: $workspaceStore!,
ducklake: input.ducklake
})
)
let dbSchemasPromise = resource(
() => [input],
async () => {
if (!input) return
const dbSchemasPath = getDbSchemasPath(input)
if (input.type == 'database') {
$dbSchemas[dbSchemasPath] = await getDbSchemas(
input.resourceType,
input.resourcePath,
$workspaceStore,
(message: string) => sendUserToast(message, true)
)
} else if (input.type == 'ducklake') {
$dbSchemas[dbSchemasPath] = await getDucklakeSchema({
workspace: $workspaceStore!,
ducklake: input.ducklake
})
}
}
refreshing = false
)
export const refresh = () => {
if (isLoading()) return
colDefs.refetch()
dbSchemasPromise.refetch()
}
export function isLoading() {
return colDefs.loading || dbSchemasPromise.loading
}
let replPanelSize = $state(36)
@@ -117,14 +105,6 @@
hasReplResult = !!replResultData
})
let colDefs = resource(
() => [input, refreshCount],
async () => {
if (!input) return
return await loadAllTablesMetaData($workspaceStore, input)
}
)
// Export for parent components
export function clearReplResult() {
replResultData = undefined
@@ -85,7 +85,6 @@
let dbManagerContent: DBManagerContent | undefined = $state()
let hasReplResult = $state(false)
let isRefreshing = $state(false)
</script>
<svelte:window bind:innerWidth={windowWidth} />
@@ -112,12 +111,7 @@
>
{#if effectiveInput && $workspaceStore}
{#key selectedDatatable}
<DBManagerContent
bind:this={dbManagerContent}
input={effectiveInput}
bind:hasReplResult
bind:isRefreshing
>
<DBManagerContent bind:this={dbManagerContent} input={effectiveInput} bind:hasReplResult>
{#snippet dbSelector()}
{#if isDatatableInput}
{#if datatables.loading}
@@ -141,7 +135,7 @@
{/if}
{#snippet actions()}
<Button
loading={isRefreshing}
loading={dbManagerContent?.isLoading() ?? false}
on:click={() => dbManagerContent?.refresh()}
startIcon={{ icon: RefreshCcw }}
size="xs"
@@ -28,7 +28,6 @@
// For DB manager
let dbManagerContent: DBManagerContent | undefined = $state()
let hasReplResult = $state(false)
let isRefreshing = $state(false)
let windowWidth = $state(window.innerWidth)
let expand = $state(false)
@@ -168,7 +167,6 @@
bind:this={dbManagerContent}
input={dbInput}
bind:hasReplResult
bind:isRefreshing
bind:selectedSchemaKey
bind:selectedTableKey
multiSelectMode={true}
@@ -216,7 +214,7 @@
</Button>
<Button
loading={isRefreshing}
loading={dbManagerContent?.isLoading() ?? false}
on:click={() => dbManagerContent?.refresh()}
startIcon={{ icon: RefreshCcw }}
size="xs"