Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(clipboard): Implement HTML and clear functionality #977

Merged
merged 19 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from 18 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
2 changes: 1 addition & 1 deletion plugins/clipboard-manager/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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!");
```
Expand Down
41 changes: 40 additions & 1 deletion plugins/clipboard-manager/guest-js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
2 changes: 1 addition & 1 deletion plugins/clipboard-manager/src/api-iife.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions plugins/clipboard-manager/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
31 changes: 27 additions & 4 deletions plugins/clipboard-manager/src/desktop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())),
}
}

Expand All @@ -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())),
}
}
}
1 change: 0 additions & 1 deletion plugins/clipboard-manager/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ pub enum Error {
#[cfg(mobile)]
#[error(transparent)]
PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError),
#[cfg(desktop)]
#[error("{0}")]
Clipboard(String),
}
Expand Down
9 changes: 8 additions & 1 deletion plugins/clipboard-manager/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand Down
13 changes: 13 additions & 0 deletions plugins/clipboard-manager/src/mobile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
))
}
}
9 changes: 8 additions & 1 deletion plugins/clipboard-manager/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
Loading