From 8751fbeff4e48f0740528bedddf6bad7192bf6fb Mon Sep 17 00:00:00 2001 From: Huakun Date: Sat, 1 Mar 2025 12:36:37 -0500 Subject: [PATCH] feat: add custom configurable app search paths (#221) * feat: add custom configurable app search paths * feat(i18n): add English and Chinese translation for app search path settings * format --- apps/desktop/messages/en.json | 7 + apps/desktop/messages/zh.json | 7 + apps/desktop/package.json | 2 +- apps/desktop/src/lib/stores/appConfig.ts | 18 ++- .../settings/app-search-paths/+page.svelte | 137 ++++++++++++++++++ .../src/routes/app/settings/sidebar.svelte | 13 +- packages/api/src/commands/apps.ts | 6 +- packages/api/src/models/apps.ts | 8 +- .../tauri-plugins/jarvis/src/commands/apps.rs | 13 +- .../jarvis/src/commands/system.rs | 2 +- packages/types/src/appConfig.ts | 5 +- packages/ui/package.json | 2 +- pnpm-lock.yaml | 26 +--- 13 files changed, 215 insertions(+), 31 deletions(-) create mode 100644 apps/desktop/src/routes/app/settings/app-search-paths/+page.svelte diff --git a/apps/desktop/messages/en.json b/apps/desktop/messages/en.json index 0cc7c1d..ccbea98 100644 --- a/apps/desktop/messages/en.json +++ b/apps/desktop/messages/en.json @@ -24,6 +24,7 @@ "settings_menu_settings": "Settings", "settings_menu_general": "General", + "settings_menu_app_search_paths": "App Search Paths", "settings_menu_developer": "Developer", "settings_menu_extensions": "Extensions", "settings_menu_set_dev_ext": "Set Dev Extension", @@ -40,6 +41,12 @@ "settings_general_developer_mode": "Developer Mode", "settings_general_language": "Language", + "settings_app_search_paths_title": "Extra App Search Paths", + "settings_app_search_paths_add_app_search_path": "Add App Search Path", + "settings_app_search_paths_table_col_search_path": "Search Path", + "settings_app_search_paths_table_col_depth": "Depth", + "settings_app_search_paths_table_col_actions": "Actions", + "settings_about_version": "Version", "settings_about_author": "Author", "settings_about_source_code": "Source Code", diff --git a/apps/desktop/messages/zh.json b/apps/desktop/messages/zh.json index a3df44b..9fd05b1 100644 --- a/apps/desktop/messages/zh.json +++ b/apps/desktop/messages/zh.json @@ -24,6 +24,7 @@ "settings_menu_settings": "设置", "settings_menu_general": "通用", + "settings_menu_app_search_paths": "应用搜索路径", "settings_menu_developer": "开发者", "settings_menu_extensions": "插件", "settings_menu_set_dev_ext": "设置开发插件", @@ -40,6 +41,12 @@ "settings_general_developer_mode": "开发者模式", "settings_general_language": "语言", + "settings_app_search_paths_title": "额外应用搜索路径", + "settings_app_search_paths_add_app_search_path": "添加应用搜索路径", + "settings_app_search_paths_table_col_search_path": "搜索路径", + "settings_app_search_paths_table_col_depth": "深度", + "settings_app_search_paths_table_col_actions": "操作", + "settings_about_version": "版本", "settings_about_author": "作者", "settings_about_source_code": "源代码", diff --git a/apps/desktop/package.json b/apps/desktop/package.json index d9e2071..d7aeceb 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -37,7 +37,7 @@ "lz-string": "^1.5.0", "pretty-bytes": "^6.1.1", "semver": "^7.6.3", - "svelte-inspect-value": "^0.2.2", + "svelte-inspect-value": "^0.3.0", "svelte-sonner": "^0.3.28", "sveltekit-superforms": "^2.22.1", "tauri-plugin-clipboard-api": "^2.1.11", diff --git a/apps/desktop/src/lib/stores/appConfig.ts b/apps/desktop/src/lib/stores/appConfig.ts index eccaad0..1789627 100644 --- a/apps/desktop/src/lib/stores/appConfig.ts +++ b/apps/desktop/src/lib/stores/appConfig.ts @@ -1,5 +1,6 @@ import { getExtensionsFolder } from "@/constants" import { createTauriSyncStore, type WithSyncStore } from "@/utils/sync-store" +import type { SearchPath } from "@kksh/api/models" import { updateTheme, type ThemeConfig } from "@kksh/svelte5" import { PersistedAppConfig, type AppConfig } from "@kksh/types" import { debug, error } from "@tauri-apps/plugin-log" @@ -27,7 +28,8 @@ export const defaultAppConfig: AppConfig = { extensionAutoUpgrade: true, joinBetaProgram: false, onBoarded: false, - developerMode: false + developerMode: false, + appSearchPaths: [] } export const appConfigLoaded = writable(false) @@ -40,6 +42,8 @@ interface AppConfigAPI { setTriggerHotkey: (triggerHotkey: string[]) => void setOnBoarded: (onBoarded: boolean) => void setLanguage: (language: string) => void + addAppSearchPath: (appSearchPath: SearchPath) => void + removeAppSearchPath: (appSearchPath: SearchPath) => void } function createAppConfig(): WithSyncStore & AppConfigAPI { @@ -94,6 +98,18 @@ function createAppConfig(): WithSyncStore & Ap setLanguage: (language: string) => { store.update((config) => ({ ...config, language })) }, + addAppSearchPath: (appSearchPath: SearchPath) => { + store.update((config) => ({ + ...config, + appSearchPaths: [...config.appSearchPaths, appSearchPath] + })) + }, + removeAppSearchPath: (appSearchPath: SearchPath) => { + store.update((config) => ({ + ...config, + appSearchPaths: config.appSearchPaths.filter((path) => path.path !== appSearchPath.path) + })) + }, init } } diff --git a/apps/desktop/src/routes/app/settings/app-search-paths/+page.svelte b/apps/desktop/src/routes/app/settings/app-search-paths/+page.svelte new file mode 100644 index 0000000..140710a --- /dev/null +++ b/apps/desktop/src/routes/app/settings/app-search-paths/+page.svelte @@ -0,0 +1,137 @@ + + +
+

{m.settings_app_search_paths_title()}

+ {#if $appConfig.developerMode} + + {/if} +
+ + + {#snippet children({ props })} + {m.settings_app_search_paths_table_col_search_path()} +
+ + Pick +
+ {/snippet} +
+ +
+ + + {#snippet children({ props })} + {m.settings_app_search_paths_table_col_depth()} + + {/snippet} + + + + +
+ + {#if $appConfig.developerMode} + + {/if} + + + + + {m.settings_app_search_paths_table_col_search_path()} + + {m.settings_app_search_paths_table_col_depth()} + + + {m.settings_app_search_paths_table_col_actions()} + + + + + {#each $appConfig.appSearchPaths as appSearchPath, i (i)} + + { + open(appSearchPath.path) + }} + > + {appSearchPath.path} + + {appSearchPath.depth} + + + + + {/each} + + +
diff --git a/apps/desktop/src/routes/app/settings/sidebar.svelte b/apps/desktop/src/routes/app/settings/sidebar.svelte index 5ab9668..91be864 100644 --- a/apps/desktop/src/routes/app/settings/sidebar.svelte +++ b/apps/desktop/src/routes/app/settings/sidebar.svelte @@ -4,7 +4,7 @@ import { goHome } from "@/utils/route" import { Button, Sidebar } from "@kksh/svelte5" import { Constants } from "@kksh/ui" - import { ArrowLeftIcon } from "lucide-svelte" + import { ArrowLeftIcon, FolderSearch } from "lucide-svelte" import Blocks from "lucide-svelte/icons/blocks" import Cog from "lucide-svelte/icons/cog" import FileCode2 from "lucide-svelte/icons/file-code-2" @@ -19,10 +19,15 @@ icon: Cog }, { - title: m.settings_menu_developer(), - url: i18n.resolveRoute("/app/settings/developer"), - icon: SquareTerminal + title: m.settings_menu_app_search_paths(), + url: i18n.resolveRoute("/app/settings/app-search-paths"), + icon: FolderSearch }, + // { + // title: m.settings_menu_developer(), + // url: i18n.resolveRoute("/app/settings/developer"), + // icon: SquareTerminal + // }, { title: m.settings_menu_extensions(), url: i18n.resolveRoute("/app/settings/extensions"), diff --git a/packages/api/src/commands/apps.ts b/packages/api/src/commands/apps.ts index f4ca8fe..28dccab 100644 --- a/packages/api/src/commands/apps.ts +++ b/packages/api/src/commands/apps.ts @@ -1,5 +1,5 @@ import { invoke } from "@tauri-apps/api/core" -import { AppInfo } from "../models" +import { AppInfo, SearchPath } from "../models" import { generateJarvisPluginCommand } from "./common" export function getAllApps(): Promise { @@ -14,6 +14,10 @@ export function refreshApplicationsListInBg(): Promise { return invoke(generateJarvisPluginCommand("refresh_applications_list_in_bg")) } +export function setExtraAppSearchPaths(paths: SearchPath[]): Promise { + return invoke(generateJarvisPluginCommand("set_extra_app_search_paths"), { paths }) +} + // export function convertAppToTListItem(app: AppInfo): TListItem { // return { // title: app.name, diff --git a/packages/api/src/models/apps.ts b/packages/api/src/models/apps.ts index 9a7a722..468dee5 100644 --- a/packages/api/src/models/apps.ts +++ b/packages/api/src/models/apps.ts @@ -1,4 +1,4 @@ -import { nullable, object, string, type InferOutput } from "valibot" +import { nullable, number, object, string, type InferOutput } from "valibot" export const AppInfo = object({ name: string(), @@ -7,3 +7,9 @@ export const AppInfo = object({ app_desktop_path: string() }) export type AppInfo = InferOutput + +export const SearchPath = object({ + path: string(), + depth: number() +}) +export type SearchPath = InferOutput diff --git a/packages/tauri-plugins/jarvis/src/commands/apps.rs b/packages/tauri-plugins/jarvis/src/commands/apps.rs index c459c3d..4187d3a 100644 --- a/packages/tauri-plugins/jarvis/src/commands/apps.rs +++ b/packages/tauri-plugins/jarvis/src/commands/apps.rs @@ -1,10 +1,11 @@ -use applications::{App, AppInfo, AppInfoContext}; +use applications::{common::SearchPath, App, AppInfo, AppInfoContext}; use std::sync::Mutex; #[derive(Default)] pub struct ApplicationsState { ctx: Mutex, } + #[tauri::command] pub async fn get_applications( state: tauri::State<'_, ApplicationsState>, @@ -32,3 +33,13 @@ pub async fn refresh_applications_list_in_bg( state.ctx.lock().unwrap().refresh_apps_in_background(); Ok(()) } + +#[tauri::command] +pub async fn set_extra_app_search_paths( + state: tauri::State<'_, ApplicationsState>, + paths: Vec, +) -> Result<(), String> { + let mut ctx = state.ctx.lock().unwrap(); + ctx.extra_search_paths = paths; + Ok(()) +} diff --git a/packages/tauri-plugins/jarvis/src/commands/system.rs b/packages/tauri-plugins/jarvis/src/commands/system.rs index 9c2e386..73d0b2b 100644 --- a/packages/tauri-plugins/jarvis/src/commands/system.rs +++ b/packages/tauri-plugins/jarvis/src/commands/system.rs @@ -130,7 +130,7 @@ pub async fn unmute() -> Result<(), String> { #[tauri::command] pub async fn get_frontmost_app() -> Result { - let ctx = applications::AppInfoContext::new(); + let ctx = applications::AppInfoContext::new(vec![]); ctx.get_frontmost_application() .map_err(|err| err.to_string()) } diff --git a/packages/types/src/appConfig.ts b/packages/types/src/appConfig.ts index 078ec74..f6ec643 100644 --- a/packages/types/src/appConfig.ts +++ b/packages/types/src/appConfig.ts @@ -1,4 +1,4 @@ -import { LightMode } from "@kksh/api/models" +import { LightMode, SearchPath } from "@kksh/api/models" import type { Platform } from "@tauri-apps/plugin-os" import * as v from "valibot" @@ -17,7 +17,8 @@ export const PersistedAppConfig = v.object({ extensionAutoUpgrade: v.boolean(), joinBetaProgram: v.boolean(), onBoarded: v.boolean(), - developerMode: v.boolean() + developerMode: v.boolean(), + appSearchPaths: v.array(SearchPath) }) export type PersistedAppConfig = v.InferOutput diff --git a/packages/ui/package.json b/packages/ui/package.json index dc3e765..2c0ca91 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -81,7 +81,7 @@ "moment": "^2.30.1", "pretty-bytes": "^6.1.1", "shiki-magic-move": "^0.5.2", - "svelte-inspect-value": "^0.2.2", + "svelte-inspect-value": "^0.3.0", "svelte-markdown": "^0.4.1", "valibot": "1.0.0-beta.12" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 407fa58..1f52406 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -267,8 +267,8 @@ importers: specifier: ^7.6.3 version: 7.6.3 svelte-inspect-value: - specifier: ^0.2.2 - version: 0.2.2(svelte@5.16.6) + specifier: ^0.3.0 + version: 0.3.0(svelte@5.16.6) svelte-sonner: specifier: ^0.3.28 version: 0.3.28(svelte@5.16.6) @@ -335,7 +335,7 @@ importers: version: 8.23.0(eslint@9.21.0(jiti@2.4.0))(typescript@5.6.3) autoprefixer: specifier: ^10.4.20 - version: 10.4.20(postcss@8.5.1) + version: 10.4.20(postcss@8.4.49) bits-ui: specifier: 1.0.0-next.86 version: 1.0.0-next.86(svelte@5.16.6) @@ -1241,8 +1241,8 @@ importers: specifier: ^5.0.0 version: 5.16.6 svelte-inspect-value: - specifier: ^0.2.2 - version: 0.2.2(svelte@5.16.6) + specifier: ^0.3.0 + version: 0.3.0(svelte@5.16.6) svelte-markdown: specifier: ^0.4.1 version: 0.4.1(svelte@5.16.6) @@ -10707,8 +10707,8 @@ packages: svelte: optional: true - svelte-inspect-value@0.2.2: - resolution: {integrity: sha512-Ly4QcIDoPo2O81CdIhx600bBaQdla65VXvXEMA9So947In8773Ey56k6A1WTsZiljAabxZFChBRqOt9nOYczuA==} + svelte-inspect-value@0.3.0: + resolution: {integrity: sha512-nHv+7+FRePs86sgL2I8jlbSrs8/uJmHJ2uxnMk9tVipWdZYYcmGhsmU+7U8lm/1RAZFS63/xSKdceMDyE09y0A==} peerDependencies: svelte: ^5.19.0 @@ -18189,16 +18189,6 @@ snapshots: postcss: 8.4.49 postcss-value-parser: 4.2.0 - autoprefixer@10.4.20(postcss@8.5.1): - dependencies: - browserslist: 4.24.2 - caniuse-lite: 1.0.30001676 - fraction.js: 4.3.7 - normalize-range: 0.1.2 - picocolors: 1.1.1 - postcss: 8.5.1 - postcss-value-parser: 4.2.0 - available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 @@ -23343,7 +23333,7 @@ snapshots: optionalDependencies: svelte: 5.16.6 - svelte-inspect-value@0.2.2(svelte@5.16.6): + svelte-inspect-value@0.3.0(svelte@5.16.6): dependencies: esm-env: 1.2.2 fast-deep-equal: 3.1.3