refactor: use shadcn for mini lyrics window

This commit is contained in:
Kingkor Roy Tirtho 2025-01-28 21:23:57 +06:00
parent 5c6cb770a8
commit 42158a99ff
2 changed files with 164 additions and 151 deletions

View File

@ -10,6 +10,7 @@ import 'package:spotube/components/image/universal_image.dart';
import 'package:spotube/components/inter_scrollbar/inter_scrollbar.dart'; import 'package:spotube/components/inter_scrollbar/inter_scrollbar.dart';
import 'package:spotube/components/ui/button_tile.dart'; import 'package:spotube/components/ui/button_tile.dart';
import 'package:spotube/extensions/artist_simple.dart'; import 'package:spotube/extensions/artist_simple.dart';
import 'package:spotube/extensions/constrains.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/extensions/duration.dart'; import 'package:spotube/extensions/duration.dart';
import 'package:spotube/hooks/utils/use_debounce.dart'; import 'package:spotube/hooks/utils/use_debounce.dart';
@ -193,8 +194,12 @@ class SiblingTracksSheet extends HookConsumerWidget {
if (!isFetchingActiveTrack && if (!isFetchingActiveTrack &&
sourceInfo.id != (activeTrack as SourcedTrack).sourceInfo.id) { sourceInfo.id != (activeTrack as SourcedTrack).sourceInfo.id) {
activeTrackNotifier.swapSibling(sourceInfo); activeTrackNotifier.swapSibling(sourceInfo);
if (MediaQuery.sizeOf(context).mdAndUp) {
closeOverlay(context);
} else {
closeDrawer(context); closeDrawer(context);
} }
}
}, },
); );
}, },

View File

@ -1,13 +1,12 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:palette_generator/palette_generator.dart'; import 'package:palette_generator/palette_generator.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart';
import 'package:shadcn_flutter/shadcn_flutter_extension.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/modules/player/player_controls.dart'; import 'package:spotube/modules/player/player_controls.dart';
import 'package:spotube/modules/player/player_queue.dart'; import 'package:spotube/modules/player/player_queue.dart';
import 'package:spotube/modules/root/sidebar.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/hooks/utils/use_force_update.dart'; import 'package:spotube/hooks/utils/use_force_update.dart';
import 'package:spotube/pages/lyrics/plain_lyrics.dart'; import 'package:spotube/pages/lyrics/plain_lyrics.dart';
@ -30,6 +29,8 @@ class MiniLyricsPage extends HookConsumerWidget {
final playlistQueue = ref.watch(audioPlayerProvider); final playlistQueue = ref.watch(audioPlayerProvider);
final index = useState(0);
final areaActive = useState(false); final areaActive = useState(false);
final hoverMode = useState(true); final hoverMode = useState(true);
final showLyrics = useState(true); final showLyrics = useState(true);
@ -43,8 +44,6 @@ class MiniLyricsPage extends HookConsumerWidget {
return null; return null;
}, []); }, []);
return MouseRegion( return MouseRegion(
onEnter: !hoverMode.value onEnter: !hoverMode.value
? null ? null
@ -56,12 +55,11 @@ class MiniLyricsPage extends HookConsumerWidget {
: (event) { : (event) {
areaActive.value = false; areaActive.value = false;
}, },
child: DefaultTabController(
length: 2,
child: Scaffold( child: Scaffold(
backgroundColor: theme.colorScheme.surface.withOpacity(0.4), backgroundColor: theme.colorScheme.background.withOpacity(0.4),
appBar: PreferredSize( headers: [
preferredSize: const Size.fromHeight(60), Padding(
padding: const EdgeInsets.all(8.0),
child: AnimatedCrossFade( child: AnimatedCrossFade(
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
crossFadeState: areaActive.value crossFadeState: areaActive.value
@ -70,37 +68,32 @@ class MiniLyricsPage extends HookConsumerWidget {
secondChild: const SizedBox(), secondChild: const SizedBox(),
firstChild: DragToMoveArea( firstChild: DragToMoveArea(
child: Row( child: Row(
spacing: 2,
children: [ children: [
const Gap(10), const Gap(10),
if (!kIsMacOS) if (kIsMacOS) const SizedBox(width: 65),
SizedBox(
height: 30,
width: 30,
child: Sidebar.brandLogo(),
),
const Spacer(),
if (showLyrics.value) if (showLyrics.value)
SizedBox( Tabs(
height: 30, index: index.value,
child: TabBar( onChanged: (i) {
index.value = i;
},
tabs: [ tabs: [
Tab(text: context.l10n.synced), Text(context.l10n.synced),
Tab(text: context.l10n.plain), Text(context.l10n.plain),
], ],
isScrollable: true,
),
), ),
const Spacer(), const Spacer(),
IconButton( Tooltip(
tooltip: context.l10n.lyrics, tooltip:
TooltipContainer(child: Text(context.l10n.lyrics)),
child: IconButton(
variance: showLyrics.value
? ButtonVariance.secondary
: ButtonVariance.ghost,
icon: showLyrics.value icon: showLyrics.value
? const Icon(SpotubeIcons.lyrics) ? const Icon(SpotubeIcons.lyrics)
: const Icon(SpotubeIcons.lyricsOff), : const Icon(SpotubeIcons.lyricsOff),
style: ButtonStyle(
foregroundColor: showLyrics.value
? WidgetStateProperty.all(theme.colorScheme.primary)
: null,
),
onPressed: () async { onPressed: () async {
showLyrics.value = !showLyrics.value; showLyrics.value = !showLyrics.value;
areaActive.value = true; areaActive.value = true;
@ -115,38 +108,41 @@ class MiniLyricsPage extends HookConsumerWidget {
} }
}, },
), ),
IconButton( ),
tooltip: context.l10n.show_hide_ui_on_hover, Tooltip(
tooltip: TooltipContainer(
child: Text(context.l10n.show_hide_ui_on_hover),
),
child: IconButton(
variance: hoverMode.value
? ButtonVariance.secondary
: ButtonVariance.ghost,
icon: hoverMode.value icon: hoverMode.value
? const Icon(SpotubeIcons.hoverOn) ? const Icon(SpotubeIcons.hoverOn)
: const Icon(SpotubeIcons.hoverOff), : const Icon(SpotubeIcons.hoverOff),
style: ButtonStyle(
foregroundColor: hoverMode.value
? WidgetStateProperty.all(theme.colorScheme.primary)
: null,
),
onPressed: () async { onPressed: () async {
areaActive.value = true; areaActive.value = true;
hoverMode.value = !hoverMode.value; hoverMode.value = !hoverMode.value;
}, },
), ),
),
if (kIsDesktop) if (kIsDesktop)
FutureBuilder( FutureBuilder(
future: windowManager.isAlwaysOnTop(), future: windowManager.isAlwaysOnTop(),
builder: (context, snapshot) { builder: (context, snapshot) {
return IconButton( return Tooltip(
tooltip: context.l10n.always_on_top, tooltip: TooltipContainer(
child: Text(context.l10n.always_on_top),
),
child: IconButton(
variance: snapshot.data == true
? ButtonVariance.secondary
: ButtonVariance.ghost,
icon: Icon( icon: Icon(
snapshot.data == true snapshot.data == true
? SpotubeIcons.pinOn ? SpotubeIcons.pinOn
: SpotubeIcons.pinOff, : SpotubeIcons.pinOff,
), ),
style: ButtonStyle(
foregroundColor: snapshot.data == true
? WidgetStateProperty.all(
theme.colorScheme.primary)
: null,
),
onPressed: snapshot.data == null onPressed: snapshot.data == null
? null ? null
: () async { : () async {
@ -155,6 +151,7 @@ class MiniLyricsPage extends HookConsumerWidget {
); );
update(); update();
}, },
),
); );
}, },
), ),
@ -163,24 +160,23 @@ class MiniLyricsPage extends HookConsumerWidget {
), ),
), ),
), ),
body: Column( ],
child: Column(
children: [ children: [
if (playlistQueue.activeTrack != null) if (playlistQueue.activeTrack != null)
Text( Text(playlistQueue.activeTrack!.name!).semiBold(),
playlistQueue.activeTrack!.name!,
style: theme.textTheme.titleMedium,
),
if (showLyrics.value) if (showLyrics.value)
Expanded( Expanded(
child: TabBarView( child: IndexedStack(
index: index.value,
children: [ children: [
SyncedLyrics( SyncedLyrics(
palette: PaletteColor(theme.colorScheme.surface, 0), palette: PaletteColor(theme.colorScheme.background, 0),
isModal: true, isModal: true,
defaultTextZoom: 65, defaultTextZoom: 65,
), ),
PlainLyrics( PlainLyrics(
palette: PaletteColor(theme.colorScheme.surface, 0), palette: PaletteColor(theme.colorScheme.background, 0),
isModal: true, isModal: true,
defaultTextZoom: 65, defaultTextZoom: 65,
), ),
@ -197,45 +193,57 @@ class MiniLyricsPage extends HookConsumerWidget {
secondChild: const SizedBox(), secondChild: const SizedBox(),
firstChild: Row( firstChild: Row(
children: [ children: [
IconButton( Tooltip(
tooltip: TooltipContainer(
child: Text(context.l10n.queue),
),
child: IconButton.ghost(
icon: const Icon(SpotubeIcons.queue), icon: const Icon(SpotubeIcons.queue),
tooltip: context.l10n.queue,
onPressed: playlistQueue.activeTrack != null onPressed: playlistQueue.activeTrack != null
? () { ? () {
showModalBottomSheet( openDrawer(
context: context, context: context,
isDismissible: true, barrierDismissible: true,
enableDrag: true, draggable: true,
isScrollControlled: true, barrierColor: Colors.black.withAlpha(100),
backgroundColor: Colors.black12,
barrierColor: Colors.black12,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), transformBackdrop: false,
position: OverlayPosition.bottom,
surfaceBlur: context.theme.surfaceBlur,
surfaceOpacity: 0.7,
expands: true,
builder: (context) => Consumer(
builder: (context, ref, _) {
final playlist = ref.watch(
audioPlayerProvider,
);
final playlistNotifier =
ref.read(audioPlayerProvider.notifier);
return ConstrainedBox(
constraints: BoxConstraints( constraints: BoxConstraints(
maxHeight: maxHeight:
MediaQuery.of(context).size.height * .7, MediaQuery.of(context).size.height *
0.8,
), ),
builder: (context) { child:
return Consumer(builder: (context, ref, _) { PlayerQueue.fromAudioPlayerNotifier(
final playlist = floating: false,
ref.watch(audioPlayerProvider);
return PlayerQueue.fromAudioPlayerNotifier(
floating: true,
playlist: playlist, playlist: playlist,
notifier: ref notifier: playlistNotifier,
.read(audioPlayerProvider.notifier), ),
); );
});
}, },
),
); );
} }
: null, : null,
), ),
),
const Flexible(child: PlayerControls(compact: true)), const Flexible(child: PlayerControls(compact: true)),
IconButton( Tooltip(
tooltip: context.l10n.exit_mini_player, tooltip: TooltipContainer(
child: Text(context.l10n.exit_mini_player)),
child: IconButton.ghost(
icon: const Icon(SpotubeIcons.maximize), icon: const Icon(SpotubeIcons.maximize),
onPressed: () async { onPressed: () async {
if (!kIsDesktop) return; if (!kIsDesktop) return;
@ -262,13 +270,13 @@ class MiniLyricsPage extends HookConsumerWidget {
} }
}, },
), ),
),
], ],
), ),
) )
], ],
), ),
), ),
),
); );
} }
} }