Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pebble/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ kotlin {
// commonMain by default and will correctly pull the Android artifacts of any KMP
// dependencies declared in commonMain.
implementation(compose.uiTooling)
implementation(libs.androidx.activity.compose)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
package coredevices.pebble.ui

import android.content.ActivityNotFoundException
import android.net.Uri
import android.webkit.ValueCallback
import android.webkit.WebChromeClient
import android.webkit.WebView
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.multiplatform.webview.web.AccompanistWebChromeClient
import com.multiplatform.webview.web.NativeWebView
import com.multiplatform.webview.web.PlatformWebViewParams
import com.multiplatform.webview.web.WebViewFactoryParam
import com.multiplatform.webview.web.defaultWebViewFactory
import io.rebble.libpebblecommon.connection.AppContext
import io.rebble.libpebblecommon.io.rebble.libpebblecommon.js.WebViewJSLocalStorageInterface
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import java.util.concurrent.atomic.AtomicReference
import kotlin.io.path.Path
import kotlin.uuid.Uuid

Expand Down Expand Up @@ -45,6 +57,38 @@ internal actual suspend fun restoreLocalStorage(webView: NativeWebView) {
}
}

@Composable
internal actual fun rememberWebViewFileChooserParams(): PlatformWebViewParams? {
val pending = remember { AtomicReference<ValueCallback<Array<Uri>>?>(null) }
val launcher = rememberLauncherForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
val uris = WebChromeClient.FileChooserParams.parseResult(result.resultCode, result.data)
pending.getAndSet(null)?.onReceiveValue(uris)
}
return remember(launcher) {
PlatformWebViewParams(
chromeClient = object : AccompanistWebChromeClient() {
override fun onShowFileChooser(
webView: WebView?,
filePathCallback: ValueCallback<Array<Uri>>?,
fileChooserParams: FileChooserParams?
): Boolean {
pending.getAndSet(filePathCallback)?.onReceiveValue(null)
val intent = fileChooserParams?.createIntent() ?: return false
return try {
launcher.launch(intent)
true
} catch (e: ActivityNotFoundException) {
pending.getAndSet(null)?.onReceiveValue(null)
false
}
}
}
)
}
}

internal actual fun persistLocalStorage(webView: NativeWebView) {
runBlocking(Dispatchers.Main) {
webView.evaluateJavascript("""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import com.multiplatform.webview.request.WebRequest
import com.multiplatform.webview.request.WebRequestInterceptResult
import com.multiplatform.webview.web.LoadingState
import com.multiplatform.webview.web.NativeWebView
import com.multiplatform.webview.web.PlatformWebViewParams
import com.multiplatform.webview.web.WebView
import com.multiplatform.webview.web.WebViewFactoryParam
import com.multiplatform.webview.web.WebViewNavigator
Expand Down Expand Up @@ -69,6 +70,9 @@ internal expect fun webViewFactory(
internal expect suspend fun restoreLocalStorage(webView: NativeWebView)
internal expect fun persistLocalStorage(webView: NativeWebView)

@Composable
internal expect fun rememberWebViewFileChooserParams(): PlatformWebViewParams?

@OptIn(ExperimentalCoroutinesApi::class)
@Composable
fun WatchappSettingsScreen(
Expand All @@ -93,6 +97,7 @@ fun WatchappSettingsScreen(
}
}
val pkjsSession by pkjsSessionFlow.collectAsState(null)
val fileChooserParams = rememberWebViewFileChooserParams()
val state = rememberWebViewState(url) {
androidWebSettings.domStorageEnabled = true
iOSWebSettings.isInspectable = true
Expand Down Expand Up @@ -152,6 +157,7 @@ fun WatchappSettingsScreen(
state = state,
modifier = Modifier.fillMaxSize().padding(paddingValues),
navigator = navigator,
platformWebViewParams = fileChooserParams,
factory = { webViewFactory(it, uuid) }
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package coredevices.pebble.ui

import androidx.compose.runtime.Composable
import co.touchlab.kermit.Logger
import com.multiplatform.webview.web.NativeWebView
import com.multiplatform.webview.web.PlatformWebViewParams
import com.multiplatform.webview.web.WebViewFactoryParam
import com.multiplatform.webview.web.defaultWebViewFactory
import kotlinx.cinterop.ExperimentalForeignApi
Expand Down Expand Up @@ -31,4 +33,7 @@ internal actual suspend fun restoreLocalStorage(webView: NativeWebView) {

internal actual fun persistLocalStorage(webView: NativeWebView) {
// no-op
}
}

@Composable
internal actual fun rememberWebViewFileChooserParams(): PlatformWebViewParams? = null