Skip to content

Commit

Permalink
Merge pull request #71 from icerockdev/develop
Browse files Browse the repository at this point in the history
Release 0.14.0
  • Loading branch information
Alex009 authored Dec 18, 2022
2 parents 89c5350 + 7438163 commit c9d1ca4
Show file tree
Hide file tree
Showing 14 changed files with 280 additions and 27 deletions.
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ allprojects {
project **build.gradle**
```groovy
dependencies {
commonMainApi("dev.icerock.moko:permissions:0.13.0")
commonTestImplementation("dev.icerock.moko:permissions-test:0.13.0")
commonMainApi("dev.icerock.moko:permissions:0.14.0")
androidMainApi("dev.icerock.moko:permissions-compose:0.14.0") // permissions api + compose extensions
commonTestImplementation("dev.icerock.moko:permissions-test:0.14.0")
}
```

Expand Down Expand Up @@ -95,6 +96,20 @@ override fun onCreate(savedInstanceState: Bundle?) {
}
```

Compose:
```kotlin
@Composable
fun TestScreen() {
val viewModel = getViewModel {
// Pass the platform implementation of the permission controller to a common code.
ViewModel(PermissionsController())
}

// Binds the permissions controller to the LocalLifecycleOwner lifecycle.
BindEffect(viewModel.permissionsController)
}
```

iOS:
```swift
// Just pass the platform implementation of the permission controller to a common code.
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ buildscript {
classpath(libs.mokoGradlePlugin)
classpath(libs.mobileMultiplatformGradlePlugin)
classpath(libs.kotlinSerializationGradlePlugin)
classpath(libs.composeJetBrainsGradlePlugin)
}
}

Expand Down
13 changes: 11 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
[versions]
kotlinVersion = "1.6.10"
androidAppCompatVersion = "1.2.0"
composeCompilerVersion = "1.1.1"
composeMaterialVersion = "1.3.1"
composeActivityVersion = "1.6.1"
materialDesignVersion = "1.0.0"
androidLifecycleVersion = "2.1.0"
androidCoreTestingVersion = "2.1.0"
coroutinesVersion = "1.6.0-native-mt"
mokoMvvmVersion = "0.12.0"
mokoPermissionsVersion = "0.13.0"
mokoPermissionsVersion = "0.14.0"
composeJetBrainsVersion = "1.1.1"
lifecycleRuntime = "2.5.1"

[libraries]
appCompat = { module = "androidx.appcompat:appcompat", version.ref = "androidAppCompatVersion" }
material = { module = "com.google.android.material:material", version.ref = "materialDesignVersion" }
composeMaterial = { module = "androidx.compose.material:material", version.ref = "composeMaterialVersion" }
composeActivity = { module = "androidx.activity:activity-compose", version.ref = "composeActivityVersion" }
lifecycle = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "androidLifecycleVersion" }
lifecycleRuntime = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleRuntime" }
coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutinesVersion" }
mokoMvvmCore = { module = "dev.icerock.moko:mvvm-core", version.ref = "mokoMvvmVersion" }
mokoMvvmTest = { module = "dev.icerock.moko:mvvm-test", version.ref = "mokoMvvmVersion" }
Expand All @@ -23,6 +31,7 @@ kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", ver
androidGradlePlugin = { module = "com.android.tools.build:gradle", version = "7.0.4" }
googleServicesGradlePlugin = { module = "com.google.gms:google-services", version = "4.3.8" }
firebaseGradlePlugin = { module = "com.google.firebase:firebase-crashlytics-gradle", version = "2.2.0" }
mokoGradlePlugin = { module = "dev.icerock.moko:moko-gradle-plugin", version = "0.1.0" }
mokoGradlePlugin = { module = "dev.icerock.moko:moko-gradle-plugin", version = "0.2.0" }
mobileMultiplatformGradlePlugin = { module = "dev.icerock:mobile-multiplatform", version = "0.14.1" }
kotlinSerializationGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlinVersion" }
composeJetBrainsGradlePlugin = { module = "org.jetbrains.compose:compose-gradle-plugin", version.ref = "composeJetBrainsVersion" }
18 changes: 18 additions & 0 deletions permissions-compose/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

plugins {
id("dev.icerock.moko.gradle.android.library")
id("dev.icerock.moko.gradle.android.publication")
id("dev.icerock.moko.gradle.stub.javadoc")
id("dev.icerock.moko.gradle.detekt")
id("org.jetbrains.compose")
}

dependencies {
api(projects.permissions)
api(compose.runtime)
api(libs.appCompat)
api(libs.composeActivity)
}
2 changes: 2 additions & 0 deletions permissions-compose/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="dev.icerock.moko.permissions.compose" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2019 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

package dev.icerock.moko.permissions.compose

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.fragment.app.FragmentActivity
import dev.icerock.moko.permissions.PermissionsController

@Suppress("FunctionNaming")
@Composable
fun BindEffect(permissionsController: PermissionsController) {
val lifecycleOwner = LocalLifecycleOwner.current
val fragmentManager = (LocalContext.current as FragmentActivity).supportFragmentManager

LaunchedEffect(true) {
permissionsController.bind(lifecycleOwner.lifecycle, fragmentManager)
}
}
2 changes: 1 addition & 1 deletion permissions/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ plugins {

dependencies {
commonMainImplementation(libs.coroutines)

androidMainImplementation(libs.appCompat)
androidMainImplementation(libs.lifecycleRuntime)
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import androidx.lifecycle.OnLifecycleEvent
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlin.coroutines.suspendCoroutine

@Suppress("TooManyFunctions")
Expand All @@ -30,6 +32,7 @@ class PermissionsControllerImpl(
private val applicationContext: Context
) : PermissionsController {
private val fragmentManagerHolder = MutableStateFlow<FragmentManager?>(null)
private val mutex: Mutex = Mutex()

override fun bind(lifecycle: Lifecycle, fragmentManager: FragmentManager) {
this.fragmentManagerHolder.value = fragmentManager
Expand All @@ -45,15 +48,17 @@ class PermissionsControllerImpl(
}

override suspend fun providePermission(permission: Permission) {
val fragmentManager: FragmentManager = awaitFragmentManager()
val resolverFragment: ResolverFragment = getOrCreateResolverFragment(fragmentManager)

val platformPermission = permission.toPlatformPermission()
suspendCoroutine<Unit> { continuation ->
resolverFragment.requestPermission(
permission,
platformPermission
) { continuation.resumeWith(it) }
mutex.withLock {
val fragmentManager: FragmentManager = awaitFragmentManager()
val resolverFragment: ResolverFragment = getOrCreateResolverFragment(fragmentManager)

val platformPermission = permission.toPlatformPermission()
suspendCoroutine<Unit> { continuation ->
resolverFragment.requestPermission(
permission,
platformPermission
) { continuation.resumeWith(it) }
}
}
}

Expand Down Expand Up @@ -124,7 +129,7 @@ class PermissionsControllerImpl(
fragmentManager
.beginTransaction()
.add(fragment, resolverFragmentTag)
.commitNow()
.commit()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package dev.icerock.moko.permissions
import android.content.pm.PackageManager
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope

internal class ResolverFragment : Fragment() {
init {
Expand All @@ -20,20 +21,22 @@ internal class ResolverFragment : Fragment() {
permissions: List<String>,
callback: (Result<Unit>) -> Unit
) {
val context = requireContext()
val toRequest = permissions.filter {
ContextCompat.checkSelfPermission(context, it) != PackageManager.PERMISSION_GRANTED
}
lifecycleScope.launchWhenCreated {
val context = requireContext()
val toRequest = permissions.filter {
ContextCompat.checkSelfPermission(context, it) != PackageManager.PERMISSION_GRANTED
}

if (toRequest.isEmpty()) {
callback.invoke(Result.success(Unit))
return
}
if (toRequest.isEmpty()) {
callback.invoke(Result.success(Unit))
return@launchWhenCreated
}

val requestCode = (permissionCallbackMap.keys.maxOrNull() ?: 0) + 1
permissionCallbackMap[requestCode] = PermissionCallback(permission, callback)
val requestCode = (permissionCallbackMap.keys.maxOrNull() ?: 0) + 1
permissionCallbackMap[requestCode] = PermissionCallback(permission, callback)

requestPermissions(toRequest.toTypedArray(), requestCode)
requestPermissions(toRequest.toTypedArray(), requestCode)
}
}

override fun onRequestPermissionsResult(
Expand Down
25 changes: 25 additions & 0 deletions sample/compose-android-app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
plugins {
id("dev.icerock.moko.gradle.android.application")
id("dev.icerock.moko.gradle.detekt")
id("kotlin-kapt")
}

android {
defaultConfig {
applicationId = "dev.icerock.moko.samples.permissions"
minSdk = 21
versionCode = 1
versionName = "0.1.0"
}

buildFeatures.compose = true
composeOptions.kotlinCompilerExtensionVersion = libs.versions.composeCompilerVersion.get()
}

dependencies {
implementation(libs.appCompat)
implementation(libs.composeActivity)
implementation(libs.composeMaterial)
implementation(projects.sample.mppLibrary)
implementation(projects.permissionsCompose)
}
31 changes: 31 additions & 0 deletions sample/compose-android-app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.icerockdev">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<application
android:label="moko-permissions test app"
android:theme="@style/Theme.AppCompat.DayNight"
tools:ignore="GoogleAppIndexingWarning">

<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Loading

0 comments on commit c9d1ca4

Please sign in to comment.