feat: enhance UI, branding assets, onboarding flow, and screen layouts
This commit is contained in:
62
lib/core/permissions.dart
Normal file
62
lib/core/permissions.dart
Normal file
@@ -0,0 +1,62 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
/// The three things the app asks for, in the order it asks.
|
||||
enum AppPermission { location, notifications, camera }
|
||||
|
||||
extension AppPermissionX on AppPermission {
|
||||
Permission get _platform => switch (this) {
|
||||
// While-in-use only: clock-in needs to know you are at the venue, and
|
||||
// nothing here justifies background tracking.
|
||||
AppPermission.location => Permission.locationWhenInUse,
|
||||
AppPermission.notifications => Permission.notification,
|
||||
AppPermission.camera => Permission.camera,
|
||||
};
|
||||
}
|
||||
|
||||
/// Thin wrapper over `permission_handler`.
|
||||
///
|
||||
/// Exists so the rest of the app never imports the plugin directly, and so the
|
||||
/// platforms it has no implementation for — web, desktop — degrade to "granted"
|
||||
/// instead of throwing. On the web the browser prompts at the point of use
|
||||
/// anyway, so asking up front is neither possible nor needed.
|
||||
class PermissionService {
|
||||
const PermissionService();
|
||||
|
||||
bool get _supported =>
|
||||
!kIsWeb &&
|
||||
(defaultTargetPlatform == TargetPlatform.android ||
|
||||
defaultTargetPlatform == TargetPlatform.iOS);
|
||||
|
||||
/// Shows the platform dialog. Returns whether the permission ended up
|
||||
/// granted — which is not the same as whether the user tapped Allow, since
|
||||
/// it may already have been permanently denied.
|
||||
Future<bool> request(AppPermission permission) async {
|
||||
if (!_supported) return true;
|
||||
final status = await permission._platform.request();
|
||||
return status.isGranted || status.isLimited;
|
||||
}
|
||||
|
||||
Future<bool> isGranted(AppPermission permission) async {
|
||||
if (!_supported) return true;
|
||||
final status = await permission._platform.status;
|
||||
return status.isGranted || status.isLimited;
|
||||
}
|
||||
|
||||
/// True once the OS will no longer show a dialog, so the only way back is
|
||||
/// the system settings page.
|
||||
Future<bool> isPermanentlyDenied(AppPermission permission) async {
|
||||
if (!_supported) return false;
|
||||
return permission._platform.status.then((s) => s.isPermanentlyDenied);
|
||||
}
|
||||
|
||||
Future<void> openSettings() async {
|
||||
if (!_supported) return;
|
||||
await openAppSettings();
|
||||
}
|
||||
}
|
||||
|
||||
final permissionServiceProvider = Provider<PermissionService>(
|
||||
(ref) => const PermissionService(),
|
||||
);
|
||||
Reference in New Issue
Block a user