refactor: track page

This commit is contained in:
Kingkor Roy Tirtho 2025-01-05 16:32:14 +06:00
parent dd0bb01af5
commit b734985199
3 changed files with 112 additions and 80 deletions

View File

@ -110,7 +110,6 @@ class AdaptivePopSheetList<T> extends StatelessWidget {
backgroundColor: context.theme.colorScheme.card,
builder: (context) {
return ListView.builder(
physics: const NeverScrollableScrollPhysics(),
itemCount: childrenModified.length,
shrinkWrap: true,
itemBuilder: (context, index) {

View File

@ -1,10 +1,10 @@
import 'dart:io';
import 'package:flutter/material.dart' hide Page;
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart';
import 'package:shadcn_flutter/shadcn_flutter_extension.dart';
import 'package:spotify/spotify.dart' hide Offset;
@ -69,16 +69,20 @@ class TrackOptions extends HookConsumerWidget {
void actionShare(BuildContext context, Track track) {
final data = "https://open.spotify.com/track/${track.id}";
Clipboard.setData(ClipboardData(text: data)).then((_) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
width: 300,
behavior: SnackBarBehavior.floating,
content: Text(
if (context.mounted) {
showToast(
context: context,
location: ToastLocation.topRight,
builder: (context, overlay) {
return SurfaceCard(
child: Text(
context.l10n.copied_to_clipboard(data),
textAlign: TextAlign.center,
),
),
);
},
);
}
});
}
@ -161,7 +165,6 @@ class TrackOptions extends HookConsumerWidget {
@override
Widget build(BuildContext context, ref) {
final scaffoldMessenger = ScaffoldMessenger.of(context);
final mediaQuery = MediaQuery.of(context);
final router = GoRouter.of(context);
final ThemeData(:colorScheme) = Theme.of(context);
@ -220,36 +223,57 @@ class TrackOptions extends HookConsumerWidget {
case TrackOptionValue.addToQueue:
await playback.addTrack(track);
if (context.mounted) {
scaffoldMessenger.showSnackBar(
SnackBar(
content: Text(
showToast(
context: context,
location: ToastLocation.topRight,
builder: (context, overlay) {
return SurfaceCard(
child: Text(
context.l10n.added_track_to_queue(track.name!),
textAlign: TextAlign.center,
),
),
);
},
);
}
break;
case TrackOptionValue.playNext:
playback.addTracksAtFirst([track]);
scaffoldMessenger.showSnackBar(
SnackBar(
content: Text(
if (context.mounted) {
showToast(
context: context,
location: ToastLocation.topRight,
builder: (context, overlay) {
return SurfaceCard(
child: Text(
context.l10n.track_will_play_next(track.name!),
),
textAlign: TextAlign.center,
),
);
},
);
}
break;
case TrackOptionValue.removeFromQueue:
playback.removeTrack(track.id!);
scaffoldMessenger.showSnackBar(
SnackBar(
content: Text(
if (context.mounted) {
showToast(
context: context,
location: ToastLocation.topRight,
builder: (context, overlay) {
return SurfaceCard(
child: Text(
context.l10n.removed_track_from_queue(
track.name!,
),
),
textAlign: TextAlign.center,
),
);
},
);
}
break;
case TrackOptionValue.favorite:
favorites.toggleTrackLike(track);
@ -286,7 +310,10 @@ class TrackOptions extends HookConsumerWidget {
case TrackOptionValue.details:
showDialog(
context: context,
builder: (context) => TrackDetailsDialog(track: track),
builder: (context) => ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: TrackDetailsDialog(track: track),
),
);
break;
case TrackOptionValue.download:
@ -299,8 +326,7 @@ class TrackOptions extends HookConsumerWidget {
},
icon: icon ?? const Icon(SpotubeIcons.moreHorizontal),
headings: [
ListTile(
dense: true,
Basic(
leading: AspectRatio(
aspectRatio: 1,
child: ClipRRect(
@ -316,8 +342,7 @@ class TrackOptions extends HookConsumerWidget {
track.name!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.titleMedium,
),
).semiBold(),
subtitle: Align(
alignment: Alignment.centerLeft,
child: ArtistLink(
@ -449,7 +474,7 @@ class TrackOptions extends HookConsumerWidget {
leading: Assets.logos.songlinkTransparent.image(
width: 22,
height: 22,
color: colorScheme.onSurface.withOpacity(0.5),
color: colorScheme.foreground.withOpacity(0.5),
),
child: Text(context.l10n.song_link),
),
@ -471,11 +496,6 @@ class TrackOptions extends HookConsumerWidget {
adaptivePopSheetList.showDropdownMenu(context, offsetFromRect);
};
return ListTileTheme(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: adaptivePopSheetList,
);
return adaptivePopSheetList;
}
}

View File

@ -1,8 +1,8 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart';
import 'package:skeletonizer/skeletonizer.dart';
import 'package:spotube/collections/fake.dart';
import 'package:spotube/collections/spotube_icons.dart';
@ -32,7 +32,7 @@ class TrackPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, ref) {
final ThemeData(:textTheme, :colorScheme) = Theme.of(context);
final ThemeData(:typography, :colorScheme) = Theme.of(context);
final mediaQuery = MediaQuery.of(context);
final playlist = ref.watch(audioPlayerProvider);
@ -53,12 +53,15 @@ class TrackPage extends HookConsumerWidget {
}
return Scaffold(
appBar: const TitleBar(
headers: const [
TitleBar(
automaticallyImplyLeading: true,
backgroundColor: Colors.transparent,
),
extendBodyBehindAppBar: true,
body: Stack(
surfaceBlur: 0,
)
],
floatingHeader: true,
child: Stack(
children: [
Positioned.fill(
child: Container(
@ -71,7 +74,7 @@ class TrackPage extends HookConsumerWidget {
),
fit: BoxFit.cover,
colorFilter: ColorFilter.mode(
colorScheme.surface.withOpacity(0.5),
colorScheme.background.withOpacity(0.5),
BlendMode.srcOver,
),
alignment: Alignment.topCenter,
@ -89,7 +92,7 @@ class TrackPage extends HookConsumerWidget {
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
colorScheme.surface,
colorScheme.background,
Colors.transparent,
],
begin: Alignment.topCenter,
@ -125,8 +128,7 @@ class TrackPage extends HookConsumerWidget {
children: [
Text(
track.name!,
style: textTheme.titleLarge,
),
).large().semiBold(),
const Gap(10),
Row(
mainAxisSize: MainAxisSize.min,
@ -170,9 +172,10 @@ class TrackPage extends HookConsumerWidget {
if (!isActive &&
!playlist.tracks
.containsBy(track, (t) => t.id))
OutlinedButton.icon(
icon: const Icon(SpotubeIcons.queueAdd),
label: Text(context.l10n.queue),
Button.outline(
leading:
const Icon(SpotubeIcons.queueAdd),
child: Text(context.l10n.queue),
onPressed: () {
playlistNotifier.addTrack(track);
},
@ -181,28 +184,38 @@ class TrackPage extends HookConsumerWidget {
if (!isActive &&
!playlist.tracks
.containsBy(track, (t) => t.id))
IconButton.outlined(
icon:
const Icon(SpotubeIcons.lightning),
tooltip: context.l10n.play_next,
Tooltip(
tooltip: TooltipContainer(
child: Text(context.l10n.play_next),
),
child: IconButton.outline(
icon: const Icon(
SpotubeIcons.lightning),
onPressed: () {
playlistNotifier
.addTracksAtFirst([track]);
},
),
),
const Gap(5),
IconButton.filled(
tooltip: isActive
Tooltip(
tooltip: TooltipContainer(
child: Text(
isActive
? context.l10n.pause_playback
: context.l10n.play,
),
),
child: IconButton.primary(
shape: ButtonShape.circle,
icon: Icon(
isActive
? SpotubeIcons.pause
: SpotubeIcons.play,
color: colorScheme.onPrimary,
),
onPressed: onPlay,
),
),
const Gap(5),
if (mediaQuery.smAndDown)
const Spacer()