Skip to content

Commit

Permalink
feat: desktop mini player support
Browse files Browse the repository at this point in the history
  • Loading branch information
KRTirtho committed Apr 15, 2023
1 parent 62ad86e commit 471812d
Show file tree
Hide file tree
Showing 10 changed files with 390 additions and 89 deletions.
38 changes: 24 additions & 14 deletions lib/collections/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter/widgets.dart';
import 'package:go_router/go_router.dart';
import 'package:spotify/spotify.dart' hide Search;
import 'package:spotube/pages/home/home.dart';
import 'package:spotube/pages/lyrics/mini_lyrics.dart';
import 'package:spotube/pages/search/search.dart';
import 'package:spotube/pages/settings/blacklist.dart';
import 'package:spotube/pages/settings/about.dart';
Expand Down Expand Up @@ -31,42 +32,51 @@ final router = GoRouter(
routes: [
GoRoute(
path: "/",
pageBuilder: (context, state) => SpotubePage(child: const HomePage()),
pageBuilder: (context, state) => const SpotubePage(child: HomePage()),
),
GoRoute(
path: "/search",
name: "Search",
pageBuilder: (context, state) =>
SpotubePage(child: const SearchPage()),
const SpotubePage(child: SearchPage()),
),
GoRoute(
path: "/library",
name: "Library",
pageBuilder: (context, state) =>
SpotubePage(child: const LibraryPage()),
const SpotubePage(child: LibraryPage()),
),
GoRoute(
path: "/lyrics",
name: "Lyrics",
pageBuilder: (context, state) =>
SpotubePage(child: const LyricsPage()),
const SpotubePage(child: LyricsPage()),
routes: [
GoRoute(
path: "mini",
parentNavigatorKey: rootNavigatorKey,
pageBuilder: (context, state) => const SpotubePage(
child: MiniLyricsPage(),
),
),
],
),
GoRoute(
path: "/settings",
pageBuilder: (context, state) => SpotubePage(
child: const SettingsPage(),
pageBuilder: (context, state) => const SpotubePage(
child: SettingsPage(),
),
routes: [
GoRoute(
path: "blacklist",
pageBuilder: (context, state) => SpotubePage(
child: const BlackListPage(),
pageBuilder: (context, state) => const SpotubePage(
child: BlackListPage(),
),
),
GoRoute(
path: "about",
pageBuilder: (context, state) => SpotubePage(
child: const AboutSpotube(),
pageBuilder: (context, state) => const SpotubePage(
child: AboutSpotube(),
),
),
],
Expand Down Expand Up @@ -106,16 +116,16 @@ final router = GoRouter(
GoRoute(
path: "/login-tutorial",
parentNavigatorKey: rootNavigatorKey,
pageBuilder: (context, state) => SpotubePage(
child: const LoginTutorial(),
pageBuilder: (context, state) => const SpotubePage(
child: LoginTutorial(),
),
),
GoRoute(
path: "/player",
parentNavigatorKey: rootNavigatorKey,
pageBuilder: (context, state) {
return SpotubePage(
child: const PlayerView(),
return const SpotubePage(
child: PlayerView(),
);
},
),
Expand Down
4 changes: 4 additions & 0 deletions lib/collections/spotube_icons.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,8 @@ abstract class SpotubeIcons {
static const zoomIn = FeatherIcons.zoomIn;
static const zoomOut = FeatherIcons.zoomOut;
static const tray = FeatherIcons.chevronDown;
static const miniPlayer = Icons.picture_in_picture_rounded;
static const maximize = FeatherIcons.maximize2;
static const pinOn = Icons.push_pin_rounded;
static const pinOff = Icons.push_pin_outlined;
}
1 change: 0 additions & 1 deletion lib/components/player/player_actions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class PlayerActions extends HookConsumerWidget {
@override
Widget build(BuildContext context, ref) {
final playlist = ref.watch(PlaylistQueueNotifier.provider);
final playlistNotifier = ref.watch(PlaylistQueueNotifier.provider.notifier);
final isLocalTrack = playlist?.activeTrack is LocalTrack;
final downloader = ref.watch(downloaderProvider);
final isInQueue = downloader.inQueue
Expand Down
141 changes: 72 additions & 69 deletions lib/components/player/player_controls.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import 'package:spotube/utils/primitive_utils.dart';

class PlayerControls extends HookConsumerWidget {
final PaletteGenerator? palette;
final bool compact;

PlayerControls({
this.palette,
this.compact = false,
Key? key,
}) : super(key: key);

Expand Down Expand Up @@ -78,8 +80,8 @@ class PlayerControls extends HookConsumerWidget {
backgroundColor: accentColor?.color ?? theme.colorScheme.primary,
foregroundColor:
accentColor?.titleTextColor ?? theme.colorScheme.onPrimary,
padding: const EdgeInsets.all(12),
iconSize: 24,
padding: EdgeInsets.all(compact ? 10 : 12),
iconSize: compact ? 18 : 24,
);

return GestureDetector(
Expand All @@ -97,82 +99,83 @@ class PlayerControls extends HookConsumerWidget {
constraints: const BoxConstraints(maxWidth: 600),
child: Column(
children: [
HookBuilder(
builder: (context) {
final progressObj = useProgress(ref);
if (!compact)
HookBuilder(
builder: (context) {
final progressObj = useProgress(ref);

final progressStatic = progressObj.item1;
final position = progressObj.item2;
final duration = progressObj.item3;
final progressStatic = progressObj.item1;
final position = progressObj.item2;
final duration = progressObj.item3;

final totalMinutes = PrimitiveUtils.zeroPadNumStr(
duration.inMinutes.remainder(60),
);
final totalSeconds = PrimitiveUtils.zeroPadNumStr(
duration.inSeconds.remainder(60),
);
final currentMinutes = PrimitiveUtils.zeroPadNumStr(
position.inMinutes.remainder(60),
);
final currentSeconds = PrimitiveUtils.zeroPadNumStr(
position.inSeconds.remainder(60),
);
final totalMinutes = PrimitiveUtils.zeroPadNumStr(
duration.inMinutes.remainder(60),
);
final totalSeconds = PrimitiveUtils.zeroPadNumStr(
duration.inSeconds.remainder(60),
);
final currentMinutes = PrimitiveUtils.zeroPadNumStr(
position.inMinutes.remainder(60),
);
final currentSeconds = PrimitiveUtils.zeroPadNumStr(
position.inSeconds.remainder(60),
);

final progress = useState<num>(
useMemoized(() => progressStatic, []),
);
final progress = useState<num>(
useMemoized(() => progressStatic, []),
);

useEffect(() {
progress.value = progressStatic;
return null;
}, [progressStatic]);
useEffect(() {
progress.value = progressStatic;
return null;
}, [progressStatic]);

return Column(
children: [
Tooltip(
message: "Slide to seek forward or backward",
child: Slider(
// cannot divide by zero
// there's an edge case for value being bigger
// than total duration. Keeping it resolved
value: progress.value.toDouble(),
onChanged: playlist?.isLoading == true
? null
: (v) {
progress.value = v;
},
onChangeEnd: (value) async {
await playlistNotifier.seek(
Duration(
seconds: (value * duration.inSeconds).toInt(),
),
);
},
activeColor: sliderColor,
inactiveColor: sliderColor.withOpacity(0.15),
),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
return Column(
children: [
Tooltip(
message: "Slide to seek forward or backward",
child: Slider(
// cannot divide by zero
// there's an edge case for value being bigger
// than total duration. Keeping it resolved
value: progress.value.toDouble(),
onChanged: playlist?.isLoading == true
? null
: (v) {
progress.value = v;
},
onChangeEnd: (value) async {
await playlistNotifier.seek(
Duration(
seconds: (value * duration.inSeconds).toInt(),
),
);
},
activeColor: sliderColor,
inactiveColor: sliderColor.withOpacity(0.15),
),
),
child: DefaultTextStyle(
style: theme.textTheme.bodySmall!.copyWith(
color: palette?.dominantColor?.bodyTextColor,
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("$currentMinutes:$currentSeconds"),
Text("$totalMinutes:$totalSeconds"),
],
child: DefaultTextStyle(
style: theme.textTheme.bodySmall!.copyWith(
color: palette?.dominantColor?.bodyTextColor,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("$currentMinutes:$currentSeconds"),
Text("$totalMinutes:$totalSeconds"),
],
),
),
),
),
],
);
},
),
],
);
},
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expand Down
14 changes: 13 additions & 1 deletion lib/components/root/bottom_player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import 'dart:ui';

import 'package:flutter/gestures.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

import 'package:spotube/collections/assets.gen.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/player/player_actions.dart';
import 'package:spotube/components/player/player_overlay.dart';
import 'package:spotube/components/player/player_track_details.dart';
Expand Down Expand Up @@ -123,7 +125,17 @@ class BottomPlayer extends HookConsumerWidget {
);
}),
),
PlayerActions()
PlayerActions(
extraActions: [
IconButton(
tooltip: 'Mini Player',
icon: const Icon(SpotubeIcons.miniPlayer),
onPressed: () {
GoRouter.of(context).push('/lyrics/mini');
},
),
],
)
],
),
)
Expand Down

0 comments on commit 471812d

Please sign in to comment.