This commit is contained in:
Forrest 2026-08-05 21:57:06 -04:00
parent 2ce32cac4e
commit b6639fb1c9
26 changed files with 454 additions and 204 deletions

View file

@ -35,7 +35,10 @@ class SettingsScreen extends ConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const _Caption(
'Quality used when playing tracks that are not downloaded.'),
'Quality used when playing tracks that are not downloaded. '
'"Original (native)" streams the source untouched — full '
'resolution up to 192 kHz / 24-bit. The kbps options '
'transcode down to that (lossy) data rate.'),
const SizedBox(height: TimbreSpacing.md),
_ChoiceChips<int>(
label: 'Max bitrate',
@ -56,7 +59,8 @@ class SettingsScreen extends ConsumerWidget {
children: [
const _Caption(
'Quality used when saving tracks for offline playback. '
'"Original" keeps the source file (best quality, largest).'),
'"Original (native)" keeps the source file untouched — '
'full resolution up to 192 kHz / 24-bit (largest).'),
const SizedBox(height: TimbreSpacing.md),
_ChoiceChips<int>(
label: 'Max bitrate',
@ -95,25 +99,39 @@ class SettingsScreen extends ConsumerWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const _Caption(
'By default the accent color is drawn from the playing '
'album art. Turn on a static accent to pin one color.'),
const _Caption('Choose the overall color theme of the app.'),
const SizedBox(height: TimbreSpacing.md),
_ChoiceChips<bool>(
label: 'Static accent',
values: const [false, true],
selected: settings.useStaticAccent,
labelFor: (v) => v ? 'On' : 'Off',
onSelect: controller.setUseStaticAccent,
_ChoiceChips<AppTheme>(
label: 'Theme',
values: AppTheme.values,
selected: settings.appTheme,
labelFor: AppSettings.themeLabel,
onSelect: controller.setAppTheme,
),
if (settings.useStaticAccent) ...[
// The static-vs-dynamic accent choice is unique to the
// Default theme; other themes lock their own accent.
if (settings.appTheme == AppTheme.standard) ...[
const SizedBox(height: TimbreSpacing.lg),
_ColorChips(
label: 'Accent color',
values: AppSettings.accentChoices,
selected: settings.staticAccentColor,
onSelect: controller.setStaticAccentColor,
const _Caption(
'By default the accent color is drawn from the playing '
'album art. Turn on a static accent to pin one color.'),
const SizedBox(height: TimbreSpacing.md),
_ChoiceChips<bool>(
label: 'Static accent',
values: const [false, true],
selected: settings.useStaticAccent,
labelFor: (v) => v ? 'On' : 'Off',
onSelect: controller.setUseStaticAccent,
),
if (settings.useStaticAccent) ...[
const SizedBox(height: TimbreSpacing.lg),
_ColorChips(
label: 'Accent color',
values: AppSettings.accentChoices,
selected: settings.staticAccentColor,
onSelect: controller.setStaticAccentColor,
),
],
],
const SizedBox(height: TimbreSpacing.lg),
const _Caption(
@ -184,7 +202,7 @@ class SettingsScreen extends ConsumerWidget {
'one is connected at a time.'),
const SizedBox(height: TimbreSpacing.sm),
if (conn.servers.isEmpty)
const Padding(
Padding(
padding: EdgeInsets.symmetric(vertical: TimbreSpacing.sm),
child: Text('No servers saved yet.',
style: TextStyle(color: TimbreColors.dimmed)),
@ -206,7 +224,7 @@ class SettingsScreen extends ConsumerWidget {
const SizedBox(height: TimbreSpacing.sm),
InkWell(
onTap: () => showConnectSheet(context),
child: const Padding(
child: Padding(
padding:
EdgeInsets.symmetric(vertical: TimbreSpacing.md),
child: Row(
@ -285,13 +303,13 @@ class _ServerManageRow extends StatelessWidget {
IconButton(
tooltip: 'Edit',
onPressed: onEdit,
icon: const Icon(Icons.edit, size: 16, color: TimbreColors.dimmed),
icon: Icon(Icons.edit, size: 16, color: TimbreColors.dimmed),
),
IconButton(
tooltip: 'Delete',
onPressed: onDelete,
icon:
const Icon(Icons.delete_outline, size: 18, color: TimbreColors.dimmed),
Icon(Icons.delete_outline, size: 18, color: TimbreColors.dimmed),
),
],
);
@ -304,7 +322,7 @@ class _Caption extends StatelessWidget {
@override
Widget build(BuildContext context) => Text(
text,
style: const TextStyle(color: TimbreColors.dimmed, fontSize: 12),
style: TextStyle(color: TimbreColors.dimmed, fontSize: 12),
);
}
@ -331,7 +349,7 @@ class _ChoiceChips<T> extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(label, style: const TextStyle(color: TimbreColors.foreground)),
Text(label, style: TextStyle(color: TimbreColors.foreground)),
const SizedBox(height: TimbreSpacing.sm),
Wrap(
spacing: TimbreSpacing.sm,
@ -415,7 +433,7 @@ class _Stepper extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(label, style: const TextStyle(color: TimbreColors.foreground)),
Text(label, style: TextStyle(color: TimbreColors.foreground)),
const SizedBox(height: TimbreSpacing.sm),
Row(
children: [
@ -432,7 +450,7 @@ class _Stepper extends StatelessWidget {
alignment: Alignment.center,
child: Text(
'$value',
style: const TextStyle(
style: TextStyle(
color: TimbreColors.foreground,
fontWeight: FontWeight.w700,
),
@ -507,7 +525,7 @@ class _ColorChips extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(label, style: const TextStyle(color: TimbreColors.foreground)),
Text(label, style: TextStyle(color: TimbreColors.foreground)),
const SizedBox(height: TimbreSpacing.sm),
Wrap(
spacing: TimbreSpacing.sm,