RhythmBox/lib/screens/player/mini.dart

224 lines
7.6 KiB
Dart
Raw Normal View History

2024-08-30 04:56:28 +00:00
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:go_router/go_router.dart';
import 'package:rhythm_box/platform.dart';
2024-09-02 12:42:33 +00:00
import 'package:rhythm_box/providers/user_preferences.dart';
2024-08-30 15:18:49 +00:00
import 'package:rhythm_box/screens/player/queue.dart';
import 'package:rhythm_box/screens/player/siblings.dart';
2024-08-30 04:56:28 +00:00
import 'package:rhythm_box/widgets/lyrics/synced_lyrics.dart';
import 'package:rhythm_box/widgets/player/bottom_player.dart';
2024-08-30 15:18:49 +00:00
import 'package:rhythm_box/widgets/player/devices.dart';
2024-09-02 12:42:33 +00:00
import 'package:wakelock_plus/wakelock_plus.dart';
2024-08-30 04:56:28 +00:00
import 'package:window_manager/window_manager.dart';
class MiniPlayerScreen extends StatefulWidget {
final Size prevSize;
const MiniPlayerScreen({super.key, required this.prevSize});
@override
State<MiniPlayerScreen> createState() => _MiniPlayerScreenState();
}
class _MiniPlayerScreenState extends State<MiniPlayerScreen> {
2024-09-02 12:42:33 +00:00
late final UserPreferencesProvider _preferences = Get.find();
2024-08-30 04:56:28 +00:00
bool _wasMaximized = false;
bool _areaActive = false;
bool _isHoverMode = true;
void _exitMiniPlayer() async {
if (!PlatformInfo.isDesktop) return;
try {
await windowManager.setMinimumSize(const Size(300, 700));
await windowManager.setAlwaysOnTop(false);
if (_wasMaximized) {
await windowManager.maximize();
} else {
await windowManager.setSize(widget.prevSize);
}
await windowManager.setAlignment(Alignment.center);
if (!PlatformInfo.isLinux) {
await windowManager.setHasShadow(true);
}
await Future.delayed(const Duration(milliseconds: 200));
} finally {
if (context.mounted) {
if (GoRouter.of(context).canPop()) {
GoRouter.of(context).pop();
} else {
GoRouter.of(context).replaceNamed('player');
}
}
}
}
2024-09-02 12:42:33 +00:00
@override
void activate() {
super.activate();
if (_preferences.state.value.playerWakelock) {
WakelockPlus.enable();
}
}
@override
void deactivate() {
super.deactivate();
WakelockPlus.disable();
}
2024-08-30 04:56:28 +00:00
@override
void initState() {
super.initState();
if (PlatformInfo.isDesktop) {
WidgetsBinding.instance.addPostFrameCallback((_) async {
_wasMaximized = await windowManager.isMaximized();
});
}
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return MouseRegion(
onEnter: !_isHoverMode
? null
: (event) {
setState(() => _areaActive = true);
},
onExit: !_isHoverMode
? null
: (event) {
setState(() => _areaActive = false);
},
child: DefaultTabController(
length: 2,
child: Scaffold(
backgroundColor: theme.colorScheme.surface,
appBar: PreferredSize(
preferredSize: const Size.fromHeight(60),
child: AnimatedCrossFade(
duration: const Duration(milliseconds: 200),
crossFadeState: _areaActive
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
secondChild: const SizedBox(),
firstChild: Material(
color: theme.colorScheme.surfaceContainer,
child: Row(
children: [
IconButton(
icon: const Icon(Icons.fullscreen_exit),
onPressed: () => _exitMiniPlayer(),
),
const Spacer(),
2024-08-30 15:18:49 +00:00
IconButton(
icon: const Icon(Icons.speaker, size: 18),
onPressed: () {
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) => const PlayerDevicePopup(),
);
},
),
IconButton(
icon: const Icon(Icons.merge),
onPressed: () {
showModalBottomSheet(
useRootNavigator: true,
isScrollControlled: true,
context: context,
builder: (context) => const SiblingTracksPopup(),
).then((_) {
if (mounted) {
setState(() {});
}
});
},
),
IconButton(
icon: const Icon(Icons.queue_music),
onPressed: () {
showModalBottomSheet(
useRootNavigator: true,
isScrollControlled: true,
context: context,
builder: (context) => const PlayerQueuePopup(),
).then((_) {
if (mounted) {
setState(() {});
}
});
},
),
2024-08-30 04:56:28 +00:00
IconButton(
icon: _isHoverMode
? const Icon(Icons.touch_app)
: const Icon(Icons.touch_app_outlined),
style: ButtonStyle(
foregroundColor: _isHoverMode
? WidgetStateProperty.all(theme.colorScheme.primary)
: null,
),
onPressed: () async {
setState(() {
_areaActive = true;
_isHoverMode = !_isHoverMode;
});
},
),
if (PlatformInfo.isDesktop)
FutureBuilder(
future: windowManager.isAlwaysOnTop(),
builder: (context, snapshot) {
return IconButton(
icon: Icon(
snapshot.data == true
? Icons.push_pin
: Icons.push_pin_outlined,
),
style: ButtonStyle(
foregroundColor: snapshot.data == true
? WidgetStateProperty.all(
theme.colorScheme.primary)
: null,
),
onPressed: snapshot.data == null
? null
: () async {
await windowManager.setAlwaysOnTop(
snapshot.data == true ? false : true,
);
2024-08-30 13:53:40 +00:00
setState(() {});
2024-08-30 04:56:28 +00:00
},
);
},
),
],
2024-08-30 13:53:40 +00:00
).paddingSymmetric(horizontal: 14),
2024-08-30 04:56:28 +00:00
),
),
),
body: Column(
children: [
const Expanded(child: SyncedLyrics(defaultTextZoom: 67)),
SizedBox(
height: 85,
child: BottomPlayer(
isMiniPlayer: true,
usePop: true,
onTap: () => _exitMiniPlayer(),
),
),
],
),
),
),
);
}
}