add more tab type options for long press

This commit is contained in:
Fabian Freund
2026-07-05 08:59:27 +02:00
parent d83487325c
commit 586024980d
@@ -22,6 +22,8 @@ import 'package:flutter_material_design_icons/flutter_material_design_icons.dart
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:weblibre/core/design/app_colors.dart';
import 'package:weblibre/core/routing/routes.dart';
import 'package:weblibre/features/geckoview/domain/providers/tab_state.dart';
import 'package:weblibre/features/geckoview/domain/repositories/tab.dart';
import 'package:weblibre/features/geckoview/features/contextmenu/extensions/hit_result.dart';
@@ -38,44 +40,99 @@ class OpenInNewTab extends HookConsumerWidget {
return hitResult.isHttpLink();
}
Future<void> _openInNewTab(
BuildContext context,
WidgetRef ref,
TabMode tabMode,
) async {
final currentTab = ref.read(selectedTabStateProvider);
final tabId = await ref
.read(tabRepositoryProvider.notifier)
.addTab(
url: hitResult.tryGetLink(),
parentId: currentTab?.id,
selectTab: false,
tabMode: tabMode,
);
if (context.mounted) {
//save reference before pop `ref` gets disposed
final repo = ref.read(tabRepositoryProvider.notifier);
showTabSwitchMessage(
context,
onSwitch: () async {
await repo.selectTab(tabId);
},
);
context.pop();
}
}
@override
Widget build(BuildContext context, WidgetRef ref) {
final settings = ref.watch(generalSettingsWithDefaultsProvider);
final currentTab = ref.watch(selectedTabStateProvider);
final currentTabMode =
currentTab?.tabMode ??
TabMode.fromTabType(settings.effectiveDefaultCreateTabType);
// Alternative tab types the user can explicitly choose, excluding the type
// that the main tile action already opens (the current tab's type).
final alternativeTypes =
<TabType>[
TabType.regular,
TabType.private,
if (settings.showIsolatedTabUi) TabType.isolated,
]..remove(currentTabMode.toTabType());
return ListTile(
leading: const Icon(MdiIcons.tabPlus),
title: const Text('Open in new tab'),
onTap: () async {
final currentTab = ref.read(selectedTabStateProvider);
final tabMode =
currentTab?.tabMode ??
TabMode.fromTabType(
ref
.read(generalSettingsWithDefaultsProvider)
.effectiveDefaultCreateTabType,
);
final tabId = await ref
.read(tabRepositoryProvider.notifier)
.addTab(
url: hitResult.tryGetLink(),
parentId: currentTab?.id,
selectTab: false,
tabMode: tabMode,
);
if (context.mounted) {
//save reference before pop `ref` gets disposed
final repo = ref.read(tabRepositoryProvider.notifier);
showTabSwitchMessage(
context,
onSwitch: () async {
await repo.selectTab(tabId);
},
);
context.pop();
}
},
trailing: alternativeTypes.isEmpty
? null
: MenuAnchor(
menuChildren: [
for (final type in alternativeTypes)
MenuItemButton(
onPressed: () =>
_openInNewTab(context, ref, TabMode.fromTabType(type)),
leadingIcon: Icon(
_iconFor(type),
color: _colorFor(context, type),
),
child: Text(_labelFor(type)),
),
],
builder: (context, controller, child) => IconButton(
icon: const Icon(Icons.expand_more),
tooltip: 'Open in a different tab type',
onPressed: () =>
controller.isOpen ? controller.close() : controller.open(),
),
),
onTap: () => _openInNewTab(context, ref, currentTabMode),
);
}
}
IconData _iconFor(TabType type) => switch (type) {
TabType.private => MdiIcons.dominoMask,
TabType.isolated => MdiIcons.snowflake,
_ => MdiIcons.tab,
};
Color? _colorFor(BuildContext context, TabType type) => switch (type) {
TabType.private => AppColors.of(context).privateTabPurple,
TabType.isolated => AppColors.of(context).isolatedTabTeal,
_ => null,
};
String _labelFor(TabType type) => switch (type) {
TabType.private => 'New private tab',
TabType.isolated => 'New isolated tab',
_ => 'New regular tab',
};