Files
krow-worker-app/lib/state/session_controller.dart
2026-09-17 22:26:11 +05:30

116 lines
3.3 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
/// Injected in `main()` once SharedPreferences has loaded.
final prefsProvider = Provider<SharedPreferences>(
(ref) => throw UnimplementedError('prefsProvider must be overridden'),
);
class SessionState {
const SessionState({
this.onboardingSeen = false,
this.phone,
this.signedIn = false,
this.locationGranted = false,
this.notificationsGranted = false,
this.cameraGranted = false,
});
final bool onboardingSeen;
final String? phone;
final bool signedIn;
final bool locationGranted;
final bool notificationsGranted;
final bool cameraGranted;
/// The three-step permission run shown right after verification.
bool get permissionsDone =>
locationGranted && notificationsGranted && cameraGranted;
SessionState copyWith({
bool? onboardingSeen,
String? phone,
bool? signedIn,
bool? locationGranted,
bool? notificationsGranted,
bool? cameraGranted,
}) => SessionState(
onboardingSeen: onboardingSeen ?? this.onboardingSeen,
phone: phone ?? this.phone,
signedIn: signedIn ?? this.signedIn,
locationGranted: locationGranted ?? this.locationGranted,
notificationsGranted: notificationsGranted ?? this.notificationsGranted,
cameraGranted: cameraGranted ?? this.cameraGranted,
);
}
class SessionController extends Notifier<SessionState> {
static const _kOnboarding = 'onboarding_seen';
static const _kPhone = 'phone';
static const _kSignedIn = 'signed_in';
static const _kLocation = 'perm_location';
static const _kNotifications = 'perm_notifications';
static const _kCamera = 'perm_camera';
SharedPreferences get _prefs => ref.read(prefsProvider);
@override
SessionState build() {
final p = _prefs;
return SessionState(
onboardingSeen: p.getBool(_kOnboarding) ?? false,
phone: p.getString(_kPhone),
signedIn: p.getBool(_kSignedIn) ?? false,
locationGranted: p.getBool(_kLocation) ?? false,
notificationsGranted: p.getBool(_kNotifications) ?? false,
cameraGranted: p.getBool(_kCamera) ?? false,
);
}
void completeOnboarding() {
_prefs.setBool(_kOnboarding, true);
state = state.copyWith(onboardingSeen: true);
}
/// The demo backend accepts any 10-digit number and always sends `123456`.
static const demoCode = '123456';
String sendCode(String phone) {
_prefs.setString(_kPhone, phone);
state = state.copyWith(phone: phone);
return demoCode;
}
bool verifyCode(String code) {
if (code != demoCode) return false;
_prefs.setBool(_kSignedIn, true);
state = state.copyWith(signedIn: true);
return true;
}
void grantLocation() {
_prefs.setBool(_kLocation, true);
state = state.copyWith(locationGranted: true);
}
void grantNotifications() {
_prefs.setBool(_kNotifications, true);
state = state.copyWith(notificationsGranted: true);
}
void grantCamera() {
_prefs.setBool(_kCamera, true);
state = state.copyWith(cameraGranted: true);
}
Future<void> signOut() async {
await _prefs.remove(_kSignedIn);
await _prefs.remove(_kPhone);
state = state.copyWith(signedIn: false, phone: '');
}
}
final sessionProvider = NotifierProvider<SessionController, SessionState>(
SessionController.new,
);