♻️ Refactor tray with manager

This commit is contained in:
2025-02-04 16:11:25 +08:00
parent efef61a8ea
commit 85e48ce03b
13 changed files with 113 additions and 55 deletions

View File

@@ -42,10 +42,10 @@ import 'package:surface/types/chat.dart';
import 'package:surface/types/realm.dart';
import 'package:flutter_web_plugins/url_strategy.dart' show usePathUrlStrategy;
import 'package:surface/widgets/dialog.dart';
import 'package:tray_manager/tray_manager.dart';
import 'package:version/version.dart';
import 'package:workmanager/workmanager.dart';
import 'package:in_app_review/in_app_review.dart';
import 'package:system_tray/system_tray.dart';
@pragma('vm:entry-point')
void appBackgroundDispatcher() {
@@ -209,7 +209,7 @@ class _AppSplashScreen extends StatefulWidget {
State<_AppSplashScreen> createState() => _AppSplashScreenState();
}
class _AppSplashScreenState extends State<_AppSplashScreen> {
class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
void _tryRequestRating() async {
final prefs = await SharedPreferences.getInstance();
if (prefs.containsKey('first_boot_time')) {
@@ -301,32 +301,26 @@ class _AppSplashScreenState extends State<_AppSplashScreen> {
if (kIsWeb || Platform.isAndroid || Platform.isIOS) return;
final icon = Platform.isWindows ? 'assets/icon/tray-icon.ico' : 'assets/icon/tray-icon.png';
final SystemTray systemTray = SystemTray();
final appVersion = await PackageInfo.fromPlatform();
await systemTray.initSystemTray(
title: "",
iconPath: icon,
trayManager.addListener(this);
await trayManager.setIcon(icon);
Menu menu = Menu(
items: [
MenuItem(
key: 'version_label',
label: 'Solian ${appVersion.version}+${appVersion.buildNumber}',
disabled: true,
),
MenuItem.separator(),
MenuItem(
key: 'exit',
label: 'trayMenuExit'.tr(),
),
],
);
await systemTray.setContextMenu([
MenuItem(label: 'trayMenuShow'.tr(), onClicked: () => appWindow.show()),
MenuItem(label: 'trayMenuHide'.tr(), onClicked: () => appWindow.hide()),
MenuItem(
label: 'trayMenuExit'.tr(),
onClicked: () {
_appLifecycleListener?.dispose();
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
},
),
]);
systemTray.registerSystemTrayEventHandler((eventName) {
if (eventName == "leftMouseDown") {
Platform.isWindows ? appWindow.show() : systemTray.popUpContextMenu();
} else if (eventName == "rightMouseDown") {
Platform.isWindows ? systemTray.popUpContextMenu() : appWindow.show();
}
});
await trayManager.setContextMenu(menu);
}
AppLifecycleListener? _appLifecycleListener;
@@ -354,6 +348,40 @@ class _AppSplashScreenState extends State<_AppSplashScreen> {
return AppExitResponse.cancel;
}
@override
void onTrayIconMouseDown() {
if (Platform.isWindows) {
appWindow.show();
} else {
trayManager.popUpContextMenu();
}
}
@override
void onTrayIconRightMouseDown() {
if (Platform.isWindows) {
trayManager.popUpContextMenu();
} else {
appWindow.show();
}
}
@override
void onTrayMenuItemClick(MenuItem menuItem) {
switch (menuItem.key) {
case 'exit':
_appLifecycleListener?.dispose();
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
break;
}
}
@override
void dispose() {
if (!kIsWeb && !(Platform.isAndroid || Platform.isIOS)) trayManager.removeListener(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
final cfg = context.read<ConfigProvider>();

View File

@@ -12,6 +12,7 @@ import 'package:surface/providers/sn_network.dart';
import 'package:surface/providers/userinfo.dart';
import 'package:surface/providers/websocket.dart';
import 'package:surface/types/notification.dart';
import 'package:tray_manager/tray_manager.dart';
class NotificationProvider extends ChangeNotifier {
late final SnNetworkProvider _sn;
@@ -86,14 +87,26 @@ class NotificationProvider extends ChangeNotifier {
notifyListeners();
});
notifyListeners();
updateTray();
final doHaptic = _cfg.prefs.getBool(kAppNotifyWithHaptic) ?? true;
if (doHaptic) HapticFeedback.mediumImpact();
}
});
}
void updateTray() {
if (kIsWeb || Platform.isAndroid || Platform.isIOS) return;
if (notifications.isEmpty) {
trayManager.setTitle('');
} else {
trayManager.setTitle(' ${notifications.length.toString()}');
}
}
void clear() {
showingCount = 0;
notifications.clear();
updateTray();
notifyListeners();
}
}

View File

@@ -7,6 +7,7 @@ import 'package:material_symbols_icons/symbols.dart';
import 'package:provider/provider.dart';
import 'package:relative_time/relative_time.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:surface/providers/notification.dart';
import 'package:surface/providers/sn_network.dart';
import 'package:surface/types/notification.dart';
import 'package:surface/types/post.dart';
@@ -54,6 +55,7 @@ class _NotificationScreenState extends State<NotificationScreen> {
try {
final sn = context.read<SnNetworkProvider>();
final nty = context.read<NotificationProvider>();
final resp = await sn.client.get('/cgi/id/notifications?take=10');
_totalCount = resp.data['count'];
_notifications.addAll(
@@ -62,6 +64,7 @@ class _NotificationScreenState extends State<NotificationScreen> {
.cast<SnNotification>() ??
[],
);
nty.updateTray();
} catch (err) {
if (!mounted) return;
context.showErrorDialog(err);
@@ -88,9 +91,11 @@ class _NotificationScreenState extends State<NotificationScreen> {
try {
final sn = context.read<SnNetworkProvider>();
final nty = context.read<NotificationProvider>();
final resp = await sn.client.put('/cgi/id/notifications/read/all');
_notifications.clear();
_fetchNotifications();
nty.clear();
if (!mounted) return;
context.showSnackbar(