From 846c9c658305410b4d44bce4ede95050605e387c Mon Sep 17 00:00:00 2001 From: dab246 Date: Tue, 5 Aug 2025 23:29:11 +0700 Subject: [PATCH] TF-3911 Remove window event listeners to prevent memory leaks in Email View --- .../html_content_viewer_on_web_widget.dart | 63 +++++++++++-------- core/lib/utils/html/html_interaction.dart | 20 ++++-- 2 files changed, 52 insertions(+), 31 deletions(-) diff --git a/core/lib/presentation/views/html_viewer/html_content_viewer_on_web_widget.dart b/core/lib/presentation/views/html_viewer/html_content_viewer_on_web_widget.dart index 36fdc97d0..f560a4a63 100644 --- a/core/lib/presentation/views/html_viewer/html_content_viewer_on_web_widget.dart +++ b/core/lib/presentation/views/html_viewer/html_content_viewer_on_web_widget.dart @@ -141,7 +141,7 @@ class _HtmlContentViewerOnWebState extends State _handleHyperLinkEvent(data['url']); } } catch (e) { - logError('_HtmlContentViewerOnWebState::_handleMessageEvent:Exception = $e'); + logError('$runtimeType::_handleMessageEvent:Exception = $e'); } } @@ -162,28 +162,32 @@ class _HtmlContentViewerOnWebState extends State dynamic data, ScrollController controller, ) { - final deltaY = data['deltaY'] ?? 0.0; - final target = controller.offset + deltaY; + try { + final deltaY = data['deltaY'] ?? 0.0; + final target = controller.offset + deltaY; - if (PlatformInfo.isWebTouchDevice) { - final newOffset = target.clamp( - controller.position.minScrollExtent, - controller.position.maxScrollExtent, - ); + if (PlatformInfo.isWebTouchDevice) { + final newOffset = target.clamp( + controller.position.minScrollExtent, + controller.position.maxScrollExtent, + ); - controller.animateTo( - newOffset, - duration: const Duration(milliseconds: 50), - curve: Curves.linear, - ); - } else { - if (target < controller.position.minScrollExtent) { - controller.jumpTo(controller.position.minScrollExtent); - } else if (target > controller.position.maxScrollExtent) { - controller.jumpTo(controller.position.maxScrollExtent); + controller.animateTo( + newOffset, + duration: const Duration(milliseconds: 50), + curve: Curves.linear, + ); } else { - controller.jumpTo(target); + if (target < controller.position.minScrollExtent) { + controller.jumpTo(controller.position.minScrollExtent); + } else if (target > controller.position.maxScrollExtent) { + controller.jumpTo(controller.position.maxScrollExtent); + } else { + controller.jumpTo(target); + } } + } catch (e) { + logError('$runtimeType::_handleIframeOnScrollChangedListener:Exception = $e'); } } @@ -271,19 +275,23 @@ class _HtmlContentViewerOnWebState extends State } void _handleOnIFrameKeyboardEvent(dynamic data) { - final shortcut = KeyShortcut( - key: data['key'] as String, - code: data['code'] as String, - shift: data['shift'] == true, - ); - log('_HtmlContentViewerOnWebState::_handleOnIFrameKeyboardEvent:📥 Shortcut pressed: $shortcut'); - widget.onIFrameKeyboardShortcutAction?.call(shortcut); + try { + final shortcut = KeyShortcut( + key: data['key'] as String, + code: data['code'] as String, + shift: data['shift'] == true, + ); + log('$runtimeType::_handleOnIFrameKeyboardEvent:📥 Shortcut pressed: $shortcut'); + widget.onIFrameKeyboardShortcutAction?.call(shortcut); + } catch (e) { + logError('$runtimeType::_handleOnIFrameKeyboardEvent: Exception = $e'); + } } @override void didUpdateWidget(covariant HtmlContentViewerOnWeb oldWidget) { super.didUpdateWidget(oldWidget); - log('_HtmlContentViewerOnWebState::didUpdateWidget():Old-Direction: ${oldWidget.direction} | Current-Direction: ${widget.direction}'); + log('$runtimeType::didUpdateWidget():Old-Direction: ${oldWidget.direction} | Current-Direction: ${widget.direction}'); if (widget.contentHtml != oldWidget.contentHtml || widget.direction != oldWidget.direction) { _setUpWeb(); @@ -311,6 +319,7 @@ class _HtmlContentViewerOnWebState extends State window.addEventListener('load', handleOnLoad); window.addEventListener('pagehide', (event) => { window.parent.removeEventListener('message', handleMessage, false); + window.removeEventListener('load', handleOnLoad); }); function handleMessage(e) { diff --git a/core/lib/utils/html/html_interaction.dart b/core/lib/utils/html/html_interaction.dart index 87a99abaa..0b33f01c7 100644 --- a/core/lib/utils/html/html_interaction.dart +++ b/core/lib/utils/html/html_interaction.dart @@ -286,7 +286,13 @@ class HtmlInteraction { }, { passive: false, }); - window.addEventListener('keydown', function(e) { + window.addEventListener('keydown', disableZoomControl); + + window.addEventListener('pagehide', (event) => { + window.removeEventListener('keydown', disableZoomControl); + }); + + function disableZoomControl(event) { if (event.metaKey || event.ctrlKey) { switch (event.key) { case '=': @@ -295,7 +301,7 @@ class HtmlInteraction { break; } } - }); + } '''; @@ -381,7 +387,13 @@ class HtmlInteraction { static String scriptHandleIframeKeyboardListener(String viewId) => ''' '''; } \ No newline at end of file