freezer/lib/api/player/systray.dart
Pato05 87c9733f51
add build script for linux
fix audio service stop on android
getTrack backend improvements
get new track token when expired
move shuffle button into LibraryPlaylists as FAB
move favoriteButton next to track title
move lyrics button on top of album art
search: fix chips, and remove checkbox when selected
2024-02-19 00:49:32 +01:00

111 lines
3 KiB
Dart

import 'dart:io';
import 'package:audio_service/audio_service.dart';
import 'package:flutter/services.dart';
import 'package:freezer/api/player/audio_handler.dart';
import 'package:freezer/settings.dart';
import 'package:freezer/translations.i18n.dart';
import 'package:tray_manager/tray_manager.dart';
import 'package:window_manager/window_manager.dart';
final sysTray = SysTray._();
/// Handles system tray and window events
class SysTray with TrayListener, WindowListener {
SysTray._();
static String getIcon({bool forcePng = false}) {
if (Platform.isWindows && !forcePng) {
if (settings.useColorTrayIcon) {
return 'assets/icon.ico';
}
return 'assets/icon_mono_small.ico';
}
if (settings.useColorTrayIcon) {
return 'assets/icon_small.png';
}
return 'assets/icon_mono_small.png';
}
bool _inited = false;
Future<void> init() async {
if (_inited) return;
_inited = true;
windowManager.addListener(this);
updateIcon();
try {
await trayManager.setToolTip('freezer');
// ignore: empty_catches
} catch (e) {}
await updateContextMenu();
trayManager.addListener(this);
playerHelper.playing
.listen((playing) => updateContextMenu(playing: playing));
audioHandler.mediaItem
.listen((mediaItem) => updateContextMenu(mediaItem: mediaItem));
}
Future<void> updateIcon() {
return trayManager.setIcon(getIcon());
}
Future<void> updateContextMenu({bool? playing, MediaItem? mediaItem}) async {
playing ??= playerHelper.playing.valueOrNull ?? false;
mediaItem ??= audioHandler.mediaItem.valueOrNull;
// create context menu
final menu = Menu(items: [
if (mediaItem != null) ...[
MenuItem(label: mediaItem.title, disabled: true),
MenuItem(label: mediaItem.artist!, disabled: true),
],
MenuItem.separator(),
MenuItem(
label: 'Previous'.i18n,
onClick: (_) => audioHandler.skipToPrevious()),
playing
? MenuItem(label: 'Pause'.i18n, onClick: (_) => audioHandler.pause())
: MenuItem(label: 'Play'.i18n, onClick: (_) => audioHandler.play()),
MenuItem(label: 'Next'.i18n, onClick: (_) => audioHandler.skipToNext()),
MenuItem.separator(),
MenuItem(
label: 'Show'.i18n,
// we can safely ignore it if it errors, as it's expected
onClick: (_) => windowManager.show().catchError((e) {})),
MenuItem(
label: 'Exit'.i18n,
onClick: (_) async {
await audioHandler.pause();
SystemNavigator.pop();
},
),
]);
// set context menu
await trayManager.setContextMenu(menu);
}
@override
void onTrayIconMouseUp() async {
try {
await windowManager.show();
// ignore: empty_catches
} catch (e) {}
}
@override
void onTrayIconRightMouseUp() => trayManager.popUpContextMenu();
@override
void onWindowClose() {
// release resources before closing
audioHandler.dispose();
}
}