close tabs by host
This commit is contained in:
@@ -7,7 +7,7 @@ part of 'providers.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$selectionActionServiceHash() =>
|
||||
r'9393acfbc2cc0864d9e9b116e65e4c2713da2ab1';
|
||||
r'c45737a0a403bff1bdb1931b89701300f8dc3726';
|
||||
|
||||
/// See also [selectionActionService].
|
||||
@ProviderFor(selectionActionService)
|
||||
|
||||
+2
-2
@@ -76,11 +76,11 @@ class _TabSheetHeader extends HookConsumerWidget {
|
||||
final container = ref.read(selectedContainerProvider);
|
||||
await ref
|
||||
.read(tabDataRepositoryProvider.notifier)
|
||||
.closeAllTabs(container);
|
||||
.closeAllTabsByContainer(container);
|
||||
|
||||
onClose();
|
||||
},
|
||||
icon: const Icon(Icons.delete),
|
||||
icon: const Icon(MdiIcons.closeBoxMultiple),
|
||||
label: const Text('Close All'),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
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:nullability/nullability.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/entities/states/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/presentation/widgets/tab_icon.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
|
||||
import 'package:weblibre/presentation/hooks/menu_controller.dart';
|
||||
|
||||
class TabPreview extends StatelessWidget {
|
||||
class TabPreview extends HookWidget {
|
||||
final TabState tab;
|
||||
final bool isActive;
|
||||
|
||||
final VoidCallback? onTap;
|
||||
final VoidCallback? onDoubleTap;
|
||||
final VoidCallback? onDelete;
|
||||
final void Function(String host)? onDeleteAll;
|
||||
|
||||
const TabPreview({
|
||||
required this.tab,
|
||||
@@ -20,12 +25,15 @@ class TabPreview extends StatelessWidget {
|
||||
this.onTap,
|
||||
this.onDoubleTap,
|
||||
this.onDelete,
|
||||
this.onDeleteAll,
|
||||
super.key,
|
||||
});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
final extendedDeleteMenuController = useMenuController();
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
@@ -62,13 +70,37 @@ class TabPreview extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
visualDensity: const VisualDensity(
|
||||
horizontal: -4.0,
|
||||
vertical: -4.0,
|
||||
MenuAnchor(
|
||||
controller: extendedDeleteMenuController,
|
||||
builder: (context, controller, child) {
|
||||
return child!;
|
||||
},
|
||||
menuChildren: [
|
||||
MenuItemButton(
|
||||
onPressed: onDeleteAll.mapNotNull(
|
||||
(p0) => () {
|
||||
p0(tab.url.host);
|
||||
},
|
||||
),
|
||||
leadingIcon: const Icon(MdiIcons.closeBoxMultiple),
|
||||
child: Text('Close all from ${tab.url.host}'),
|
||||
),
|
||||
],
|
||||
child: IconButton(
|
||||
visualDensity: const VisualDensity(
|
||||
horizontal: -4.0,
|
||||
vertical: -4.0,
|
||||
),
|
||||
onPressed: onDelete,
|
||||
onLongPress: () {
|
||||
if (extendedDeleteMenuController.isOpen) {
|
||||
extendedDeleteMenuController.close();
|
||||
} else {
|
||||
extendedDeleteMenuController.open();
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.close),
|
||||
),
|
||||
onPressed: onDelete,
|
||||
icon: const Icon(Icons.close),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -166,6 +198,15 @@ class TabPreviewDraggable extends HookConsumerWidget {
|
||||
onClose();
|
||||
}
|
||||
},
|
||||
onDeleteAll: (host) async {
|
||||
final containerId = await ref
|
||||
.read(tabDataRepositoryProvider.notifier)
|
||||
.containerTabId(tab.id);
|
||||
|
||||
await ref
|
||||
.read(tabDataRepositoryProvider.notifier)
|
||||
.closeAllTabsByHost(containerId, host);
|
||||
},
|
||||
// onDoubleTap: () {
|
||||
// ref.read(overlayDialogControllerProvider.notifier).show(
|
||||
// TabActionDialog(
|
||||
|
||||
@@ -66,6 +66,20 @@ class ContainerDao extends DatabaseAccessor<TabDatabase>
|
||||
return query.map((row) => row.read(db.tab.id)!);
|
||||
}
|
||||
|
||||
Selectable<TabData> getContainerTabsData(String? containerId) {
|
||||
final query =
|
||||
db.tab.select()
|
||||
..where(
|
||||
(t) =>
|
||||
(containerId != null)
|
||||
? t.containerId.equals(containerId)
|
||||
: t.containerId.isNull(),
|
||||
)
|
||||
..orderBy([(t) => OrderingTerm.asc(t.orderKey)]);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
SingleSelectable<String> generateLeadingOrderKey(
|
||||
String? containerId, {
|
||||
int bucket = 0,
|
||||
|
||||
@@ -43,7 +43,9 @@ class ContainerRepository extends _$ContainerRepository {
|
||||
}
|
||||
|
||||
Future<void> deleteContainer(String id) async {
|
||||
await ref.read(tabDataRepositoryProvider.notifier).closeAllTabs(id);
|
||||
await ref
|
||||
.read(tabDataRepositoryProvider.notifier)
|
||||
.closeAllTabsByContainer(id);
|
||||
|
||||
return ref.read(tabDatabaseProvider).containerDao.deleteContainer(id);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ part of 'container.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$containerRepositoryHash() =>
|
||||
r'9fff10b7896ea8865282bc315df21abde18b9d69';
|
||||
r'5344ecde33c1c80c1fa2bc8383faca181da91593';
|
||||
|
||||
/// See also [ContainerRepository].
|
||||
@ProviderFor(ContainerRepository)
|
||||
|
||||
@@ -20,7 +20,7 @@ class TabDataRepository extends _$TabDataRepository {
|
||||
.assignOrderKey(tabId, orderKey: orderKey);
|
||||
}
|
||||
|
||||
Future<void> closeAllTabs(String? containerId) async {
|
||||
Future<void> closeAllTabsByContainer(String? containerId) async {
|
||||
final tabIds =
|
||||
await ref
|
||||
.read(tabDatabaseProvider)
|
||||
@@ -33,6 +33,25 @@ class TabDataRepository extends _$TabDataRepository {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> closeAllTabsByHost(String? containerId, String host) async {
|
||||
final tabs =
|
||||
await ref
|
||||
.read(tabDatabaseProvider)
|
||||
.containerDao
|
||||
.getContainerTabsData(containerId)
|
||||
.get();
|
||||
|
||||
final filtered =
|
||||
tabs
|
||||
.where((tab) => tab.url?.host == host)
|
||||
.map((tab) => tab.id)
|
||||
.toList();
|
||||
|
||||
if (filtered.isNotEmpty) {
|
||||
await ref.read(tabRepositoryProvider.notifier).closeTabs(filtered);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> containerTabId(String tabId) {
|
||||
return ref
|
||||
.read(tabDatabaseProvider)
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'tab.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$tabDataRepositoryHash() => r'b5193e58aa331c7d0dc374e01032fe3a44955c99';
|
||||
String _$tabDataRepositoryHash() => r'0de1de9f948e38cc0a6d2fc18a06b1327d41c7ca';
|
||||
|
||||
/// See also [TabDataRepository].
|
||||
@ProviderFor(TabDataRepository)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
@@ -8,6 +6,7 @@ import 'package:path_provider/path_provider.dart' as path_provider;
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:sqlite3/sqlite3.dart';
|
||||
import 'package:sqlite3_flutter_libs/sqlite3_flutter_libs.dart';
|
||||
import 'package:universal_io/io.dart';
|
||||
import 'package:weblibre/features/web_feed/data/database/database.dart';
|
||||
|
||||
part 'providers.g.dart';
|
||||
|
||||
Reference in New Issue
Block a user