aves/lib/widgets/common/action_delegates/permission_aware.dart

58 lines
2.4 KiB
Dart

import 'package:aves/model/image_entry.dart';
import 'package:aves/services/android_file_service.dart';
import 'package:aves/utils/android_file_utils.dart';
import 'package:flutter/material.dart';
import 'package:tuple/tuple.dart';
mixin PermissionAwareMixin {
Future<bool> checkStoragePermission(BuildContext context, Iterable<ImageEntry> entries) {
return checkStoragePermissionForPaths(context, entries.where((e) => e.path != null).map((e) => e.path));
}
Future<bool> checkStoragePermissionForPaths(BuildContext context, Iterable<String> paths) async {
final volumes = paths.map((path) => androidFileUtils.getStorageVolume(path)).toSet();
final removableVolumes = volumes.where((v) => v.isRemovable);
final volumePermissions = await Future.wait<Tuple2<StorageVolume, bool>>(
removableVolumes.map(
(volume) => AndroidFileService.hasGrantedPermissionToVolumeRoot(volume.path).then(
(granted) => Tuple2(volume, granted),
),
),
);
final ungrantedVolumes = volumePermissions.where((t) => !t.item2).map((t) => t.item1).toList();
while (ungrantedVolumes.isNotEmpty) {
final volume = ungrantedVolumes.first;
final confirmed = await showDialog<bool>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Storage Volume Access'),
content: Text('Please select the root directory of “${volume.description}” in the next screen, so that this app can access it and complete your request.'),
actions: [
FlatButton(
onPressed: () => Navigator.pop(context),
child: Text('Cancel'.toUpperCase()),
),
FlatButton(
onPressed: () => Navigator.pop(context, true),
child: Text('OK'.toUpperCase()),
),
],
);
},
);
// abort if the user cancels in Flutter
if (confirmed == null || !confirmed) return false;
final granted = await AndroidFileService.requestVolumeAccess(volume.path);
debugPrint('$runtimeType _checkStoragePermission with volume=${volume.path} got granted=$granted');
if (granted) {
ungrantedVolumes.remove(volume);
} else {
// abort if the user denies access from the native dialog
return false;
}
}
return true;
}
}