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