mirror of
https://github.com/Dr-Blank/Vaani.git
synced 2026-02-16 06:19:35 +00:00
1.增加托盘图标
2.关闭修改为最小化到托盘 3.优化播放页播放速率选项
This commit is contained in:
parent
779c132a11
commit
13767656b5
14 changed files with 354 additions and 15 deletions
|
|
@ -28,7 +28,9 @@ class SpeedSelector extends HookConsumerWidget {
|
|||
// hook the onSpeedSelected function to the state
|
||||
useEffect(
|
||||
() {
|
||||
onSpeedSelected(speedState.value);
|
||||
Future.microtask(() {
|
||||
onSpeedSelected(speedState.value);
|
||||
});
|
||||
return null;
|
||||
},
|
||||
[speedState.value],
|
||||
|
|
|
|||
|
|
@ -14,19 +14,34 @@ import 'package:vaani/features/player/providers/audiobook_player.dart'
|
|||
import 'package:vaani/features/shake_detection/providers/shake_detector.dart';
|
||||
import 'package:vaani/features/sleep_timer/providers/sleep_timer_provider.dart';
|
||||
import 'package:vaani/generated/l10n.dart';
|
||||
import 'package:vaani/models/tray.dart';
|
||||
import 'package:vaani/router/router.dart';
|
||||
import 'package:vaani/settings/api_settings_provider.dart';
|
||||
import 'package:vaani/settings/app_settings_provider.dart';
|
||||
import 'package:vaani/settings/settings.dart';
|
||||
import 'package:vaani/shared/utils/utils.dart';
|
||||
import 'package:vaani/theme/providers/system_theme_provider.dart';
|
||||
import 'package:vaani/theme/providers/theme_from_cover_provider.dart';
|
||||
import 'package:vaani/theme/theme.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
final appLogger = Logger(AppMetadata.appName);
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// 初始化窗口管理器
|
||||
if (Utils.isDesktop()) {
|
||||
await windowManager.ensureInitialized();
|
||||
final windowOptions = WindowOptions(
|
||||
minimumSize: Size(1050, 700),
|
||||
center: true,
|
||||
skipTaskbar: false,
|
||||
);
|
||||
await windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
await windowManager.setPreventClose(true);
|
||||
});
|
||||
}
|
||||
// Configure the root Logger
|
||||
await initLogging();
|
||||
|
||||
|
|
@ -39,7 +54,7 @@ void main() async {
|
|||
// run the app
|
||||
runApp(
|
||||
const ProviderScope(
|
||||
child: _EagerInitialization(child: MyApp()),
|
||||
child: _EagerInitialization(child: TrayFramework(MyApp())),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
130
lib/models/tray.dart
Normal file
130
lib/models/tray.dart
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:tray_manager/tray_manager.dart';
|
||||
import 'package:vaani/features/player/providers/audiobook_player.dart';
|
||||
import 'package:vaani/settings/constants.dart';
|
||||
import 'package:vaani/shared/utils/utils.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
class TrayFramework extends ConsumerStatefulWidget {
|
||||
final Widget child;
|
||||
const TrayFramework(this.child, {super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<TrayFramework> createState() => _TrayFrameworkState();
|
||||
}
|
||||
|
||||
class _TrayFrameworkState extends ConsumerState<TrayFramework>
|
||||
with TrayListener, WindowListener {
|
||||
@override
|
||||
void initState() {
|
||||
if (Utils.isDesktop()) {
|
||||
windowManager.addListener(this);
|
||||
_init();
|
||||
}
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
trayManager.removeListener(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _init() async {
|
||||
await trayManager.setIcon(
|
||||
Utils.isWindows() ? 'assets/icon/logo.ico' : 'assets/icon/logo.png',
|
||||
);
|
||||
await trayManager.setToolTip(AppMetadata.appName);
|
||||
Menu menu = Menu(
|
||||
items: [
|
||||
MenuItem(
|
||||
key: 'show_window',
|
||||
// label: 'Show Window',
|
||||
label: '显示主窗口',
|
||||
onClick: (menuItem) => windowManager.show(),
|
||||
),
|
||||
MenuItem.separator(),
|
||||
MenuItem(
|
||||
key: 'play_pause',
|
||||
label: '播放/暂停',
|
||||
onClick: (menuItem) =>
|
||||
ref.read(audiobookPlayerProvider).togglePlayPause(),
|
||||
),
|
||||
MenuItem(
|
||||
key: 'previous',
|
||||
label: '上一个',
|
||||
onClick: (menuItem) =>
|
||||
ref.read(audiobookPlayerProvider).seekToPrevious(),
|
||||
),
|
||||
MenuItem(
|
||||
key: 'next',
|
||||
label: '下一个',
|
||||
onClick: (menuItem) => ref.read(audiobookPlayerProvider).seekToNext(),
|
||||
),
|
||||
MenuItem.separator(),
|
||||
MenuItem(
|
||||
key: 'exit_app',
|
||||
// label: 'Exit App',
|
||||
label: '退出',
|
||||
onClick: (menuItem) => windowManager.destroy(),
|
||||
),
|
||||
],
|
||||
);
|
||||
await trayManager.setContextMenu(menu);
|
||||
trayManager.addListener(this);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return widget.child;
|
||||
}
|
||||
|
||||
@override
|
||||
void onTrayIconMouseDown() {
|
||||
// do something, for example pop up the menu
|
||||
// print('onTrayIconMouseDown');
|
||||
windowManager.show();
|
||||
}
|
||||
|
||||
@override
|
||||
void onTrayIconMouseUp() {
|
||||
// do something, for example pop up the menu
|
||||
// print('onTrayIconMouseUp');
|
||||
}
|
||||
|
||||
@override
|
||||
void onTrayIconRightMouseDown() {
|
||||
// do something
|
||||
// print('onTrayIconRightMouseDown');
|
||||
trayManager.popUpContextMenu(bringAppToFront: true);
|
||||
}
|
||||
|
||||
@override
|
||||
void onTrayIconRightMouseUp() {
|
||||
// do something
|
||||
// print('onTrayIconRightMouseUp');
|
||||
}
|
||||
|
||||
// @override
|
||||
// void onTrayMenuItemClick(MenuItem menuItem) {
|
||||
// print(menuItem.key);
|
||||
// if (menuItem.key == 'show_window') {
|
||||
// // do something
|
||||
// } else if (menuItem.key == 'exit_app') {
|
||||
// // do something
|
||||
|
||||
// } else if (menuItem.key == 'play_pause'){
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
@override
|
||||
void onWindowClose() async {
|
||||
final isPreventClose = await windowManager.isPreventClose();
|
||||
if (isPreventClose) {
|
||||
windowManager.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
lib/shared/utils/utils.dart
Normal file
40
lib/shared/utils/utils.dart
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class Utils {
|
||||
static isAndroid() {
|
||||
return !kIsWeb && Platform.isAndroid;
|
||||
}
|
||||
|
||||
static isIOS() {
|
||||
return !kIsWeb && Platform.isIOS;
|
||||
}
|
||||
|
||||
static isMobile() {
|
||||
return !kIsWeb && (Platform.isAndroid || Platform.isIOS);
|
||||
}
|
||||
|
||||
static isDesktop() {
|
||||
if (kIsWeb) {
|
||||
return false;
|
||||
}
|
||||
return Platform.isWindows || Platform.isLinux || Platform.isMacOS;
|
||||
}
|
||||
|
||||
static isWindows() {
|
||||
return !kIsWeb && Platform.isWindows;
|
||||
}
|
||||
|
||||
static isMacos() {
|
||||
return !kIsWeb && Platform.isMacOS;
|
||||
}
|
||||
|
||||
static isLinux() {
|
||||
return !kIsWeb && Platform.isLinux;
|
||||
}
|
||||
|
||||
static isWeb() {
|
||||
return kIsWeb;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
|
||||
class ExpandableDescription extends HookWidget {
|
||||
const ExpandableDescription({
|
||||
|
|
@ -78,18 +79,28 @@ class ExpandableDescription extends HookWidget {
|
|||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: AnimatedSwitcher(
|
||||
duration: duration * 3,
|
||||
child: isDescExpanded.value
|
||||
? Text(
|
||||
style: textTheme.bodyMedium,
|
||||
content,
|
||||
maxLines: null,
|
||||
)
|
||||
: Text(
|
||||
style: textTheme.bodyMedium,
|
||||
content,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
// child: isDescExpanded.value
|
||||
// ? Text(
|
||||
// style: textTheme.bodyMedium,
|
||||
// content,
|
||||
// maxLines: null,
|
||||
// )
|
||||
// : Text(
|
||||
// style: textTheme.bodyMedium,
|
||||
// content,
|
||||
// maxLines: 3,
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// ),
|
||||
child: Html(
|
||||
data: '<div class="vaani-ellipsis">$content</div>',
|
||||
style: {
|
||||
"div": Style(
|
||||
maxLines: isDescExpanded.value ? null : 3,
|
||||
textOverflow: TextOverflow.ellipsis,
|
||||
fontStyle: textTheme.bodyMedium?.fontStyle,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class SimpleHomeShelf extends HookConsumerWidget {
|
|||
),
|
||||
// fix the height of the shelf as a percentage of the screen height
|
||||
SizedBox(
|
||||
height: height ?? getDefaultShelfHeight(context, perCent: 0.5),
|
||||
height: height ?? getDefaultShelfHeight(context, perCent: 0.45),
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue