From 1ea1fd4d0e05c43349560c036cd0007bce87cc91 Mon Sep 17 00:00:00 2001 From: mahdahar <89adham@gmail.com> Date: Thu, 5 Mar 2026 16:18:43 +0700 Subject: [PATCH] Fix memory leaks in dashboard: clear iframe src on dialog close, limit toast queue, add cleanup destroy method --- app/Config/Filters.php | 2 +- app/Views/shared/script_requests.php | 44 +++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/app/Config/Filters.php b/app/Config/Filters.php index 7fc4f38..986f0db 100644 --- a/app/Config/Filters.php +++ b/app/Config/Filters.php @@ -61,7 +61,7 @@ class Filters extends BaseFilters 'after' => [ 'pagecache', // Web Page Caching 'performance', // Performance Metrics - 'toolbar', // Debug Toolbar + #'toolbar', // Debug Toolbar ], ]; diff --git a/app/Views/shared/script_requests.php b/app/Views/shared/script_requests.php index f569864..bf0fa64 100644 --- a/app/Views/shared/script_requests.php +++ b/app/Views/shared/script_requests.php @@ -7,6 +7,10 @@ document.addEventListener('alpine:init', () => { isLoading: false, counters: { Pend: 0, Coll: 0, Recv: 0, Inc: 0, Fin: 0, Total: 0 }, + // Toast queue to prevent DOM accumulation + _toastQueue: [], + _maxToasts: 3, + selectedPrinter: localStorage.getItem('selectedPrinter') || 'zebracs2', initSelectedPrinter() { @@ -224,6 +228,7 @@ document.addEventListener('alpine:init', () => { closeSampleDialog() { this.isDialogSampleOpen = false; this.item = null; + this.item = []; }, fetchItem(accessnumber) { @@ -489,6 +494,9 @@ document.addEventListener('alpine:init', () => { this.previewItem = null; this.previewAccessnumber = null; this.isPreviewIframeLoaded = false; + // Clear iframe src to release memory + const iframe = this.$refs.previewIframe; + if (iframe) iframe.src = 'about:blank'; }, getPreviewUrl() { if(this.previewAccessnumber != null) { @@ -563,6 +571,9 @@ document.addEventListener('alpine:init', () => { this.engResultItem = null; this.isEngResultIframeLoaded = false; this.isCreatingEngResult = false; + // Clear iframe src to release memory + const iframe = this.$refs.engResultIframe; + if (iframe) iframe.src = 'about:blank'; }, getEngResultUrl() { @@ -602,11 +613,42 @@ document.addEventListener('alpine:init', () => { }, showToast(message, type = 'success') { + // Limit concurrent toasts to prevent DOM accumulation + if (this._toastQueue.length >= this._maxToasts) { + const oldToast = this._toastQueue.shift(); + if (oldToast && oldToast.parentNode) oldToast.remove(); + } + const toast = document.createElement('div'); toast.className = `alert alert-${type} fixed top-4 right-4 z-50`; toast.innerHTML = ` ${message}`; document.body.appendChild(toast); - setTimeout(() => toast.remove(), 2000); + this._toastQueue.push(toast); + + setTimeout(() => { + toast.remove(); + const index = this._toastQueue.indexOf(toast); + if (index > -1) this._toastQueue.splice(index, 1); + }, 2000); + }, + + destroy() { + // Clear large data arrays to free memory + this.list = []; + this.filtered = []; + this.sorted = []; + this.paginated = []; + this.auditData = null; + this._cachedAuditEvents = []; + this.item = null; + this.previewItem = null; + this.engResultItem = null; + // Clear any open dialogs and their iframe references + if (this.$refs.previewIframe) this.$refs.previewIframe.src = 'about:blank'; + if (this.$refs.engResultIframe) this.$refs.engResultIframe.src = 'about:blank'; + // Clear any remaining toasts + this._toastQueue.forEach(t => { if (t.parentNode) t.remove(); }); + this._toastQueue = []; }, })); });