This commit is contained in:
Forrest 2026-07-29 16:22:00 -04:00
parent fc22d11df1
commit 27a8a62475
32 changed files with 354 additions and 335 deletions

View file

@ -34,16 +34,16 @@ class _NowPlayingScreenState extends ConsumerState<NowPlayingScreen> {
if (current == null) {
return const Center(
child: Text('Nothing playing.',
style: TextStyle(color: RatuneColors.dimmed)),
style: TextStyle(color: TimbreColors.dimmed)),
);
}
return Padding(
padding: const EdgeInsets.fromLTRB(
RatuneSpacing.lg,
RatuneSpacing.xl,
RatuneSpacing.lg,
RatuneSpacing.lg,
TimbreSpacing.lg,
TimbreSpacing.xl,
TimbreSpacing.lg,
TimbreSpacing.lg,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
@ -53,21 +53,21 @@ class _NowPlayingScreenState extends ConsumerState<NowPlayingScreen> {
Expanded(
child: _showQueue ? const _QueuePanel() : const _AlbumArtPanel(),
),
const SizedBox(height: RatuneSpacing.xl),
const SizedBox(height: TimbreSpacing.xl),
_InfoStrip(song: current, state: state, accent: accent),
const SizedBox(height: RatuneSpacing.sm),
const SizedBox(height: TimbreSpacing.sm),
_FavRating(song: current),
const SizedBox(height: RatuneSpacing.xs),
const SizedBox(height: TimbreSpacing.xs),
_Transport(state: state, ref: ref, accent: accent),
if (!state.supported)
const Padding(
padding: EdgeInsets.only(top: RatuneSpacing.sm),
padding: EdgeInsets.only(top: TimbreSpacing.sm),
child: Text(
'Audio output unavailable on this platform — test on Android/iOS.',
style: TextStyle(color: RatuneColors.dimmed, fontSize: 11),
style: TextStyle(color: TimbreColors.dimmed, fontSize: 11),
),
),
const SizedBox(height: RatuneSpacing.sm),
const SizedBox(height: TimbreSpacing.sm),
_QueueToggle(
showQueue: _showQueue,
queueLength: state.queue.length,
@ -102,8 +102,8 @@ class _QueueToggle extends StatelessWidget {
onTap: onTap,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: RatuneSpacing.lg,
vertical: RatuneSpacing.sm,
horizontal: TimbreSpacing.lg,
vertical: TimbreSpacing.sm,
),
child: Row(
mainAxisSize: MainAxisSize.min,
@ -111,13 +111,13 @@ class _QueueToggle extends StatelessWidget {
Icon(
showQueue ? Icons.album_outlined : Icons.queue_music,
size: 16,
color: showQueue ? accent : RatuneColors.dimmed,
color: showQueue ? accent : TimbreColors.dimmed,
),
const SizedBox(width: RatuneSpacing.sm),
const SizedBox(width: TimbreSpacing.sm),
Text(
showQueue ? 'Album art' : 'Queue ($queueLength)',
style: TextStyle(
color: showQueue ? accent : RatuneColors.foreground,
color: showQueue ? accent : TimbreColors.foreground,
),
),
],
@ -140,7 +140,7 @@ class _QueuePanel extends ConsumerWidget {
return HairlinePanel(
title: 'Queue',
trailing: '(${state.queue.length})',
padding: const EdgeInsets.symmetric(vertical: RatuneSpacing.md),
padding: const EdgeInsets.symmetric(vertical: TimbreSpacing.md),
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: state.queue.length,
@ -153,15 +153,15 @@ class _QueuePanel extends ConsumerWidget {
.playSongs(state.queue, startIndex: i),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: RatuneSpacing.lg,
vertical: RatuneSpacing.xs,
horizontal: TimbreSpacing.lg,
vertical: TimbreSpacing.xs,
),
child: Row(
children: [
SizedBox(
width: 28,
child: Text('${i + 1}',
style: const TextStyle(color: RatuneColors.dimmed)),
style: const TextStyle(color: TimbreColors.dimmed)),
),
Expanded(
child: Text(
@ -169,23 +169,23 @@ class _QueuePanel extends ConsumerWidget {
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: isCurrent ? accent : RatuneColors.foreground,
color: isCurrent ? accent : TimbreColors.foreground,
fontWeight:
isCurrent ? FontWeight.w700 : FontWeight.w400,
),
),
),
Text(_fmt(song.duration),
style: const TextStyle(color: RatuneColors.dimmed)),
style: const TextStyle(color: TimbreColors.dimmed)),
InkWell(
onTap: () =>
ref.read(playbackProvider.notifier).removeAt(i),
customBorder: const CircleBorder(),
child: const SizedBox(
width: RatuneSpacing.minTouchTarget,
height: RatuneSpacing.minTouchTarget,
width: TimbreSpacing.minTouchTarget,
height: TimbreSpacing.minTouchTarget,
child: Icon(Icons.close,
size: 18, color: RatuneColors.dimmed),
size: 18, color: TimbreColors.dimmed),
),
),
],
@ -216,11 +216,11 @@ class _AlbumArtPanel extends ConsumerWidget {
return HairlinePanel(
title: 'Album Art',
padding: const EdgeInsets.all(RatuneSpacing.md),
padding: const EdgeInsets.all(TimbreSpacing.md),
child: AspectRatio(
aspectRatio: 1,
child: ColoredBox(
color: RatuneColors.surface,
color: TimbreColors.surface,
child: artUri != null
? Image.network(
artUri,
@ -263,15 +263,15 @@ class _FavRating extends ConsumerWidget {
onTap: () => ref.read(favoritesProvider.notifier).toggleSong(song),
customBorder: const CircleBorder(),
child: Padding(
padding: const EdgeInsets.all(RatuneSpacing.sm),
padding: const EdgeInsets.all(TimbreSpacing.sm),
child: Icon(
starred ? Icons.favorite : Icons.favorite_border,
color: starred ? accent : RatuneColors.dimmed,
color: starred ? accent : TimbreColors.dimmed,
size: 22,
),
),
),
const SizedBox(width: RatuneSpacing.md),
const SizedBox(width: TimbreSpacing.md),
for (int i = 1; i <= 5; i++)
GestureDetector(
onTap: () => ref
@ -282,7 +282,7 @@ class _FavRating extends ConsumerWidget {
child: Icon(
i <= rating ? Icons.star : Icons.star_border,
size: 18,
color: i <= rating ? accent : RatuneColors.dimmed,
color: i <= rating ? accent : TimbreColors.dimmed,
),
),
),
@ -291,9 +291,9 @@ class _FavRating extends ConsumerWidget {
onTap: () => showAddToPlaylistSheet(context, songs: [song]),
customBorder: const CircleBorder(),
child: const Padding(
padding: EdgeInsets.all(RatuneSpacing.sm),
padding: EdgeInsets.all(TimbreSpacing.sm),
child: Icon(Icons.playlist_add,
size: 22, color: RatuneColors.dimmed),
size: 22, color: TimbreColors.dimmed),
),
),
InkWell(
@ -305,7 +305,7 @@ class _FavRating extends ConsumerWidget {
},
customBorder: const CircleBorder(),
child: Padding(
padding: const EdgeInsets.all(RatuneSpacing.sm),
padding: const EdgeInsets.all(TimbreSpacing.sm),
child: isDownloading
? const SizedBox(
width: 18,
@ -317,7 +317,7 @@ class _FavRating extends ConsumerWidget {
? Icons.download_done
: Icons.download_outlined,
size: 22,
color: isDownloaded ? accent : RatuneColors.dimmed,
color: isDownloaded ? accent : TimbreColors.dimmed,
),
),
),
@ -348,19 +348,19 @@ class _InfoStrip extends StatelessWidget {
overflow: TextOverflow.ellipsis,
style: TextStyle(color: accent, fontWeight: FontWeight.w700)),
Text(song.artist ?? 'Unknown artist',
style: const TextStyle(color: RatuneColors.foreground)),
style: const TextStyle(color: TimbreColors.foreground)),
if (album.isNotEmpty)
Text(album, style: const TextStyle(color: RatuneColors.dimmed)),
const SizedBox(height: RatuneSpacing.md),
Text(album, style: const TextStyle(color: TimbreColors.dimmed)),
const SizedBox(height: TimbreSpacing.md),
Row(
children: [
Text(_fmtDur(state.position),
style: const TextStyle(color: RatuneColors.dimmed)),
const SizedBox(width: RatuneSpacing.md),
style: const TextStyle(color: TimbreColors.dimmed)),
const SizedBox(width: TimbreSpacing.md),
Expanded(child: BlockProgressBar(progress: state.progress)),
const SizedBox(width: RatuneSpacing.md),
const SizedBox(width: TimbreSpacing.md),
Text(_fmtDur(state.duration),
style: const TextStyle(color: RatuneColors.dimmed)),
style: const TextStyle(color: TimbreColors.dimmed)),
],
),
],
@ -387,20 +387,20 @@ class _Transport extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_btn(Icons.shuffle, controller.toggleShuffle,
color: state.shuffle ? accent : RatuneColors.dimmed),
color: state.shuffle ? accent : TimbreColors.dimmed),
_btn(Icons.skip_previous, controller.previous),
_btn(state.playing ? Icons.pause : Icons.play_arrow,
controller.togglePlayPause,
color: accent, size: 40),
_btn(Icons.skip_next, controller.next),
_btn(loopIcon, controller.cycleLoop,
color: state.loop != LoopMode.off ? accent : RatuneColors.dimmed),
color: state.loop != LoopMode.off ? accent : TimbreColors.dimmed),
],
);
}
Widget _btn(IconData icon, VoidCallback onTap,
{Color color = RatuneColors.foreground, double size = 28}) {
{Color color = TimbreColors.foreground, double size = 28}) {
return IconButton(
onPressed: onTap,
icon: Icon(icon, color: color, size: size),
@ -413,7 +413,7 @@ class _ArtFallback extends StatelessWidget {
@override
Widget build(BuildContext context) => const Center(
child: Icon(Icons.album_outlined,
color: RatuneColors.dimmed, size: 48),
color: TimbreColors.dimmed, size: 48),
);
}