mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
parent
6907f9c756
commit
7ac791757a
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"flutterSdkVersion": "3.19.1",
|
"flutterSdkVersion": "3.19.5",
|
||||||
"flavors": {}
|
"flavors": {}
|
||||||
}
|
}
|
2
.github/workflows/spotube-publish-binary.yml
vendored
2
.github/workflows/spotube-publish-binary.yml
vendored
@ -4,7 +4,7 @@ on:
|
|||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
description: Version to publish (x.x.x)
|
description: Version to publish (x.x.x)
|
||||||
default: 3.1.0
|
default: 3.6.0
|
||||||
required: true
|
required: true
|
||||||
dry_run:
|
dry_run:
|
||||||
description: Dry run
|
description: Dry run
|
||||||
|
2
.github/workflows/spotube-release-binary.yml
vendored
2
.github/workflows/spotube-release-binary.yml
vendored
@ -26,7 +26,7 @@ on:
|
|||||||
default: true
|
default: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
FLUTTER_VERSION: '3.19.1'
|
FLUTTER_VERSION: '3.19.5'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
windows:
|
windows:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'package:envied/envied.dart';
|
import 'package:envied/envied.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
part 'env.g.dart';
|
part 'env.g.dart';
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ abstract class Env {
|
|||||||
static final String _enableUpdateChecker = _Env._enableUpdateChecker;
|
static final String _enableUpdateChecker = _Env._enableUpdateChecker;
|
||||||
|
|
||||||
static bool get enableUpdateChecker =>
|
static bool get enableUpdateChecker =>
|
||||||
DesktopTools.platform.isFlatpak || _enableUpdateChecker == "1";
|
kIsFlatpak || _enableUpdateChecker == "1";
|
||||||
|
|
||||||
static String discordAppId = "1176718791388975124";
|
static String discordAppId = "1176718791388975124";
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
import 'package:win32_registry/win32_registry.dart';
|
import 'package:win32_registry/win32_registry.dart';
|
||||||
|
|
||||||
Future<void> registerWindowsScheme(String scheme) async {
|
Future<void> registerWindowsScheme(String scheme) async {
|
||||||
if (!DesktopTools.platform.isWindows) return;
|
if (!kIsWindows) return;
|
||||||
String appPath = Platform.resolvedExecutable;
|
String appPath = Platform.resolvedExecutable;
|
||||||
|
|
||||||
String protocolRegKey = 'Software\\Classes\\$scheme';
|
String protocolRegKey = 'Software\\Classes\\$scheme';
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@ -24,6 +23,7 @@ import 'package:spotube/provider/user_preferences/user_preferences_provider.dart
|
|||||||
import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
|
import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
|
||||||
import 'package:spotube/provider/volume_provider.dart';
|
import 'package:spotube/provider/volume_provider.dart';
|
||||||
import 'package:spotube/utils/platform.dart';
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
class BottomPlayer extends HookConsumerWidget {
|
class BottomPlayer extends HookConsumerWidget {
|
||||||
BottomPlayer({super.key});
|
BottomPlayer({super.key});
|
||||||
@ -95,19 +95,19 @@ class BottomPlayer extends HookConsumerWidget {
|
|||||||
tooltip: context.l10n.mini_player,
|
tooltip: context.l10n.mini_player,
|
||||||
icon: const Icon(SpotubeIcons.miniPlayer),
|
icon: const Icon(SpotubeIcons.miniPlayer),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final prevSize =
|
if (!kIsDesktop) return;
|
||||||
await DesktopTools.window.getSize();
|
|
||||||
await DesktopTools.window.setMinimumSize(
|
final prevSize = await windowManager.getSize();
|
||||||
|
await windowManager.setMinimumSize(
|
||||||
const Size(300, 300),
|
const Size(300, 300),
|
||||||
);
|
);
|
||||||
await DesktopTools.window.setAlwaysOnTop(true);
|
await windowManager.setAlwaysOnTop(true);
|
||||||
if (!kIsLinux) {
|
if (!kIsLinux) {
|
||||||
await DesktopTools.window.setHasShadow(false);
|
await windowManager.setHasShadow(false);
|
||||||
}
|
}
|
||||||
await DesktopTools.window
|
await windowManager
|
||||||
.setAlignment(Alignment.topRight);
|
.setAlignment(Alignment.topRight);
|
||||||
await DesktopTools.window
|
await windowManager.setSize(const Size(400, 500));
|
||||||
.setSize(const Size(400, 500));
|
|
||||||
await Future.delayed(
|
await Future.delayed(
|
||||||
const Duration(milliseconds: 100),
|
const Duration(milliseconds: 100),
|
||||||
() async {
|
() async {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
|
import 'package:draggable_scrollbar/draggable_scrollbar.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
class InterScrollbar extends HookWidget {
|
class InterScrollbar extends HookWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
@ -15,7 +15,7 @@ class InterScrollbar extends HookWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (DesktopTools.platform.isDesktop) return child;
|
if (kIsDesktop) return child;
|
||||||
|
|
||||||
return DraggableScrollbar.semicircle(
|
return DraggableScrollbar.semicircle(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
|
@ -7,7 +7,8 @@ import 'package:titlebar_buttons/titlebar_buttons.dart';
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||||
import 'dart:io' show Platform;
|
import 'dart:io' show Platform;
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
class PageWindowTitleBar extends StatefulHookConsumerWidget
|
class PageWindowTitleBar extends StatefulHookConsumerWidget
|
||||||
implements PreferredSizeWidget {
|
implements PreferredSizeWidget {
|
||||||
@ -89,7 +90,7 @@ class _PageWindowTitleBarState extends ConsumerState<PageWindowTitleBar> {
|
|||||||
final systemTitleBar =
|
final systemTitleBar =
|
||||||
ref.read(userPreferencesProvider.select((s) => s.systemTitleBar));
|
ref.read(userPreferencesProvider.select((s) => s.systemTitleBar));
|
||||||
if (kIsDesktop && !systemTitleBar) {
|
if (kIsDesktop && !systemTitleBar) {
|
||||||
DesktopTools.window.startDragging();
|
windowManager.startDragging();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,11 +108,7 @@ class _PageWindowTitleBarState extends ConsumerState<PageWindowTitleBar> {
|
|||||||
|
|
||||||
return SliverPadding(
|
return SliverPadding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
left: DesktopTools.platform.isMacOS &&
|
left: kIsMacOS && hasFullscreen && hasLeadingOrCanPop ? 65 : 0,
|
||||||
hasFullscreen &&
|
|
||||||
hasLeadingOrCanPop
|
|
||||||
? 65
|
|
||||||
: 0,
|
|
||||||
),
|
),
|
||||||
sliver: SliverAppBar(
|
sliver: SliverAppBar(
|
||||||
leading: widget.leading,
|
leading: widget.leading,
|
||||||
@ -149,11 +146,7 @@ class _PageWindowTitleBarState extends ConsumerState<PageWindowTitleBar> {
|
|||||||
onVerticalDragStart: onDrag,
|
onVerticalDragStart: onDrag,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
left: DesktopTools.platform.isMacOS &&
|
left: kIsMacOS && hasFullscreen && hasLeadingOrCanPop ? 65 : 0,
|
||||||
hasFullscreen &&
|
|
||||||
hasLeadingOrCanPop
|
|
||||||
? 65
|
|
||||||
: 0,
|
|
||||||
),
|
),
|
||||||
child: AppBar(
|
child: AppBar(
|
||||||
leading: widget.leading,
|
leading: widget.leading,
|
||||||
@ -193,12 +186,12 @@ class WindowTitleBarButtons extends HookConsumerWidget {
|
|||||||
const type = ThemeType.auto;
|
const type = ThemeType.auto;
|
||||||
|
|
||||||
Future<void> onClose() async {
|
Future<void> onClose() async {
|
||||||
await DesktopTools.window.close();
|
await windowManager.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
if (kIsDesktop) {
|
if (kIsDesktop) {
|
||||||
DesktopTools.window.isMaximized().then((value) {
|
windowManager.isMaximized().then((value) {
|
||||||
isMaximized.value = value;
|
isMaximized.value = value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -235,14 +228,14 @@ class WindowTitleBarButtons extends HookConsumerWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
MinimizeWindowButton(
|
MinimizeWindowButton(
|
||||||
onPressed: DesktopTools.window.minimize,
|
onPressed: windowManager.minimize,
|
||||||
colors: colors,
|
colors: colors,
|
||||||
),
|
),
|
||||||
if (isMaximized.value != true)
|
if (isMaximized.value != true)
|
||||||
MaximizeWindowButton(
|
MaximizeWindowButton(
|
||||||
colors: colors,
|
colors: colors,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
DesktopTools.window.maximize();
|
windowManager.maximize();
|
||||||
isMaximized.value = true;
|
isMaximized.value = true;
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -250,7 +243,7 @@ class WindowTitleBarButtons extends HookConsumerWidget {
|
|||||||
RestoreWindowButton(
|
RestoreWindowButton(
|
||||||
colors: colors,
|
colors: colors,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
DesktopTools.window.unmaximize();
|
windowManager.unmaximize();
|
||||||
isMaximized.value = false;
|
isMaximized.value = false;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -270,16 +263,16 @@ class WindowTitleBarButtons extends HookConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
DecoratedMinimizeButton(
|
DecoratedMinimizeButton(
|
||||||
type: type,
|
type: type,
|
||||||
onPressed: DesktopTools.window.minimize,
|
onPressed: windowManager.minimize,
|
||||||
),
|
),
|
||||||
DecoratedMaximizeButton(
|
DecoratedMaximizeButton(
|
||||||
type: type,
|
type: type,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (await DesktopTools.window.isMaximized()) {
|
if (await windowManager.isMaximized()) {
|
||||||
await DesktopTools.window.unmaximize();
|
await windowManager.unmaximize();
|
||||||
isMaximized.value = false;
|
isMaximized.value = false;
|
||||||
} else {
|
} else {
|
||||||
await DesktopTools.window.maximize();
|
await windowManager.maximize();
|
||||||
isMaximized.value = true;
|
isMaximized.value = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:spotube/collections/assets.gen.dart';
|
import 'package:spotube/collections/assets.gen.dart';
|
||||||
import 'package:spotube/components/shared/image/universal_image.dart';
|
import 'package:spotube/components/shared/image/universal_image.dart';
|
||||||
@ -12,6 +12,7 @@ import 'package:spotube/components/shared/tracks_view/track_view_props.dart';
|
|||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:spotube/extensions/constrains.dart';
|
import 'package:spotube/extensions/constrains.dart';
|
||||||
import 'package:spotube/hooks/utils/use_palette_color.dart';
|
import 'package:spotube/hooks/utils/use_palette_color.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
class TrackViewFlexHeader extends HookConsumerWidget {
|
class TrackViewFlexHeader extends HookConsumerWidget {
|
||||||
const TrackViewFlexHeader({super.key});
|
const TrackViewFlexHeader({super.key});
|
||||||
@ -53,7 +54,7 @@ class TrackViewFlexHeader extends HookConsumerWidget {
|
|||||||
floating: false,
|
floating: false,
|
||||||
pinned: true,
|
pinned: true,
|
||||||
expandedHeight: 450,
|
expandedHeight: 450,
|
||||||
automaticallyImplyLeading: DesktopTools.platform.isMobile,
|
automaticallyImplyLeading: kIsMobile,
|
||||||
backgroundColor: palette.color,
|
backgroundColor: palette.color,
|
||||||
title: isExpanded ? null : Text(props.title, style: headingStyle),
|
title: isExpanded ? null : Text(props.title, style: headingStyle),
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.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:sliver_tools/sliver_tools.dart';
|
import 'package:sliver_tools/sliver_tools.dart';
|
||||||
@ -8,6 +8,7 @@ import 'package:spotube/components/shared/page_window_title_bar.dart';
|
|||||||
import 'package:spotube/components/shared/tracks_view/sections/header/flexible_header.dart';
|
import 'package:spotube/components/shared/tracks_view/sections/header/flexible_header.dart';
|
||||||
import 'package:spotube/components/shared/tracks_view/sections/body/track_view_body.dart';
|
import 'package:spotube/components/shared/tracks_view/sections/body/track_view_body.dart';
|
||||||
import 'package:spotube/components/shared/tracks_view/track_view_props.dart';
|
import 'package:spotube/components/shared/tracks_view/track_view_props.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
class TrackView extends HookConsumerWidget {
|
class TrackView extends HookConsumerWidget {
|
||||||
const TrackView({super.key});
|
const TrackView({super.key});
|
||||||
@ -18,7 +19,7 @@ class TrackView extends HookConsumerWidget {
|
|||||||
final controller = useScrollController();
|
final controller = useScrollController();
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: DesktopTools.platform.isDesktop
|
appBar: kIsDesktop
|
||||||
? const PageWindowTitleBar(
|
? const PageWindowTitleBar(
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
|
@ -1,29 +1,31 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:spotube/hooks/configurators/use_window_listener.dart';
|
import 'package:spotube/hooks/configurators/use_window_listener.dart';
|
||||||
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
||||||
import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
|
import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
|
||||||
// ignore: depend_on_referenced_packages
|
|
||||||
import 'package:local_notifier/local_notifier.dart';
|
import 'package:local_notifier/local_notifier.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
final closeNotification = DesktopTools.createNotification(
|
final closeNotification = !kIsDesktop
|
||||||
title: 'Spotube',
|
? null
|
||||||
message: 'Running in background. Minimized to System Tray',
|
: (LocalNotification(
|
||||||
actions: [
|
title: 'Spotube',
|
||||||
LocalNotificationAction(text: 'Close The App'),
|
body: 'Running in background. Minimized to System Tray',
|
||||||
],
|
actions: [
|
||||||
)?..onClickAction = (value) {
|
LocalNotificationAction(text: 'Close The App'),
|
||||||
exit(0);
|
],
|
||||||
};
|
)..onClickAction = (value) {
|
||||||
|
exit(0);
|
||||||
|
});
|
||||||
|
|
||||||
void useCloseBehavior(WidgetRef ref) {
|
void useCloseBehavior(WidgetRef ref) {
|
||||||
useWindowListener(
|
useWindowListener(
|
||||||
onWindowClose: () async {
|
onWindowClose: () async {
|
||||||
final preferences = ref.read(userPreferencesProvider);
|
final preferences = ref.read(userPreferencesProvider);
|
||||||
if (preferences.closeBehavior == CloseBehavior.minimizeToTray) {
|
if (preferences.closeBehavior == CloseBehavior.minimizeToTray) {
|
||||||
await DesktopTools.window.hide();
|
await windowManager.hide();
|
||||||
closeNotification?.show();
|
closeNotification?.show();
|
||||||
} else {
|
} else {
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -7,7 +7,7 @@ import 'package:spotube/collections/routes.dart';
|
|||||||
import 'package:spotube/provider/spotify_provider.dart';
|
import 'package:spotube/provider/spotify_provider.dart';
|
||||||
import 'package:flutter_sharing_intent/flutter_sharing_intent.dart';
|
import 'package:flutter_sharing_intent/flutter_sharing_intent.dart';
|
||||||
import 'package:flutter_sharing_intent/model/sharing_file.dart';
|
import 'package:flutter_sharing_intent/model/sharing_file.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
final appLinks = AppLinks();
|
final appLinks = AppLinks();
|
||||||
final linkStream = appLinks.allStringLinkStream.asBroadcastStream();
|
final linkStream = appLinks.allStringLinkStream.asBroadcastStream();
|
||||||
@ -53,7 +53,7 @@ void useDeepLinking(WidgetRef ref) {
|
|||||||
|
|
||||||
StreamSubscription? mediaStream;
|
StreamSubscription? mediaStream;
|
||||||
|
|
||||||
if (DesktopTools.platform.isMobile) {
|
if (kIsMobile) {
|
||||||
FlutterSharingIntent.instance.getInitialSharing().then(uriListener);
|
FlutterSharingIntent.instance.getInitialSharing().then(uriListener);
|
||||||
|
|
||||||
mediaStream =
|
mediaStream =
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import 'package:disable_battery_optimization/disable_battery_optimization.dart';
|
import 'package:disable_battery_optimization/disable_battery_optimization.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:spotube/hooks/utils/use_async_effect.dart';
|
import 'package:spotube/hooks/utils/use_async_effect.dart';
|
||||||
import 'package:spotube/services/kv_store/kv_store.dart';
|
import 'package:spotube/services/kv_store/kv_store.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
void useDisableBatteryOptimizations() {
|
void useDisableBatteryOptimizations() {
|
||||||
useAsyncEffect(() async {
|
useAsyncEffect(() async {
|
||||||
if (!DesktopTools.platform.isAndroid ||
|
if (!kIsAndroid || KVStoreService.askedForBatteryOptimization) return;
|
||||||
KVStoreService.askedForBatteryOptimization) return;
|
|
||||||
|
|
||||||
await DisableBatteryOptimization.showDisableBatteryOptimizationSettings();
|
await DisableBatteryOptimization.showDisableBatteryOptimizationSettings();
|
||||||
|
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.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:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:spotube/components/library/user_local_tracks.dart';
|
import 'package:spotube/components/library/user_local_tracks.dart';
|
||||||
import 'package:spotube/hooks/utils/use_async_effect.dart';
|
import 'package:spotube/hooks/utils/use_async_effect.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
void useGetStoragePermissions(WidgetRef ref) {
|
void useGetStoragePermissions(WidgetRef ref) {
|
||||||
final context = useContext();
|
final context = useContext();
|
||||||
|
|
||||||
useAsyncEffect(
|
useAsyncEffect(
|
||||||
() async {
|
() async {
|
||||||
if (!DesktopTools.platform.isMobile) return;
|
if (!kIsMobile) return;
|
||||||
|
|
||||||
final androidInfo = await DeviceInfoPlugin().androidInfo;
|
final androidInfo = await DeviceInfoPlugin().androidInfo;
|
||||||
|
|
||||||
|
@ -1,128 +0,0 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
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/proxy_playlist/proxy_playlist.dart';
|
|
||||||
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
|
|
||||||
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
|
||||||
|
|
||||||
void useInitSysTray(WidgetRef ref) {
|
|
||||||
final context = useContext();
|
|
||||||
final systemTray = useRef<SystemTray?>(null);
|
|
||||||
|
|
||||||
final initializeMenu = useCallback(() async {
|
|
||||||
systemTray.value?.destroy();
|
|
||||||
final playlist = ref.read(proxyPlaylistProvider);
|
|
||||||
final playlistQueue = ref.read(proxyPlaylistProvider.notifier);
|
|
||||||
final preferences = ref.read(userPreferencesProvider);
|
|
||||||
if (!preferences.showSystemTrayIcon) {
|
|
||||||
await systemTray.value?.destroy();
|
|
||||||
systemTray.value = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final enabled = !playlist.isFetching;
|
|
||||||
systemTray.value = await DesktopTools.createSystemTrayMenu(
|
|
||||||
title: DesktopTools.platform.isWindows ? "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 && (playlist.tracks.length) > 1,
|
|
||||||
onClicked: (p0) async {
|
|
||||||
await playlistQueue.next();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
MenuItemLabel(
|
|
||||||
label: "Previous",
|
|
||||||
name: "previous",
|
|
||||||
enabled: enabled && (playlist.tracks.length) > 1,
|
|
||||||
onClicked: (p0) async {
|
|
||||||
await playlistQueue.previous();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
MenuSeparator(),
|
|
||||||
MenuItemLabel(
|
|
||||||
label: "Quit",
|
|
||||||
name: "quit",
|
|
||||||
onClicked: (item) async {
|
|
||||||
exit(0);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
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<ProxyPlaylist?>(
|
|
||||||
proxyPlaylistProvider,
|
|
||||||
(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,6 +1,8 @@
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
class CallbackWindowListener implements WindowListener {
|
class CallbackWindowListener implements WindowListener {
|
||||||
final VoidCallback? _onWindowClose;
|
final VoidCallback? _onWindowClose;
|
||||||
@ -154,6 +156,8 @@ void useWindowListener({
|
|||||||
VoidCallback? onWindowEvent,
|
VoidCallback? onWindowEvent,
|
||||||
}) {
|
}) {
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
|
if (!kIsDesktop) return null;
|
||||||
|
|
||||||
final listener = CallbackWindowListener(
|
final listener = CallbackWindowListener(
|
||||||
onWindowClose: onWindowClose,
|
onWindowClose: onWindowClose,
|
||||||
onWindowFocus: onWindowFocus,
|
onWindowFocus: onWindowFocus,
|
||||||
@ -172,9 +176,9 @@ void useWindowListener({
|
|||||||
onWindowUndocked: onWindowUndocked,
|
onWindowUndocked: onWindowUndocked,
|
||||||
onWindowEvent: onWindowEvent,
|
onWindowEvent: onWindowEvent,
|
||||||
);
|
);
|
||||||
DesktopTools.window.addListener(listener);
|
windowManager.addListener(listener);
|
||||||
return () {
|
return () {
|
||||||
DesktopTools.window.removeListener(listener);
|
windowManager.removeListener(listener);
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
onWindowClose,
|
onWindowClose,
|
||||||
|
@ -4,11 +4,11 @@ import 'package:device_preview/device_preview.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:local_notifier/local_notifier.dart';
|
||||||
import 'package:media_kit/media_kit.dart';
|
import 'package:media_kit/media_kit.dart';
|
||||||
import 'package:metadata_god/metadata_god.dart';
|
import 'package:metadata_god/metadata_god.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
@ -19,6 +19,7 @@ import 'package:spotube/hooks/configurators/use_close_behavior.dart';
|
|||||||
import 'package:spotube/hooks/configurators/use_deep_linking.dart';
|
import 'package:spotube/hooks/configurators/use_deep_linking.dart';
|
||||||
import 'package:spotube/hooks/configurators/use_disable_battery_optimizations.dart';
|
import 'package:spotube/hooks/configurators/use_disable_battery_optimizations.dart';
|
||||||
import 'package:spotube/hooks/configurators/use_get_storage_perms.dart';
|
import 'package:spotube/hooks/configurators/use_get_storage_perms.dart';
|
||||||
|
import 'package:spotube/provider/tray_manager/tray_manager.dart';
|
||||||
import 'package:spotube/l10n/l10n.dart';
|
import 'package:spotube/l10n/l10n.dart';
|
||||||
import 'package:spotube/models/logger.dart';
|
import 'package:spotube/models/logger.dart';
|
||||||
import 'package:spotube/models/skip_segment.dart';
|
import 'package:spotube/models/skip_segment.dart';
|
||||||
@ -31,15 +32,17 @@ import 'package:spotube/provider/user_preferences/user_preferences_provider.dart
|
|||||||
import 'package:spotube/services/audio_player/audio_player.dart';
|
import 'package:spotube/services/audio_player/audio_player.dart';
|
||||||
import 'package:spotube/services/cli/cli.dart';
|
import 'package:spotube/services/cli/cli.dart';
|
||||||
import 'package:spotube/services/kv_store/kv_store.dart';
|
import 'package:spotube/services/kv_store/kv_store.dart';
|
||||||
|
import 'package:spotube/services/wm_tools/wm_tools.dart';
|
||||||
import 'package:spotube/themes/theme.dart';
|
import 'package:spotube/themes/theme.dart';
|
||||||
import 'package:spotube/utils/persisted_state_notifier.dart';
|
import 'package:spotube/utils/persisted_state_notifier.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
import 'package:system_theme/system_theme.dart';
|
import 'package:system_theme/system_theme.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:spotube/hooks/configurators/use_init_sys_tray.dart';
|
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||||
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
import 'package:flutter_displaymode/flutter_displaymode.dart';
|
||||||
import 'package:timezone/data/latest.dart' as tz;
|
import 'package:timezone/data/latest.dart' as tz;
|
||||||
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
Future<void> main(List<String> rawArgs) async {
|
Future<void> main(List<String> rawArgs) async {
|
||||||
final arguments = await startCLI(rawArgs);
|
final arguments = await startCLI(rawArgs);
|
||||||
@ -55,12 +58,12 @@ Future<void> main(List<String> rawArgs) async {
|
|||||||
MediaKit.ensureInitialized();
|
MediaKit.ensureInitialized();
|
||||||
|
|
||||||
// force High Refresh Rate on some Android devices (like One Plus)
|
// force High Refresh Rate on some Android devices (like One Plus)
|
||||||
if (DesktopTools.platform.isAndroid) {
|
if (kIsAndroid) {
|
||||||
await FlutterDisplayMode.setHighRefreshRate();
|
await FlutterDisplayMode.setHighRefreshRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DesktopTools.platform.isDesktop) {
|
if (kIsDesktop) {
|
||||||
await DesktopTools.window.setPreventClose(true);
|
await windowManager.setPreventClose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
await SystemTheme.accentColor.load();
|
await SystemTheme.accentColor.load();
|
||||||
@ -69,7 +72,7 @@ Future<void> main(List<String> rawArgs) async {
|
|||||||
MetadataGod.initialize();
|
MetadataGod.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DesktopTools.platform.isWindows || DesktopTools.platform.isLinux) {
|
if (kIsWindows || kIsLinux) {
|
||||||
DiscordRPC.initialize();
|
DiscordRPC.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,14 +104,10 @@ Future<void> main(List<String> rawArgs) async {
|
|||||||
path: hiveCacheDir,
|
path: hiveCacheDir,
|
||||||
);
|
);
|
||||||
|
|
||||||
await DesktopTools.ensureInitialized(
|
if (kIsDesktop) {
|
||||||
DesktopWindowOptions(
|
await localNotifier.setup(appName: "Spotube");
|
||||||
hideTitleBar: true,
|
await WindowManagerTools.initialize();
|
||||||
title: "Spotube",
|
}
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
minimumSize: const Size(300, 700),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
Catcher2(
|
Catcher2(
|
||||||
enableLogger: arguments["verbose"],
|
enableLogger: arguments["verbose"],
|
||||||
@ -189,9 +188,9 @@ class SpotubeState extends ConsumerState<Spotube> {
|
|||||||
ref.listen(playbackServerProvider, (_, __) {});
|
ref.listen(playbackServerProvider, (_, __) {});
|
||||||
ref.listen(connectServerProvider, (_, __) {});
|
ref.listen(connectServerProvider, (_, __) {});
|
||||||
ref.listen(connectClientsProvider, (_, __) {});
|
ref.listen(connectClientsProvider, (_, __) {});
|
||||||
|
ref.listen(trayManagerProvider, (_, __) {});
|
||||||
|
|
||||||
useDisableBatteryOptimizations();
|
useDisableBatteryOptimizations();
|
||||||
useInitSysTray(ref);
|
|
||||||
useDeepLinking(ref);
|
useDeepLinking(ref);
|
||||||
useCloseBehavior(ref);
|
useCloseBehavior(ref);
|
||||||
useGetStoragePermissions(ref);
|
useGetStoragePermissions(ref);
|
||||||
@ -233,9 +232,7 @@ class SpotubeState extends ConsumerState<Spotube> {
|
|||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return DevicePreview.appBuilder(
|
return DevicePreview.appBuilder(
|
||||||
context,
|
context,
|
||||||
DesktopTools.platform.isDesktop && !DesktopTools.platform.isMacOS
|
kIsDesktop && !kIsMacOS ? DragToResizeArea(child: child!) : child,
|
||||||
? DragToResizeArea(child: child!)
|
|
||||||
: child,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
themeMode: themeMode,
|
themeMode: themeMode,
|
||||||
|
@ -12,7 +12,7 @@ part of 'connect.dart';
|
|||||||
T _$identity<T>(T value) => value;
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
final _privateConstructorUsedError = UnsupportedError(
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||||
|
|
||||||
WebSocketLoadEventData _$WebSocketLoadEventDataFromJson(
|
WebSocketLoadEventData _$WebSocketLoadEventDataFromJson(
|
||||||
Map<String, dynamic> json) {
|
Map<String, dynamic> json) {
|
||||||
|
@ -12,7 +12,7 @@ part of 'home_feed.dart';
|
|||||||
T _$identity<T>(T value) => value;
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
final _privateConstructorUsedError = UnsupportedError(
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||||
|
|
||||||
SpotifySectionPlaylist _$SpotifySectionPlaylistFromJson(
|
SpotifySectionPlaylist _$SpotifySectionPlaylistFromJson(
|
||||||
Map<String, dynamic> json) {
|
Map<String, dynamic> json) {
|
||||||
|
@ -12,7 +12,7 @@ part of 'recommendation_seeds.dart';
|
|||||||
T _$identity<T>(T value) => value;
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
final _privateConstructorUsedError = UnsupportedError(
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$GeneratePlaylistProviderInput {
|
mixin _$GeneratePlaylistProviderInput {
|
||||||
|
@ -12,7 +12,7 @@ import 'package:spotube/components/shared/waypoint.dart';
|
|||||||
import 'package:spotube/extensions/constrains.dart';
|
import 'package:spotube/extensions/constrains.dart';
|
||||||
import 'package:spotube/provider/spotify/spotify.dart';
|
import 'package:spotube/provider/spotify/spotify.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
class GenrePlaylistsPage extends HookConsumerWidget {
|
class GenrePlaylistsPage extends HookConsumerWidget {
|
||||||
final Category category;
|
final Category category;
|
||||||
@ -27,7 +27,7 @@ class GenrePlaylistsPage extends HookConsumerWidget {
|
|||||||
final scrollController = useScrollController();
|
final scrollController = useScrollController();
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: DesktopTools.platform.isDesktop
|
appBar: kIsDesktop
|
||||||
? const PageWindowTitleBar(
|
? const PageWindowTitleBar(
|
||||||
leading: BackButton(color: Colors.white),
|
leading: BackButton(color: Colors.white),
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
@ -53,12 +53,12 @@ class GenrePlaylistsPage extends HookConsumerWidget {
|
|||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverAppBar(
|
SliverAppBar(
|
||||||
automaticallyImplyLeading: DesktopTools.platform.isMobile,
|
automaticallyImplyLeading: kIsMobile,
|
||||||
expandedHeight: mediaQuery.mdAndDown ? 200 : 150,
|
expandedHeight: mediaQuery.mdAndDown ? 200 : 150,
|
||||||
title: const Text(""),
|
title: const Text(""),
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
centerTitle: DesktopTools.platform.isDesktop,
|
centerTitle: kIsDesktop,
|
||||||
title: Text(
|
title: Text(
|
||||||
category.name!,
|
category.name!,
|
||||||
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
@ -18,6 +17,7 @@ import 'package:spotube/pages/lyrics/synced_lyrics.dart';
|
|||||||
import 'package:spotube/provider/authentication_provider.dart';
|
import 'package:spotube/provider/authentication_provider.dart';
|
||||||
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
|
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
|
||||||
import 'package:spotube/utils/platform.dart';
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
class MiniLyricsPage extends HookConsumerWidget {
|
class MiniLyricsPage extends HookConsumerWidget {
|
||||||
final Size prevSize;
|
final Size prevSize;
|
||||||
@ -36,9 +36,11 @@ class MiniLyricsPage extends HookConsumerWidget {
|
|||||||
final showLyrics = useState(true);
|
final showLyrics = useState(true);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
if (kIsDesktop) {
|
||||||
wasMaximized.value = await DesktopTools.window.isMaximized();
|
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||||
});
|
wasMaximized.value = await windowManager.isMaximized();
|
||||||
|
});
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -112,11 +114,13 @@ class MiniLyricsPage extends HookConsumerWidget {
|
|||||||
areaActive.value = true;
|
areaActive.value = true;
|
||||||
hoverMode.value = false;
|
hoverMode.value = false;
|
||||||
|
|
||||||
await DesktopTools.window.setSize(
|
if (kIsDesktop) {
|
||||||
showLyrics.value
|
await windowManager.setSize(
|
||||||
? const Size(400, 500)
|
showLyrics.value
|
||||||
: const Size(400, 150),
|
? const Size(400, 500)
|
||||||
);
|
: const Size(400, 150),
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
@ -135,33 +139,34 @@ class MiniLyricsPage extends HookConsumerWidget {
|
|||||||
hoverMode.value = !hoverMode.value;
|
hoverMode.value = !hoverMode.value;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
FutureBuilder(
|
if (kIsDesktop)
|
||||||
future: DesktopTools.window.isAlwaysOnTop(),
|
FutureBuilder(
|
||||||
builder: (context, snapshot) {
|
future: windowManager.isAlwaysOnTop(),
|
||||||
return IconButton(
|
builder: (context, snapshot) {
|
||||||
tooltip: context.l10n.always_on_top,
|
return IconButton(
|
||||||
icon: Icon(
|
tooltip: context.l10n.always_on_top,
|
||||||
snapshot.data == true
|
icon: Icon(
|
||||||
? SpotubeIcons.pinOn
|
snapshot.data == true
|
||||||
: SpotubeIcons.pinOff,
|
? SpotubeIcons.pinOn
|
||||||
),
|
: SpotubeIcons.pinOff,
|
||||||
style: ButtonStyle(
|
),
|
||||||
foregroundColor: snapshot.data == true
|
style: ButtonStyle(
|
||||||
? MaterialStateProperty.all(
|
foregroundColor: snapshot.data == true
|
||||||
theme.colorScheme.primary)
|
? MaterialStateProperty.all(
|
||||||
: null,
|
theme.colorScheme.primary)
|
||||||
),
|
: null,
|
||||||
onPressed: snapshot.data == null
|
),
|
||||||
? null
|
onPressed: snapshot.data == null
|
||||||
: () async {
|
? null
|
||||||
await DesktopTools.window.setAlwaysOnTop(
|
: () async {
|
||||||
snapshot.data == true ? false : true,
|
await windowManager.setAlwaysOnTop(
|
||||||
);
|
snapshot.data == true ? false : true,
|
||||||
update();
|
);
|
||||||
},
|
update();
|
||||||
);
|
},
|
||||||
},
|
);
|
||||||
),
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -243,19 +248,20 @@ class MiniLyricsPage extends HookConsumerWidget {
|
|||||||
tooltip: context.l10n.exit_mini_player,
|
tooltip: context.l10n.exit_mini_player,
|
||||||
icon: const Icon(SpotubeIcons.maximize),
|
icon: const Icon(SpotubeIcons.maximize),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
|
if (!kIsDesktop) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await DesktopTools.window
|
await windowManager
|
||||||
.setMinimumSize(const Size(300, 700));
|
.setMinimumSize(const Size(300, 700));
|
||||||
await DesktopTools.window.setAlwaysOnTop(false);
|
await windowManager.setAlwaysOnTop(false);
|
||||||
if (wasMaximized.value) {
|
if (wasMaximized.value) {
|
||||||
await DesktopTools.window.maximize();
|
await windowManager.maximize();
|
||||||
} else {
|
} else {
|
||||||
await DesktopTools.window.setSize(prevSize);
|
await windowManager.setSize(prevSize);
|
||||||
}
|
}
|
||||||
await DesktopTools.window
|
await windowManager.setAlignment(Alignment.center);
|
||||||
.setAlignment(Alignment.center);
|
|
||||||
if (!kIsLinux) {
|
if (!kIsLinux) {
|
||||||
await DesktopTools.window.setHasShadow(true);
|
await windowManager.setHasShadow(true);
|
||||||
}
|
}
|
||||||
await Future.delayed(
|
await Future.delayed(
|
||||||
const Duration(milliseconds: 200));
|
const Duration(milliseconds: 200));
|
||||||
|
@ -2,7 +2,6 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@ -21,6 +20,7 @@ import 'package:spotube/provider/download_manager_provider.dart';
|
|||||||
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
|
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
|
||||||
import 'package:spotube/services/connectivity_adapter.dart';
|
import 'package:spotube/services/connectivity_adapter.dart';
|
||||||
import 'package:spotube/utils/persisted_state_notifier.dart';
|
import 'package:spotube/utils/persisted_state_notifier.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
const rootPaths = {
|
const rootPaths = {
|
||||||
"/": 0,
|
"/": 0,
|
||||||
@ -206,7 +206,7 @@ class RootApp extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
extendBody: true,
|
extendBody: true,
|
||||||
drawerScrimColor: Colors.transparent,
|
drawerScrimColor: Colors.transparent,
|
||||||
endDrawer: DesktopTools.platform.isDesktop
|
endDrawer: kIsDesktop
|
||||||
? Container(
|
? Container(
|
||||||
constraints: const BoxConstraints(maxWidth: 800),
|
constraints: const BoxConstraints(maxWidth: 800),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:spotube/collections/spotube_icons.dart';
|
import 'package:spotube/collections/spotube_icons.dart';
|
||||||
@ -8,6 +7,7 @@ import 'package:spotube/components/shared/adaptive/adaptive_select_tile.dart';
|
|||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
||||||
import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
|
import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
class SettingsDesktopSection extends HookConsumerWidget {
|
class SettingsDesktopSection extends HookConsumerWidget {
|
||||||
const SettingsDesktopSection({super.key});
|
const SettingsDesktopSection({super.key});
|
||||||
@ -53,7 +53,7 @@ class SettingsDesktopSection extends HookConsumerWidget {
|
|||||||
value: preferences.systemTitleBar,
|
value: preferences.systemTitleBar,
|
||||||
onChanged: preferencesNotifier.setSystemTitleBar,
|
onChanged: preferencesNotifier.setSystemTitleBar,
|
||||||
),
|
),
|
||||||
if (!DesktopTools.platform.isMacOS)
|
if (!kIsMacOS)
|
||||||
SwitchListTile(
|
SwitchListTile(
|
||||||
secondary: const Icon(SpotubeIcons.discord),
|
secondary: const Icon(SpotubeIcons.discord),
|
||||||
title: Text(context.l10n.discord_rich_presence),
|
title: Text(context.l10n.discord_rich_presence),
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:file_selector/file_selector.dart';
|
import 'package:file_selector/file_selector.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.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:spotube/collections/spotube_icons.dart';
|
import 'package:spotube/collections/spotube_icons.dart';
|
||||||
import 'package:spotube/components/settings/section_card_with_heading.dart';
|
import 'package:spotube/components/settings/section_card_with_heading.dart';
|
||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
class SettingsDownloadsSection extends HookConsumerWidget {
|
class SettingsDownloadsSection extends HookConsumerWidget {
|
||||||
const SettingsDownloadsSection({super.key});
|
const SettingsDownloadsSection({super.key});
|
||||||
@ -18,7 +18,7 @@ class SettingsDownloadsSection extends HookConsumerWidget {
|
|||||||
final preferences = ref.watch(userPreferencesProvider);
|
final preferences = ref.watch(userPreferencesProvider);
|
||||||
|
|
||||||
final pickDownloadLocation = useCallback(() async {
|
final pickDownloadLocation = useCallback(() async {
|
||||||
if (DesktopTools.platform.isMobile || DesktopTools.platform.isMacOS) {
|
if (kIsMobile || kIsMacOS) {
|
||||||
final dirStr = await FilePicker.platform.getDirectoryPath(
|
final dirStr = await FilePicker.platform.getDirectoryPath(
|
||||||
initialDirectory: preferences.downloadLocation,
|
initialDirectory: preferences.downloadLocation,
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.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:spotube/components/shared/page_window_title_bar.dart';
|
import 'package:spotube/components/shared/page_window_title_bar.dart';
|
||||||
@ -14,6 +13,7 @@ import 'package:spotube/pages/settings/sections/downloads.dart';
|
|||||||
import 'package:spotube/pages/settings/sections/language_region.dart';
|
import 'package:spotube/pages/settings/sections/language_region.dart';
|
||||||
import 'package:spotube/pages/settings/sections/playback.dart';
|
import 'package:spotube/pages/settings/sections/playback.dart';
|
||||||
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
class SettingsPage extends HookConsumerWidget {
|
class SettingsPage extends HookConsumerWidget {
|
||||||
const SettingsPage({super.key});
|
const SettingsPage({super.key});
|
||||||
@ -45,8 +45,7 @@ class SettingsPage extends HookConsumerWidget {
|
|||||||
const SettingsAppearanceSection(),
|
const SettingsAppearanceSection(),
|
||||||
const SettingsPlaybackSection(),
|
const SettingsPlaybackSection(),
|
||||||
const SettingsDownloadsSection(),
|
const SettingsDownloadsSection(),
|
||||||
if (DesktopTools.platform.isDesktop)
|
if (kIsDesktop) const SettingsDesktopSection(),
|
||||||
const SettingsDesktopSection(),
|
|
||||||
if (!kIsWeb) const SettingsDevelopersSection(),
|
if (!kIsWeb) const SettingsDevelopersSection(),
|
||||||
const SettingsAboutSection(),
|
const SettingsAboutSection(),
|
||||||
Center(
|
Center(
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
import 'package:dart_discord_rpc/dart_discord_rpc.dart';
|
import 'package:dart_discord_rpc/dart_discord_rpc.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:spotify/spotify.dart';
|
import 'package:spotify/spotify.dart';
|
||||||
import 'package:spotube/collections/env.dart';
|
import 'package:spotube/collections/env.dart';
|
||||||
import 'package:spotube/extensions/artist_simple.dart';
|
import 'package:spotube/extensions/artist_simple.dart';
|
||||||
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
|
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
|
||||||
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
class Discord extends ChangeNotifier {
|
class Discord extends ChangeNotifier {
|
||||||
final DiscordRPC? discordRPC;
|
final DiscordRPC? discordRPC;
|
||||||
final bool isEnabled;
|
final bool isEnabled;
|
||||||
|
|
||||||
Discord(this.isEnabled)
|
Discord(this.isEnabled)
|
||||||
: discordRPC = (DesktopTools.platform.isWindows ||
|
: discordRPC = (kIsWindows || kIsLinux) && isEnabled
|
||||||
DesktopTools.platform.isLinux) &&
|
|
||||||
isEnabled
|
|
||||||
? DiscordRPC(applicationId: Env.discordAppId)
|
? DiscordRPC(applicationId: Env.discordAppId)
|
||||||
: null {
|
: null {
|
||||||
discordRPC?.start(autoRegister: true);
|
discordRPC?.start(autoRegister: true);
|
||||||
|
79
lib/provider/tray_manager/tray_manager.dart
Normal file
79
lib/provider/tray_manager/tray_manager.dart
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:spotube/provider/tray_manager/tray_menu.dart';
|
||||||
|
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
import 'package:tray_manager/tray_manager.dart';
|
||||||
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
|
class SystemTrayManager with TrayListener {
|
||||||
|
final Ref ref;
|
||||||
|
final bool enabled;
|
||||||
|
|
||||||
|
SystemTrayManager(
|
||||||
|
this.ref, {
|
||||||
|
required this.enabled,
|
||||||
|
}) {
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> initialize() async {
|
||||||
|
if (!kIsDesktop) return;
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
await trayManager.setIcon(
|
||||||
|
kIsWindows
|
||||||
|
? 'assets/spotube-logo.ico'
|
||||||
|
: kIsFlatpak
|
||||||
|
? 'com.github.KRTirtho.Spotube.png'
|
||||||
|
: 'assets/spotube-logo.png',
|
||||||
|
);
|
||||||
|
trayManager.addListener(this);
|
||||||
|
} else {
|
||||||
|
await trayManager.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
trayManager.removeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
onTrayIconMouseDown() {
|
||||||
|
if (kIsWindows) {
|
||||||
|
windowManager.show();
|
||||||
|
} else {
|
||||||
|
trayManager.popUpContextMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
onTrayIconRightMouseDown() {
|
||||||
|
if (!kIsWindows) {
|
||||||
|
windowManager.show();
|
||||||
|
} else {
|
||||||
|
trayManager.popUpContextMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final trayManagerProvider = Provider(
|
||||||
|
(ref) {
|
||||||
|
final enabled = ref.watch(
|
||||||
|
userPreferencesProvider.select((s) => s.showSystemTrayIcon),
|
||||||
|
);
|
||||||
|
|
||||||
|
ref.listen(trayMenuProvider, (_, menu) {
|
||||||
|
if (!enabled || !kIsDesktop) return;
|
||||||
|
trayManager.setContextMenu(menu);
|
||||||
|
});
|
||||||
|
|
||||||
|
final manager = SystemTrayManager(
|
||||||
|
ref,
|
||||||
|
enabled: enabled,
|
||||||
|
);
|
||||||
|
|
||||||
|
ref.onDispose(manager.dispose);
|
||||||
|
|
||||||
|
return manager;
|
||||||
|
},
|
||||||
|
);
|
108
lib/provider/tray_manager/tray_menu.dart
Normal file
108
lib/provider/tray_manager/tray_menu.dart
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
|
||||||
|
import 'package:spotube/services/audio_player/audio_player.dart';
|
||||||
|
import 'package:spotube/services/audio_player/loop_mode.dart';
|
||||||
|
import 'package:tray_manager/tray_manager.dart';
|
||||||
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
|
final audioPlayerLoopMode = StreamProvider<PlaybackLoopMode>((ref) {
|
||||||
|
return audioPlayer.loopModeStream;
|
||||||
|
});
|
||||||
|
|
||||||
|
final audioPlayerShuffleMode = StreamProvider<bool>((ref) {
|
||||||
|
return audioPlayer.shuffledStream;
|
||||||
|
});
|
||||||
|
final audioPlayerPlaying = StreamProvider<bool>((ref) {
|
||||||
|
return audioPlayer.playingStream;
|
||||||
|
});
|
||||||
|
|
||||||
|
final trayMenuProvider = Provider((ref) {
|
||||||
|
final playlistNotifier = ref.watch(proxyPlaylistProvider.notifier);
|
||||||
|
final isPlaybackPlaying =
|
||||||
|
ref.watch(proxyPlaylistProvider.select((s) => s.activeTrack != null));
|
||||||
|
final isLoopOne =
|
||||||
|
ref.watch(audioPlayerLoopMode).asData?.value == PlaybackLoopMode.one;
|
||||||
|
final isShuffled = ref.watch(audioPlayerShuffleMode).asData?.value ?? false;
|
||||||
|
final isPlaying = ref.watch(audioPlayerPlaying).asData?.value ?? false;
|
||||||
|
|
||||||
|
return Menu(
|
||||||
|
items: [
|
||||||
|
MenuItem(
|
||||||
|
label: "Show/Hide Window",
|
||||||
|
onClick: (menuItem) async {
|
||||||
|
if (await windowManager.isVisible()) {
|
||||||
|
await windowManager.hide();
|
||||||
|
} else {
|
||||||
|
await windowManager.focus();
|
||||||
|
await windowManager.show();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MenuItem.separator(),
|
||||||
|
MenuItem(
|
||||||
|
label: isPlaying ? "Pause" : "Play",
|
||||||
|
disabled: !isPlaybackPlaying,
|
||||||
|
onClick: (menuItem) async {
|
||||||
|
if (audioPlayer.isPlaying) {
|
||||||
|
await audioPlayer.pause();
|
||||||
|
} else {
|
||||||
|
await audioPlayer.resume();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MenuItem(
|
||||||
|
label: "Next",
|
||||||
|
disabled: !isPlaybackPlaying,
|
||||||
|
onClick: (menuItem) {
|
||||||
|
playlistNotifier.next();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MenuItem(
|
||||||
|
label: "Previous",
|
||||||
|
disabled: !isPlaybackPlaying,
|
||||||
|
onClick: (menuItem) {
|
||||||
|
playlistNotifier.previous();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MenuItem.submenu(
|
||||||
|
label: "Playback",
|
||||||
|
submenu: Menu(
|
||||||
|
items: [
|
||||||
|
MenuItem(
|
||||||
|
label: "Repeat",
|
||||||
|
checked: isLoopOne,
|
||||||
|
onClick: (menuItem) {
|
||||||
|
audioPlayer.setLoopMode(
|
||||||
|
isLoopOne ? PlaybackLoopMode.none : PlaybackLoopMode.one,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MenuItem(
|
||||||
|
label: "Shuffle",
|
||||||
|
checked: isShuffled,
|
||||||
|
onClick: (menuItem) {
|
||||||
|
audioPlayer.setShuffle(!isShuffled);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MenuItem.separator(),
|
||||||
|
MenuItem(
|
||||||
|
label: "Stop",
|
||||||
|
onClick: (menuItem) {
|
||||||
|
playlistNotifier.stop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
MenuItem.separator(),
|
||||||
|
MenuItem(
|
||||||
|
label: "Quit",
|
||||||
|
onClick: (menuItem) {
|
||||||
|
exit(0);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
@ -1,7 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:spotify/spotify.dart';
|
import 'package:spotify/spotify.dart';
|
||||||
@ -15,6 +14,7 @@ import 'package:spotube/services/sourced_track/enums.dart';
|
|||||||
import 'package:spotube/utils/persisted_state_notifier.dart';
|
import 'package:spotube/utils/persisted_state_notifier.dart';
|
||||||
import 'package:spotube/utils/platform.dart';
|
import 'package:spotube/utils/platform.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
class UserPreferencesNotifier extends PersistedStateNotifier<UserPreferences> {
|
class UserPreferencesNotifier extends PersistedStateNotifier<UserPreferences> {
|
||||||
final Ref ref;
|
final Ref ref;
|
||||||
@ -103,8 +103,8 @@ class UserPreferencesNotifier extends PersistedStateNotifier<UserPreferences> {
|
|||||||
|
|
||||||
void setSystemTitleBar(bool isSystemTitleBar) {
|
void setSystemTitleBar(bool isSystemTitleBar) {
|
||||||
state = state.copyWith(systemTitleBar: isSystemTitleBar);
|
state = state.copyWith(systemTitleBar: isSystemTitleBar);
|
||||||
if (DesktopTools.platform.isDesktop) {
|
if (kIsDesktop) {
|
||||||
DesktopTools.window.setTitleBarStyle(
|
windowManager.setTitleBarStyle(
|
||||||
isSystemTitleBar ? TitleBarStyle.normal : TitleBarStyle.hidden,
|
isSystemTitleBar ? TitleBarStyle.normal : TitleBarStyle.hidden,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -151,8 +151,8 @@ class UserPreferencesNotifier extends PersistedStateNotifier<UserPreferences> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DesktopTools.platform.isDesktop) {
|
if (kIsDesktop) {
|
||||||
await DesktopTools.window.setTitleBarStyle(
|
await windowManager.setTitleBarStyle(
|
||||||
state.systemTitleBar ? TitleBarStyle.normal : TitleBarStyle.hidden,
|
state.systemTitleBar ? TitleBarStyle.normal : TitleBarStyle.hidden,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -62,10 +62,10 @@ class UserPreferences with _$UserPreferences {
|
|||||||
@Default(false) bool amoledDarkTheme,
|
@Default(false) bool amoledDarkTheme,
|
||||||
@Default(true) bool checkUpdate,
|
@Default(true) bool checkUpdate,
|
||||||
@Default(false) bool normalizeAudio,
|
@Default(false) bool normalizeAudio,
|
||||||
@Default(true) bool showSystemTrayIcon,
|
@Default(false) bool showSystemTrayIcon,
|
||||||
@Default(false) bool skipNonMusic,
|
@Default(false) bool skipNonMusic,
|
||||||
@Default(false) bool systemTitleBar,
|
@Default(false) bool systemTitleBar,
|
||||||
@Default(CloseBehavior.minimizeToTray) CloseBehavior closeBehavior,
|
@Default(CloseBehavior.close) CloseBehavior closeBehavior,
|
||||||
@Default(SpotubeColor(0xFF2196F3, name: "Blue"))
|
@Default(SpotubeColor(0xFF2196F3, name: "Blue"))
|
||||||
@JsonKey(
|
@JsonKey(
|
||||||
fromJson: UserPreferences._accentColorSchemeFromJson,
|
fromJson: UserPreferences._accentColorSchemeFromJson,
|
||||||
|
@ -12,7 +12,7 @@ part of 'user_preferences_state.dart';
|
|||||||
T _$identity<T>(T value) => value;
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
final _privateConstructorUsedError = UnsupportedError(
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||||
|
|
||||||
UserPreferences _$UserPreferencesFromJson(Map<String, dynamic> json) {
|
UserPreferences _$UserPreferencesFromJson(Map<String, dynamic> json) {
|
||||||
return _UserPreferences.fromJson(json);
|
return _UserPreferences.fromJson(json);
|
||||||
@ -415,10 +415,10 @@ class _$UserPreferencesImpl implements _UserPreferences {
|
|||||||
this.amoledDarkTheme = false,
|
this.amoledDarkTheme = false,
|
||||||
this.checkUpdate = true,
|
this.checkUpdate = true,
|
||||||
this.normalizeAudio = false,
|
this.normalizeAudio = false,
|
||||||
this.showSystemTrayIcon = true,
|
this.showSystemTrayIcon = false,
|
||||||
this.skipNonMusic = false,
|
this.skipNonMusic = false,
|
||||||
this.systemTitleBar = false,
|
this.systemTitleBar = false,
|
||||||
this.closeBehavior = CloseBehavior.minimizeToTray,
|
this.closeBehavior = CloseBehavior.close,
|
||||||
@JsonKey(
|
@JsonKey(
|
||||||
fromJson: UserPreferences._accentColorSchemeFromJson,
|
fromJson: UserPreferences._accentColorSchemeFromJson,
|
||||||
toJson: UserPreferences._accentColorSchemeToJson,
|
toJson: UserPreferences._accentColorSchemeToJson,
|
||||||
|
@ -16,12 +16,12 @@ _$UserPreferencesImpl _$$UserPreferencesImplFromJson(
|
|||||||
amoledDarkTheme: json['amoledDarkTheme'] as bool? ?? false,
|
amoledDarkTheme: json['amoledDarkTheme'] as bool? ?? false,
|
||||||
checkUpdate: json['checkUpdate'] as bool? ?? true,
|
checkUpdate: json['checkUpdate'] as bool? ?? true,
|
||||||
normalizeAudio: json['normalizeAudio'] as bool? ?? false,
|
normalizeAudio: json['normalizeAudio'] as bool? ?? false,
|
||||||
showSystemTrayIcon: json['showSystemTrayIcon'] as bool? ?? true,
|
showSystemTrayIcon: json['showSystemTrayIcon'] as bool? ?? false,
|
||||||
skipNonMusic: json['skipNonMusic'] as bool? ?? false,
|
skipNonMusic: json['skipNonMusic'] as bool? ?? false,
|
||||||
systemTitleBar: json['systemTitleBar'] as bool? ?? false,
|
systemTitleBar: json['systemTitleBar'] as bool? ?? false,
|
||||||
closeBehavior:
|
closeBehavior:
|
||||||
$enumDecodeNullable(_$CloseBehaviorEnumMap, json['closeBehavior']) ??
|
$enumDecodeNullable(_$CloseBehaviorEnumMap, json['closeBehavior']) ??
|
||||||
CloseBehavior.minimizeToTray,
|
CloseBehavior.close,
|
||||||
accentColorScheme: UserPreferences._accentColorSchemeReadValue(
|
accentColorScheme: UserPreferences._accentColorSchemeReadValue(
|
||||||
json, 'accentColorScheme') ==
|
json, 'accentColorScheme') ==
|
||||||
null
|
null
|
||||||
|
@ -101,7 +101,7 @@ abstract class AudioPlayerInterface {
|
|||||||
return _mkPlayer.state.completed;
|
return _mkPlayer.state.completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> get isShuffled async {
|
bool get isShuffled {
|
||||||
return _mkPlayer.shuffled;
|
return _mkPlayer.shuffled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:catcher_2/catcher_2.dart';
|
import 'package:catcher_2/catcher_2.dart';
|
||||||
import 'package:media_kit/media_kit.dart';
|
import 'package:media_kit/media_kit.dart';
|
||||||
import 'package:flutter_broadcasts/flutter_broadcasts.dart';
|
import 'package:flutter_broadcasts/flutter_broadcasts.dart';
|
||||||
@ -7,6 +6,7 @@ import 'package:package_info_plus/package_info_plus.dart';
|
|||||||
import 'package:audio_session/audio_session.dart';
|
import 'package:audio_session/audio_session.dart';
|
||||||
// ignore: implementation_imports
|
// ignore: implementation_imports
|
||||||
import 'package:spotube/services/audio_player/playback_state.dart';
|
import 'package:spotube/services/audio_player/playback_state.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
/// MediaKit [Player] by default doesn't have a state stream.
|
/// MediaKit [Player] by default doesn't have a state stream.
|
||||||
/// This class adds a state stream to the [Player] class.
|
/// This class adds a state stream to the [Player] class.
|
||||||
@ -54,7 +54,7 @@ class CustomPlayer extends Player {
|
|||||||
PackageInfo.fromPlatform().then((packageInfo) {
|
PackageInfo.fromPlatform().then((packageInfo) {
|
||||||
_packageName = packageInfo.packageName;
|
_packageName = packageInfo.packageName;
|
||||||
});
|
});
|
||||||
if (DesktopTools.platform.isAndroid) {
|
if (kIsAndroid) {
|
||||||
_androidAudioManager = AndroidAudioManager();
|
_androidAudioManager = AndroidAudioManager();
|
||||||
AudioSession.instance.then((s) async {
|
AudioSession.instance.then((s) async {
|
||||||
_androidAudioSessionId =
|
_androidAudioSessionId =
|
||||||
@ -71,7 +71,7 @@ class CustomPlayer extends Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> notifyAudioSessionUpdate(bool active) async {
|
Future<void> notifyAudioSessionUpdate(bool active) async {
|
||||||
if (DesktopTools.platform.isAndroid) {
|
if (kIsAndroid) {
|
||||||
sendBroadcast(
|
sendBroadcast(
|
||||||
BroadcastMessage(
|
BroadcastMessage(
|
||||||
name: active
|
name: active
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:audio_service/audio_service.dart';
|
import 'package:audio_service/audio_service.dart';
|
||||||
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:spotify/spotify.dart';
|
import 'package:spotify/spotify.dart';
|
||||||
import 'package:spotube/extensions/artist_simple.dart';
|
import 'package:spotube/extensions/artist_simple.dart';
|
||||||
@ -8,6 +7,7 @@ import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
|
|||||||
import 'package:spotube/services/audio_services/mobile_audio_service.dart';
|
import 'package:spotube/services/audio_services/mobile_audio_service.dart';
|
||||||
import 'package:spotube/services/audio_services/windows_audio_service.dart';
|
import 'package:spotube/services/audio_services/windows_audio_service.dart';
|
||||||
import 'package:spotube/services/sourced_track/sourced_track.dart';
|
import 'package:spotube/services/sourced_track/sourced_track.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
class AudioServices {
|
class AudioServices {
|
||||||
final MobileAudioService? mobile;
|
final MobileAudioService? mobile;
|
||||||
@ -19,9 +19,7 @@ class AudioServices {
|
|||||||
Ref ref,
|
Ref ref,
|
||||||
ProxyPlaylistNotifier playback,
|
ProxyPlaylistNotifier playback,
|
||||||
) async {
|
) async {
|
||||||
final mobile = DesktopTools.platform.isMobile ||
|
final mobile = kIsMobile || kIsMacOS || kIsLinux
|
||||||
DesktopTools.platform.isMacOS ||
|
|
||||||
DesktopTools.platform.isLinux
|
|
||||||
? await AudioService.init(
|
? await AudioService.init(
|
||||||
builder: () => MobileAudioService(playback),
|
builder: () => MobileAudioService(playback),
|
||||||
config: const AudioServiceConfig(
|
config: const AudioServiceConfig(
|
||||||
@ -31,9 +29,7 @@ class AudioServices {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
final smtc = DesktopTools.platform.isWindows
|
final smtc = kIsWindows ? WindowsAudioService(ref, playback) : null;
|
||||||
? WindowsAudioService(ref, playback)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return AudioServices(
|
return AudioServices(
|
||||||
mobile,
|
mobile,
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:spotube/services/wm_tools/wm_tools.dart';
|
||||||
|
|
||||||
abstract class KVStoreService {
|
abstract class KVStoreService {
|
||||||
static SharedPreferences? _sharedPreferences;
|
static SharedPreferences? _sharedPreferences;
|
||||||
@ -23,4 +26,21 @@ abstract class KVStoreService {
|
|||||||
|
|
||||||
static Future<void> setRecentSearches(List<String> value) async =>
|
static Future<void> setRecentSearches(List<String> value) async =>
|
||||||
await sharedPreferences.setStringList('recentSearches', value);
|
await sharedPreferences.setStringList('recentSearches', value);
|
||||||
|
|
||||||
|
static WindowSize? get windowSize {
|
||||||
|
final raw = sharedPreferences.getString('windowSize');
|
||||||
|
|
||||||
|
if (raw == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return WindowSize.fromJson(jsonDecode(raw));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> setWindowSize(WindowSize value) async =>
|
||||||
|
await sharedPreferences.setString(
|
||||||
|
'windowSize',
|
||||||
|
jsonEncode(
|
||||||
|
value.toJson(),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ part of 'song_link.dart';
|
|||||||
T _$identity<T>(T value) => value;
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
final _privateConstructorUsedError = UnsupportedError(
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||||
|
|
||||||
SongLink _$SongLinkFromJson(Map<String, dynamic> json) {
|
SongLink _$SongLinkFromJson(Map<String, dynamic> json) {
|
||||||
return _SongLink.fromJson(json);
|
return _SongLink.fromJson(json);
|
||||||
|
@ -163,7 +163,7 @@ class PipedSourcedTrack extends SourcedTrack {
|
|||||||
final PipedSearchResult(items: searchResults) = await pipedClient.search(
|
final PipedSearchResult(items: searchResults) = await pipedClient.search(
|
||||||
query,
|
query,
|
||||||
preference.searchMode == SearchMode.youtube
|
preference.searchMode == SearchMode.youtube
|
||||||
? PipedFilter.videos
|
? PipedFilter.video
|
||||||
: PipedFilter.musicSongs,
|
: PipedFilter.musicSongs,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
88
lib/services/wm_tools/wm_tools.dart
Normal file
88
lib/services/wm_tools/wm_tools.dart
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:spotube/services/kv_store/kv_store.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
|
class WindowSize {
|
||||||
|
final double height;
|
||||||
|
final double width;
|
||||||
|
final bool maximized;
|
||||||
|
|
||||||
|
WindowSize({
|
||||||
|
required this.height,
|
||||||
|
required this.width,
|
||||||
|
required this.maximized,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory WindowSize.fromJson(Map<String, dynamic> json) => WindowSize(
|
||||||
|
height: json["height"],
|
||||||
|
width: json["width"],
|
||||||
|
maximized: json["maximized"],
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
"height": height,
|
||||||
|
"width": width,
|
||||||
|
"maximized": maximized,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class WindowManagerTools with WidgetsBindingObserver {
|
||||||
|
static WindowManagerTools? _instance;
|
||||||
|
static WindowManagerTools get instance => _instance!;
|
||||||
|
|
||||||
|
WindowManagerTools._();
|
||||||
|
|
||||||
|
static Future<void> initialize() async {
|
||||||
|
await windowManager.ensureInitialized();
|
||||||
|
_instance = WindowManagerTools._();
|
||||||
|
WidgetsBinding.instance.addObserver(instance);
|
||||||
|
|
||||||
|
await windowManager.waitUntilReadyToShow(
|
||||||
|
const WindowOptions(
|
||||||
|
title: "Spotube",
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
minimumSize: Size(300, 700),
|
||||||
|
titleBarStyle: TitleBarStyle.hidden,
|
||||||
|
),
|
||||||
|
() async {
|
||||||
|
final savedSize = KVStoreService.windowSize;
|
||||||
|
await windowManager.setResizable(true);
|
||||||
|
if (savedSize?.maximized == true &&
|
||||||
|
!(await windowManager.isMaximized())) {
|
||||||
|
await windowManager.maximize();
|
||||||
|
} else if (savedSize != null) {
|
||||||
|
await windowManager.setSize(Size(savedSize.width, savedSize.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
await windowManager.focus();
|
||||||
|
await windowManager.show();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Size? _prevSize;
|
||||||
|
|
||||||
|
@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 (windowSameDimension || _prevSize == null) {
|
||||||
|
_prevSize = size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final isMaximized = await windowManager.isMaximized();
|
||||||
|
await KVStoreService.setWindowSize(
|
||||||
|
WindowSize(
|
||||||
|
height: size.height,
|
||||||
|
width: size.width,
|
||||||
|
maximized: isMaximized,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
_prevSize = size;
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@
|
|||||||
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
||||||
#include <screen_retriever/screen_retriever_plugin.h>
|
#include <screen_retriever/screen_retriever_plugin.h>
|
||||||
#include <system_theme/system_theme_plugin.h>
|
#include <system_theme/system_theme_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 <url_launcher_linux/url_launcher_plugin.h>
|
||||||
#include <window_manager/window_manager_plugin.h>
|
#include <window_manager/window_manager_plugin.h>
|
||||||
#include <window_size/window_size_plugin.h>
|
#include <window_size/window_size_plugin.h>
|
||||||
@ -44,9 +44,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||||||
g_autoptr(FlPluginRegistrar) system_theme_registrar =
|
g_autoptr(FlPluginRegistrar) system_theme_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "SystemThemePlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "SystemThemePlugin");
|
||||||
system_theme_plugin_register_with_registrar(system_theme_registrar);
|
system_theme_plugin_register_with_registrar(system_theme_registrar);
|
||||||
g_autoptr(FlPluginRegistrar) system_tray_registrar =
|
g_autoptr(FlPluginRegistrar) tray_manager_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "SystemTrayPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "TrayManagerPlugin");
|
||||||
system_tray_plugin_register_with_registrar(system_tray_registrar);
|
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);
|
||||||
|
@ -11,7 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
media_kit_libs_linux
|
media_kit_libs_linux
|
||||||
screen_retriever
|
screen_retriever
|
||||||
system_theme
|
system_theme
|
||||||
system_tray
|
tray_manager
|
||||||
url_launcher_linux
|
url_launcher_linux
|
||||||
window_manager
|
window_manager
|
||||||
window_size
|
window_size
|
||||||
|
@ -21,7 +21,7 @@ import screen_retriever
|
|||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
import sqflite
|
import sqflite
|
||||||
import system_theme
|
import system_theme
|
||||||
import system_tray
|
import tray_manager
|
||||||
import url_launcher_macos
|
import url_launcher_macos
|
||||||
import window_manager
|
import window_manager
|
||||||
import window_size
|
import window_size
|
||||||
@ -37,13 +37,13 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
||||||
LocalNotifierPlugin.register(with: registry.registrar(forPlugin: "LocalNotifierPlugin"))
|
LocalNotifierPlugin.register(with: registry.registrar(forPlugin: "LocalNotifierPlugin"))
|
||||||
MediaKitLibsMacosAudioPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosAudioPlugin"))
|
MediaKitLibsMacosAudioPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosAudioPlugin"))
|
||||||
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
|
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
SystemThemePlugin.register(with: registry.registrar(forPlugin: "SystemThemePlugin"))
|
SystemThemePlugin.register(with: registry.registrar(forPlugin: "SystemThemePlugin"))
|
||||||
SystemTrayPlugin.register(with: registry.registrar(forPlugin: "SystemTrayPlugin"))
|
TrayManagerPlugin.register(with: registry.registrar(forPlugin: "TrayManagerPlugin"))
|
||||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||||
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
|
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
|
||||||
WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin"))
|
WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin"))
|
||||||
|
@ -44,7 +44,7 @@ PODS:
|
|||||||
- FMDB (>= 2.7.5)
|
- FMDB (>= 2.7.5)
|
||||||
- system_theme (0.0.1):
|
- system_theme (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- system_tray (0.0.1):
|
- tray_manager (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- url_launcher_macos (0.0.1):
|
- url_launcher_macos (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
@ -73,7 +73,7 @@ DEPENDENCIES:
|
|||||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
|
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
|
||||||
- system_theme (from `Flutter/ephemeral/.symlinks/plugins/system_theme/macos`)
|
- system_theme (from `Flutter/ephemeral/.symlinks/plugins/system_theme/macos`)
|
||||||
- system_tray (from `Flutter/ephemeral/.symlinks/plugins/system_tray/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`)
|
||||||
- window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`)
|
- window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`)
|
||||||
- window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`)
|
- window_size (from `Flutter/ephemeral/.symlinks/plugins/window_size/macos`)
|
||||||
@ -122,8 +122,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos
|
||||||
system_theme:
|
system_theme:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/system_theme/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/system_theme/macos
|
||||||
system_tray:
|
tray_manager:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/system_tray/macos
|
: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
|
||||||
window_manager:
|
window_manager:
|
||||||
@ -132,11 +132,11 @@ EXTERNAL SOURCES:
|
|||||||
:path: Flutter/ephemeral/.symlinks/plugins/window_size/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/window_size/macos
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
app_links: 4481ed4d71f384b0c3ae5016f4633aa73d32ff67
|
app_links: 10e0a0ab602ffaf34d142cd4862f29d34b303b2a
|
||||||
audio_service: b88ff778e0e3915efd4cd1a5ad6f0beef0c950a9
|
audio_service: b88ff778e0e3915efd4cd1a5ad6f0beef0c950a9
|
||||||
audio_session: dea1f41890dbf1718f04a56f1d6150fd50039b72
|
audio_session: dea1f41890dbf1718f04a56f1d6150fd50039b72
|
||||||
bonsoir_darwin: e3b8526c42ca46a885142df84229131dfabea842
|
bonsoir_darwin: e3b8526c42ca46a885142df84229131dfabea842
|
||||||
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
|
device_info_plus: ce1b7762849d3ec103d0e0517299f2db7ad60720
|
||||||
file_selector_macos: 468fb6b81fac7c0e88d71317f3eec34c3b008ff9
|
file_selector_macos: 468fb6b81fac7c0e88d71317f3eec34c3b008ff9
|
||||||
flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d
|
flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d
|
||||||
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
|
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
|
||||||
@ -147,13 +147,13 @@ SPEC CHECKSUMS:
|
|||||||
media_kit_native_event_loop: 7321675377cb9ae8596a29bddf3a3d2b5e8792c5
|
media_kit_native_event_loop: 7321675377cb9ae8596a29bddf3a3d2b5e8792c5
|
||||||
metadata_god: eceae399d0020475069a5cebc35943ce8562b5d7
|
metadata_god: eceae399d0020475069a5cebc35943ce8562b5d7
|
||||||
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
||||||
package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce
|
package_info_plus: fa739dd842b393193c5ca93c26798dff6e3d0e0c
|
||||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
|
||||||
screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38
|
screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38
|
||||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
|
||||||
sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea
|
sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea
|
||||||
system_theme: c7b9f6659a5caa26c9bc2284da096781e9a6fcbc
|
system_theme: c7b9f6659a5caa26c9bc2284da096781e9a6fcbc
|
||||||
system_tray: e53c972838c69589ff2e77d6d3abfd71332f9e5d
|
tray_manager: 9064e219c56d75c476e46b9a21182087930baf90
|
||||||
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
|
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
|
||||||
window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8
|
window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8
|
||||||
window_size: 339dafa0b27a95a62a843042038fa6c3c48de195
|
window_size: 339dafa0b27a95a62a843042038fa6c3c48de195
|
||||||
|
658
pubspec.lock
658
pubspec.lock
File diff suppressed because it is too large
Load Diff
96
pubspec.yaml
96
pubspec.yaml
@ -13,96 +13,89 @@ environment:
|
|||||||
flutter: ">=3.10.0"
|
flutter: ">=3.10.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
args: ^2.3.2
|
args: ^2.5.0
|
||||||
async: ^2.9.0
|
async: ^2.9.0
|
||||||
audio_service: ^0.18.9
|
audio_service: ^0.18.13
|
||||||
audio_session: ^0.1.18
|
audio_service_mpris: ^0.1.3
|
||||||
|
audio_session: ^0.1.19
|
||||||
auto_size_text: ^3.0.0
|
auto_size_text: ^3.0.0
|
||||||
buttons_tabbar: ^1.3.6
|
buttons_tabbar: ^1.3.8
|
||||||
cached_network_image: ^3.3.1
|
cached_network_image: ^3.3.1
|
||||||
catcher_2: 1.0.0
|
catcher_2: ^1.2.4
|
||||||
collection: ^1.15.0
|
collection: ^1.15.0
|
||||||
cupertino_icons: ^1.0.5
|
|
||||||
curved_navigation_bar: ^1.0.3
|
curved_navigation_bar: ^1.0.3
|
||||||
dbus: ^0.7.8
|
dbus: ^0.7.8
|
||||||
device_info_plus: ^9.1.2
|
device_info_plus: ^10.1.0
|
||||||
device_preview: ^1.1.0
|
device_preview: ^1.1.0
|
||||||
dio: ^5.4.1
|
dio: ^5.4.3+1
|
||||||
disable_battery_optimization: ^1.1.0+1
|
disable_battery_optimization: ^1.1.1
|
||||||
duration: ^3.0.12
|
duration: ^3.0.12
|
||||||
envied: ^0.3.0
|
envied: ^0.5.4+1
|
||||||
file_selector: ^1.0.1
|
file_picker: ^8.0.0+1
|
||||||
fluentui_system_icons: ^1.1.189
|
file_selector: ^1.0.3
|
||||||
|
fluentui_system_icons: ^1.1.234
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_cache_manager: ^3.3.0
|
flutter_cache_manager: ^3.3.0
|
||||||
flutter_desktop_tools:
|
|
||||||
git:
|
|
||||||
url: https://github.com/KRTirtho/flutter_desktop_tools.git
|
|
||||||
ref: 1f0bec3283626dcbd8ee2f54e238d096d8dea50e
|
|
||||||
flutter_displaymode: ^0.6.0
|
flutter_displaymode: ^0.6.0
|
||||||
flutter_feather_icons: ^2.0.0+1
|
flutter_feather_icons: ^2.0.0+1
|
||||||
flutter_hooks: ^0.20.5
|
flutter_hooks: ^0.20.5
|
||||||
flutter_inappwebview: ^6.0.0
|
flutter_inappwebview: ^6.0.0
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_native_splash: ^2.3.10
|
flutter_native_splash: ^2.4.0
|
||||||
flutter_riverpod: ^2.4.10
|
flutter_riverpod: ^2.5.1
|
||||||
flutter_secure_storage: ^9.0.0
|
flutter_secure_storage: ^9.0.0
|
||||||
flutter_svg: ^1.1.6
|
flutter_svg: ^1.1.6
|
||||||
form_validator: ^2.1.1
|
form_validator: ^2.1.1
|
||||||
fuzzywuzzy: ^1.1.6
|
fuzzywuzzy: ^1.1.6
|
||||||
go_router: 12.1.3 # Stuck on this https://github.com/flutter/flutter/issues/140869
|
go_router: 12.1.3 # Stuck on this https://github.com/flutter/flutter/issues/140869
|
||||||
google_fonts: ^6.1.0
|
google_fonts: ^6.2.1
|
||||||
hive: ^2.2.3
|
hive: ^2.2.3
|
||||||
hive_flutter: ^1.1.0
|
hive_flutter: ^1.1.0
|
||||||
hooks_riverpod: ^2.4.3
|
hooks_riverpod: ^2.5.1
|
||||||
html: ^0.15.1
|
html: ^0.15.1
|
||||||
http: ^1.2.0
|
http: ^1.2.0
|
||||||
image_picker: ^1.0.4
|
image_picker: ^1.1.0
|
||||||
intl: ^0.18.0
|
intl: ^0.18.0
|
||||||
introduction_screen: ^3.0.2
|
introduction_screen: ^3.1.14
|
||||||
json_annotation: ^4.8.1
|
json_annotation: ^4.8.1
|
||||||
logger: ^2.0.2
|
logger: ^2.0.2
|
||||||
media_kit: ^1.1.3
|
media_kit: ^1.1.10+1
|
||||||
media_kit_libs_audio: ^1.0.3
|
media_kit_libs_audio: ^1.0.4
|
||||||
metadata_god: ^0.5.2+1
|
metadata_god: ^0.5.2+1
|
||||||
mime: ^1.0.2
|
mime: ^1.0.2
|
||||||
package_info_plus: ^4.1.0
|
package_info_plus: ^6.0.0
|
||||||
palette_generator: ^0.3.3
|
palette_generator: ^0.3.3
|
||||||
path: ^1.8.0
|
path: ^1.8.0
|
||||||
path_provider: ^2.0.8
|
path_provider: ^2.1.3
|
||||||
permission_handler: ^11.0.1
|
permission_handler: ^11.3.1
|
||||||
piped_client:
|
piped_client: ^0.1.1
|
||||||
git:
|
|
||||||
url: https://github.com/KRTirtho/piped_client.git
|
|
||||||
popover: ^0.3.0
|
popover: ^0.3.0
|
||||||
scrobblenaut:
|
scrobblenaut:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/KRTirtho/scrobblenaut.git
|
url: https://github.com/KRTirtho/scrobblenaut.git
|
||||||
ref: dart-3-support
|
ref: dart-3-support
|
||||||
scroll_to_index: ^3.0.1
|
scroll_to_index: ^3.0.1
|
||||||
sidebarx: ^0.16.3
|
sidebarx: ^0.17.1
|
||||||
shared_preferences: ^2.2.2
|
shared_preferences: ^2.2.3
|
||||||
skeleton_text: ^3.0.1
|
skeleton_text: ^3.0.1
|
||||||
smtc_windows: ^0.1.1
|
smtc_windows: ^0.1.2
|
||||||
stroke_text: ^0.0.2
|
stroke_text: ^0.0.2
|
||||||
system_theme: ^2.1.0
|
system_theme: ^2.1.0
|
||||||
titlebar_buttons: ^1.0.0
|
titlebar_buttons: ^1.0.0
|
||||||
url_launcher: ^6.1.7
|
url_launcher: ^6.2.6
|
||||||
uuid: ^3.0.7
|
uuid: ^4.4.0
|
||||||
version: ^3.0.2
|
version: ^3.0.2
|
||||||
visibility_detector: ^0.4.0+2
|
visibility_detector: ^0.4.0+2
|
||||||
window_manager: ^0.3.1
|
window_manager: ^0.3.8
|
||||||
window_size:
|
window_size:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/google/flutter-desktop-embedding.git
|
url: https://github.com/google/flutter-desktop-embedding.git
|
||||||
ref: a738913c8ce2c9f47515382d40827e794a334274
|
ref: a738913c8ce2c9f47515382d40827e794a334274
|
||||||
path: plugins/window_size
|
path: plugins/window_size
|
||||||
youtube_explode_dart: ^2.0.1
|
youtube_explode_dart: ^2.2.0
|
||||||
simple_icons: ^7.10.0
|
simple_icons: ^10.1.3
|
||||||
audio_service_mpris: ^0.1.0
|
|
||||||
file_picker: ^6.0.0
|
|
||||||
jiosaavn: ^0.1.0
|
jiosaavn: ^0.1.0
|
||||||
draggable_scrollbar:
|
draggable_scrollbar:
|
||||||
git:
|
git:
|
||||||
@ -116,28 +109,29 @@ dependencies:
|
|||||||
url: https://github.com/Tommypop2/dart_discord_rpc.git
|
url: https://github.com/Tommypop2/dart_discord_rpc.git
|
||||||
html_unescape: ^2.0.0
|
html_unescape: ^2.0.0
|
||||||
wikipedia_api: ^0.1.0
|
wikipedia_api: ^0.1.0
|
||||||
skeletonizer: ^0.8.0
|
skeletonizer: ^1.1.1
|
||||||
app_links: ^3.5.0
|
app_links: ^4.0.1
|
||||||
win32_registry: ^1.1.2
|
win32_registry: ^1.1.3
|
||||||
flutter_sharing_intent: ^1.1.0
|
flutter_sharing_intent: ^1.1.0
|
||||||
flutter_broadcasts: ^0.4.0
|
flutter_broadcasts: ^0.4.0
|
||||||
freezed_annotation: ^2.4.1
|
freezed_annotation: ^2.4.1
|
||||||
spotify: ^0.13.3
|
spotify: ^0.13.5
|
||||||
bonsoir: ^5.1.9
|
bonsoir: ^5.1.9
|
||||||
shelf: ^1.4.1
|
shelf: ^1.4.1
|
||||||
shelf_router: ^1.1.4
|
shelf_router: ^1.1.4
|
||||||
shelf_web_socket: ^1.0.4
|
shelf_web_socket: ^1.0.4
|
||||||
web_socket_channel: ^2.4.4
|
web_socket_channel: ^2.4.5
|
||||||
lrc: ^1.0.2
|
lrc: ^1.0.2
|
||||||
pub_api_client: ^2.4.0
|
pub_api_client: ^2.4.0
|
||||||
pubspec_parse: ^1.2.2
|
pubspec_parse: ^1.2.2
|
||||||
timezone: ^0.9.2
|
timezone: ^0.9.2
|
||||||
crypto: ^3.0.3
|
crypto: ^3.0.3
|
||||||
|
local_notifier: ^0.1.6
|
||||||
|
tray_manager: ^0.2.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^2.4.9
|
build_runner: ^2.4.9
|
||||||
envied_generator: ^0.3.0+3
|
envied_generator: ^0.5.4+1
|
||||||
flutter_distributor: ^0.0.2
|
|
||||||
flutter_gen_runner: ^5.4.0
|
flutter_gen_runner: ^5.4.0
|
||||||
flutter_launcher_icons: ^0.13.1
|
flutter_launcher_icons: ^0.13.1
|
||||||
flutter_lints: ^3.0.1
|
flutter_lints: ^3.0.1
|
||||||
@ -147,12 +141,12 @@ dev_dependencies:
|
|||||||
sdk: flutter
|
sdk: flutter
|
||||||
hive_generator: ^2.0.0
|
hive_generator: ^2.0.0
|
||||||
json_serializable: ^6.6.2
|
json_serializable: ^6.6.2
|
||||||
freezed: ^2.4.6
|
freezed: ^2.5.2
|
||||||
custom_lint: ^0.5.11
|
custom_lint: ^0.6.4
|
||||||
riverpod_lint: ^2.1.1
|
riverpod_lint: ^2.3.10
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
system_tray: 2.0.2
|
uuid: ^4.4.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
generate: true
|
generate: true
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||||
#include <screen_retriever/screen_retriever_plugin.h>
|
#include <screen_retriever/screen_retriever_plugin.h>
|
||||||
#include <system_theme/system_theme_plugin.h>
|
#include <system_theme/system_theme_plugin.h>
|
||||||
#include <system_tray/system_tray_plugin.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 <window_manager/window_manager_plugin.h>
|
#include <window_manager/window_manager_plugin.h>
|
||||||
#include <window_size/window_size_plugin.h>
|
#include <window_size/window_size_plugin.h>
|
||||||
@ -42,8 +42,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||||||
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
|
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
|
||||||
SystemThemePluginRegisterWithRegistrar(
|
SystemThemePluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("SystemThemePlugin"));
|
registry->GetRegistrarForPlugin("SystemThemePlugin"));
|
||||||
SystemTrayPluginRegisterWithRegistrar(
|
TrayManagerPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("SystemTrayPlugin"));
|
registry->GetRegistrarForPlugin("TrayManagerPlugin"));
|
||||||
UrlLauncherWindowsRegisterWithRegistrar(
|
UrlLauncherWindowsRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||||
WindowManagerPluginRegisterWithRegistrar(
|
WindowManagerPluginRegisterWithRegistrar(
|
||||||
|
@ -13,7 +13,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
permission_handler_windows
|
permission_handler_windows
|
||||||
screen_retriever
|
screen_retriever
|
||||||
system_theme
|
system_theme
|
||||||
system_tray
|
tray_manager
|
||||||
url_launcher_windows
|
url_launcher_windows
|
||||||
window_manager
|
window_manager
|
||||||
window_size
|
window_size
|
||||||
|
Loading…
Reference in New Issue
Block a user