Skip to content

Commit

Permalink
Bump version to v1.0.1. Add onSomethingUpdate API function
Browse files Browse the repository at this point in the history
  • Loading branch information
HuakunShen committed May 31, 2024
1 parent 7851c5f commit 4dc4125
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 123 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "tauri-plugin-clipboard"
license = "MIT"
version = "1.0.0"
version = "1.0.1"
description = "A clipboard plugin for Tauri that supports text, files and image, as well as clipboard update listening."
authors = [ "Huakun" ]
edition = "2021"
Expand Down
41 changes: 2 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ You need to make sure the package versions is compatible with the correct versio

- Tauri 1.x: package and crate version should start with 1.x
- Tauri 2.x: package and crate version should start with 2.x

- Or you can install with git url and branch `v2`

```toml
Expand Down Expand Up @@ -305,45 +306,7 @@ The returned unlisten function from `startListening` also does two things:
1. Stop monitor thread by invoking `stop_monitor` command to Tauri core.
2. Stop listener started in `listenToClipboard`.

For more details read the source code from [./webview-src/api.ts](./webview-src/api.ts).

#### Break On Type

`listenToClipboard` and `startListening` function takes an optional parameter `breakOnType` with type

```ts
type BreakOnTypeInput = {
text?: boolean;
html?: boolean;
rtf?: boolean;
image?: boolean;
files?: boolean;
};
```

This parameter is used to break the monitor event emission when the clipboard content type matches the type. For example, when HTML content is copied, text update event will also be emitted.

The order of type checking is `file -> image -> html -> rtf -> text`.

The default `breakOnType` is

```ts
{
text: false,
html: false,
rtf: false,
image: false,
files: true
}
```

When files are copied, text is also updated. By default, text update event will not be emitted when files are copied.

If you don't want to listen to text update when HTML content is copied, you can set `breakOnType` to `{ html: true }`.

Read more
- https://crosscopy.github.io/tauri-plugin-clipboard/functions/listenToClipboard.html
- https://crosscopy.github.io/tauri-plugin-clipboard/functions/startListening.html
For more details read the source code from [./webview-src/api.ts](./webview-src/api.ts) and documentation https://crosscopy.github.io/tauri-plugin-clipboard.

### Image

Expand Down
2 changes: 1 addition & 1 deletion examples/demo/package-lock.json

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

6 changes: 6 additions & 0 deletions examples/demo/src/lib/components/listener.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
onRTFUpdate,
onFilesUpdate,
startListening,
onSomethingUpdate,
listenToMonitorStatusUpdate,
isMonitorRunning,
hasHTML,
Expand All @@ -30,6 +31,7 @@
let unlistenRTF: UnlistenFn;
let unlistenClipboard: () => Promise<void>;
let unlistenFiles: UnlistenFn;
let unlistenSomethingUpdate: UnlistenFn;
const has = {
hasHTML: false,
hasImage: false,
Expand Down Expand Up @@ -62,6 +64,10 @@
unlistenRTF = await onRTFUpdate((newRTF) => {
rtf = newRTF;
});
unlistenSomethingUpdate = await onSomethingUpdate((updatedTypes) => {
console.log('updated types:', updatedTypes);
});
unlistenClipboard = await startListening();
onClipboardUpdate(async () => {
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tauri-plugin-clipboard-api",
"version": "1.0.0",
"version": "1.0.1",
"author": "Huakun Shen",
"type": "module",
"description": "",
Expand Down
39 changes: 17 additions & 22 deletions webview-dist/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { z } from "zod";
import { UnlistenFn } from "@tauri-apps/api/event";
export declare const START_MONITOR_COMMAND = "plugin:clipboard|start_monitor";
export declare const STOP_MONITOR_COMMAND = "plugin:clipboard|stop_monitor";
export declare const SOMETHING_CHANGED = "plugin:clipboard://something-changed";
export declare const TEXT_CHANGED = "plugin:clipboard://text-changed";
export declare const HTML_CHANGED = "plugin:clipboard://html-changed";
export declare const RTF_CHANGED = "plugin:clipboard://rtf-changed";
Expand Down Expand Up @@ -113,36 +114,19 @@ export declare function startBruteForceTextMonitor(delay?: number): () => void;
* @returns stop running function that can be called to stop the monitor
*/
export declare function startBruteForceImageMonitor(delay?: number): () => void;
export declare const BreakOnType: z.ZodObject<{
text: z.ZodDefault<z.ZodBoolean>;
html: z.ZodDefault<z.ZodBoolean>;
rtf: z.ZodDefault<z.ZodBoolean>;
image: z.ZodDefault<z.ZodBoolean>;
files: z.ZodDefault<z.ZodBoolean>;
}, "strip", z.ZodTypeAny, {
declare type UpdatedTypes = {
text: boolean;
html: boolean;
rtf: boolean;
image: boolean;
files: boolean;
}, {
text?: boolean | undefined;
html?: boolean | undefined;
rtf?: boolean | undefined;
image?: boolean | undefined;
files?: boolean | undefined;
}>;
export declare type BreakOnTypeInput = z.input<typeof BreakOnType>;
export declare type BreakOnType = z.infer<typeof BreakOnType>;
export declare const DefaultBreakOn: BreakOnType;
};
/**
* Listen to "plugin:clipboard://clipboard-monitor/update" from Tauri core.
* But this event doesn't tell us whether text or image is updated,
* so this function will detect which is changed and emit the corresponding event
* Event constant variables: TEXT_CHANGED or IMAGE_CHANGED
* The corresponding clipboard type event will be emitted when there is clipboard update.
* @returns unlisten function
*/
export declare function listenToClipboard(breakOn?: BreakOnTypeInput): Promise<UnlistenFn>;
export declare function listenToClipboard(): Promise<UnlistenFn>;
/**
* This listen to clipboard monitor update event, and trigger the callback function.
* However from this event we don't know whether it's text or image, no real data is returned.
Expand All @@ -152,6 +136,16 @@ export declare function listenToClipboard(breakOn?: BreakOnTypeInput): Promise<U
*/
export declare function onClipboardUpdate(cb: () => void): Promise<UnlistenFn>;
export declare function onTextUpdate(cb: (text: string) => void): Promise<UnlistenFn>;
/**
* Listen to clipboard update event and get the updated types in a callback.
* This listener tells you what types of data are updated.
* This relies on `listenToClipboard()` who emits events this function listens to.
* You can run `listenToClipboard()` or `startListening()` before calling this function.
* When HTML is copied, this will be passed to callback: {files: false, image: false, html: true, rtf: false, text: true}
* @param cb
* @returns
*/
export declare function onSomethingUpdate(cb: (updatedTypes: UpdatedTypes) => void): Promise<UnlistenFn>;
export declare function onHTMLUpdate(cb: (text: string) => void): Promise<UnlistenFn>;
export declare function onRTFUpdate(cb: (text: string) => void): Promise<UnlistenFn>;
export declare function onFilesUpdate(cb: (files: string[]) => void): Promise<UnlistenFn>;
Expand Down Expand Up @@ -180,4 +174,5 @@ export declare function stopMonitor(): Promise<void>;
* @param cb callback to be called when there is monitor status update
*/
export declare function listenToMonitorStatusUpdate(cb: (running: boolean) => void): Promise<UnlistenFn>;
export declare function startListening(breakOn?: BreakOnTypeInput): Promise<() => Promise<void>>;
export declare function startListening(): Promise<() => Promise<void>>;
export {};
2 changes: 1 addition & 1 deletion webview-dist/index.js

Large diffs are not rendered by default.

102 changes: 46 additions & 56 deletions webview-src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { emit, listen, UnlistenFn } from "@tauri-apps/api/event";

export const START_MONITOR_COMMAND = "plugin:clipboard|start_monitor";
export const STOP_MONITOR_COMMAND = "plugin:clipboard|stop_monitor";
export const SOMETHING_CHANGED = "plugin:clipboard://something-changed";
export const TEXT_CHANGED = "plugin:clipboard://text-changed";
export const HTML_CHANGED = "plugin:clipboard://html-changed";
export const RTF_CHANGED = "plugin:clipboard://rtf-changed";
Expand Down Expand Up @@ -229,65 +230,53 @@ export function startBruteForceImageMonitor(delay: number = 1000) {
};
}

export const BreakOnType = z.object({
text: z.boolean().default(false),
html: z.boolean().default(false),
rtf: z.boolean().default(false),
image: z.boolean().default(false),
files: z.boolean().default(true),
});
export type BreakOnTypeInput = z.input<typeof BreakOnType>;
export type BreakOnType = z.infer<typeof BreakOnType>;
export const DefaultBreakOn: BreakOnType = {
text: false,
html: false,
rtf: false,
image: false,
files: true,
type UpdatedTypes = {
text: boolean;
html: boolean;
rtf: boolean;
image: boolean;
files: boolean;
};

/**
* Listen to "plugin:clipboard://clipboard-monitor/update" from Tauri core.
* The corresponding clipboard type event will be emitted when there is clipboard update.
* Multiple types of clipboard data can be copied at the same time. e.g. When HTML is copied, text is also updated. files copy also update text.
* There is an optional `breakOn` argument to control whether to break event emitting for other types.
* Type checking order: files -> image -> html -> rtf -> text
* If you don't want text update triggered when html is copied, pass breakOn argument `{html: true}`
* By default, files is set to true. When files are copied, text event won't be triggered. If you want text event to be triggered, pass `{files: false}`
*
* Due to the order of checking, the text field doesn't matter as no other types are checked after text.
* @returns unlisten function
*/
export function listenToClipboard(
breakOn: BreakOnTypeInput = DefaultBreakOn
): Promise<UnlistenFn> {
const parseBreakOn = BreakOnType.parse(breakOn);
export function listenToClipboard(): Promise<UnlistenFn> {
return listen(MONITOR_UPDATE_EVENT, async (e) => {
if (e.payload === "clipboard update") {
if (await hasFiles()) {
const flags: UpdatedTypes = {
files: await hasFiles(),
image: await hasImage(),
html: await hasHTML(),
rtf: await hasRTF(),
text: await hasText(),
};
await emit(SOMETHING_CHANGED, flags);
if (flags.files) {
const files = await readFiles();
if (files && files.length > 0) {
await emit(FILES_CHANGED, { value: files });
}
if (parseBreakOn.files) return;
// return; // ! this return is necessary, copying files also update clipboard text, but we don't want text update to be triggered
flags.files = true;
return; // ! this return is necessary, copying files also update clipboard text, but we don't want text update to be triggered
}
if (await hasImage()) {
if (flags.image) {
const img = await readImageBase64();
if (img) await emit(IMAGE_CHANGED, { value: img });
if (parseBreakOn.image) return;
flags.image = true;
}
if (await hasHTML()) {
if (flags.html) {
await emit(HTML_CHANGED, { value: await readHtml() });
if (parseBreakOn.html) return;
flags.html = true;
}
if (await hasRTF()) {
if (flags.rtf) {
await emit(RTF_CHANGED, { value: await readRtf() });
if (parseBreakOn.rtf) return;
flags.rtf = true;
}
if (await hasText()) {
if (flags.text) {
await emit(TEXT_CHANGED, { value: await readText() });
if (parseBreakOn.text) return;
flags.text = true;
}
// when clear() is called, this error is thrown, let ignore it
// if (!success) {
Expand Down Expand Up @@ -317,6 +306,23 @@ export async function onTextUpdate(
});
}

/**
* Listen to clipboard update event and get the updated types in a callback.
* This listener tells you what types of data are updated.
* This relies on `listenToClipboard()` who emits events this function listens to.
* You can run `listenToClipboard()` or `startListening()` before calling this function.
* When HTML is copied, this will be passed to callback: {files: false, image: false, html: true, rtf: false, text: true}
* @param cb
* @returns
*/
export async function onSomethingUpdate(
cb: (updatedTypes: UpdatedTypes) => void
) {
return await listen(SOMETHING_CHANGED, (event) => {
cb(event.payload as UpdatedTypes);
});
}

export async function onHTMLUpdate(
cb: (text: string) => void
): Promise<UnlistenFn> {
Expand Down Expand Up @@ -397,25 +403,9 @@ export async function listenToMonitorStatusUpdate(
});
}

/**
* Start monitor service thread with `startMonitor()` and then run `listenToClipboard()`
* The corresponding clipboard type event will be emitted when there is clipboard update.
* Use `onImageUpdate()`, `onTextUpdate()`, `onHTMLUpdate()`, `onFilesUpdate()`, `onRTFUpdate()` to listen to the event after calling this function.
*
* Multiple types of clipboard data can be copied at the same time. e.g. When HTML is copied, text is also updated. files copy also update text.
* There is an optional `breakOn` argument to control whether to break event emitting for other types.
* Type checking order: files -> image -> html -> rtf -> text
* If you don't want text update triggered when html is copied, pass breakOn argument `{html: true}`
* By default, files is set to true. When files are copied, text event won't be triggered. If you want text event to be triggered, pass `{files: false}`
*
* Due to the order of checking, the text field doesn't matter as no other types are checked after text.
* @returns unlisten function
*/
export function startListening(
breakOn: BreakOnTypeInput = DefaultBreakOn
): Promise<() => Promise<void>> {
export function startListening(): Promise<() => Promise<void>> {
return startMonitor()
.then(() => listenToClipboard(breakOn))
.then(() => listenToClipboard())
.then((unlistenClipboard) => {
// return an unlisten function that stop listening to clipboard update and stop the monitor
return async () => {
Expand Down

0 comments on commit 4dc4125

Please sign in to comment.