feat: enhance UI, branding assets, onboarding flow, and screen layouts
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../core/permissions.dart';
|
||||
|
||||
/// Injected in `main()` once SharedPreferences has loaded.
|
||||
final prefsProvider = Provider<SharedPreferences>(
|
||||
(ref) => throw UnimplementedError('prefsProvider must be overridden'),
|
||||
@@ -8,7 +10,6 @@ final prefsProvider = Provider<SharedPreferences>(
|
||||
|
||||
class SessionState {
|
||||
const SessionState({
|
||||
this.onboardingSeen = false,
|
||||
this.phone,
|
||||
this.signedIn = false,
|
||||
this.locationGranted = false,
|
||||
@@ -16,7 +17,6 @@ class SessionState {
|
||||
this.cameraGranted = false,
|
||||
});
|
||||
|
||||
final bool onboardingSeen;
|
||||
final String? phone;
|
||||
final bool signedIn;
|
||||
final bool locationGranted;
|
||||
@@ -28,14 +28,12 @@ class SessionState {
|
||||
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,
|
||||
@@ -45,7 +43,6 @@ class SessionState {
|
||||
}
|
||||
|
||||
class SessionController extends Notifier<SessionState> {
|
||||
static const _kOnboarding = 'onboarding_seen';
|
||||
static const _kPhone = 'phone';
|
||||
static const _kSignedIn = 'signed_in';
|
||||
static const _kLocation = 'perm_location';
|
||||
@@ -58,7 +55,6 @@ class SessionController extends Notifier<SessionState> {
|
||||
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,
|
||||
@@ -67,11 +63,6 @@ class SessionController extends Notifier<SessionState> {
|
||||
);
|
||||
}
|
||||
|
||||
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';
|
||||
|
||||
@@ -88,19 +79,40 @@ class SessionController extends Notifier<SessionState> {
|
||||
return true;
|
||||
}
|
||||
|
||||
void grantLocation() {
|
||||
_prefs.setBool(_kLocation, true);
|
||||
state = state.copyWith(locationGranted: true);
|
||||
/// Asks the OS, then records what it actually said.
|
||||
///
|
||||
/// The stored flag is a cache for the UI, never the source of truth — the
|
||||
/// user can revoke a permission in system settings without the app running,
|
||||
/// so [refresh] re-reads the real status whenever a screen needs it.
|
||||
Future<bool> request(AppPermission permission) async {
|
||||
final granted = await ref
|
||||
.read(permissionServiceProvider)
|
||||
.request(permission);
|
||||
_record(permission, granted);
|
||||
return granted;
|
||||
}
|
||||
|
||||
void grantNotifications() {
|
||||
_prefs.setBool(_kNotifications, true);
|
||||
state = state.copyWith(notificationsGranted: true);
|
||||
/// Re-reads all three from the OS. Called when a screen that shows their
|
||||
/// state appears, so a change made in system settings is picked up.
|
||||
Future<void> refresh() async {
|
||||
final service = ref.read(permissionServiceProvider);
|
||||
for (final permission in AppPermission.values) {
|
||||
_record(permission, await service.isGranted(permission));
|
||||
}
|
||||
}
|
||||
|
||||
void grantCamera() {
|
||||
_prefs.setBool(_kCamera, true);
|
||||
state = state.copyWith(cameraGranted: true);
|
||||
void _record(AppPermission permission, bool granted) {
|
||||
switch (permission) {
|
||||
case AppPermission.location:
|
||||
_prefs.setBool(_kLocation, granted);
|
||||
state = state.copyWith(locationGranted: granted);
|
||||
case AppPermission.notifications:
|
||||
_prefs.setBool(_kNotifications, granted);
|
||||
state = state.copyWith(notificationsGranted: granted);
|
||||
case AppPermission.camera:
|
||||
_prefs.setBool(_kCamera, granted);
|
||||
state = state.copyWith(cameraGranted: granted);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> signOut() async {
|
||||
|
||||
Reference in New Issue
Block a user