From 2ed16b8b4361b11ece20941102ec681232836b3d Mon Sep 17 00:00:00 2001 From: jelveh Date: Sat, 16 Aug 2025 13:15:04 -0700 Subject: [PATCH] add support for transactions --- src/gui/src/UI/UIDesktop.js | 15 ++++++++++- src/gui/src/globals.js | 26 ++++++++++++++++++- src/gui/src/helpers/refresh_item_container.js | 22 ++++++++++++++-- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/gui/src/UI/UIDesktop.js b/src/gui/src/UI/UIDesktop.js index 326a42441..59fc8f80a 100644 --- a/src/gui/src/UI/UIDesktop.js +++ b/src/gui/src/UI/UIDesktop.js @@ -44,6 +44,13 @@ import item_icon from "../helpers/item_icon.js" import UIWindowSearch from "./UIWindowSearch.js" async function UIDesktop(options) { + // start a transaction if we're not in embedded or fullpage mode + let transaction; + if (!window.is_embedded && !window.is_fullpage_mode) { + transaction = new window.Transaction('desktop-load'); + transaction.start(); + } + let h = ''; // Set up the desktop channel for communication between different tabs in the same browser @@ -1040,7 +1047,13 @@ async function UIDesktop(options) { // because the items aren't visible anyway and we don't need to waste bandwidth/server resources //------------------------------------------- if (!window.is_embedded && !window.is_fullpage_mode) { - refresh_item_container(el_desktop, { fadeInItems: true }) + refresh_item_container(el_desktop, { + fadeInItems: true, + onComplete: () => { + // End transaction when desktop is fully ready for user interaction + transaction.end(); + } + }) // Show welcome window if user hasn't already seen it and hasn't directly navigated to an app if (!window.url_paths[0]?.toLocaleLowerCase() === 'app' || !window.url_paths[1]) { diff --git a/src/gui/src/globals.js b/src/gui/src/globals.js index 86cef5c4c..06b2b2e42 100644 --- a/src/gui/src/globals.js +++ b/src/gui/src/globals.js @@ -256,4 +256,28 @@ window.reset_item_positions = true; // The variable decides if the item position window.file_templates = [] // default language -window.locale = 'en'; \ No newline at end of file +window.locale = 'en'; + +// the transaction class +window.Transaction = class { + constructor(name) { + this.name = name; + this.id = uuidv4(); + } + + start() { + this.start_ts = Date.now(); + } + + end() { + this.end_ts = Date.now(); + this.duration = this.end_ts - this.start_ts; + + // emit an event + window.dispatchEvent(new CustomEvent('transaction-ended', { + detail: { + transaction: this + } + })); + } +} \ No newline at end of file diff --git a/src/gui/src/helpers/refresh_item_container.js b/src/gui/src/helpers/refresh_item_container.js index 3d361094a..8bca15bb3 100644 --- a/src/gui/src/helpers/refresh_item_container.js +++ b/src/gui/src/helpers/refresh_item_container.js @@ -228,8 +228,21 @@ const refresh_item_container = function(el_item_container, options){ $(el_item_container).attr('data-sort_order') ); - if(options.fadeInItems) - $(el_item_container).animate({'opacity': '1'}); + if(options.fadeInItems) { + $(el_item_container).animate({'opacity': '1'}, { + complete: () => { + // Call onComplete callback when fade-in animation is done + if(options.onComplete && typeof options.onComplete === 'function') { + options.onComplete(); + } + } + }); + } else { + // If no fade-in animation, call onComplete immediately + if(options.onComplete && typeof options.onComplete === 'function') { + options.onComplete(); + } + } // update footer item count if this is an explorer window if(el_window) @@ -249,6 +262,11 @@ const refresh_item_container = function(el_item_container, options){ // show error message $(error_message).html('Failed to load directory' + html_encode((e && e.message ? ': ' + e.message : ''))); $(error_message).show(); + + // Call onComplete callback even in error case, since the "loading" is technically complete + if(options.onComplete && typeof options.onComplete === 'function') { + options.onComplete(); + } }); }