possibility to inject child tabs
This commit is contained in:
@@ -23,10 +23,8 @@ GeckoSelectionActionService selectionActionService(Ref ref) {
|
||||
service.setActions([
|
||||
SearchAction((text) async {
|
||||
final router = await ref.read(routerProvider.future);
|
||||
final isCurrentPrivate =
|
||||
ref.read(selectedTabStateProvider)?.isPrivate ?? false;
|
||||
final route = SearchRoute(
|
||||
tabType: isCurrentPrivate ? TabType.private : TabType.regular,
|
||||
tabType: ref.read(selectedTabTypeProvider) ?? TabType.regular,
|
||||
searchText: text,
|
||||
);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ part of 'providers.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$selectionActionServiceHash() =>
|
||||
r'456bab83920ae78969bece514d5524e2445e06b6';
|
||||
r'a3682b3f97d9798aadbca3be882d5be74085b762';
|
||||
|
||||
/// See also [selectionActionService].
|
||||
@ProviderFor(selectionActionService)
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:riverpod/riverpod.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
import 'package:weblibre/core/logger.dart';
|
||||
import 'package:weblibre/core/routing/routes.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/entities/states/find_result.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/entities/states/history.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/entities/states/readerable.dart';
|
||||
@@ -204,3 +205,14 @@ TabState? selectedTabState(Ref ref) {
|
||||
final tabId = ref.watch(selectedTabProvider);
|
||||
return ref.watch(tabStateProvider(tabId));
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
TabType? selectedTabType(Ref ref) {
|
||||
final isPrivate = ref.watch(
|
||||
selectedTabStateProvider.select((value) => value?.isPrivate),
|
||||
);
|
||||
|
||||
return isPrivate.mapNotNull(
|
||||
(isCurrentPrivate) => isCurrentPrivate ? TabType.private : TabType.regular,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -158,6 +158,23 @@ final selectedTabStateProvider = AutoDisposeProvider<TabState?>.internal(
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
typedef SelectedTabStateRef = AutoDisposeProviderRef<TabState?>;
|
||||
String _$selectedTabTypeHash() => r'53093fc6db8becde7500163661e087fb0a2eb955';
|
||||
|
||||
/// See also [selectedTabType].
|
||||
@ProviderFor(selectedTabType)
|
||||
final selectedTabTypeProvider = AutoDisposeProvider<TabType?>.internal(
|
||||
selectedTabType,
|
||||
name: r'selectedTabTypeProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$selectedTabTypeHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
typedef SelectedTabTypeRef = AutoDisposeProviderRef<TabType?>;
|
||||
String _$tabStatesHash() => r'e4d2f2b4ddd65beac8a1fd0d22bad1e0a26b41bd';
|
||||
|
||||
/// See also [TabStates].
|
||||
|
||||
+3
-36
@@ -17,6 +17,7 @@ import 'package:weblibre/features/geckoview/features/browser/domain/entities/she
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/edit_url_dialog.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/extension_badge_icon.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/tab_creation_menu.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/tabs_action_button.dart';
|
||||
import 'package:weblibre/features/geckoview/features/find_in_page/presentation/controllers/find_in_page.dart';
|
||||
import 'package:weblibre/features/geckoview/features/readerview/presentation/widgets/reader_button.dart';
|
||||
@@ -95,43 +96,9 @@ class BrowserBottomAppBar extends HookConsumerWidget {
|
||||
actions: [
|
||||
if (selectedTabId != null && displayedSheet is! ViewTabsSheet)
|
||||
ReaderButton(),
|
||||
MenuAnchor(
|
||||
TabCreationMenu(
|
||||
controller: tabMenuController,
|
||||
builder: (context, controller, child) {
|
||||
return child!;
|
||||
},
|
||||
menuChildren: [
|
||||
if (selectedTabId != null) ...[
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.closeTab(selectedTabId);
|
||||
},
|
||||
leadingIcon: const Icon(Icons.close),
|
||||
child: const Text('Close Tab'),
|
||||
),
|
||||
const Divider(),
|
||||
],
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await const SearchRoute(
|
||||
tabType: TabType.private,
|
||||
).push(context);
|
||||
},
|
||||
leadingIcon: const Icon(MdiIcons.tabUnselected),
|
||||
child: const Text('Add Private Tab'),
|
||||
),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await const SearchRoute(
|
||||
tabType: TabType.regular,
|
||||
).push(context);
|
||||
},
|
||||
leadingIcon: const Icon(MdiIcons.tabPlus),
|
||||
child: const Text('Add Tab'),
|
||||
),
|
||||
],
|
||||
selectedTabId: selectedTabId,
|
||||
child: TabsActionButton(
|
||||
isActive: displayedSheet is ViewTabsSheet,
|
||||
onTap: () {
|
||||
|
||||
+2
-1
@@ -299,7 +299,8 @@ class _BrowserViewState extends ConsumerState<BrowserView>
|
||||
context,
|
||||
onAdd: (searchText) async {
|
||||
await SearchRoute(
|
||||
tabType: TabType.regular,
|
||||
tabType:
|
||||
ref.read(selectedTabTypeProvider) ?? TabType.regular,
|
||||
searchText: searchText ?? SearchRoute.emptySearchText,
|
||||
).push(context);
|
||||
},
|
||||
|
||||
+3
-7
@@ -79,7 +79,7 @@ class _TabSheetHeader extends HookConsumerWidget {
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(MdiIcons.graph),
|
||||
icon: const Icon(MdiIcons.familyTree),
|
||||
selectedIcon: const Icon(MdiIcons.table),
|
||||
isSelected: treeViewEnabled,
|
||||
iconSize: 18,
|
||||
@@ -443,10 +443,8 @@ class ViewTabsSheetWidget extends HookConsumerWidget {
|
||||
),
|
||||
child: FloatingActionButton.small(
|
||||
onPressed: () async {
|
||||
final isCurrentPrivate =
|
||||
ref.read(selectedTabStateProvider)?.isPrivate ?? false;
|
||||
await SearchRoute(
|
||||
tabType: isCurrentPrivate ? TabType.private : TabType.regular,
|
||||
tabType: ref.read(selectedTabTypeProvider) ?? TabType.regular,
|
||||
).push(context);
|
||||
|
||||
onClose();
|
||||
@@ -618,10 +616,8 @@ class ViewTabTreesSheetWidget extends HookConsumerWidget {
|
||||
),
|
||||
child: FloatingActionButton.small(
|
||||
onPressed: () async {
|
||||
final isCurrentPrivate =
|
||||
ref.read(selectedTabStateProvider)?.isPrivate ?? false;
|
||||
await SearchRoute(
|
||||
tabType: isCurrentPrivate ? TabType.private : TabType.regular,
|
||||
tabType: ref.read(selectedTabTypeProvider) ?? TabType.regular,
|
||||
).push(context);
|
||||
|
||||
onClose();
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
import 'package:flutter/material.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';
|
||||
import 'package:weblibre/features/geckoview/domain/repositories/tab.dart';
|
||||
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
|
||||
|
||||
class TabCreationMenu extends HookConsumerWidget {
|
||||
final Widget child;
|
||||
final MenuController controller;
|
||||
final String? selectedTabId;
|
||||
|
||||
const TabCreationMenu({
|
||||
super.key,
|
||||
required this.child,
|
||||
required this.controller,
|
||||
required this.selectedTabId,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final createChildTabsOption = ref.watch(
|
||||
generalSettingsRepositoryProvider.select(
|
||||
(value) => value.createChildTabsOption,
|
||||
),
|
||||
);
|
||||
|
||||
return MenuAnchor(
|
||||
controller: controller,
|
||||
builder: (context, controller, child) {
|
||||
return child!;
|
||||
},
|
||||
menuChildren: [
|
||||
if (selectedTabId != null) ...[
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.closeTab(selectedTabId!);
|
||||
},
|
||||
leadingIcon: const Icon(Icons.close),
|
||||
child: const Text('Close Tab'),
|
||||
),
|
||||
const Divider(),
|
||||
],
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await const SearchRoute(tabType: TabType.regular).push(context);
|
||||
},
|
||||
leadingIcon: const Icon(MdiIcons.tabPlus),
|
||||
child: const Text('Add Regular Tab'),
|
||||
),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await const SearchRoute(tabType: TabType.private).push(context);
|
||||
},
|
||||
leadingIcon: const Icon(MdiIcons.tabUnselected),
|
||||
child: const Text('Add Private Tab'),
|
||||
),
|
||||
if (createChildTabsOption)
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await const SearchRoute(tabType: TabType.child).push(context);
|
||||
},
|
||||
leadingIcon: const Icon(MdiIcons.fileTree),
|
||||
child: const Text('Add Child Tab'),
|
||||
),
|
||||
],
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import 'package:weblibre/features/bangs/data/models/bang_data.dart';
|
||||
import 'package:weblibre/features/bangs/domain/providers/bangs.dart';
|
||||
import 'package:weblibre/features/bangs/domain/providers/search.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/controllers/bottom_sheet.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/providers/selected_tab.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/browser/domain/providers.dart';
|
||||
import 'package:weblibre/features/geckoview/features/search/presentation/widgets/clipboard_fill.dart';
|
||||
@@ -16,6 +18,7 @@ import 'package:weblibre/features/geckoview/features/search/presentation/widgets
|
||||
import 'package:weblibre/features/geckoview/features/search/presentation/widgets/search_modules/history_suggestions.dart';
|
||||
import 'package:weblibre/features/geckoview/features/search/presentation/widgets/search_modules/search_suggestions.dart';
|
||||
import 'package:weblibre/features/geckoview/features/search/presentation/widgets/search_modules/tab_search.dart';
|
||||
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
|
||||
import 'package:weblibre/presentation/hooks/sampled_value_notifier.dart';
|
||||
import 'package:weblibre/utils/uri_parser.dart' as uri_parser;
|
||||
|
||||
@@ -29,8 +32,20 @@ class SearchScreen extends HookConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final formKey = useMemoized(() => GlobalKey<FormState>());
|
||||
|
||||
final createChildTabsOption = ref.watch(
|
||||
generalSettingsRepositoryProvider.select(
|
||||
(value) => value.createChildTabsOption,
|
||||
),
|
||||
);
|
||||
|
||||
final selectedTabType = useState(tabType);
|
||||
final isPrivate = selectedTabType.value == TabType.private;
|
||||
final currentTabTabType = ref.watch(selectedTabTypeProvider);
|
||||
|
||||
final privateTabMode = switch (selectedTabType.value) {
|
||||
TabType.regular => false,
|
||||
TabType.private => true,
|
||||
TabType.child => currentTabTabType == TabType.private,
|
||||
};
|
||||
|
||||
final searchTextController = useTextEditingController(
|
||||
text: initialSearchText,
|
||||
@@ -61,7 +76,7 @@ class SearchScreen extends HookConsumerWidget {
|
||||
if (activeBang != null && (formKey.currentState?.validate() == true)) {
|
||||
final searchUri = activeBang.getTemplateUrl(query);
|
||||
|
||||
if (!isPrivate) {
|
||||
if (!privateTabMode) {
|
||||
await ref
|
||||
.read(bangSearchProvider.notifier)
|
||||
.triggerBangSearch(activeBang, query);
|
||||
@@ -69,7 +84,13 @@ class SearchScreen extends HookConsumerWidget {
|
||||
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.addTab(url: searchUri, private: isPrivate);
|
||||
.addTab(
|
||||
url: searchUri,
|
||||
private: privateTabMode,
|
||||
parentId: (selectedTabType.value == TabType.child)
|
||||
? ref.read(selectedTabProvider)
|
||||
: null,
|
||||
);
|
||||
|
||||
if (context.mounted) {
|
||||
ref.read(bottomSheetControllerProvider.notifier).dismiss();
|
||||
@@ -93,17 +114,23 @@ class SearchScreen extends HookConsumerWidget {
|
||||
canRequestFocus: false,
|
||||
child: SegmentedButton(
|
||||
showSelectedIcon: false,
|
||||
segments: const [
|
||||
ButtonSegment(
|
||||
segments: [
|
||||
const ButtonSegment(
|
||||
value: TabType.regular,
|
||||
label: Text('Regular'),
|
||||
icon: Icon(MdiIcons.tab),
|
||||
),
|
||||
ButtonSegment(
|
||||
const ButtonSegment(
|
||||
value: TabType.private,
|
||||
label: Text('Private'),
|
||||
icon: Icon(MdiIcons.tabUnselected),
|
||||
),
|
||||
if (createChildTabsOption)
|
||||
const ButtonSegment(
|
||||
value: TabType.child,
|
||||
label: Text('Child'),
|
||||
icon: Icon(MdiIcons.fileTree),
|
||||
),
|
||||
],
|
||||
selected: {selectedTabType.value},
|
||||
onSelectionChanged: (value) {
|
||||
@@ -118,6 +145,14 @@ class SearchScreen extends HookConsumerWidget {
|
||||
TabType.private => SegmentedButton.styleFrom(
|
||||
selectedBackgroundColor: const Color(0x648000D7),
|
||||
),
|
||||
TabType.child =>
|
||||
(currentTabTabType == TabType.private)
|
||||
? SegmentedButton.styleFrom(
|
||||
selectedBackgroundColor: const Color(
|
||||
0x648000D7,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -151,7 +186,14 @@ class SearchScreen extends HookConsumerWidget {
|
||||
if (newUrl != null) {
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.addTab(url: newUrl, private: isPrivate);
|
||||
.addTab(
|
||||
url: newUrl,
|
||||
private: privateTabMode,
|
||||
parentId:
|
||||
(selectedTabType.value == TabType.child)
|
||||
? ref.read(selectedTabProvider)
|
||||
: null,
|
||||
);
|
||||
|
||||
if (context.mounted) {
|
||||
ref
|
||||
@@ -181,7 +223,7 @@ class SearchScreen extends HookConsumerWidget {
|
||||
TabSearch(searchTextListenable: sampledSearchText),
|
||||
FeedSearch(searchTextNotifier: sampledSearchText),
|
||||
HistorySuggestions(
|
||||
isPrivate: isPrivate,
|
||||
isPrivate: privateTabMode,
|
||||
searchTextListenable: sampledSearchText,
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user