First of all: Thanks for this great package! 😊
It's widely adopted for good reasons and I want to congratulate you on that.
I understand how the API of this package got designed but Dart's introduction of extension methods makes it possible to design a much tighter, more readable API. Here are just some of my ideas:
Enums:
I think the PermissionStatus
and ServiceStatus
should be enum
s so that users can switch
over the result. Values and other methods can still be defined using extension methods.
PermissionHandler:
I know this is what gives the package its name, but I'm not sure a PermissionHandler
is needed at all. Currently, it mainly provides a namespace for all the functions of this package. But they could be defined just as well on the PermissionGroup
s themselves, which seems much more intuitive to me.
status
could be a getter, because it doesn't perform an action that the developer or user perceives. Developers still know that some work is involved, because it returns a Future
.
Also, most of the time you only want to request a single permission, so it makes sense to also provide a method for that.
current | proposed
--- | ---
await PermissionHandler()
.checkPermissionStatus(PermissionGroup.camera)
| await PermissionGroup.camera.status
(await PermissionHandler()
.requestPermissions([PermissionGroup.camera]))[PermissionGroup.camera]
| await PermissionGroup.camera.request()
PermissionHandler()
.requestPermissions([PermissionGroup.camera, PermissionGroup.storage]))
| await [PermissionGroup.camera, PermissionGroup.storage].request()
Intuitive getters:
Sure, users can always check someStatus == PermissionStatus.granted
, but someStatus.isGranted
seems more intuitive, allowing for (await PermissionGroup.camera.status).isGranted
.
These getters could not only get implemented on PermissionStatus
, but also on Future<PermissionStatus>
, allowing even terser syntax: await PermissionGroup.camera.checkStatus().isGranted
.
To make the API more declarative, maybe these getters could also get directly implemented on PermissionGroup
s as syntactic sugar for implicitly calling the check()
function: await PermissionGroup.camera.isGranted
Support common patterns:
Very often, permissions are checked and if they are denied, a request is made. That could be supported using some requestIfDenied
method, that returns the status if the status is not PermissionStatus.denied
and otherwise requests the permission from the user and then returns the new status: PermissionGroup.camera.requestIfDenied()
PermissionGroups?
I understand that some of the permissions resemble multiple OS-level permissions, but I think that's an implementation detail that most developers using this API don't really care about.
Maybe, PermissionGroup
could get renamed to Permission
?
Putting it all together
Most of this was trivial syntactic sugar, but putting it all together, it makes for much more terse code.
What before looked like this:
var handler = PermissionHandler();
var permission = await handler.checkPermissionStatus(PermissionGroup.storage);
if (permission != PermissionStatus.granted) {
var permissions = await handler.requestPermissions([PermissionGroup.storage]);
if (permissions[PermissionGroup.storage] != PermissionStatus.granted) {
// Do stuff.
}
}
could now be as easy as this:
if (await Permission.storage.requestIfDenied().isGranted) {
// Do stuff.
}
Of course, these are breaking changes to the api and require a major version update to 5.0.0. I do think though that the simplicity of that API would be worth it.
What do you think about these changes? If you decide on redesigning the API, I'm happy to help to implement the changes.
platform: android platform: ios status: in progress type: enhancement