add long press actions on contextual buttons; move extension shortcut into contextual; disable reader view button in tab bar;
This commit is contained in:
@@ -44,8 +44,8 @@ class TabSession extends _$TabSession {
|
||||
return _sessionService.stopLoading();
|
||||
}
|
||||
|
||||
Future<void> reload() {
|
||||
return _sessionService.reload();
|
||||
Future<void> reload({LoadUrlFlags flags = LoadUrlFlags.NONE}) {
|
||||
return _sessionService.reload(flags: flags);
|
||||
}
|
||||
|
||||
Future<void> goBack() {
|
||||
|
||||
@@ -57,7 +57,7 @@ final class TabSessionProvider extends $NotifierProvider<TabSession, void> {
|
||||
}
|
||||
}
|
||||
|
||||
String _$tabSessionHash() => r'b9381c334672fd3f733a4cc86ce696fb7de6fa5d';
|
||||
String _$tabSessionHash() => r'be44598ad023c2fb23e48d3fa4bf805c4640c599';
|
||||
|
||||
final class TabSessionFamily extends $Family
|
||||
with $ClassFamilyOverride<TabSession, void, void, void, String?> {
|
||||
|
||||
+1
@@ -40,4 +40,5 @@ enum ToolbarButtonId {
|
||||
pageUp,
|
||||
pageDown,
|
||||
font,
|
||||
extensionShortcut,
|
||||
}
|
||||
|
||||
+7
@@ -147,6 +147,12 @@ const fontToolbarButtonSpec = ToolbarButtonSpec(
|
||||
defaultVisible: false,
|
||||
);
|
||||
|
||||
const extensionShortcutToolbarButtonSpec = ToolbarButtonSpec(
|
||||
id: ToolbarButtonId.extensionShortcut,
|
||||
defaultVisible: false,
|
||||
canBeFallbackTarget: false,
|
||||
);
|
||||
|
||||
const toolbarButtonSpecs = [
|
||||
backToolbarButtonSpec,
|
||||
forwardToolbarButtonSpec,
|
||||
@@ -169,6 +175,7 @@ const toolbarButtonSpecs = [
|
||||
pageUpToolbarButtonSpec,
|
||||
pageDownToolbarButtonSpec,
|
||||
fontToolbarButtonSpec,
|
||||
extensionShortcutToolbarButtonSpec,
|
||||
];
|
||||
|
||||
final Map<String, ToolbarButtonSpec> toolbarButtonSpecsById = {
|
||||
|
||||
+244
-35
@@ -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:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
@@ -27,11 +28,15 @@ import 'package:weblibre/features/geckoview/domain/providers.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/providers/desktop_mode.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/providers/tab_session.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/providers/tab_state.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/providers/web_extensions_state.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/repositories/tab.dart';
|
||||
import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/bookmark_item.dart';
|
||||
import 'package:weblibre/features/geckoview/features/bookmarks/domain/repositories/bookmarks.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/domain/entities/font_size_constants.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_spec.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/models/contextual_toolbar_scope.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/widgets/contextual_bar_buttons.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/extension_shortcut_menu.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/font_size_bottom_sheet.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/navigation_buttons.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/tabs_action_button.dart';
|
||||
@@ -112,18 +117,7 @@ final List<ToolbarButtonDefinition> toolbarButtonRegistry = [
|
||||
spec: bookmarksToolbarButtonSpec,
|
||||
label: 'Bookmarks',
|
||||
icon: MdiIcons.bookmarkMultiple,
|
||||
builder: (scope, context, ref) {
|
||||
return IconButton(
|
||||
onPressed: scope.isPreview
|
||||
? () {}
|
||||
: () async {
|
||||
await BookmarkListRoute(
|
||||
entryGuid: BookmarkRoot.root.id,
|
||||
).push(context);
|
||||
},
|
||||
icon: const Icon(MdiIcons.bookmarkMultiple),
|
||||
);
|
||||
},
|
||||
builder: (scope, context, ref) => _BookmarkToolbarButton(scope: scope),
|
||||
),
|
||||
ToolbarButtonDefinition(
|
||||
spec: shareToolbarButtonSpec,
|
||||
@@ -177,21 +171,7 @@ final List<ToolbarButtonDefinition> toolbarButtonRegistry = [
|
||||
spec: reloadToolbarButtonSpec,
|
||||
label: 'Reload',
|
||||
icon: Icons.refresh,
|
||||
builder: (scope, context, ref) {
|
||||
return IconButton(
|
||||
onPressed: scope.isPreview
|
||||
? () {}
|
||||
: () async {
|
||||
final tabId = scope.selectedTabId;
|
||||
if (tabId != null) {
|
||||
await ref
|
||||
.read(tabSessionProvider(tabId: tabId).notifier)
|
||||
.reload();
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.refresh),
|
||||
);
|
||||
},
|
||||
builder: (scope, context, ref) => _ReloadToolbarButton(scope: scope),
|
||||
),
|
||||
ToolbarButtonDefinition(
|
||||
spec: readerModeToolbarButtonSpec,
|
||||
@@ -276,14 +256,7 @@ final List<ToolbarButtonDefinition> toolbarButtonRegistry = [
|
||||
spec: closeTabToolbarButtonSpec,
|
||||
label: 'Close Tab',
|
||||
icon: MdiIcons.tabMinus,
|
||||
builder: (scope, context, ref) {
|
||||
return IconButton(
|
||||
onPressed: scope.isPreview
|
||||
? () {}
|
||||
: () => _closeTab(context, ref, scope.selectedTabId),
|
||||
icon: const Icon(MdiIcons.tabMinus),
|
||||
);
|
||||
},
|
||||
builder: (scope, context, ref) => _CloseTabToolbarButton(scope: scope),
|
||||
),
|
||||
ToolbarButtonDefinition(
|
||||
spec: inputUrlToolbarButtonSpec,
|
||||
@@ -417,6 +390,24 @@ final List<ToolbarButtonDefinition> toolbarButtonRegistry = [
|
||||
return _FontToolbarButton(selectedTabId: scope.selectedTabId);
|
||||
},
|
||||
),
|
||||
ToolbarButtonDefinition(
|
||||
spec: extensionShortcutToolbarButtonSpec,
|
||||
label: 'Extensions',
|
||||
icon: MdiIcons.puzzle,
|
||||
isPrimaryAvailable: (scope, ref) => ref
|
||||
.read(
|
||||
webExtensionsStateProvider(
|
||||
WebExtensionActionType.browser,
|
||||
).select((value) => value.values),
|
||||
)
|
||||
.isNotEmpty,
|
||||
builder: (scope, context, ref) {
|
||||
if (scope.isPreview) {
|
||||
return IconButton(onPressed: () {}, icon: const Icon(MdiIcons.puzzle));
|
||||
}
|
||||
return const _ExtensionShortcutToolbarButton();
|
||||
},
|
||||
),
|
||||
];
|
||||
|
||||
final Map<String, ToolbarButtonDefinition> toolbarButtonRegistryById = {
|
||||
@@ -452,6 +443,224 @@ Future<void> _closeTab(
|
||||
}
|
||||
}
|
||||
|
||||
class _ExtensionShortcutToolbarButton extends HookConsumerWidget {
|
||||
const _ExtensionShortcutToolbarButton();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final menuController = useMemoized(MenuController.new);
|
||||
|
||||
return ExtensionShortcutMenu(
|
||||
controller: menuController,
|
||||
child: IconButton(
|
||||
onPressed: menuController.open,
|
||||
icon: const Icon(MdiIcons.puzzle),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ReloadToolbarButton extends HookConsumerWidget {
|
||||
final ContextualToolbarScope scope;
|
||||
|
||||
const _ReloadToolbarButton({required this.scope});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final menuController = useMemoized(MenuController.new);
|
||||
|
||||
return MenuAnchor(
|
||||
controller: menuController,
|
||||
builder: (context, controller, child) => child!,
|
||||
menuChildren: [
|
||||
MenuItemButton(
|
||||
leadingIcon: const Icon(Icons.refresh),
|
||||
onPressed: () async {
|
||||
final tabId = scope.selectedTabId;
|
||||
if (tabId != null) {
|
||||
await ref
|
||||
.read(tabSessionProvider(tabId: tabId).notifier)
|
||||
.reload(flags: LoadUrlFlags.BYPASS_CACHE);
|
||||
}
|
||||
},
|
||||
child: const Text('Hard Refresh'),
|
||||
),
|
||||
],
|
||||
child: IconButton(
|
||||
onPressed: scope.isPreview
|
||||
? () {}
|
||||
: () async {
|
||||
final tabId = scope.selectedTabId;
|
||||
if (tabId != null) {
|
||||
await ref
|
||||
.read(tabSessionProvider(tabId: tabId).notifier)
|
||||
.reload();
|
||||
}
|
||||
},
|
||||
onLongPress: scope.isPreview ? null : menuController.open,
|
||||
icon: const Icon(Icons.refresh),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CloseTabToolbarButton extends HookConsumerWidget {
|
||||
final ContextualToolbarScope scope;
|
||||
|
||||
const _CloseTabToolbarButton({required this.scope});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final menuController = useMemoized(MenuController.new);
|
||||
final host = ref.watch(
|
||||
tabStateProvider(scope.selectedTabId).select((s) => s?.url.host),
|
||||
);
|
||||
|
||||
return MenuAnchor(
|
||||
controller: menuController,
|
||||
builder: (context, controller, child) => child!,
|
||||
menuChildren: [
|
||||
MenuItemButton(
|
||||
leadingIcon: const Icon(Icons.tab),
|
||||
onPressed: () async {
|
||||
final tabStates = ref.read(tabStatesProvider);
|
||||
final otherIds = tabStates.keys
|
||||
.where((id) => id != scope.selectedTabId)
|
||||
.toList();
|
||||
if (otherIds.isNotEmpty) {
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.closeTabs(otherIds);
|
||||
}
|
||||
},
|
||||
child: const Text('Close Others'),
|
||||
),
|
||||
if (host != null && host.isNotEmpty)
|
||||
MenuItemButton(
|
||||
leadingIcon: const Icon(Icons.language),
|
||||
onPressed: () async {
|
||||
final tabStates = ref.read(tabStatesProvider);
|
||||
final sameHostIds = tabStates.entries
|
||||
.where((e) => e.value.url.host == host)
|
||||
.map((e) => e.key)
|
||||
.toList();
|
||||
if (sameHostIds.isNotEmpty) {
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.closeTabs(sameHostIds);
|
||||
}
|
||||
},
|
||||
child: const Text('Close from Same Host'),
|
||||
),
|
||||
],
|
||||
child: IconButton(
|
||||
onPressed: scope.isPreview
|
||||
? () {}
|
||||
: () => _closeTab(context, ref, scope.selectedTabId),
|
||||
onLongPress: scope.isPreview ? null : menuController.open,
|
||||
icon: const Icon(MdiIcons.tabMinus),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _BookmarkToolbarButton extends HookConsumerWidget {
|
||||
final ContextualToolbarScope scope;
|
||||
|
||||
const _BookmarkToolbarButton({required this.scope});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final menuController = useMemoized(MenuController.new);
|
||||
|
||||
final tabUrl = scope.tabState?.url;
|
||||
final bookmarkable = tabUrl != null && !scope.isPreview;
|
||||
|
||||
// Walk the in-memory bookmark tree to find GUIDs for the current URL.
|
||||
final existingGuids = ref.watch(
|
||||
bookmarksRepositoryProvider.select((async) {
|
||||
final result = <String>[];
|
||||
|
||||
if (!bookmarkable) return const <String>[];
|
||||
|
||||
final root = async.value;
|
||||
if (root == null) return const <String>[];
|
||||
|
||||
void collect(BookmarkItem item) {
|
||||
if (item is BookmarkEntry && item.url == tabUrl) {
|
||||
result.add(item.guid);
|
||||
}
|
||||
|
||||
if (item is BookmarkFolder) {
|
||||
for (final child in item.children ?? const <BookmarkItem>[]) {
|
||||
collect(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collect(root);
|
||||
|
||||
return result;
|
||||
}),
|
||||
);
|
||||
|
||||
final isBookmarked = existingGuids.isNotEmpty;
|
||||
|
||||
return MenuAnchor(
|
||||
controller: menuController,
|
||||
builder: (context, controller, child) => child!,
|
||||
menuChildren: [
|
||||
if (isBookmarked)
|
||||
MenuItemButton(
|
||||
leadingIcon: const Icon(MdiIcons.bookmarkRemove),
|
||||
onPressed: () async {
|
||||
for (final guid in existingGuids) {
|
||||
await ref
|
||||
.read(bookmarksRepositoryProvider.notifier)
|
||||
.delete(guid);
|
||||
}
|
||||
if (context.mounted) {
|
||||
ui_helper.showInfoMessage(context, 'Bookmark removed');
|
||||
}
|
||||
},
|
||||
child: const Text('Remove Bookmark'),
|
||||
)
|
||||
else
|
||||
MenuItemButton(
|
||||
leadingIcon: const Icon(MdiIcons.bookmarkPlus),
|
||||
onPressed: !bookmarkable
|
||||
? null
|
||||
: () async {
|
||||
await ref
|
||||
.read(bookmarksRepositoryProvider.notifier)
|
||||
.addBookmark(
|
||||
parentGuid: BookmarkRoot.mobile.id,
|
||||
url: tabUrl,
|
||||
title: scope.tabState!.titleOrAuthority,
|
||||
);
|
||||
|
||||
if (context.mounted) {
|
||||
ui_helper.showInfoMessage(context, 'Bookmark added');
|
||||
}
|
||||
},
|
||||
child: const Text('Add Bookmark'),
|
||||
),
|
||||
],
|
||||
child: IconButton(
|
||||
onPressed: scope.isPreview
|
||||
? () {}
|
||||
: () async {
|
||||
await BookmarkListRoute(
|
||||
entryGuid: BookmarkRoot.root.id,
|
||||
).push(context);
|
||||
},
|
||||
onLongPress: scope.isPreview ? null : menuController.open,
|
||||
icon: const Icon(MdiIcons.bookmarkMultiple),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _adjustFontSize(
|
||||
BuildContext context,
|
||||
WidgetRef ref, {
|
||||
|
||||
+24
-71
@@ -28,28 +28,23 @@ import 'package:flutter_material_design_icons/flutter_material_design_icons.dart
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:weblibre/core/design/app_colors.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/controllers/bottom_sheet.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/entities/states/readerable.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/entities/sheet.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/domain/providers.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/providers/toolbar_button_configs.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_id.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/widgets/contextual_bar_buttons.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/widgets/contextual_toolbar.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/controllers/toolbar_visibility.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/extension_shortcut_menu.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/tab_icon.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/tab_menu.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/toolbar_button.dart';
|
||||
import 'package:weblibre/features/geckoview/features/readerview/presentation/controllers/readerable.dart';
|
||||
import 'package:weblibre/features/geckoview/features/readerview/presentation/widgets/reader_button.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/data/entities/tab_mode.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/utils/container_colors.dart';
|
||||
import 'package:weblibre/features/user/data/models/general_settings.dart';
|
||||
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
|
||||
import 'package:weblibre/presentation/hooks/menu_controller.dart';
|
||||
import 'package:weblibre/presentation/widgets/selectable_chips.dart';
|
||||
import 'package:weblibre/presentation/widgets/url_icon.dart';
|
||||
|
||||
@@ -72,8 +67,6 @@ class BrowserTopAppBar extends StatelessWidget {
|
||||
displayedSheet: null,
|
||||
showContextualToolbar: false,
|
||||
showQuickTabSwitcherBar: false,
|
||||
showMainToolbarNavigationButton: !showContextualToolbar,
|
||||
showMainToolbarTabsCount: !showContextualToolbar,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -108,8 +101,6 @@ class BrowserBottomAppBar extends StatelessWidget {
|
||||
showMainToolbar: showMainToolbar,
|
||||
showContextualToolbar: showContextualToolbar,
|
||||
showQuickTabSwitcherBar: showQuickTabSwitcherBar,
|
||||
showMainToolbarNavigationButton: !showContextualToolbar,
|
||||
showMainToolbarTabsCount: !showContextualToolbar,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -137,17 +128,12 @@ class BrowserTabBar extends HookConsumerWidget {
|
||||
final bool showQuickTabSwitcherBar;
|
||||
final Sheet? displayedSheet;
|
||||
|
||||
final bool showMainToolbarTabsCount;
|
||||
final bool showMainToolbarNavigationButton;
|
||||
|
||||
const BrowserTabBar({
|
||||
super.key,
|
||||
required this.showMainToolbar,
|
||||
required this.displayedSheet,
|
||||
required this.showContextualToolbar,
|
||||
required this.showQuickTabSwitcherBar,
|
||||
required this.showMainToolbarTabsCount,
|
||||
required this.showMainToolbarNavigationButton,
|
||||
});
|
||||
|
||||
static const contextualToolabarHeight = 54.0;
|
||||
@@ -180,18 +166,37 @@ class BrowserTabBar extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final extensionMenuController = useMenuController();
|
||||
|
||||
final selectedTabId = ref.watch(selectedTabProvider);
|
||||
final settings = ref.watch(generalSettingsWithDefaultsProvider);
|
||||
|
||||
// Determine which buttons are actually visible in the contextual toolbar
|
||||
// so we only hide them from the main toolbar when they're genuinely present there.
|
||||
final contextualConfigs = ref
|
||||
.watch(effectiveToolbarButtonConfigsProvider)
|
||||
.value;
|
||||
|
||||
final tabsCountInContextual =
|
||||
showContextualToolbar &&
|
||||
contextualConfigs.any(
|
||||
(c) => c.buttonId == ToolbarButtonId.tabsCount.name && c.isVisible,
|
||||
);
|
||||
|
||||
final menuInContextual =
|
||||
showContextualToolbar &&
|
||||
contextualConfigs.any(
|
||||
(c) =>
|
||||
c.buttonId == ToolbarButtonId.navigationMenu.name && c.isVisible,
|
||||
);
|
||||
|
||||
final showMainToolbarTabsCount = !tabsCountInContextual;
|
||||
final showMainToolbarNavigationButton = !menuInContextual;
|
||||
|
||||
final containerColor = ref.watch(
|
||||
watchTabContainerDataProvider(
|
||||
selectedTabId,
|
||||
).select((data) => data.value?.color),
|
||||
);
|
||||
|
||||
final showExtensionShortcut = settings.showExtensionShortcut;
|
||||
final quickTabSwitcherMode = settings.effectiveUiQuickTabSwitcherMode();
|
||||
|
||||
final tabBarPosition = settings.tabBarPosition;
|
||||
@@ -221,58 +226,6 @@ class BrowserTabBar extends HookConsumerWidget {
|
||||
: const AppBarTitle()
|
||||
: null,
|
||||
actions: [
|
||||
if (showTabTitle)
|
||||
Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final tabBarReaderView = ref.watch(
|
||||
generalSettingsWithDefaultsProvider.select(
|
||||
(value) => value.tabBarReaderView,
|
||||
),
|
||||
);
|
||||
|
||||
final readerabilityStateActive = ref.watch(
|
||||
selectedTabStateProvider.select(
|
||||
(state) =>
|
||||
(state?.readerableState ?? ReaderableState.$default())
|
||||
.active,
|
||||
),
|
||||
);
|
||||
|
||||
return Visibility(
|
||||
visible: tabBarReaderView || readerabilityStateActive,
|
||||
child: ReaderButton(
|
||||
buttonBuilder: (isLoading, readerActive, icon) =>
|
||||
ToolbarButton(
|
||||
onTap: isLoading
|
||||
? null
|
||||
: () async {
|
||||
await ref
|
||||
.read(
|
||||
readerableScreenControllerProvider
|
||||
.notifier,
|
||||
)
|
||||
.toggleReaderView(!readerActive);
|
||||
},
|
||||
child: icon,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
if (showExtensionShortcut)
|
||||
ExtensionShortcutMenu(
|
||||
controller: extensionMenuController,
|
||||
child: ToolbarButton(
|
||||
onTap: () {
|
||||
if (extensionMenuController.isOpen) {
|
||||
extensionMenuController.close();
|
||||
} else {
|
||||
extensionMenuController.open();
|
||||
}
|
||||
},
|
||||
child: const Icon(MdiIcons.puzzle),
|
||||
),
|
||||
),
|
||||
if (showMainToolbarTabsCount)
|
||||
TabsCountButton(
|
||||
selectedTabId: selectedTabId,
|
||||
|
||||
+4
-4
@@ -234,8 +234,8 @@ class GridTabPreview extends HookConsumerWidget {
|
||||
onPressed: () {
|
||||
onDeleteAll?.call(tabState.url.host);
|
||||
},
|
||||
leadingIcon: const Icon(MdiIcons.closeBoxMultiple),
|
||||
child: Text('Close all from ${tabState.url.host}'),
|
||||
leadingIcon: const Icon(Icons.language),
|
||||
child: const Text('Close from Same Host'),
|
||||
),
|
||||
],
|
||||
child: SizedBox(
|
||||
@@ -567,8 +567,8 @@ class ListTabPreview extends HookConsumerWidget {
|
||||
onPressed: () {
|
||||
onDeleteAll?.call(tabState.url.host);
|
||||
},
|
||||
leadingIcon: const Icon(MdiIcons.closeBoxMultiple),
|
||||
child: Text('Close all from ${tabState.url.host}'),
|
||||
leadingIcon: const Icon(Icons.language),
|
||||
child: const Text('Close from Same Host'),
|
||||
),
|
||||
],
|
||||
child: IconButton(
|
||||
|
||||
Reference in New Issue
Block a user