Skip to content

A Tauri clipboard plugin for both text and image content

License

Notifications You must be signed in to change notification settings

ktlwap/tauri-plugin-clipboard

 
 

Repository files navigation

Tauri Plugin clipboard

A Tauri plugin for clipboard IO. Support both text and image.

The reason I built this plugin is becasue official Tauri API only supports clipboard with text, not image. So you can still use the official API for text.

One thing about clipboard image io is that the input and output is always base64 png string.

Installation

If you are installing from npm and crate.io package registry, make sure the versions for both packages are the same, otherwise, the API may not match.

Crate: https://crates.io/crates/tauri-plugin-clipboard

cargo add tauri-plugin-clipboard to add the package.

Or add the following to your Cargo.toml for the latest unpublished version (not recommanded).

tauri-plugin-clipboard = { git = "https://github.com/CrossCopy/tauri-plugin-clipboard", tag = "v0.3.2" }

Run the following to install JavaScript/TypeScript API package.

npm i tauri-plugin-clipboard-api
# npm add https://github.com/CrossCopy/tauri-plugin-clipboard # or this for latest unpublished version (not recommended)

In main.rs, add the following to your tauri::Builder:

tauri::Builder::default()
    .plugin(tauri_plugin_clipboard::init())
    .run(tauri::generate_context!())
    .expect("failed to run app");

Read more in the official doc about how to use.

Example

npm run build
cd examples/svelte-app
npm run tauri dev
# there are a few buttons you can click to test the clipboard plugin

See App.svelte for an example of how to use the plugin in JS/TS.

It works the same with other frontend frameworks like Vue, React, etc.

Sample Usage (TypeScript API)

import {
    writeText,
    readText,
    readImage,
    writeImage,
} from "tauri-plugin-clipboard-api";
readText().then((text) => {
    // TODO
});

writeText("huakun zui shuai").then(() => {});

readImage()
.then((base64Img) => {
    imageStr = `data:image/png;base64, ${base64Img}`
})
.catch((err) => {
    alert(err);
});

writeImage(sample_base64_image).then(() => {
    // TODO
});

Sample Usage (Rust API)

use tauri::Manager;
use tauri_plugin_clipboard::ManagerExt;

fn main() {
  tauri::Builder::default()
    .plugin(tauri_plugin_clipboard::init())
    .setup(|app| {
        let app_handle = app.app_handle();
        match app_handle.clipboard().read_text() {
            Ok(result) => {
                println!("content: {}", result);
            },
            Err(e) => print!("err is \"{}\"\n", e), // TODO: log
        };
        Ok(())
    })
    .build(tauri::generate_context!())
    .expect("failed to run app");
}

Sample Listener Usage

We use Tauri's event system. Start a listener with Tauri's listen() function to start listening for event, and call listenImage() and listenText() to listen for clipboard update. When clipboard is updated, event will be emitted.

The following example is in svelte.

import { emit, listen, type UnlistenFn } from "@tauri-apps/api/event";
import {
    TEXT_CHANGED,
    IMAGE_CHANGED,
    listenText,
    listenImage,
    listenToClipboard,
} from "tauri-plugin-clipboard-api";

let listenTextContent = "";
let listenImageContent = "";
let tauriTextUnlisten: UnlistenFn;
let tauriImageUnlisten: UnlistenFn;
let listenToClipboardUnlisten: UnlistenFn;
let textUnlisten: () => void;
let imageUnlisten: () => void;

export async function startListening() {
    tauriTextUnlisten = await listen(TEXT_CHANGED, (event) => {
        console.log(event);
        listenTextContent = (event.payload as any).value;
    });
    tauriImageUnlisten = await listen(IMAGE_CHANGED, (event) => {
        console.log(event);
        listenImageContent = (event.payload as any).value;
    });
    // ==================== Choose from one of the two options below ====================
    // listen separately with JavaScript by comparing previous value and current value
    imageUnlisten = listenImage();
    textUnlisten = listenText();
    // or
    // listen on both text and image using clipboard-master crate (recommended, should be more efficient)
    listenToClipboardUnlisten = await listenToClipboard(); // start listener for both text and image
    // ==================================================================================
}

function stopListening() {
    imageUnlisten();
    textUnlisten();
    tauriTextUnlisten();
    tauriImageUnlisten();
    listenToClipboardUnlisten();
}

onMount(() => {
    startListening();
});

onDestroy(() => {
    stopListening();
});

The base64 image string can be converted to Uint8Array and written to file system using tauri's fs API.

import { writeBinaryFile, BaseDirectory } from "@tauri-apps/api/fs";

writeBinaryFile('tmp/avatar.png', new Uint8Array(atob(base64Img).split('').map(char => char.charCodeAt(0))), { dir: BaseDirectory.Cache })

About

A Tauri clipboard plugin for both text and image content

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Rust 65.3%
  • TypeScript 30.0%
  • JavaScript 4.7%