diff --git a/.github/workflows/auth-release.yml b/.github/workflows/auth-release.yml index 7f56f12203..1f70fc9c6c 100644 --- a/.github/workflows/auth-release.yml +++ b/.github/workflows/auth-release.yml @@ -83,7 +83,7 @@ jobs: - name: Install dependencies for desktop build run: | sudo apt-get update -y - sudo apt-get install -y libsecret-1-dev libsodium-dev libwebkit2gtk-4.0-dev libfuse2 ninja-build libgtk-3-dev dpkg-dev pkg-config rpm libsqlite3-dev locate + sudo apt-get install -y libsecret-1-dev libsodium-dev libwebkit2gtk-4.0-dev libfuse2 ninja-build libgtk-3-dev dpkg-dev pkg-config rpm libsqlite3-dev locate appindicator3-0.1 libappindicator3-dev - name: Install appimagetool run: | diff --git a/auth/assets/icon-light.ico b/auth/assets/icon-light.ico new file mode 100644 index 0000000000..6f45f522b6 Binary files /dev/null and b/auth/assets/icon-light.ico differ diff --git a/auth/lib/app/view/app.dart b/auth/lib/app/view/app.dart index 1d3d99017a..2ca5e4b3ee 100644 --- a/auth/lib/app/view/app.dart +++ b/auth/lib/app/view/app.dart @@ -18,6 +18,7 @@ import 'package:ente_auth/ui/settings/app_update_dialog.dart'; import 'package:flutter/foundation.dart'; import "package:flutter/material.dart"; import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:system_tray/system_tray.dart'; import 'package:window_manager/window_manager.dart'; class App extends StatefulWidget { @@ -43,9 +44,14 @@ class _AppState extends State with WindowListener { }); } + Future initWindowManager() async { + windowManager.addListener(this); + await windowManager.setPreventClose(true); + } + @override void initState() { - windowManager.addListener(this); + initWindowManager(); _signedOutEvent = Bus.instance.on().listen((event) { if (mounted) { setState(() {}); @@ -139,6 +145,12 @@ class _AppState extends State with WindowListener { }; } + @override + void onWindowClose() async { + final AppWindow appWindow = AppWindow(); + await appWindow.hide(); + } + @override void onWindowResize() { WindowListenerService.instance.onWindowResize().ignore(); diff --git a/auth/lib/main.dart b/auth/lib/main.dart index 7cab45651a..ab843f3d3b 100644 --- a/auth/lib/main.dart +++ b/auth/lib/main.dart @@ -31,13 +31,50 @@ import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:logging/logging.dart'; import 'package:path_provider/path_provider.dart'; import 'package:privacy_screen/privacy_screen.dart'; +import 'package:system_tray/system_tray.dart'; import 'package:window_manager/window_manager.dart'; final _logger = Logger("main"); +Future initSystemTray() async { + String path = + Platform.isWindows ? 'assets/icon-light.ico' : 'assets/icon-light.png'; + + final AppWindow appWindow = AppWindow(); + final SystemTray systemTray = SystemTray(); + + // We first init the systray menu + await systemTray.initSystemTray( + title: "", + iconPath: path, + ); + + // create context menu + final show = MenuItem(label: 'Show', onClicked: () => appWindow.show()); + final hide = MenuItem(label: 'Hide', onClicked: () => appWindow.hide()); + final exit = MenuItem(label: 'Exit', onClicked: () => appWindow.close()); + + // set context menu + await systemTray.setContextMenu([show, hide, exit]); + + const kSystemTrayEventClick = 'leftMouseDown'; + const kSystemTrayEventRightClick = 'rightMouseDown'; + // // handle system tray event + systemTray.registerSystemTrayEventHandler((eventName) { + debugPrint("eventName: $eventName"); + if (eventName == kSystemTrayEventClick) { + Platform.isWindows ? appWindow.show() : systemTray.popUpContextMenu(); + } else if (eventName == kSystemTrayEventRightClick) { + Platform.isWindows ? systemTray.popUpContextMenu() : appWindow.show(); + } + }); +} + void main() async { WidgetsFlutterBinding.ensureInitialized(); + initSystemTray().ignore(); + if (PlatformUtil.isDesktop()) { await windowManager.ensureInitialized(); await WindowListenerService.instance.init(); diff --git a/auth/linux/flutter/generated_plugin_registrant.cc b/auth/linux/flutter/generated_plugin_registrant.cc index 0ed133fb11..0bbf397b00 100644 --- a/auth/linux/flutter/generated_plugin_registrant.cc +++ b/auth/linux/flutter/generated_plugin_registrant.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin"); sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar); + g_autoptr(FlPluginRegistrar) system_tray_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "SystemTrayPlugin"); + system_tray_plugin_register_with_registrar(system_tray_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/auth/linux/flutter/generated_plugins.cmake b/auth/linux/flutter/generated_plugins.cmake index 71d04ad88a..0f2c32b0a4 100644 --- a/auth/linux/flutter/generated_plugins.cmake +++ b/auth/linux/flutter/generated_plugins.cmake @@ -13,6 +13,7 @@ list(APPEND FLUTTER_PLUGIN_LIST smart_auth sodium_libs sqlite3_flutter_libs + system_tray url_launcher_linux window_manager ) diff --git a/auth/linux/packaging/appimage/make_config.yaml b/auth/linux/packaging/appimage/make_config.yaml index a2041fda42..39d925e0b9 100644 --- a/auth/linux/packaging/appimage/make_config.yaml +++ b/auth/linux/packaging/appimage/make_config.yaml @@ -7,7 +7,7 @@ keywords: - Authentication - 2FA -generic_name: Ente Authentication +generic_name: ente Auth categories: - Utility diff --git a/auth/linux/packaging/deb/make_config.yaml b/auth/linux/packaging/deb/make_config.yaml index 65ae3bd656..28f1dfe2ba 100644 --- a/auth/linux/packaging/deb/make_config.yaml +++ b/auth/linux/packaging/deb/make_config.yaml @@ -15,6 +15,9 @@ dependencies: - libsqlite3-0 - libsodium23 - libsecret-1-0 + - libappindicator3-1 | libayatana-appindicator3-1 + - gir1.2-appindicator3-0.1 | gir1.2-ayatanaappindicator3-0.1 + - libayatana-ido3-0.4-0 keywords: - Authentication diff --git a/auth/linux/packaging/rpm/make_config.yaml b/auth/linux/packaging/rpm/make_config.yaml index 6fd8412ea9..8427e9aa98 100644 --- a/auth/linux/packaging/rpm/make_config.yaml +++ b/auth/linux/packaging/rpm/make_config.yaml @@ -14,6 +14,7 @@ dependencies: - webkit2gtk-4.0 - libsodium - libsecret + - libappindicator keywords: - Authentication diff --git a/auth/macos/Flutter/GeneratedPluginRegistrant.swift b/auth/macos/Flutter/GeneratedPluginRegistrant.swift index 58190b0b53..509bf66749 100644 --- a/auth/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/auth/macos/Flutter/GeneratedPluginRegistrant.swift @@ -24,6 +24,7 @@ import smart_auth import sodium_libs import sqflite import sqlite3_flutter_libs +import system_tray import url_launcher_macos import window_manager @@ -47,6 +48,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { SodiumLibsPlugin.register(with: registry.registrar(forPlugin: "SodiumLibsPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) + SystemTrayPlugin.register(with: registry.registrar(forPlugin: "SystemTrayPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) } diff --git a/auth/macos/Podfile.lock b/auth/macos/Podfile.lock index 2467d732da..6412895521 100644 --- a/auth/macos/Podfile.lock +++ b/auth/macos/Podfile.lock @@ -63,6 +63,8 @@ PODS: - sqlite3/fts5 - sqlite3/perf-threadsafe - sqlite3/rtree + - system_tray (0.0.1): + - FlutterMacOS - url_launcher_macos (0.0.1): - FlutterMacOS - window_manager (0.2.0): @@ -89,6 +91,7 @@ DEPENDENCIES: - sodium_libs (from `Flutter/ephemeral/.symlinks/plugins/sodium_libs/macos`) - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`) - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos`) + - system_tray (from `Flutter/ephemeral/.symlinks/plugins/system_tray/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) @@ -141,6 +144,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin sqlite3_flutter_libs: :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/macos + system_tray: + :path: Flutter/ephemeral/.symlinks/plugins/system_tray/macos url_launcher_macos: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos window_manager: @@ -172,6 +177,7 @@ SPEC CHECKSUMS: sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec sqlite3: 73b7fc691fdc43277614250e04d183740cb15078 sqlite3_flutter_libs: 06a05802529659a272beac4ee1350bfec294f386 + system_tray: e53c972838c69589ff2e77d6d3abfd71332f9e5d url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 diff --git a/auth/macos/Runner/AppDelegate.swift b/auth/macos/Runner/AppDelegate.swift index d53ef64377..218f93e023 100644 --- a/auth/macos/Runner/AppDelegate.swift +++ b/auth/macos/Runner/AppDelegate.swift @@ -4,6 +4,6 @@ import FlutterMacOS @NSApplicationMain class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { - return true + return false } } diff --git a/auth/pubspec.lock b/auth/pubspec.lock index 95b15e5ef1..66ef40e2a3 100644 --- a/auth/pubspec.lock +++ b/auth/pubspec.lock @@ -1463,6 +1463,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.0+1" + system_tray: + dependency: "direct main" + description: + name: system_tray + sha256: "1bcc11bc230033be20d7443c29f65f68d67169715a838a1122f20fbff5dd2d19" + url: "https://pub.dev" + source: hosted + version: "0.1.1" term_glyph: dependency: transitive description: diff --git a/auth/pubspec.yaml b/auth/pubspec.yaml index fc0f1c2f78..9ce1ed03e9 100644 --- a/auth/pubspec.yaml +++ b/auth/pubspec.yaml @@ -93,6 +93,7 @@ dependencies: sqlite3_flutter_libs: ^0.5.19+1 step_progress_indicator: ^1.0.2 styled_text: ^8.1.0 + system_tray: ^0.1.1 tuple: ^2.0.0 url_launcher: ^6.1.5 uuid: ^4.2.2 diff --git a/auth/windows/flutter/generated_plugin_registrant.cc b/auth/windows/flutter/generated_plugin_registrant.cc index f6197f8ce6..aed85fbffc 100644 --- a/auth/windows/flutter/generated_plugin_registrant.cc +++ b/auth/windows/flutter/generated_plugin_registrant.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("SodiumLibsPluginCApi")); Sqlite3FlutterLibsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); + SystemTrayPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SystemTrayPlugin")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); WindowManagerPluginRegisterWithRegistrar( diff --git a/auth/windows/flutter/generated_plugins.cmake b/auth/windows/flutter/generated_plugins.cmake index 985932151f..2578d34e23 100644 --- a/auth/windows/flutter/generated_plugins.cmake +++ b/auth/windows/flutter/generated_plugins.cmake @@ -16,6 +16,7 @@ list(APPEND FLUTTER_PLUGIN_LIST smart_auth sodium_libs sqlite3_flutter_libs + system_tray url_launcher_windows window_manager )