clear data of isolated containers; improved tab handling/state/duplication;

This commit is contained in:
Fabian Freund
2025-12-31 06:22:48 +01:00
parent 62f53ce327
commit d4585921ce
22 changed files with 909 additions and 280 deletions
@@ -32,6 +32,8 @@ part 'tab.g.dart';
@CopyWith()
class TabState extends WebPageInfo {
static final defaultUrl = Uri.parse('about:blank');
@CopyWithField(immutable: true)
final String id;
@@ -92,7 +94,7 @@ class TabState extends WebPageInfo {
id: tabId,
parentId: null,
contextId: null,
url: Uri.parse('about:blank'),
url: defaultUrl,
title: "",
icon: null,
thumbnail: null,
@@ -46,9 +46,9 @@ part 'tab_state.g.dart';
@Riverpod(keepAlive: true)
class TabStates extends _$TabStates {
void _onTabContentStateChange(TabContentState contentState) {
final current =
state[contentState.id] ?? TabState.$default(contentState.id);
Future<void> _onTabContentStateChange(TabContentState contentState) async {
final current = await patchedState(contentState.id);
final url = Uri.parse(contentState.url);
// Determine title based on priority: new non-empty title > existing title if URL authority unchanged > new title
@@ -81,6 +81,27 @@ class TabStates extends _$TabStates {
}
}
Future<TabState> patchedState(String id) async {
var current = stateOrNull?[id];
if (current == null || current.url == TabState.defaultUrl) {
current ??= TabState.$default(id);
final tabData = await ref
.read(tabDataRepositoryProvider.notifier)
.getTabDataById(id);
if (tabData?.url != null) {
current = current.copyWith(
title: tabData!.title ?? current.title,
url: tabData.url ?? current.url,
);
}
}
return current;
}
Future<void> _onIconChange(IconChangeEvent event) async {
final IconChangeEvent(:tabId, :bytes) = event;
@@ -174,8 +195,8 @@ class TabStates extends _$TabStates {
final eventService = ref.watch(eventServiceProvider);
final subscriptions = [
eventService.tabContentEvents.listen((event) {
_onTabContentStateChange(event);
eventService.tabContentEvents.listen((event) async {
await _onTabContentStateChange(event);
}),
eventService.iconChangeEvents.listen((event) async {
await _onIconChange(event);
@@ -41,7 +41,7 @@ final class TabStatesProvider
}
}
String _$tabStatesHash() => r'778242f0b67eb7646014d0df857a3a71de214c40';
String _$tabStatesHash() => r'cd73ea6ea479f2708a2c9e5ca86054c9d2464116';
abstract class _$TabStates extends $Notifier<Map<String, TabState>> {
Map<String, TabState> build();
@@ -75,7 +75,7 @@ class TabRepository extends _$TabRepository {
await ref.read(selectedContainerProvider.notifier).fetchData(),
);
final newTabId = await tabDao.upsertContainerTabTransactional(
final newTabId = await tabDao.upsertTabTransactional(
() {
return _tabsService.addTab(
url: url,
@@ -93,6 +93,7 @@ class TabRepository extends _$TabRepository {
parentId: Value(parentId),
containerId: Value(assingedContainer.value?.id),
isPrivate: Value(private),
url: Value(url),
);
if (launchedFromIntent) {
@@ -102,10 +103,42 @@ class TabRepository extends _$TabRepository {
return newTabId;
}
Future<List<String>> addMultipleTabs({
required List<AddTabParams> tabs,
String? selectTabId,
Value<ContainerData?>? container,
}) async {
final tabDao = ref.read(tabDatabaseProvider).tabDao;
final db = ref.read(tabDatabaseProvider);
return await db.transaction(() async {
final createdTabIds = await _tabsService.addMultipleTabs(
tabs: tabs,
selectTabId: selectTabId,
);
// Upsert all tabs in the database
for (var i = 0; i < createdTabIds.length; i++) {
final tabId = createdTabIds[i];
final tab = tabs[i];
await tabDao.insertTab(
tabId,
parentId: Value(tab.parentId),
containerId: Value(container?.value?.id),
isPrivate: Value(tab.private),
url: Value(Uri.tryParse(tab.url)),
);
}
return createdTabIds;
});
}
Future<String> duplicateTab({
required String selectTabId,
String? containerId,
bool selectTab = true,
required String? containerId,
bool selectTab = false,
}) async {
final tabDao = ref.read(tabDatabaseProvider).tabDao;
@@ -115,7 +148,7 @@ class TabRepository extends _$TabRepository {
.getContainerData(containerId),
);
return await tabDao.upsertContainerTabTransactional(
return await tabDao.upsertTabTransactional(
() {
return _tabsService.duplicateTab(
selectTabId: selectTabId,
@@ -376,14 +409,16 @@ class TabRepository extends _$TabRepository {
final db = ref.watch(tabDatabaseProvider);
final tabAddedSub = eventSerivce.tabAddedStream.listen((tabId) async {
// ignore: only_use_keep_alive_inside_keep_alive
final containerId = ref.read(selectedContainerProvider);
await db.tabDao.upsertUnassignedTab(
tabId,
parentId: const Value.absent(),
containerId: Value(containerId),
isPrivate: const Value.absent(),
);
if (await db.tabDao.getTabDataById(tabId).getSingleOrNull() == null) {
// ignore: only_use_keep_alive_inside_keep_alive
final containerId = ref.read(selectedContainerProvider);
await db.tabDao.insertTab(
tabId,
parentId: const Value.absent(),
containerId: Value(containerId),
isPrivate: const Value.absent(),
);
}
});
final containerSiteAssignementSub = eventSerivce.siteAssignementEvent.listen((
@@ -407,7 +442,7 @@ class TabRepository extends _$TabRepository {
if (containerData != null) {
final tabIsEmpty =
tabState.url == TabState.$default(tabState.id).url &&
tabState.url == TabState.defaultUrl &&
tabState.historyState.items.isEmpty;
if (event.blocked || tabIsEmpty) {
@@ -41,7 +41,7 @@ final class TabRepositoryProvider
}
}
String _$tabRepositoryHash() => r'0411e8b3fa9c3e344106f8fa8178bd6eb613309a';
String _$tabRepositoryHash() => r'de20adb4a38f8cd443be7d2f4ea07eded58803a3';
abstract class _$TabRepository extends $Notifier<void> {
void build();