cover art color scheme extraction (in background)

refactor text styles to use theme
port over part of album screen
This commit is contained in:
austinried
2025-12-03 13:22:14 +09:00
parent b9a094c1c4
commit 6609671ae2
13 changed files with 682 additions and 101 deletions

View File

@@ -1,8 +1,16 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'dart:async';
class AlbumScreen extends StatelessWidget {
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../../l10n/generated/app_localizations.dart';
import '../state/database.dart';
import '../state/source.dart';
import '../ui/cover_art_theme.dart';
import '../ui/images.dart';
class AlbumScreen extends HookConsumerWidget {
const AlbumScreen({
super.key,
required this.id,
@@ -11,27 +19,126 @@ class AlbumScreen extends StatelessWidget {
final String id;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Album $id!'),
TextButton(
onPressed: () {
context.push('/artist');
},
child: Text('Artist...'),
),
CachedNetworkImage(
imageUrl: 'https://placehold.net/400x400.png',
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
],
Widget build(BuildContext context, WidgetRef ref) {
final l = AppLocalizations.of(context);
final db = ref.watch(databaseProvider);
final sourceId = ref.watch(sourceIdProvider);
final getAlbum = useMemoized(
() => db.libraryDao.getAlbum(sourceId, id).getSingle(),
);
final album = useFuture(getAlbum).data;
if (album == null) {
return Container();
}
return CoverArtTheme(
coverArt: album.coverArt,
child: Scaffold(
body: Center(
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: SafeArea(
child: Padding(
padding: EdgeInsetsGeometry.symmetric(horizontal: 16),
child: _Header(
title: album.name,
subtitle: album.albumArtist,
coverArt: album.coverArt,
playText: l.resourcesAlbumActionsPlay,
onPlay: () {},
onMore: () {},
),
),
),
),
],
),
),
),
);
}
}
class _Header extends HookConsumerWidget {
const _Header({
required this.title,
this.subtitle,
this.coverArt,
this.playText,
this.onPlay,
this.onMore,
// required this.downloadActions,
});
final String title;
final String? subtitle;
final String? coverArt;
final String? playText;
final void Function()? onPlay;
final FutureOr<void> Function()? onMore;
// final List<DownloadAction> downloadActions;
@override
Widget build(BuildContext context, WidgetRef ref) {
// final inheritedStyle = DefaultTextStyle.of(context).style;
final theme = Theme.of(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 16),
CoverArtImage(
height: 300,
thumbnail: false,
coverArt: coverArt,
fit: BoxFit.contain,
),
const SizedBox(height: 20),
Column(
children: [
Text(
title,
style: theme.textTheme.headlineMedium,
textAlign: TextAlign.center,
),
Text(
subtitle ?? '',
style: theme.textTheme.headlineSmall,
textAlign: TextAlign.center,
),
],
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.download_done_rounded),
),
if (onPlay != null)
FilledButton.icon(
onPressed: onPlay,
icon: const Icon(Icons.play_arrow_rounded),
label: Text(
playText ?? '',
// style: theme.textTheme.bodyLarge?.copyWith(
// color: theme.colorScheme.onPrimary,
// ),
),
),
if (onMore != null)
IconButton(
onPressed: onMore,
icon: const Icon(Icons.more_horiz),
),
],
),
],
);
}
}

View File

@@ -8,7 +8,6 @@ import '../../l10n/generated/app_localizations.dart';
import '../lists/albums_grid.dart';
import '../lists/artists_list.dart';
import '../state/services.dart';
import '../ui/text.dart';
import '../util/custom_scroll_fix.dart';
const kIconSize = 26.0;
@@ -162,6 +161,7 @@ class TabTitleText extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final l = AppLocalizations.of(context);
final text = TextTheme.of(context);
String tabLocalization(LibraryTab tab) => switch (tab) {
LibraryTab.albums => l.navigationTabsAlbums,
@@ -180,7 +180,7 @@ class TabTitleText extends HookConsumerWidget {
return;
}, [tabName]);
return TextH1(tabText.value);
return Text(tabText.value, style: text.headlineLarge);
}
}

View File

@@ -5,7 +5,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../../l10n/generated/app_localizations.dart';
import '../state/database.dart';
import '../state/source.dart';
import '../ui/text.dart';
const kHorizontalPadding = 18.0;
@@ -15,10 +14,11 @@ class SettingsScreen extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final l = AppLocalizations.of(context);
final text = TextTheme.of(context);
return Scaffold(
appBar: AppBar(
title: TextH1(l.navigationTabsSettings),
title: Text(l.navigationTabsSettings, style: text.headlineLarge),
),
body: ListView(
children: [
@@ -59,6 +59,8 @@ class _SectionHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
final text = TextTheme.of(context);
return Column(
children: [
const SizedBox(height: 16),
@@ -66,7 +68,7 @@ class _SectionHeader extends StatelessWidget {
width: double.infinity,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: kHorizontalPadding),
child: TextH2(title),
child: Text(title, style: text.headlineMedium),
),
),
],