63 lines
2.3 KiB
Dart
63 lines
2.3 KiB
Dart
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(),
|
|
);
|