From 99643f8029d778d6ed4e5c95b6232a288f9e0602 Mon Sep 17 00:00:00 2001 From: E44 <129310925+programmer-44@users.noreply.github.com> Date: Mon, 19 Jan 2026 15:39:53 +0100 Subject: [PATCH] chore(control): display transferring file correctly (still a few bugs) --- .../src/lib/components/InodeElement.svelte | 124 ++++----- control/frontend/src/lib/ts/database.ts | 3 +- .../src/lib/ts/file_transfer_handler.ts | 247 +++++++++++------- control/frontend/src/lib/ts/stores/files.ts | 38 +-- control/frontend/src/lib/ts/types.ts | 28 +- 5 files changed, 234 insertions(+), 206 deletions(-) diff --git a/control/frontend/src/lib/components/InodeElement.svelte b/control/frontend/src/lib/components/InodeElement.svelte index ec4719b..72bff2e 100755 --- a/control/frontend/src/lib/components/InodeElement.svelte +++ b/control/frontend/src/lib/components/InodeElement.svelte @@ -11,7 +11,7 @@ type Inode, get_file_primary_key, type FileOnDisplay, - type CompleteFileLoadingData + type FileTransferTask } from '$lib/ts/types'; import { @@ -33,9 +33,12 @@ import { get_thumbnail_url } from '$lib/ts/stores/thumbnails'; import { liveQuery, type Observable } from 'dexie'; import { db } from '$lib/ts/database'; + import { file_transfer_tasks } from '$lib/ts/file_transfer_handler'; let { file, not_interactable = false }: { file: Inode; not_interactable?: boolean } = $props(); + let file_primary_key = $derived(get_file_primary_key(file)); + let missing_colliding_displays_ids: | Observable<{ missing: string[]; colliding: string[] }> | undefined = $state(); @@ -44,31 +47,26 @@ missing_colliding_displays_ids = liveQuery(() => get_missing_colliding_display_ids(file, s)); }); - let loading_data: - | Observable - | undefined = $state(); - $effect(() => { - const d = $selected_display_ids; - loading_data = liveQuery(() => get_loading_data(get_file_primary_key(file), d)); - }); + let file_transfer_task: FileTransferTask | null = $derived( + $file_transfer_tasks.hasOwnProperty(file_primary_key) + ? $file_transfer_tasks[file_primary_key] + : null + ); let loading_finished = $state(false); + let previous_loading_state = $state(false); $effect(() => { - if (!loading_data) return; - let prev: boolean | undefined; - const sub = loading_data.subscribe((v) => { - if (prev === true && v.is_loading === false) { - loading_finished = true; - setTimeout(() => (loading_finished = false), 200); - } - prev = v.is_loading; - }); - return () => sub.unsubscribe(); + const ftt = file_transfer_task; + if (previous_loading_state && !ftt) { + loading_finished = true; + setTimeout(() => (loading_finished = false), 200); + } + previous_loading_state = !!ftt; }); - let thumbnail_url = liveQuery(() => get_thumbnail_url(get_file_primary_key(file))); + let thumbnail_url = liveQuery(() => get_thumbnail_url(file_primary_key)); let date_mapping: Observable> = liveQuery(() => - get_date_mapping(get_file_primary_key(file)) + get_date_mapping(file_primary_key) ); const is_folder = file.type === 'inode/directory'; @@ -130,7 +128,7 @@ function get_grayed_out_text_color_strings(is_selected: boolean): string { if (not_interactable) return 'text-stone-400'; - if ($loading_data?.is_loading) return 'text-white/20'; + if (!!file_transfer_task) return 'text-white/20'; const color = is_selected ? 'text-stone-600' : 'text-stone-400'; const factor = is_selected ? -1 : 1; return `${color} group-hover:${get_shifted_color(color, factor * 100)} group-active:${get_shifted_color(color, factor * 150)}`; @@ -138,15 +136,15 @@ function get_grayed_out_border_color_strings(is_selected: boolean): string { if (not_interactable) return 'border-stone-550'; - if ($loading_data?.is_loading) return 'border-white/10'; + if (!!file_transfer_task) return 'border-white/10'; const color = is_selected ? 'border-stone-450' : 'border-stone-550'; const factor = is_selected ? 1 : 1; return `${color} group-hover:${get_shifted_color(color, factor * 100)} group-active:${get_shifted_color(color, factor * 150)}`; } function onclick(e: Event) { - if (not_interactable || $loading_data?.is_loading) return; - select(selected_file_ids, get_file_primary_key(file), 'toggle'); + if (not_interactable || !!file_transfer_task) return; + select(selected_file_ids, file_primary_key, 'toggle'); e.stopPropagation(); } @@ -164,11 +162,11 @@ if (loading_finished) { out += 'bg-stone-500 text-white/30'; - } else if ($loading_data?.is_loading) { + } else if (!!file_transfer_task) { out += 'bg-stone-700 text-white/30'; } else { out += get_selectable_color_classes( - !not_interactable && is_selected(get_file_primary_key(file), $selected_file_ids), + !not_interactable && is_selected(file_primary_key, $selected_file_ids), { bg: true, hover: !not_interactable, @@ -180,7 +178,7 @@ if (not_interactable) { out += ' rounded-lg'; - } else if ($loading_data?.is_loading) { + } else if (!!file_transfer_task) { out += ' rounded-r-lg'; } else { out += ' rounded-r-lg cursor-pointer'; @@ -189,54 +187,20 @@ return out; } - async function get_loading_data( - file_primary_key: string, - selected_display_ids: string[] - ): Promise { - const file_on_display_data: FileOnDisplay[] = await db.files_on_display - .where('file_primary_key') - .equals(file_primary_key) - .filter((e) => selected_display_ids.includes(e.display_id)) - .toArray(); - if (file_on_display_data.length === 0) { - return { - is_loading: true, - total_percentage: 0, - total_seconds_until_finish: -1, - display_data: [] - }; + function get_total_percentage(ftt: FileTransferTask): number { + let total_percentage: number; + if (ftt.data.type === 'upload') { + total_percentage = ftt.loading_data.percentage; + } else { + const percentage_array = ftt.data.destination_display_data.map( + (dd) => dd.loading_data.percentage + ); + total_percentage = + (ftt.loading_data.percentage + percentage_array.reduce((total, n) => total + n, 0)) / + (1 + percentage_array.length); } - const display_data = []; - let is_loading = false; - let percentage_sum = 0; - let total_seconds_until_finish = 0; - for (const fod of file_on_display_data) { - if (!!fod.loading_data) { - if (!is_loading) is_loading = true; - percentage_sum += fod.loading_data.percentage; - total_seconds_until_finish += fod.loading_data.seconds_until_finish; - const display = await get_display_by_id(fod.display_id); - if (!display) continue; - const display_data_element = { - loading_data: fod.loading_data, - display_name: display.name - }; - if (fod.loading_data.type === 'sync_download') { - display_data.unshift(display_data_element); // insert sync_download element at beginning - } else { - display_data.push(display_data_element); - } - } else { - percentage_sum += 100; - } - } - let total_percentage = percentage_sum / display_data.length; - return { - is_loading, - total_percentage, - total_seconds_until_finish, - display_data - }; + + return Math.min(total_percentage, 100); } @@ -302,10 +266,10 @@ {onclick} class="{get_main_classes()} relative transition-colors duration-200 gap-4 flex flex-row justify-between group w-full min-w-0" > - {#if $loading_data?.is_loading} + {#if !!file_transfer_task}
{/if}
@@ -334,7 +298,7 @@