mirror of
https://github.com/kunkunsh/kunkun.git
synced 2025-04-20 05:29:17 +00:00
Update Extension API (#25)
* feat: add file drop API to ui worker extension * update: some shell API
This commit is contained in:
parent
7b9be980b9
commit
e9609cf8ee
315
Cargo.lock
generated
315
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -33,7 +33,7 @@ chrono = { workspace = true }
|
|||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
urlencoding = "2.1.3"
|
urlencoding = "2.1.3"
|
||||||
tauri-plugin-process = "2.0.1"
|
tauri-plugin-process = "2.0.1"
|
||||||
tauri-plugin-shellx = "2.0.11"
|
tauri-plugin-shellx = "2.0.12"
|
||||||
tauri-plugin-fs = "2.0.1"
|
tauri-plugin-fs = "2.0.1"
|
||||||
tauri-plugin-dialog = "2.0.1"
|
tauri-plugin-dialog = "2.0.1"
|
||||||
tauri-plugin-notification = "2.0.1"
|
tauri-plugin-notification = "2.0.1"
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
"shellx:allow-spawn",
|
"shellx:allow-spawn",
|
||||||
"shellx:allow-stdin-write",
|
"shellx:allow-stdin-write",
|
||||||
"shellx:allow-fix-path-env",
|
"shellx:allow-fix-path-env",
|
||||||
|
"shellx:allow-where-is-command",
|
||||||
"dialog:default",
|
"dialog:default",
|
||||||
"dialog:allow-open",
|
"dialog:allow-open",
|
||||||
"dialog:allow-confirm",
|
"dialog:allow-confirm",
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
unregisterExtensionSpawnedProcess,
|
unregisterExtensionSpawnedProcess,
|
||||||
unregisterExtensionWindow
|
unregisterExtensionWindow
|
||||||
} from "@kksh/api/commands"
|
} from "@kksh/api/commands"
|
||||||
import { warn } from "@tauri-apps/plugin-log"
|
import { debug, warn } from "@tauri-apps/plugin-log"
|
||||||
import { get, writable, type Writable } from "svelte/store"
|
import { get, writable, type Writable } from "svelte/store"
|
||||||
|
|
||||||
export type WinExtMap = Record<
|
export type WinExtMap = Record<
|
||||||
@ -99,6 +99,7 @@ function createWinExtMapStore(): Writable<WinExtMap> & API {
|
|||||||
cleanupProcessesFromWindow: async (windowLabel: string) => {
|
cleanupProcessesFromWindow: async (windowLabel: string) => {
|
||||||
const winExtMap = get(store)
|
const winExtMap = get(store)
|
||||||
if (winExtMap[windowLabel]) {
|
if (winExtMap[windowLabel]) {
|
||||||
|
debug(`Cleaning up processes from window ${windowLabel}: ${winExtMap[windowLabel].pids}`)
|
||||||
await killProcesses(winExtMap[windowLabel].pids)
|
await killProcesses(winExtMap[windowLabel].pids)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -9,7 +9,7 @@ import type { UnlistenFn } from "@tauri-apps/api/event"
|
|||||||
import { extname } from "@tauri-apps/api/path"
|
import { extname } from "@tauri-apps/api/path"
|
||||||
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"
|
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"
|
||||||
import * as deepLink from "@tauri-apps/plugin-deep-link"
|
import * as deepLink from "@tauri-apps/plugin-deep-link"
|
||||||
import { error } from "@tauri-apps/plugin-log"
|
import { error, info } from "@tauri-apps/plugin-log"
|
||||||
import { goto } from "$app/navigation"
|
import { goto } from "$app/navigation"
|
||||||
import { toast } from "svelte-sonner"
|
import { toast } from "svelte-sonner"
|
||||||
import * as v from "valibot"
|
import * as v from "valibot"
|
||||||
@ -20,7 +20,7 @@ const StorePathSearchParams = v.object({
|
|||||||
})
|
})
|
||||||
|
|
||||||
export function initDeeplink(): Promise<UnlistenFn> {
|
export function initDeeplink(): Promise<UnlistenFn> {
|
||||||
console.log("init deeplink")
|
info("init deeplink")
|
||||||
if (!isInMainWindow()) {
|
if (!isInMainWindow()) {
|
||||||
return Promise.resolve(() => {})
|
return Promise.resolve(() => {})
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
import { isInMainWindow } from "@/utils/window"
|
import { isInMainWindow } from "@/utils/window"
|
||||||
import { listenToKillProcessEvent, listenToRecordExtensionProcessEvent } from "@kksh/api/events"
|
import { listenToKillProcessEvent, listenToRecordExtensionProcessEvent } from "@kksh/api/events"
|
||||||
import {
|
import {
|
||||||
|
Button,
|
||||||
ModeWatcher,
|
ModeWatcher,
|
||||||
themeConfigStore,
|
themeConfigStore,
|
||||||
ThemeWrapper,
|
ThemeWrapper,
|
||||||
@ -19,11 +20,12 @@
|
|||||||
import { Constants, ViewTransition } from "@kksh/ui"
|
import { Constants, ViewTransition } from "@kksh/ui"
|
||||||
import type { UnlistenFn } from "@tauri-apps/api/event"
|
import type { UnlistenFn } from "@tauri-apps/api/event"
|
||||||
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"
|
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"
|
||||||
import { attachConsole } from "@tauri-apps/plugin-log"
|
import { attachConsole, error, info } from "@tauri-apps/plugin-log"
|
||||||
import { afterNavigate, beforeNavigate } from "$app/navigation"
|
import { afterNavigate, beforeNavigate } from "$app/navigation"
|
||||||
import { gsap } from "gsap"
|
import { gsap } from "gsap"
|
||||||
import { Flip } from "gsap/Flip"
|
import { Flip } from "gsap/Flip"
|
||||||
import { onDestroy, onMount } from "svelte"
|
import { onDestroy, onMount } from "svelte"
|
||||||
|
import * as shellx from "tauri-plugin-shellx-api"
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* Gsap Flip Animation */
|
/* Gsap Flip Animation */
|
||||||
@ -57,6 +59,15 @@
|
|||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
attachConsole().then((unlistener) => unlisteners.push(unlistener))
|
attachConsole().then((unlistener) => unlisteners.push(unlistener))
|
||||||
initDeeplink().then((unlistener) => unlisteners.push(unlistener))
|
initDeeplink().then((unlistener) => unlisteners.push(unlistener))
|
||||||
|
shellx
|
||||||
|
.fixPathEnv()
|
||||||
|
.then(() => {
|
||||||
|
info("fixed path env")
|
||||||
|
shellx.hasCommand("ffprobe").then((res) => {
|
||||||
|
console.log("has ffprobe:", res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(error)
|
||||||
|
|
||||||
quickLinks.init()
|
quickLinks.init()
|
||||||
appConfig.init()
|
appConfig.init()
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { getExtensionsFolder, IS_IN_TAURI } from "@/constants"
|
import { getExtensionsFolder, IS_IN_TAURI } from "@/constants"
|
||||||
|
import { error } from "@tauri-apps/plugin-log"
|
||||||
import type { LayoutLoad } from "./$types"
|
import type { LayoutLoad } from "./$types"
|
||||||
|
|
||||||
// Tauri doesn't have a Node.js server to do proper SSR
|
// Tauri doesn't have a Node.js server to do proper SSR
|
||||||
|
@ -22,6 +22,14 @@
|
|||||||
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"
|
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"
|
||||||
import { exit } from "@tauri-apps/plugin-process"
|
import { exit } from "@tauri-apps/plugin-process"
|
||||||
import { ArrowBigUpIcon, CircleXIcon, EllipsisVerticalIcon, RefreshCcwIcon } from "lucide-svelte"
|
import { ArrowBigUpIcon, CircleXIcon, EllipsisVerticalIcon, RefreshCcwIcon } from "lucide-svelte"
|
||||||
|
import { onMount } from "svelte"
|
||||||
|
import { hasCommand, whereIsCommand } from "tauri-plugin-shellx-api"
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
hasCommand("ffmpeg").then((has) => {
|
||||||
|
console.log("has", has)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
let inputEle: HTMLInputElement | null = null
|
let inputEle: HTMLInputElement | null = null
|
||||||
function onKeyDown(event: KeyboardEvent) {
|
function onKeyDown(event: KeyboardEvent) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { appState } from "@/stores/appState.js"
|
import { appState } from "@/stores/appState.js"
|
||||||
import { winExtMap } from "@/stores/winExtMap.js"
|
import { winExtMap } from "@/stores/winExtMap.js"
|
||||||
import { listenToRefreshDevExt } from "@/utils/tauri-events.js"
|
import { listenToFileDrop, listenToRefreshDevExt } from "@/utils/tauri-events.js"
|
||||||
import { isInMainWindow } from "@/utils/window.js"
|
import { isInMainWindow } from "@/utils/window.js"
|
||||||
import { type Remote } from "@huakunshen/comlink"
|
import { type Remote } from "@huakunshen/comlink"
|
||||||
import { db } from "@kksh/api/commands"
|
import { db } from "@kksh/api/commands"
|
||||||
@ -42,6 +42,7 @@
|
|||||||
let { loadedExt, scriptPath, extInfoInDB } = $derived(data)
|
let { loadedExt, scriptPath, extInfoInDB } = $derived(data)
|
||||||
let workerAPI: Remote<WorkerExtension> | undefined = undefined
|
let workerAPI: Remote<WorkerExtension> | undefined = undefined
|
||||||
let unlistenRefreshWorkerExt: UnlistenFn | undefined
|
let unlistenRefreshWorkerExt: UnlistenFn | undefined
|
||||||
|
let unlistenFileDrop: UnlistenFn | undefined
|
||||||
let worker: Worker | undefined
|
let worker: Worker | undefined
|
||||||
let listViewContent = $state<ListSchema.List>()
|
let listViewContent = $state<ListSchema.List>()
|
||||||
let formViewContent = $state<FormSchema.Form>()
|
let formViewContent = $state<FormSchema.Form>()
|
||||||
@ -54,6 +55,7 @@
|
|||||||
const appWin = getCurrentWebviewWindow()
|
const appWin = getCurrentWebviewWindow()
|
||||||
const loadingBar = $derived($appState.loadingBar || extensionLoadingBar)
|
const loadingBar = $derived($appState.loadingBar || extensionLoadingBar)
|
||||||
let loaded = $state(false)
|
let loaded = $state(false)
|
||||||
|
let listview: Templates.ListView | undefined = $state(undefined)
|
||||||
|
|
||||||
async function goBack() {
|
async function goBack() {
|
||||||
if (isInMainWindow()) {
|
if (isInMainWindow()) {
|
||||||
@ -208,7 +210,6 @@
|
|||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
launchWorkerExt()
|
launchWorkerExt()
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
worker?.terminate()
|
worker?.terminate()
|
||||||
}
|
}
|
||||||
@ -220,8 +221,14 @@
|
|||||||
}, 100)
|
}, 100)
|
||||||
unlistenRefreshWorkerExt = await listenToRefreshDevExt(() => {
|
unlistenRefreshWorkerExt = await listenToRefreshDevExt(() => {
|
||||||
debug("Refreshing Worker Extension")
|
debug("Refreshing Worker Extension")
|
||||||
|
winExtMap.cleanupProcessesFromWindow(appWin.label)
|
||||||
launchWorkerExt()
|
launchWorkerExt()
|
||||||
})
|
})
|
||||||
|
unlistenFileDrop = await listenToFileDrop((evt) => {
|
||||||
|
workerAPI?.onFilesDropped(evt.payload.paths)
|
||||||
|
appWin.setFocus()
|
||||||
|
listview?.inputFocus()
|
||||||
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
appState.setLoadingBar(false)
|
appState.setLoadingBar(false)
|
||||||
loaded = true
|
loaded = true
|
||||||
@ -230,6 +237,7 @@
|
|||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
unlistenRefreshWorkerExt?.()
|
unlistenRefreshWorkerExt?.()
|
||||||
|
unlistenFileDrop?.()
|
||||||
winExtMap.unregisterExtensionFromWindow(appWin.label)
|
winExtMap.unregisterExtensionFromWindow(appWin.label)
|
||||||
extensionLoadingBar = false
|
extensionLoadingBar = false
|
||||||
appState.setActionPanel(undefined)
|
appState.setActionPanel(undefined)
|
||||||
@ -243,6 +251,7 @@
|
|||||||
<Templates.ListView
|
<Templates.ListView
|
||||||
bind:searchTerm
|
bind:searchTerm
|
||||||
bind:searchBarPlaceholder
|
bind:searchBarPlaceholder
|
||||||
|
bind:this={listview}
|
||||||
{pbar}
|
{pbar}
|
||||||
{listViewContent}
|
{listViewContent}
|
||||||
{loading}
|
{loading}
|
||||||
|
@ -77,10 +77,10 @@ const config: Config = {
|
|||||||
keyframes: {
|
keyframes: {
|
||||||
"accordion-down": {
|
"accordion-down": {
|
||||||
from: { height: "0" },
|
from: { height: "0" },
|
||||||
to: { height: "var(--bits-accordion-content-height)" }
|
to: { height: "var(--radix-accordion-content-height)" }
|
||||||
},
|
},
|
||||||
"accordion-up": {
|
"accordion-up": {
|
||||||
from: { height: "var(--bits-accordion-content-height)" },
|
from: { height: "var(--radix-accordion-content-height)" },
|
||||||
to: { height: "0" }
|
to: { height: "0" }
|
||||||
},
|
},
|
||||||
"caret-blink": {
|
"caret-blink": {
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
"@tauri-apps/plugin-upload": "^2.0.0",
|
"@tauri-apps/plugin-upload": "^2.0.0",
|
||||||
"supabase": "^1.207.9",
|
"supabase": "^1.207.9",
|
||||||
"tauri-plugin-network-api": "workspace:*",
|
"tauri-plugin-network-api": "workspace:*",
|
||||||
"tauri-plugin-shellx-api": "^2.0.11",
|
"tauri-plugin-shellx-api": "^2.0.14",
|
||||||
"tauri-plugin-system-info-api": "workspace:*",
|
"tauri-plugin-system-info-api": "workspace:*",
|
||||||
"valibot": "^0.40.0",
|
"valibot": "^0.40.0",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.23.8"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://jsr.io/schema/config-file.v1.json",
|
"$schema": "https://jsr.io/schema/config-file.v1.json",
|
||||||
"name": "@kunkun/api",
|
"name": "@kunkun/api",
|
||||||
"version": "0.0.28",
|
"version": "0.0.32",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts",
|
".": "./src/index.ts",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@kksh/api",
|
"name": "@kksh/api",
|
||||||
"version": "0.0.28",
|
"version": "0.0.33",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts",
|
".": "./src/index.ts",
|
||||||
@ -63,7 +63,7 @@
|
|||||||
"svelte-sonner": "^0.3.28",
|
"svelte-sonner": "^0.3.28",
|
||||||
"tauri-api-adapter": "0.3.8",
|
"tauri-api-adapter": "0.3.8",
|
||||||
"tauri-plugin-network-api": "2.0.4",
|
"tauri-plugin-network-api": "2.0.4",
|
||||||
"tauri-plugin-shellx-api": "^2.0.11",
|
"tauri-plugin-shellx-api": "^2.0.14",
|
||||||
"tauri-plugin-system-info-api": "2.0.8",
|
"tauri-plugin-system-info-api": "2.0.8",
|
||||||
"valibot": "^0.40.0"
|
"valibot": "^0.40.0"
|
||||||
},
|
},
|
||||||
|
@ -64,7 +64,9 @@ export const DenoSysOptions = union([
|
|||||||
literal("networkInterfaces"),
|
literal("networkInterfaces"),
|
||||||
literal("systemMemoryInfo"),
|
literal("systemMemoryInfo"),
|
||||||
literal("uid"),
|
literal("uid"),
|
||||||
literal("gid")
|
literal("gid"),
|
||||||
|
literal("cpus"),
|
||||||
|
string()
|
||||||
])
|
])
|
||||||
|
|
||||||
export type DenoSysOptions = InferOutput<typeof DenoSysOptions>
|
export type DenoSysOptions = InferOutput<typeof DenoSysOptions>
|
||||||
|
@ -101,7 +101,7 @@ class BaseShellCommand<O extends IOPayload> extends EventEmitter<CommandEvents>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Command<O extends IOPayload> extends BaseShellCommand<O> {
|
export class Command<O extends IOPayload> extends BaseShellCommand<O> {
|
||||||
api: Remote<IShellServer>
|
api: Remote<IShellServer>
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -158,7 +158,7 @@ class Command<O extends IOPayload> extends BaseShellCommand<O> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DenoCommand<O extends IOPayload> extends BaseShellCommand<O> {
|
export class DenoCommand<O extends IOPayload> extends BaseShellCommand<O> {
|
||||||
config: DenoRunConfig
|
config: DenoRunConfig
|
||||||
scriptPath: string
|
scriptPath: string
|
||||||
api: Remote<IShellServer>
|
api: Remote<IShellServer>
|
||||||
@ -247,8 +247,10 @@ export type IShell = {
|
|||||||
): Promise<{
|
): Promise<{
|
||||||
rpcChannel: RPCChannel<LocalAPI, RemoteAPI>
|
rpcChannel: RPCChannel<LocalAPI, RemoteAPI>
|
||||||
process: Child
|
process: Child
|
||||||
|
command: DenoCommand<string>
|
||||||
}>
|
}>
|
||||||
RPCChannel: typeof RPCChannel
|
RPCChannel: typeof RPCChannel
|
||||||
|
whereIsCommand: (command: string) => Promise<string | null>
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TauriShellStdio implements StdioInterface {
|
export class TauriShellStdio implements StdioInterface {
|
||||||
@ -295,7 +297,8 @@ export function constructShellAPI(api: Remote<IShellServer>): IShell {
|
|||||||
const stdioRPC = new RPCChannel<LocalAPI, RemoteAPI>(stdio, localAPIImplementation)
|
const stdioRPC = new RPCChannel<LocalAPI, RemoteAPI>(stdio, localAPIImplementation)
|
||||||
return {
|
return {
|
||||||
rpcChannel: stdioRPC,
|
rpcChannel: stdioRPC,
|
||||||
process: denoProcess
|
process: denoProcess,
|
||||||
|
command: denoCmd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,28 +356,11 @@ export function constructShellAPI(api: Remote<IShellServer>): IShell {
|
|||||||
* @returns Whether the current platform is likely to be Windows.
|
* @returns Whether the current platform is likely to be Windows.
|
||||||
*/
|
*/
|
||||||
function likelyOnWindows(): Promise<boolean> {
|
function likelyOnWindows(): Promise<boolean> {
|
||||||
return createCommand("powershell.exe", ["-Command", "echo $env:OS"])
|
// return createCommand("powershell.exe", ["-Command", "echo $env:OS"])
|
||||||
.execute()
|
// .execute()
|
||||||
.then((out) => out.code === 0 && out.stdout.toLowerCase().includes("windows"))
|
// .then((out) => out.code === 0 && out.stdout.toLowerCase().includes("windows"))
|
||||||
.catch(() => false)
|
// .catch(() => false)
|
||||||
}
|
return api.likelyOnWindows()
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if a command is available with `which` or `where` command.
|
|
||||||
* Support Windows, Mac, Linux
|
|
||||||
* @param command
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
async function hasCommand(command: string): Promise<boolean> {
|
|
||||||
const targetCmd = command.trim().split(" ")[0]
|
|
||||||
if (!targetCmd) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const isOnWindows = await likelyOnWindows()
|
|
||||||
const whereCmd = isOnWindows ? "where" : "which"
|
|
||||||
const cmd = createCommand(whereCmd, [targetCmd])
|
|
||||||
const out = await cmd.execute()
|
|
||||||
return out.code === 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -391,14 +377,15 @@ export function constructShellAPI(api: Remote<IShellServer>): IShell {
|
|||||||
executePythonScript,
|
executePythonScript,
|
||||||
executeZshScript,
|
executeZshScript,
|
||||||
executeNodeScript,
|
executeNodeScript,
|
||||||
hasCommand,
|
hasCommand: api.hasCommand,
|
||||||
likelyOnWindows,
|
likelyOnWindows,
|
||||||
createCommand,
|
createCommand,
|
||||||
createDenoCommand,
|
createDenoCommand,
|
||||||
Child,
|
Child,
|
||||||
TauriShellStdio,
|
TauriShellStdio,
|
||||||
createDenoRpcChannel,
|
createDenoRpcChannel,
|
||||||
RPCChannel
|
RPCChannel,
|
||||||
|
whereIsCommand: api.whereIsCommand
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +95,7 @@ export async function verifyDenoCmdPermission(
|
|||||||
let allowAllSys = false
|
let allowAllSys = false
|
||||||
const denySys: string[] = []
|
const denySys: string[] = []
|
||||||
let denyAllSys = false
|
let denyAllSys = false
|
||||||
|
|
||||||
for (const perm of pathMatchedPerms) {
|
for (const perm of pathMatchedPerms) {
|
||||||
if (perm.allow) {
|
if (perm.allow) {
|
||||||
for (const allow of perm.allow) {
|
for (const allow of perm.allow) {
|
||||||
@ -277,25 +278,25 @@ export async function verifyDenoCmdPermission(
|
|||||||
throw new Error("allowAllSys is not allowed")
|
throw new Error("allowAllSys is not allowed")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (difference(config.allowEnv, allowEnv).length > 0) {
|
if (!allowAllEnv && difference(config.allowEnv, allowEnv).length > 0) {
|
||||||
throw new Error(`allowEnv is not allowed: ${difference(config.allowEnv, allowEnv)}`)
|
throw new Error(`allowEnv is not allowed: ${difference(config.allowEnv, allowEnv)}`)
|
||||||
}
|
}
|
||||||
if (difference(config.allowNet, allowNet).length > 0) {
|
if (!allowAllNet && difference(config.allowNet, allowNet).length > 0) {
|
||||||
throw new Error(`allowNet is not allowed: ${difference(config.allowNet, allowNet)}`)
|
throw new Error(`allowNet is not allowed: ${difference(config.allowNet, allowNet)}`)
|
||||||
}
|
}
|
||||||
if (difference(config.allowRead, allowRead).length > 0) {
|
if (!allowAllRead && difference(config.allowRead, allowRead).length > 0) {
|
||||||
throw new Error(`allowRead is not allowed: ${difference(config.allowRead, allowRead)}`)
|
throw new Error(`allowRead is not allowed: ${difference(config.allowRead, allowRead)}`)
|
||||||
}
|
}
|
||||||
if (difference(config.allowWrite, allowWrite).length > 0) {
|
if (!allowAllWrite && difference(config.allowWrite, allowWrite).length > 0) {
|
||||||
throw new Error(`allowWrite is not allowed: ${difference(config.allowWrite, allowWrite)}`)
|
throw new Error(`allowWrite is not allowed: ${difference(config.allowWrite, allowWrite)}`)
|
||||||
}
|
}
|
||||||
if (difference(config.allowRun, allowRun).length > 0) {
|
if (!allowAllRun && difference(config.allowRun, allowRun).length > 0) {
|
||||||
throw new Error(`allowRun is not allowed: ${difference(config.allowRun, allowRun)}`)
|
throw new Error(`allowRun is not allowed: ${difference(config.allowRun, allowRun)}`)
|
||||||
}
|
}
|
||||||
if (difference(config.allowFfi, allowFfi).length > 0) {
|
if (!allowAllFfi && difference(config.allowFfi, allowFfi).length > 0) {
|
||||||
throw new Error(`allowFfi is not allowed: ${difference(config.allowFfi, allowFfi)}`)
|
throw new Error(`allowFfi is not allowed: ${difference(config.allowFfi, allowFfi)}`)
|
||||||
}
|
}
|
||||||
if (difference(config.allowSys, allowSys).length > 0) {
|
if (!allowAllSys && difference(config.allowSys, allowSys).length > 0) {
|
||||||
throw new Error(`allowSys is not allowed: ${difference(config.allowSys, allowSys)}`)
|
throw new Error(`allowSys is not allowed: ${difference(config.allowSys, allowSys)}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ export type IShellServer = IShellServer1 & {
|
|||||||
cb: (evt: CommandEvent<O>) => void
|
cb: (evt: CommandEvent<O>) => void
|
||||||
): Promise<number>
|
): Promise<number>
|
||||||
recordSpawnedProcess(pid: number): Promise<void>
|
recordSpawnedProcess(pid: number): Promise<void>
|
||||||
|
whereIsCommand(command: string): Promise<string | null>
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will be implemented in the @kksh/api package
|
// This will be implemented in the @kksh/api package
|
||||||
|
@ -3,6 +3,8 @@ import { Channel, invoke } from "@tauri-apps/api/core"
|
|||||||
import { emitTo } from "@tauri-apps/api/event"
|
import { emitTo } from "@tauri-apps/api/event"
|
||||||
import { getCurrentWindow } from "@tauri-apps/api/window"
|
import { getCurrentWindow } from "@tauri-apps/api/window"
|
||||||
import {
|
import {
|
||||||
|
hasCommand,
|
||||||
|
whereIsCommand,
|
||||||
type ChildProcess,
|
type ChildProcess,
|
||||||
type CommandEvent,
|
type CommandEvent,
|
||||||
type InternalSpawnOptions,
|
type InternalSpawnOptions,
|
||||||
@ -197,18 +199,18 @@ export function constructShellApi(
|
|||||||
)
|
)
|
||||||
return executeNodeScript(script)
|
return executeNodeScript(script)
|
||||||
}
|
}
|
||||||
async function hasCommand(command: string): Promise<boolean> {
|
|
||||||
// check if command is clean, check if it's a single command without arguments or semicolons with regex.
|
|
||||||
if (!/^[a-zA-Z0-9_-]+$/.test(command)) {
|
|
||||||
return Promise.reject(new Error("Invalid command"))
|
|
||||||
}
|
|
||||||
return hasCommand(command)
|
|
||||||
}
|
|
||||||
async function likelyOnWindows(): Promise<boolean> {
|
async function likelyOnWindows(): Promise<boolean> {
|
||||||
return likelyOnWindows()
|
return likelyOnWindows()
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
whereIsCommand(command: string): Promise<string | null> {
|
||||||
|
const cleanedCommand = command.trim().split(" ")[0]
|
||||||
|
if (!cleanedCommand) {
|
||||||
|
return Promise.resolve(null)
|
||||||
|
}
|
||||||
|
return whereIsCommand(cleanedCommand).then((res) => (res === "" ? null : res))
|
||||||
|
},
|
||||||
async recordSpawnedProcess(pid: number): Promise<void> {
|
async recordSpawnedProcess(pid: number): Promise<void> {
|
||||||
// get window label
|
// get window label
|
||||||
const curWin = await getCurrentWindow()
|
const curWin = await getCurrentWindow()
|
||||||
@ -286,7 +288,13 @@ export function constructShellApi(
|
|||||||
executePythonScript,
|
executePythonScript,
|
||||||
executeZshScript,
|
executeZshScript,
|
||||||
executeNodeScript,
|
executeNodeScript,
|
||||||
hasCommand,
|
hasCommand: (command: string): Promise<boolean> => {
|
||||||
|
// check if command is clean, check if it's a single command without arguments or semicolons with regex.
|
||||||
|
if (!/^[a-zA-Z0-9_-]+$/.test(command)) {
|
||||||
|
return Promise.reject(new Error("Invalid command"))
|
||||||
|
}
|
||||||
|
return hasCommand(command)
|
||||||
|
},
|
||||||
likelyOnWindows
|
likelyOnWindows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,10 @@ export abstract class WorkerExtension {
|
|||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onFilesDropped(paths: string[]): Promise<void> {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
onBeforeGoBack(): Promise<void> {
|
onBeforeGoBack(): Promise<void> {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
|
@ -97,8 +97,7 @@ export const {
|
|||||||
security,
|
security,
|
||||||
workerUi: ui
|
workerUi: ui
|
||||||
} = _api
|
} = _api
|
||||||
export { Child, RPCChannel } from "../api/shell"
|
export { Child, RPCChannel, Command, DenoCommand } from "../api/shell"
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* UI Component Schema */
|
/* UI Component Schema */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
@ -13,7 +13,7 @@ export const breakingChangesVersionCheckpoints = [
|
|||||||
const checkpointVersions = breakingChangesVersionCheckpoints.map((c) => c.version)
|
const checkpointVersions = breakingChangesVersionCheckpoints.map((c) => c.version)
|
||||||
const sortedCheckpointVersions = sort(checkpointVersions)
|
const sortedCheckpointVersions = sort(checkpointVersions)
|
||||||
|
|
||||||
export const version = "0.0.28"
|
export const version = "0.0.33"
|
||||||
|
|
||||||
export function isVersionBetween(v: string, start: string, end: string) {
|
export function isVersionBetween(v: string, start: string, end: string) {
|
||||||
const vCleaned = clean(v)
|
const vCleaned = clean(v)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"imports": {
|
"imports": {
|
||||||
"@kunkun/api": "jsr:@kunkun/api@^0.0.14"
|
"@hk/photographer-toolbox": "jsr:@hk/photographer-toolbox@^0.1.3",
|
||||||
|
"@kunkun/api": "jsr:@kunkun/api@^0.0.27"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,8 @@
|
|||||||
|
import { image } from "@hk/photographer-toolbox"
|
||||||
|
|
||||||
|
// image
|
||||||
|
// .readImageMetadata(
|
||||||
|
// "/Users/hacker/Dev/projects/photographer-lib-deno/data/DJI_20241002175820_0054_D.JPG"
|
||||||
|
// )
|
||||||
|
// .then(console.log)
|
||||||
|
console.log(image);
|
@ -1,13 +1,32 @@
|
|||||||
|
import { image } from "@hk/photographer-toolbox"
|
||||||
import { expose } from "@kunkun/api/runtime/deno"
|
import { expose } from "@kunkun/api/runtime/deno"
|
||||||
|
|
||||||
|
// import { image } from "jsr:@hk/photographer-toolbox@^0.1.3"
|
||||||
|
|
||||||
export interface API {
|
export interface API {
|
||||||
add(a: number, b: number): Promise<number>
|
add(a: number, b: number): Promise<number>
|
||||||
subtract(a: number, b: number): Promise<number>
|
subtract(a: number, b: number): Promise<number>
|
||||||
|
// readImageMetadata: (path: string) => Promise<any>
|
||||||
|
// readImageMetadata: typeof image.readImageMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define your API methods
|
// Define your API methods
|
||||||
export const apiMethods: API = {
|
export const apiMethods: API = {
|
||||||
add: async (a: number, b: number) => a + b,
|
add: async (a: number, b: number) => a + b,
|
||||||
subtract: async (a: number, b: number) => a - b
|
subtract: async (a: number, b: number) => a - b
|
||||||
|
// readImageMetadata: (path: string) => Promise.resolve(`path + ${path}`)
|
||||||
|
// readImageMetadata: image.readImageMetadata
|
||||||
}
|
}
|
||||||
expose(apiMethods)
|
expose(apiMethods)
|
||||||
|
// image
|
||||||
|
// .readImageMetadata(
|
||||||
|
// "/Users/hacker/Dev/projects/photographer-lib-deno/data/DJI_20241002175820_0054_D.JPG"
|
||||||
|
// )
|
||||||
|
// .then(console.log)
|
||||||
|
/**
|
||||||
|
* env: npm_package_config_libvips
|
||||||
|
* ffi: sharp-darwin-arm64.node
|
||||||
|
* sys: cpus
|
||||||
|
* read: exists /usr/bin/perl
|
||||||
|
* Run: /Users/hacker/Library/Caches/deno/npm/registry.npmjs.org/exiftool-vendored.pl/12.96.0/bin/exiftool
|
||||||
|
*/
|
||||||
|
@ -1,114 +1,110 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../../schema/manifest-json-schema.json",
|
"$schema": "../../schema/manifest-json-schema.json",
|
||||||
"name": "demo-template-extension",
|
"name": "demo-template-extension",
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"kunkun": {
|
"kunkun": {
|
||||||
"name": "Demo Template Extension",
|
"name": "Demo Template Extension",
|
||||||
"shortDescription": "Demo Template Extension",
|
"shortDescription": "Demo Template Extension",
|
||||||
"longDescription": "Demo Template Extension",
|
"longDescription": "Demo Template Extension",
|
||||||
"identifier": "demo-worker-template-ext",
|
"identifier": "demo-worker-template-ext",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"fetch:all",
|
"fetch:all",
|
||||||
"shell:kill",
|
"shell:kill",
|
||||||
"security:mac:all",
|
"security:mac:all",
|
||||||
{
|
{
|
||||||
"permission": "shell:deno:execute",
|
"permission": "shell:deno:spawn",
|
||||||
"allow": [
|
"allow": [
|
||||||
{
|
{
|
||||||
"path": "$EXTENSION/deno-src/deno-script.ts",
|
"path": "$EXTENSION/deno-src/deno-script.ts"
|
||||||
"env": [
|
},
|
||||||
"npm_package_config_libvips",
|
{
|
||||||
"CWD"
|
"path": "$EXTENSION/deno-src/rpc.ts",
|
||||||
],
|
"env": "*",
|
||||||
"ffi": "*",
|
"ffi": "*",
|
||||||
"read": [
|
"read": "*",
|
||||||
"$DESKTOP"
|
"sys": "*",
|
||||||
]
|
"run": "*"
|
||||||
},
|
}
|
||||||
{
|
]
|
||||||
"path": "$EXTENSION/deno-src/rpc.ts",
|
},
|
||||||
"ffi": "*"
|
{
|
||||||
}
|
"permission": "open:file",
|
||||||
]
|
"allow": [
|
||||||
},
|
{
|
||||||
{
|
"path": "$EXTENSION/src/deno-script.ts"
|
||||||
"permission": "open:file",
|
}
|
||||||
"allow": [
|
]
|
||||||
{
|
},
|
||||||
"path": "$EXTENSION/src/deno-script.ts"
|
"shell:stdin-write",
|
||||||
}
|
{
|
||||||
]
|
"permission": "shell:execute",
|
||||||
},
|
"allow": [
|
||||||
"shell:stdin-write",
|
{
|
||||||
{
|
"cmd": {
|
||||||
"permission": "shell:execute",
|
"program": "ls",
|
||||||
"allow": [
|
"args": [
|
||||||
{
|
"-l"
|
||||||
"cmd": {
|
]
|
||||||
"program": "ls",
|
}
|
||||||
"args": [
|
},
|
||||||
"-l"
|
{
|
||||||
]
|
"cmd": {
|
||||||
}
|
"program": "bash",
|
||||||
},
|
"args": [
|
||||||
{
|
"-c",
|
||||||
"cmd": {
|
".+"
|
||||||
"program": "bash",
|
]
|
||||||
"args": [
|
}
|
||||||
"-c",
|
},
|
||||||
".+"
|
{
|
||||||
]
|
"cmd": {
|
||||||
}
|
"program": "deno",
|
||||||
},
|
"args": [
|
||||||
{
|
"-A",
|
||||||
"cmd": {
|
".+",
|
||||||
"program": "deno",
|
".+"
|
||||||
"args": [
|
]
|
||||||
"-A",
|
}
|
||||||
".+",
|
}
|
||||||
".+"
|
]
|
||||||
]
|
}
|
||||||
}
|
],
|
||||||
}
|
"demoImages": [],
|
||||||
]
|
"icon": {
|
||||||
}
|
"type": "iconify",
|
||||||
],
|
"value": "carbon:demo"
|
||||||
"demoImages": [],
|
},
|
||||||
"icon": {
|
"customUiCmds": [],
|
||||||
"type": "iconify",
|
"templateUiCmds": [
|
||||||
"value": "carbon:demo"
|
{
|
||||||
},
|
"name": "Demo Worker Template",
|
||||||
"customUiCmds": [],
|
"main": "dist/index.js",
|
||||||
"templateUiCmds": [
|
"cmds": []
|
||||||
{
|
}
|
||||||
"name": "Demo Worker Template",
|
]
|
||||||
"main": "dist/index.js",
|
},
|
||||||
"cmds": []
|
"scripts": {
|
||||||
}
|
"dev": "bun build.ts dev",
|
||||||
]
|
"build": "bun build.ts"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"dependencies": {
|
||||||
"dev": "bun build.ts dev",
|
"@hk/comlink-stdio": "npm:@jsr/hk__comlink-stdio@^0.1.6",
|
||||||
"build": "bun build.ts"
|
"@kksh/api": "workspace:*",
|
||||||
},
|
"@kunkun/api": "npm:@jsr/kunkun__api@^0.0.13"
|
||||||
"dependencies": {
|
},
|
||||||
"@hk/comlink-stdio": "npm:@jsr/hk__comlink-stdio@^0.1.6",
|
"devDependencies": {
|
||||||
"@kksh/api": "workspace:*",
|
"@rollup/plugin-commonjs": "^26.0.1",
|
||||||
"@kunkun/api": "npm:@jsr/kunkun__api@^0.0.13"
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||||
},
|
"@rollup/plugin-typescript": "^11.1.6",
|
||||||
"devDependencies": {
|
"@types/bun": "latest",
|
||||||
"@rollup/plugin-commonjs": "^26.0.1",
|
"rollup-plugin-visualizer": "^5.12.0"
|
||||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
},
|
||||||
"@rollup/plugin-typescript": "^11.1.6",
|
"peerDependencies": {
|
||||||
"@types/bun": "latest",
|
"typescript": "^5.0.0"
|
||||||
"rollup-plugin-visualizer": "^5.12.0"
|
},
|
||||||
},
|
"files": [
|
||||||
"peerDependencies": {
|
"./dist",
|
||||||
"typescript": "^5.0.0"
|
".gitignore"
|
||||||
},
|
]
|
||||||
"files": [
|
|
||||||
"./dist",
|
|
||||||
".gitignore"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -56,13 +56,35 @@ class ExtensionTemplate extends WorkerExtension {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
ui.showLoadingBar(false)
|
ui.showLoadingBar(false)
|
||||||
}, 2000)
|
}, 2000)
|
||||||
const { rpcChannel, process } = await shell.createDenoRpcChannel<
|
const { rpcChannel, process, command } = await shell.createDenoRpcChannel<
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
add(a: number, b: number): Promise<number>
|
add(a: number, b: number): Promise<number>
|
||||||
subtract(a: number, b: number): Promise<number>
|
subtract(a: number, b: number): Promise<number>
|
||||||
|
// readImageMetadata(path: string): Promise<any>
|
||||||
}
|
}
|
||||||
>("$EXTENSION/deno-src/rpc.ts", [], {}, {})
|
>(
|
||||||
|
"$EXTENSION/deno-src/rpc.ts",
|
||||||
|
[],
|
||||||
|
{
|
||||||
|
allowEnv: ["npm_package_config_libvips"],
|
||||||
|
// allowAllEnv: true,
|
||||||
|
// allowFfi: ["*sharp-darwin-arm64.node"],
|
||||||
|
allowAllFfi: true,
|
||||||
|
allowAllRead: true,
|
||||||
|
allowAllSys: true,
|
||||||
|
// allowRun: ["*exiftool"]
|
||||||
|
allowAllRun: true
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
// const child = new Child(process.pid)
|
||||||
|
command.stdout.on("data", (data) => {
|
||||||
|
console.log("stdout", data.toString())
|
||||||
|
})
|
||||||
|
command.stderr.on("data", (data) => {
|
||||||
|
console.log("stderr", data.toString())
|
||||||
|
})
|
||||||
const api = rpcChannel.getApi()
|
const api = rpcChannel.getApi()
|
||||||
await api.add(1, 2).then(console.log)
|
await api.add(1, 2).then(console.log)
|
||||||
await api.subtract(1, 2).then(console.log)
|
await api.subtract(1, 2).then(console.log)
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
"tailwind-variants": "^0.2.1",
|
"tailwind-variants": "^0.2.1",
|
||||||
"tailwindcss": "^3.4.14",
|
"tailwindcss": "^3.4.14",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"tauri-plugin-shellx-api": "^2.0.11",
|
"tauri-plugin-shellx-api": "^2.0.14",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.23.8"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -13,7 +13,9 @@
|
|||||||
let {
|
let {
|
||||||
searchTerm = $bindable(""),
|
searchTerm = $bindable(""),
|
||||||
searchBarPlaceholder = $bindable(""),
|
searchBarPlaceholder = $bindable(""),
|
||||||
|
inputRef = $bindable<HTMLInputElement | null>(null),
|
||||||
pbar,
|
pbar,
|
||||||
|
highlightedValue = $bindable<string>(""),
|
||||||
onGoBack,
|
onGoBack,
|
||||||
onListScrolledToBottom,
|
onListScrolledToBottom,
|
||||||
onEnterKeyPressed,
|
onEnterKeyPressed,
|
||||||
@ -26,7 +28,9 @@
|
|||||||
}: {
|
}: {
|
||||||
searchTerm: string
|
searchTerm: string
|
||||||
searchBarPlaceholder: string
|
searchBarPlaceholder: string
|
||||||
|
inputRef?: HTMLInputElement | null
|
||||||
pbar: number | null
|
pbar: number | null
|
||||||
|
highlightedValue?: string
|
||||||
onGoBack?: () => void
|
onGoBack?: () => void
|
||||||
onListScrolledToBottom?: () => void
|
onListScrolledToBottom?: () => void
|
||||||
onEnterKeyPressed?: () => void
|
onEnterKeyPressed?: () => void
|
||||||
@ -37,19 +41,27 @@
|
|||||||
loading: boolean
|
loading: boolean
|
||||||
listViewContent: ListSchema.List
|
listViewContent: ListSchema.List
|
||||||
} = $props()
|
} = $props()
|
||||||
let mounted = $state(false)
|
|
||||||
let leftPane: PaneAPI | undefined
|
let leftPane: PaneAPI | undefined
|
||||||
let rightPane: PaneAPI | undefined
|
let rightPane: PaneAPI | undefined
|
||||||
let isScrolling = $state(false)
|
let isScrolling = $state(false)
|
||||||
let highlightedValue = $state<string>("")
|
|
||||||
let privateSearchTerm = $state("")
|
let privateSearchTerm = $state("")
|
||||||
// let detailWidth = $derived()
|
// let detailWidth = $derived()
|
||||||
let prevDetailWidth = $state(0)
|
let prevDetailWidth = $state(0)
|
||||||
|
|
||||||
const detailWidth = $derived(listViewContent.detail ? (listViewContent.detail?.width ?? 70) : 0)
|
const detailWidth = $derived(listViewContent.detail ? (listViewContent.detail?.width ?? 70) : 0)
|
||||||
|
|
||||||
|
export function inputFocus() {
|
||||||
|
inputRef?.focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setHighlightedValue(value: string) {
|
||||||
|
highlightedValue = value
|
||||||
|
}
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
onHighlightedItemChanged?.(highlightedValue)
|
if (highlightedValue.startsWith("{")) {
|
||||||
|
onHighlightedItemChanged?.(JSON.parse(highlightedValue).value)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
@ -80,6 +92,7 @@
|
|||||||
class="h-screen w-full rounded-lg border shadow-md"
|
class="h-screen w-full rounded-lg border shadow-md"
|
||||||
shouldFilter={listViewContent.filter !== "none"}
|
shouldFilter={listViewContent.filter !== "none"}
|
||||||
bind:value={highlightedValue}
|
bind:value={highlightedValue}
|
||||||
|
loop
|
||||||
filter={(value, search, keywords) => {
|
filter={(value, search, keywords) => {
|
||||||
if (!value.startsWith("{")) {
|
if (!value.startsWith("{")) {
|
||||||
return -1
|
return -1
|
||||||
@ -95,6 +108,7 @@
|
|||||||
bind:value={searchTerm}
|
bind:value={searchTerm}
|
||||||
placeholder={searchBarPlaceholder}
|
placeholder={searchBarPlaceholder}
|
||||||
autofocus
|
autofocus
|
||||||
|
bind:ref={inputRef}
|
||||||
onkeydown={(e) => {
|
onkeydown={(e) => {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
23
pnpm-lock.yaml
generated
23
pnpm-lock.yaml
generated
@ -69,8 +69,8 @@ importers:
|
|||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:vendors/tauri-plugin-network
|
version: link:vendors/tauri-plugin-network
|
||||||
tauri-plugin-shellx-api:
|
tauri-plugin-shellx-api:
|
||||||
specifier: ^2.0.11
|
specifier: ^2.0.14
|
||||||
version: 2.0.11
|
version: 2.0.14
|
||||||
tauri-plugin-system-info-api:
|
tauri-plugin-system-info-api:
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:vendors/tauri-plugin-system-info
|
version: link:vendors/tauri-plugin-system-info
|
||||||
@ -323,8 +323,8 @@ importers:
|
|||||||
specifier: 2.0.4
|
specifier: 2.0.4
|
||||||
version: 2.0.4(typescript@5.5.4)
|
version: 2.0.4(typescript@5.5.4)
|
||||||
tauri-plugin-shellx-api:
|
tauri-plugin-shellx-api:
|
||||||
specifier: ^2.0.11
|
specifier: ^2.0.14
|
||||||
version: 2.0.11
|
version: 2.0.14
|
||||||
tauri-plugin-system-info-api:
|
tauri-plugin-system-info-api:
|
||||||
specifier: 2.0.8
|
specifier: 2.0.8
|
||||||
version: 2.0.8(typescript@5.5.4)
|
version: 2.0.8(typescript@5.5.4)
|
||||||
@ -586,8 +586,8 @@ importers:
|
|||||||
specifier: ^1.0.7
|
specifier: ^1.0.7
|
||||||
version: 1.0.7(tailwindcss@3.4.14)
|
version: 1.0.7(tailwindcss@3.4.14)
|
||||||
tauri-plugin-shellx-api:
|
tauri-plugin-shellx-api:
|
||||||
specifier: ^2.0.11
|
specifier: ^2.0.14
|
||||||
version: 2.0.11
|
version: 2.0.14
|
||||||
zod:
|
zod:
|
||||||
specifier: ^3.23.8
|
specifier: ^3.23.8
|
||||||
version: 3.23.8
|
version: 3.23.8
|
||||||
@ -4105,6 +4105,9 @@ packages:
|
|||||||
tauri-plugin-shellx-api@2.0.11:
|
tauri-plugin-shellx-api@2.0.11:
|
||||||
resolution: {integrity: sha512-+FKIP1FBHdIQ6tASohww3MOf/8CDvYMYpPg9glO59h8TGVxTNP2ofiOEKLYk8M/o2H4tP7mxxca11QpDAT2LXw==}
|
resolution: {integrity: sha512-+FKIP1FBHdIQ6tASohww3MOf/8CDvYMYpPg9glO59h8TGVxTNP2ofiOEKLYk8M/o2H4tP7mxxca11QpDAT2LXw==}
|
||||||
|
|
||||||
|
tauri-plugin-shellx-api@2.0.14:
|
||||||
|
resolution: {integrity: sha512-MdSYD2KDw63b7yEIa9Q2GXnbidL5Tk+s92BJX0XvYfHrv2l1fYE2vdRWGnyhvCWmUavyCeiOle5uMxM6QLOb2Q==}
|
||||||
|
|
||||||
tauri-plugin-system-info-api@2.0.8:
|
tauri-plugin-system-info-api@2.0.8:
|
||||||
resolution: {integrity: sha512-EFdLXNGp6Zu9SNsZCkU+55A8027OnrVw/TQrd0oJHgfZzs4qvm1iMmSvyid4MLftt33iZDhjCzxYijaaOxeKSg==}
|
resolution: {integrity: sha512-EFdLXNGp6Zu9SNsZCkU+55A8027OnrVw/TQrd0oJHgfZzs4qvm1iMmSvyid4MLftt33iZDhjCzxYijaaOxeKSg==}
|
||||||
|
|
||||||
@ -8519,7 +8522,7 @@ snapshots:
|
|||||||
shx: 0.3.4
|
shx: 0.3.4
|
||||||
tauri-plugin-clipboard-api: 2.1.11(typescript@5.5.4)
|
tauri-plugin-clipboard-api: 2.1.11(typescript@5.5.4)
|
||||||
tauri-plugin-network-api: 2.0.4(typescript@5.5.4)
|
tauri-plugin-network-api: 2.0.4(typescript@5.5.4)
|
||||||
tauri-plugin-shellx-api: 2.0.11
|
tauri-plugin-shellx-api: 2.0.14
|
||||||
tauri-plugin-system-info-api: 2.0.8(typescript@5.5.4)
|
tauri-plugin-system-info-api: 2.0.8(typescript@5.5.4)
|
||||||
tsc-alias: 1.8.10
|
tsc-alias: 1.8.10
|
||||||
typescript: 5.5.4
|
typescript: 5.5.4
|
||||||
@ -8546,7 +8549,7 @@ snapshots:
|
|||||||
shx: 0.3.4
|
shx: 0.3.4
|
||||||
tauri-plugin-clipboard-api: 2.1.11(typescript@5.6.3)
|
tauri-plugin-clipboard-api: 2.1.11(typescript@5.6.3)
|
||||||
tauri-plugin-network-api: 2.0.4(typescript@5.6.3)
|
tauri-plugin-network-api: 2.0.4(typescript@5.6.3)
|
||||||
tauri-plugin-shellx-api: 2.0.11
|
tauri-plugin-shellx-api: 2.0.14
|
||||||
tauri-plugin-system-info-api: 2.0.8(typescript@5.6.3)
|
tauri-plugin-system-info-api: 2.0.8(typescript@5.6.3)
|
||||||
tsc-alias: 1.8.10
|
tsc-alias: 1.8.10
|
||||||
typescript: 5.6.3
|
typescript: 5.6.3
|
||||||
@ -8586,6 +8589,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@tauri-apps/api': 2.1.0
|
'@tauri-apps/api': 2.1.0
|
||||||
|
|
||||||
|
tauri-plugin-shellx-api@2.0.14:
|
||||||
|
dependencies:
|
||||||
|
'@tauri-apps/api': 2.1.0
|
||||||
|
|
||||||
tauri-plugin-system-info-api@2.0.8(typescript@5.5.4):
|
tauri-plugin-system-info-api@2.0.8(typescript@5.5.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tauri-apps/api': 2.1.0
|
'@tauri-apps/api': 2.1.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user