pref observer and fixator

This commit is contained in:
Fabian Freund
2025-10-19 16:45:56 +02:00
parent 64d588ee3e
commit 73dab11113
16 changed files with 598 additions and 72 deletions
@@ -22,6 +22,7 @@ import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
import 'package:riverpod/riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:weblibre/core/logger.dart';
import 'package:weblibre/features/geckoview/features/preferences/data/repositories/preference_observer.dart';
import 'package:weblibre/features/user/domain/repositories/engine_settings.dart';
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
@@ -134,8 +135,20 @@ class EngineSettingsReplicationService
settings.fingerprintingProtectionOverrides,
);
}
if (previous.value?.enablePdfJs != settings.enablePdfJs) {
// ignore: only_use_keep_alive_inside_keep_alive
await ref
.read(preferenceFixatorProvider.notifier)
.register('pdfjs.disabled', !settings.enablePdfJs);
}
} else {
await _service.setDefaultSettings(settings);
// ignore: only_use_keep_alive_inside_keep_alive
await ref
.read(preferenceFixatorProvider.notifier)
.register('pdfjs.disabled', !settings.enablePdfJs);
initialSettingsSent = true;
}
}
@@ -44,7 +44,7 @@ final class EngineSettingsReplicationServiceProvider
}
String _$engineSettingsReplicationServiceHash() =>
r'3c96e6e45537399582fdf6e8b1fafc44c613b89d';
r'd28cc58a94f45008a478bf52a9c40d61811b591d';
abstract class _$EngineSettingsReplicationService extends $Notifier<void> {
void build();
@@ -44,6 +44,7 @@ import 'package:weblibre/features/geckoview/features/browser/domain/providers/li
import 'package:weblibre/features/geckoview/features/browser/domain/services/browser_data.dart';
import 'package:weblibre/features/geckoview/features/browser/domain/services/engine_settings_replication.dart';
import 'package:weblibre/features/geckoview/features/browser/domain/services/proxy_settings_replication.dart';
import 'package:weblibre/features/geckoview/features/preferences/data/repositories/preference_observer.dart';
import 'package:weblibre/features/share_intent/domain/entities/shared_content.dart';
import 'package:weblibre/features/user/data/models/general_settings.dart';
import 'package:weblibre/features/user/domain/repositories/cache.dart';
@@ -373,6 +374,19 @@ class _BrowserViewState extends ConsumerState<BrowserView>
},
);
ref.listenManual(
fireImmediately: true,
preferenceFixatorProvider,
(previous, next) {},
onError: (error, stackTrace) {
logger.e(
'Error listening to preferenceFixatorProvider',
error: error,
stackTrace: stackTrace,
);
},
);
ref.listenManual(
fireImmediately: true,
proxySettingsReplicationProvider,
@@ -56,7 +56,7 @@ class PreferenceSetting with FastEquatable {
final Object value;
@JsonKey(includeFromJson: false, includeToJson: false)
final GeckoPrefValue? current;
final GeckoPref? current;
bool get isActive => value == current?.value;
@@ -80,7 +80,7 @@ abstract class _$PreferenceSettingCWProxy {
PreferenceSetting description(String? description);
PreferenceSetting current(GeckoPrefValue? current);
PreferenceSetting current(GeckoPref? current);
PreferenceSetting requireUserOptIn(bool requireUserOptIn);
@@ -97,7 +97,7 @@ abstract class _$PreferenceSettingCWProxy {
Object value,
String? title,
String? description,
GeckoPrefValue? current,
GeckoPref? current,
bool requireUserOptIn,
bool shouldBeDefault,
});
@@ -121,7 +121,7 @@ class _$PreferenceSettingCWProxyImpl implements _$PreferenceSettingCWProxy {
call(description: description);
@override
PreferenceSetting current(GeckoPrefValue? current) => call(current: current);
PreferenceSetting current(GeckoPref? current) => call(current: current);
@override
PreferenceSetting requireUserOptIn(bool requireUserOptIn) =>
@@ -163,7 +163,7 @@ class _$PreferenceSettingCWProxyImpl implements _$PreferenceSettingCWProxy {
current: current == const $CopyWithPlaceholder()
? _value.current
// ignore: cast_nullable_to_non_nullable
: current as GeckoPrefValue?,
: current as GeckoPref?,
requireUserOptIn:
requireUserOptIn == const $CopyWithPlaceholder() ||
requireUserOptIn == null
@@ -0,0 +1,81 @@
import 'dart:async';
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:weblibre/features/geckoview/domain/providers.dart';
part 'preference_observer.g.dart';
@Riverpod()
class PreferenceChangeListener extends _$PreferenceChangeListener {
@override
Stream<GeckoPref> build() async* {
final events = ref.watch(eventServiceProvider);
await GeckoPrefService().startObserveChanges();
ref.onDispose(() async {
await GeckoPrefService().stopObserveChanges();
});
yield* events.prefUpdateEvent;
}
}
@Riverpod()
class PreferenceFixator extends _$PreferenceFixator {
Future<void> register(String name, Object value) async {
await GeckoPrefService().applyPrefs({name: value});
state = {...state}
..update(
name,
(_) => value,
ifAbsent: () {
unawaited(GeckoPrefService().registerPrefForObservation(name));
return value;
},
);
}
Future<void> unregister(String name) async {
await GeckoPrefService().unregisterPrefForObservation(name);
state = {...state}..remove(name);
}
@override
Map<String, Object> build() {
ref.listen(preferenceChangeListenerProvider, (previous, next) async {
if (next.hasValue) {
final setting = stateOrNull?[next.value!.name];
if (setting != null && next.value?.value != setting) {
await GeckoPrefService().applyPrefs({next.value!.name: setting});
}
}
});
return {};
}
}
// @Riverpod()
// class PreferenceObserver extends _$PreferenceObserver {
// @override
// Stream<GeckoPref> build(String pref) {
// final updateStream = ref
// .watch(preferenceChangeListenerProvider)
// .where((x) => x.name == pref);
// unawaited(GeckoPrefService().registerPrefForObservation(pref));
// ref.onDispose(() async {
// await GeckoPrefService().unregisterPrefForObservation(pref);
// });
// return GeckoPrefService()
// .getPrefs([pref])
// .asStream()
// .map((value) => value.values.first)
// .concatWith([updateStream]);
// }
// }
@@ -0,0 +1,109 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'preference_observer.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning
@ProviderFor(PreferenceChangeListener)
const preferenceChangeListenerProvider = PreferenceChangeListenerProvider._();
final class PreferenceChangeListenerProvider
extends $StreamNotifierProvider<PreferenceChangeListener, GeckoPref> {
const PreferenceChangeListenerProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'preferenceChangeListenerProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$preferenceChangeListenerHash();
@$internal
@override
PreferenceChangeListener create() => PreferenceChangeListener();
}
String _$preferenceChangeListenerHash() =>
r'668c1bcd0636ec515a5e92ee5ba4ea7a67fa7a6d';
abstract class _$PreferenceChangeListener extends $StreamNotifier<GeckoPref> {
Stream<GeckoPref> build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref = this.ref as $Ref<AsyncValue<GeckoPref>, GeckoPref>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<AsyncValue<GeckoPref>, GeckoPref>,
AsyncValue<GeckoPref>,
Object?,
Object?
>;
element.handleValue(ref, created);
}
}
@ProviderFor(PreferenceFixator)
const preferenceFixatorProvider = PreferenceFixatorProvider._();
final class PreferenceFixatorProvider
extends $NotifierProvider<PreferenceFixator, Map<String, Object>> {
const PreferenceFixatorProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'preferenceFixatorProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$preferenceFixatorHash();
@$internal
@override
PreferenceFixator create() => PreferenceFixator();
/// {@macro riverpod.override_with_value}
Override overrideWithValue(Map<String, Object> value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<Map<String, Object>>(value),
);
}
}
String _$preferenceFixatorHash() => r'dfa323859c660d3db74dba7297e2a33b758ed78a';
abstract class _$PreferenceFixator extends $Notifier<Map<String, Object>> {
Map<String, Object> build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref = this.ref as $Ref<Map<String, Object>, Map<String, Object>>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<Map<String, Object>, Map<String, Object>>,
Map<String, Object>,
Object?,
Object?
>;
element.handleValue(ref, created);
}
}
@@ -65,7 +65,7 @@ Future<PreferenceSettingGroup> _preferenceSettingGroup(
class _PreferenceRepository extends _$PreferenceRepository {
final _prefManager = GeckoPrefService();
// Use BehaviorSubject instead of StreamController
late BehaviorSubject<Map<String, GeckoPrefValue>> _prefSubject;
late BehaviorSubject<Map<String, GeckoPref>> _prefSubject;
Future<void> _updatePrefs() async {
final prefs = await _prefManager.getAllPrefs();
@@ -83,8 +83,8 @@ class _PreferenceRepository extends _$PreferenceRepository {
}
@override
Raw<Stream<Map<String, GeckoPrefValue>>> build() {
_prefSubject = BehaviorSubject<Map<String, GeckoPrefValue>>();
Raw<Stream<Map<String, GeckoPref>>> build() {
_prefSubject = BehaviorSubject<Map<String, GeckoPref>>();
ref.onDispose(() async {
await _prefSubject.close();
@@ -229,7 +229,7 @@ final class _PreferenceRepositoryProvider
extends
$NotifierProvider<
_PreferenceRepository,
Raw<Stream<Map<String, GeckoPrefValue>>>
Raw<Stream<Map<String, GeckoPref>>>
> {
const _PreferenceRepositoryProvider._()
: super(
@@ -250,21 +250,22 @@ final class _PreferenceRepositoryProvider
_PreferenceRepository create() => _PreferenceRepository();
/// {@macro riverpod.override_with_value}
Override overrideWithValue(Raw<Stream<Map<String, GeckoPrefValue>>> value) {
Override overrideWithValue(Raw<Stream<Map<String, GeckoPref>>> value) {
return $ProviderOverride(
origin: this,
providerOverride:
$SyncValueProvider<Raw<Stream<Map<String, GeckoPrefValue>>>>(value),
providerOverride: $SyncValueProvider<Raw<Stream<Map<String, GeckoPref>>>>(
value,
),
);
}
}
String _$_preferenceRepositoryHash() =>
r'9a98b95677d4070def531ea1e5b900892045a1ef';
r'0f6812988a23407f6648e32fb1585984d2433bbc';
abstract class _$PreferenceRepository
extends $Notifier<Raw<Stream<Map<String, GeckoPrefValue>>>> {
Raw<Stream<Map<String, GeckoPrefValue>>> build();
extends $Notifier<Raw<Stream<Map<String, GeckoPref>>>> {
Raw<Stream<Map<String, GeckoPref>>> build();
@$mustCallSuper
@override
void runBuild() {
@@ -272,17 +273,17 @@ abstract class _$PreferenceRepository
final ref =
this.ref
as $Ref<
Raw<Stream<Map<String, GeckoPrefValue>>>,
Raw<Stream<Map<String, GeckoPrefValue>>>
Raw<Stream<Map<String, GeckoPref>>>,
Raw<Stream<Map<String, GeckoPref>>>
>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<
Raw<Stream<Map<String, GeckoPrefValue>>>,
Raw<Stream<Map<String, GeckoPrefValue>>>
Raw<Stream<Map<String, GeckoPref>>>,
Raw<Stream<Map<String, GeckoPref>>>
>,
Raw<Stream<Map<String, GeckoPrefValue>>>,
Raw<Stream<Map<String, GeckoPref>>>,
Object?,
Object?
>;