Close reader when user click the close button on window frame.

This commit is contained in:
2025-03-03 20:50:11 +08:00
parent 4af15b9139
commit 0f6874f8d7
2 changed files with 63 additions and 8 deletions

View File

@@ -17,9 +17,18 @@ class WindowFrameController extends InheritedWidget {
/// Sets the visibility of the window frame. /// Sets the visibility of the window frame.
final void Function(bool) setWindowFrame; 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({ const WindowFrameController._create({
required this.isWindowFrameHidden, required this.isWindowFrameHidden,
required this.setWindowFrame, required this.setWindowFrame,
required this.addCloseListener,
required this.removeCloseListener,
required super.child, required super.child,
}); });
@@ -42,16 +51,40 @@ class WindowFrame extends StatefulWidget {
} }
} }
typedef WindowCloseListener = bool Function();
class _WindowFrameState extends State<WindowFrame> { class _WindowFrameState extends State<WindowFrame> {
bool isWindowFrameHidden = false; bool isWindowFrameHidden = false;
bool useDarkTheme = false; bool useDarkTheme = false;
var closeListeners = <WindowCloseListener>[];
/// Sets the visibility of the window frame.
void setWindowFrame(bool show) { void setWindowFrame(bool show) {
setState(() { setState(() {
isWindowFrameHidden = !show; 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (App.isMobile) return widget.child; if (App.isMobile) return widget.child;
@@ -114,7 +147,9 @@ class _WindowFrameState extends State<WindowFrame> {
onPressed: debug, onPressed: debug,
child: Text('Debug'), child: Text('Debug'),
), ),
if (!App.isMacOS) const WindowButtons() if (!App.isMacOS) _WindowButtons(
onClose: _onClose,
)
], ],
), ),
); );
@@ -132,19 +167,23 @@ class _WindowFrameState extends State<WindowFrame> {
return WindowFrameController._create( return WindowFrameController._create(
isWindowFrameHidden: isWindowFrameHidden, isWindowFrameHidden: isWindowFrameHidden,
setWindowFrame: setWindowFrame, setWindowFrame: setWindowFrame,
addCloseListener: addCloseListener,
removeCloseListener: removeCloseListener,
child: body, child: body,
); );
} }
} }
class WindowButtons extends StatefulWidget { class _WindowButtons extends StatefulWidget {
const WindowButtons({super.key}); const _WindowButtons({required this.onClose});
final void Function() onClose;
@override @override
State<WindowButtons> createState() => _WindowButtonsState(); State<_WindowButtons> createState() => _WindowButtonsState();
} }
class _WindowButtonsState extends State<WindowButtons> with WindowListener { class _WindowButtonsState extends State<_WindowButtons> with WindowListener {
bool isMaximized = false; bool isMaximized = false;
@override @override
@@ -233,9 +272,7 @@ class _WindowButtonsState extends State<WindowButtons> with WindowListener {
color: !dark ? Colors.white : Colors.black, color: !dark ? Colors.white : Colors.black,
), ),
hoverColor: Colors.red, hoverColor: Colors.red,
onPressed: () { onPressed: widget.onClose,
windowManager.close();
},
) )
], ],
), ),

View File

@@ -170,6 +170,7 @@ class _ReaderState extends State<Reader>
void didChangeDependencies() { void didChangeDependencies() {
super.didChangeDependencies(); super.didChangeDependencies();
initImagesPerPage(widget.initialPage ?? 1); initImagesPerPage(widget.initialPage ?? 1);
initReaderWindow();
} }
void setImageCacheSize() async { void setImageCacheSize() async {
@@ -203,6 +204,7 @@ class _ReaderState extends State<Reader>
DataSync().onDataChanged(); DataSync().onDataChanged();
}); });
PaintingBinding.instance.imageCache.maximumSizeBytes = 100 << 20; PaintingBinding.instance.imageCache.maximumSizeBytes = 100 << 20;
disposeReaderWindow();
super.dispose(); super.dispose();
} }
@@ -499,6 +501,13 @@ abstract mixin class _ReaderLocation {
mixin class _ReaderWindow { mixin class _ReaderWindow {
bool isFullscreen = false; bool isFullscreen = false;
late WindowFrameController windowFrame;
void initReaderWindow() {
windowFrame = WindowFrame.of(App.rootContext);
windowFrame.addCloseListener(onWindowClose);
}
void fullscreen() async { void fullscreen() async {
await windowManager.hide(); await windowManager.hide();
await windowManager.setFullScreen(!isFullscreen); await windowManager.setFullScreen(!isFullscreen);
@@ -506,6 +515,15 @@ mixin class _ReaderWindow {
isFullscreen = !isFullscreen; isFullscreen = !isFullscreen;
WindowFrame.of(App.rootContext).setWindowFrame(!isFullscreen); WindowFrame.of(App.rootContext).setWindowFrame(!isFullscreen);
} }
bool onWindowClose() {
App.rootContext.pop();
return false;
}
void disposeReaderWindow() {
windowFrame.removeCloseListener(onWindowClose);
}
} }
enum ReaderMode { enum ReaderMode {