user_profile_provider.dart
1 import 'dart:io'; 2 3 import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 5 import '../services/user_profile_service.dart'; 6 7 /// Provider for the UserProfileService singleton. 8 final userProfileServiceProvider = Provider<UserProfileService>((ref) { 9 return UserProfileService.instance; 10 }); 11 12 /// State for the user profile. 13 class UserProfileState { 14 final String? picturePath; 15 final String? displayName; 16 final Set<String> shareProfileContactIds; 17 final bool shareWithAll; 18 19 const UserProfileState({ 20 this.picturePath, 21 this.displayName, 22 this.shareProfileContactIds = const {}, 23 this.shareWithAll = false, 24 }); 25 26 UserProfileState copyWith({ 27 String? picturePath, 28 String? displayName, 29 Set<String>? shareProfileContactIds, 30 bool? shareWithAll, 31 bool clearPicture = false, 32 bool clearDisplayName = false, 33 }) { 34 return UserProfileState( 35 picturePath: clearPicture ? null : (picturePath ?? this.picturePath), 36 displayName: clearDisplayName ? null : (displayName ?? this.displayName), 37 shareProfileContactIds: 38 shareProfileContactIds ?? this.shareProfileContactIds, 39 shareWithAll: shareWithAll ?? this.shareWithAll, 40 ); 41 } 42 } 43 44 /// Notifier for user profile state. 45 class UserProfileNotifier extends StateNotifier<UserProfileState> { 46 final UserProfileService _service; 47 48 UserProfileNotifier(this._service) : super(const UserProfileState()) { 49 _load(); 50 } 51 52 Future<void> _load() async { 53 await _service.init(); 54 state = UserProfileState( 55 picturePath: await _service.picturePath, 56 displayName: _service.displayName, 57 shareProfileContactIds: _service.shareProfileContactIds, 58 shareWithAll: _service.shareWithAll, 59 ); 60 } 61 62 Future<void> setPicture(File imageFile) async { 63 final path = await _service.setPicture(imageFile); 64 state = state.copyWith(picturePath: path); 65 } 66 67 Future<void> removePicture() async { 68 await _service.removePicture(); 69 state = state.copyWith(clearPicture: true); 70 } 71 72 Future<void> setDisplayName(String? name) async { 73 await _service.setDisplayName(name); 74 if (name == null || name.isEmpty) { 75 state = state.copyWith(clearDisplayName: true); 76 } else { 77 state = state.copyWith(displayName: name); 78 } 79 } 80 81 bool isSharedWith(String contactIdHex) { 82 return _service.isSharedWith(contactIdHex); 83 } 84 85 /// Toggle sharing and return the new state. 86 Future<bool> toggleShareWith(String contactIdHex) async { 87 final nowShared = await _service.toggleShareWith(contactIdHex); 88 state = state.copyWith( 89 shareProfileContactIds: _service.shareProfileContactIds, 90 ); 91 return nowShared; 92 } 93 94 Future<void> setShareWith(String contactIdHex, bool share) async { 95 await _service.setShareWith(contactIdHex, share); 96 state = state.copyWith( 97 shareProfileContactIds: _service.shareProfileContactIds, 98 ); 99 } 100 101 int get sharedContactCount => state.shareProfileContactIds.length; 102 103 Future<void> setShareWithAll(bool value) async { 104 await _service.setShareWithAll(value); 105 state = state.copyWith(shareWithAll: value); 106 } 107 108 Future<List<String>> ensureAllContactsShared(List<String> allContactHexIds) async { 109 final newIds = await _service.ensureAllContactsShared(allContactHexIds); 110 state = state.copyWith( 111 shareProfileContactIds: _service.shareProfileContactIds, 112 ); 113 return newIds; 114 } 115 } 116 117 /// Provider for user profile notifier. 118 final userProfileProvider = 119 StateNotifierProvider<UserProfileNotifier, UserProfileState>((ref) { 120 final service = ref.watch(userProfileServiceProvider); 121 return UserProfileNotifier(service); 122 });