fix(settings): match services-page compact row style on desktop
This commit is contained in:
@@ -147,10 +147,12 @@ class _ServiceHubRow extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return FocusableListTile(
|
||||
leading: leading,
|
||||
title: Text(title),
|
||||
title: Text(title, style: settingsOptionTitleStyle(context)),
|
||||
subtitle: Text(username != null ? t.services.connectedAs(username: username!) : t.services.notConnected),
|
||||
trailing: const AppIcon(Symbols.chevron_right_rounded, fill: 1),
|
||||
onTap: onTap,
|
||||
dense: settingsRowDense(),
|
||||
visualDensity: settingsRowVisualDensity(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,12 +333,15 @@ class _SettingsScreenState extends State<SettingsScreen> with FocusableTab, Moun
|
||||
return FocusableListTile(
|
||||
focusNode: _focusTracker.get(_kDownloadLocation),
|
||||
leading: const AppIcon(Symbols.folder_rounded, fill: 1),
|
||||
title: Text(isCustom ? t.settings.downloadLocationCustom : t.settings.downloadLocationDefault),
|
||||
title: Text(
|
||||
isCustom ? t.settings.downloadLocationCustom : t.settings.downloadLocationDefault,
|
||||
style: settingsOptionTitleStyle(context),
|
||||
),
|
||||
subtitle: Text(currentPath, maxLines: 2, overflow: .ellipsis),
|
||||
trailing: const AppIcon(Symbols.chevron_right_rounded, fill: 1),
|
||||
onTap: () => _showDownloadLocationDialog(),
|
||||
dense: false,
|
||||
visualDensity: VisualDensity.standard,
|
||||
dense: settingsRowDense(),
|
||||
visualDensity: settingsRowVisualDensity(),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -517,7 +520,10 @@ class _SettingsScreenState extends State<SettingsScreen> with FocusableTab, Moun
|
||||
fill: 1,
|
||||
color: hasUpdate ? Colors.orange : null,
|
||||
),
|
||||
title: Text(hasUpdate ? t.settings.updateAvailable : t.settings.checkForUpdates),
|
||||
title: Text(
|
||||
hasUpdate ? t.settings.updateAvailable : t.settings.checkForUpdates,
|
||||
style: settingsOptionTitleStyle(context),
|
||||
),
|
||||
subtitle: hasUpdate ? Text(t.update.versionAvailable(version: _updateInfo!['latestVersion'])) : null,
|
||||
trailing: _isCheckingForUpdate
|
||||
? const LoadingIndicatorBox(size: 24)
|
||||
@@ -531,8 +537,8 @@ class _SettingsScreenState extends State<SettingsScreen> with FocusableTab, Moun
|
||||
_checkForUpdates();
|
||||
}
|
||||
},
|
||||
dense: false,
|
||||
visualDensity: VisualDensity.standard,
|
||||
dense: settingsRowDense(),
|
||||
visualDensity: settingsRowVisualDensity(),
|
||||
),
|
||||
_buildAutoCheckUpdatesOnStartupTile(),
|
||||
],
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:material_symbols_icons/symbols.dart';
|
||||
|
||||
import '../screens/settings/settings_utils.dart';
|
||||
import '../services/settings_service.dart';
|
||||
import '../utils/platform_detector.dart';
|
||||
import 'app_icon.dart';
|
||||
import 'focusable_list_tile.dart';
|
||||
import 'settings_section.dart';
|
||||
@@ -41,7 +40,6 @@ class SettingSwitchTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isMobile = PlatformDetector.isMobile(context);
|
||||
final svc = _TileBase._svc;
|
||||
return ValueListenableBuilder<bool>(
|
||||
valueListenable: svc.listenable(pref),
|
||||
@@ -51,8 +49,8 @@ class SettingSwitchTile extends StatelessWidget {
|
||||
title: Text(title, style: settingsOptionTitleStyle(context)),
|
||||
subtitle: subtitle != null ? Text(subtitle!) : null,
|
||||
value: value,
|
||||
dense: isMobile,
|
||||
visualDensity: isMobile ? const VisualDensity(vertical: -3) : VisualDensity.standard,
|
||||
dense: settingsRowDense(),
|
||||
visualDensity: settingsRowVisualDensity(),
|
||||
onChanged: enabled
|
||||
? (v) async {
|
||||
await svc.write(pref, v);
|
||||
@@ -88,7 +86,6 @@ class SettingNavigationTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isMobile = PlatformDetector.isMobile(context);
|
||||
return FocusableListTile(
|
||||
focusNode: focusNode,
|
||||
leading: AppIcon(icon, fill: 1),
|
||||
@@ -96,8 +93,8 @@ class SettingNavigationTile extends StatelessWidget {
|
||||
subtitle: subtitle != null ? Text(subtitle!) : null,
|
||||
trailing: AppIcon(trailingIcon, fill: 1),
|
||||
onTap: onTap ?? () => Navigator.push(context, MaterialPageRoute(builder: destinationBuilder!)),
|
||||
dense: isMobile,
|
||||
visualDensity: isMobile ? const VisualDensity(vertical: -3) : VisualDensity.standard,
|
||||
dense: settingsRowDense(),
|
||||
visualDensity: settingsRowVisualDensity(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -129,7 +126,6 @@ class SettingNumberTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isMobile = PlatformDetector.isMobile(context);
|
||||
final svc = _TileBase._svc;
|
||||
return ValueListenableBuilder<int>(
|
||||
valueListenable: svc.listenable(pref),
|
||||
@@ -138,8 +134,8 @@ class SettingNumberTile extends StatelessWidget {
|
||||
title: Text(title, style: settingsOptionTitleStyle(context)),
|
||||
subtitle: Text(subtitleBuilder(value)),
|
||||
trailing: const AppIcon(Symbols.chevron_right_rounded, fill: 1),
|
||||
dense: isMobile,
|
||||
visualDensity: isMobile ? const VisualDensity(vertical: -3) : VisualDensity.standard,
|
||||
dense: settingsRowDense(),
|
||||
visualDensity: settingsRowVisualDensity(),
|
||||
onTap: () => showNumericInputDialog(
|
||||
context: context,
|
||||
title: title,
|
||||
@@ -186,7 +182,6 @@ class SettingSelectionTile<T, S> extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isMobile = PlatformDetector.isMobile(context);
|
||||
final svc = _TileBase._svc;
|
||||
return ValueListenableBuilder<S>(
|
||||
valueListenable: svc.listenable(pref),
|
||||
@@ -197,8 +192,8 @@ class SettingSelectionTile<T, S> extends StatelessWidget {
|
||||
title: Text(title, style: settingsOptionTitleStyle(context)),
|
||||
subtitle: Text(subtitleBuilder(value)),
|
||||
trailing: const AppIcon(Symbols.chevron_right_rounded, fill: 1),
|
||||
dense: isMobile,
|
||||
visualDensity: isMobile ? const VisualDensity(vertical: -3) : VisualDensity.standard,
|
||||
dense: settingsRowDense(),
|
||||
visualDensity: settingsRowVisualDensity(),
|
||||
onTap: () async {
|
||||
final picked = await showSelectionDialog<T>(
|
||||
context: context,
|
||||
@@ -238,7 +233,6 @@ class SettingRegexTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isMobile = PlatformDetector.isMobile(context);
|
||||
final svc = _TileBase._svc;
|
||||
return ValueListenableBuilder<String>(
|
||||
valueListenable: svc.listenable(pref),
|
||||
@@ -247,8 +241,8 @@ class SettingRegexTile extends StatelessWidget {
|
||||
title: Text(title, style: settingsOptionTitleStyle(context)),
|
||||
subtitle: Text(subtitle),
|
||||
trailing: const AppIcon(Symbols.chevron_right_rounded, fill: 1),
|
||||
dense: isMobile,
|
||||
visualDensity: isMobile ? const VisualDensity(vertical: -3) : VisualDensity.standard,
|
||||
dense: settingsRowDense(),
|
||||
visualDensity: settingsRowVisualDensity(),
|
||||
onTap: () => showRegexInputDialog(
|
||||
context: context,
|
||||
title: title,
|
||||
@@ -331,7 +325,6 @@ class SettingColorTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isMobile = PlatformDetector.isMobile(context);
|
||||
final svc = _TileBase._svc;
|
||||
return ValueListenableBuilder<String>(
|
||||
valueListenable: svc.listenable(pref),
|
||||
@@ -348,8 +341,8 @@ class SettingColorTile extends StatelessWidget {
|
||||
border: Border.all(color: Theme.of(context).colorScheme.outlineVariant),
|
||||
),
|
||||
),
|
||||
dense: isMobile,
|
||||
visualDensity: isMobile ? const VisualDensity(vertical: -3) : VisualDensity.standard,
|
||||
dense: settingsRowDense(),
|
||||
visualDensity: settingsRowVisualDensity(),
|
||||
onTap: () => showColorInputDialog(
|
||||
context: context,
|
||||
title: title,
|
||||
|
||||
@@ -6,14 +6,22 @@ import 'expressive_button_group.dart';
|
||||
|
||||
/// Standard settings-option title style.
|
||||
///
|
||||
/// Mobile matches Flutter's dense ListTile title size so custom controls and
|
||||
/// ordinary settings rows keep the same hierarchy. Desktop and TV retain the
|
||||
/// larger body style used for D-pad readability.
|
||||
/// Matches Flutter's dense ListTile title size so custom controls and
|
||||
/// ordinary settings rows keep the same hierarchy. TV retains the larger
|
||||
/// body style used for D-pad readability at distance.
|
||||
TextStyle? settingsOptionTitleStyle(BuildContext context) {
|
||||
final style = Theme.of(context).textTheme.bodyLarge;
|
||||
return PlatformDetector.isMobile(context) ? style?.copyWith(fontSize: 13) : style;
|
||||
return PlatformDetector.isTV() ? style : style?.copyWith(fontSize: 13);
|
||||
}
|
||||
|
||||
/// Standard settings-row density, paired with [settingsOptionTitleStyle]:
|
||||
/// compact rows everywhere except TV, where full-height rows keep D-pad
|
||||
/// readability.
|
||||
bool settingsRowDense() => !PlatformDetector.isTV();
|
||||
|
||||
VisualDensity settingsRowVisualDensity() =>
|
||||
settingsRowDense() ? const VisualDensity(vertical: -3) : VisualDensity.standard;
|
||||
|
||||
class SettingsSectionHeader extends StatelessWidget {
|
||||
final String title;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user