mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-09-02 20:10:37 +02:00
feat: update to alpha.17, typed mobile plugin IPC arguments (#676)
Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
This commit is contained in:
co-authored by
Amr Bashir
parent
76cfdc32b4
commit
e438e0a62d
@@ -2,7 +2,7 @@
|
||||
|
||||
## \[2.0.0-alpha.2]
|
||||
|
||||
- [`5c13736`](https://github.com/tauri-apps/plugins-workspace/commit/5c137365c60790e8d4037d449e8237aa3fffdab0)([#673](https://github.com/tauri-apps/plugins-workspace/pull/673)) Update to @tauri-apps/api v2.0.0-alpha.16.
|
||||
- [`5c13736`](https://github.com/tauri-apps/plugins-workspace/commit/5c137365c60790e8d4037d449e8237aa3fffdab0)([#673](https://github.com/tauri-apps/plugins-workspace/pull/673)) Update to @tauri-apps/api v2.0.0-alpha.9.
|
||||
|
||||
## \[2.0.0-alpha.2]
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ rust-version = { workspace = true }
|
||||
links = "tauri-plugin-clipboard-manager"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = [ "dox" ]
|
||||
rustc-args = [ "--cfg", "docsrs" ]
|
||||
rustdoc-args = [ "--cfg", "docsrs" ]
|
||||
targets = [ "x86_64-unknown-linux-gnu", "x86_64-linux-android" ]
|
||||
|
||||
[build-dependencies]
|
||||
@@ -24,6 +25,3 @@ thiserror = { workspace = true }
|
||||
|
||||
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
||||
arboard = "3"
|
||||
|
||||
[features]
|
||||
dox = [ "tauri/dox" ]
|
||||
|
||||
@@ -38,6 +38,7 @@ dependencies {
|
||||
implementation("androidx.core:core-ktx:1.9.0")
|
||||
implementation("androidx.appcompat:appcompat:1.6.0")
|
||||
implementation("com.google.android.material:material:1.7.0")
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.3")
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||
|
||||
@@ -11,11 +11,74 @@ import android.content.ClipDescription
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import app.tauri.annotation.Command
|
||||
import app.tauri.annotation.InvokeArg
|
||||
import app.tauri.annotation.TauriPlugin
|
||||
import app.tauri.plugin.Invoke
|
||||
import app.tauri.plugin.JSObject
|
||||
import app.tauri.plugin.Plugin
|
||||
import com.fasterxml.jackson.core.JsonGenerator
|
||||
import com.fasterxml.jackson.core.JsonParser
|
||||
import com.fasterxml.jackson.core.JsonProcessingException
|
||||
import com.fasterxml.jackson.databind.DeserializationContext
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
import com.fasterxml.jackson.databind.SerializerProvider
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer
|
||||
import java.io.IOException
|
||||
|
||||
@InvokeArg
|
||||
@JsonDeserialize(using = WriteOptionsDeserializer::class)
|
||||
sealed class WriteOptions {
|
||||
@JsonDeserialize
|
||||
class PlainText: WriteOptions() {
|
||||
lateinit var text: String
|
||||
var label: String? = null
|
||||
}
|
||||
}
|
||||
|
||||
@JsonSerialize(using = ReadClipDataSerializer::class)
|
||||
sealed class ReadClipData {
|
||||
class PlainText: ReadClipData() {
|
||||
lateinit var text: String
|
||||
}
|
||||
}
|
||||
|
||||
internal class ReadClipDataSerializer @JvmOverloads constructor(t: Class<ReadClipData>? = null) :
|
||||
StdSerializer<ReadClipData>(t) {
|
||||
@Throws(IOException::class, JsonProcessingException::class)
|
||||
override fun serialize(
|
||||
value: ReadClipData, jgen: JsonGenerator, provider: SerializerProvider
|
||||
) {
|
||||
jgen.writeStartObject()
|
||||
when (value) {
|
||||
is ReadClipData.PlainText -> {
|
||||
jgen.writeObjectFieldStart("plainText")
|
||||
|
||||
jgen.writeStringField("text", value.text)
|
||||
|
||||
jgen.writeEndObject()
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
|
||||
jgen.writeEndObject()
|
||||
}
|
||||
}
|
||||
|
||||
internal class WriteOptionsDeserializer: JsonDeserializer<WriteOptions>() {
|
||||
override fun deserialize(
|
||||
jsonParser: JsonParser,
|
||||
deserializationContext: DeserializationContext
|
||||
): WriteOptions {
|
||||
val node: JsonNode = jsonParser.codec.readTree(jsonParser)
|
||||
node.get("plainText")?.let {
|
||||
return jsonParser.codec.treeToValue(it, WriteOptions.PlainText::class.java)
|
||||
} ?: run {
|
||||
throw Error("unknown write options $node")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TauriPlugin
|
||||
class ClipboardPlugin(private val activity: Activity) : Plugin(activity) {
|
||||
@@ -25,22 +88,14 @@ class ClipboardPlugin(private val activity: Activity) : Plugin(activity) {
|
||||
@Command
|
||||
@Suppress("MoveVariableDeclarationIntoWhen")
|
||||
fun write(invoke: Invoke) {
|
||||
val options = invoke.getObject("options")
|
||||
if (options == null) {
|
||||
invoke.reject("Missing `options` input")
|
||||
return
|
||||
}
|
||||
val kind = invoke.getString("kind", "")
|
||||
val args = invoke.parseArgs(WriteOptions::class.java)
|
||||
|
||||
val clipData = when (kind) {
|
||||
"PlainText" -> {
|
||||
val label = options.getString("label", "")
|
||||
val text = options.getString("text", "")
|
||||
ClipData.newPlainText(label, text)
|
||||
val clipData = when (args) {
|
||||
is WriteOptions.PlainText -> {
|
||||
ClipData.newPlainText(args.label, args.text)
|
||||
}
|
||||
|
||||
else -> {
|
||||
invoke.reject("Unknown kind $kind")
|
||||
invoke.reject("unimplemented clip data")
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -52,10 +107,12 @@ class ClipboardPlugin(private val activity: Activity) : Plugin(activity) {
|
||||
|
||||
@Command
|
||||
fun read(invoke: Invoke) {
|
||||
val (kind, options) = if (manager.hasPrimaryClip()) {
|
||||
val data = if (manager.hasPrimaryClip()) {
|
||||
if (manager.primaryClipDescription?.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN) == true) {
|
||||
val item: ClipData.Item = manager.primaryClip!!.getItemAt(0)
|
||||
Pair("PlainText", item.text)
|
||||
val data = ReadClipData.PlainText()
|
||||
data.text = item.text.toString()
|
||||
data
|
||||
} else {
|
||||
// TODO
|
||||
invoke.reject("Clipboard content reader not implemented")
|
||||
@@ -66,9 +123,6 @@ class ClipboardPlugin(private val activity: Activity) : Plugin(activity) {
|
||||
return
|
||||
}
|
||||
|
||||
val response = JSObject()
|
||||
response.put("kind", kind)
|
||||
response.put("options", options)
|
||||
invoke.resolve(response)
|
||||
invoke.resolveObject(data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ fn main() {
|
||||
{
|
||||
println!("{error:#}");
|
||||
// when building documentation for Android the plugin build result is irrelevant to the crate itself
|
||||
if !(cfg!(feature = "dox") && std::env::var("TARGET").unwrap().contains("android")) {
|
||||
if !(cfg!(docsrs) && std::env::var("TARGET").unwrap().contains("android")) {
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,7 @@
|
||||
|
||||
import { invoke } from "@tauri-apps/api/primitives";
|
||||
|
||||
interface Clip<K, T> {
|
||||
kind: K;
|
||||
options: T;
|
||||
}
|
||||
|
||||
type ClipResponse = Clip<"PlainText", string>;
|
||||
type ClipResponse = Record<"plainText", { text: string }>;
|
||||
|
||||
/**
|
||||
* Writes plain text to the clipboard.
|
||||
@@ -36,8 +31,7 @@ async function writeText(
|
||||
): Promise<void> {
|
||||
return invoke("plugin:clipboard|write", {
|
||||
data: {
|
||||
kind: "PlainText",
|
||||
options: {
|
||||
plainText: {
|
||||
label: opts?.label,
|
||||
text,
|
||||
},
|
||||
@@ -56,7 +50,7 @@ async function writeText(
|
||||
*/
|
||||
async function readText(): Promise<string> {
|
||||
const kind: ClipResponse = await invoke("plugin:clipboard|read");
|
||||
return kind.options;
|
||||
return kind.plainText.text;
|
||||
}
|
||||
|
||||
export { writeText, readText };
|
||||
|
||||
@@ -2,42 +2,42 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import SwiftRs
|
||||
import Tauri
|
||||
import UIKit
|
||||
import WebKit
|
||||
import Tauri
|
||||
import SwiftRs
|
||||
|
||||
enum WriteOptions: Codable {
|
||||
case plainText(text: String)
|
||||
}
|
||||
|
||||
enum ReadClipData: Codable {
|
||||
case plainText(text: String)
|
||||
}
|
||||
|
||||
class ClipboardPlugin: Plugin {
|
||||
@objc public func write(_ invoke: Invoke) throws {
|
||||
let options = invoke.getObject("options")
|
||||
if let options = options {
|
||||
let clipboard = UIPasteboard.general
|
||||
let kind = invoke.getString("kind", "")
|
||||
switch kind {
|
||||
case "PlainText":
|
||||
let text = options["text"] as? String
|
||||
clipboard.string = text
|
||||
default:
|
||||
invoke.reject("Unknown kind \(kind)")
|
||||
return
|
||||
}
|
||||
invoke.resolve()
|
||||
} else {
|
||||
invoke.reject("Missing `options` input")
|
||||
}
|
||||
}
|
||||
@objc public func write(_ invoke: Invoke) throws {
|
||||
let options = try invoke.parseArgs(WriteOptions.self)
|
||||
let clipboard = UIPasteboard.general
|
||||
switch options {
|
||||
case .plainText(let text):
|
||||
clipboard.string = text
|
||||
default:
|
||||
invoke.unimplemented()
|
||||
return
|
||||
}
|
||||
invoke.resolve()
|
||||
|
||||
@objc public func read(_ invoke: Invoke) throws {
|
||||
let clipboard = UIPasteboard.general
|
||||
if let text = clipboard.string {
|
||||
invoke.resolve([
|
||||
"kind": "PlainText",
|
||||
"options": text
|
||||
])
|
||||
} else {
|
||||
invoke.reject("Clipboard is empty")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func read(_ invoke: Invoke) throws {
|
||||
let clipboard = UIPasteboard.general
|
||||
if let text = clipboard.string {
|
||||
invoke.resolve(ReadClipData.plainText(text: text))
|
||||
} else {
|
||||
invoke.reject("Clipboard is empty")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@_cdecl("init_plugin_clipboard")
|
||||
|
||||
@@ -27,6 +27,6 @@
|
||||
"tslib": "^2.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "2.0.0-alpha.9"
|
||||
"@tauri-apps/api": "2.0.0-alpha.11"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
if("__TAURI__"in window){var __TAURI_CLIPBOARDMANAGER__=function(e){"use strict";var n=Object.defineProperty,t=(e,n,t)=>{if(!n.has(e))throw TypeError("Cannot "+t)},r=(e,n,r)=>(t(e,n,"read from private field"),r?r.call(e):n.get(e));function i(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}((e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})})({},{Channel:()=>s,PluginListener:()=>o,addPluginListener:()=>_,convertFileSrc:()=>c,invoke:()=>l,transformCallback:()=>i});var a,s=class{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,((e,n,t)=>{if(n.has(e))throw TypeError("Cannot add the same private member more than once");n instanceof WeakSet?n.add(e):n.set(e,t)})(this,a,(()=>{})),this.id=i((e=>{r(this,a).call(this,e)}))}set onmessage(e){var n,r,i,s;i=e,t(n=this,r=a,"write to private field"),s?s.call(n,i):r.set(n,i)}get onmessage(){return r(this,a)}toJSON(){return`__CHANNEL__:${this.id}`}};a=new WeakMap;var o=class{constructor(e,n,t){this.plugin=e,this.event=n,this.channelId=t}async unregister(){return l(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}};async function _(e,n,t){let r=new s;return r.onmessage=t,l(`plugin:${e}|register_listener`,{event:n,handler:r}).then((()=>new o(e,n,r.id)))}async function l(e,n={},t){return window.__TAURI_INTERNALS__.invoke(e,n,t)}function c(e,n="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(e,n)}return e.readText=async function(){return(await l("plugin:clipboard|read")).options},e.writeText=async function(e,n){return l("plugin:clipboard|write",{data:{kind:"PlainText",options:{label:null==n?void 0:n.label,text:e}}})},e}({});Object.defineProperty(window.__TAURI__,"clipboardManager",{value:__TAURI_CLIPBOARDMANAGER__})}
|
||||
if("__TAURI__"in window){var __TAURI_CLIPBOARDMANAGER__=function(e){"use strict";async function n(e,n={},r){return window.__TAURI_INTERNALS__.invoke(e,n,r)}return"function"==typeof SuppressedError&&SuppressedError,e.readText=async function(){return(await n("plugin:clipboard|read")).plainText.text},e.writeText=async function(e,r){return n("plugin:clipboard|write",{data:{plainText:{label:null==r?void 0:r.label,text:e}}})},e}({});Object.defineProperty(window.__TAURI__,"clipboardManager",{value:__TAURI_CLIPBOARDMANAGER__})}
|
||||
|
||||
@@ -39,7 +39,7 @@ impl<R: Runtime> Clipboard<R> {
|
||||
match &self.clipboard {
|
||||
Ok(clipboard) => {
|
||||
let text = clipboard.lock().unwrap().get_text()?;
|
||||
Ok(ClipboardContents::PlainText(text))
|
||||
Ok(ClipboardContents::PlainText { text })
|
||||
}
|
||||
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
|
||||
}
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(tag = "kind", content = "options")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum ClipKind {
|
||||
PlainText { label: Option<String>, text: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(tag = "kind", content = "options")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum ClipboardContents {
|
||||
PlainText(String),
|
||||
PlainText { text: String },
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user