From 2367dc0c9e73d195122eb8587a758b4a7c2c0119 Mon Sep 17 00:00:00 2001 From: E44 <129310925+programmer-44@users.noreply.github.com> Date: Sun, 4 Jan 2026 23:25:19 +0100 Subject: [PATCH] chore(control): add progress_bar in InodeElement --- .../src/lib/components/InodeElement.svelte | 139 +++++++++++++++--- 1 file changed, 115 insertions(+), 24 deletions(-) diff --git a/control/frontend/src/lib/components/InodeElement.svelte b/control/frontend/src/lib/components/InodeElement.svelte index a923a91..484e49a 100755 --- a/control/frontend/src/lib/components/InodeElement.svelte +++ b/control/frontend/src/lib/components/InodeElement.svelte @@ -6,7 +6,12 @@ get_shifted_color } from '$lib/ts/stores/ui_behavior'; import Button from '$lib/components/Button.svelte'; - import { supported_file_type_icon, type Inode, get_file_primary_key } from '$lib/ts/types'; + import { + supported_file_type_icon, + type Inode, + get_file_primary_key, + type FileOnDisplay + } from '$lib/ts/types'; import { is_selected, @@ -26,6 +31,7 @@ import { run_on_all_selected_displays } from '$lib/ts/stores/displays'; import { get_thumbnail_url } from '$lib/ts/stores/thumbnails'; import { liveQuery, type Observable } from 'dexie'; + import { db } from '$lib/ts/files_display.db'; let { file, not_interactable = false }: { file: Inode; not_interactable?: boolean } = $props(); @@ -37,8 +43,19 @@ missing_colliding_displays_ids = liveQuery(() => get_missing_colliding_display_ids(file, s)); }); - let thumbnail_url = liveQuery(() => get_thumbnail_url(get_file_primary_key(file))); + let loading_data: + | Observable<{ + is_loading: boolean; + total_percentage: number; + display_data: { is_loading: boolean; percentage: number }[]; + }> + | undefined = $state(); + $effect(() => { + const d = $selected_display_ids; + loading_data = liveQuery(() => get_loading_data(get_file_primary_key(file), d)); + }); + let thumbnail_url = liveQuery(() => get_thumbnail_url(get_file_primary_key(file))); let date_mapping: Observable> = liveQuery(() => get_date_mapping(get_file_primary_key(file)) ); @@ -52,21 +69,28 @@ if (keys.length === 1) return get_formated_created_string(date_mapping[keys[0]], full_string); - let out = ""; + let out = ''; let is_different = false; - const first_formated_created_string = get_formated_created_string(date_mapping[keys[0]], full_string); + const first_formated_created_string = get_formated_created_string( + date_mapping[keys[0]], + full_string + ); out += `${keys[0]}: ${first_formated_created_string}`; for (const key of keys.splice(0, 1)) { - const current_formated_created_string = get_formated_created_string(date_mapping[key], full_string); - if (!is_different && current_formated_created_string !== first_formated_created_string) is_different = true; - out += `\n${key}: ${current_formated_created_string}` + const current_formated_created_string = get_formated_created_string( + date_mapping[key], + full_string + ); + if (!is_different && current_formated_created_string !== first_formated_created_string) + is_different = true; + out += `\n${key}: ${current_formated_created_string}`; } if (full_string) { return is_different ? out : first_formated_created_string; } else { - return is_different ? "versch." : first_formated_created_string; + return is_different ? 'versch.' : first_formated_created_string; } } @@ -95,6 +119,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'; 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)}`; @@ -102,13 +127,14 @@ 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'; 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) return; + if (not_interactable || $loading_data?.is_loading) return; select(selected_file_ids, get_file_primary_key(file), 'toggle'); e.stopPropagation(); } @@ -121,6 +147,73 @@ await run_on_all_selected_displays(open_file, true, path_to_file); } } + + function get_main_classes(): string { + let out = ''; + + if ($loading_data?.is_loading) { + 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), + { + bg: true, + hover: !not_interactable, + active: !not_interactable, + text: true + } + ); + } + + if (not_interactable) { + out += ' rounded-lg'; + } else if ($loading_data?.is_loading) { + out += ' rounded-r-lg'; + } else { + out += ' rounded-r-lg cursor-pointer'; + } + + return out; + } + + async function get_loading_data( + file_primary_key: string, + selected_display_ids: string[] + ): Promise<{ + is_loading: boolean; + total_percentage: number; + display_data: { is_loading: boolean; percentage: number }[]; + }> { + 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, + display_data: [] + }; + } + const display_data = []; + let is_loading = false; + let percentage_sum = 0; + for (const fod of file_on_display_data) { + if (!is_loading) is_loading = fod.is_loading; + percentage_sum += fod.percentage; + display_data.push({ + is_loading: fod.is_loading, + percentage: fod.percentage + }); + } + let total_percentage = percentage_sum / display_data.length; + return { + is_loading, + total_percentage, + display_data + }; + }
@@ -178,27 +271,25 @@ if (e.key === 'Enter' || e.key === ' ') onclick(e); }} {onclick} - class="{get_selectable_color_classes( - !not_interactable && is_selected(get_file_primary_key(file), $selected_file_ids), - { - bg: true, - hover: !not_interactable, - active: !not_interactable, - text: true - } - )} {not_interactable - ? 'rounded-lg' - : 'rounded-r-lg cursor-pointer'} transition-colors duration-200 gap-4 flex flex-row justify-between group w-full min-w-0" + 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} +
{#if is_folder} {:else if $thumbnail_url || null} file_thumbnail {:else if supported_file_type_icon[get_file_type(file)?.display_name || '']} @@ -215,7 +306,7 @@