provider lifecycle hardenings
This commit is contained in:
@@ -60,7 +60,7 @@ class AppInitializationService extends _$AppInitializationService {
|
||||
}
|
||||
|
||||
Future<void> initialize() async {
|
||||
state = await Result.fromAsync(() async {
|
||||
final result = await Result.fromAsync(() async {
|
||||
final errors = <ErrorMessage>[];
|
||||
|
||||
await ref.read(formatProvider.future);
|
||||
@@ -80,6 +80,12 @@ class AppInitializationService extends _$AppInitializationService {
|
||||
|
||||
return (initialized: true, stage: null, errors: errors);
|
||||
});
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = result;
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -54,7 +54,7 @@ final class AppInitializationServiceProvider
|
||||
}
|
||||
|
||||
String _$appInitializationServiceHash() =>
|
||||
r'c26f968d53b4ea18f7be890c9610c9bf9d300322';
|
||||
r'bf4c472d5b0b758d703b8ca40763cf2a59712a4c';
|
||||
|
||||
abstract class _$AppInitializationService
|
||||
extends
|
||||
|
||||
@@ -80,7 +80,14 @@ class AddonDetails extends _$AddonDetails {
|
||||
|
||||
Future<void> _run(Future<AddonInfo?> Function() action) async {
|
||||
state = const AsyncLoading<AddonInfo?>();
|
||||
state = await AsyncValue.guard(action);
|
||||
|
||||
final result = await AsyncValue.guard(action);
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = result;
|
||||
|
||||
ref.invalidate(addonListProvider);
|
||||
}
|
||||
@@ -239,6 +246,10 @@ class AddonUpdateCheck extends _$AddonUpdateCheck {
|
||||
: AddonUpdateRunDone(attempt?.message);
|
||||
});
|
||||
|
||||
if (!ref.mounted) {
|
||||
return result.value ?? const AddonUpdateRunFailed();
|
||||
}
|
||||
|
||||
state = result;
|
||||
ref.invalidate(addonDetailsProvider(addonId));
|
||||
ref.invalidate(lastAddonUpdateAttemptProvider(addonId));
|
||||
@@ -261,26 +272,40 @@ class AddonList extends _$AddonList {
|
||||
}
|
||||
|
||||
Future<void> install(AddonInfo addon) async {
|
||||
ref.read(addonBusyIdsProvider.notifier).add(addon.id);
|
||||
final busyIds = ref.read(addonBusyIdsProvider.notifier);
|
||||
busyIds.add(addon.id);
|
||||
|
||||
try {
|
||||
await _service.installAddon(Uri.parse(addon.downloadUrl));
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
ref.invalidate(addonDetailsProvider(addon.id));
|
||||
ref.invalidateSelf();
|
||||
await future;
|
||||
} finally {
|
||||
ref.read(addonBusyIdsProvider.notifier).remove(addon.id);
|
||||
busyIds.remove(addon.id);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> uninstall(AddonInfo addon) async {
|
||||
ref.read(addonBusyIdsProvider.notifier).add(addon.id);
|
||||
final busyIds = ref.read(addonBusyIdsProvider.notifier);
|
||||
busyIds.add(addon.id);
|
||||
|
||||
try {
|
||||
await _service.uninstallAddon(addon.id);
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
ref.invalidate(addonDetailsProvider(addon.id));
|
||||
ref.invalidateSelf();
|
||||
await future;
|
||||
} finally {
|
||||
ref.read(addonBusyIdsProvider.notifier).remove(addon.id);
|
||||
busyIds.remove(addon.id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,8 +317,15 @@ class AddonList extends _$AddonList {
|
||||
|
||||
@Riverpod()
|
||||
class AddonBusyIds extends _$AddonBusyIds {
|
||||
void add(String id) => state = {...state, id};
|
||||
void remove(String id) => state = {...state}..remove(id);
|
||||
void add(String id) {
|
||||
if (!ref.mounted) return;
|
||||
state = {...state, id};
|
||||
}
|
||||
|
||||
void remove(String id) {
|
||||
if (!ref.mounted) return;
|
||||
state = {...state}..remove(id);
|
||||
}
|
||||
|
||||
@override
|
||||
Set<String> build() => const {};
|
||||
@@ -329,9 +361,16 @@ class PinnedAddonIds extends _$PinnedAddonIds {
|
||||
class BulkAddonUpdate extends _$BulkAddonUpdate {
|
||||
Future<void> triggerAll() async {
|
||||
state = const AsyncLoading();
|
||||
state = await AsyncValue.guard(() async {
|
||||
|
||||
final result = await AsyncValue.guard(() async {
|
||||
await ref.read(addonServiceProvider).triggerAllAddonUpdates();
|
||||
});
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = result;
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -50,7 +50,7 @@ final class AddonDetailsProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$addonDetailsHash() => r'26b4a33e9d17aced1d3fb5c6ff28921f611ca5b0';
|
||||
String _$addonDetailsHash() => r'b8b7b0620d618488227fb6b8ba889279b933b707';
|
||||
|
||||
final class AddonDetailsFamily extends $Family
|
||||
with
|
||||
@@ -658,7 +658,7 @@ final class AddonUpdateCheckProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$addonUpdateCheckHash() => r'4ef375b5cd9b0eb89fbbdaff3f93a35482191af5';
|
||||
String _$addonUpdateCheckHash() => r'496cf9756101c9c36fa4b90f1fd92627aee92177';
|
||||
|
||||
final class AddonUpdateCheckFamily extends $Family
|
||||
with
|
||||
@@ -739,7 +739,7 @@ final class AddonListProvider
|
||||
AddonList create() => AddonList();
|
||||
}
|
||||
|
||||
String _$addonListHash() => r'7625b69a433d073e186571453e39b557d8b48a5d';
|
||||
String _$addonListHash() => r'1e60b0b04702e6ed6143ccf19d9e4140d1a1deec';
|
||||
|
||||
abstract class _$AddonList extends $AsyncNotifier<List<AddonInfo>> {
|
||||
FutureOr<List<AddonInfo>> build();
|
||||
@@ -791,7 +791,7 @@ final class AddonBusyIdsProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$addonBusyIdsHash() => r'6f9761320d42b2b5132936797617fdb13b718dd3';
|
||||
String _$addonBusyIdsHash() => r'aac8fd8784ba296129ffdb17c2d1355c1546140f';
|
||||
|
||||
abstract class _$AddonBusyIds extends $Notifier<Set<String>> {
|
||||
Set<String> build();
|
||||
@@ -895,7 +895,7 @@ final class BulkAddonUpdateProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$bulkAddonUpdateHash() => r'2605711734f9eb6af70e721a4337556a7ea85512';
|
||||
String _$bulkAddonUpdateHash() => r'ec3cdc136c0ad4a6687516bf14912fd5b96b11b4';
|
||||
|
||||
abstract class _$BulkAddonUpdate extends $Notifier<AsyncValue<void>> {
|
||||
AsyncValue<void> build();
|
||||
|
||||
@@ -39,6 +39,10 @@ class WebExtensionsState extends _$WebExtensionsState {
|
||||
: _imageCache = LRUCache(50, onEvict: (image) => image.dispose());
|
||||
|
||||
void _onExtensionUpdate(ExtensionDataEvent event) {
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ExtensionDataEvent(:extensionId, :data) = event;
|
||||
|
||||
if (data != null) {
|
||||
@@ -81,6 +85,11 @@ class WebExtensionsState extends _$WebExtensionsState {
|
||||
|
||||
final image = await tryDecodeImage(bytes);
|
||||
|
||||
if (!ref.mounted) {
|
||||
image?.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (image != null) {
|
||||
// set() will evict the old entry via onEvict callback, which handles disposal
|
||||
_imageCache.set(extensionId, image);
|
||||
@@ -185,13 +194,13 @@ class WebExtensionsState extends _$WebExtensionsState {
|
||||
},
|
||||
);
|
||||
|
||||
ref.onDispose(() async {
|
||||
ref.onDispose(() {
|
||||
// Dispose all cached images
|
||||
_imageCache.clear();
|
||||
|
||||
// Cancel all stream subscriptions
|
||||
for (final sub in subscriptions) {
|
||||
await sub.cancel();
|
||||
unawaited(sub.cancel());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ final class WebExtensionsStateProvider
|
||||
}
|
||||
|
||||
String _$webExtensionsStateHash() =>
|
||||
r'13cbbea409b5b643eb6766689f6b23a4d1701204';
|
||||
r'e067323e9a0a466e46e0c4d529667950ee62d4ca';
|
||||
|
||||
final class WebExtensionsStateFamily extends $Family
|
||||
with
|
||||
|
||||
@@ -784,8 +784,9 @@ class TabRepository extends _$TabRepository {
|
||||
|
||||
final containerSiteAssignementSub = eventSerivce.siteAssignementEvent.listen(
|
||||
(event) async {
|
||||
if (event.tabId != null) {
|
||||
final tabState = ref.read(tabStatesProvider)[event.tabId];
|
||||
final tabId = event.tabId;
|
||||
if (tabId != null) {
|
||||
final tabState = ref.read(tabStatesProvider)[tabId];
|
||||
if (tabState != null) {
|
||||
final uri = Uri.parse(event.url);
|
||||
final originUri = event.originUrl.mapNotNull(Uri.parse);
|
||||
@@ -793,52 +794,81 @@ class TabRepository extends _$TabRepository {
|
||||
final targetContainerId = await ref
|
||||
.read(containerRepositoryProvider.notifier)
|
||||
.siteAssignedContainerId(Uri.parse(uri.origin));
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final containerData = await targetContainerId.mapNotNull(
|
||||
(id) => ref
|
||||
.read(containerRepositoryProvider.notifier)
|
||||
.getContainerData(id),
|
||||
);
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (containerData != null) {
|
||||
final currentTabState = ref.read(tabStatesProvider)[tabId];
|
||||
if (currentTabState == null) {
|
||||
logger.w('Could not get tab for assignement ${event.url}');
|
||||
return;
|
||||
}
|
||||
|
||||
final tabIsEmpty =
|
||||
tabState.url == TabState.defaultUrl &&
|
||||
tabState.historyState.items.isEmpty;
|
||||
currentTabState.url == TabState.defaultUrl &&
|
||||
currentTabState.historyState.items.isEmpty;
|
||||
|
||||
if (event.blocked || tabIsEmpty) {
|
||||
await addTab(
|
||||
url: uri,
|
||||
tabMode: tabState.tabMode,
|
||||
tabMode: currentTabState.tabMode,
|
||||
containerSelection: TabContainerSelection.specific(
|
||||
containerData,
|
||||
),
|
||||
parentId: tabState.id,
|
||||
parentId: currentTabState.id,
|
||||
selectTab: true,
|
||||
);
|
||||
|
||||
if (tabState.historyState.items.isEmpty) {
|
||||
await closeTab(tabState.id);
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTabState.historyState.items.isEmpty) {
|
||||
await closeTab(currentTabState.id);
|
||||
}
|
||||
} else {
|
||||
final tabContainerId = await ref
|
||||
.read(tabDataRepositoryProvider.notifier)
|
||||
.getTabContainerId(tabState.id);
|
||||
.getTabContainerId(currentTabState.id);
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final latestTabState = ref.read(tabStatesProvider)[tabId];
|
||||
if (latestTabState == null) {
|
||||
logger.w('Could not get tab for assignement ${event.url}');
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetContainerId != tabContainerId) {
|
||||
if (originUri == null) {
|
||||
await ref
|
||||
.read(tabDataRepositoryProvider.notifier)
|
||||
.assignContainer(tabState.id, containerData);
|
||||
} else if (tabState.url == originUri) {
|
||||
.assignContainer(latestTabState.id, containerData);
|
||||
} else if (latestTabState.url == originUri) {
|
||||
await ref
|
||||
.read(tabDataRepositoryProvider.notifier)
|
||||
.assignContainer(
|
||||
tabState.id,
|
||||
latestTabState.id,
|
||||
containerData,
|
||||
closeOldTab: false,
|
||||
);
|
||||
} else {
|
||||
logger.w(
|
||||
'Could not match origin url for assignment ${tabState.url} to request ${event.originUrl}',
|
||||
'Could not match origin url for assignment ${latestTabState.url} to request ${event.originUrl}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ final class TabRepositoryProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$tabRepositoryHash() => r'a68941d373f348201e3d8b1cab26343acca3852f';
|
||||
String _$tabRepositoryHash() => r'f458baaf9061143a668470dccd57f32664728951';
|
||||
|
||||
abstract class _$TabRepository extends $Notifier<void> {
|
||||
void build();
|
||||
|
||||
+11
-3
@@ -42,20 +42,24 @@ class AllowUnsignedExtensions extends _$AllowUnsignedExtensions {
|
||||
await fixator.unregister(_signatureRequiredPref);
|
||||
await GeckoPrefService().applyPrefs({_signatureRequiredPref: true});
|
||||
}
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = AsyncData(allow);
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<bool> build() async {
|
||||
final fixator = ref.read(preferenceFixatorProvider.notifier);
|
||||
final prefs = await GeckoPrefService().getPrefs([_signatureRequiredPref]);
|
||||
final pref = prefs[_signatureRequiredPref];
|
||||
final allowUnsigned = pref?.value == false;
|
||||
|
||||
// Re-register with fixator to prevent Gecko from resetting
|
||||
if (allowUnsigned) {
|
||||
await ref
|
||||
.read(preferenceFixatorProvider.notifier)
|
||||
.register(_signatureRequiredPref, false);
|
||||
await fixator.register(_signatureRequiredPref, false);
|
||||
}
|
||||
|
||||
return allowUnsigned;
|
||||
@@ -68,6 +72,10 @@ class AddonAutoUpdate extends _$AddonAutoUpdate {
|
||||
final service = ref.read(addonServiceProvider);
|
||||
await service.setAddonAutoUpdateEnabled(enabled: enabled);
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = AsyncData(enabled);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -34,7 +34,7 @@ final class AllowUnsignedExtensionsProvider
|
||||
}
|
||||
|
||||
String _$allowUnsignedExtensionsHash() =>
|
||||
r'3b67f51cabf8e2f37d992320c5b93bb61c6dbe1f';
|
||||
r'ba282219edc9149da886371d873d2a5ee0dfb6dd';
|
||||
|
||||
abstract class _$AllowUnsignedExtensions extends $AsyncNotifier<bool> {
|
||||
FutureOr<bool> build();
|
||||
@@ -78,7 +78,7 @@ final class AddonAutoUpdateProvider
|
||||
AddonAutoUpdate create() => AddonAutoUpdate();
|
||||
}
|
||||
|
||||
String _$addonAutoUpdateHash() => r'89791e8b771da715b068bbdbe5c3c24a3dad4194';
|
||||
String _$addonAutoUpdateHash() => r'0a2661316d1d1345e81df2552925eda3c2bf6ec1';
|
||||
|
||||
abstract class _$AddonAutoUpdate extends $AsyncNotifier<bool> {
|
||||
FutureOr<bool> build();
|
||||
|
||||
+7
-2
@@ -31,11 +31,16 @@ class PreferenceChangeListener extends _$PreferenceChangeListener {
|
||||
Stream<GeckoPref> build() async* {
|
||||
final events = ref.watch(eventServiceProvider);
|
||||
|
||||
ref.onDispose(() {
|
||||
unawaited(GeckoPrefService().stopObserveChanges());
|
||||
});
|
||||
|
||||
await GeckoPrefService().startObserveChanges();
|
||||
|
||||
ref.onDispose(() async {
|
||||
if (!ref.mounted) {
|
||||
await GeckoPrefService().stopObserveChanges();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
yield* events.prefUpdateEvent;
|
||||
}
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ final class PreferenceChangeListenerProvider
|
||||
}
|
||||
|
||||
String _$preferenceChangeListenerHash() =>
|
||||
r'de9759b32a6a6b9bab5656137a365da78633f866';
|
||||
r'baf2abe1948998a043a8473547a225582dbc8c7b';
|
||||
|
||||
abstract class _$PreferenceChangeListener extends $StreamNotifier<GeckoPref> {
|
||||
Stream<GeckoPref> build();
|
||||
|
||||
+35
-27
@@ -243,8 +243,8 @@ class _PreferenceRepository extends _$PreferenceRepository {
|
||||
|
||||
_prefSubject = BehaviorSubject<Map<String, GeckoPref>>();
|
||||
|
||||
ref.onDispose(() async {
|
||||
await _prefSubject.close();
|
||||
ref.onDispose(() {
|
||||
unawaited(_prefSubject.close());
|
||||
});
|
||||
|
||||
ref.onAddListener(() {
|
||||
@@ -260,19 +260,21 @@ class _PreferenceRepository extends _$PreferenceRepository {
|
||||
@Riverpod()
|
||||
class UnifiedPreferenceSettingsRepository
|
||||
extends _$UnifiedPreferenceSettingsRepository {
|
||||
Map<String, PreferenceSettingGroup>? _statelessGroups;
|
||||
|
||||
Future<void> apply() async {
|
||||
final preferenceRepository = ref.read(
|
||||
_preferenceRepositoryProvider(partition).notifier,
|
||||
);
|
||||
|
||||
_statelessGroups = await ref.read(
|
||||
final groups = await ref.read(
|
||||
_preferenceSettingGroupsProvider(partition).future,
|
||||
);
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final prefs = {
|
||||
for (final group in _statelessGroups!.values)
|
||||
for (final group in groups.values)
|
||||
...Map.fromEntries(
|
||||
group.settings.entries
|
||||
.where((e) => !e.value.requireUserOptIn)
|
||||
@@ -288,11 +290,15 @@ class UnifiedPreferenceSettingsRepository
|
||||
_preferenceRepositoryProvider(partition).notifier,
|
||||
);
|
||||
|
||||
_statelessGroups = await ref.read(
|
||||
final groups = await ref.read(
|
||||
_preferenceSettingGroupsProvider(partition).future,
|
||||
);
|
||||
|
||||
final prefs = _statelessGroups!.values
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final prefs = groups.values
|
||||
.map((group) => group.settings.keys)
|
||||
.flattened
|
||||
.toList();
|
||||
@@ -304,14 +310,13 @@ class UnifiedPreferenceSettingsRepository
|
||||
Stream<Map<String, PreferenceSettingGroup>> build(
|
||||
PreferencePartition partition,
|
||||
) async* {
|
||||
_statelessGroups = await ref.watch(
|
||||
final prefStream = ref.watch(_preferenceRepositoryProvider(partition));
|
||||
final groups = await ref.watch(
|
||||
_preferenceSettingGroupsProvider(partition).future,
|
||||
);
|
||||
|
||||
final prefStream = ref.watch(_preferenceRepositoryProvider(partition));
|
||||
|
||||
yield* prefStream.map(
|
||||
(prefs) => _statelessGroups!.map(
|
||||
(prefs) => groups.map(
|
||||
(groupName, group) => MapEntry(
|
||||
groupName,
|
||||
group.copyWith.settings(
|
||||
@@ -329,26 +334,28 @@ class UnifiedPreferenceSettingsRepository
|
||||
@Riverpod()
|
||||
class PreferenceSettingsGroupRepository
|
||||
extends _$PreferenceSettingsGroupRepository {
|
||||
PreferenceSettingGroup? _statelessSettingGroup;
|
||||
|
||||
Future<void> apply({List<String>? filter}) async {
|
||||
final preferenceRepository = ref.read(
|
||||
_preferenceRepositoryProvider(partition).notifier,
|
||||
);
|
||||
|
||||
_statelessSettingGroup ??= await ref.read(
|
||||
final settingGroup = await ref.read(
|
||||
_preferenceSettingGroupProvider(partition, groupName).future,
|
||||
);
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final prefs = Map.fromEntries(
|
||||
filter?.map(
|
||||
(e) => MapEntry(
|
||||
e,
|
||||
_statelessSettingGroup!.settings[e]?.value ??
|
||||
settingGroup.settings[e]?.value ??
|
||||
(throw Exception('Preference not part of group')),
|
||||
),
|
||||
) ??
|
||||
_statelessSettingGroup!.settings.entries
|
||||
settingGroup.settings.entries
|
||||
.where((e) => !e.value.requireUserOptIn)
|
||||
.map((e) => MapEntry(e.key, e.value.value)),
|
||||
);
|
||||
@@ -361,19 +368,21 @@ class PreferenceSettingsGroupRepository
|
||||
_preferenceRepositoryProvider(partition).notifier,
|
||||
);
|
||||
|
||||
_statelessSettingGroup ??= await ref.read(
|
||||
final settingGroup = await ref.read(
|
||||
_preferenceSettingGroupProvider(partition, groupName).future,
|
||||
);
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (filter != null &&
|
||||
filter.any(
|
||||
(value) => !_statelessSettingGroup!.settings.containsKey(value),
|
||||
)) {
|
||||
filter.any((value) => !settingGroup.settings.containsKey(value))) {
|
||||
throw Exception('Preference not part of group');
|
||||
}
|
||||
|
||||
await preferenceRepository.resetPrefs(
|
||||
filter ?? _statelessSettingGroup!.settings.keys.toList(),
|
||||
filter ?? settingGroup.settings.keys.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -382,15 +391,14 @@ class PreferenceSettingsGroupRepository
|
||||
PreferencePartition partition,
|
||||
String groupName,
|
||||
) async* {
|
||||
_statelessSettingGroup = await ref.watch(
|
||||
final prefStream = ref.watch(_preferenceRepositoryProvider(partition));
|
||||
final settingGroup = await ref.watch(
|
||||
_preferenceSettingGroupProvider(partition, groupName).future,
|
||||
);
|
||||
|
||||
final prefStream = ref.watch(_preferenceRepositoryProvider(partition));
|
||||
|
||||
yield* prefStream.map(
|
||||
(prefs) => _statelessSettingGroup!.copyWith.settings(
|
||||
_statelessSettingGroup!.settings.map(
|
||||
(prefs) => settingGroup.copyWith.settings(
|
||||
settingGroup.settings.map(
|
||||
(key, value) => MapEntry(key, value.copyWith.current(prefs[key])),
|
||||
),
|
||||
),
|
||||
|
||||
+3
-3
@@ -334,7 +334,7 @@ final class _PreferenceRepositoryProvider
|
||||
}
|
||||
|
||||
String _$_preferenceRepositoryHash() =>
|
||||
r'c416d7684f1e8f24dd9e5fc98ecb6312c07d938f';
|
||||
r'ca5ccbe1c3f5f1576e3e7ba359c3cd1324281a97';
|
||||
|
||||
final class _PreferenceRepositoryFamily extends $Family
|
||||
with
|
||||
@@ -441,7 +441,7 @@ final class UnifiedPreferenceSettingsRepositoryProvider
|
||||
}
|
||||
|
||||
String _$unifiedPreferenceSettingsRepositoryHash() =>
|
||||
r'03c8c2f247974ff32bba14b4b34857a0f14f6f37';
|
||||
r'c544b5815ec676ddb6cde1ffeb8c9ef4a7dc4469';
|
||||
|
||||
final class UnifiedPreferenceSettingsRepositoryFamily extends $Family
|
||||
with
|
||||
@@ -554,7 +554,7 @@ final class PreferenceSettingsGroupRepositoryProvider
|
||||
}
|
||||
|
||||
String _$preferenceSettingsGroupRepositoryHash() =>
|
||||
r'b5c439643ec78094122c33983e58d0977641832a';
|
||||
r'c8335b39c4c9fa95c4d415231b103a2feff97d26';
|
||||
|
||||
final class PreferenceSettingsGroupRepositoryFamily extends $Family
|
||||
with
|
||||
|
||||
+2
@@ -44,6 +44,7 @@ Future<void> showPwaInstallDialog(BuildContext context, WidgetRef ref) async {
|
||||
url: url,
|
||||
);
|
||||
|
||||
if (!context.mounted) return;
|
||||
if (config == null) return;
|
||||
|
||||
final name = config.name;
|
||||
@@ -106,6 +107,7 @@ Future<void> showShortcutInstallDialog(
|
||||
showAppOption: showAppOption,
|
||||
);
|
||||
|
||||
if (!context.mounted) return;
|
||||
if (config == null) return;
|
||||
|
||||
final name = config.name;
|
||||
|
||||
+9
-1
@@ -34,7 +34,15 @@ class ReaderableScreenController extends _$ReaderableScreenController {
|
||||
final eventChange = ref.read(eventServiceProvider).readerableEvents.first;
|
||||
final toggle = _service.toggleReaderView(enable);
|
||||
|
||||
state = await AsyncValue.guard(() => Future.wait([toggle, eventChange]));
|
||||
final result = await AsyncValue.guard(
|
||||
() => Future.wait([toggle, eventChange]),
|
||||
);
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = result;
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ final class ReaderableScreenControllerProvider
|
||||
}
|
||||
|
||||
String _$readerableScreenControllerHash() =>
|
||||
r'62b2167ff8f9fe21c3cf3339e135a50aa684160c';
|
||||
r'46206cfb431c5d36dc6351a8fc52c3b98b86dd0f';
|
||||
|
||||
abstract class _$ReaderableScreenController extends $AsyncNotifier<void> {
|
||||
FutureOr<void> build();
|
||||
|
||||
+7
-1
@@ -38,7 +38,7 @@ class TabSearchRepository extends _$TabSearchRepository {
|
||||
String ellipsis = '…',
|
||||
}) async {
|
||||
if (input.isNotEmpty) {
|
||||
state = await AsyncValue.guard(() async {
|
||||
final result = await AsyncValue.guard(() async {
|
||||
return (
|
||||
query: input,
|
||||
results: await ref
|
||||
@@ -55,6 +55,12 @@ class TabSearchRepository extends _$TabSearchRepository {
|
||||
.get(),
|
||||
);
|
||||
});
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = result;
|
||||
} else {
|
||||
state = const AsyncValue.data(null);
|
||||
}
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ final class TabSearchRepositoryProvider
|
||||
}
|
||||
|
||||
String _$tabSearchRepositoryHash() =>
|
||||
r'473057d6a9f1e76d6b7fec13f710189d758bc924';
|
||||
r'a05922f7c487105f46abbd272fbc2ed72994c332';
|
||||
|
||||
final class TabSearchRepositoryFamily extends $Family
|
||||
with
|
||||
|
||||
@@ -33,11 +33,18 @@ class SaveGeneralSettingsController extends _$SaveGeneralSettingsController {
|
||||
|
||||
Future<void> save(UpdateGeneralSettingsFunc updateSettings) async {
|
||||
state = const AsyncLoading();
|
||||
state = await AsyncValue.guard(
|
||||
|
||||
final result = await AsyncValue.guard(
|
||||
() => ref
|
||||
.read(generalSettingsRepositoryProvider.notifier)
|
||||
.updateSettings(updateSettings),
|
||||
);
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,11 +57,18 @@ class SaveEngineSettingsController extends _$SaveEngineSettingsController {
|
||||
|
||||
Future<void> save(UpdateEngineSettingsFunc updateSettings) async {
|
||||
state = const AsyncLoading();
|
||||
state = await AsyncValue.guard(
|
||||
|
||||
final result = await AsyncValue.guard(
|
||||
() => ref
|
||||
.read(engineSettingsRepositoryProvider.notifier)
|
||||
.updateSettings(updateSettings),
|
||||
);
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,10 +81,17 @@ class SaveTorSettingsController extends _$SaveTorSettingsController {
|
||||
|
||||
Future<void> save(UpdateTorSettingsFunc updateSettings) async {
|
||||
state = const AsyncLoading();
|
||||
state = await AsyncValue.guard(
|
||||
|
||||
final result = await AsyncValue.guard(
|
||||
() => ref
|
||||
.read(torSettingsRepositoryProvider.notifier)
|
||||
.updateSettings(updateSettings),
|
||||
);
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ final class SaveGeneralSettingsControllerProvider
|
||||
}
|
||||
|
||||
String _$saveGeneralSettingsControllerHash() =>
|
||||
r'b75c9c52452a9cb687f69dad1523f1ed5205847e';
|
||||
r'9a6d663234c1a1750bf90bf29b4664e4d86861c0';
|
||||
|
||||
abstract class _$SaveGeneralSettingsController extends $AsyncNotifier<void> {
|
||||
FutureOr<void> build();
|
||||
@@ -81,7 +81,7 @@ final class SaveEngineSettingsControllerProvider
|
||||
}
|
||||
|
||||
String _$saveEngineSettingsControllerHash() =>
|
||||
r'd3d74a6aadc89532b1d81c424d92efbfa43002d5';
|
||||
r'fbe89c8f9772e50fc8ada3d41a233ba5650a7982';
|
||||
|
||||
abstract class _$SaveEngineSettingsController extends $AsyncNotifier<void> {
|
||||
FutureOr<void> build();
|
||||
@@ -126,7 +126,7 @@ final class SaveTorSettingsControllerProvider
|
||||
}
|
||||
|
||||
String _$saveTorSettingsControllerHash() =>
|
||||
r'd8aa04d7ae60c97bdad6c072f894189509dd35d3';
|
||||
r'bc8bac2f2d777025fa3e2c85badcbc095a9e3ad1';
|
||||
|
||||
abstract class _$SaveTorSettingsController extends $AsyncNotifier<void> {
|
||||
FutureOr<void> build();
|
||||
|
||||
@@ -31,11 +31,9 @@ part 'providers.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
Future<KagiSourceService> kagiSourceService(Ref ref) async {
|
||||
final db = ref.watch(smallWebDatabaseProvider);
|
||||
final categories = await ref.watch(kagiCategoriesProvider.future);
|
||||
return KagiSourceService(
|
||||
ref.watch(smallWebDatabaseProvider),
|
||||
categories.remap,
|
||||
);
|
||||
return KagiSourceService(db, categories.remap);
|
||||
}
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
@@ -45,13 +43,11 @@ WanderSourceService wanderSourceService(Ref ref) {
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
Future<SmallWebDiscoverService> smallWebDiscoverService(Ref ref) async {
|
||||
final db = ref.watch(smallWebDatabaseProvider);
|
||||
final wanderService = ref.watch(wanderSourceServiceProvider);
|
||||
final kagiService = await ref.watch(kagiSourceServiceProvider.future);
|
||||
|
||||
return SmallWebDiscoverService(
|
||||
ref.watch(smallWebDatabaseProvider),
|
||||
kagiService,
|
||||
ref.watch(wanderSourceServiceProvider),
|
||||
);
|
||||
return SmallWebDiscoverService(db, kagiService, wanderService);
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
|
||||
@@ -48,7 +48,7 @@ final class KagiSourceServiceProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$kagiSourceServiceHash() => r'7f0cca556d22cc65356660f3e59c976a35d40d37';
|
||||
String _$kagiSourceServiceHash() => r'5e8aef50353b959d681675feba9eba75bb91bdff';
|
||||
|
||||
@ProviderFor(wanderSourceService)
|
||||
final wanderSourceServiceProvider = WanderSourceServiceProvider._();
|
||||
@@ -138,7 +138,7 @@ final class SmallWebDiscoverServiceProvider
|
||||
}
|
||||
|
||||
String _$smallWebDiscoverServiceHash() =>
|
||||
r'14fba9eb1c2aa51fa1fac2c2c764ea400603e8ca';
|
||||
r'eefefdc1b22c6f7e57e61a0c1dafa2b8080ab150';
|
||||
|
||||
@ProviderFor(smallWebRecentVisits)
|
||||
final smallWebRecentVisitsProvider = SmallWebRecentVisitsFamily._();
|
||||
|
||||
@@ -28,7 +28,8 @@ part 'fetch_articles.g.dart';
|
||||
class FetchArticlesController extends _$FetchArticlesController {
|
||||
Future<void> fetchAllArticles() async {
|
||||
state = const AsyncLoading();
|
||||
state = await AsyncValue.guard(() async {
|
||||
|
||||
final result = await AsyncValue.guard(() async {
|
||||
final feedRepository = ref.read(feedRepositoryProvider.notifier);
|
||||
|
||||
final feeds = await feedRepository.getAllFeeds();
|
||||
@@ -52,11 +53,18 @@ class FetchArticlesController extends _$FetchArticlesController {
|
||||
}).toList(),
|
||||
);
|
||||
});
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = result;
|
||||
}
|
||||
|
||||
Future<void> fetchFeedArticles(Uri uri) async {
|
||||
state = const AsyncLoading();
|
||||
state = await AsyncValue.guard(() async {
|
||||
|
||||
final result = await AsyncValue.guard(() async {
|
||||
final feedRepository = ref.read(feedRepositoryProvider.notifier);
|
||||
|
||||
final result = await ref.read(feedReaderProvider.notifier).parseFeed(uri);
|
||||
@@ -64,6 +72,12 @@ class FetchArticlesController extends _$FetchArticlesController {
|
||||
await feedRepository.upsertArticles(result.articleData);
|
||||
await feedRepository.touchFeedFetched(uri);
|
||||
});
|
||||
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = result;
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -42,7 +42,7 @@ final class FetchArticlesControllerProvider
|
||||
}
|
||||
|
||||
String _$fetchArticlesControllerHash() =>
|
||||
r'5dcb9de003bc911d365c6a8ef107bf1bf446755b';
|
||||
r'b8a1813f3497af731f20a48693b700eb3d9aeceb';
|
||||
|
||||
abstract class _$FetchArticlesController extends $Notifier<AsyncValue<void>> {
|
||||
AsyncValue<void> build();
|
||||
|
||||
Reference in New Issue
Block a user