Mini player

This commit is contained in:
2024-08-30 12:56:28 +08:00
parent 0a24c86682
commit 8b8915e28f
10 changed files with 341 additions and 81 deletions

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:get/get.dart';
import 'package:rhythm_box/providers/recent_played.dart';
import 'package:rhythm_box/providers/spotify.dart';
@ -72,17 +73,20 @@ class _ExploreScreenState extends State<ExploreScreen> {
title: 'New Releases',
list: _newReleasesPlaylist,
),
if (_newReleasesPlaylist?.isNotEmpty ?? false) const Gap(16),
if (_recentlyPlaylist?.isNotEmpty ?? false)
PlaylistSection(
isLoading: _isLoading['recently']!,
title: 'Recent Played',
list: _recentlyPlaylist,
),
if (_recentlyPlaylist?.isNotEmpty ?? false) const Gap(16),
PlaylistSection(
isLoading: _isLoading['featured']!,
title: 'Featured',
list: _featuredPlaylist,
),
const Gap(16),
],
),
),

View File

@ -0,0 +1,161 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:go_router/go_router.dart';
import 'package:rhythm_box/platform.dart';
import 'package:rhythm_box/widgets/lyrics/synced_lyrics.dart';
import 'package:rhythm_box/widgets/player/bottom_player.dart';
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> {
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');
}
}
}
}
@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(),
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,
);
},
);
},
),
],
).paddingSymmetric(horizontal: 24),
),
),
),
body: Column(
children: [
const Expanded(child: SyncedLyrics(defaultTextZoom: 67)),
SizedBox(
height: 85,
child: BottomPlayer(
isMiniPlayer: true,
usePop: true,
onTap: () => _exitMiniPlayer(),
),
),
],
),
),
),
);
}
}

View File

@ -73,8 +73,8 @@ class _PlayerScreenState extends State<PlayerScreen> {
child: Row(
children: [
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
child: ListView(
padding: const EdgeInsets.symmetric(vertical: 24),
children: [
Obx(
() => LimitedBox(
@ -356,7 +356,7 @@ class _PlayerScreenState extends State<PlayerScreen> {
)
],
),
).marginAll(24),
).marginSymmetric(horizontal: 24),
),
);
}