fix(control): uploaded files never finished animation

This commit is contained in:
E44
2026-01-12 19:56:51 +01:00
parent 9be8a70452
commit ea2f063991
2 changed files with 77 additions and 37 deletions
@@ -199,19 +199,10 @@ function generate_valid_file_name(original_file_name: string, used_file_names: s
async function upload(task: FileTransferTask): Promise<void> { async function upload(task: FileTransferTask): Promise<void> {
const task_data = task.data; const task_data = task.data;
if (task_data.type !== 'upload' || !task_data.file) return console.warn('Task cancelled: wrong task type:', task); if (task_data.type !== 'upload' || !task_data.file)
return console.warn('Task cancelled: wrong task type:', task);
await upload_file_via_xhr(task, task.display, task_data.file); await upload_file_via_xhr(task, task.display, task_data.file);
// Generate Thumbnail if not done already
setTimeout(async () => {
const inode_element: Inode | undefined = await db.files.get(
JSON.parse(task.file_primary_key) as [string, string, number, string]
);
if (!!inode_element && inode_element.thumbnail === null) {
await generate_thumbnail(task.display.ip, task.path, inode_element);
}
}, 10);
} }
export async function sync(task: FileTransferTask) { export async function sync(task: FileTransferTask) {
@@ -271,7 +262,8 @@ export async function download_file(selected_file_id: string, selected_display_i
selected_file_id, selected_file_id,
selected_display_ids selected_display_ids
); );
if (!file_data || file_data.file.type === 'inode/directory') return console.warn('Download cancelled: is folder'); if (!file_data || file_data.file.type === 'inode/directory')
return console.warn('Download cancelled: is folder');
try { try {
const url = `http://${file_data.short_display_with_file.ip}:1323/api${get_sanitized_file_url(file_data.file.path + file_data.file.name)}`; const url = `http://${file_data.short_display_with_file.ip}:1323/api${get_sanitized_file_url(file_data.file.path + file_data.file.name)}`;
@@ -305,8 +297,7 @@ async function start_task_loop() {
const current_task = tasks[0]; const current_task = tasks[0];
if (current_task.data.type === 'upload') { if (current_task.data.type === 'upload') {
await upload(current_task); await upload(current_task);
} } else if (current_task.data.type === 'sync') {
else if (current_task.data.type === 'sync') {
await sync(current_task); await sync(current_task);
} }
tasks.shift(); // Remove current_task from tasks tasks.shift(); // Remove current_task from tasks
@@ -314,8 +305,13 @@ async function start_task_loop() {
is_processing = false; is_processing = false;
} }
async function upload_file_via_xhr(task: FileTransferTask, current_short_display: ShortDisplay, current_file: File) { async function upload_file_via_xhr(
task: FileTransferTask,
current_short_display: ShortDisplay,
current_file: File
) {
const start_time = new Date(); const start_time = new Date();
const loading_type = task.data.type === 'upload' ? 'upload' : 'sync_upload';
return new Promise<void>((resolve) => { return new Promise<void>((resolve) => {
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
@@ -328,7 +324,13 @@ async function upload_file_via_xhr(task: FileTransferTask, current_short_display
xhr.upload.onprogress = (e) => { xhr.upload.onprogress = (e) => {
const apply = async () => { const apply = async () => {
await update_current_loading_data(task.data.type === 'upload' ? 'upload' : 'sync_upload', task, e.loaded, start_time, current_short_display.id); await update_current_loading_data(
loading_type,
task,
e.loaded,
start_time,
current_short_display.id
);
}; };
apply(); apply();
}; };
@@ -341,9 +343,20 @@ async function upload_file_via_xhr(task: FileTransferTask, current_short_display
xhr.onreadystatechange = async () => { xhr.onreadystatechange = async () => {
if (xhr.readyState === 4) { if (xhr.readyState === 4) {
if (xhr.status == 200) { if (xhr.status == 200) {
await db.files_on_display.update([current_short_display.ip, task.file_primary_key], { // set loading_data to 100%
await db.files_on_display.update([current_short_display.id, task.file_primary_key], {
date_created: new Date(),
loading_data: null loading_data: null
}); // TODO: Stattdessen update machen und gucken, ob die Datei wirklich da ist });
// Generate Thumbnail if not done already
setTimeout(async () => {
const inode_element: Inode | undefined = await db.files.get(
JSON.parse(task.file_primary_key) as [string, string, number, string]
);
if (!!inode_element && inode_element.thumbnail === null) {
await generate_thumbnail(task.display.ip, task.path, inode_element);
}
}, 10);
} else { } else {
await show_error(task, `HTTP ${xhr.status}`); await show_error(task, `HTTP ${xhr.status}`);
} }
@@ -352,21 +365,33 @@ async function upload_file_via_xhr(task: FileTransferTask, current_short_display
}; };
xhr.send(current_file); xhr.send(current_file);
}) });
} }
async function update_current_loading_data(type: FileLoadingData['type'], task: FileTransferTask, current_bytes: number, start_time: Date, other_display_id: string | null = null) { async function update_current_loading_data(
const current_percentage = task.bytes_total > 0 ? Math.round((current_bytes / task.bytes_total) * 100) : 1; type: FileLoadingData['type'],
task: FileTransferTask,
current_bytes: number,
start_time: Date,
other_display_id: string | null = null
) {
const current_percentage = Math.min(
task.bytes_total > 0 ? Math.round((current_bytes / task.bytes_total) * 100) : 1,
99
); // calculate percantage, but maximum value is 99%
const prognosed_data = get_prognosed_data(start_time, current_bytes, task.bytes_total); const prognosed_data = get_prognosed_data(start_time, current_bytes, task.bytes_total);
await db.files_on_display.update([other_display_id ? other_display_id : task.display.id, task.file_primary_key], { await db.files_on_display.update(
[other_display_id ? other_display_id : task.display.id, task.file_primary_key],
{
loading_data: { loading_data: {
type, type,
percentage: current_percentage, percentage: current_percentage,
bytes_per_second: prognosed_data.bytes_per_second, bytes_per_second: prognosed_data.bytes_per_second,
seconds_until_finish: prognosed_data.seconds_until_finish seconds_until_finish: prognosed_data.seconds_until_finish
} }
}); }
);
} }
function get_prognosed_data( function get_prognosed_data(
+23 -8
View File
@@ -211,17 +211,30 @@ export async function update_folder_elements_recursively(
const new_folder_elements = await get_file_data(display.ip, file_path); const new_folder_elements = await get_file_data(display.ip, file_path);
if (!new_folder_elements) return; if (!new_folder_elements) return;
const existing_file_keys_on_display_in_path: [string, string, number, string][] = ( const existing_files_on_display_in_path: FileOnDisplay[] = await db.files_on_display
await db.files_on_display.where('display_id').equals(display.id).toArray() .where('display_id')
).map((e) => JSON.parse(e.file_primary_key) as [string, string, number, string]); .equals(display.id)
const existing_files_on_display_in_path: Inode[] = await db.files .toArray();
const existing_file_keys_on_display_in_path: [string, string, number, string][] =
existing_files_on_display_in_path.map(
(e) => JSON.parse(e.file_primary_key) as [string, string, number, string]
);
const existing_files: Inode[] = await db.files
.where('[path+name+size+type]') .where('[path+name+size+type]')
.anyOf(existing_file_keys_on_display_in_path) .anyOf(existing_file_keys_on_display_in_path)
.filter((e) => e.path === file_path) .filter((e) => e.path === file_path)
.toArray(); .toArray();
const existing_files_with_loading_state: { folder_element: Inode; is_loading: boolean }[] =
existing_files.map((folder_element) => ({
folder_element,
is_loading: !!existing_files_on_display_in_path.find(
(e) => e.file_primary_key === get_file_primary_key(folder_element)
)?.loading_data
}));
const diff = get_folder_elements_difference( const diff = get_folder_elements_difference(
existing_files_on_display_in_path, existing_files_with_loading_state,
new_folder_elements new_folder_elements
); );
@@ -262,13 +275,15 @@ export async function update_folder_elements_recursively(
} }
function get_folder_elements_difference( function get_folder_elements_difference(
old_elements: Inode[], old_elements: { folder_element: Inode; is_loading: boolean }[],
new_elements: { folder_element: Inode; date_created: Date }[] new_elements: { folder_element: Inode; date_created: Date }[]
): { deleted: Inode[]; new: { folder_element: Inode; date_created: Date }[] } { ): { deleted: Inode[]; new: { folder_element: Inode; date_created: Date }[] } {
const old_keys = new Set(old_elements.map((e) => get_file_primary_key(e))); const old_keys = new Set(old_elements.map((e) => get_file_primary_key(e.folder_element)));
const new_keys = new Set(new_elements.map((e) => get_file_primary_key(e.folder_element))); const new_keys = new Set(new_elements.map((e) => get_file_primary_key(e.folder_element)));
const only_in_old = old_elements.filter((e) => !new_keys.has(get_file_primary_key(e))); const only_in_old = old_elements
.filter((e) => !new_keys.has(get_file_primary_key(e.folder_element)) && !e.is_loading)
.map((e) => e.folder_element);
const only_in_new = new_elements.filter( const only_in_new = new_elements.filter(
(e) => !old_keys.has(get_file_primary_key(e.folder_element)) (e) => !old_keys.has(get_file_primary_key(e.folder_element))
); );