Workaround for #2818

Signed-off-by: Joel Jothiprakasam <hijoelj@gmail.com>
This commit is contained in:
Joel Jothiprakasam
2024-10-24 00:54:26 -05:00
parent ce1b428e7c
commit c3d9e46970
8 changed files with 114 additions and 57 deletions

View File

@ -8,7 +8,6 @@ import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:bluebubbles/app/components/custom/custom_error_box.dart';
import 'package:bluebubbles/helpers/backend/startup_tasks.dart';
import 'package:bluebubbles/helpers/helpers.dart';
import 'package:bluebubbles/database/database.dart';
import 'package:bluebubbles/services/network/http_overrides.dart';
import 'package:bluebubbles/utils/logger/logger.dart';
import 'package:bluebubbles/utils/window_effects.dart';
@ -40,6 +39,7 @@ import 'package:path/path.dart' as p;
import 'package:permission_handler/permission_handler.dart';
import 'package:screen_retriever/screen_retriever.dart';
import 'package:secure_application/secure_application.dart';
import 'package:system_tray/system_tray.dart' as st;
import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz;
import 'package:tray_manager/tray_manager.dart';
@ -49,6 +49,7 @@ import 'package:window_manager/window_manager.dart';
import 'package:windows_taskbar/windows_taskbar.dart';
bool isAuthing = false;
final systemTray = st.SystemTray();
@pragma('vm:entry-point')
//ignore: prefer_void_to_null
@ -247,37 +248,6 @@ class DesktopWindowListener extends WindowListener {
}
}
class DesktopTrayListener extends TrayListener {
DesktopTrayListener._();
static final DesktopTrayListener instance = DesktopTrayListener._();
@override
void onTrayIconMouseDown() async {
await windowManager.show();
}
@override
void onTrayIconRightMouseDown() async {
await trayManager.popUpContextMenu();
}
@override
void onTrayMenuItemClick(MenuItem menuItem) async {
switch (menuItem.key) {
case 'show_app':
await windowManager.show();
break;
case 'hide_app':
await windowManager.hide();
break;
case 'close_app':
await windowManager.close();
break;
}
}
}
class Main extends StatelessWidget {
final ThemeData darkTheme;
final ThemeData lightTheme;
@ -445,7 +415,7 @@ class Home extends StatefulWidget {
State<Home> createState() => _HomeState();
}
class _HomeState extends OptimizedState<Home> with WidgetsBindingObserver {
class _HomeState extends OptimizedState<Home> with WidgetsBindingObserver, TrayListener {
final ReceivePort port = ReceivePort();
bool serverCompatible = true;
bool fullyLoaded = false;
@ -527,7 +497,17 @@ class _HomeState extends OptimizedState<Home> with WidgetsBindingObserver {
/* ----- SYSTEM TRAY INITIALIZATION ----- */
await initSystemTray();
trayManager.addListener(DesktopTrayListener.instance);
if (Platform.isWindows) {
systemTray.registerSystemTrayEventHandler((eventName) {
if (eventName == st.kSystemTrayEventClick) {
onTrayIconMouseDown();
} else if (eventName == st.kSystemTrayEventRightClick) {
onTrayIconRightMouseDown();
}
});
} else {
trayManager.addListener(this);
}
/* ----- NOTIFICATIONS INITIALIZATION ----- */
await localNotifier.setup(appName: "BlueBubbles");
@ -543,12 +523,43 @@ class _HomeState extends OptimizedState<Home> with WidgetsBindingObserver {
});
}
@override
void onTrayIconMouseDown() async {
await windowManager.show();
}
@override
void onTrayIconRightMouseDown() async {
if (Platform.isWindows) {
await systemTray.popUpContextMenu();
} else {
await trayManager.popUpContextMenu();
}
}
@override
void onTrayMenuItemClick(MenuItem menuItem) async {
switch (menuItem.key) {
case 'show_app':
await windowManager.show();
break;
case 'hide_app':
await windowManager.hide();
break;
case 'close_app':
await windowManager.close();
break;
}
}
@override
void dispose() {
// Clean up observer when app is fully closed
WidgetsBinding.instance.removeObserver(this);
windowManager.removeListener(DesktopWindowListener.instance);
trayManager.removeListener(DesktopTrayListener.instance);
if (Platform.isLinux) {
trayManager.removeListener(this);
}
super.dispose();
}
@ -629,32 +640,58 @@ class _HomeState extends OptimizedState<Home> with WidgetsBindingObserver {
}
Future<void> initSystemTray() async {
String path;
if (Platform.isWindows) {
path = 'assets/icon/icon.ico';
} else if (isFlatpak) {
path = 'app.bluebubbles.BlueBubbles';
} else if (isSnap) {
path = p.joinAll([p.dirname(Platform.resolvedExecutable), 'data/flutter_assets/assets/icon', 'icon.png']);
await systemTray.initSystemTray(
iconPath: 'assets/icon/icon.ico',
toolTip: "BlueBubbles",
);
} else {
path = 'assets/icon/icon.png';
String path;
if (isFlatpak) {
path = 'app.bluebubbles.BlueBubbles';
} else if (isSnap) {
path = p.joinAll([p.dirname(Platform.resolvedExecutable), 'data/flutter_assets/assets/icon', 'icon.png']);
} else {
path = 'assets/icon/icon.png';
}
await trayManager.setIcon(path);
}
// We first init the systray menu and then add the menu entries
await trayManager.setIcon(path);
if (Platform.isWindows) {
await trayManager.setToolTip("BlueBubbles");
}
await setSystemTrayContextMenu(windowHidden: !appWindow.isVisible);
}
Future<void> setSystemTrayContextMenu({bool windowHidden = false}) async {
await trayManager.setContextMenu(Menu(
items: [
MenuItem(label: windowHidden ? 'Show App' : 'Hide App', key: windowHidden ? 'show_app' : 'hide_app'),
MenuItem.separator(),
MenuItem(label: 'Close App', key: 'close_app'),
],
));
}
if (Platform.isWindows) {
st.Menu menu = st.Menu();
menu.buildFrom([
st.MenuItemLabel(
label: windowHidden ? 'Show App' : 'Hide App',
onClicked: (st.MenuItemBase menuItem) async {
if (windowHidden) {
await windowManager.show();
} else {
await windowManager.hide();
}
},
),
st.MenuSeparator(),
st.MenuItemLabel(
label: 'Close App',
onClicked: (_) async {
await windowManager.close();
},
),
]);
await systemTray.setContextMenu(menu);
} else {
await trayManager.setContextMenu(Menu(
items: [
MenuItem(label: windowHidden ? 'Show App' : 'Hide App', key: windowHidden ? 'show_app' : 'hide_app'),
MenuItem.separator(),
MenuItem(label: 'Close App', key: 'close_app'),
],
));
}
}

View File

@ -24,6 +24,7 @@
#include <record_linux/record_linux_plugin.h>
#include <screen_retriever/screen_retriever_plugin.h>
#include <super_native_extensions/super_native_extensions_plugin.h>
#include <system_tray/system_tray_plugin.h>
#include <tray_manager/tray_manager_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
#include <window_manager/window_manager_plugin.h>
@ -83,6 +84,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) super_native_extensions_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "SuperNativeExtensionsPlugin");
super_native_extensions_plugin_register_with_registrar(super_native_extensions_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) tray_manager_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "TrayManagerPlugin");
tray_manager_plugin_register_with_registrar(tray_manager_registrar);

View File

@ -21,6 +21,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
record_linux
screen_retriever
super_native_extensions
system_tray
tray_manager
url_launcher_linux
window_manager

View File

@ -41,6 +41,7 @@ import share_plus
import shared_preferences_foundation
import store_checker
import super_native_extensions
import system_tray
import tray_manager
import url_launcher_macos
import video_player_avfoundation
@ -84,6 +85,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
StoreCheckerPlugin.register(with: registry.registrar(forPlugin: "StoreCheckerPlugin"))
SuperNativeExtensionsPlugin.register(with: registry.registrar(forPlugin: "SuperNativeExtensionsPlugin"))
SystemTrayPlugin.register(with: registry.registrar(forPlugin: "SystemTrayPlugin"))
TrayManagerPlugin.register(with: registry.registrar(forPlugin: "TrayManagerPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))

View File

@ -2906,6 +2906,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.0"
system_tray:
dependency: "direct main"
description:
name: system_tray
sha256: "40444e5de8ed907822a98694fd031b8accc3cb3c0baa547634ce76189cf3d9cf"
url: "https://pub.dev"
source: hosted
version: "2.0.3"
term_glyph:
dependency: transitive
description:
@ -2966,10 +2974,10 @@ packages:
dependency: "direct main"
description:
name: tray_manager
sha256: c9a63fd88bd3546287a7eb8ccc978d707eef82c775397af17dda3a4f4c039e64
sha256: bdc3ac6c36f3d12d871459e4a9822705ce5a1165a17fa837103bc842719bf3f7
url: "https://pub.dev"
source: hosted
version: "0.2.3"
version: "0.2.4"
try_catch:
dependency: transitive
description:

View File

@ -172,6 +172,7 @@ dependencies:
url: https://github.com/ravitejaavv/store_checker
ref: master
synchronized: ^3.1.0+1
system_tray: ^2.0.3
super_drag_and_drop: ^0.8.20
supercharged: ^2.1.1
system_info2: ^4.0.0

View File

@ -32,6 +32,7 @@
#include <secure_application/secure_application_plugin.h>
#include <share_plus/share_plus_windows_plugin_c_api.h>
#include <super_native_extensions/super_native_extensions_plugin_c_api.h>
#include <system_tray/system_tray_plugin.h>
#include <tray_manager/tray_manager_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h>
#include <window_manager/window_manager_plugin.h>
@ -90,6 +91,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
SuperNativeExtensionsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SuperNativeExtensionsPluginCApi"));
SystemTrayPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SystemTrayPlugin"));
TrayManagerPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("TrayManagerPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(

View File

@ -29,6 +29,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
secure_application
share_plus
super_native_extensions
system_tray
tray_manager
url_launcher_windows
window_manager