mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
fix: doesn't minimize to tray when system title bar close button is used #866
This commit is contained in:
parent
5f1df5a87d
commit
bb8f250f5f
@ -11,16 +11,6 @@ import 'dart:io' show Platform, exit;
|
|||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
||||||
import 'package:local_notifier/local_notifier.dart';
|
import 'package:local_notifier/local_notifier.dart';
|
||||||
|
|
||||||
final closeNotification = DesktopTools.createNotification(
|
|
||||||
title: 'Spotube',
|
|
||||||
message: 'Running in background. Minimized to System Tray',
|
|
||||||
actions: [
|
|
||||||
LocalNotificationAction(text: 'Close The App'),
|
|
||||||
],
|
|
||||||
)?..onClickAction = (value) {
|
|
||||||
exit(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
class PageWindowTitleBar extends StatefulHookConsumerWidget
|
class PageWindowTitleBar extends StatefulHookConsumerWidget
|
||||||
implements PreferredSizeWidget {
|
implements PreferredSizeWidget {
|
||||||
final Widget? leading;
|
final Widget? leading;
|
||||||
@ -113,12 +103,7 @@ class WindowTitleBarButtons extends HookConsumerWidget {
|
|||||||
const type = ThemeType.auto;
|
const type = ThemeType.auto;
|
||||||
|
|
||||||
Future<void> onClose() async {
|
Future<void> onClose() async {
|
||||||
if (preferences.closeBehavior == CloseBehavior.close) {
|
await DesktopTools.window.close();
|
||||||
exit(0);
|
|
||||||
} else {
|
|
||||||
await DesktopTools.window.hide();
|
|
||||||
await closeNotification?.show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
|
32
lib/hooks/configurators/use_close_behavior.dart
Normal file
32
lib/hooks/configurators/use_close_behavior.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:spotube/hooks/configurators/use_window_listener.dart';
|
||||||
|
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
||||||
|
import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
|
||||||
|
import 'package:local_notifier/local_notifier.dart';
|
||||||
|
|
||||||
|
final closeNotification = DesktopTools.createNotification(
|
||||||
|
title: 'Spotube',
|
||||||
|
message: 'Running in background. Minimized to System Tray',
|
||||||
|
actions: [
|
||||||
|
LocalNotificationAction(text: 'Close The App'),
|
||||||
|
],
|
||||||
|
)?..onClickAction = (value) {
|
||||||
|
exit(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
void useCloseBehavior(WidgetRef ref) {
|
||||||
|
useWindowListener(
|
||||||
|
onWindowClose: () async {
|
||||||
|
final preferences = ref.read(userPreferencesProvider);
|
||||||
|
if (preferences.closeBehavior == CloseBehavior.minimizeToTray) {
|
||||||
|
await DesktopTools.window.hide();
|
||||||
|
closeNotification?.show();
|
||||||
|
} else {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
197
lib/hooks/configurators/use_window_listener.dart
Normal file
197
lib/hooks/configurators/use_window_listener.dart
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
|
||||||
|
class CallbackWindowListener implements WindowListener {
|
||||||
|
final VoidCallback? _onWindowClose;
|
||||||
|
final VoidCallback? _onWindowFocus;
|
||||||
|
final VoidCallback? _onWindowBlur;
|
||||||
|
final VoidCallback? _onWindowMaximize;
|
||||||
|
final VoidCallback? _onWindowUnmaximize;
|
||||||
|
final VoidCallback? _onWindowMinimize;
|
||||||
|
final VoidCallback? _onWindowRestore;
|
||||||
|
final VoidCallback? _onWindowResize;
|
||||||
|
final VoidCallback? _onWindowResized;
|
||||||
|
final VoidCallback? _onWindowMove;
|
||||||
|
final VoidCallback? _onWindowMoved;
|
||||||
|
final VoidCallback? _onWindowEnterFullScreen;
|
||||||
|
final VoidCallback? _onWindowLeaveFullScreen;
|
||||||
|
final VoidCallback? _onWindowDocked;
|
||||||
|
final VoidCallback? _onWindowUndocked;
|
||||||
|
final VoidCallback? _onWindowEvent;
|
||||||
|
|
||||||
|
const CallbackWindowListener({
|
||||||
|
VoidCallback? onWindowClose,
|
||||||
|
VoidCallback? onWindowFocus,
|
||||||
|
VoidCallback? onWindowBlur,
|
||||||
|
VoidCallback? onWindowMaximize,
|
||||||
|
VoidCallback? onWindowUnmaximize,
|
||||||
|
VoidCallback? onWindowMinimize,
|
||||||
|
VoidCallback? onWindowRestore,
|
||||||
|
VoidCallback? onWindowResize,
|
||||||
|
VoidCallback? onWindowResized,
|
||||||
|
VoidCallback? onWindowMove,
|
||||||
|
VoidCallback? onWindowMoved,
|
||||||
|
VoidCallback? onWindowEnterFullScreen,
|
||||||
|
VoidCallback? onWindowLeaveFullScreen,
|
||||||
|
VoidCallback? onWindowDocked,
|
||||||
|
VoidCallback? onWindowUndocked,
|
||||||
|
VoidCallback? onWindowEvent,
|
||||||
|
}) : _onWindowClose = onWindowClose,
|
||||||
|
_onWindowFocus = onWindowFocus,
|
||||||
|
_onWindowBlur = onWindowBlur,
|
||||||
|
_onWindowMaximize = onWindowMaximize,
|
||||||
|
_onWindowUnmaximize = onWindowUnmaximize,
|
||||||
|
_onWindowMinimize = onWindowMinimize,
|
||||||
|
_onWindowRestore = onWindowRestore,
|
||||||
|
_onWindowResize = onWindowResize,
|
||||||
|
_onWindowResized = onWindowResized,
|
||||||
|
_onWindowMove = onWindowMove,
|
||||||
|
_onWindowMoved = onWindowMoved,
|
||||||
|
_onWindowEnterFullScreen = onWindowEnterFullScreen,
|
||||||
|
_onWindowLeaveFullScreen = onWindowLeaveFullScreen,
|
||||||
|
_onWindowDocked = onWindowDocked,
|
||||||
|
_onWindowUndocked = onWindowUndocked,
|
||||||
|
_onWindowEvent = onWindowEvent;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowBlur() {
|
||||||
|
return _onWindowBlur?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowClose() {
|
||||||
|
return _onWindowClose?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowDocked() {
|
||||||
|
return _onWindowDocked?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowEnterFullScreen() {
|
||||||
|
return _onWindowEnterFullScreen?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowEvent(String eventName) {
|
||||||
|
return _onWindowEvent?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowFocus() {
|
||||||
|
return _onWindowFocus?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowLeaveFullScreen() {
|
||||||
|
return _onWindowLeaveFullScreen?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowMaximize() {
|
||||||
|
return _onWindowMaximize?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowMinimize() {
|
||||||
|
return _onWindowMinimize?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowMove() {
|
||||||
|
return _onWindowMove?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowMoved() {
|
||||||
|
return _onWindowMoved?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowResize() {
|
||||||
|
return _onWindowResize?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowResized() {
|
||||||
|
return _onWindowResized?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowRestore() {
|
||||||
|
return _onWindowRestore?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowUndocked() {
|
||||||
|
return _onWindowUndocked?.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowUnmaximize() {
|
||||||
|
return _onWindowUnmaximize?.call();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void useWindowListener({
|
||||||
|
VoidCallback? onWindowClose,
|
||||||
|
VoidCallback? onWindowFocus,
|
||||||
|
VoidCallback? onWindowBlur,
|
||||||
|
VoidCallback? onWindowMaximize,
|
||||||
|
VoidCallback? onWindowUnmaximize,
|
||||||
|
VoidCallback? onWindowMinimize,
|
||||||
|
VoidCallback? onWindowRestore,
|
||||||
|
VoidCallback? onWindowResize,
|
||||||
|
VoidCallback? onWindowResized,
|
||||||
|
VoidCallback? onWindowMove,
|
||||||
|
VoidCallback? onWindowMoved,
|
||||||
|
VoidCallback? onWindowEnterFullScreen,
|
||||||
|
VoidCallback? onWindowLeaveFullScreen,
|
||||||
|
VoidCallback? onWindowDocked,
|
||||||
|
VoidCallback? onWindowUndocked,
|
||||||
|
VoidCallback? onWindowEvent,
|
||||||
|
}) {
|
||||||
|
useEffect(() {
|
||||||
|
final listener = CallbackWindowListener(
|
||||||
|
onWindowClose: onWindowClose,
|
||||||
|
onWindowFocus: onWindowFocus,
|
||||||
|
onWindowBlur: onWindowBlur,
|
||||||
|
onWindowMaximize: onWindowMaximize,
|
||||||
|
onWindowUnmaximize: onWindowUnmaximize,
|
||||||
|
onWindowMinimize: onWindowMinimize,
|
||||||
|
onWindowRestore: onWindowRestore,
|
||||||
|
onWindowResize: onWindowResize,
|
||||||
|
onWindowResized: onWindowResized,
|
||||||
|
onWindowMove: onWindowMove,
|
||||||
|
onWindowMoved: onWindowMoved,
|
||||||
|
onWindowEnterFullScreen: onWindowEnterFullScreen,
|
||||||
|
onWindowLeaveFullScreen: onWindowLeaveFullScreen,
|
||||||
|
onWindowDocked: onWindowDocked,
|
||||||
|
onWindowUndocked: onWindowUndocked,
|
||||||
|
onWindowEvent: onWindowEvent,
|
||||||
|
);
|
||||||
|
DesktopTools.window.addListener(listener);
|
||||||
|
return () {
|
||||||
|
DesktopTools.window.removeListener(listener);
|
||||||
|
};
|
||||||
|
}, [
|
||||||
|
onWindowClose,
|
||||||
|
onWindowFocus,
|
||||||
|
onWindowBlur,
|
||||||
|
onWindowMaximize,
|
||||||
|
onWindowUnmaximize,
|
||||||
|
onWindowMinimize,
|
||||||
|
onWindowRestore,
|
||||||
|
onWindowResize,
|
||||||
|
onWindowResized,
|
||||||
|
onWindowMove,
|
||||||
|
onWindowMoved,
|
||||||
|
onWindowEnterFullScreen,
|
||||||
|
onWindowLeaveFullScreen,
|
||||||
|
onWindowDocked,
|
||||||
|
onWindowUndocked,
|
||||||
|
onWindowEvent,
|
||||||
|
]);
|
||||||
|
}
|
@ -15,6 +15,7 @@ import 'package:metadata_god/metadata_god.dart';
|
|||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:spotube/collections/routes.dart';
|
import 'package:spotube/collections/routes.dart';
|
||||||
import 'package:spotube/collections/intents.dart';
|
import 'package:spotube/collections/intents.dart';
|
||||||
|
import 'package:spotube/hooks/configurators/use_close_behavior.dart';
|
||||||
import 'package:spotube/hooks/configurators/use_disable_battery_optimizations.dart';
|
import 'package:spotube/hooks/configurators/use_disable_battery_optimizations.dart';
|
||||||
import 'package:spotube/hooks/configurators/use_get_storage_perms.dart';
|
import 'package:spotube/hooks/configurators/use_get_storage_perms.dart';
|
||||||
import 'package:spotube/l10n/l10n.dart';
|
import 'package:spotube/l10n/l10n.dart';
|
||||||
@ -49,6 +50,10 @@ Future<void> main(List<String> rawArgs) async {
|
|||||||
await FlutterDisplayMode.setHighRefreshRate();
|
await FlutterDisplayMode.setHighRefreshRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DesktopTools.platform.isDesktop) {
|
||||||
|
await DesktopTools.window.setPreventClose(true);
|
||||||
|
}
|
||||||
|
|
||||||
await DesktopTools.ensureInitialized(
|
await DesktopTools.ensureInitialized(
|
||||||
DesktopWindowOptions(
|
DesktopWindowOptions(
|
||||||
hideTitleBar: true,
|
hideTitleBar: true,
|
||||||
@ -177,6 +182,7 @@ class SpotubeState extends ConsumerState<Spotube> {
|
|||||||
ref.watch(paletteProvider.select((s) => s?.dominantColor?.color));
|
ref.watch(paletteProvider.select((s) => s?.dominantColor?.color));
|
||||||
|
|
||||||
useInitSysTray(ref);
|
useInitSysTray(ref);
|
||||||
|
useCloseBehavior(ref);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
FlutterNativeSplash.remove();
|
FlutterNativeSplash.remove();
|
||||||
|
Loading…
Reference in New Issue
Block a user