feat: system tray support (#31)

This commit is contained in:
Kingkor Roy Tirtho 2023-04-10 23:19:14 +06:00
parent 5e47faa606
commit 06a043764d
14 changed files with 304 additions and 95 deletions

BIN
assets/spotube-logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -67,4 +67,5 @@ abstract class SpotubeIcons {
static const genres = FeatherIcons.music;
static const zoomIn = FeatherIcons.zoomIn;
static const zoomOut = FeatherIcons.zoomOut;
static const tray = FeatherIcons.chevronDown;
}

View File

@ -1,5 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/provider/user_preferences_provider.dart';
import 'package:spotube/utils/platform.dart';
import 'package:titlebar_buttons/titlebar_buttons.dart';
import 'package:window_manager/window_manager.dart';
@ -85,7 +87,7 @@ class _PageWindowTitleBarState extends State<PageWindowTitleBar> {
}
}
class WindowTitleBarButtons extends HookWidget {
class WindowTitleBarButtons extends HookConsumerWidget {
final Color? foregroundColor;
const WindowTitleBarButtons({
Key? key,
@ -93,10 +95,20 @@ class WindowTitleBarButtons extends HookWidget {
}) : super(key: key);
@override
Widget build(BuildContext context) {
Widget build(BuildContext context, ref) {
final closeBehavior =
ref.watch(userPreferencesProvider.select((s) => s.closeBehavior));
final isMaximized = useState<bool?>(null);
const type = ThemeType.auto;
void onClose() {
if (closeBehavior == CloseBehavior.close) {
windowManager.close();
} else {
windowManager.hide();
}
}
useEffect(() {
if (kIsDesktop) {
windowManager.isMaximized().then((value) {
@ -157,7 +169,7 @@ class WindowTitleBarButtons extends HookWidget {
),
CloseWindowButton(
colors: closeColors,
onPressed: windowManager.close,
onPressed: onClose,
),
],
),
@ -187,7 +199,7 @@ class WindowTitleBarButtons extends HookWidget {
),
DecoratedCloseButton(
type: type,
onPressed: windowManager.close,
onPressed: onClose,
),
],
),

View File

@ -0,0 +1,125 @@
import 'package:flutter/material.dart';
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/collections/intents.dart';
import 'package:spotube/provider/playlist_queue_provider.dart';
import 'package:spotube/provider/user_preferences_provider.dart';
void useInitSysTray(WidgetRef ref) {
final context = useContext();
final systemTray = useRef<SystemTray?>(null);
final initializeMenu = useCallback(() async {
systemTray.value?.destroy();
final playlistQueue = ref.read(PlaylistQueueNotifier.notifier);
final preferences = ref.read(userPreferencesProvider);
if (!preferences.showSystemTrayIcon) {
await systemTray.value?.destroy();
systemTray.value = null;
return;
}
final enabled =
playlistQueue.isLoaded && playlistQueue.state?.isLoading != true;
systemTray.value = await DesktopTools.createSystemTrayMenu(
title: "Spotube",
iconPath: "assets/spotube-logo.png",
windowsIconPath: "assets/spotube-logo.ico",
items: [
MenuItemLabel(
label: "Show/Hide",
name: "show-hide",
onClicked: (item) async {
if (await DesktopTools.window.isVisible()) {
await DesktopTools.window.hide();
} else {
await DesktopTools.window.show();
}
},
),
MenuSeparator(),
MenuItemLabel(
label: "Play/Pause",
name: "play-pause",
enabled: enabled,
onClicked: (_) async {
Actions.maybeInvoke<PlayPauseIntent>(
context, PlayPauseIntent(ref)) ??
PlayPauseAction().invoke(PlayPauseIntent(ref));
},
),
MenuItemLabel(
label: "Next",
name: "next",
enabled: enabled && (playlistQueue.state?.tracks.length ?? 0) > 1,
onClicked: (p0) async {
await playlistQueue.next();
},
),
MenuItemLabel(
label: "Previous",
name: "previous",
enabled: enabled && (playlistQueue.state?.tracks.length ?? 0) > 1,
onClicked: (p0) async {
await playlistQueue.previous();
},
),
MenuSeparator(),
MenuItemLabel(
label: "Quit",
name: "quit",
onClicked: (item) async {
await DesktopTools.window.close();
},
),
],
onEvent: (event, tray) async {
if (DesktopTools.platform.isWindows) {
switch (event) {
case SystemTrayEvent.click:
await DesktopTools.window.show();
break;
case SystemTrayEvent.rightClick:
await tray.popUpContextMenu();
break;
default:
}
} else {
switch (event) {
case SystemTrayEvent.rightClick:
await DesktopTools.window.show();
break;
case SystemTrayEvent.click:
await tray.popUpContextMenu();
break;
default:
}
}
},
);
}, [ref]);
useReassemble(initializeMenu);
ref.listen<PlaylistQueue?>(
PlaylistQueueNotifier.provider,
(previous, next) {
initializeMenu();
},
);
ref.listen(
userPreferencesProvider.select((s) => s.showSystemTrayIcon),
(previous, next) {
initializeMenu();
},
);
useEffect(() {
WidgetsBinding.instance.addPostFrameCallback((_) {
initializeMenu();
});
return () async {
await systemTray.value?.destroy();
};
}, [initializeMenu]);
}

View File

@ -1,4 +1,3 @@
import 'dart:convert';
import 'dart:io';
import 'package:args/args.dart';
@ -7,13 +6,13 @@ import 'package:fl_query/fl_query.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:metadata_god/metadata_god.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:spotube/collections/cache_keys.dart';
import 'package:spotube/collections/env.dart';
import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart';
import 'package:spotube/entities/cache_track.dart';
@ -26,11 +25,10 @@ import 'package:spotube/services/audio_player.dart';
import 'package:spotube/services/pocketbase.dart';
import 'package:spotube/services/youtube.dart';
import 'package:spotube/themes/theme.dart';
import 'package:spotube/utils/platform.dart';
import 'package:window_manager/window_manager.dart';
import 'package:window_size/window_size.dart';
import 'package:system_theme/system_theme.dart';
import 'hooks/use_init_sys_tray.dart';
Future<void> main(List<String> rawArgs) async {
final parser = ArgParser();
@ -69,6 +67,15 @@ Future<void> main(List<String> rawArgs) async {
}
WidgetsFlutterBinding.ensureInitialized();
await DesktopTools.ensureInitialized(
DesktopWindowOptions(
hideTitleBar: true,
title: "Spotube",
backgroundColor: Colors.transparent,
minimumSize: const Size(300, 700),
),
);
await SystemTheme.accentColor.load();
MetadataGod.initialize();
await QueryClient.initialize(cachePrefix: "oss.krtirtho.spotube");
@ -77,32 +84,6 @@ Future<void> main(List<String> rawArgs) async {
Hive.registerAdapter(CacheTrackSkipSegmentAdapter());
await Env.configure();
if (kIsDesktop) {
await windowManager.ensureInitialized();
WindowOptions windowOptions = const WindowOptions(
center: true,
backgroundColor: Colors.transparent,
titleBarStyle: TitleBarStyle.hidden,
title: "Spotube",
);
setWindowMinSize(const Size(kReleaseMode ? 1020 : 300, 700));
await windowManager.waitUntilReadyToShow(windowOptions, () async {
final localStorage = await SharedPreferences.getInstance();
final rawSize = localStorage.getString(LocalStorageKeys.windowSizeInfo);
final savedSize = rawSize != null ? json.decode(rawSize) : null;
final wasMaximized = savedSize?["maximized"] ?? false;
final double? height = savedSize?["height"];
final double? width = savedSize?["width"];
await windowManager.setResizable(true);
if (wasMaximized) {
await windowManager.maximize();
} else if (height != null && width != null) {
await windowManager.setSize(Size(width, height));
}
await windowManager.show();
});
}
Catcher(
enableLogger: arguments["verbose"],
debugConfig: CatcherOptions(
@ -188,44 +169,14 @@ class Spotube extends StatefulHookConsumerWidget {
context.findAncestorStateOfType<SpotubeState>()!;
}
class SpotubeState extends ConsumerState<Spotube> with WidgetsBindingObserver {
class SpotubeState extends ConsumerState<Spotube> {
final logger = getLogger(Spotube);
SharedPreferences? localStorage;
Size? prevSize;
@override
void initState() {
super.initState();
SharedPreferences.getInstance().then(((value) => localStorage = value));
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeMetrics() async {
super.didChangeMetrics();
if (kIsMobile) return;
final size = await windowManager.getSize();
final windowSameDimension =
prevSize?.width == size.width && prevSize?.height == size.height;
if (localStorage == null || windowSameDimension) return;
final isMaximized = await windowManager.isMaximized();
localStorage!.setString(
LocalStorageKeys.windowSizeInfo,
jsonEncode({
'maximized': isMaximized,
'width': size.width,
'height': size.height,
}),
);
prevSize = size;
}
@override
@ -235,6 +186,8 @@ class SpotubeState extends ConsumerState<Spotube> with WidgetsBindingObserver {
final accentMaterialColor =
ref.watch(userPreferencesProvider.select((s) => s.accentColorScheme));
useInitSysTray(ref);
/// For enabling hot reload for audio player
useEffect(() {
return () {

View File

@ -1,6 +1,7 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
@ -198,14 +199,6 @@ class SettingsPage extends HookConsumerWidget {
),
onTap: pickColorScheme(),
),
SwitchListTile(
secondary: const Icon(SpotubeIcons.album),
title: const Text("Rotating Album Art"),
value: preferences.rotatingAlbumArt,
onChanged: (state) {
preferences.setRotatingAlbumArt(state);
},
),
Text(
" Playback",
style: theme.textTheme.headlineSmall
@ -321,6 +314,43 @@ class SettingsPage extends HookConsumerWidget {
preferences.setSaveTrackLyrics(state);
},
),
if (DesktopTools.platform.isDesktop) ...[
Text(
" Desktop",
style: theme.textTheme.headlineSmall
?.copyWith(fontWeight: FontWeight.bold),
),
AdaptiveListTile(
leading: const Icon(SpotubeIcons.close),
title: const Text("Close Behavior"),
trailing: (context, update) =>
DropdownButton<CloseBehavior>(
value: preferences.closeBehavior,
items: const [
DropdownMenuItem(
value: CloseBehavior.close,
child: Text("Close"),
),
DropdownMenuItem(
value: CloseBehavior.minimizeToTray,
child: Text("Minimize to Tray"),
),
],
onChanged: (value) {
if (value != null) {
preferences.setCloseBehavior(value);
update?.call(() {});
}
},
),
),
SwitchListTile(
secondary: const Icon(SpotubeIcons.tray),
title: const Text("Show System Tray Icon"),
value: preferences.showSystemTrayIcon,
onChanged: preferences.setShowSystemTrayIcon,
),
],
Text(
" About",
style: theme.textTheme.headlineSmall

View File

@ -21,6 +21,11 @@ enum AudioQuality {
low,
}
enum CloseBehavior {
minimizeToTray,
close,
}
class UserPreferences extends PersistedChangeNotifier {
ThemeMode themeMode;
String recommendationMarket;
@ -35,10 +40,13 @@ class UserPreferences extends PersistedChangeNotifier {
String downloadLocation;
LayoutMode layoutMode;
bool rotatingAlbumArt;
bool predownload;
CloseBehavior closeBehavior;
bool showSystemTrayIcon;
UserPreferences({
required this.geniusAccessToken,
required this.recommendationMarket,
@ -51,7 +59,8 @@ class UserPreferences extends PersistedChangeNotifier {
this.audioQuality = AudioQuality.high,
this.skipSponsorSegments = true,
this.downloadLocation = "",
this.rotatingAlbumArt = true,
this.closeBehavior = CloseBehavior.minimizeToTray,
this.showSystemTrayIcon = true,
}) : super() {
if (downloadLocation.isEmpty) {
_getDefaultDownloadDirectory().then(
@ -134,8 +143,14 @@ class UserPreferences extends PersistedChangeNotifier {
updatePersistence();
}
void setRotatingAlbumArt(bool should) {
rotatingAlbumArt = should;
void setCloseBehavior(CloseBehavior behavior) {
closeBehavior = behavior;
notifyListeners();
updatePersistence();
}
void setShowSystemTrayIcon(bool show) {
showSystemTrayIcon = show;
notifyListeners();
updatePersistence();
}
@ -175,8 +190,14 @@ class UserPreferences extends PersistedChangeNotifier {
(mode) => mode.name == map["layoutMode"],
orElse: () => kIsDesktop ? LayoutMode.extended : LayoutMode.compact,
);
rotatingAlbumArt = map["rotatingAlbumArt"] ?? rotatingAlbumArt;
predownload = map["predownload"] ?? predownload;
closeBehavior = map["closeBehavior"] != null
? CloseBehavior.values[map["closeBehavior"]]
: closeBehavior;
showSystemTrayIcon = map["showSystemTrayIcon"] ?? showSystemTrayIcon;
}
@override
@ -192,8 +213,9 @@ class UserPreferences extends PersistedChangeNotifier {
"skipSponsorSegments": skipSponsorSegments,
"downloadLocation": downloadLocation,
"layoutMode": layoutMode.name,
"rotatingAlbumArt": rotatingAlbumArt,
"predownload": predownload,
"closeBehavior": closeBehavior.index,
"showSystemTrayIcon": showSystemTrayIcon,
};
}
}

View File

@ -8,8 +8,11 @@
#include <audioplayers_linux/audioplayers_linux_plugin.h>
#include <catcher/catcher_plugin.h>
#include <desktop_multi_window/desktop_multi_window_plugin.h>
#include <native_context_menu/native_context_menu_plugin.h>
#include <screen_retriever/screen_retriever_plugin.h>
#include <system_theme/system_theme_plugin.h>
#include <system_tray/system_tray_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
#include <window_manager/window_manager_plugin.h>
#include <window_size/window_size_plugin.h>
@ -21,12 +24,21 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) catcher_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "CatcherPlugin");
catcher_plugin_register_with_registrar(catcher_registrar);
g_autoptr(FlPluginRegistrar) desktop_multi_window_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopMultiWindowPlugin");
desktop_multi_window_plugin_register_with_registrar(desktop_multi_window_registrar);
g_autoptr(FlPluginRegistrar) native_context_menu_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "NativeContextMenuPlugin");
native_context_menu_plugin_register_with_registrar(native_context_menu_registrar);
g_autoptr(FlPluginRegistrar) screen_retriever_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
screen_retriever_plugin_register_with_registrar(screen_retriever_registrar);
g_autoptr(FlPluginRegistrar) system_theme_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "SystemThemePlugin");
system_theme_plugin_register_with_registrar(system_theme_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);

View File

@ -5,8 +5,11 @@
list(APPEND FLUTTER_PLUGIN_LIST
audioplayers_linux
catcher
desktop_multi_window
native_context_menu
screen_retriever
system_theme
system_tray
url_launcher_linux
window_manager
window_size

View File

@ -9,13 +9,16 @@ import audio_service
import audio_session
import audioplayers_darwin
import catcher
import desktop_multi_window
import device_info_plus
import native_context_menu
import package_info_plus
import path_provider_foundation
import screen_retriever
import shared_preferences_foundation
import sqflite
import system_theme
import system_tray
import url_launcher_macos
import window_manager
import window_size
@ -25,13 +28,16 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
CatcherPlugin.register(with: registry.registrar(forPlugin: "CatcherPlugin"))
FlutterMultiWindowPlugin.register(with: registry.registrar(forPlugin: "FlutterMultiWindowPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
NativeContextMenuPlugin.register(with: registry.registrar(forPlugin: "NativeContextMenuPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
SystemThemePlugin.register(with: registry.registrar(forPlugin: "SystemThemePlugin"))
SystemTrayPlugin.register(with: registry.registrar(forPlugin: "SystemTrayPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin"))

View File

@ -466,6 +466,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.7.8"
desktop_multi_window:
dependency: transitive
description:
name: desktop_multi_window
sha256: "29971186ae0790e32b156f127f9c22c5ee77bdb94b14f7cea23f2356d0c76cfc"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
device_info_plus:
dependency: transitive
description:
@ -599,6 +607,13 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.3.0"
flutter_desktop_tools:
dependency: "direct main"
description:
path: "../flutter_desktop_tools"
relative: true
source: path
version: "0.0.1"
flutter_distributor:
dependency: "direct dev"
description:
@ -1000,6 +1015,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.1"
native_context_menu:
dependency: transitive
description:
name: native_context_menu
sha256: "566f13d1f55e57bc8aca3b71b157b1ff03c2cc3821f6e9d980f76233ed30c9b7"
url: "https://pub.dev"
source: hosted
version: "0.2.2+5"
oauth2:
dependency: transitive
description:
@ -1324,58 +1347,58 @@ packages:
dependency: "direct main"
description:
name: shared_preferences
sha256: "5949029e70abe87f75cfe59d17bf5c397619c4b74a099b10116baeb34786fad9"
sha256: "858aaa72d8f61637d64e776aca82e1c67e6d9ee07979123c5d17115031c1b13b"
url: "https://pub.dev"
source: hosted
version: "2.0.17"
version: "2.1.0"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: "955e9736a12ba776bdd261cf030232b30eadfcd9c79b32a3250dd4a494e8c8f7"
sha256: "8304d8a1f7d21a429f91dee552792249362b68a331ac5c3c1caf370f658873f6"
url: "https://pub.dev"
source: hosted
version: "2.0.15"
version: "2.1.0"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: "2b55c18636a4edc529fa5cd44c03d3f3100c00513f518c5127c951978efcccd0"
sha256: cf2a42fb20148502022861f71698db12d937c7459345a1bdaa88fc91a91b3603
url: "https://pub.dev"
source: hosted
version: "2.1.3"
version: "2.2.0"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
sha256: f8ea038aa6da37090093974ebdcf4397010605fd2ff65c37a66f9d28394cb874
sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa"
url: "https://pub.dev"
source: hosted
version: "2.1.3"
version: "2.2.0"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: da9431745ede5ece47bc26d5d73a9d3c6936ef6945c101a5aca46f62e52c1cf3
sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d
url: "https://pub.dev"
source: hosted
version: "2.1.0"
version: "2.2.0"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
sha256: a4b5bc37fe1b368bbc81f953197d55e12f49d0296e7e412dfe2d2d77d6929958
sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5"
url: "https://pub.dev"
source: hosted
version: "2.0.4"
version: "2.1.0"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
sha256: "5eaf05ae77658d3521d0e993ede1af962d4b326cd2153d312df716dc250f00c9"
sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173"
url: "https://pub.dev"
source: hosted
version: "2.1.3"
version: "2.2.0"
shelf:
dependency: transitive
description:
@ -1550,6 +1573,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.0.2"
system_tray:
dependency: transitive
description:
name: system_tray
sha256: "087edb877f22f286d82d42f330fa640138c192e98aa9d20c2b83aa4e406bb432"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
term_glyph:
dependency: transitive
description:
@ -1808,5 +1839,5 @@ packages:
source: hosted
version: "1.12.3"
sdks:
dart: ">=2.19.2 <3.0.0"
dart: ">=2.19.6 <3.0.0"
flutter: ">=3.3.0"

View File

@ -82,6 +82,8 @@ dependencies:
ref: a738913c8ce2c9f47515382d40827e794a334274
path: plugins/window_size
youtube_explode_dart: ^1.12.1
flutter_desktop_tools:
path: ../flutter_desktop_tools
dev_dependencies:
build_runner: ^2.3.2

View File

@ -8,9 +8,12 @@
#include <audioplayers_windows/audioplayers_windows_plugin.h>
#include <catcher/catcher_plugin.h>
#include <desktop_multi_window/desktop_multi_window_plugin.h>
#include <native_context_menu/native_context_menu_plugin.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
#include <screen_retriever/screen_retriever_plugin.h>
#include <system_theme/system_theme_plugin.h>
#include <system_tray/system_tray_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h>
#include <window_manager/window_manager_plugin.h>
#include <window_size/window_size_plugin.h>
@ -20,12 +23,18 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin"));
CatcherPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("CatcherPlugin"));
DesktopMultiWindowPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("DesktopMultiWindowPlugin"));
NativeContextMenuPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("NativeContextMenuPlugin"));
PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
ScreenRetrieverPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
SystemThemePluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SystemThemePlugin"));
SystemTrayPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SystemTrayPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
WindowManagerPluginRegisterWithRegistrar(

View File

@ -5,9 +5,12 @@
list(APPEND FLUTTER_PLUGIN_LIST
audioplayers_windows
catcher
desktop_multi_window
native_context_menu
permission_handler_windows
screen_retriever
system_theme
system_tray
url_launcher_windows
window_manager
window_size