show tabmenu for quick tabs
This commit is contained in:
+38
-15
@@ -331,22 +331,24 @@ class BrowserTabBar extends HookConsumerWidget {
|
|||||||
TabMenu(
|
TabMenu(
|
||||||
controller: trippleDotMenuController,
|
controller: trippleDotMenuController,
|
||||||
selectedTabId: selectedTabId,
|
selectedTabId: selectedTabId,
|
||||||
child: InkWell(
|
builder: (context, controller, child) {
|
||||||
onTap: () {
|
return InkWell(
|
||||||
if (trippleDotMenuController.isOpen) {
|
onTap: () {
|
||||||
trippleDotMenuController.close();
|
if (controller.isOpen) {
|
||||||
} else {
|
controller.close();
|
||||||
trippleDotMenuController.open();
|
} else {
|
||||||
}
|
controller.open();
|
||||||
},
|
}
|
||||||
child: const Padding(
|
},
|
||||||
padding: EdgeInsets.symmetric(
|
child: const Padding(
|
||||||
horizontal: 8.0,
|
padding: EdgeInsets.symmetric(
|
||||||
vertical: 15.0,
|
horizontal: 8.0,
|
||||||
|
vertical: 15.0,
|
||||||
|
),
|
||||||
|
child: Icon(MdiIcons.dotsVertical),
|
||||||
),
|
),
|
||||||
child: Icon(MdiIcons.dotsVertical),
|
);
|
||||||
),
|
},
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (showMainToolbarTabsCount)
|
if (showMainToolbarTabsCount)
|
||||||
TabsCountButton(
|
TabsCountButton(
|
||||||
@@ -500,6 +502,27 @@ class QuickTabSwitcher extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
await animation;
|
await animation;
|
||||||
},
|
},
|
||||||
|
itemWrap: (child, item) {
|
||||||
|
return TabMenu(
|
||||||
|
selectedTabId: item.id,
|
||||||
|
enableFindInPage: false,
|
||||||
|
enableFetchFeeds: false,
|
||||||
|
enableDesktopMode: false,
|
||||||
|
enableReaderMode: false,
|
||||||
|
builder: (context, controller, _) {
|
||||||
|
return InkWell(
|
||||||
|
onLongPress: () {
|
||||||
|
if (controller.isOpen) {
|
||||||
|
controller.close();
|
||||||
|
} else {
|
||||||
|
controller.open();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
availableItems: tabStates.value
|
availableItems: tabStates.value
|
||||||
.map(
|
.map(
|
||||||
(state) => (
|
(state) => (
|
||||||
|
|||||||
@@ -40,206 +40,220 @@ import 'package:weblibre/features/geckoview/features/tabs/data/models/container_
|
|||||||
import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart';
|
import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/container.dart';
|
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/container.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
|
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
|
||||||
|
import 'package:weblibre/presentation/hooks/menu_controller.dart';
|
||||||
import 'package:weblibre/presentation/widgets/website_feed_menu_button.dart';
|
import 'package:weblibre/presentation/widgets/website_feed_menu_button.dart';
|
||||||
import 'package:weblibre/utils/ui_helper.dart' as ui_helper;
|
import 'package:weblibre/utils/ui_helper.dart' as ui_helper;
|
||||||
|
|
||||||
class TabMenu extends HookConsumerWidget {
|
class TabMenu extends HookConsumerWidget {
|
||||||
final Widget child;
|
final MenuAnchorChildBuilder builder;
|
||||||
final MenuController controller;
|
final MenuController? controller;
|
||||||
final String selectedTabId;
|
final String selectedTabId;
|
||||||
|
final bool enableFindInPage;
|
||||||
|
final bool enableReaderMode;
|
||||||
|
final bool enableDesktopMode;
|
||||||
|
final bool enableFetchFeeds;
|
||||||
|
final bool enableAddBookmark;
|
||||||
|
final bool enableCloneTab;
|
||||||
|
final bool enableContainer;
|
||||||
|
final bool enableShare;
|
||||||
|
final bool enableExport;
|
||||||
|
final bool enableCloseTab;
|
||||||
|
|
||||||
const TabMenu({
|
const TabMenu({
|
||||||
super.key,
|
super.key,
|
||||||
required this.child,
|
required this.builder,
|
||||||
required this.controller,
|
|
||||||
required this.selectedTabId,
|
required this.selectedTabId,
|
||||||
|
this.controller,
|
||||||
|
this.enableFindInPage = true,
|
||||||
|
this.enableReaderMode = true,
|
||||||
|
this.enableDesktopMode = true,
|
||||||
|
this.enableFetchFeeds = true,
|
||||||
|
this.enableAddBookmark = true,
|
||||||
|
this.enableCloneTab = true,
|
||||||
|
this.enableContainer = true,
|
||||||
|
this.enableShare = true,
|
||||||
|
this.enableExport = true,
|
||||||
|
this.enableCloseTab = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final showFeeds = useState(false);
|
final showFeeds = useState(false);
|
||||||
|
|
||||||
|
final controller = this.controller ?? useMenuController();
|
||||||
|
|
||||||
return MenuAnchor(
|
return MenuAnchor(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
onClose: () {
|
onClose: () {
|
||||||
showFeeds.value = false;
|
showFeeds.value = false;
|
||||||
},
|
},
|
||||||
builder: (context, controller, child) {
|
builder: builder,
|
||||||
return child!;
|
|
||||||
},
|
|
||||||
menuChildren: [
|
menuChildren: [
|
||||||
MenuItemButton(
|
if (enableFindInPage)
|
||||||
onPressed: () {
|
MenuItemButton(
|
||||||
ref.read(bottomSheetControllerProvider.notifier).requestDismiss();
|
onPressed: () {
|
||||||
|
ref.read(bottomSheetControllerProvider.notifier).requestDismiss();
|
||||||
|
|
||||||
ref
|
ref
|
||||||
.read(findInPageControllerProvider(selectedTabId).notifier)
|
.read(findInPageControllerProvider(selectedTabId).notifier)
|
||||||
.show();
|
.show();
|
||||||
},
|
},
|
||||||
leadingIcon: const Icon(Icons.search),
|
leadingIcon: const Icon(Icons.search),
|
||||||
child: const Text('Find in page'),
|
child: const Text('Find in page'),
|
||||||
),
|
),
|
||||||
ReaderButton(
|
if (enableReaderMode)
|
||||||
buttonBuilder: (isLoading, readerActive, icon) => MenuItemButton(
|
ReaderButton(
|
||||||
onPressed: isLoading
|
buttonBuilder: (isLoading, readerActive, icon) => MenuItemButton(
|
||||||
? null
|
onPressed: isLoading
|
||||||
: () async {
|
? null
|
||||||
|
: () async {
|
||||||
|
await ref
|
||||||
|
.read(readerableScreenControllerProvider.notifier)
|
||||||
|
.toggleReaderView(!readerActive);
|
||||||
|
},
|
||||||
|
leadingIcon: icon,
|
||||||
|
trailingIcon: Checkbox(
|
||||||
|
value: readerActive,
|
||||||
|
onChanged: (value) async {
|
||||||
|
if (value != null && !isLoading) {
|
||||||
await ref
|
await ref
|
||||||
.read(readerableScreenControllerProvider.notifier)
|
.read(readerableScreenControllerProvider.notifier)
|
||||||
.toggleReaderView(!readerActive);
|
.toggleReaderView(!readerActive);
|
||||||
},
|
|
||||||
leadingIcon: icon,
|
|
||||||
trailingIcon: Checkbox(
|
|
||||||
value: readerActive,
|
|
||||||
onChanged: (value) async {
|
|
||||||
if (value != null && !isLoading) {
|
|
||||||
await ref
|
|
||||||
.read(readerableScreenControllerProvider.notifier)
|
|
||||||
.toggleReaderView(!readerActive);
|
|
||||||
controller.close();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
child: const Text('Reader Mode'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Consumer(
|
|
||||||
builder: (context, childRef, child) {
|
|
||||||
final enabled = childRef.watch(desktopModeProvider(selectedTabId));
|
|
||||||
|
|
||||||
return MenuItemButton(
|
|
||||||
onPressed: () {
|
|
||||||
ref.read(desktopModeProvider(selectedTabId).notifier).toggle();
|
|
||||||
},
|
|
||||||
leadingIcon: const Icon(MdiIcons.monitor),
|
|
||||||
trailingIcon: Checkbox(
|
|
||||||
value: enabled,
|
|
||||||
onChanged: (value) {
|
|
||||||
if (value != null) {
|
|
||||||
ref
|
|
||||||
.read(desktopModeProvider(selectedTabId).notifier)
|
|
||||||
.enabled(value);
|
|
||||||
controller.close();
|
controller.close();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
child: const Text('Desktop Mode'),
|
child: const Text('Reader Mode'),
|
||||||
);
|
),
|
||||||
},
|
),
|
||||||
),
|
if (enableDesktopMode)
|
||||||
const Divider(),
|
Consumer(
|
||||||
Visibility(
|
builder: (context, childRef, child) {
|
||||||
visible: showFeeds.value,
|
final enabled = childRef.watch(
|
||||||
replacement: MenuItemButton(
|
desktopModeProvider(selectedTabId),
|
||||||
closeOnActivate: false,
|
);
|
||||||
leadingIcon: const Icon(Icons.rss_feed),
|
|
||||||
child: const Text('Fetch Feeds'),
|
return MenuItemButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showFeeds.value = true;
|
ref
|
||||||
|
.read(desktopModeProvider(selectedTabId).notifier)
|
||||||
|
.toggle();
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(MdiIcons.monitor),
|
||||||
|
trailingIcon: Checkbox(
|
||||||
|
value: enabled,
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value != null) {
|
||||||
|
ref
|
||||||
|
.read(desktopModeProvider(selectedTabId).notifier)
|
||||||
|
.enabled(value);
|
||||||
|
controller.close();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
child: const Text('Desktop Mode'),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
child: WebsiteFeedMenuButton(selectedTabId),
|
if (enableFindInPage || enableReaderMode || enableDesktopMode)
|
||||||
),
|
const Divider(),
|
||||||
MenuItemButton(
|
if (enableFetchFeeds)
|
||||||
leadingIcon: const Icon(MdiIcons.bookmarkPlus),
|
Visibility(
|
||||||
child: const Text('Add Bookmark'),
|
visible: showFeeds.value,
|
||||||
onPressed: () async {
|
replacement: MenuItemButton(
|
||||||
final tabState = ref.read(tabStateProvider(selectedTabId))!;
|
closeOnActivate: false,
|
||||||
|
leadingIcon: const Icon(Icons.rss_feed),
|
||||||
|
child: const Text('Fetch Feeds'),
|
||||||
|
onPressed: () {
|
||||||
|
showFeeds.value = true;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
child: WebsiteFeedMenuButton(selectedTabId),
|
||||||
|
),
|
||||||
|
if (enableAddBookmark)
|
||||||
|
MenuItemButton(
|
||||||
|
leadingIcon: const Icon(MdiIcons.bookmarkPlus),
|
||||||
|
child: const Text('Add Bookmark'),
|
||||||
|
onPressed: () async {
|
||||||
|
final tabState = ref.read(tabStateProvider(selectedTabId))!;
|
||||||
|
|
||||||
await BookmarkEntryAddRoute(
|
await BookmarkEntryAddRoute(
|
||||||
bookmarkInfo: jsonEncode(
|
bookmarkInfo: jsonEncode(
|
||||||
BookmarkInfo(
|
BookmarkInfo(
|
||||||
title: tabState.titleOrAuthority,
|
title: tabState.titleOrAuthority,
|
||||||
url: tabState.url.toString(),
|
url: tabState.url.toString(),
|
||||||
).encode(),
|
).encode(),
|
||||||
),
|
),
|
||||||
).push(context);
|
).push(context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
SubmenuButton(
|
if (enableCloneTab)
|
||||||
menuChildren: [
|
SubmenuButton(
|
||||||
MenuItemButton(
|
menuChildren: [
|
||||||
leadingIcon: const Icon(MdiIcons.tabPlus),
|
MenuItemButton(
|
||||||
child: const Text('Regular'),
|
leadingIcon: const Icon(MdiIcons.tabPlus),
|
||||||
onPressed: () async {
|
child: const Text('Regular'),
|
||||||
final tabState = ref.read(tabStateProvider(selectedTabId))!;
|
onPressed: () async {
|
||||||
|
final tabState = ref.read(tabStateProvider(selectedTabId))!;
|
||||||
|
|
||||||
final tabId = await ref
|
final tabId = await ref
|
||||||
.read(tabRepositoryProvider.notifier)
|
.read(tabRepositoryProvider.notifier)
|
||||||
.addTab(
|
.addTab(
|
||||||
url: tabState.url,
|
url: tabState.url,
|
||||||
private: false,
|
private: false,
|
||||||
selectTab: false,
|
selectTab: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
//save reference before pop `ref` gets disposed
|
||||||
|
final repo = ref.read(tabRepositoryProvider.notifier);
|
||||||
|
|
||||||
|
ui_helper.showTabSwitchMessage(
|
||||||
|
context,
|
||||||
|
onSwitch: () async {
|
||||||
|
await repo.selectTab(tabId);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (context.mounted) {
|
|
||||||
//save reference before pop `ref` gets disposed
|
|
||||||
final repo = ref.read(tabRepositoryProvider.notifier);
|
|
||||||
|
|
||||||
ui_helper.showTabSwitchMessage(
|
|
||||||
context,
|
|
||||||
onSwitch: () async {
|
|
||||||
await repo.selectTab(tabId);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
MenuItemButton(
|
|
||||||
leadingIcon: const Icon(MdiIcons.tabUnselected),
|
|
||||||
child: const Text('Private'),
|
|
||||||
onPressed: () async {
|
|
||||||
final tabState = ref.read(tabStateProvider(selectedTabId))!;
|
|
||||||
|
|
||||||
final tabId = await ref
|
|
||||||
.read(tabRepositoryProvider.notifier)
|
|
||||||
.addTab(url: tabState.url, private: true, selectTab: false);
|
|
||||||
|
|
||||||
if (context.mounted) {
|
|
||||||
//save reference before pop `ref` gets disposed
|
|
||||||
final repo = ref.read(tabRepositoryProvider.notifier);
|
|
||||||
|
|
||||||
ui_helper.showTabSwitchMessage(
|
|
||||||
context,
|
|
||||||
onSwitch: () async {
|
|
||||||
await repo.selectTab(tabId);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
leadingIcon: const Icon(MdiIcons.tabPlus),
|
|
||||||
child: const Text('Clone Tab'),
|
|
||||||
),
|
|
||||||
SubmenuButton(
|
|
||||||
menuChildren: [
|
|
||||||
MenuItemButton(
|
|
||||||
leadingIcon: const Icon(MdiIcons.folderArrowUpDownOutline),
|
|
||||||
child: const Text('Assign Container'),
|
|
||||||
onPressed: () async {
|
|
||||||
final targetContainerId = await const ContainerSelectionRoute()
|
|
||||||
.push<String?>(context);
|
|
||||||
|
|
||||||
if (targetContainerId != null) {
|
|
||||||
final containerData = await ref
|
|
||||||
.read(containerRepositoryProvider.notifier)
|
|
||||||
.getContainerData(targetContainerId);
|
|
||||||
|
|
||||||
if (containerData != null) {
|
|
||||||
final tabState = ref.read(tabStateProvider(selectedTabId))!;
|
|
||||||
|
|
||||||
await ref
|
|
||||||
.read(tabDataRepositoryProvider.notifier)
|
|
||||||
.assignContainer(tabState.id, containerData);
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
),
|
||||||
),
|
MenuItemButton(
|
||||||
Consumer(
|
leadingIcon: const Icon(MdiIcons.tabUnselected),
|
||||||
child: MenuItemButton(
|
child: const Text('Private'),
|
||||||
leadingIcon: const Icon(MdiIcons.webPlus),
|
onPressed: () async {
|
||||||
child: const Text('URL relation'),
|
final tabState = ref.read(tabStateProvider(selectedTabId))!;
|
||||||
|
|
||||||
|
final tabId = await ref
|
||||||
|
.read(tabRepositoryProvider.notifier)
|
||||||
|
.addTab(
|
||||||
|
url: tabState.url,
|
||||||
|
private: true,
|
||||||
|
selectTab: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
//save reference before pop `ref` gets disposed
|
||||||
|
final repo = ref.read(tabRepositoryProvider.notifier);
|
||||||
|
|
||||||
|
ui_helper.showTabSwitchMessage(
|
||||||
|
context,
|
||||||
|
onSwitch: () async {
|
||||||
|
await repo.selectTab(tabId);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
leadingIcon: const Icon(MdiIcons.tabPlus),
|
||||||
|
child: const Text('Clone Tab'),
|
||||||
|
),
|
||||||
|
if (enableContainer)
|
||||||
|
SubmenuButton(
|
||||||
|
menuChildren: [
|
||||||
|
MenuItemButton(
|
||||||
|
leadingIcon: const Icon(MdiIcons.folderArrowUpDownOutline),
|
||||||
|
child: const Text('Assign Container'),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final targetContainerId =
|
final targetContainerId =
|
||||||
await const ContainerSelectionRoute().push<String?>(
|
await const ContainerSelectionRoute().push<String?>(
|
||||||
@@ -254,129 +268,165 @@ class TabMenu extends HookConsumerWidget {
|
|||||||
if (containerData != null) {
|
if (containerData != null) {
|
||||||
final tabState = ref.read(
|
final tabState = ref.read(
|
||||||
tabStateProvider(selectedTabId),
|
tabStateProvider(selectedTabId),
|
||||||
);
|
)!;
|
||||||
final origin = tabState?.url.origin.mapNotNull(Uri.parse);
|
|
||||||
|
|
||||||
if (origin != null) {
|
await ref
|
||||||
await ref
|
.read(tabDataRepositoryProvider.notifier)
|
||||||
.read(containerRepositoryProvider.notifier)
|
.assignContainer(tabState.id, containerData);
|
||||||
.replaceContainer(
|
|
||||||
containerData.copyWith.metadata(
|
|
||||||
containerData.metadata.copyWith.assignedSites([
|
|
||||||
...?containerData.metadata.assignedSites,
|
|
||||||
origin,
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
builder: (context, ref, child) {
|
Consumer(
|
||||||
final isSiteAssigned = ref.watch(
|
child: MenuItemButton(
|
||||||
watchIsCurrentSiteAssignedToContainerProvider,
|
leadingIcon: const Icon(MdiIcons.webPlus),
|
||||||
);
|
child: const Text('URL relation'),
|
||||||
|
onPressed: () async {
|
||||||
|
final targetContainerId =
|
||||||
|
await const ContainerSelectionRoute().push<String?>(
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
|
||||||
return Visibility(
|
if (targetContainerId != null) {
|
||||||
visible:
|
final containerData = await ref
|
||||||
isSiteAssigned.hasValue && !isSiteAssigned.requireValue,
|
.read(containerRepositoryProvider.notifier)
|
||||||
child: child!,
|
.getContainerData(targetContainerId);
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Consumer(
|
|
||||||
child: MenuItemButton(
|
|
||||||
leadingIcon: const Icon(MdiIcons.folderCancelOutline),
|
|
||||||
child: const Text('Unassign Container'),
|
|
||||||
onPressed: () async {
|
|
||||||
final tabState = ref.read(tabStateProvider(selectedTabId))!;
|
|
||||||
|
|
||||||
await ref
|
if (containerData != null) {
|
||||||
.read(tabDataRepositoryProvider.notifier)
|
final tabState = ref.read(
|
||||||
.unassignContainer(tabState.id);
|
tabStateProvider(selectedTabId),
|
||||||
|
);
|
||||||
|
final origin = tabState?.url.origin.mapNotNull(
|
||||||
|
Uri.parse,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (origin != null) {
|
||||||
|
await ref
|
||||||
|
.read(containerRepositoryProvider.notifier)
|
||||||
|
.replaceContainer(
|
||||||
|
containerData.copyWith.metadata(
|
||||||
|
containerData.metadata.copyWith.assignedSites(
|
||||||
|
[
|
||||||
|
...?containerData.metadata.assignedSites,
|
||||||
|
origin,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
builder: (context, ref, child) {
|
||||||
|
final isSiteAssigned = ref.watch(
|
||||||
|
watchIsCurrentSiteAssignedToContainerProvider,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Visibility(
|
||||||
|
visible:
|
||||||
|
isSiteAssigned.hasValue && !isSiteAssigned.requireValue,
|
||||||
|
child: child!,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
builder: (context, ref, child) {
|
Consumer(
|
||||||
final containerId = ref.watch(
|
child: MenuItemButton(
|
||||||
watchContainerTabIdProvider(
|
leadingIcon: const Icon(MdiIcons.folderCancelOutline),
|
||||||
selectedTabId,
|
child: const Text('Unassign Container'),
|
||||||
).select((value) => value.value),
|
onPressed: () async {
|
||||||
);
|
final tabState = ref.read(tabStateProvider(selectedTabId))!;
|
||||||
|
|
||||||
return Visibility(visible: containerId != null, child: child!);
|
await ref
|
||||||
},
|
.read(tabDataRepositoryProvider.notifier)
|
||||||
),
|
.unassignContainer(tabState.id);
|
||||||
],
|
},
|
||||||
leadingIcon: const Icon(MdiIcons.folder),
|
),
|
||||||
child: const Text('Container'),
|
builder: (context, ref, child) {
|
||||||
),
|
final containerId = ref.watch(
|
||||||
SubmenuButton(
|
watchContainerTabIdProvider(
|
||||||
menuChildren: [
|
selectedTabId,
|
||||||
CopyAddressMenuItemButton(selectedTabId: selectedTabId),
|
).select((value) => value.value),
|
||||||
LaunchExternalMenuItemButton(selectedTabId: selectedTabId),
|
|
||||||
ShareScreenshotMenuItemButton(selectedTabId: selectedTabId),
|
|
||||||
ShareMenuItemButton(selectedTabId: selectedTabId),
|
|
||||||
ShowQrCodeMenuItemButton(selectedTabId: selectedTabId),
|
|
||||||
],
|
|
||||||
leadingIcon: const Icon(Icons.share),
|
|
||||||
child: const Text('Share'),
|
|
||||||
),
|
|
||||||
SubmenuButton(
|
|
||||||
menuChildren: [
|
|
||||||
ShareMarkdownActionMenuItemButton(
|
|
||||||
selectedTabId: selectedTabId,
|
|
||||||
title: const Text('Copy as Markdown'),
|
|
||||||
// ignore: deprecated_member_use
|
|
||||||
icon: const Icon(MdiIcons.languageMarkdownOutline),
|
|
||||||
shareMarkdownAction: (content, fileName) async {
|
|
||||||
await Clipboard.setData(ClipboardData(text: content));
|
|
||||||
|
|
||||||
if (context.mounted) {
|
|
||||||
ui_helper.showInfoMessage(
|
|
||||||
context,
|
|
||||||
'Markdown copied to clipboard',
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ShareMarkdownActionMenuItemButton(
|
|
||||||
selectedTabId: selectedTabId,
|
|
||||||
title: const Text('Export as Markdown'),
|
|
||||||
// ignore: deprecated_member_use
|
|
||||||
icon: const Icon(MdiIcons.languageMarkdown),
|
|
||||||
shareMarkdownAction: (content, fileName) async {
|
|
||||||
await FilePicker.platform.saveFile(
|
|
||||||
fileName: fileName,
|
|
||||||
type: FileType.custom,
|
|
||||||
allowedExtensions: ['md'],
|
|
||||||
bytes: utf8.encode(content),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
SaveToPdfMenuItemButton(selectedTabId: selectedTabId),
|
|
||||||
],
|
|
||||||
leadingIcon: const Icon(MdiIcons.fileExport),
|
|
||||||
child: const Text('Export'),
|
|
||||||
),
|
|
||||||
MenuItemButton(
|
|
||||||
onPressed: () async {
|
|
||||||
await ref
|
|
||||||
.read(tabRepositoryProvider.notifier)
|
|
||||||
.closeTab(selectedTabId);
|
|
||||||
|
|
||||||
if (context.mounted) {
|
return Visibility(
|
||||||
ui_helper.showTabUndoClose(
|
visible: containerId != null,
|
||||||
context,
|
child: child!,
|
||||||
ref.read(tabRepositoryProvider.notifier).undoClose,
|
);
|
||||||
);
|
},
|
||||||
}
|
),
|
||||||
},
|
],
|
||||||
leadingIcon: const Icon(Icons.close),
|
leadingIcon: const Icon(MdiIcons.folder),
|
||||||
child: const Text('Close Tab'),
|
child: const Text('Container'),
|
||||||
),
|
),
|
||||||
|
if (enableShare)
|
||||||
|
SubmenuButton(
|
||||||
|
menuChildren: [
|
||||||
|
CopyAddressMenuItemButton(selectedTabId: selectedTabId),
|
||||||
|
LaunchExternalMenuItemButton(selectedTabId: selectedTabId),
|
||||||
|
ShareScreenshotMenuItemButton(selectedTabId: selectedTabId),
|
||||||
|
ShareMenuItemButton(selectedTabId: selectedTabId),
|
||||||
|
ShowQrCodeMenuItemButton(selectedTabId: selectedTabId),
|
||||||
|
],
|
||||||
|
leadingIcon: const Icon(Icons.share),
|
||||||
|
child: const Text('Share'),
|
||||||
|
),
|
||||||
|
if (enableExport)
|
||||||
|
SubmenuButton(
|
||||||
|
menuChildren: [
|
||||||
|
ShareMarkdownActionMenuItemButton(
|
||||||
|
selectedTabId: selectedTabId,
|
||||||
|
title: const Text('Copy as Markdown'),
|
||||||
|
// ignore: deprecated_member_use
|
||||||
|
icon: const Icon(MdiIcons.languageMarkdownOutline),
|
||||||
|
shareMarkdownAction: (content, fileName) async {
|
||||||
|
await Clipboard.setData(ClipboardData(text: content));
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
ui_helper.showInfoMessage(
|
||||||
|
context,
|
||||||
|
'Markdown copied to clipboard',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ShareMarkdownActionMenuItemButton(
|
||||||
|
selectedTabId: selectedTabId,
|
||||||
|
title: const Text('Export as Markdown'),
|
||||||
|
// ignore: deprecated_member_use
|
||||||
|
icon: const Icon(MdiIcons.languageMarkdown),
|
||||||
|
shareMarkdownAction: (content, fileName) async {
|
||||||
|
await FilePicker.platform.saveFile(
|
||||||
|
fileName: fileName,
|
||||||
|
type: FileType.custom,
|
||||||
|
allowedExtensions: ['md'],
|
||||||
|
bytes: utf8.encode(content),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SaveToPdfMenuItemButton(selectedTabId: selectedTabId),
|
||||||
|
],
|
||||||
|
leadingIcon: const Icon(MdiIcons.fileExport),
|
||||||
|
child: const Text('Export'),
|
||||||
|
),
|
||||||
|
if (enableCloseTab)
|
||||||
|
MenuItemButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await ref
|
||||||
|
.read(tabRepositoryProvider.notifier)
|
||||||
|
.closeTab(selectedTabId);
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
ui_helper.showTabUndoClose(
|
||||||
|
context,
|
||||||
|
ref.read(tabRepositoryProvider.notifier).undoClose,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
leadingIcon: const Icon(Icons.close),
|
||||||
|
child: const Text('Close Tab'),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: child,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user