106 lines
4.0 KiB
Dart
106 lines
4.0 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:onesignal_flutter/onesignal_flutter.dart';
|
|
|
|
import '../../repositories/auth_repository.dart';
|
|
import '../../services/supabase_auth_service.dart'; // Dibutuhkan untuk DI di authRepositoryProvider
|
|
import 'auth_state.dart';
|
|
|
|
// ── Provider ────────────────────────────────────────────────────
|
|
/// Provider global untuk [AuthRepository].
|
|
final authRepositoryProvider = Provider<AuthRepository>(
|
|
(ref) => AuthRepository(SupabaseAuthService()),
|
|
);
|
|
|
|
/// Provider utama untuk mengelola status autentikasi di seluruh aplikasi.
|
|
final authProvider = StateNotifierProvider<AuthNotifier, AuthState>(
|
|
(ref) => AuthNotifier(ref.read(authRepositoryProvider)),
|
|
);
|
|
|
|
// ── Notifier ────────────────────────────────────────────────────
|
|
/// Notifier yang mengelola logika bisnis autentikasi pengguna.
|
|
/// Berfungsi sebagai penghubung antara UI dan [AuthRepository], serta mengontrol pendaftaran OneSignal Push Notification.
|
|
class AuthNotifier extends StateNotifier<AuthState> {
|
|
final AuthRepository _repo;
|
|
|
|
AuthNotifier(this._repo) : super(const AuthIdle());
|
|
|
|
/// Memeriksa status sesi login yang tersimpan di perangkat lokal.
|
|
/// Dipanggil pertama kali saat aplikasi dibuka untuk fitur Auto-Login.
|
|
Future<void> checkAuthStatus() async {
|
|
state = const AuthLoading();
|
|
try {
|
|
// Mengambil sesi aktif dari repository
|
|
final user = await _repo.checkSession();
|
|
|
|
if (user != null) {
|
|
// Jika sesi valid, login ke OneSignal menggunakan ID user untuk pengiriman notifikasi personal
|
|
OneSignal.login(user.id);
|
|
state = AuthSuccess(user);
|
|
} else {
|
|
state = const AuthIdle();
|
|
}
|
|
} catch (e) {
|
|
state = const AuthIdle();
|
|
}
|
|
}
|
|
|
|
/// Memproses login pengguna menggunakan email dan password.
|
|
Future<void> login(String email, String password) async {
|
|
state = const AuthLoading();
|
|
try {
|
|
final user = await _repo.login(email, password);
|
|
// Daftarkan ke OneSignal saat login berhasil
|
|
OneSignal.login(user.id);
|
|
state = AuthSuccess(user);
|
|
} catch (e) {
|
|
state = AuthError(e.toString().replaceFirst('Exception: ', ''));
|
|
}
|
|
}
|
|
|
|
/// Memproses registrasi akun baru (Nama, Email, Password).
|
|
Future<void> register(
|
|
String name, String email, String password) async {
|
|
state = const AuthLoading();
|
|
try {
|
|
final user = await _repo.register(name, email, password);
|
|
// Daftarkan ke OneSignal saat registrasi berhasil
|
|
OneSignal.login(user.id);
|
|
state = AuthSuccess(user);
|
|
} catch (e) {
|
|
state = AuthError(e.toString().replaceFirst('Exception: ', ''));
|
|
}
|
|
}
|
|
|
|
/// Menghubungkan akun pengguna dengan perangkat IoT ESP32 berdasarkan [claimCode] dari alat.
|
|
/// Setelah berhasil diklaim, state [AuthState] akan diperbarui dengan data `deviceId` yang baru.
|
|
Future<void> claimDevice(String claimCode) async {
|
|
final currentState = state;
|
|
if (currentState is! AuthSuccess) return;
|
|
|
|
state = const AuthLoading();
|
|
try {
|
|
final deviceId = await _repo.claimDevice(currentState.user.id, claimCode);
|
|
// Update UserModel dengan deviceId baru secara immutable
|
|
final updatedUser = currentState.user.copyWith(deviceId: deviceId);
|
|
state = AuthSuccess(updatedUser);
|
|
} catch (e) {
|
|
// Revert ke state sebelumnya jika terjadi error klaim
|
|
state = currentState;
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Keluar dari sesi login pengguna.
|
|
/// Menghapus kredensial dari Supabase, memutus sesi OneSignal, dan mereset state ke [AuthIdle].
|
|
Future<void> logout() async {
|
|
OneSignal.logout();
|
|
await _repo.logout();
|
|
state = const AuthIdle();
|
|
}
|
|
|
|
/// Mereset kondisi error saat ini kembali ke [AuthIdle].
|
|
void resetError() {
|
|
if (state is AuthError) state = const AuthIdle();
|
|
}
|
|
}
|