Skip to content

Commit 48c94a5

Browse files
committed
Fix permissions bug
1 parent e5888f7 commit 48c94a5

File tree

83 files changed

+265
-224
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+265
-224
lines changed

app/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ android {
3737
else -> 0
3838
}
3939

40-
val vCode = 241
40+
val vCode = 244
4141
versionCode = vCode - singleAbiNum
42-
versionName = "1.2.36"
42+
versionName = "1.2.37"
4343

4444
ndk {
4545
//noinspection ChromeOsAbiSupport

app/src/main/java/com/ismartcoding/plain/features/Permissions.kt

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,16 @@ enum class Permission {
243243
}
244244
}
245245

246-
data class PermissionItem(val icon: ImageVector?, val permission: Permission, val permissions: Set<Permission>, val granted: Boolean)
246+
data class PermissionItem(val icon: ImageVector?, val permission: Permission, val permissions: Set<Permission>, var granted: Boolean = false) {
247+
248+
companion object {
249+
fun create(context: Context, icon: ImageVector?, permission: Permission, permissions: Set<Permission> = setOf(permission)): PermissionItem {
250+
return PermissionItem(icon, permission, permissions).apply {
251+
granted = permissions.all { it.can(context) }
252+
}
253+
}
254+
}
255+
}
247256

248257
object Permissions {
249258
private val launcherMap = mutableMapOf<Permission, ActivityResultLauncher<String>>()
@@ -252,46 +261,51 @@ object Permissions {
252261
private lateinit var multipleLauncher: ActivityResultLauncher<Array<String>>
253262

254263
suspend fun checkAsync(context: Context, permissions: Set<Permission>) {
255-
val ps = permissions.map { it.toString() }
256-
val apiPermissions = ApiPermissionsPreference.getAsync(context)
257-
if (!apiPermissions.all { ps.contains(it) }) {
258-
throw Exception("no_permission")
264+
val apiPermissions = ApiPermissionsPreference.getAsync(context).toMutableSet()
265+
if (apiPermissions.contains(Permission.WRITE_CONTACTS.toString())) {
266+
apiPermissions.add(Permission.READ_CONTACTS.toString())
267+
}
268+
if (apiPermissions.contains(Permission.WRITE_CALL_LOG.toString())) {
269+
apiPermissions.add(Permission.READ_CALL_LOG.toString())
270+
}
271+
for (item in permissions.map { it.toString() }) {
272+
if (!apiPermissions.contains(item)) {
273+
throw Exception("no_permission")
274+
}
259275
}
260276
}
261277

262-
fun anyCan(context: Context, permissions: Set<Permission>): Boolean {
263-
return permissions.any { it.can(context) }
278+
fun allCan(context: Context, permissions: Set<Permission>): Boolean {
279+
return permissions.all { it.can(context) }
264280
}
265281

266282
fun getWebList(context: Context): List<PermissionItem> {
267283
val list = mutableListOf<PermissionItem>()
268284
list.add(
269-
PermissionItem(Icons.Outlined.Folder, Permission.WRITE_EXTERNAL_STORAGE, setOf(Permission.WRITE_EXTERNAL_STORAGE),
270-
setOf(Permission.WRITE_EXTERNAL_STORAGE).all { it.can(context) })
285+
PermissionItem.create(
286+
context, Icons.Outlined.Folder, Permission.WRITE_EXTERNAL_STORAGE
287+
)
271288
)
272289
if (AppFeatureType.NOTIFICATIONS.has()) {
273290
list.add(
274-
PermissionItem(Icons.Outlined.Notifications, Permission.NOTIFICATION_LISTENER, setOf(Permission.NOTIFICATION_LISTENER),
275-
setOf(Permission.NOTIFICATION_LISTENER).all { it.can(context) })
291+
PermissionItem.create(context, Icons.Outlined.Notifications, Permission.NOTIFICATION_LISTENER)
276292
)
277293
}
278294
list.add(
279-
PermissionItem(Icons.Outlined.Contacts, Permission.WRITE_CONTACTS, setOf(Permission.WRITE_CONTACTS),
280-
setOf(Permission.WRITE_CONTACTS).all { it.can(context) })
295+
PermissionItem.create(context, Icons.Outlined.Contacts, Permission.WRITE_CONTACTS, setOf(Permission.READ_CONTACTS, Permission.WRITE_CONTACTS))
281296
)
297+
282298
if (AppFeatureType.SOCIAL.has()) {
283-
list.add(PermissionItem(Icons.Outlined.Sms, Permission.READ_SMS, setOf(Permission.READ_SMS), setOf(Permission.READ_SMS).all { it.can(context) }))
284-
list.add(PermissionItem(Icons.AutoMirrored.Outlined.List, Permission.WRITE_CALL_LOG, setOf(Permission.WRITE_CALL_LOG), setOf(Permission.WRITE_CALL_LOG).all { it.can(context) }))
299+
list.add(PermissionItem.create(context, Icons.Outlined.Sms, Permission.READ_SMS))
300+
list.add(PermissionItem.create(context, Icons.AutoMirrored.Outlined.List, Permission.WRITE_CALL_LOG, setOf(Permission.READ_CALL_LOG, Permission.WRITE_CALL_LOG)))
285301
}
286302
list.add(
287-
PermissionItem(Icons.Outlined.Call, Permission.CALL_PHONE, setOf(Permission.CALL_PHONE),
288-
setOf(Permission.CALL_PHONE).all { it.can(context) })
303+
PermissionItem.create(context, Icons.Outlined.Call, Permission.CALL_PHONE)
289304
)
290305
list.add(
291-
PermissionItem(Icons.Outlined.Numbers, Permission.READ_PHONE_NUMBERS, setOf(Permission.READ_PHONE_STATE, Permission.READ_PHONE_NUMBERS),
292-
setOf(Permission.READ_PHONE_STATE, Permission.READ_PHONE_NUMBERS).all { it.can(context) })
306+
PermissionItem.create(context, Icons.Outlined.Numbers, Permission.READ_PHONE_NUMBERS, setOf(Permission.READ_PHONE_STATE, Permission.READ_PHONE_NUMBERS))
293307
)
294-
list.add(PermissionItem(null, Permission.NONE, setOf(Permission.NONE), false))
308+
list.add(PermissionItem(null, Permission.NONE, setOf(Permission.NONE)))
295309
return list
296310
}
297311

app/src/main/java/com/ismartcoding/plain/ui/base/TextWithLinkSupport.kt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import androidx.compose.ui.text.AnnotatedString
77
import androidx.compose.ui.text.SpanStyle
88
import androidx.compose.ui.text.buildAnnotatedString
99
import androidx.compose.ui.text.withStyle
10+
import com.ismartcoding.plain.R
11+
import com.ismartcoding.plain.packageManager
12+
import com.ismartcoding.plain.ui.helpers.DialogHelper
1013
import com.ismartcoding.plain.ui.helpers.WebHelper
1114
import java.util.regex.Matcher
1215
import java.util.regex.Pattern
@@ -93,13 +96,21 @@ fun AnnotatedString.urlAt(
9396

9497
"EMAIL" -> {
9598
val emailIntent = Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:${it.item}"))
96-
context.startActivity(emailIntent)
99+
if (emailIntent.resolveActivity(packageManager) != null) {
100+
context.startActivity(emailIntent)
101+
} else {
102+
DialogHelper.showMessage(R.string.not_supported_error)
103+
}
97104
return
98105
}
99106

100107
"PHONE" -> {
101108
val phoneIntent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:${it.item}"))
102-
context.startActivity(phoneIntent)
109+
if (phoneIntent.resolveActivity(packageManager) != null) {
110+
context.startActivity(phoneIntent)
111+
} else {
112+
DialogHelper.showMessage(R.string.not_supported_error)
113+
}
103114
return
104115
}
105116
}

app/src/main/java/com/ismartcoding/plain/ui/call/CallsDialog.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import com.ismartcoding.plain.extensions.formatDateTime
1717
import com.ismartcoding.plain.features.ActionEvent
1818
import com.ismartcoding.plain.features.Permission
1919
import com.ismartcoding.plain.features.PermissionResultEvent
20+
import com.ismartcoding.plain.features.PermissionsResultEvent
2021
import com.ismartcoding.plain.features.call.CallHelper
2122
import com.ismartcoding.plain.features.call.DCall
2223
import com.ismartcoding.plain.features.tag.TagHelper
@@ -57,6 +58,7 @@ class CallsDialog : BaseListDrawerDialog() {
5758
}
5859
}
5960
}
61+
6062
R.id.delete -> {
6163
if (!Permission.WRITE_CALL_LOG.can(requireContext())) {
6264
Permission.WRITE_CALL_LOG.grant(requireContext())
@@ -78,6 +80,7 @@ class CallsDialog : BaseListDrawerDialog() {
7880
}
7981
}
8082
}
83+
8184
else -> {
8285
BottomMenuHelper.onMenuItemClick(viewModel, binding, this)
8386
}
@@ -87,16 +90,17 @@ class CallsDialog : BaseListDrawerDialog() {
8790

8891
override fun initEvents() {
8992
receiveEvent<PermissionResultEvent> { event ->
90-
if (setOf(Permission.READ_CALL_LOG, Permission.WRITE_CALL_LOG).contains(event.permission)) {
91-
checkPermission()
92-
} else if (event.permission == Permission.CALL_PHONE) {
93+
if (event.permission == Permission.CALL_PHONE) {
9394
if (Permission.CALL_PHONE.can(requireContext())) {
9495
CallHelper.call(requireContext(), phoneNumberToCall)
9596
} else {
9697
DialogHelper.showMessage(R.string.call_phone_permission_required)
9798
}
9899
}
99100
}
101+
receiveEvent<PermissionsResultEvent> { event ->
102+
checkPermission()
103+
}
100104
receiveEvent<ActionEvent> { event ->
101105
if (event.source == ActionSourceType.CALL) {
102106
binding.list.page.refresh()

app/src/main/java/com/ismartcoding/plain/ui/contact/ContactsDialog.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import com.ismartcoding.plain.data.enums.DataType
1717
import com.ismartcoding.plain.features.ActionEvent
1818
import com.ismartcoding.plain.features.Permission
1919
import com.ismartcoding.plain.features.PermissionResultEvent
20+
import com.ismartcoding.plain.features.PermissionsResultEvent
2021
import com.ismartcoding.plain.features.call.CallHelper
2122
import com.ismartcoding.plain.features.contact.ContactHelper
2223
import com.ismartcoding.plain.features.contact.DContact
@@ -62,6 +63,7 @@ class ContactsDialog : BaseListDrawerDialog() {
6263
}
6364
}
6465
}
66+
6567
R.id.delete -> {
6668
if (!Permission.WRITE_CONTACTS.can(requireContext())) {
6769
Permission.WRITE_CONTACTS.grant(requireContext())
@@ -83,6 +85,7 @@ class ContactsDialog : BaseListDrawerDialog() {
8385
}
8486
}
8587
}
88+
8689
else -> {
8790
BottomMenuHelper.onMenuItemClick(viewModel, binding, this)
8891
}
@@ -97,16 +100,17 @@ class ContactsDialog : BaseListDrawerDialog() {
97100

98101
override fun initEvents() {
99102
receiveEvent<PermissionResultEvent> { event ->
100-
if (event.permission == Permission.READ_CONTACTS) {
101-
checkPermission()
102-
} else if (event.permission == Permission.CALL_PHONE) {
103+
if (event.permission == Permission.CALL_PHONE) {
103104
if (Permission.CALL_PHONE.can(requireContext())) {
104105
CallHelper.call(requireContext(), phoneNumberToCall)
105106
} else {
106107
DialogHelper.showMessage(R.string.call_phone_permission_required)
107108
}
108109
}
109110
}
111+
receiveEvent<PermissionsResultEvent> { event ->
112+
checkPermission()
113+
}
110114
receiveEvent<ActionEvent> { event ->
111115
if (event.source == ActionSourceType.CONTACT) {
112116
binding.list.page.refresh()

app/src/main/java/com/ismartcoding/plain/ui/extensions/ViewPageListBinding.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@ package com.ismartcoding.plain.ui.extensions
33
import android.content.Context
44
import android.view.View
55
import androidx.core.view.isVisible
6+
import com.ismartcoding.lib.channel.sendEvent
67
import com.ismartcoding.plain.R
78
import com.ismartcoding.plain.databinding.ViewPageListBinding
89
import com.ismartcoding.plain.features.Permission
910
import com.ismartcoding.plain.features.Permissions
11+
import com.ismartcoding.plain.features.RequestPermissionsEvent
1012
import com.ismartcoding.plain.features.locale.LocaleHelper.getString
1113

1214
fun ViewPageListBinding.checkPermission(
1315
context: Context,
1416
permissions: Set<Permission>,
1517
permission: Permission,
1618
) {
17-
if (Permissions.anyCan(context, permissions)) {
19+
if (Permissions.allCan(context, permissions)) {
1820
page.visibility = View.VISIBLE
1921
empty.root.isVisible = false
2022
page.showLoading()
@@ -26,7 +28,7 @@ fun ViewPageListBinding.checkPermission(
2628
button.text = getString(R.string.grant_access)
2729
button.isVisible = true
2830
button.setSafeClick {
29-
permission.grant(context)
31+
sendEvent(RequestPermissionsEvent(permissions.toSet()))
3032
}
3133
}
3234
}

app/src/main/java/com/ismartcoding/plain/ui/sms/SmsDialog.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import com.ismartcoding.plain.extensions.formatDateTime
1515
import com.ismartcoding.plain.features.ActionEvent
1616
import com.ismartcoding.plain.features.Permission
1717
import com.ismartcoding.plain.features.PermissionResultEvent
18+
import com.ismartcoding.plain.features.PermissionsResultEvent
1819
import com.ismartcoding.plain.features.sms.DMessage
1920
import com.ismartcoding.plain.features.sms.SmsHelper
2021
import com.ismartcoding.plain.ui.BaseListDrawerDialog
@@ -45,7 +46,7 @@ class SmsDialog : BaseListDrawerDialog() {
4546
}
4647

4748
override fun initEvents() {
48-
receiveEvent<PermissionResultEvent> {
49+
receiveEvent<PermissionsResultEvent> {
4950
checkPermission()
5051
}
5152
receiveEvent<ActionEvent> { event ->

app/src/main/java/com/ismartcoding/plain/web/SXGraphQL.kt

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,9 @@ class SXGraphQL(val schema: Schema) {
282282
}
283283
query("imageCount") {
284284
resolver { query: String ->
285-
if (Permission.WRITE_EXTERNAL_STORAGE.can(MainApp.instance)) {
286-
ImageHelper.count(MainApp.instance, QueryHelper.prepareQuery(query))
285+
val context = MainApp.instance
286+
if (Permission.WRITE_EXTERNAL_STORAGE.can(context)) {
287+
ImageHelper.count(context, QueryHelper.prepareQuery(query))
287288
} else {
288289
0
289290
}
@@ -374,9 +375,10 @@ class SXGraphQL(val schema: Schema) {
374375
executor = Executor.DataLoaderPrepared
375376
}
376377
resolver { offset: Int, limit: Int, query: String ->
377-
Permissions.checkAsync(MainApp.instance, setOf(Permission.READ_CONTACTS, Permission.WRITE_CONTACTS))
378+
val context = MainApp.instance
379+
Permissions.checkAsync(context, setOf(Permission.READ_CONTACTS))
378380
try {
379-
ContactHelper.search(MainApp.instance, QueryHelper.prepareQuery(query), limit, offset).map { it.toModel() }
381+
ContactHelper.search(context, QueryHelper.prepareQuery(query), limit, offset).map { it.toModel() }
380382
} catch (ex: Exception) {
381383
LogCat.e(ex)
382384
emptyList()
@@ -393,22 +395,23 @@ class SXGraphQL(val schema: Schema) {
393395
}
394396
query("contactCount") {
395397
resolver { query: String ->
396-
if (Permissions.anyCan(MainApp.instance, setOf(Permission.READ_CONTACTS, Permission.WRITE_CONTACTS))) {
397-
ContactHelper.count(MainApp.instance, QueryHelper.prepareQuery(query))
398+
val context = MainApp.instance
399+
if (Permission.READ_CONTACTS.can(context)) {
400+
ContactHelper.count(context, QueryHelper.prepareQuery(query))
398401
} else {
399402
0
400403
}
401404
}
402405
}
403406
query("contactSources") {
404407
resolver { ->
405-
Permissions.checkAsync(MainApp.instance, setOf(Permission.READ_CONTACTS, Permission.WRITE_CONTACTS))
408+
Permissions.checkAsync(MainApp.instance, setOf(Permission.READ_CONTACTS))
406409
SourceHelper.getAll().map { it.toModel() }
407410
}
408411
}
409412
query("contactGroups") {
410413
resolver { node: Execution.Node ->
411-
Permissions.checkAsync(MainApp.instance, setOf(Permission.READ_CONTACTS, Permission.WRITE_CONTACTS))
414+
Permissions.checkAsync(MainApp.instance, setOf(Permission.READ_CONTACTS))
412415
val groups = GroupHelper.getAll().map { it.toModel() }
413416
val fields = node.getFields()
414417
if (fields.contains(ContactGroup::contactCount.name)) {
@@ -422,7 +425,7 @@ class SXGraphQL(val schema: Schema) {
422425
executor = Executor.DataLoaderPrepared
423426
}
424427
resolver { offset: Int, limit: Int, query: String ->
425-
Permissions.checkAsync(MainApp.instance, setOf(Permission.READ_CALL_LOG, Permission.WRITE_CALL_LOG))
428+
Permissions.checkAsync(MainApp.instance, setOf(Permission.READ_CALL_LOG))
426429
CallHelper.search(MainApp.instance, QueryHelper.prepareQuery(query), limit, offset).map { it.toModel() }
427430
}
428431
type<Call> {
@@ -436,8 +439,9 @@ class SXGraphQL(val schema: Schema) {
436439
}
437440
query("callCount") {
438441
resolver { query: String ->
439-
if (Permissions.anyCan(MainApp.instance, setOf(Permission.READ_CALL_LOG, Permission.WRITE_CALL_LOG))) {
440-
CallHelper.count(MainApp.instance, QueryHelper.prepareQuery(query))
442+
val context = MainApp.instance
443+
if (Permission.READ_CALL_LOG.can(context)) {
444+
CallHelper.count(context, QueryHelper.prepareQuery(query))
441445
} else {
442446
0
443447
}
@@ -606,9 +610,10 @@ class SXGraphQL(val schema: Schema) {
606610
}
607611
query("deviceInfo") {
608612
resolver { ->
609-
val apiPermissions = ApiPermissionsPreference.getAsync(MainApp.instance)
610-
val readPhoneNumber = apiPermissions.contains(Permission.READ_PHONE_STATE.toString()) && apiPermissions.contains(Permission.READ_PHONE_NUMBERS.toString())
611-
DeviceInfoHelper.getDeviceInfo(MainApp.instance, readPhoneNumber).toModel()
613+
val context = MainApp.instance
614+
val apiPermissions = ApiPermissionsPreference.getAsync(context)
615+
val readPhoneNumber = apiPermissions.contains(Permission.READ_PHONE_NUMBERS.toString())
616+
DeviceInfoHelper.getDeviceInfo(context, readPhoneNumber).toModel()
612617
}
613618
}
614619
query("battery") {

0 commit comments

Comments
 (0)