mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
feat: system tray support (#31)
This commit is contained in:
parent
5e47faa606
commit
06a043764d
BIN
assets/spotube-logo.ico
Normal file
BIN
assets/spotube-logo.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
125
lib/hooks/use_init_sys_tray.dart
Normal file
125
lib/hooks/use_init_sys_tray.dart
Normal 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]);
|
||||
}
|
@ -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 () {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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"))
|
||||
|
61
pubspec.lock
61
pubspec.lock
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user