80 lines
2.4 KiB
Dart
80 lines
2.4 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
|
|
|
import '../models/profile.dart';
|
|
import 'auth_provider.dart';
|
|
import 'supabase_provider.dart';
|
|
|
|
final currentUserIdProvider = Provider<String?>((ref) {
|
|
final authState = ref.watch(authStateChangesProvider);
|
|
// Be explicit about loading/error to avoid dynamic dispatch problems.
|
|
return authState.when(
|
|
data: (state) => state.session?.user.id,
|
|
loading: () => ref.watch(sessionProvider)?.user.id,
|
|
error: (_, __) => ref.watch(sessionProvider)?.user.id,
|
|
);
|
|
});
|
|
|
|
final currentProfileProvider = StreamProvider<Profile?>((ref) {
|
|
final userId = ref.watch(currentUserIdProvider);
|
|
if (userId == null) {
|
|
return const Stream.empty();
|
|
}
|
|
final client = ref.watch(supabaseClientProvider);
|
|
return client
|
|
.from('profiles')
|
|
.stream(primaryKey: ['id'])
|
|
.eq('id', userId)
|
|
.map((rows) => rows.isEmpty ? null : Profile.fromMap(rows.first));
|
|
});
|
|
|
|
final profilesProvider = StreamProvider<List<Profile>>((ref) {
|
|
final client = ref.watch(supabaseClientProvider);
|
|
return client
|
|
.from('profiles')
|
|
.stream(primaryKey: ['id'])
|
|
.order('full_name')
|
|
.map((rows) => rows.map(Profile.fromMap).toList());
|
|
});
|
|
|
|
/// Controller for the current user's profile (update full name / password).
|
|
final profileControllerProvider = Provider<ProfileController>((ref) {
|
|
final client = ref.watch(supabaseClientProvider);
|
|
return ProfileController(client);
|
|
});
|
|
|
|
class ProfileController {
|
|
ProfileController(this._client);
|
|
|
|
final SupabaseClient _client;
|
|
|
|
/// Update the `profiles.full_name` for the given user id.
|
|
Future<void> updateFullName({
|
|
required String userId,
|
|
required String fullName,
|
|
}) async {
|
|
await _client
|
|
.from('profiles')
|
|
.update({'full_name': fullName})
|
|
.eq('id', userId);
|
|
}
|
|
|
|
/// Update the current user's password (works for OAuth users too).
|
|
Future<void> updatePassword(String password) async {
|
|
if (password.length < 8) {
|
|
throw Exception('Password must be at least 8 characters');
|
|
}
|
|
await _client.auth.updateUser(UserAttributes(password: password));
|
|
}
|
|
}
|
|
|
|
final isAdminProvider = Provider<bool>((ref) {
|
|
final profileAsync = ref.watch(currentProfileProvider);
|
|
return profileAsync.maybeWhen(
|
|
data: (profile) => profile?.role == 'admin',
|
|
orElse: () => false,
|
|
);
|
|
});
|