Skip to content

Commit

Permalink
Add system tray
Browse files Browse the repository at this point in the history
  • Loading branch information
narumi147 committed Feb 7, 2023
1 parent 1c32357 commit d2ea603
Show file tree
Hide file tree
Showing 26 changed files with 331 additions and 95 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/deploy-github-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
asset_extension: .zip
asset_content_type: application/zip
build_options:
- os: ubuntu-latest
- os: ubuntu-20.04
target: linux
build_target: linux
build_path: build/linux/x64/release/bundle
Expand Down Expand Up @@ -70,6 +70,7 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libx11-dev pkg-config cmake ninja-build libblkid-dev
sudo apt-get install -y appindicator3-0.1 libappindicator3-dev
- name: Install Android dependencies
if: matrix.target == 'android'
Expand Down
8 changes: 7 additions & 1 deletion lib/app/chaldea.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import '../packages/platform/platform.dart';
import 'app.dart';
import 'routes/parser.dart';
import 'tools/backup_backend/chaldea_backend.dart';
import 'tools/system_tray.dart';

class Chaldea extends StatefulWidget {
Chaldea({super.key});
Expand Down Expand Up @@ -159,6 +160,7 @@ class _ChaldeaState extends State<Chaldea> with AfterLayoutMixin {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
}
}
SystemTrayUtil.init();

if (db.settings.autoUpdateApp && !kIsWeb) {
await Future.delayed(const Duration(seconds: 5));
Expand All @@ -179,8 +181,12 @@ class _ChaldeaState extends State<Chaldea> with AfterLayoutMixin {
void setOnWindowClose() {
if (!PlatformU.isDesktop) return;
FlutterWindowClose.setWindowShouldCloseHandler(() async {
logger.i('closing desktop app...');
await db.saveAll();
if (db.settings.showSystemTray) {
SystemTrayUtil.appWindow.hide();
return false;
}
logger.i('closing desktop app...');
if (!db.settings.alertUploadUserData) {
await Future.delayed(const Duration(milliseconds: 200));
return true;
Expand Down
204 changes: 111 additions & 93 deletions lib/app/modules/home/subpage/display_setting_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';

import 'package:chaldea/app/app.dart';
import 'package:chaldea/app/tools/system_tray.dart';
import 'package:chaldea/generated/l10n.dart';
import 'package:chaldea/models/models.dart';
import 'package:chaldea/packages/app_info.dart';
Expand Down Expand Up @@ -40,106 +41,15 @@ class _DisplaySettingPageState extends State<DisplaySettingPage> {
body: ListView(
children: [
TileGroup(
header: 'App',
header: S.current.gallery_tab_name,
children: [
if (PlatformU.isMacOS || PlatformU.isWindows)
SwitchListTile.adaptive(
value: db.settings.alwaysOnTop,
title: Text(S.current.setting_always_on_top),
onChanged: (v) async {
db.settings.alwaysOnTop = v;
db.saveSettings();
MethodChannelChaldea.setAlwaysOnTop(v);
setState(() {});
},
),
SwitchListTile.adaptive(
value: db.settings.display.showWindowFab,
title: Text(S.current.display_show_window_fab),
onChanged: (v) async {
db.settings.display.showWindowFab = v;
db.saveSettings();
if (v) {
WindowManagerFab.createOverlay(context);
} else {
WindowManagerFab.removeOverlay();
}
setState(() {});
},
),
SwitchListTile.adaptive(
value: db.settings.showDebugFab,
title: Text(S.current.debug_fab),
subtitle: Text('${S.current.screenshots} etc.'),
onChanged: (v) {
setState(() {
db.settings.showDebugFab = v;
db.saveSettings();
});
if (v) {
DebugFab.createOverlay(context);
} else {
DebugFab.removeOverlay();
}
},
),
// only show on mobile phone, not desktop and tablet
// on Android, cannot detect phone or mobile
if (PlatformU.isMobile && !AppInfo.isIPad || kDebugMode)
SwitchListTile.adaptive(
value: db.settings.autoRotate,
title: Text(S.current.setting_auto_rotate),
onChanged: (v) {
setState(() {
db.settings.autoRotate = v;
if (v) {
SystemChrome.setPreferredOrientations([]);
} else {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp]);
}
});
db.notifyAppUpdate();
},
),
if (PlatformU.isTargetDesktop)
SwitchListTile.adaptive(
value: db.settings.enableMouseDrag,
title: Text(S.current.setting_drag_by_mouse),
subtitle: Text(S.current.desktop_only),
onChanged: (v) {
setState(() {
db.settings.enableMouseDrag = v;
});
db.notifyAppUpdate();
},
),
SwitchListTile.adaptive(
value: db.settings.globalSelection,
title: Text(S.current.global_text_selection),
// subtitle: Text(S.current.desktop_only),
onChanged: (v) {
setState(() {
db.settings.globalSelection = v;
});
db.notifyAppUpdate();
},
),
ListTile(
title: Text(S.current.carousel_setting),
trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () {
router.pushPage(const CarouselSettingPage());
},
),
ListTile(
title: Text(S.current.setting_split_ratio),
subtitle: Text(S.current.setting_split_ratio_hint),
trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () {
router.pushPage(MasterRatioSetting());
},
),
SwitchListTile.adaptive(
value: db.settings.display.showAccountAtHome,
title: Text(S.current.setting_show_account_at_homepage),
Expand All @@ -151,6 +61,14 @@ class _DisplaySettingPageState extends State<DisplaySettingPage> {
db.notifyUserdata();
},
),
ListTile(
title: Text(S.current.setting_split_ratio),
subtitle: Text(S.current.setting_split_ratio_hint),
trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () {
router.pushPage(MasterRatioSetting());
},
),
],
),
TileGroup(
Expand Down Expand Up @@ -356,7 +274,107 @@ class _DisplaySettingPageState extends State<DisplaySettingPage> {
),
),
],
)
),
TileGroup(
header: 'App',
children: [
if (PlatformU.isMacOS || PlatformU.isWindows)
SwitchListTile.adaptive(
value: db.settings.alwaysOnTop,
title: Text(S.current.setting_always_on_top),
onChanged: (v) async {
db.settings.alwaysOnTop = v;
db.saveSettings();
MethodChannelChaldea.setAlwaysOnTop(v);
setState(() {});
},
),
SwitchListTile.adaptive(
value: db.settings.display.showWindowFab,
title: Text(S.current.display_show_window_fab),
onChanged: (v) async {
db.settings.display.showWindowFab = v;
db.saveSettings();
if (v) {
WindowManagerFab.createOverlay(context);
} else {
WindowManagerFab.removeOverlay();
}
setState(() {});
},
),
SwitchListTile.adaptive(
value: db.settings.showDebugFab,
title: Text(S.current.debug_fab),
subtitle: Text('${S.current.screenshots} etc.'),
onChanged: (v) {
setState(() {
db.settings.showDebugFab = v;
db.saveSettings();
});
if (v) {
DebugFab.createOverlay(context);
} else {
DebugFab.removeOverlay();
}
},
),
// only show on mobile phone, not desktop and tablet
// on Android, cannot detect phone or mobile
if (PlatformU.isMobile && !AppInfo.isIPad || kDebugMode)
SwitchListTile.adaptive(
value: db.settings.autoRotate,
title: Text(S.current.setting_auto_rotate),
onChanged: (v) {
setState(() {
db.settings.autoRotate = v;
if (v) {
SystemChrome.setPreferredOrientations([]);
} else {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp]);
}
});
db.notifyAppUpdate();
},
),
if (PlatformU.isTargetDesktop)
SwitchListTile.adaptive(
value: db.settings.enableMouseDrag,
title: Text(S.current.setting_drag_by_mouse),
subtitle: Text(S.current.desktop_only),
onChanged: (v) {
setState(() {
db.settings.enableMouseDrag = v;
});
db.notifyAppUpdate();
},
),
if (PlatformU.isDesktop)
SwitchListTile.adaptive(
value: db.settings.showSystemTray,
title: Text(S.current.show_system_tray),
subtitle: Text(S.current.system_tray_close_hint),
onChanged: (v) {
setState(() {
db.settings.showSystemTray = v;
});
SystemTrayUtil.toggle(v);
},
),
SwitchListTile.adaptive(
value: db.settings.globalSelection,
title: Text(S.current.global_text_selection),
// subtitle: Text(S.current.desktop_only),
onChanged: (v) {
setState(() {
db.settings.globalSelection = v;
});
db.notifyAppUpdate();
},
),
],
),
],
),
);
Expand Down
71 changes: 71 additions & 0 deletions lib/app/tools/system_tray.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import 'package:flutter/material.dart';

import 'package:system_tray/system_tray.dart';

import 'package:chaldea/generated/l10n.dart';
import 'package:chaldea/models/db.dart';
import 'package:chaldea/packages/app_info.dart';
import 'package:chaldea/packages/platform/platform.dart';
import 'package:chaldea/utils/constants.dart';

class SystemTrayUtil {
const SystemTrayUtil._();
static final AppWindow appWindow = AppWindow();
static final SystemTray _systemTray = SystemTray();
static final Menu _menuMain = Menu();

static bool _installed = false;

static String _getIcon() {
String name = PlatformU.isWindows ? 'app_icon.ico' : 'app_icon_rounded.png';
return 'res/img/launcher_icon/$name';
}

static Future<void> toggle([bool? value]) {
if (value != null) {
return value ? init() : destroy();
} else {
return _installed ? destroy() : init();
}
}

static Future<void> destroy() async {
if (_installed) {
_installed = false;
return _systemTray.destroy();
}
}

static Future<void> init() async {
if (!PlatformU.isDesktop) return;
await _systemTray.initSystemTray(iconPath: _getIcon());
// _systemTray.setTitle(kAppName);
_systemTray.registerSystemTrayEventHandler((eventName) {
debugPrint("eventName: $eventName");
if (eventName == kSystemTrayEventClick) {
PlatformU.isWindows ? appWindow.show() : _systemTray.popUpContextMenu();
} else if (eventName == kSystemTrayEventRightClick) {
PlatformU.isWindows ? _systemTray.popUpContextMenu() : appWindow.show();
}
});

await _menuMain.buildFrom([
MenuItemLabel(
label: '$kAppName v${AppInfo.versionString}', enabled: false),
MenuSeparator(),
MenuItemLabel(
label: S.current.show, onClicked: (menuItem) => appWindow.show()),
MenuItemLabel(
label: S.current.hide, onClicked: (menuItem) => appWindow.hide()),
MenuItemLabel(
label: S.current.quit,
onClicked: (menuItem) async {
await db.saveAll();
appWindow.close();
},
),
]);
_systemTray.setContextMenu(_menuMain);
_installed = true;
}
}
Loading

0 comments on commit d2ea603

Please sign in to comment.