tauri-plugin-thumbar 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +185 -3
- package/dist-js/index.cjs +63 -0
- package/dist-js/index.d.ts +53 -0
- package/dist-js/index.js +56 -0
- package/package.json +36 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Miaoyww
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,185 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# tauri-plugin-thumbar
|
|
2
|
+
|
|
3
|
+
Runtime-defined Windows taskbar thumbnail toolbar controls for Tauri applications.
|
|
4
|
+
|
|
5
|
+
The button list is supplied at runtime. Windows only lets an application add
|
|
6
|
+
buttons to a window's thumbnail toolbar once, so `initialize` takes the complete
|
|
7
|
+
list (up to 7 buttons) and `update` changes icon, tooltip, enabled and visible
|
|
8
|
+
state afterwards. `set_cover` replaces the taskbar hover thumbnail with a static
|
|
9
|
+
cover image.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
This plugin targets Tauri v2 and Rust 1.77.2+.
|
|
14
|
+
|
|
15
|
+
Add the Rust crate to your `src-tauri/Cargo.toml`:
|
|
16
|
+
|
|
17
|
+
```toml
|
|
18
|
+
[dependencies]
|
|
19
|
+
tauri-plugin-thumbar = "0.1.0"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Add the JS bindings package:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
pnpm add tauri-plugin-thumbar
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Rust setup
|
|
29
|
+
|
|
30
|
+
Register the plugin in your Tauri builder:
|
|
31
|
+
|
|
32
|
+
```rust
|
|
33
|
+
fn run() {
|
|
34
|
+
tauri::Builder::default()
|
|
35
|
+
.plugin(tauri_plugin_thumbar::init())
|
|
36
|
+
.run(tauri::generate_context!())
|
|
37
|
+
.expect("error while running tauri app");
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Initialize the toolbar from the app setup hook:
|
|
42
|
+
|
|
43
|
+
```rust
|
|
44
|
+
use tauri::Manager;
|
|
45
|
+
use tauri_plugin_thumbar::{Button, ThumbarExt};
|
|
46
|
+
|
|
47
|
+
tauri::Builder::default()
|
|
48
|
+
.plugin(tauri_plugin_thumbar::init())
|
|
49
|
+
.setup(|app| {
|
|
50
|
+
let window = app.get_webview_window("main").unwrap();
|
|
51
|
+
|
|
52
|
+
app.thumbar().initialize(
|
|
53
|
+
&window,
|
|
54
|
+
vec![
|
|
55
|
+
Button::new(1, "icons/thumbar/previous.ico")
|
|
56
|
+
.tooltip("Previous")
|
|
57
|
+
.event("thumbar-previous"),
|
|
58
|
+
Button::new(2, "icons/thumbar/play.ico")
|
|
59
|
+
.tooltip("Play")
|
|
60
|
+
.event("thumbar-toggle"),
|
|
61
|
+
Button::new(3, "icons/thumbar/next.ico")
|
|
62
|
+
.tooltip("Next")
|
|
63
|
+
.event("thumbar-next"),
|
|
64
|
+
],
|
|
65
|
+
Some(Box::new(|window, id| {
|
|
66
|
+
// Runs on the window's UI thread. Do not block; forward to a
|
|
67
|
+
// channel or another thread instead.
|
|
68
|
+
let _ = (window, id);
|
|
69
|
+
})),
|
|
70
|
+
)?;
|
|
71
|
+
|
|
72
|
+
Ok(())
|
|
73
|
+
})
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Update a button later:
|
|
77
|
+
|
|
78
|
+
```rust
|
|
79
|
+
use tauri_plugin_thumbar::ButtonUpdate;
|
|
80
|
+
|
|
81
|
+
app.thumbar().update(
|
|
82
|
+
&window,
|
|
83
|
+
ButtonUpdate::new(2)
|
|
84
|
+
.icon("icons/thumbar/pause.ico")
|
|
85
|
+
.tooltip("Pause"),
|
|
86
|
+
)?;
|
|
87
|
+
|
|
88
|
+
app.thumbar().update(&window, ButtonUpdate::new(3).enabled(false))?;
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Buttons
|
|
92
|
+
|
|
93
|
+
- At most **7** buttons are supported by the Windows thumbnail toolbar.
|
|
94
|
+
- `id` must be unique within the window and in `1..=65535`.
|
|
95
|
+
- `icon` is a Tauri resource path to an `.ico` file. Bundle the file through
|
|
96
|
+
`tauri.conf.json` (`bundle.resources`).
|
|
97
|
+
- `enabled` and `visible` default to `true`.
|
|
98
|
+
- `event` is optional. When set, the plugin emits that app event on click with
|
|
99
|
+
`{ id, window }` as the payload.
|
|
100
|
+
|
|
101
|
+
Buttons can only be added once per window. Use `update` to change the icon,
|
|
102
|
+
tooltip, enabled or visible state; use `visible: false` to hide a button instead
|
|
103
|
+
of removing it.
|
|
104
|
+
|
|
105
|
+
## Cover
|
|
106
|
+
|
|
107
|
+
`set_cover` makes DWM render a static image in the taskbar hover thumbnail
|
|
108
|
+
instead of a live preview of the window. `clear_cover` restores the live
|
|
109
|
+
thumbnail.
|
|
110
|
+
|
|
111
|
+
The cover can come from an absolute local path or from encoded image bytes:
|
|
112
|
+
|
|
113
|
+
```rust
|
|
114
|
+
use tauri_plugin_thumbar::{Cover, ThumbarExt};
|
|
115
|
+
|
|
116
|
+
app.thumbar().set_cover(&window, Some(Cover::from_path("/path/to/cover.jpg")))?;
|
|
117
|
+
app.thumbar().set_cover(&window, Some(Cover::from_bytes(cover_bytes)))?;
|
|
118
|
+
app.thumbar().set_cover(&window, None)?;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
From JavaScript:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { clearCover, setCoverFromBytes, setCoverFromPath } from 'tauri-plugin-thumbar'
|
|
125
|
+
|
|
126
|
+
await setCoverFromPath('C:\\cache\\cover.jpg')
|
|
127
|
+
await setCoverFromBytes(new Uint8Array(await response.arrayBuffer()))
|
|
128
|
+
await clearCover()
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
- Call `initialize` before `set_cover`; the cover belongs to an initialized
|
|
132
|
+
window.
|
|
133
|
+
- PNG, JPEG, WebP and GIF are supported.
|
|
134
|
+
- The encoded image must not exceed **16 MiB**.
|
|
135
|
+
- Paths must be absolute; relative paths are rejected.
|
|
136
|
+
- The cover stays attached until `clear_cover` or the window is destroyed.
|
|
137
|
+
- The image is scaled to fit and letterboxed on black. It is rendered when DWM
|
|
138
|
+
requests the thumbnail, for both the iconic thumbnail and the peek preview.
|
|
139
|
+
- Setting `DWMWA_FORCE_ICONIC_REPRESENTATION` is required for this behavior.
|
|
140
|
+
It forces the iconic representation for the window's taskbar thumbnail and
|
|
141
|
+
peek preview; Windows versions that show a full-size peek preview from the
|
|
142
|
+
Alt+Tab switcher may therefore use the cover there as well.
|
|
143
|
+
|
|
144
|
+
## JavaScript usage
|
|
145
|
+
|
|
146
|
+
Add the plugin's default permission to your capability (for example
|
|
147
|
+
`src-tauri/capabilities/default.json`):
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"permissions": ["thumbar:default"]
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
import { initialize, isSupported, update } from 'tauri-plugin-thumbar'
|
|
157
|
+
import { listen } from '@tauri-apps/api/event'
|
|
158
|
+
|
|
159
|
+
if (await isSupported()) {
|
|
160
|
+
await initialize([
|
|
161
|
+
{ id: 1, icon: 'icons/thumbar/previous.ico', tooltip: 'Previous', event: 'thumbar-previous' },
|
|
162
|
+
{ id: 2, icon: 'icons/thumbar/play.ico', tooltip: 'Play', event: 'thumbar-toggle' },
|
|
163
|
+
{ id: 3, icon: 'icons/thumbar/next.ico', tooltip: 'Next', event: 'thumbar-next' }
|
|
164
|
+
])
|
|
165
|
+
|
|
166
|
+
await update({ id: 2, icon: 'icons/thumbar/pause.ico', tooltip: 'Pause' })
|
|
167
|
+
|
|
168
|
+
const unlisten = await listen<{ id: number; window: string }>('thumbar-toggle', (event) => {
|
|
169
|
+
console.log(event.payload.id, event.payload.window)
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Production notes
|
|
175
|
+
|
|
176
|
+
- This plugin does **not** set App User Model ID (AUMID). Set it once in your
|
|
177
|
+
app entrypoint if you need a stable shell identity for notifications, jump
|
|
178
|
+
lists or taskbar pinning.
|
|
179
|
+
- Ensure configured icon files are included as Tauri bundle resources.
|
|
180
|
+
- Non-Windows platforms intentionally succeed with no-op behavior for
|
|
181
|
+
cross-platform safety.
|
|
182
|
+
- The Rust click handler runs inside the window procedure on the UI thread.
|
|
183
|
+
Keep it non-blocking.
|
|
184
|
+
- If Explorer restarts, the plugin re-adds the current button state when the
|
|
185
|
+
taskbar button is recreated.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@tauri-apps/api/core');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Adds the complete thumbnail toolbar button list to the current window.
|
|
7
|
+
*
|
|
8
|
+
* Windows only allows buttons to be added once per window. Call `update` for
|
|
9
|
+
* subsequent changes; at most 7 buttons are supported.
|
|
10
|
+
*/
|
|
11
|
+
async function initialize(buttons) {
|
|
12
|
+
await core.invoke('plugin:thumbar|initialize', { buttons });
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Updates an existing button's icon, tooltip, enabled or visible state.
|
|
16
|
+
*/
|
|
17
|
+
async function update(button) {
|
|
18
|
+
await core.invoke('plugin:thumbar|update', { button });
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Sets the taskbar hover thumbnail from an absolute local image path.
|
|
22
|
+
*
|
|
23
|
+
* PNG, JPEG, WebP and GIF are supported, up to 16 MiB.
|
|
24
|
+
*/
|
|
25
|
+
async function setCoverFromPath(path) {
|
|
26
|
+
await core.invoke('plugin:thumbar|set_cover', { cover: { path } });
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Sets the taskbar hover thumbnail from encoded image bytes.
|
|
30
|
+
*
|
|
31
|
+
* PNG, JPEG, WebP and GIF are supported, up to 16 MiB.
|
|
32
|
+
*/
|
|
33
|
+
async function setCoverFromBytes(bytes) {
|
|
34
|
+
const data = toBase64(bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes));
|
|
35
|
+
await core.invoke('plugin:thumbar|set_cover', { cover: { data } });
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Restores the live window thumbnail on the taskbar.
|
|
39
|
+
*/
|
|
40
|
+
async function clearCover() {
|
|
41
|
+
await core.invoke('plugin:thumbar|set_cover', { cover: null });
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Returns whether the current platform supports native thumbnail toolbars.
|
|
45
|
+
*/
|
|
46
|
+
async function isSupported() {
|
|
47
|
+
return await core.invoke('plugin:thumbar|is_supported');
|
|
48
|
+
}
|
|
49
|
+
function toBase64(bytes) {
|
|
50
|
+
let binary = '';
|
|
51
|
+
const chunkSize = 0x8000;
|
|
52
|
+
for (let index = 0; index < bytes.length; index += chunkSize) {
|
|
53
|
+
binary += String.fromCharCode(...bytes.subarray(index, index + chunkSize));
|
|
54
|
+
}
|
|
55
|
+
return btoa(binary);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
exports.clearCover = clearCover;
|
|
59
|
+
exports.initialize = initialize;
|
|
60
|
+
exports.isSupported = isSupported;
|
|
61
|
+
exports.setCoverFromBytes = setCoverFromBytes;
|
|
62
|
+
exports.setCoverFromPath = setCoverFromPath;
|
|
63
|
+
exports.update = update;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export interface ThumbarButton {
|
|
2
|
+
/** Unique identifier within the window, in 1..=65535. */
|
|
3
|
+
id: number;
|
|
4
|
+
/** Tauri resource path to an .ico file. */
|
|
5
|
+
icon: string;
|
|
6
|
+
tooltip?: string;
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
visible?: boolean;
|
|
9
|
+
/** Optional app event emitted when the button is clicked. */
|
|
10
|
+
event?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ThumbarButtonUpdate {
|
|
13
|
+
id: number;
|
|
14
|
+
icon?: string;
|
|
15
|
+
tooltip?: string;
|
|
16
|
+
enabled?: boolean;
|
|
17
|
+
visible?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface ThumbarClickEvent {
|
|
20
|
+
id: number;
|
|
21
|
+
window: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Adds the complete thumbnail toolbar button list to the current window.
|
|
25
|
+
*
|
|
26
|
+
* Windows only allows buttons to be added once per window. Call `update` for
|
|
27
|
+
* subsequent changes; at most 7 buttons are supported.
|
|
28
|
+
*/
|
|
29
|
+
export declare function initialize(buttons: ThumbarButton[]): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Updates an existing button's icon, tooltip, enabled or visible state.
|
|
32
|
+
*/
|
|
33
|
+
export declare function update(button: ThumbarButtonUpdate): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Sets the taskbar hover thumbnail from an absolute local image path.
|
|
36
|
+
*
|
|
37
|
+
* PNG, JPEG, WebP and GIF are supported, up to 16 MiB.
|
|
38
|
+
*/
|
|
39
|
+
export declare function setCoverFromPath(path: string): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Sets the taskbar hover thumbnail from encoded image bytes.
|
|
42
|
+
*
|
|
43
|
+
* PNG, JPEG, WebP and GIF are supported, up to 16 MiB.
|
|
44
|
+
*/
|
|
45
|
+
export declare function setCoverFromBytes(bytes: Uint8Array | ArrayBuffer): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Restores the live window thumbnail on the taskbar.
|
|
48
|
+
*/
|
|
49
|
+
export declare function clearCover(): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Returns whether the current platform supports native thumbnail toolbars.
|
|
52
|
+
*/
|
|
53
|
+
export declare function isSupported(): Promise<boolean>;
|
package/dist-js/index.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { invoke } from '@tauri-apps/api/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Adds the complete thumbnail toolbar button list to the current window.
|
|
5
|
+
*
|
|
6
|
+
* Windows only allows buttons to be added once per window. Call `update` for
|
|
7
|
+
* subsequent changes; at most 7 buttons are supported.
|
|
8
|
+
*/
|
|
9
|
+
async function initialize(buttons) {
|
|
10
|
+
await invoke('plugin:thumbar|initialize', { buttons });
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Updates an existing button's icon, tooltip, enabled or visible state.
|
|
14
|
+
*/
|
|
15
|
+
async function update(button) {
|
|
16
|
+
await invoke('plugin:thumbar|update', { button });
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Sets the taskbar hover thumbnail from an absolute local image path.
|
|
20
|
+
*
|
|
21
|
+
* PNG, JPEG, WebP and GIF are supported, up to 16 MiB.
|
|
22
|
+
*/
|
|
23
|
+
async function setCoverFromPath(path) {
|
|
24
|
+
await invoke('plugin:thumbar|set_cover', { cover: { path } });
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Sets the taskbar hover thumbnail from encoded image bytes.
|
|
28
|
+
*
|
|
29
|
+
* PNG, JPEG, WebP and GIF are supported, up to 16 MiB.
|
|
30
|
+
*/
|
|
31
|
+
async function setCoverFromBytes(bytes) {
|
|
32
|
+
const data = toBase64(bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes));
|
|
33
|
+
await invoke('plugin:thumbar|set_cover', { cover: { data } });
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Restores the live window thumbnail on the taskbar.
|
|
37
|
+
*/
|
|
38
|
+
async function clearCover() {
|
|
39
|
+
await invoke('plugin:thumbar|set_cover', { cover: null });
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Returns whether the current platform supports native thumbnail toolbars.
|
|
43
|
+
*/
|
|
44
|
+
async function isSupported() {
|
|
45
|
+
return await invoke('plugin:thumbar|is_supported');
|
|
46
|
+
}
|
|
47
|
+
function toBase64(bytes) {
|
|
48
|
+
let binary = '';
|
|
49
|
+
const chunkSize = 0x8000;
|
|
50
|
+
for (let index = 0; index < bytes.length; index += chunkSize) {
|
|
51
|
+
binary += String.fromCharCode(...bytes.subarray(index, index + chunkSize));
|
|
52
|
+
}
|
|
53
|
+
return btoa(binary);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { clearCover, initialize, isSupported, setCoverFromBytes, setCoverFromPath, update };
|
package/package.json
CHANGED
|
@@ -1,6 +1,37 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "tauri-plugin-thumbar",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
1
|
+
{
|
|
2
|
+
"name": "tauri-plugin-thumbar",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "JavaScript bindings for tauri-plugin-thumbar",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"authors": [
|
|
7
|
+
"Miaoyww"
|
|
8
|
+
],
|
|
9
|
+
"repository": "https://github.com/Miaoyww/tauri-plugin-thumbar",
|
|
10
|
+
"type": "module",
|
|
11
|
+
"types": "./dist-js/index.d.ts",
|
|
12
|
+
"main": "./dist-js/index.cjs",
|
|
13
|
+
"module": "./dist-js/index.js",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist-js",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"exports": {
|
|
19
|
+
"types": "./dist-js/index.d.ts",
|
|
20
|
+
"import": "./dist-js/index.js",
|
|
21
|
+
"require": "./dist-js/index.cjs"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "rollup -c && tsc -p guest-js/tsconfig.json",
|
|
25
|
+
"typecheck": "tsc -p guest-js/tsconfig.json --noEmit"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@tauri-apps/api": "^2.0.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
32
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
33
|
+
"rollup": "^4.60.2",
|
|
34
|
+
"tslib": "^2.8.1",
|
|
35
|
+
"typescript": "^5.6.0"
|
|
36
|
+
}
|
|
6
37
|
}
|