From fbddf3e0f76a21ca97a72ca0002c4b3ec662a95c Mon Sep 17 00:00:00 2001 From: Fabian Freund Date: Sat, 14 Feb 2026 19:40:49 +0100 Subject: [PATCH] setting to show/hide quick tab titles --- .../browser_modules/bottom_app_bar.dart | 18 +++++++-- .../screens/appearance_display_settings.dart | 38 +++++++++++++++++++ .../user/data/models/general_settings.dart | 7 +++- .../user/data/models/general_settings.g.dart | 16 ++++++++ .../domain/repositories/general_settings.dart | 2 + .../repositories/general_settings.g.dart | 2 +- .../widgets/selectable_chips.dart | 3 ++ 7 files changed, 80 insertions(+), 6 deletions(-) diff --git a/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart b/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart index e09806ea..118681a8 100644 --- a/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart +++ b/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/bottom_app_bar.dart @@ -482,6 +482,11 @@ class QuickTabSwitcher extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final appColors = AppColors.of(context); final selectedTabId = ref.watch(selectedTabProvider); + final showTitles = ref.watch( + generalSettingsWithDefaultsProvider.select( + (s) => s.quickTabSwitcherShowTitles, + ), + ); final tabStates = (switch (quickTabSwitcherMode) { QuickTabSwitcherMode.lastUsedTabs => ref.watch(fifoTabStatesProvider), @@ -511,14 +516,19 @@ class QuickTabSwitcher extends HookConsumerWidget { enableDelete: false, scrollController: chipScrollController, itemId: (item) => item.id, + labelPadding: (item) => + (!showTitles && !item.isHistory && !item.isPrivate) + ? EdgeInsets.zero + : null, itemLabel: (item) { return Row( mainAxisSize: MainAxisSize.min, children: [ - ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 64), - child: Text(item.title), - ), + if (item.isHistory || showTitles) + ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 64), + child: Text(item.title), + ), if (item.isPrivate) Padding( padding: const EdgeInsets.only(left: 8.0), diff --git a/app/lib/features/settings/presentation/screens/appearance_display_settings.dart b/app/lib/features/settings/presentation/screens/appearance_display_settings.dart index da293fc1..1b62b6f5 100644 --- a/app/lib/features/settings/presentation/screens/appearance_display_settings.dart +++ b/app/lib/features/settings/presentation/screens/appearance_display_settings.dart @@ -82,11 +82,49 @@ class _TabBarLayoutSection extends StatelessWidget { _TabListShowFaviconsTile(), _ShowQuickTabSwitcherBarTile(), _QuickTabSwitcherModeSection(), + _QuickTabSwitcherShowTitlesTile(), ], ); } } +class _QuickTabSwitcherShowTitlesTile extends HookConsumerWidget { + const _QuickTabSwitcherShowTitlesTile(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final quickTabSwitcherShowTitles = ref.watch( + generalSettingsWithDefaultsProvider.select( + (s) => s.quickTabSwitcherShowTitles, + ), + ); + final tabBarShowQuickTabSwitcherBar = ref.watch( + generalSettingsWithDefaultsProvider.select( + (s) => s.tabBarShowQuickTabSwitcherBar, + ), + ); + + return SwitchListTile.adaptive( + title: const Text('Show Titles in Quick Tab Switcher'), + subtitle: const Text( + 'Display tab titles alongside icons in the quick tab switcher bar', + ), + secondary: const Icon(MdiIcons.textRecognition), + value: quickTabSwitcherShowTitles, + onChanged: tabBarShowQuickTabSwitcherBar + ? (value) async { + await ref + .read(saveGeneralSettingsControllerProvider.notifier) + .save( + (currentSettings) => currentSettings.copyWith + .quickTabSwitcherShowTitles(value), + ); + } + : null, + ); + } +} + class _GesturesSection extends StatelessWidget { const _GesturesSection(); diff --git a/app/lib/features/user/data/models/general_settings.dart b/app/lib/features/user/data/models/general_settings.dart index c9f62be1..d0266561 100644 --- a/app/lib/features/user/data/models/general_settings.dart +++ b/app/lib/features/user/data/models/general_settings.dart @@ -87,6 +87,7 @@ class GeneralSettings with FastEquatable { final int maxSearchHistoryEntries; final bool allowClipboardAccess; final bool tabListShowFavicons; + final bool quickTabSwitcherShowTitles; GeneralSettings({ required this.themeMode, @@ -116,6 +117,7 @@ class GeneralSettings with FastEquatable { required this.maxSearchHistoryEntries, required this.allowClipboardAccess, required this.tabListShowFavicons, + required this.quickTabSwitcherShowTitles, }); GeneralSettings.withDefaults({ @@ -146,6 +148,7 @@ class GeneralSettings with FastEquatable { int? maxSearchHistoryEntries, bool? allowClipboardAccess, bool? tabListShowFavicons, + bool? quickTabSwitcherShowTitles, }) : themeMode = themeMode ?? ThemeMode.dark, enableReadability = enableReadability ?? true, enforceReadability = enforceReadability ?? false, @@ -176,7 +179,8 @@ class GeneralSettings with FastEquatable { unassignedTabsAutoCleanInterval ?? Duration.zero, maxSearchHistoryEntries = maxSearchHistoryEntries ?? 5, allowClipboardAccess = allowClipboardAccess ?? true, - tabListShowFavicons = tabListShowFavicons ?? false; + tabListShowFavicons = tabListShowFavicons ?? false, + quickTabSwitcherShowTitles = quickTabSwitcherShowTitles ?? true; factory GeneralSettings.fromJson(Map json) => _$GeneralSettingsFromJson(json); @@ -212,5 +216,6 @@ class GeneralSettings with FastEquatable { maxSearchHistoryEntries, allowClipboardAccess, tabListShowFavicons, + quickTabSwitcherShowTitles, ]; } diff --git a/app/lib/features/user/data/models/general_settings.g.dart b/app/lib/features/user/data/models/general_settings.g.dart index 5431887e..9eeb77aa 100644 --- a/app/lib/features/user/data/models/general_settings.g.dart +++ b/app/lib/features/user/data/models/general_settings.g.dart @@ -73,6 +73,8 @@ abstract class _$GeneralSettingsCWProxy { GeneralSettings tabListShowFavicons(bool tabListShowFavicons); + GeneralSettings quickTabSwitcherShowTitles(bool quickTabSwitcherShowTitles); + /// Creates a new instance with the provided field values. /// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `GeneralSettings(...).copyWith.fieldName(value)`. /// @@ -108,6 +110,7 @@ abstract class _$GeneralSettingsCWProxy { int maxSearchHistoryEntries, bool allowClipboardAccess, bool tabListShowFavicons, + bool quickTabSwitcherShowTitles, }); } @@ -231,6 +234,10 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy { GeneralSettings tabListShowFavicons(bool tabListShowFavicons) => call(tabListShowFavicons: tabListShowFavicons); + @override + GeneralSettings quickTabSwitcherShowTitles(bool quickTabSwitcherShowTitles) => + call(quickTabSwitcherShowTitles: quickTabSwitcherShowTitles); + @override /// Creates a new instance with the provided field values. /// Passing `null` to a nullable field nullifies it, while `null` for a non-nullable field is ignored. To update a single field use `GeneralSettings(...).copyWith.fieldName(value)`. @@ -267,6 +274,7 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy { Object? maxSearchHistoryEntries = const $CopyWithPlaceholder(), Object? allowClipboardAccess = const $CopyWithPlaceholder(), Object? tabListShowFavicons = const $CopyWithPlaceholder(), + Object? quickTabSwitcherShowTitles = const $CopyWithPlaceholder(), }) { return GeneralSettings( themeMode: themeMode == const $CopyWithPlaceholder() || themeMode == null @@ -427,6 +435,12 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy { ? _value.tabListShowFavicons // ignore: cast_nullable_to_non_nullable : tabListShowFavicons as bool, + quickTabSwitcherShowTitles: + quickTabSwitcherShowTitles == const $CopyWithPlaceholder() || + quickTabSwitcherShowTitles == null + ? _value.quickTabSwitcherShowTitles + // ignore: cast_nullable_to_non_nullable + : quickTabSwitcherShowTitles as bool, ); } } @@ -504,6 +518,7 @@ GeneralSettings _$GeneralSettingsFromJson( maxSearchHistoryEntries: (json['maxSearchHistoryEntries'] as num?)?.toInt(), allowClipboardAccess: json['allowClipboardAccess'] as bool?, tabListShowFavicons: json['tabListShowFavicons'] as bool?, + quickTabSwitcherShowTitles: json['quickTabSwitcherShowTitles'] as bool?, ); Map _$GeneralSettingsToJson( @@ -545,6 +560,7 @@ Map _$GeneralSettingsToJson( 'maxSearchHistoryEntries': instance.maxSearchHistoryEntries, 'allowClipboardAccess': instance.allowClipboardAccess, 'tabListShowFavicons': instance.tabListShowFavicons, + 'quickTabSwitcherShowTitles': instance.quickTabSwitcherShowTitles, }; const _$ThemeModeEnumMap = { diff --git a/app/lib/features/user/domain/repositories/general_settings.dart b/app/lib/features/user/domain/repositories/general_settings.dart index 5a99c907..c540321d 100644 --- a/app/lib/features/user/domain/repositories/general_settings.dart +++ b/app/lib/features/user/domain/repositories/general_settings.dart @@ -149,6 +149,8 @@ class GeneralSettingsRepository extends _$GeneralSettingsRepository { DriftSqlType.bool, db.typeMapping, ), + 'quickTabSwitcherShowTitles': settings['quickTabSwitcherShowTitles'] + ?.readAs(DriftSqlType.bool, db.typeMapping), }); } diff --git a/app/lib/features/user/domain/repositories/general_settings.g.dart b/app/lib/features/user/domain/repositories/general_settings.g.dart index 28d277f3..4c80e21d 100644 --- a/app/lib/features/user/domain/repositories/general_settings.g.dart +++ b/app/lib/features/user/domain/repositories/general_settings.g.dart @@ -35,7 +35,7 @@ final class GeneralSettingsRepositoryProvider } String _$generalSettingsRepositoryHash() => - r'a4e4fb6f4e5b40d32b4cc676532af3bacdbe54d2'; + r'290fc9fb5dd79b94bb4a42a131184b385a1ecb4d'; abstract class _$GeneralSettingsRepository extends $StreamNotifier { diff --git a/app/lib/presentation/widgets/selectable_chips.dart b/app/lib/presentation/widgets/selectable_chips.dart index aeeda56b..5afbf467 100644 --- a/app/lib/presentation/widgets/selectable_chips.dart +++ b/app/lib/presentation/widgets/selectable_chips.dart @@ -71,6 +71,7 @@ class SelectableChips extends StatelessWidget { final int? Function(T item)? itemBadgeCount; final Color? Function(T item)? itemBackgroundColor; final Color? selectedBorderColor; + final EdgeInsetsGeometry? Function(T item)? labelPadding; final Widget Function(Widget child, S item)? itemWrap; @@ -97,6 +98,7 @@ class SelectableChips extends StatelessWidget { this.onLongPress, this.sortSelectedFirst = true, this.scrollController, + this.labelPadding, super.key, }); @@ -150,6 +152,7 @@ class SelectableChips extends StatelessWidget { child: FilterChip( selected: selectedBorderColor == null && isSelected, showCheckmark: false, + labelPadding: labelPadding?.call(item), onSelected: (value) { if (value) { onSelected?.call(item);