offline updates and playhead fix

This commit is contained in:
Forrest 2026-08-16 12:46:30 -04:00
parent 7a199fe4df
commit 6663330260
14 changed files with 1673 additions and 545 deletions

View file

@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../state/providers.dart';
import '../theme/tokens.dart';
import 'art_image.dart';
/// Persistent mini-player pinned above the tab bar. Visible only while a track
/// is loaded; tapping the body jumps to the Now Playing tab.
@ -23,11 +24,12 @@ class MiniPlayer extends ConsumerWidget {
final playing = ref.watch(activePlaybackProvider.select((s) => s.playing));
final controller = ref.read(playbackCommandsProvider);
final client = ref.watch(subsonicClientProvider);
final accent = Theme.of(context).colorScheme.primary;
final artUri = (client != null && current.coverArt != null)
? client.coverArtUri(current.coverArt!, size: 128).toString()
: null;
final artUri = resolveArtUriW(
ref,
coverArt: current.coverArt,
size: 128,
)?.toString();
return Column(
mainAxisSize: MainAxisSize.min,
@ -45,17 +47,16 @@ class MiniPlayer extends ConsumerWidget {
SizedBox(
width: 40,
height: 40,
child: ColoredBox(
color: TimbreColors.background,
child: artUri != null
? Image.network(
artUri,
key: ValueKey(artUri),
fit: BoxFit.cover,
gaplessPlayback: true,
errorBuilder: (_, _, _) => const _ArtFallback(),
)
: const _ArtFallback(),
// Keep the mini player's darker `background` fill behind the
// art (ArtImage's own fill is `surface`) by handing it a
// background-tinted placeholder for the null/error cases.
child: ArtImage(
artUri,
fit: BoxFit.cover,
placeholder: ColoredBox(
color: TimbreColors.background,
child: const _ArtFallback(),
),
),
),
const SizedBox(width: TimbreSpacing.md),
@ -83,9 +84,11 @@ class MiniPlayer extends ConsumerWidget {
),
),
_btn(Icons.skip_previous, controller.previous),
_btn(playing ? Icons.pause : Icons.play_arrow,
controller.togglePlayPause,
color: accent),
_btn(
playing ? Icons.pause : Icons.play_arrow,
controller.togglePlayPause,
color: accent,
),
_btn(Icons.skip_next, controller.next),
],
),
@ -111,7 +114,9 @@ class _MiniProgress extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final progress = ref.watch(activePlaybackProvider.select((s) => s.progress));
final progress = ref.watch(
activePlaybackProvider.select((s) => s.progress),
);
final accent = Theme.of(context).colorScheme.primary;
return SizedBox(
height: 2,
@ -129,7 +134,6 @@ class _ArtFallback extends StatelessWidget {
const _ArtFallback();
@override
Widget build(BuildContext context) => Center(
child: Icon(Icons.album_outlined,
color: TimbreColors.dimmed, size: 22),
);
child: Icon(Icons.album_outlined, color: TimbreColors.dimmed, size: 22),
);
}