init
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
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, UserProfile>(ProfileNotifier.new);
|
||||
|
||||
class ProfileNotifier extends AsyncNotifier<UserProfile> {
|
||||
@override
|
||||
Future<UserProfile> 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<void> 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<bool> 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<void> 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user