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 request(AppPermission permission) async { if (!_supported) return true; final status = await permission._platform.request(); return status.isGranted || status.isLimited; } Future 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 isPermanentlyDenied(AppPermission permission) async { if (!_supported) return false; return permission._platform.status.then((s) => s.isPermanentlyDenied); } Future openSettings() async { if (!_supported) return; await openAppSettings(); } } final permissionServiceProvider = Provider( (ref) => const PermissionService(), );