This commit is contained in:
2025-09-04 22:10:00 +08:00
parent c527b5e67c
commit 3b375abc09
18 changed files with 150 additions and 6 deletions

View File

@@ -62,4 +62,3 @@ If you want to build the release version, use the flutter build command. Learn m
```bash ```bash
flutter build <platform> flutter build <platform>
``` ```

View File

@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="192" fill="none">
<path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="12"
d="M54 147h86" />
<path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"
d="M57 111s-2-4.5-2-10m22 22s-4 7-11 4m9-22s-2-4.5-2-10" />
<path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="12"
d="M54 147a32 32 0 0 1-11.999-61.665A39 39 0 0 1 81 46m59 101a30 30 0 0 0 29.933-28" />
<circle cx="132" cy="75" r="4" stroke="#fff" stroke-linecap="round" stroke-linejoin="round"
stroke-width="8" />
<path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"
d="M112.5 41.217C100.843 47.961 93 60.564 93 75c0 6.375 1.53 12.393 4.242 17.707m69.513-35.419A38.84 38.84 0 0 1 171 75c0 14.433-7.84 27.034-19.493 33.779m-.793-43.317A20.9 20.9 0 0 1 153 75c0 7.77-4.221 14.556-10.495 18.188m-21.003-36.38C115.224 60.44 111 67.226 111 75a20.9 20.9 0 0 0 2.284 9.533" />
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,7 +1,7 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:island/models/post.dart'; import 'package:island/models/post.dart';
import 'package:island/services/text.dart'; import 'package:island/utils/text.dart';
part 'post_category.freezed.dart'; part 'post_category.freezed.dart';
part 'post_category.g.dart'; part 'post_category.g.dart';

View File

@@ -10,7 +10,7 @@ import 'package:island/pods/config.dart';
import 'package:island/pods/network.dart'; import 'package:island/pods/network.dart';
import 'package:island/screens/account/me/account_settings.dart'; import 'package:island/screens/account/me/account_settings.dart';
import 'package:island/screens/auth/oidc.native.dart'; import 'package:island/screens/auth/oidc.native.dart';
import 'package:island/services/text.dart'; import 'package:island/utils/text.dart';
import 'package:island/services/time.dart'; import 'package:island/services/time.dart';
import 'package:island/widgets/alert.dart'; import 'package:island/widgets/alert.dart';
import 'package:island/widgets/content/sheet.dart'; import 'package:island/widgets/content/sheet.dart';

View File

@@ -17,7 +17,7 @@ import 'package:island/pods/network.dart';
import 'package:island/pods/userinfo.dart'; import 'package:island/pods/userinfo.dart';
import 'package:island/services/color.dart'; import 'package:island/services/color.dart';
import 'package:island/services/responsive.dart'; import 'package:island/services/responsive.dart';
import 'package:island/services/text.dart'; import 'package:island/utils/text.dart';
import 'package:island/services/time.dart'; import 'package:island/services/time.dart';
import 'package:island/services/timezone/native.dart'; import 'package:island/services/timezone/native.dart';
import 'package:island/widgets/account/account_name.dart'; import 'package:island/widgets/account/account_name.dart';

View File

@@ -11,7 +11,7 @@ import 'package:island/models/publisher.dart';
import 'package:island/pods/network.dart'; import 'package:island/pods/network.dart';
import 'package:island/screens/creators/publishers.dart'; import 'package:island/screens/creators/publishers.dart';
import 'package:island/services/responsive.dart'; import 'package:island/services/responsive.dart';
import 'package:island/services/text.dart'; import 'package:island/utils/text.dart';
import 'package:island/widgets/account/account_picker.dart'; import 'package:island/widgets/account/account_picker.dart';
import 'package:island/widgets/alert.dart'; import 'package:island/widgets/alert.dart';
import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/app_scaffold.dart';

View File

@@ -0,0 +1,58 @@
import 'dart:io';
import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:flutter/foundation.dart';
import 'package:tray_manager/tray_manager.dart';
class TrayService {
TrayService._();
static final TrayService _instance = TrayService._();
static TrayService get instance => _instance;
bool _checkPlatformAvalability() {
if (kIsWeb) return false;
if (Platform.isAndroid || Platform.isIOS) return false;
return true;
}
Future<void> initialize(TrayListener listener) async {
if (!_checkPlatformAvalability()) return;
await trayManager.setIcon(
Platform.isWindows
? 'assets/icons/icon.ico'
: 'assets/icons/icon-outline.svg',
);
final menu = Menu(
items: [
MenuItem(key: 'show_window', label: 'Show Window'),
MenuItem.separator(),
MenuItem(key: 'exit_app', label: 'Exit App'),
],
);
await trayManager.setContextMenu(menu);
trayManager.addListener(listener);
}
Future<void> dispose(TrayListener listener) async {
if (!_checkPlatformAvalability()) return;
trayManager.removeListener(listener);
await trayManager.destroy();
}
void handleAction(MenuItem item) {
switch (item.key) {
case 'show_window':
appWindow.show();
break;
case 'exit_app':
appWindow.close();
break;
}
}
}

View File

@@ -1,15 +1,18 @@
import 'dart:async'; import 'dart:async';
import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/pods/websocket.dart'; import 'package:island/pods/websocket.dart';
import 'package:island/screens/tray_manager.dart';
import 'package:island/services/notify.dart'; import 'package:island/services/notify.dart';
import 'package:island/services/sharing_intent.dart'; import 'package:island/services/sharing_intent.dart';
import 'package:island/services/update_service.dart'; import 'package:island/services/update_service.dart';
import 'package:island/widgets/content/network_status_sheet.dart'; import 'package:island/widgets/content/network_status_sheet.dart';
import 'package:island/widgets/tour/tour.dart'; import 'package:island/widgets/tour/tour.dart';
import 'package:tray_manager/tray_manager.dart';
class AppWrapper extends HookConsumerWidget { class AppWrapper extends HookConsumerWidget with TrayListener {
final Widget child; final Widget child;
const AppWrapper({super.key, required this.child}); const AppWrapper({super.key, required this.child});
@@ -20,10 +23,16 @@ class AppWrapper extends HookConsumerWidget {
Future(() { Future(() {
if (context.mounted) ntySubs = setupNotificationListener(context, ref); if (context.mounted) ntySubs = setupNotificationListener(context, ref);
}); });
final sharingService = SharingIntentService(); final sharingService = SharingIntentService();
sharingService.initialize(context); sharingService.initialize(context);
UpdateService().checkForUpdates(context); UpdateService().checkForUpdates(context);
TrayService.instance.initialize(this);
return () { return () {
TrayService.instance.dispose(this);
sharingService.dispose(); sharingService.dispose();
ntySubs?.cancel(); ntySubs?.cancel();
}; };
@@ -52,4 +61,27 @@ class AppWrapper extends HookConsumerWidget {
return TourTriggerWidget(key: UniqueKey(), child: child); return TourTriggerWidget(key: UniqueKey(), child: child);
} }
void _trayIconPrimaryAction() {
appWindow.show();
}
void _trayIconSecondaryAction() {
trayManager.popUpContextMenu();
}
@override
void onTrayIconMouseUp() {
_trayIconPrimaryAction();
}
@override
void onTrayIconRightMouseDown() {
_trayIconSecondaryAction();
}
@override
void onTrayMenuItemClick(MenuItem menuItem) {
TrayService.instance.handleAction(menuItem);
}
} }

View File

@@ -41,6 +41,7 @@ class PostShuffleScreen extends HookConsumerWidget {
? CardSwiper( ? CardSwiper(
controller: cardSwiperController, controller: cardSwiperController,
cardsCount: postListState.value!.items.length, cardsCount: postListState.value!.items.length,
isLoop: false,
cardBuilder: ( cardBuilder: (
context, context,
index, index,

View File

@@ -22,6 +22,7 @@
#include <record_linux/record_linux_plugin.h> #include <record_linux/record_linux_plugin.h>
#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h> #include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
#include <super_native_extensions/super_native_extensions_plugin.h> #include <super_native_extensions/super_native_extensions_plugin.h>
#include <tray_manager/tray_manager_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h> #include <url_launcher_linux/url_launcher_plugin.h>
#include <volume_controller/volume_controller_plugin.h> #include <volume_controller/volume_controller_plugin.h>
@@ -74,6 +75,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) super_native_extensions_registrar = g_autoptr(FlPluginRegistrar) super_native_extensions_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "SuperNativeExtensionsPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "SuperNativeExtensionsPlugin");
super_native_extensions_plugin_register_with_registrar(super_native_extensions_registrar); super_native_extensions_plugin_register_with_registrar(super_native_extensions_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);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);

View File

@@ -19,6 +19,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
record_linux record_linux
sqlite3_flutter_libs sqlite3_flutter_libs
super_native_extensions super_native_extensions
tray_manager
url_launcher_linux url_launcher_linux
volume_controller volume_controller
) )

View File

@@ -37,6 +37,7 @@ import sign_in_with_apple
import sqflite_darwin import sqflite_darwin
import sqlite3_flutter_libs import sqlite3_flutter_libs
import super_native_extensions import super_native_extensions
import tray_manager
import url_launcher_macos import url_launcher_macos
import volume_controller import volume_controller
import wakelock_plus import wakelock_plus
@@ -74,6 +75,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin"))
SuperNativeExtensionsPlugin.register(with: registry.registrar(forPlugin: "SuperNativeExtensionsPlugin")) SuperNativeExtensionsPlugin.register(with: registry.registrar(forPlugin: "SuperNativeExtensionsPlugin"))
TrayManagerPlugin.register(with: registry.registrar(forPlugin: "TrayManagerPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
VolumeControllerPlugin.register(with: registry.registrar(forPlugin: "VolumeControllerPlugin")) VolumeControllerPlugin.register(with: registry.registrar(forPlugin: "VolumeControllerPlugin"))
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))

View File

@@ -237,6 +237,8 @@ PODS:
- sqlite3/session - sqlite3/session
- super_native_extensions (0.0.1): - super_native_extensions (0.0.1):
- FlutterMacOS - FlutterMacOS
- tray_manager (0.0.1):
- FlutterMacOS
- url_launcher_macos (0.0.1): - url_launcher_macos (0.0.1):
- FlutterMacOS - FlutterMacOS
- volume_controller (0.0.1): - volume_controller (0.0.1):
@@ -280,6 +282,7 @@ DEPENDENCIES:
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`) - sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
- sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin`) - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin`)
- super_native_extensions (from `Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos`) - super_native_extensions (from `Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos`)
- tray_manager (from `Flutter/ephemeral/.symlinks/plugins/tray_manager/macos`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
- volume_controller (from `Flutter/ephemeral/.symlinks/plugins/volume_controller/macos`) - volume_controller (from `Flutter/ephemeral/.symlinks/plugins/volume_controller/macos`)
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`) - wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
@@ -376,6 +379,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin
super_native_extensions: super_native_extensions:
:path: Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos :path: Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos
tray_manager:
:path: Flutter/ephemeral/.symlinks/plugins/tray_manager/macos
url_launcher_macos: url_launcher_macos:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
volume_controller: volume_controller:
@@ -437,6 +442,7 @@ SPEC CHECKSUMS:
sqlite3: 73513155ec6979715d3904ef53a8d68892d4032b sqlite3: 73513155ec6979715d3904ef53a8d68892d4032b
sqlite3_flutter_libs: 83f8e9f5b6554077f1d93119fe20ebaa5f3a9ef1 sqlite3_flutter_libs: 83f8e9f5b6554077f1d93119fe20ebaa5f3a9ef1
super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189 super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189
tray_manager: a104b5c81b578d83f3c3d0f40a997c8b10810166
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673 url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
volume_controller: 5c068e6d085c80dadd33fc2c918d2114b775b3dd volume_controller: 5c068e6d085c80dadd33fc2c918d2114b775b3dd
wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497 wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497

View File

@@ -1573,6 +1573,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
menu_base:
dependency: transitive
description:
name: menu_base
sha256: "820368014a171bd1241030278e6c2617354f492f5c703d7b7d4570a6b8b84405"
url: "https://pub.dev"
source: hosted
version: "0.1.1"
meta: meta:
dependency: transitive dependency: transitive
description: description:
@@ -2165,6 +2173,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.0" version: "3.0.0"
shortid:
dependency: transitive
description:
name: shortid
sha256: d0b40e3dbb50497dad107e19c54ca7de0d1a274eb9b4404991e443dadb9ebedb
url: "https://pub.dev"
source: hosted
version: "0.1.2"
sign_in_with_apple: sign_in_with_apple:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -2435,6 +2451,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.3.0" version: "3.3.0"
tray_manager:
dependency: "direct main"
description:
name: tray_manager
sha256: "537e539f48cd82d8ee2240d4330158c7b44c7e043e8e18b5811f2f8f6b7df25a"
url: "https://pub.dev"
source: hosted
version: "0.5.1"
tuple: tuple:
dependency: transitive dependency: transitive
description: description:

View File

@@ -138,6 +138,7 @@ dependencies:
screenshot: ^3.0.0 screenshot: ^3.0.0
flutter_card_swiper: ^7.0.2 flutter_card_swiper: ^7.0.2
file_saver: ^0.3.1 file_saver: ^0.3.1
tray_manager: ^0.5.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@@ -28,6 +28,7 @@
#include <share_plus/share_plus_windows_plugin_c_api.h> #include <share_plus/share_plus_windows_plugin_c_api.h>
#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h> #include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
#include <super_native_extensions/super_native_extensions_plugin_c_api.h> #include <super_native_extensions/super_native_extensions_plugin_c_api.h>
#include <tray_manager/tray_manager_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h> #include <url_launcher_windows/url_launcher_windows.h>
#include <volume_controller/volume_controller_plugin_c_api.h> #include <volume_controller/volume_controller_plugin_c_api.h>
@@ -76,6 +77,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin")); registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin"));
SuperNativeExtensionsPluginCApiRegisterWithRegistrar( SuperNativeExtensionsPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SuperNativeExtensionsPluginCApi")); registry->GetRegistrarForPlugin("SuperNativeExtensionsPluginCApi"));
TrayManagerPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("TrayManagerPlugin"));
UrlLauncherWindowsRegisterWithRegistrar( UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows")); registry->GetRegistrarForPlugin("UrlLauncherWindows"));
VolumeControllerPluginCApiRegisterWithRegistrar( VolumeControllerPluginCApiRegisterWithRegistrar(

View File

@@ -25,6 +25,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
share_plus share_plus
sqlite3_flutter_libs sqlite3_flutter_libs
super_native_extensions super_native_extensions
tray_manager
url_launcher_windows url_launcher_windows
volume_controller volume_controller
) )