visual nesting indicator for quick tab switcher

This commit is contained in:
Fabian Freund
2026-06-06 06:33:39 +02:00
parent bafd77af5a
commit beb9a27a9c
9 changed files with 167 additions and 10 deletions
@@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:weblibre/core/routing/routes.dart';
@@ -100,6 +101,12 @@ const List<SettingsSectionDefinition> toolbarLayoutSettingsSections = [
keywords: ['page titles'],
child: _QuickTabSwitcherShowTitlesTile(),
),
SettingsEntryDefinition(
title: 'Hierarchy Depth in Quick Tab Switcher',
subtitle: 'How many nesting chevrons to show on switcher chips',
keywords: ['hierarchy', 'nesting', 'depth', 'tree', 'chevrons'],
child: _QuickTabSwitcherHierarchyGlyphsTile(),
),
],
),
SettingsSectionDefinition(
@@ -453,6 +460,100 @@ class _QuickTabSwitcherShowTitlesTile extends HookConsumerWidget {
}
}
class _QuickTabSwitcherHierarchyGlyphsTile extends HookConsumerWidget {
const _QuickTabSwitcherHierarchyGlyphsTile();
static String _label(int glyphs) => switch (glyphs) {
0 => 'Off',
1 => '1 level',
_ => '$glyphs levels',
};
@override
Widget build(BuildContext context, WidgetRef ref) {
final hierarchyGlyphs = ref.watch(
generalSettingsWithDefaultsProvider.select(
(s) => s.quickTabSwitcherHierarchyGlyphs,
),
);
final tabBarShowQuickTabSwitcherBar = ref.watch(
generalSettingsWithDefaultsProvider.select(
(s) => s.tabBarShowQuickTabSwitcherBar,
),
);
final sliderValue = useState(hierarchyGlyphs.toDouble());
useEffect(() {
sliderValue.value = hierarchyGlyphs.toDouble();
return null;
}, [hierarchyGlyphs]);
final currentGlyphs = sliderValue.value.round();
final enabled = tabBarShowQuickTabSwitcherBar;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTile(
title: const Text('Hierarchy Depth in Quick Tab Switcher'),
subtitle: const Text(
'How many nesting chevrons to show on switcher chips before '
'collapsing into a count badge (0 hides the indicator)',
),
leading: const Icon(MdiIcons.fileTree),
contentPadding: EdgeInsets.zero,
enabled: enabled,
),
Row(
children: [
Expanded(
child: Slider(
min: minQuickTabSwitcherHierarchyGlyphs.toDouble(),
max: maxQuickTabSwitcherHierarchyGlyphs.toDouble(),
divisions:
maxQuickTabSwitcherHierarchyGlyphs -
minQuickTabSwitcherHierarchyGlyphs,
label: _label(currentGlyphs),
value: sliderValue.value.clamp(
minQuickTabSwitcherHierarchyGlyphs.toDouble(),
maxQuickTabSwitcherHierarchyGlyphs.toDouble(),
),
onChanged: enabled
? (value) {
sliderValue.value = value;
}
: null,
onChangeEnd: enabled
? (value) async {
final normalized = value.round();
sliderValue.value = normalized.toDouble();
await ref
.read(
saveGeneralSettingsControllerProvider.notifier,
)
.save(
(currentSettings) => currentSettings.copyWith
.quickTabSwitcherHierarchyGlyphs(normalized),
);
}
: null,
),
),
Text(
_label(currentGlyphs),
style: Theme.of(context).textTheme.titleMedium,
),
],
),
],
),
);
}
}
class _AutoHideTabBarTile extends HookConsumerWidget {
const _AutoHideTabBarTile();
@@ -160,7 +160,7 @@ class TabBarPreviewCard extends HookWidget {
tabMode: TabMode.isolated('preview-isolated-context'),
isHistory: false,
isPinned: false,
depth: 2,
depth: 3,
url: Uri.parse('https://example.com/bank'),
color: null,
avatar: const Icon(MdiIcons.web, size: 20),
@@ -203,6 +203,7 @@ class TabBarPreviewCard extends HookWidget {
scrollController: quickTabsController,
showTitles: settings.quickTabSwitcherShowTitles,
showIsolatedTabUi: settings.showIsolatedTabUi,
hierarchyGlyphs: settings.quickTabSwitcherHierarchyGlyphs,
enablePinTabInMenu: false,
onSelected: (_) async {},
);