This commit is contained in:
@@ -54,6 +54,14 @@ class TabProgressStates extends _$TabProgressStates {
|
||||
|
||||
state = {...state}..[tabId] = progress;
|
||||
}
|
||||
|
||||
void removeAll(Set<String> tabIds) {
|
||||
if (!state.keys.any(tabIds.contains)) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = {...state}..removeWhere((tabId, _) => tabIds.contains(tabId));
|
||||
}
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
@@ -88,6 +96,17 @@ class TabThumbnails extends _$TabThumbnails {
|
||||
|
||||
state = {...state}..[tabId] = thumbnail;
|
||||
}
|
||||
|
||||
void removeAll(Set<String> tabIds) {
|
||||
if (!state.keys.any(tabIds.contains)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// EquatableImage owns its ui.Image through a finalizer. Dropping the map
|
||||
// reference is safer than disposing it here because an outgoing tab-preview
|
||||
// frame may still hold the same wrapper briefly.
|
||||
state = {...state}..removeWhere((tabId, _) => tabIds.contains(tabId));
|
||||
}
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
@@ -112,6 +131,14 @@ class TabHistoryStates extends _$TabHistoryStates {
|
||||
|
||||
state = {...state}..[tabId] = history;
|
||||
}
|
||||
|
||||
void removeAll(Set<String> tabIds) {
|
||||
if (!state.keys.any(tabIds.contains)) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = {...state}..removeWhere((tabId, _) => tabIds.contains(tabId));
|
||||
}
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
@@ -142,6 +169,14 @@ class TabFindResultStates extends _$TabFindResultStates {
|
||||
|
||||
FindResultState resultFor(String tabId) =>
|
||||
state[tabId] ?? FindResultState.$default();
|
||||
|
||||
void removeAll(Set<String> tabIds) {
|
||||
if (!state.keys.any(tabIds.contains)) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = {...state}..removeWhere((tabId, _) => tabIds.contains(tabId));
|
||||
}
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
@@ -170,6 +205,14 @@ class TabTranslationStates extends _$TabTranslationStates {
|
||||
|
||||
state = {...state}..[tabId] = translation;
|
||||
}
|
||||
|
||||
void removeAll(Set<String> tabIds) {
|
||||
if (!state.keys.any(tabIds.contains)) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = {...state}..removeWhere((tabId, _) => tabIds.contains(tabId));
|
||||
}
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
|
||||
@@ -36,6 +36,7 @@ import 'package:weblibre/features/geckoview/domain/entities/states/translation.d
|
||||
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_detail_state.dart';
|
||||
import 'package:weblibre/features/geckoview/domain/providers/tab_list.dart';
|
||||
import 'package:weblibre/features/geckoview/features/find_in_page/domain/repositories/find_in_page.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/data/entities/isolation_context.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/data/entities/tab_mode.dart';
|
||||
@@ -75,6 +76,14 @@ class TabStates extends _$TabStates {
|
||||
state = {...state}..[tabId] = next;
|
||||
}
|
||||
|
||||
void _removeAll(Set<String> tabIds) {
|
||||
if (!state.keys.any(tabIds.contains)) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = {...state}..removeWhere((tabId, _) => tabIds.contains(tabId));
|
||||
}
|
||||
|
||||
Future<void> _onTabContentStateChange(TabContentState contentState) async {
|
||||
final current = await patchedState(contentState.id);
|
||||
|
||||
@@ -187,6 +196,9 @@ class TabStates extends _$TabStates {
|
||||
bytes,
|
||||
targetWidth: thumbnailDecodeWidth,
|
||||
allowUpscaling: false,
|
||||
// Periodic screenshots are almost always unique. Caching each decode
|
||||
// retained up to 100 obsolete GPU images in the global icon LRU.
|
||||
cacheResult: false,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -415,6 +427,29 @@ class TabStates extends _$TabStates {
|
||||
},
|
||||
);
|
||||
|
||||
ref.listen(tabListProvider, (previous, next) {
|
||||
if (previous == null) {
|
||||
// The first list can be a partial restore snapshot. There is no reliable
|
||||
// removal signal until Gecko has emitted at least two snapshots.
|
||||
return;
|
||||
}
|
||||
|
||||
final activeTabIds = next.value.toSet();
|
||||
final removedTabIds = previous.value
|
||||
.where((tabId) => !activeTabIds.contains(tabId))
|
||||
.toSet();
|
||||
if (removedTabIds.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
_removeAll(removedTabIds);
|
||||
ref.read(tabProgressStatesProvider.notifier).removeAll(removedTabIds);
|
||||
ref.read(tabThumbnailsProvider.notifier).removeAll(removedTabIds);
|
||||
ref.read(tabHistoryStatesProvider.notifier).removeAll(removedTabIds);
|
||||
ref.read(tabFindResultStatesProvider.notifier).removeAll(removedTabIds);
|
||||
ref.read(tabTranslationStatesProvider.notifier).removeAll(removedTabIds);
|
||||
});
|
||||
|
||||
ref.onDispose(() async {
|
||||
for (final sub in subscriptions) {
|
||||
await sub.cancel();
|
||||
|
||||
Reference in New Issue
Block a user