site assign context menu

This commit is contained in:
Fabian Freund
2025-11-16 06:12:55 +01:00
parent a8e0c07667
commit 0d35359da0
3 changed files with 99 additions and 0 deletions
@@ -24,6 +24,7 @@ import 'package:flutter/services.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:share_plus/share_plus.dart';
import 'package:weblibre/core/routing/routes.dart';
import 'package:weblibre/features/geckoview/domain/controllers/bottom_sheet.dart';
@@ -35,6 +36,7 @@ import 'package:weblibre/features/geckoview/features/browser/presentation/dialog
import 'package:weblibre/features/geckoview/features/find_in_page/presentation/controllers/find_in_page.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/models/container_data.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/tab.dart';
@@ -214,6 +216,50 @@ class TabMenu extends HookConsumerWidget {
}
},
),
Consumer(
child: MenuItemButton(
leadingIcon: const Icon(MdiIcons.webPlus),
child: const Text('Assign Site to Container'),
onPressed: () async {
final targetContainerId = await 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));
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!,
);
},
),
Consumer(
child: MenuItemButton(
leadingIcon: const Icon(MdiIcons.folderCancelOutline),
@@ -20,6 +20,8 @@
import 'package:nullability/nullability.dart';
import 'package:riverpod/riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.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/features/tabs/data/database/definitions.drift.dart';
import 'package:weblibre/features/geckoview/features/tabs/data/entities/container_filter.dart';
import 'package:weblibre/features/geckoview/features/tabs/data/models/container_data.dart';
@@ -124,3 +126,18 @@ Stream<String?> watchContainerTabId(Ref ref, String tabId) {
Stream<List<SiteAssignment>> watchAllAssignedSites(Ref ref) {
return ref.read(tabDatabaseProvider).containerDao.allAssignedSites().watch();
}
@Riverpod()
Stream<bool> watchIsCurrentSiteAssignedToContainer(Ref ref) {
final currentUri = ref.watch(
selectedTabStateProvider.select(
(value) => value?.url ?? TabState.$default('').url,
),
);
return ref
.read(tabDatabaseProvider)
.containerDao
.isSiteAssignedToContainer(currentUri)
.watchSingle();
}
@@ -673,3 +673,39 @@ final class WatchAllAssignedSitesProvider
String _$watchAllAssignedSitesHash() =>
r'd755451be0ad7e03db36ba39c64f6f0b5c1d9ba3';
@ProviderFor(watchIsCurrentSiteAssignedToContainer)
const watchIsCurrentSiteAssignedToContainerProvider =
WatchIsCurrentSiteAssignedToContainerProvider._();
final class WatchIsCurrentSiteAssignedToContainerProvider
extends $FunctionalProvider<AsyncValue<bool>, bool, Stream<bool>>
with $FutureModifier<bool>, $StreamProvider<bool> {
const WatchIsCurrentSiteAssignedToContainerProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'watchIsCurrentSiteAssignedToContainerProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() =>
_$watchIsCurrentSiteAssignedToContainerHash();
@$internal
@override
$StreamProviderElement<bool> $createElement($ProviderPointer pointer) =>
$StreamProviderElement(pointer);
@override
Stream<bool> create(Ref ref) {
return watchIsCurrentSiteAssignedToContainer(ref);
}
}
String _$watchIsCurrentSiteAssignedToContainerHash() =>
r'2942672c75b671fbe84489606e5341f0290502c3';