···77abstract class ProfileState with _$ProfileState {
88 const factory ProfileState({
99 ProfileViewDetailed? profile,
1010- @Default(false) bool isEarlySupporter,
1110 @Default(false) bool showAuthPrompt,
1211 String?
1312 currentViewDid, // DID being viewed or null for current user's profile
···11+import 'package:get_it/get_it.dart';
22+import 'package:riverpod_annotation/riverpod_annotation.dart';
33+import 'package:spark/src/core/network/atproto/data/models/pref_models.dart';
44+import 'package:spark/src/core/network/atproto/data/repositories/pref_repository.dart';
55+import 'package:spark/src/core/network/atproto/data/repositories/sprk_repository.dart';
66+import 'package:spark/src/core/utils/logging/log_service.dart';
77+import 'package:spark/src/core/utils/logging/logger.dart';
88+99+part 'preferences_provider.g.dart';
1010+1111+/// Central provider for user preferences.
1212+///
1313+/// This provider loads preferences once at startup and holds them in memory.
1414+/// All services that need preferences should watch this provider instead of
1515+/// calling getPreferences() directly.
1616+///
1717+/// When preferences are updated (via [updatePreferences]), all watchers are
1818+/// automatically notified of the change.
1919+@Riverpod(keepAlive: true)
2020+class UserPreferences extends _$UserPreferences {
2121+ late final PrefRepository _prefRepository;
2222+ late final SprkRepository _sprkRepository;
2323+ late final SparkLogger _logger;
2424+2525+ @override
2626+ Future<Preferences> build() async {
2727+ _prefRepository = GetIt.instance<PrefRepository>();
2828+ _sprkRepository = GetIt.instance<SprkRepository>();
2929+ _logger = GetIt.instance<LogService>().getLogger('UserPreferences');
3030+3131+ _logger.d('Loading preferences...');
3232+3333+ // Wait for auth to be initialized
3434+ await _sprkRepository.authRepository.initializationComplete;
3535+3636+ if (!_sprkRepository.authRepository.isAuthenticated) {
3737+ _logger.w('Not authenticated, returning empty preferences');
3838+ return Preferences(preferences: []);
3939+ }
4040+4141+ try {
4242+ final preferences = await _prefRepository.getPreferences();
4343+ _logger.d('Preferences loaded successfully');
4444+ return preferences;
4545+ } catch (e) {
4646+ _logger.e('Error loading preferences: $e');
4747+ rethrow;
4848+ }
4949+ }
5050+5151+ /// Gets the current preferences synchronously if available.
5252+ /// Returns null if preferences haven't been loaded yet or there was an error.
5353+ Preferences? get currentPreferences => state.asData?.value;
5454+5555+ /// Refreshes preferences from the server.
5656+ /// This should be called when logging in or when syncing from another device.
5757+ Future<void> refresh() async {
5858+ _logger.d('Refreshing preferences from server...');
5959+ state = const AsyncValue.loading();
6060+6161+ try {
6262+ final preferences = await _prefRepository.getPreferences();
6363+ state = AsyncValue.data(preferences);
6464+ _logger.d('Preferences refreshed successfully');
6565+ } catch (e, st) {
6666+ _logger.e('Error refreshing preferences: $e');
6767+ state = AsyncValue.error(e, st);
6868+ }
6969+ }
7070+7171+ /// Updates preferences on the server and in local state.
7272+ /// This should be called whenever preferences are modified.
7373+ Future<void> updatePreferences(Preferences preferences) async {
7474+ _logger.d('Updating preferences...');
7575+7676+ try {
7777+ await _prefRepository.putPreferences(preferences);
7878+ state = AsyncValue.data(preferences);
7979+ _logger.d('Preferences updated successfully');
8080+ } catch (e, st) {
8181+ _logger.e('Error updating preferences: $e');
8282+ state = AsyncValue.error(e, st);
8383+ rethrow;
8484+ }
8585+ }
8686+8787+ /// Updates preferences by applying a transformation function.
8888+ /// This is useful for making partial updates without fetching first.
8989+ Future<void> updatePreferencesWithFn(
9090+ Preferences Function(Preferences current) updater,
9191+ ) async {
9292+ final current = state.asData?.value;
9393+ if (current == null) {
9494+ throw Exception('Cannot update preferences: not loaded yet');
9595+ }
9696+9797+ final updated = updater(current);
9898+ await updatePreferences(updated);
9999+ }
100100+}