Feat(ToolView): Add native api
Add native api to support clipboard operations
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
package top.fatweb.oxygen.toolbox.ui.view
|
package top.fatweb.oxygen.toolbox.ui.view
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.util.Log
|
||||||
|
import android.webkit.ConsoleMessage
|
||||||
import androidx.compose.animation.core.Ease
|
import androidx.compose.animation.core.Ease
|
||||||
import androidx.compose.animation.core.animateFloat
|
import androidx.compose.animation.core.animateFloat
|
||||||
import androidx.compose.animation.core.infiniteRepeatable
|
import androidx.compose.animation.core.infiniteRepeatable
|
||||||
@@ -26,20 +28,25 @@ import androidx.compose.material3.Text
|
|||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import com.kevinnzou.web.AccompanistWebChromeClient
|
||||||
import com.kevinnzou.web.WebView
|
import com.kevinnzou.web.WebView
|
||||||
import com.kevinnzou.web.rememberWebViewStateWithHTMLData
|
import com.kevinnzou.web.rememberWebViewStateWithHTMLData
|
||||||
|
import timber.log.Timber
|
||||||
import top.fatweb.oxygen.toolbox.R
|
import top.fatweb.oxygen.toolbox.R
|
||||||
import top.fatweb.oxygen.toolbox.icon.Loading
|
import top.fatweb.oxygen.toolbox.icon.Loading
|
||||||
import top.fatweb.oxygen.toolbox.icon.OxygenIcons
|
import top.fatweb.oxygen.toolbox.icon.OxygenIcons
|
||||||
import top.fatweb.oxygen.toolbox.ui.component.OxygenTopAppBar
|
import top.fatweb.oxygen.toolbox.ui.component.OxygenTopAppBar
|
||||||
|
import top.fatweb.oxygen.toolbox.util.NativeWebApi
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun ToolViewRoute(
|
internal fun ToolViewRoute(
|
||||||
@@ -67,6 +74,7 @@ internal fun ToolViewScreen(
|
|||||||
isPreview: Boolean,
|
isPreview: Boolean,
|
||||||
onBackClick: () -> Unit
|
onBackClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
val infiniteTransition = rememberInfiniteTransition(label = "infiniteTransition")
|
val infiniteTransition = rememberInfiniteTransition(label = "infiniteTransition")
|
||||||
|
|
||||||
@@ -150,8 +158,33 @@ internal fun ToolViewScreen(
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.imePadding(),
|
.imePadding(),
|
||||||
state = webViewState,
|
state = webViewState,
|
||||||
|
chromeClient = remember {
|
||||||
|
object : AccompanistWebChromeClient() {
|
||||||
|
override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean {
|
||||||
|
consoleMessage?.let {
|
||||||
|
Timber.tag("WebView").log(
|
||||||
|
priority = when (it.messageLevel()) {
|
||||||
|
ConsoleMessage.MessageLevel.TIP -> Log.VERBOSE
|
||||||
|
ConsoleMessage.MessageLevel.LOG -> Log.INFO
|
||||||
|
ConsoleMessage.MessageLevel.WARNING -> Log.WARN
|
||||||
|
ConsoleMessage.MessageLevel.ERROR -> Log.ERROR
|
||||||
|
else -> Log.DEBUG
|
||||||
|
},
|
||||||
|
message = "${it.message()} (${it.lineNumber()})"
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
onCreated = {
|
onCreated = {
|
||||||
it.settings.javaScriptEnabled = true
|
it.settings.javaScriptEnabled = true
|
||||||
|
it.settings.domStorageEnabled = true
|
||||||
|
it.addJavascriptInterface(
|
||||||
|
NativeWebApi(context = context, webView = it),
|
||||||
|
"NativeApi"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package top.fatweb.oxygen.toolbox.util
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Context.CLIPBOARD_SERVICE
|
||||||
|
import android.webkit.JavascriptInterface
|
||||||
|
import android.webkit.WebView
|
||||||
|
|
||||||
|
class NativeWebApi(
|
||||||
|
private val context: Context,
|
||||||
|
private val webView: WebView
|
||||||
|
) {
|
||||||
|
@JavascriptInterface
|
||||||
|
fun copyToClipboard(text: String): Boolean {
|
||||||
|
val clipboardManager = context.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager?
|
||||||
|
return clipboardManager?.let {
|
||||||
|
it.setPrimaryClip(ClipData.newPlainText("copy", text))
|
||||||
|
true
|
||||||
|
} ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
@JavascriptInterface
|
||||||
|
fun readClipboard(): String {
|
||||||
|
val clipboardManager = context.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager?
|
||||||
|
return clipboardManager?.primaryClip?.getItemAt(0)?.text?.toString() ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun callback(callback: String, vararg args: Any) {
|
||||||
|
val jsCode =
|
||||||
|
"$callback(${args.map { if (it is String) "'$it'" else it }.joinToString(", ")})"
|
||||||
|
webView.evaluateJavascript(jsCode, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user