From ae49d0f9371dfa3fe318bfd2c750867886ea269d Mon Sep 17 00:00:00 2001 From: Fabian Freund Date: Thu, 2 Oct 2025 13:34:47 +0200 Subject: [PATCH] provider mounted hardenings --- app/lib/core/providers/router.dart | 10 +-- app/lib/core/providers/router.g.dart | 2 +- .../domain/services/app_initialization.dart | 6 ++ .../domain/services/app_initialization.g.dart | 2 +- app/lib/features/about/domain/providers.dart | 8 +- .../features/about/domain/providers.g.dart | 4 +- .../domain/services/home_widget.dart | 2 +- .../domain/services/home_widget.g.dart | 2 +- .../domain/controllers/bottom_sheet.dart | 1 + .../features/geckoview/domain/providers.dart | 82 +++++++++-------- .../geckoview/domain/providers.g.dart | 2 +- .../geckoview/domain/repositories/tab.dart | 90 +++++++++++-------- .../geckoview/domain/repositories/tab.g.dart | 2 +- .../browser/domain/providers/intent.dart | 1 + .../domain/services/browser_addon.dart | 2 + .../domain/services/browser_addon.g.dart | 2 +- .../repositories/preference_settings.dart | 32 +++++-- .../repositories/preference_settings.g.dart | 6 +- .../domain/providers/selected_container.dart | 6 +- .../providers/selected_container.g.dart | 2 +- .../domain/repositories/gecko_inference.dart | 16 +++- .../repositories/gecko_inference.g.dart | 6 +- .../tor/domain/services/tor_proxy.dart | 2 + .../tor/domain/services/tor_proxy.g.dart | 2 +- .../domain/repositories/engine_settings.dart | 9 +- .../repositories/engine_settings.g.dart | 2 +- .../domain/repositories/general_settings.dart | 4 +- .../repositories/general_settings.g.dart | 2 +- .../domain/repositories/tor_settings.dart | 4 +- .../domain/repositories/tor_settings.g.dart | 2 +- .../controllers/fetch_articles.dart | 28 +++--- .../controllers/fetch_articles.g.dart | 2 +- 32 files changed, 197 insertions(+), 146 deletions(-) diff --git a/app/lib/core/providers/router.dart b/app/lib/core/providers/router.dart index 85fdde03..97ef1e8a 100644 --- a/app/lib/core/providers/router.dart +++ b/app/lib/core/providers/router.dart @@ -26,16 +26,14 @@ part 'router.g.dart'; @Riverpod(keepAlive: true) Future router(Ref ref) async { + final onboardingRepository = ref.read(onboardingRepositoryProvider.notifier); + String? initialLocation; - final onboardingMandatory = await ref - .read(onboardingRepositoryProvider.notifier) - .isOutdated(); + final onboardingMandatory = await onboardingRepository.isOutdated(); if (onboardingMandatory) { - final current = await ref - .read(onboardingRepositoryProvider.notifier) - .getCurrentRevision(); + final current = await onboardingRepository.getCurrentRevision(); final route = OnboardingRoute( currentRevision: current ?? -1, diff --git a/app/lib/core/providers/router.g.dart b/app/lib/core/providers/router.g.dart index 3bd6fdf3..f849f572 100644 --- a/app/lib/core/providers/router.g.dart +++ b/app/lib/core/providers/router.g.dart @@ -41,4 +41,4 @@ final class RouterProvider } } -String _$routerHash() => r'ce7cc5b5f236781a06867a852a08ed03d3582022'; +String _$routerHash() => r'9e7ab621a0e97d0aab2c6bd1fd0e272d81e5298c'; diff --git a/app/lib/domain/services/app_initialization.dart b/app/lib/domain/services/app_initialization.dart index e8812132..52484758 100644 --- a/app/lib/domain/services/app_initialization.dart +++ b/app/lib/domain/services/app_initialization.dart @@ -64,8 +64,14 @@ class AppInitializationService extends _$AppInitializationService { final errors = []; await ref.read(formatProvider.future); + if (!ref.mounted) { + return (initialized: false, stage: null, errors: errors); + } await _initPackageInfo(); + if (!ref.mounted) { + return (initialized: false, stage: null, errors: errors); + } final bangSyncResults = await _initBangs(); for (final MapEntry(value: result) in bangSyncResults.entries) { diff --git a/app/lib/domain/services/app_initialization.g.dart b/app/lib/domain/services/app_initialization.g.dart index 1997c51a..2d625599 100644 --- a/app/lib/domain/services/app_initialization.g.dart +++ b/app/lib/domain/services/app_initialization.g.dart @@ -54,7 +54,7 @@ final class AppInitializationServiceProvider } String _$appInitializationServiceHash() => - r'9966be978ea4990c56a3aba347e7979921bf6b2b'; + r'c26f968d53b4ea18f7be890c9610c9bf9d300322'; abstract class _$AppInitializationService extends diff --git a/app/lib/features/about/domain/providers.dart b/app/lib/features/about/domain/providers.dart index 6133e6c9..c72e75a2 100644 --- a/app/lib/features/about/domain/providers.dart +++ b/app/lib/features/about/domain/providers.dart @@ -5,11 +5,11 @@ import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'providers.g.dart'; @Riverpod(keepAlive: true) -Future packageInfo(Ref ref) { - return PackageInfo.fromPlatform(); +Future packageInfo(Ref ref) async { + return await PackageInfo.fromPlatform(); } @Riverpod() -Future geckoVersion(Ref ref) { - return GeckoBrowserService().getGeckoVersion(); +Future geckoVersion(Ref ref) async { + return await GeckoBrowserService().getGeckoVersion(); } diff --git a/app/lib/features/about/domain/providers.g.dart b/app/lib/features/about/domain/providers.g.dart index 04026669..e8dde0e3 100644 --- a/app/lib/features/about/domain/providers.g.dart +++ b/app/lib/features/about/domain/providers.g.dart @@ -46,7 +46,7 @@ final class PackageInfoProvider } } -String _$packageInfoHash() => r'cc57db7b4684ab0d5df0f050b8ea045a3658e89a'; +String _$packageInfoHash() => r'44d37547139567a5f03c1942c1d62ff1abb07248'; @ProviderFor(geckoVersion) const geckoVersionProvider = GeckoVersionProvider._(); @@ -79,4 +79,4 @@ final class GeckoVersionProvider } } -String _$geckoVersionHash() => r'3a8639b5d1d07c60a789cf705ede09a91cbaee63'; +String _$geckoVersionHash() => r'1ad2af96ba1999660c208a0095530d901d589228'; diff --git a/app/lib/features/app_widget/domain/services/home_widget.dart b/app/lib/features/app_widget/domain/services/home_widget.dart index 846d724d..cfccebd6 100644 --- a/app/lib/features/app_widget/domain/services/home_widget.dart +++ b/app/lib/features/app_widget/domain/services/home_widget.dart @@ -25,7 +25,7 @@ import 'package:weblibre/data/models/received_intent_parameter.dart'; part 'home_widget.g.dart'; @Riverpod(keepAlive: true) -FutureOr widgetPinnable(Ref ref) async { +Future widgetPinnable(Ref ref) async { return await HomeWidget.isRequestPinWidgetSupported() ?? false; } diff --git a/app/lib/features/app_widget/domain/services/home_widget.g.dart b/app/lib/features/app_widget/domain/services/home_widget.g.dart index c9afef1d..27cb411b 100644 --- a/app/lib/features/app_widget/domain/services/home_widget.g.dart +++ b/app/lib/features/app_widget/domain/services/home_widget.g.dart @@ -40,7 +40,7 @@ final class WidgetPinnableProvider } } -String _$widgetPinnableHash() => r'f91041f0f051ad0f00dd765cafea5571ca8c8088'; +String _$widgetPinnableHash() => r'3181e5e3e69e7e796e6429ca7507bbbc239f6c21'; @ProviderFor(appWidgetLaunchStream) const appWidgetLaunchStreamProvider = AppWidgetLaunchStreamProvider._(); diff --git a/app/lib/features/geckoview/domain/controllers/bottom_sheet.dart b/app/lib/features/geckoview/domain/controllers/bottom_sheet.dart index d2f20204..64cbda0b 100644 --- a/app/lib/features/geckoview/domain/controllers/bottom_sheet.dart +++ b/app/lib/features/geckoview/domain/controllers/bottom_sheet.dart @@ -55,6 +55,7 @@ class BottomSheetExtend extends _$BottomSheetExtend { @override Stream build() { _extentStreamController = StreamController(); + ref.onDispose(() async { await _extentStreamController.close(); }); diff --git a/app/lib/features/geckoview/domain/providers.dart b/app/lib/features/geckoview/domain/providers.dart index b6bc6ef3..1eb40061 100644 --- a/app/lib/features/geckoview/domain/providers.dart +++ b/app/lib/features/geckoview/domain/providers.dart @@ -42,51 +42,59 @@ GeckoSelectionActionService selectionActionService(Ref ref) { unawaited( service.setActions([ NewTabAction((text) async { - final router = await ref.read(routerProvider.future); - final settings = ref.read(generalSettingsWithDefaultsProvider); - final route = SearchRoute( - tabType: - // ignore: only_use_keep_alive_inside_keep_alive - ref.read(selectedTabTypeProvider) ?? - settings.defaultCreateTabType, - searchText: text, - ); + if (ref.mounted) { + final router = await ref.read(routerProvider.future); + if (ref.mounted) { + final settings = ref.read(generalSettingsWithDefaultsProvider); + final route = SearchRoute( + tabType: + // ignore: only_use_keep_alive_inside_keep_alive + ref.read(selectedTabTypeProvider) ?? + settings.defaultCreateTabType, + searchText: text, + ); - await router.push(route.location); + await router.push(route.location); + } + } }), DefaultSearchAction((text) async { - final defaultSearchBang = await ref.read( - defaultSearchBangDataProvider.future, - ); + if (ref.mounted) { + final defaultSearchBang = await ref.read( + defaultSearchBangDataProvider.future, + ); - if (defaultSearchBang != null) { - // ignore: only_use_keep_alive_inside_keep_alive - final currentTab = ref.read(selectedTabStateProvider); - final isPrivate = - currentTab?.isPrivate ?? - ref - .read(generalSettingsWithDefaultsProvider) - .defaultCreateTabType == - TabType.private; + if (ref.mounted && defaultSearchBang != null) { + // ignore: only_use_keep_alive_inside_keep_alive + final currentTab = ref.read(selectedTabStateProvider); + final isPrivate = + currentTab?.isPrivate ?? + ref + .read(generalSettingsWithDefaultsProvider) + .defaultCreateTabType == + TabType.private; - await ref - .read(tabRepositoryProvider.notifier) - .addTab( - url: defaultSearchBang.getTemplateUrl(text), - parentId: currentTab?.id, - private: isPrivate, - ); - } else { - logger.e('No default search bang found'); + await ref + .read(tabRepositoryProvider.notifier) + .addTab( + url: defaultSearchBang.getTemplateUrl(text), + parentId: currentTab?.id, + private: isPrivate, + ); + } else { + logger.e('No default search bang found'); + } } }), FindInPageAction((text) async { - final tabId = ref.read(selectedTabProvider); - if (tabId != null) { - // ignore: only_use_keep_alive_inside_keep_alive - await ref - .read(findInPageControllerProvider(tabId).notifier) - .findAll(text: text); + if (ref.mounted) { + final tabId = ref.read(selectedTabProvider); + if (tabId != null) { + // ignore: only_use_keep_alive_inside_keep_alive + await ref + .read(findInPageControllerProvider(tabId).notifier) + .findAll(text: text); + } } }), ShareAction((text) async { diff --git a/app/lib/features/geckoview/domain/providers.g.dart b/app/lib/features/geckoview/domain/providers.g.dart index fc6d8ba2..dccdb1ff 100644 --- a/app/lib/features/geckoview/domain/providers.g.dart +++ b/app/lib/features/geckoview/domain/providers.g.dart @@ -55,7 +55,7 @@ final class SelectionActionServiceProvider } String _$selectionActionServiceHash() => - r'c89d981c2ba253ed940887fa59c11ad93d8589a8'; + r'424c2c444524ee4bf2302405cac3358c148a7b16'; @ProviderFor(eventService) const eventServiceProvider = EventServiceProvider._(); diff --git a/app/lib/features/geckoview/domain/repositories/tab.dart b/app/lib/features/geckoview/domain/repositories/tab.dart index 3b593ac4..77daec6a 100644 --- a/app/lib/features/geckoview/domain/repositories/tab.dart +++ b/app/lib/features/geckoview/domain/repositories/tab.dart @@ -66,6 +66,8 @@ class TabRepository extends _$TabRepository { Value? container, bool launchedFromIntent = false, }) async { + final tabDao = ref.read(tabDatabaseProvider).tabDao; + final assingedContainer = container ?? Value( @@ -73,27 +75,24 @@ class TabRepository extends _$TabRepository { await ref.read(selectedContainerProvider.notifier).fetchData(), ); - final newTabId = await ref - .read(tabDatabaseProvider) - .tabDao - .upsertContainerTabTransactional( - () { - return _tabsService.addTab( - url: url, - selectTab: selectTab, - startLoading: startLoading, - parentId: parentId, - flags: flags, - contextId: assingedContainer.value?.metadata.contextualIdentity, - source: source, - private: private, - historyMetadata: historyMetadata, - additionalHeaders: additionalHeaders, - ); - }, - parentId: Value(parentId), - containerId: Value(assingedContainer.value?.id), + final newTabId = await tabDao.upsertContainerTabTransactional( + () { + return _tabsService.addTab( + url: url, + selectTab: selectTab, + startLoading: startLoading, + parentId: parentId, + flags: flags, + contextId: assingedContainer.value?.metadata.contextualIdentity, + source: source, + private: private, + historyMetadata: historyMetadata, + additionalHeaders: additionalHeaders, ); + }, + parentId: Value(parentId), + containerId: Value(assingedContainer.value?.id), + ); if (launchedFromIntent) { _tabFromIntent.add(newTabId); @@ -107,26 +106,25 @@ class TabRepository extends _$TabRepository { String? containerId, bool selectTab = true, }) async { + final tabDao = ref.read(tabDatabaseProvider).tabDao; + final containerData = await containerId.mapNotNull( (containerId) => ref .read(containerRepositoryProvider.notifier) .getContainerData(containerId), ); - return ref - .read(tabDatabaseProvider) - .tabDao - .upsertContainerTabTransactional( - () { - return _tabsService.duplicateTab( - selectTabId: selectTabId, - newContextId: containerData?.metadata.contextualIdentity, - selectNewTab: selectTab, - ); - }, - parentId: const Value.absent(), - containerId: Value(containerData?.id), + return await tabDao.upsertContainerTabTransactional( + () { + return _tabsService.duplicateTab( + selectTabId: selectTabId, + newContextId: containerData?.metadata.contextualIdentity, + selectNewTab: selectTab, ); + }, + parentId: const Value.absent(), + containerId: Value(containerData?.id), + ); } Future selectPreviouslyOpenedTab(String tabId) async { @@ -136,7 +134,7 @@ class TabRepository extends _$TabRepository { .previousTabByTimestamp(tabId: tabId) .getSingleOrNull(); - if (previousTabId != null) { + if (ref.mounted && previousTabId != null) { return selectTab(previousTabId); } @@ -158,7 +156,7 @@ class TabRepository extends _$TabRepository { ) .getSingleOrNull(); - if (previousTabId != null) { + if (ref.mounted && previousTabId != null) { return selectTab(previousTabId); } @@ -180,7 +178,7 @@ class TabRepository extends _$TabRepository { ) .getSingleOrNull(); - if (previousTabId != null) { + if (ref.mounted && previousTabId != null) { return selectTab(previousTabId); } @@ -192,12 +190,16 @@ class TabRepository extends _$TabRepository { .read(tabDataRepositoryProvider.notifier) .getContainerTabId(tabId); + if (!ref.mounted) return false; + final containerData = await containerId.mapNotNull( (containerId) => ref .read(containerRepositoryProvider.notifier) .getContainerData(containerId), ); + if (!ref.mounted) return false; + if (containerData != null) { if (containerData.metadata.authSettings.authenticationRequired) { // ignore: only_use_keep_alive_inside_keep_alive @@ -234,11 +236,15 @@ class TabRepository extends _$TabRepository { .read(tabDataRepositoryProvider.notifier) .getContainerTabId(tabId); + if (!ref.mounted) return; + final sameContainerTabs = await ref .read(containerRepositoryProvider.notifier) .getContainerTabIds(currentContainerId) .then((tabs) => tabs.where((tab) => tab != tabId).toList()); + if (!ref.mounted) return; + final previousTabId = await ref .read(tabDatabaseProvider) .definitionsDrift @@ -257,6 +263,8 @@ class TabRepository extends _$TabRepository { } } + if (!ref.mounted) return; + final previousOrderedTabId = await ref .read(tabDatabaseProvider) .definitionsDrift @@ -271,6 +279,8 @@ class TabRepository extends _$TabRepository { return _tabsService.selectTab(tabId: previousOrderedTabId); } + if (!ref.mounted) return; + final nextOrderedTabId = await ref .read(tabDatabaseProvider) .definitionsDrift @@ -285,6 +295,8 @@ class TabRepository extends _$TabRepository { return _tabsService.selectTab(tabId: nextOrderedTabId); } + if (!ref.mounted) return; + final unassignedTabs = await ref .read(containerRepositoryProvider.notifier) .getContainerTabIds(null) @@ -294,6 +306,8 @@ class TabRepository extends _$TabRepository { return _tabsService.selectTab(tabId: unassignedTabs.first); } + if (!ref.mounted) return; + //We only take containers without authentication! final availableContainers = await ref .read(containerRepositoryProvider.notifier) @@ -305,6 +319,8 @@ class TabRepository extends _$TabRepository { container.metadata.authSettings.authenticationRequired == false, ); + if (!ref.mounted) return; + final nextContainerTabs = await nextAvailableContainerUnauthenticated .mapNotNull( (container) => ref @@ -317,7 +333,7 @@ class TabRepository extends _$TabRepository { return _tabsService.selectTab(tabId: nextContainerTabs!.first); } - if (availableContainers.isNotEmpty) { + if (ref.mounted && availableContainers.isNotEmpty) { //Last resort push new tab to avoid any authenticated tab is selected // ignore: avoid_redundant_argument_values await addTab(selectTab: true, private: false); diff --git a/app/lib/features/geckoview/domain/repositories/tab.g.dart b/app/lib/features/geckoview/domain/repositories/tab.g.dart index 584db2f2..7b704634 100644 --- a/app/lib/features/geckoview/domain/repositories/tab.g.dart +++ b/app/lib/features/geckoview/domain/repositories/tab.g.dart @@ -41,7 +41,7 @@ final class TabRepositoryProvider } } -String _$tabRepositoryHash() => r'adf53bb00e5c80e9fcad6b9111d5723c996e966f'; +String _$tabRepositoryHash() => r'6fd5f78d5e5b728984b10a8824e06e82c5c26f4c'; abstract class _$TabRepository extends $Notifier { void build(); diff --git a/app/lib/features/geckoview/features/browser/domain/providers/intent.dart b/app/lib/features/geckoview/features/browser/domain/providers/intent.dart index 546c5264..1d3fbde8 100644 --- a/app/lib/features/geckoview/features/browser/domain/providers/intent.dart +++ b/app/lib/features/geckoview/features/browser/domain/providers/intent.dart @@ -53,6 +53,7 @@ class EngineBoundIntentStream extends _$EngineBoundIntentStream { @override Stream build() { _streamController = StreamController(); + ref.onDispose(() async { await _streamController.close(); }); diff --git a/app/lib/features/geckoview/features/browser/domain/services/browser_addon.dart b/app/lib/features/geckoview/features/browser/domain/services/browser_addon.dart index a240c6cc..98aef85e 100644 --- a/app/lib/features/geckoview/features/browser/domain/services/browser_addon.dart +++ b/app/lib/features/geckoview/features/browser/domain/services/browser_addon.dart @@ -52,6 +52,8 @@ class BrowserAddonService extends _$BrowserAddonService { Future install(String addonGuid) async { try { final xpiUrl = await getAddonXpiUrl(addonGuid); + if (!ref.mounted) return false; + await ref.read(addonServiceProvider).installAddon(xpiUrl); return true; diff --git a/app/lib/features/geckoview/features/browser/domain/services/browser_addon.g.dart b/app/lib/features/geckoview/features/browser/domain/services/browser_addon.g.dart index b7a047ba..bcf46ca6 100644 --- a/app/lib/features/geckoview/features/browser/domain/services/browser_addon.g.dart +++ b/app/lib/features/geckoview/features/browser/domain/services/browser_addon.g.dart @@ -42,7 +42,7 @@ final class BrowserAddonServiceProvider } String _$browserAddonServiceHash() => - r'1dd73c322e712e1492d74f1af844d5b5cc8f81bb'; + r'3f2166251f02fe8c103cca93c02eb982b2800577'; abstract class _$BrowserAddonService extends $Notifier { void build(); diff --git a/app/lib/features/geckoview/features/preferences/data/repositories/preference_settings.dart b/app/lib/features/geckoview/features/preferences/data/repositories/preference_settings.dart index 10c7a7a7..9bdfdc8b 100644 --- a/app/lib/features/geckoview/features/preferences/data/repositories/preference_settings.dart +++ b/app/lib/features/geckoview/features/preferences/data/repositories/preference_settings.dart @@ -52,8 +52,8 @@ Future _preferenceSettingGroup( Ref ref, PreferencePartition partition, String groupName, -) { - return ref.watch( +) async { + return await ref.watch( _preferenceSettingGroupsProvider(partition).selectAsync( (groups) => groups[groupName] ?? (throw Exception('Unknown setting group')), @@ -104,6 +104,10 @@ class UnifiedPreferenceSettingsRepository Map? _statelessGroups; Future apply() async { + final preferenceRepository = ref.read( + _preferenceRepositoryProvider.notifier, + ); + _statelessGroups = await ref.read( _preferenceSettingGroupsProvider(partition).future, ); @@ -117,10 +121,14 @@ class UnifiedPreferenceSettingsRepository ), }; - await ref.read(_preferenceRepositoryProvider.notifier).applyPrefs(prefs); + await preferenceRepository.applyPrefs(prefs); } Future reset() async { + final preferenceRepository = ref.read( + _preferenceRepositoryProvider.notifier, + ); + _statelessGroups = await ref.read( _preferenceSettingGroupsProvider(partition).future, ); @@ -130,7 +138,7 @@ class UnifiedPreferenceSettingsRepository .flattened .toList(); - await ref.read(_preferenceRepositoryProvider.notifier).resetPrefs(prefs); + await preferenceRepository.resetPrefs(prefs); } @override @@ -167,6 +175,10 @@ class PreferenceSettingsGroupRepository PreferenceSettingGroup? _statelessSettingGroup; Future apply({List? filter}) async { + final preferenceRepository = ref.read( + _preferenceRepositoryProvider.notifier, + ); + _statelessSettingGroup ??= await ref.read( _preferenceSettingGroupProvider(partition, groupName).future, ); @@ -184,10 +196,14 @@ class PreferenceSettingsGroupRepository .map((e) => MapEntry(e.key, e.value.value)), ); - await ref.read(_preferenceRepositoryProvider.notifier).applyPrefs(prefs); + await preferenceRepository.applyPrefs(prefs); } Future reset({List? filter}) async { + final preferenceRepository = ref.read( + _preferenceRepositoryProvider.notifier, + ); + _statelessSettingGroup ??= await ref.read( _preferenceSettingGroupProvider(partition, groupName).future, ); @@ -199,9 +215,9 @@ class PreferenceSettingsGroupRepository throw Exception('Preference not part of group'); } - await ref - .read(_preferenceRepositoryProvider.notifier) - .resetPrefs(filter ?? _statelessSettingGroup!.settings.keys.toList()); + await preferenceRepository.resetPrefs( + filter ?? _statelessSettingGroup!.settings.keys.toList(), + ); } @override diff --git a/app/lib/features/geckoview/features/preferences/data/repositories/preference_settings.g.dart b/app/lib/features/geckoview/features/preferences/data/repositories/preference_settings.g.dart index abc84a79..ceab515b 100644 --- a/app/lib/features/geckoview/features/preferences/data/repositories/preference_settings.g.dart +++ b/app/lib/features/geckoview/features/preferences/data/repositories/preference_settings.g.dart @@ -193,7 +193,7 @@ final class _PreferenceSettingGroupProvider } String _$_preferenceSettingGroupHash() => - r'64d80a37928d7e5aea7d3d567dde8ade7292cd5f'; + r'df85cf2207411a89b4c379e24989857f81d04011'; final class _PreferenceSettingGroupFamily extends $Family with @@ -341,7 +341,7 @@ final class UnifiedPreferenceSettingsRepositoryProvider } String _$unifiedPreferenceSettingsRepositoryHash() => - r'35aa16ffa7aa1453c8331ed7470ef85a68d27178'; + r'23c0da1fdc975bbfb88b3cf82f242dbe0d50cd87'; final class UnifiedPreferenceSettingsRepositoryFamily extends $Family with @@ -455,7 +455,7 @@ final class PreferenceSettingsGroupRepositoryProvider } String _$preferenceSettingsGroupRepositoryHash() => - r'60f416ffe1cde4d535fb5b643a80aead20836bae'; + r'05db908036ffa999886f4e9dc4429aa85f8957f9'; final class PreferenceSettingsGroupRepositoryFamily extends $Family with diff --git a/app/lib/features/geckoview/features/tabs/domain/providers/selected_container.dart b/app/lib/features/geckoview/features/tabs/domain/providers/selected_container.dart index 0c43e6f3..d43aca01 100644 --- a/app/lib/features/geckoview/features/tabs/domain/providers/selected_container.dart +++ b/app/lib/features/geckoview/features/tabs/domain/providers/selected_container.dart @@ -37,7 +37,7 @@ enum SetContainerResult { failed, success, successHasProxy } class SelectedContainer extends _$SelectedContainer { Future fetchData() async { if (state != null) { - return ref + return await ref .read(containerRepositoryProvider.notifier) .getContainerData(state!); } @@ -72,7 +72,7 @@ class SelectedContainer extends _$SelectedContainer { .read(containerRepositoryProvider.notifier) .getContainerData(id); - if (container != null) { + if (ref.mounted && container != null) { final passAuth = await authenticateContainer(container); if (passAuth) { if (container.metadata.useProxy) { @@ -127,7 +127,7 @@ class SelectedContainer extends _$SelectedContainer { .read(tabDataRepositoryProvider.notifier) .getContainerTabId(next); - if (tabContainerId != stateOrNull) { + if (ref.mounted && tabContainerId != stateOrNull) { if (tabContainerId != null) { await setContainerId(tabContainerId); } else { diff --git a/app/lib/features/geckoview/features/tabs/domain/providers/selected_container.g.dart b/app/lib/features/geckoview/features/tabs/domain/providers/selected_container.g.dart index 82d555fe..a5425339 100644 --- a/app/lib/features/geckoview/features/tabs/domain/providers/selected_container.g.dart +++ b/app/lib/features/geckoview/features/tabs/domain/providers/selected_container.g.dart @@ -41,7 +41,7 @@ final class SelectedContainerProvider } } -String _$selectedContainerHash() => r'94d68a5b8f2746166ab2269afb6cd50c7c7599bf'; +String _$selectedContainerHash() => r'4754aa8ad9b43b022821a41771eb5af5e33b1cb6'; abstract class _$SelectedContainer extends $Notifier { String? build(); diff --git a/app/lib/features/geckoview/features/tabs/domain/repositories/gecko_inference.dart b/app/lib/features/geckoview/features/tabs/domain/repositories/gecko_inference.dart index 8a680a38..81d635ee 100644 --- a/app/lib/features/geckoview/features/tabs/domain/repositories/gecko_inference.dart +++ b/app/lib/features/geckoview/features/tabs/domain/repositories/gecko_inference.dart @@ -249,11 +249,13 @@ Future containerTopic(Ref ref, String containerId) async { ), ); + if (!ref.mounted) return null; + final topic = await ref .read(geckoInferenceRepositoryProvider.notifier) .predictDocumentTopic(titles.value); - if (topic.isNotEmpty) { + if (ref.mounted && topic.isNotEmpty) { ref.keepAlive(); } @@ -274,7 +276,7 @@ Future?> suggestClusters(Ref ref) async { ), ); - if (unassignedTitles.value.isNotEmpty) { + if (ref.mounted && unassignedTitles.value.isNotEmpty) { return await ref .read(geckoInferenceRepositoryProvider.notifier) .suggestClusters(unassignedDocumentsInput: unassignedTitles.value); @@ -294,6 +296,8 @@ Future?> containerTabSuggestions( final container = await ref.watch(containerDataProvider(containerId).future); + if (!ref.mounted) return null; + final assignedTitles = await ref.watch( containerTabsDataProvider(containerId).selectAsync( (tabData) => EquatableValue( @@ -305,6 +309,8 @@ Future?> containerTabSuggestions( ), ); + if (!ref.mounted) return null; + final unassignedTitles = await ref.watch( containerTabsDataProvider(null).selectAsync( (tabData) => EquatableValue( @@ -316,7 +322,9 @@ Future?> containerTabSuggestions( ), ); - if (assignedTitles.value.isNotEmpty && unassignedTitles.value.isNotEmpty) { + if (ref.mounted && + assignedTitles.value.isNotEmpty && + unassignedTitles.value.isNotEmpty) { final topic = container?.name ?? await ref @@ -325,7 +333,7 @@ Future?> containerTabSuggestions( assignedTitles.value.map((tab) => tab.$2).toSet(), ); - if (topic != null) { + if (ref.mounted && topic != null) { final suggestedTitles = await ref .read(geckoInferenceRepositoryProvider.notifier) .suggestDocuments( diff --git a/app/lib/features/geckoview/features/tabs/domain/repositories/gecko_inference.g.dart b/app/lib/features/geckoview/features/tabs/domain/repositories/gecko_inference.g.dart index 93a7eb5c..97704b85 100644 --- a/app/lib/features/geckoview/features/tabs/domain/repositories/gecko_inference.g.dart +++ b/app/lib/features/geckoview/features/tabs/domain/repositories/gecko_inference.g.dart @@ -112,7 +112,7 @@ final class ContainerTopicProvider } } -String _$containerTopicHash() => r'dd2af0571a84f9cc2536af6a1079e7ee58e2a0a5'; +String _$containerTopicHash() => r'ddb306605a0e38b1d750bf4412cbd595f8f264cc'; final class ContainerTopicFamily extends $Family with $FunctionalFamilyOverride, String> { @@ -171,7 +171,7 @@ final class SuggestClustersProvider } } -String _$suggestClustersHash() => r'3b7da171b3596f708a8039658578251ae61655ea'; +String _$suggestClustersHash() => r'694b401ddd6ce68084f79883e67fda4b44607ef0'; @ProviderFor(containerTabSuggestions) const containerTabSuggestionsProvider = ContainerTabSuggestionsFamily._(); @@ -230,7 +230,7 @@ final class ContainerTabSuggestionsProvider } String _$containerTabSuggestionsHash() => - r'ab8e596f0c7e8562bf998c701145e48eb1e520d5'; + r'9e7e9b9d245959fcf8c87cb8822313ded801ebc0'; final class ContainerTabSuggestionsFamily extends $Family with $FunctionalFamilyOverride?>, String?> { diff --git a/app/lib/features/tor/domain/services/tor_proxy.dart b/app/lib/features/tor/domain/services/tor_proxy.dart index 7c19133e..3608e83c 100644 --- a/app/lib/features/tor/domain/services/tor_proxy.dart +++ b/app/lib/features/tor/domain/services/tor_proxy.dart @@ -247,6 +247,8 @@ class TorProxyService extends _$TorProxyService { await _tor.initializeService(); + if (!ref.mounted) return null; + ref.listen( fireImmediately: true, browserViewLifecycleProvider, diff --git a/app/lib/features/tor/domain/services/tor_proxy.g.dart b/app/lib/features/tor/domain/services/tor_proxy.g.dart index 4f288da4..7a88bdaf 100644 --- a/app/lib/features/tor/domain/services/tor_proxy.g.dart +++ b/app/lib/features/tor/domain/services/tor_proxy.g.dart @@ -33,7 +33,7 @@ final class TorProxyServiceProvider TorProxyService create() => TorProxyService(); } -String _$torProxyServiceHash() => r'82b4964ddf14d02893ebbea3b25d91216359ba10'; +String _$torProxyServiceHash() => r'21592493593c7c2a6cf1ac8311526a7fd6114b98'; abstract class _$TorProxyService extends $AsyncNotifier { FutureOr build(); diff --git a/app/lib/features/user/domain/repositories/engine_settings.dart b/app/lib/features/user/domain/repositories/engine_settings.dart index e628cc95..4d5611fa 100644 --- a/app/lib/features/user/domain/repositories/engine_settings.dart +++ b/app/lib/features/user/domain/repositories/engine_settings.dart @@ -104,18 +104,17 @@ class EngineSettingsRepository extends _$EngineSettingsRepository { Future updateSettings( UpdateEngineSettingsFunc updateWithCurrent, ) async { + final db = ref.read(userDatabaseProvider); + final current = await fetchSettings(); final oldJson = current.toJson(); final newJson = updateWithCurrent(current).toJson(); - return ref.read(userDatabaseProvider).transaction(() async { + return db.transaction(() async { for (final MapEntry(:key, :value) in newJson.entries) { if (oldJson[key] != value) { - await ref - .read(userDatabaseProvider) - .settingDao - .updateSetting(key, _partitionKey, value); + await db.settingDao.updateSetting(key, _partitionKey, value); } } }); diff --git a/app/lib/features/user/domain/repositories/engine_settings.g.dart b/app/lib/features/user/domain/repositories/engine_settings.g.dart index fa9804af..da3b7998 100644 --- a/app/lib/features/user/domain/repositories/engine_settings.g.dart +++ b/app/lib/features/user/domain/repositories/engine_settings.g.dart @@ -34,7 +34,7 @@ final class EngineSettingsRepositoryProvider } String _$engineSettingsRepositoryHash() => - r'8cf0a615f825ddc6411c2985d2cdc19ef31251cb'; + r'f5e50bbfc707cdae698ac201d42e165bffc7615f'; abstract class _$EngineSettingsRepository extends $StreamNotifier { diff --git a/app/lib/features/user/domain/repositories/general_settings.dart b/app/lib/features/user/domain/repositories/general_settings.dart index b328e8cb..f3028f77 100644 --- a/app/lib/features/user/domain/repositories/general_settings.dart +++ b/app/lib/features/user/domain/repositories/general_settings.dart @@ -116,13 +116,13 @@ class GeneralSettingsRepository extends _$GeneralSettingsRepository { Future updateSettings( UpdateGeneralSettingsFunc updateWithCurrent, ) async { + final db = ref.read(userDatabaseProvider); + final current = await fetchSettings(); final oldJson = current.toJson(); final newJson = updateWithCurrent(current).toJson(); - final db = ref.read(userDatabaseProvider); - return db.transaction(() async { for (final MapEntry(:key, :value) in newJson.entries) { if (oldJson[key] != value) { diff --git a/app/lib/features/user/domain/repositories/general_settings.g.dart b/app/lib/features/user/domain/repositories/general_settings.g.dart index 167af782..d29a2fef 100644 --- a/app/lib/features/user/domain/repositories/general_settings.g.dart +++ b/app/lib/features/user/domain/repositories/general_settings.g.dart @@ -35,7 +35,7 @@ final class GeneralSettingsRepositoryProvider } String _$generalSettingsRepositoryHash() => - r'3e2a07b8956094cd9376a254d9aedaa80a3c45c4'; + r'a9b21f9c5ef50bb8a8761995ed2fea723375b80e'; abstract class _$GeneralSettingsRepository extends $StreamNotifier { diff --git a/app/lib/features/user/domain/repositories/tor_settings.dart b/app/lib/features/user/domain/repositories/tor_settings.dart index 52c8d742..438d3748 100644 --- a/app/lib/features/user/domain/repositories/tor_settings.dart +++ b/app/lib/features/user/domain/repositories/tor_settings.dart @@ -69,13 +69,13 @@ class TorSettingsRepository extends _$TorSettingsRepository { } Future updateSettings(UpdateTorSettingsFunc updateWithCurrent) async { + final db = ref.read(userDatabaseProvider); + final current = await fetchSettings(); final oldJson = current.toJson(); final newJson = updateWithCurrent(current).toJson(); - final db = ref.read(userDatabaseProvider); - return db.transaction(() async { for (final MapEntry(:key, :value) in newJson.entries) { if (oldJson[key] != value) { diff --git a/app/lib/features/user/domain/repositories/tor_settings.g.dart b/app/lib/features/user/domain/repositories/tor_settings.g.dart index 6e15e24a..f8a4b346 100644 --- a/app/lib/features/user/domain/repositories/tor_settings.g.dart +++ b/app/lib/features/user/domain/repositories/tor_settings.g.dart @@ -34,7 +34,7 @@ final class TorSettingsRepositoryProvider } String _$torSettingsRepositoryHash() => - r'be8519d4baf60436cae422813c2f2bbb5c2186d3'; + r'341730ed58b49ab3d721583e0f2d5ac650018918'; abstract class _$TorSettingsRepository extends $StreamNotifier { Stream build(); diff --git a/app/lib/features/web_feed/presentation/controllers/fetch_articles.dart b/app/lib/features/web_feed/presentation/controllers/fetch_articles.dart index f4ae86d4..8b57df1f 100644 --- a/app/lib/features/web_feed/presentation/controllers/fetch_articles.dart +++ b/app/lib/features/web_feed/presentation/controllers/fetch_articles.dart @@ -29,24 +29,19 @@ class FetchArticlesController extends _$FetchArticlesController { Future fetchAllArticles() async { state = const AsyncLoading(); state = await AsyncValue.guard(() async { - final feeds = await ref - .read(feedRepositoryProvider.notifier) - .getAllFeeds(); + final feedRepository = ref.read(feedRepositoryProvider.notifier); + + final feeds = await feedRepository.getAllFeeds(); await Future.wait( feeds.map((feed) async { try { - final result = await ref - .read(feedReaderProvider.notifier) - .parseFeed(feed.url); + final feedReader = ref.read(feedReaderProvider.notifier); - await ref - .read(feedRepositoryProvider.notifier) - .upsertArticles(result.articleData); + final result = await feedReader.parseFeed(feed.url); - await ref - .read(feedRepositoryProvider.notifier) - .touchFeedFetched(feed.url); + await feedRepository.upsertArticles(result.articleData); + await feedRepository.touchFeedFetched(feed.url); } catch (e, s) { logger.e( 'Failed fetching feed ${feed.url}', @@ -62,13 +57,12 @@ class FetchArticlesController extends _$FetchArticlesController { Future fetchFeedArticles(Uri uri) async { state = const AsyncLoading(); state = await AsyncValue.guard(() async { + final feedRepository = ref.read(feedRepositoryProvider.notifier); + final result = await ref.read(feedReaderProvider.notifier).parseFeed(uri); - await ref - .read(feedRepositoryProvider.notifier) - .upsertArticles(result.articleData); - - await ref.read(feedRepositoryProvider.notifier).touchFeedFetched(uri); + await feedRepository.upsertArticles(result.articleData); + await feedRepository.touchFeedFetched(uri); }); } diff --git a/app/lib/features/web_feed/presentation/controllers/fetch_articles.g.dart b/app/lib/features/web_feed/presentation/controllers/fetch_articles.g.dart index 5c38ac66..976f931b 100644 --- a/app/lib/features/web_feed/presentation/controllers/fetch_articles.g.dart +++ b/app/lib/features/web_feed/presentation/controllers/fetch_articles.g.dart @@ -42,7 +42,7 @@ final class FetchArticlesControllerProvider } String _$fetchArticlesControllerHash() => - r'c198a1c1200aaeb6095fbc6ebe41b3069f1de7cc'; + r'5dcb9de003bc911d365c6a8ef107bf1bf446755b'; abstract class _$FetchArticlesController extends $Notifier> { AsyncValue build();