import 'dart:io'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:image_picker/image_picker.dart'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; import '../../../core/constants/app_defaults.dart'; import '../../../core/providers/app_providers.dart'; import '../../../data/local/models/models.dart'; final profileProvider = AsyncNotifierProvider(ProfileNotifier.new); class ProfileNotifier extends AsyncNotifier { @override Future build() async { final isar = await ref.watch(isarProvider.future); final profile = await isar.userProfiles.get(AppDefaults.singletonId); if (profile != null) return profile; // Bootstrap should have created one; create defensively. final fresh = UserProfile.createDefault(); await isar.writeTxn(() => isar.userProfiles.put(fresh)); return fresh; } Future updateNickname(String nickname) async { final trimmed = nickname.trim(); if (trimmed.isEmpty) return; final current = state.value; if (current == null) return; final updated = current.copyWith(nickname: trimmed); final isar = await ref.read(isarProvider.future); await isar.writeTxn(() => isar.userProfiles.put(updated)); state = AsyncData(updated); } /// Picks an image from gallery or camera, copies it into the app sandbox /// and stores the local file path on the profile. Future updateAvatar({required bool fromCamera}) async { final current = state.value; if (current == null) return false; final picker = ImagePicker(); final xfile = await picker.pickImage( source: fromCamera ? ImageSource.camera : ImageSource.gallery, maxWidth: 512, maxHeight: 512, imageQuality: 85, ); if (xfile == null) return false; final docs = await getApplicationDocumentsDirectory(); final destPath = p.join(docs.path, AppDefaults.avatarFileName); final sourceFile = File(xfile.path); await sourceFile.copy(destPath); final updated = current.copyWith( avatarLocalPath: destPath, avatarSource: AvatarSource.localFile, ); final isar = await ref.read(isarProvider.future); await isar.writeTxn(() => isar.userProfiles.put(updated)); state = AsyncData(updated); return true; } Future resetAvatar() async { final current = state.value; if (current == null) return; final updated = current.copyWith( avatarAssetPath: AppDefaults.defaultAvatarAssetPath, avatarLocalPath: null, avatarSource: AvatarSource.asset, ); final isar = await ref.read(isarProvider.future); await isar.writeTxn(() => isar.userProfiles.put(updated)); state = AsyncData(updated); } }