mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-04-21 11:26:15 +02:00
feat(clipboard): Implement HTML and clear functionality (#977)
* Implement arboard HTML features (desktop only) and ability to trigger clipboard clear Signed-off-by: TukanDev <contact@tukandev.com> * Update readme of clipboard plugin Signed-off-by: TukanDev <contact@tukandev.com> * Update plugins/clipboard-manager/src/desktop.rs Propagate error for clear as requested Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com> * Update plugins/clipboard-manager/guest-js/index.ts Change to camelCase as requested Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com> * Update plugins/clipboard-manager/guest-js/index.ts use camelCase here too Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com> * Update README.md Revert back as mentioned in HTML PR * Update index.ts After discussion readHtml() is decided to be removed. Will follow and remove corresponding rust side function too. * Strip all other existence of read_html out as determined in HTML support PR conversation Signed-off-by: TukanDev <contact@tukandev.com> * Apply requested changes v2 Signed-off-by: TukanDev <contact@tukandev.com> * pnpm run build and cargo fmt Signed-off-by: TukanDev <contact@tukandev.com> * Update plugins/clipboard-manager/src/mobile.rs fix ci calling Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com> * mobile read_html omg.... Signed-off-by: TukanDev <contact@tukandev.com> * Update plugins/clipboard-manager/src/mobile.rs * pnpm format.... Signed-off-by: TukanDev <contact@tukandev.com> * error on mobile as well * clear on mobile * change file --------- Signed-off-by: TukanDev <contact@tukandev.com>
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"clipboard-manager": patch
|
||||
"clipboard-manager-js": patch
|
||||
---
|
||||
|
||||
Add support for writing HTML content to the clipboard.
|
||||
@@ -60,7 +60,7 @@ fn main() {
|
||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||
|
||||
```javascript
|
||||
import { writeText, readText } from "@tauri-apps/plugin-clipboard-manager";
|
||||
import { writeText, readText, writeHtml, readHtml, clear } from "@tauri-apps/plugin-clipboard-manager";
|
||||
await writeText("Tauri is awesome!");
|
||||
assert(await readText(), "Tauri is awesome!");
|
||||
```
|
||||
|
||||
@@ -53,4 +53,43 @@ async function readText(): Promise<string> {
|
||||
return kind.plainText.text;
|
||||
}
|
||||
|
||||
export { writeText, readText };
|
||||
/**
|
||||
* Writes HTML or fallbacks to write provided plain text to the clipboard.
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { writeHtml, readHtml } from '@tauri-apps/plugin-clipboard-manager';
|
||||
* await writeHtml('<h1>Tauri is awesome!</h1>', 'plaintext');
|
||||
* await writeHtml('<h1>Tauri is awesome!</h1>', '<h1>Tauri is awesome</h1>'); // Will write "<h1>Tauri is awesome</h1>" as plain text
|
||||
* assert(await readText(), '<h1>Tauri is awesome!</h1>');
|
||||
* ```
|
||||
*
|
||||
* @returns A promise indicating the success or failure of the operation.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function writeHtml(html: string, altHtml?: string): Promise<void> {
|
||||
return invoke("plugin:clipboard-manager|write_html", {
|
||||
data: {
|
||||
html: {
|
||||
html,
|
||||
altHtml,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the clipboard.
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { clear } from '@tauri-apps/plugin-clipboard-manager';
|
||||
* await clear();
|
||||
* ```
|
||||
* @since 2.0.0
|
||||
*/
|
||||
async function clear(): Promise<void> {
|
||||
await invoke("plugin:clipboard-manager|clear");
|
||||
return;
|
||||
}
|
||||
|
||||
export { writeText, readText, writeHtml, clear };
|
||||
|
||||
@@ -1 +1 @@
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_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-manager|read")).plainText.text},e.writeText=async function(e,r){return n("plugin:clipboard-manager|write",{data:{plainText:{label:r?.label,text:e}}})},e}({});Object.defineProperty(window.__TAURI__,"clipboardManager",{value:__TAURI_PLUGIN_CLIPBOARDMANAGER__})}
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_CLIPBOARDMANAGER__=function(n){"use strict";async function r(n,r={},a){return window.__TAURI_INTERNALS__.invoke(n,r,a)}return"function"==typeof SuppressedError&&SuppressedError,n.clear=async function(){await r("plugin:clipboard-manager|clear")},n.readText=async function(){return(await r("plugin:clipboard-manager|read")).plainText.text},n.writeHtml=async function(n,a){return r("plugin:clipboard-manager|write_html",{data:{html:{html:n,altHtml:a}}})},n.writeText=async function(n,a){return r("plugin:clipboard-manager|write",{data:{plainText:{label:a?.label,text:n}}})},n}({});Object.defineProperty(window.__TAURI__,"clipboardManager",{value:__TAURI_PLUGIN_CLIPBOARDMANAGER__})}
|
||||
|
||||
@@ -22,3 +22,20 @@ pub(crate) async fn read<R: Runtime>(
|
||||
) -> Result<ClipboardContents> {
|
||||
clipboard.read()
|
||||
}
|
||||
|
||||
#[command]
|
||||
pub(crate) async fn write_html<R: Runtime>(
|
||||
_app: AppHandle<R>,
|
||||
clipboard: State<'_, Clipboard<R>>,
|
||||
data: ClipKind,
|
||||
) -> Result<()> {
|
||||
clipboard.write_html(data)
|
||||
}
|
||||
|
||||
#[command]
|
||||
pub(crate) async fn clear<R: Runtime>(
|
||||
_app: AppHandle<R>,
|
||||
clipboard: State<'_, Clipboard<R>>,
|
||||
) -> Result<()> {
|
||||
clipboard.clear()
|
||||
}
|
||||
|
||||
@@ -28,10 +28,12 @@ pub struct Clipboard<R: Runtime> {
|
||||
|
||||
impl<R: Runtime> Clipboard<R> {
|
||||
pub fn write(&self, kind: ClipKind) -> crate::Result<()> {
|
||||
let ClipKind::PlainText { text, .. } = kind;
|
||||
match &self.clipboard {
|
||||
Ok(clipboard) => clipboard.lock().unwrap().set_text(text).map_err(Into::into),
|
||||
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
|
||||
match kind {
|
||||
ClipKind::PlainText { text, .. } => match &self.clipboard {
|
||||
Ok(clipboard) => clipboard.lock().unwrap().set_text(text).map_err(Into::into),
|
||||
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
|
||||
},
|
||||
_ => Err(crate::Error::Clipboard("Invalid clip kind!".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,4 +46,25 @@ impl<R: Runtime> Clipboard<R> {
|
||||
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_html(&self, kind: ClipKind) -> crate::Result<()> {
|
||||
match kind {
|
||||
ClipKind::Html { html, alt_html, .. } => match &self.clipboard {
|
||||
Ok(clipboard) => clipboard
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_html(html, alt_html)
|
||||
.map_err(Into::into),
|
||||
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
|
||||
},
|
||||
_ => Err(crate::Error::Clipboard("Invalid clip kind!".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&self) -> crate::Result<()> {
|
||||
match &self.clipboard {
|
||||
Ok(clipboard) => clipboard.lock().unwrap().clear().map_err(Into::into),
|
||||
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ pub enum Error {
|
||||
#[cfg(mobile)]
|
||||
#[error(transparent)]
|
||||
PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError),
|
||||
#[cfg(desktop)]
|
||||
#[error("{0}")]
|
||||
Clipboard(String),
|
||||
}
|
||||
|
||||
@@ -49,7 +49,14 @@ impl<R: Runtime, T: Manager<R>> crate::ClipboardExt<R> for T {
|
||||
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
Builder::new("clipboard-manager")
|
||||
.js_init_script(include_str!("api-iife.js").to_string())
|
||||
.invoke_handler(tauri::generate_handler![commands::write, commands::read])
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
commands::write,
|
||||
commands::read,
|
||||
#[cfg(desktop)]
|
||||
commands::write_html,
|
||||
#[cfg(desktop)]
|
||||
commands::clear
|
||||
])
|
||||
.setup(|app, api| {
|
||||
#[cfg(mobile)]
|
||||
let clipboard = mobile::init(app, api)?;
|
||||
|
||||
@@ -39,4 +39,17 @@ impl<R: Runtime> Clipboard<R> {
|
||||
pub fn read(&self) -> crate::Result<ClipboardContents> {
|
||||
self.0.run_mobile_plugin("read", ()).map_err(Into::into)
|
||||
}
|
||||
|
||||
// Treat HTML as unsupported on mobile until tested
|
||||
pub fn write_html(&self, _kind: ClipKind) -> crate::Result<()> {
|
||||
Err(crate::Error::Clipboard(
|
||||
"Unsupported on this platform".to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn clear(&self) -> crate::Result<()> {
|
||||
Err(crate::Error::Clipboard(
|
||||
"Unsupported on this platform".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,14 @@ use serde::{Deserialize, Serialize};
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum ClipKind {
|
||||
PlainText { label: Option<String>, text: String },
|
||||
PlainText {
|
||||
label: Option<String>,
|
||||
text: String,
|
||||
},
|
||||
Html {
|
||||
html: String,
|
||||
alt_html: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
||||
Reference in New Issue
Block a user