From 62080d02f62ad0f1843cd8b9730bee722b5fd8b4 Mon Sep 17 00:00:00 2001 From: ishtiyak Date: Sun, 23 Nov 2025 17:40:51 +0530 Subject: [PATCH 1/2] feat: sort the desktop icon --- frappe/desk/page/desktop/desktop.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/desk/page/desktop/desktop.js b/frappe/desk/page/desktop/desktop.js index e53f4e51e6..11649166ac 100644 --- a/frappe/desk/page/desktop/desktop.js +++ b/frappe/desk/page/desktop/desktop.js @@ -278,8 +278,8 @@ class DesktopIconGrid { } prepare() { - this.icons_data = this.icons_data.sort((a, b) => a.idx - b.idx); this.total_pages = 1; + this.icons_data = this.icons_data.sort((a, b) => a.name.localeCompare(b.name)); this.icons_data_by_page = this.icons_data || this.split_data(this.icons_data, this.page_size.total()); } From ceafcc8790b7d3254c9f23ea1114a4a886c50ed6 Mon Sep 17 00:00:00 2001 From: Sagar Vora <16315650+sagarvora@users.noreply.github.com> Date: Sun, 23 Nov 2025 20:53:16 +0530 Subject: [PATCH 2/2] fix: use script/link tag injection in frappe.require to preserve global scope - Changed frappe.require to use script/link tag injection instead of fetch + IIFE - This fixes loading of UMD libraries like html5-qrcode that need global scope - Maintains original behavior: waits for assets to load before callback - Resolves scanner breakage caused by PR #33973 --- frappe/public/js/frappe/assets.js | 54 ++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/frappe/public/js/frappe/assets.js b/frappe/public/js/frappe/assets.js index cde8715c23..fade5972c9 100644 --- a/frappe/public/js/frappe/assets.js +++ b/frappe/public/js/frappe/assets.js @@ -23,11 +23,28 @@ class AssetManager { constructor() { this._executed = []; this._handlers = { - js: function (txt) { - frappe.dom.eval(txt); + js: (url) => { + return new Promise((resolve) => { + const script = document.createElement("script"); + script.type = "text/javascript"; + script.src = url; + script.onload = resolve; + // for backward compatibility, resolve even on error + script.onerror = resolve; + document.head.appendChild(script); + }); }, - css: function (txt) { - frappe.dom.set_style(txt); + css: (url) => { + return new Promise((resolve) => { + const link = document.createElement("link"); + link.type = "text/css"; + link.rel = "stylesheet"; + link.href = url; + link.onload = resolve; + // for backward compatibility, resolve even on error + link.onerror = resolve; + document.head.appendChild(link); + }); }, }; } @@ -77,11 +94,16 @@ class AssetManager { console.log("localStorage cleared"); } - eval_assets(path, content) { - if (!this._executed.includes(path)) { - this._handlers[this.extn(path)](content); - this._executed.push(path); + load_asset(path, url) { + if (this._executed.includes(path)) { + return Promise.resolve(); } + + const ext = this.extn(path); + const handler = this._handlers[ext]; + return handler(url).then(() => { + this._executed.push(path); + }); } execute(items, callback) { @@ -91,8 +113,7 @@ class AssetManager { const version_string = frappe.boot.developer_mode || window.dev_server ? Date.now() : window._version_number; - let fetched_assets = {}; - async function fetch_item(path) { + let load_promises = items.map((path) => { let url = new URL(path, window.location.origin); // Add the version to the URL to bust the cache for non-bundled assets @@ -103,17 +124,12 @@ class AssetManager { ) { url.searchParams.append("v", version_string); } - const response = await fetch(url.toString()); - fetched_assets[path] = await response.text(); - } + + return me.load_asset(path, url.toString()); + }); frappe.dom.freeze(); - const fetch_promises = items.map(fetch_item); - Promise.all(fetch_promises).then(() => { - items.forEach((path) => { - let body = fetched_assets[path]; - me.eval_assets(path, body); - }); + Promise.all(load_promises).then(() => { frappe.dom.unfreeze(); callback?.(); });