refactor container selection pattern and improve search UI

This commit is contained in:
Fabian Freund
2026-02-25 15:47:38 +01:00
parent 702b4b27ca
commit dc5f7902ab
45 changed files with 1713 additions and 735 deletions
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2024-2026 Fabian Freund.
*
* This file is part of WebLibre
* (see https://weblibre.eu).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'package:weblibre/features/geckoview/features/tabs/data/models/container_data.dart';
sealed class TabContainerSelection {
const TabContainerSelection();
const factory TabContainerSelection.useSelected() =
UseSelectedContainerTabSelection;
const factory TabContainerSelection.unassigned() =
UnassignedContainerTabSelection;
const factory TabContainerSelection.specific(ContainerData container) =
SpecificContainerTabSelection;
}
final class UseSelectedContainerTabSelection extends TabContainerSelection {
const UseSelectedContainerTabSelection();
}
final class UnassignedContainerTabSelection extends TabContainerSelection {
const UnassignedContainerTabSelection();
}
final class SpecificContainerTabSelection extends TabContainerSelection {
final ContainerData container;
const SpecificContainerTabSelection(this.container);
}
@@ -26,6 +26,7 @@ import 'package:nullability/nullability.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:weblibre/core/logger.dart';
import 'package:weblibre/features/geckoview/domain/entities/states/tab.dart';
import 'package:weblibre/features/geckoview/domain/entities/tab_container_selection.dart';
import 'package:weblibre/features/geckoview/domain/providers.dart';
import 'package:weblibre/features/geckoview/domain/providers/selected_tab.dart';
import 'package:weblibre/features/geckoview/domain/providers/tab_list.dart';
@@ -87,20 +88,22 @@ class TabRepository extends _$TabRepository {
required bool private,
HistoryMetadataKey? historyMetadata,
Map<String, String>? additionalHeaders,
Value<ContainerData?>? container,
TabContainerSelection containerSelection =
const TabContainerSelection.useSelected(),
bool launchedFromIntent = false,
}) async {
final tabDao = ref.read(tabDatabaseProvider).tabDao;
final assingedContainer =
container ??
Value<ContainerData?>(
await ref.read(selectedContainerProvider.notifier).fetchData(),
);
final assignedContainer = switch (containerSelection) {
UseSelectedContainerTabSelection() =>
await ref.read(selectedContainerProvider.notifier).fetchData(),
UnassignedContainerTabSelection() => null,
SpecificContainerTabSelection(:final container) => container,
};
final validatedParentId = await _resolveParentIdForContext(
parentId: parentId,
targetContextId: assingedContainer.value?.metadata.contextualIdentity,
targetContextId: assignedContainer?.metadata.contextualIdentity,
);
final newTabId = await tabDao.upsertTabTransactional(
@@ -111,7 +114,7 @@ class TabRepository extends _$TabRepository {
startLoading: startLoading,
parentId: validatedParentId,
flags: flags,
contextId: assingedContainer.value?.metadata.contextualIdentity,
contextId: assignedContainer?.metadata.contextualIdentity,
source: source,
private: private,
historyMetadata: historyMetadata,
@@ -119,7 +122,7 @@ class TabRepository extends _$TabRepository {
);
},
parentId: Value(validatedParentId),
containerId: Value(assingedContainer.value?.id),
containerId: Value(assignedContainer?.id),
isPrivate: Value(private),
url: Value(url),
);
@@ -134,10 +137,17 @@ class TabRepository extends _$TabRepository {
Future<List<String>> addMultipleTabs({
required List<AddTabParams> tabs,
String? selectTabId,
Value<ContainerData?>? container,
TabContainerSelection containerSelection =
const TabContainerSelection.unassigned(),
}) async {
final tabDao = ref.read(tabDatabaseProvider).tabDao;
final db = ref.read(tabDatabaseProvider);
final assignedContainer = switch (containerSelection) {
UseSelectedContainerTabSelection() =>
await ref.read(selectedContainerProvider.notifier).fetchData(),
UnassignedContainerTabSelection() => null,
SpecificContainerTabSelection(:final container) => container,
};
return await db.transaction(() async {
final createdTabIds = await _tabsService.addMultipleTabs(
@@ -177,7 +187,7 @@ class TabRepository extends _$TabRepository {
tabId,
parentId: Value(validatedParentId),
source: TabSource.manual,
containerId: Value(container?.value?.id),
containerId: Value(assignedContainer?.id),
isPrivate: Value(tab.private),
url: Value(Uri.tryParse(tab.url)),
);
@@ -466,7 +476,9 @@ class TabRepository extends _$TabRepository {
await addTab(
url: uri,
private: tabState.isPrivate,
container: Value(containerData),
containerSelection: TabContainerSelection.specific(
containerData,
),
parentId: tabState.id,
selectTab: true,
);
@@ -41,7 +41,7 @@ final class TabRepositoryProvider
}
}
String _$tabRepositoryHash() => r'0a676c0513917e8853677ebd592954bde0f15f57';
String _$tabRepositoryHash() => r'd77e4e74bb7ee1b466172bca245b05c6bf03196c';
abstract class _$TabRepository extends $Notifier<void> {
void build();