mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-21 16:31:18 +02:00
Add system tray
This commit is contained in:
37
src-tauri/Cargo.lock
generated
37
src-tauri/Cargo.lock
generated
@@ -1627,12 +1627,46 @@ dependencies = [
|
|||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libappindicator"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db2d3cb96d092b4824cb306c9e544c856a4cb6210c1081945187f7f1924b47e8"
|
||||||
|
dependencies = [
|
||||||
|
"glib",
|
||||||
|
"gtk",
|
||||||
|
"gtk-sys",
|
||||||
|
"libappindicator-sys",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libappindicator-sys"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1b3b6681973cea8cc3bce7391e6d7d5502720b80a581c9a95c9cbaf592826aa"
|
||||||
|
dependencies = [
|
||||||
|
"gtk-sys",
|
||||||
|
"libloading",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.139"
|
version = "0.2.139"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libloading"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "line-wrap"
|
name = "line-wrap"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@@ -3407,6 +3441,7 @@ dependencies = [
|
|||||||
"core-foundation",
|
"core-foundation",
|
||||||
"core-graphics",
|
"core-graphics",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
|
"dirs-next",
|
||||||
"dispatch",
|
"dispatch",
|
||||||
"gdk",
|
"gdk",
|
||||||
"gdk-pixbuf",
|
"gdk-pixbuf",
|
||||||
@@ -3420,6 +3455,7 @@ dependencies = [
|
|||||||
"instant",
|
"instant",
|
||||||
"jni",
|
"jni",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"libappindicator",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"ndk",
|
"ndk",
|
||||||
@@ -3635,6 +3671,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_with",
|
"serde_with",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"toml",
|
||||||
"url",
|
"url",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"windows",
|
"windows",
|
||||||
|
|||||||
@@ -15,15 +15,15 @@ tauri-build = { version = "1.2", features = [] }
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
serde_json = { version = "1.0" }
|
serde_json = { version = "1.0" }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
tauri = { version = "1.2", features = ["devtools", "shell-open", "window-start-dragging"] }
|
tauri = { version = "1.2", features = ["config-toml", "devtools", "shell-open", "system-tray", "window-start-dragging"] }
|
||||||
http = { version = "0.2.8" }
|
http = { version = "0.2.8" }
|
||||||
reqwest = { version = "0.11.14", features = ["json"] }
|
reqwest = { version = "0.11.14", features = ["json"] }
|
||||||
tokio = { version = "1.25.0", features = ["full"] }
|
tokio = { version = "1.25.0", features = ["full"] }
|
||||||
futures = { version = "0.3.26" }
|
futures = { version = "0.3.26" }
|
||||||
deno_core = { version = "0.171.0" }
|
deno_core = { version = "0.171.0" }
|
||||||
deno_ast = { version = "0.24.0", features = ["transpiling"] }
|
deno_ast = { version = "0.24.0", features = ["transpiling"] }
|
||||||
objc = "0.2.7"
|
objc = { version = "0.2.7" }
|
||||||
cocoa = "0.24.1"
|
cocoa = { version = "0.24.1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# by default Tauri runs in production mode
|
# by default Tauri runs in production mode
|
||||||
|
|||||||
@@ -11,16 +11,38 @@ mod commands;
|
|||||||
mod runtime;
|
mod runtime;
|
||||||
mod window_ext;
|
mod window_ext;
|
||||||
|
|
||||||
use tauri::{Manager, WindowEvent};
|
use tauri::{
|
||||||
|
CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
|
||||||
|
WindowEvent,
|
||||||
|
};
|
||||||
use window_ext::WindowExt;
|
use window_ext::WindowExt;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// here `"quit".to_string()` defines the menu item id, and the second parameter is the menu item label.
|
||||||
|
let quit = CustomMenuItem::new("quit".to_string(), "Quit");
|
||||||
|
let tray_menu = SystemTrayMenu::new().add_item(quit);
|
||||||
|
let system_tray = SystemTray::new().with_menu(tray_menu);
|
||||||
|
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
|
.system_tray(system_tray)
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
let win = app.get_window("main").unwrap();
|
let win = app.get_window("main").unwrap();
|
||||||
win.position_traffic_lights();
|
win.position_traffic_lights();
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
.on_system_tray_event(|app, event| match event {
|
||||||
|
SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
|
||||||
|
"quit" => {
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
"hide" => {
|
||||||
|
let window = app.get_window("main").unwrap();
|
||||||
|
window.hide().unwrap();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
})
|
||||||
.on_window_event(|e| {
|
.on_window_event(|e| {
|
||||||
let apply_offset = || {
|
let apply_offset = || {
|
||||||
let win = e.window();
|
let win = e.window();
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
{
|
|
||||||
"build": {
|
|
||||||
"beforeDevCommand": "npm run dev",
|
|
||||||
"beforeBuildCommand": "npm run build",
|
|
||||||
"devPath": "http://localhost:1420",
|
|
||||||
"distDir": "../dist",
|
|
||||||
"withGlobalTauri": false
|
|
||||||
},
|
|
||||||
"package": {
|
|
||||||
"productName": "Twosomnia",
|
|
||||||
"version": "0.0.1"
|
|
||||||
},
|
|
||||||
"tauri": {
|
|
||||||
"allowlist": {
|
|
||||||
"all": false,
|
|
||||||
"shell": {
|
|
||||||
"all": false,
|
|
||||||
"open": true
|
|
||||||
},
|
|
||||||
"window": {
|
|
||||||
"startDragging": true
|
|
||||||
},
|
|
||||||
"fs": {
|
|
||||||
"scope": [
|
|
||||||
"$RESOURCE/*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"bundle": {
|
|
||||||
"active": true,
|
|
||||||
"category": "DeveloperTool",
|
|
||||||
"copyright": "",
|
|
||||||
"deb": {
|
|
||||||
"depends": []
|
|
||||||
},
|
|
||||||
"externalBin": [],
|
|
||||||
"icon": [
|
|
||||||
"icons/32x32.png",
|
|
||||||
"icons/128x128.png",
|
|
||||||
"icons/128x128@2x.png",
|
|
||||||
"icons/icon.icns",
|
|
||||||
"icons/icon.ico"
|
|
||||||
],
|
|
||||||
"identifier": "co.schier.twosomnia",
|
|
||||||
"longDescription": "",
|
|
||||||
"macOS": {
|
|
||||||
"entitlements": null,
|
|
||||||
"exceptionDomain": "",
|
|
||||||
"frameworks": [],
|
|
||||||
"providerShortName": null,
|
|
||||||
"signingIdentity": null
|
|
||||||
},
|
|
||||||
"resources": [
|
|
||||||
"plugins/*"
|
|
||||||
],
|
|
||||||
"shortDescription": "",
|
|
||||||
"targets": "all",
|
|
||||||
"windows": {
|
|
||||||
"certificateThumbprint": null,
|
|
||||||
"digestAlgorithm": "sha256",
|
|
||||||
"timestampUrl": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": {
|
|
||||||
"csp": null
|
|
||||||
},
|
|
||||||
"updater": {
|
|
||||||
"active": false
|
|
||||||
},
|
|
||||||
"windows": [
|
|
||||||
{
|
|
||||||
"fullscreen": false,
|
|
||||||
"height": 800,
|
|
||||||
"resizable": true,
|
|
||||||
"title": "Twosomnia",
|
|
||||||
"width": 1400,
|
|
||||||
"titleBarStyle": "Overlay",
|
|
||||||
"hiddenTitle": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
73
src-tauri/tauri.toml
Normal file
73
src-tauri/tauri.toml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
[build]
|
||||||
|
beforeDevCommand = "npm run dev"
|
||||||
|
beforeBuildCommand = "npm run build"
|
||||||
|
devPath = "http://localhost:1420"
|
||||||
|
distDir = "../dist"
|
||||||
|
withGlobalTauri = false
|
||||||
|
|
||||||
|
[package]
|
||||||
|
productName = "Twosomnia"
|
||||||
|
version = "0.0.1"
|
||||||
|
|
||||||
|
[tauri.allowlist]
|
||||||
|
all = false
|
||||||
|
|
||||||
|
[tauri.allowlist.shell]
|
||||||
|
all = false
|
||||||
|
open = true
|
||||||
|
|
||||||
|
[tauri.allowlist.window]
|
||||||
|
startDragging = true
|
||||||
|
|
||||||
|
[tauri.allowlist.fs]
|
||||||
|
scope = [ "$RESOURCE/*" ]
|
||||||
|
|
||||||
|
[tauri.bundle]
|
||||||
|
active = true
|
||||||
|
category = "DeveloperTool"
|
||||||
|
copyright = ""
|
||||||
|
externalBin = [ ]
|
||||||
|
icon = [
|
||||||
|
"icons/32x32.png",
|
||||||
|
"icons/128x128.png",
|
||||||
|
"icons/128x128@2x.png",
|
||||||
|
"icons/icon.icns",
|
||||||
|
"icons/icon.ico"
|
||||||
|
]
|
||||||
|
identifier = "co.schier.twosomnia"
|
||||||
|
longDescription = ""
|
||||||
|
resources = [ "plugins/*" ]
|
||||||
|
shortDescription = ""
|
||||||
|
targets = "all"
|
||||||
|
|
||||||
|
[tauri.bundle.deb]
|
||||||
|
depends = [ ]
|
||||||
|
|
||||||
|
[tauri.bundle.macOS]
|
||||||
|
exceptionDomain = ""
|
||||||
|
frameworks = [ ]
|
||||||
|
|
||||||
|
[tauri.bundle.windows]
|
||||||
|
digestAlgorithm = "sha256"
|
||||||
|
timestampUrl = ""
|
||||||
|
|
||||||
|
[tauri.security]
|
||||||
|
|
||||||
|
[tauri.updater]
|
||||||
|
active = false
|
||||||
|
endpoints = [ ]
|
||||||
|
pubkey = ""
|
||||||
|
dialog = true
|
||||||
|
|
||||||
|
[[tauri.windows]]
|
||||||
|
fullscreen = false
|
||||||
|
height = 800
|
||||||
|
resizable = true
|
||||||
|
title = "Twosomnia"
|
||||||
|
width = 1_400
|
||||||
|
titleBarStyle = "Overlay"
|
||||||
|
hiddenTitle = true
|
||||||
|
|
||||||
|
[tauri.systemTray]
|
||||||
|
iconPath = "icons/icon.png"
|
||||||
|
iconAsTemplate = true
|
||||||
@@ -20,7 +20,7 @@ interface Response {
|
|||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [responseBody, setResponseBody] = useState<Response | null>(null);
|
const [response, setResponse] = useState<Response | null>(null);
|
||||||
const [url, setUrl] = useState('https://go-server.schier.dev/debug');
|
const [url, setUrl] = useState('https://go-server.schier.dev/debug');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [method, setMethod] = useState<string>('get');
|
const [method, setMethod] = useState<string>('get');
|
||||||
@@ -36,14 +36,14 @@ function App() {
|
|||||||
resp.body = resp.body.replace(/<head>/gi, `<head><base href="${resp.url}"/>`);
|
resp.body = resp.body.replace(/<head>/gi, `<head><base href="${resp.url}"/>`);
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setResponseBody(resp);
|
setResponse(resp);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setError(`${err}`);
|
setError(`${err}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const contentType = responseBody?.headers['content-type']?.split(';')[0] ?? 'text/plain';
|
const contentType = response?.headers['content-type']?.split(';')[0] ?? 'text/plain';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -64,12 +64,12 @@ function App() {
|
|||||||
</DropdownMenuRadio>
|
</DropdownMenuRadio>
|
||||||
</HStack>
|
</HStack>
|
||||||
</nav>
|
</nav>
|
||||||
<div className="h-full w-full overflow-auto">
|
<VStack className="w-full">
|
||||||
<HStack as={WindowDragRegion} items="center" className="pl-4 pr-1">
|
<HStack as={WindowDragRegion} items="center" className="pl-4 pr-1">
|
||||||
<h5>Hello, Friend!</h5>
|
<h5>Hello, Friend!</h5>
|
||||||
<IconButton icon="gear" className="ml-auto" size="sm" />
|
<IconButton icon="gear" className="ml-auto" size="sm" />
|
||||||
</HStack>
|
</HStack>
|
||||||
<VStack className="p-4 max-w-[40rem] mx-auto" space={3}>
|
<VStack className="p-4 max-w-[35rem] mx-auto" space={3}>
|
||||||
<HStack as="form" className="items-end" onSubmit={sendRequest} space={2}>
|
<HStack as="form" className="items-end" onSubmit={sendRequest} space={2}>
|
||||||
<DropdownMenuRadio
|
<DropdownMenuRadio
|
||||||
onValueChange={setMethod}
|
onValueChange={setMethod}
|
||||||
@@ -105,30 +105,30 @@ function App() {
|
|||||||
</HStack>
|
</HStack>
|
||||||
</HStack>
|
</HStack>
|
||||||
{error && <div className="text-white bg-red-500 px-4 py-1 rounded">{error}</div>}
|
{error && <div className="text-white bg-red-500 px-4 py-1 rounded">{error}</div>}
|
||||||
{responseBody !== null && (
|
{response !== null && (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div className="my-1 italic text-gray-500 text-sm">
|
||||||
{responseBody?.method.toUpperCase()}
|
{response?.method.toUpperCase()}
|
||||||
•
|
•
|
||||||
{responseBody?.status}
|
{response?.status}
|
||||||
•
|
•
|
||||||
{responseBody?.elapsed}ms •
|
{response?.elapsed}ms •
|
||||||
{responseBody?.elapsed2}ms
|
{response?.elapsed2}ms
|
||||||
</div>
|
</div>
|
||||||
{contentType.includes('html') ? (
|
{contentType.includes('html') ? (
|
||||||
<iframe
|
<iframe
|
||||||
title="Response preview"
|
title="Response preview"
|
||||||
srcDoc={responseBody.body}
|
srcDoc={response.body}
|
||||||
sandbox="allow-scripts allow-same-origin"
|
sandbox="allow-scripts allow-same-origin"
|
||||||
className="h-[70vh] w-full rounded-lg"
|
className="h-[70vh] w-full rounded-lg"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : response?.body ? (
|
||||||
<Editor value={responseBody?.body} contentType={contentType} />
|
<Editor value={response?.body} contentType={contentType} />
|
||||||
)}
|
) : null}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</VStack>
|
</VStack>
|
||||||
</div>
|
</VStack>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export function Input({ label, labelClassName, hideLabel, className, name, ...pr
|
|||||||
id={id}
|
id={id}
|
||||||
className={classnames(
|
className={classnames(
|
||||||
className,
|
className,
|
||||||
'border-2 border-gray-100 bg-gray-50 h-10 pl-3 pr-2 rounded-md text-sm focus:outline-none',
|
'w-0 min-w-[100%] border-2 border-gray-100 bg-gray-50 h-10 pl-3 pr-2 rounded-md text-sm focus:outline-none',
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export interface VStackProps extends BaseStackProps {
|
|||||||
|
|
||||||
export function VStack({ className, space, children, ...props }: VStackProps) {
|
export function VStack({ className, space, children, ...props }: VStackProps) {
|
||||||
return (
|
return (
|
||||||
<BaseStack className={classnames(className, 'h-full flex-col')} {...props}>
|
<BaseStack className={classnames(className, 'w-full h-full flex-col')} {...props}>
|
||||||
{space
|
{space
|
||||||
? Children.toArray(children)
|
? Children.toArray(children)
|
||||||
.filter(Boolean) // Remove null/false/undefined children
|
.filter(Boolean) // Remove null/false/undefined children
|
||||||
|
|||||||
Reference in New Issue
Block a user