From 0f6874f8d7c98d3cc4bdb653b0b9191d0144e9ce Mon Sep 17 00:00:00 2001 From: nyne Date: Mon, 3 Mar 2025 20:50:11 +0800 Subject: [PATCH] Close reader when user click the close button on window frame. --- lib/components/window_frame.dart | 53 +++++++++++++++++++++++++++----- lib/pages/reader/reader.dart | 18 +++++++++++ 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/lib/components/window_frame.dart b/lib/components/window_frame.dart index 98b3db5..3453aed 100644 --- a/lib/components/window_frame.dart +++ b/lib/components/window_frame.dart @@ -17,9 +17,18 @@ class WindowFrameController extends InheritedWidget { /// Sets the visibility of the window frame. final void Function(bool) setWindowFrame; + /// Adds a listener that will be called when close button is clicked. + /// The listener should return `true` to allow the window to be closed. + final void Function(WindowCloseListener listener) addCloseListener; + + /// Removes a close listener. + final void Function(WindowCloseListener listener) removeCloseListener; + const WindowFrameController._create({ required this.isWindowFrameHidden, required this.setWindowFrame, + required this.addCloseListener, + required this.removeCloseListener, required super.child, }); @@ -42,16 +51,40 @@ class WindowFrame extends StatefulWidget { } } +typedef WindowCloseListener = bool Function(); + class _WindowFrameState extends State { bool isWindowFrameHidden = false; bool useDarkTheme = false; + var closeListeners = []; + /// Sets the visibility of the window frame. void setWindowFrame(bool show) { setState(() { isWindowFrameHidden = !show; }); } + /// Adds a listener that will be called when close button is clicked. + /// The listener should return `true` to allow the window to be closed. + void addCloseListener(WindowCloseListener listener) { + closeListeners.add(listener); + } + + /// Removes a close listener. + void removeCloseListener(WindowCloseListener listener) { + closeListeners.remove(listener); + } + + void _onClose() { + for (var listener in closeListeners) { + if (!listener()) { + return; + } + } + windowManager.close(); + } + @override Widget build(BuildContext context) { if (App.isMobile) return widget.child; @@ -114,7 +147,9 @@ class _WindowFrameState extends State { onPressed: debug, child: Text('Debug'), ), - if (!App.isMacOS) const WindowButtons() + if (!App.isMacOS) _WindowButtons( + onClose: _onClose, + ) ], ), ); @@ -132,19 +167,23 @@ class _WindowFrameState extends State { return WindowFrameController._create( isWindowFrameHidden: isWindowFrameHidden, setWindowFrame: setWindowFrame, + addCloseListener: addCloseListener, + removeCloseListener: removeCloseListener, child: body, ); } } -class WindowButtons extends StatefulWidget { - const WindowButtons({super.key}); +class _WindowButtons extends StatefulWidget { + const _WindowButtons({required this.onClose}); + + final void Function() onClose; @override - State createState() => _WindowButtonsState(); + State<_WindowButtons> createState() => _WindowButtonsState(); } -class _WindowButtonsState extends State with WindowListener { +class _WindowButtonsState extends State<_WindowButtons> with WindowListener { bool isMaximized = false; @override @@ -233,9 +272,7 @@ class _WindowButtonsState extends State with WindowListener { color: !dark ? Colors.white : Colors.black, ), hoverColor: Colors.red, - onPressed: () { - windowManager.close(); - }, + onPressed: widget.onClose, ) ], ), diff --git a/lib/pages/reader/reader.dart b/lib/pages/reader/reader.dart index 76aeba4..e2ff1e8 100644 --- a/lib/pages/reader/reader.dart +++ b/lib/pages/reader/reader.dart @@ -170,6 +170,7 @@ class _ReaderState extends State void didChangeDependencies() { super.didChangeDependencies(); initImagesPerPage(widget.initialPage ?? 1); + initReaderWindow(); } void setImageCacheSize() async { @@ -203,6 +204,7 @@ class _ReaderState extends State DataSync().onDataChanged(); }); PaintingBinding.instance.imageCache.maximumSizeBytes = 100 << 20; + disposeReaderWindow(); super.dispose(); } @@ -499,6 +501,13 @@ abstract mixin class _ReaderLocation { mixin class _ReaderWindow { bool isFullscreen = false; + late WindowFrameController windowFrame; + + void initReaderWindow() { + windowFrame = WindowFrame.of(App.rootContext); + windowFrame.addCloseListener(onWindowClose); + } + void fullscreen() async { await windowManager.hide(); await windowManager.setFullScreen(!isFullscreen); @@ -506,6 +515,15 @@ mixin class _ReaderWindow { isFullscreen = !isFullscreen; WindowFrame.of(App.rootContext).setWindowFrame(!isFullscreen); } + + bool onWindowClose() { + App.rootContext.pop(); + return false; + } + + void disposeReaderWindow() { + windowFrame.removeCloseListener(onWindowClose); + } } enum ReaderMode {