mirror of
https://github.com/kunkunsh/kunkun.git
synced 2025-04-11 17:29:44 +00:00
feat: add extensionsInstallDir var to +layout.ts, exposed to all pages
All pages won't need to get the path asynchronously, it's kind of like a global constant
This commit is contained in:
parent
54b7cc58c4
commit
f64e562034
@ -5,6 +5,7 @@ passing everything through props will be very complicated and hard to maintain.
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { systemCommands } from "@/cmds/system"
|
import { systemCommands } from "@/cmds/system"
|
||||||
import { devStoreExts, installedStoreExts } from "@/stores"
|
import { devStoreExts, installedStoreExts } from "@/stores"
|
||||||
|
import { getActiveElementNodeName } from "@/utils/dom"
|
||||||
import type { ExtPackageJsonExtra } from "@kksh/api/models"
|
import type { ExtPackageJsonExtra } from "@kksh/api/models"
|
||||||
import { isExtPathInDev } from "@kksh/extension/utils"
|
import { isExtPathInDev } from "@kksh/extension/utils"
|
||||||
import { Command } from "@kksh/svelte5"
|
import { Command } from "@kksh/svelte5"
|
||||||
@ -35,8 +36,20 @@ passing everything through props will be very complicated and hard to maintain.
|
|||||||
appState: Writable<AppState>
|
appState: Writable<AppState>
|
||||||
builtinCmds: BuiltinCmd[]
|
builtinCmds: BuiltinCmd[]
|
||||||
} = $props()
|
} = $props()
|
||||||
|
|
||||||
|
function onKeyDown(event: KeyboardEvent) {
|
||||||
|
if (event.key === "Escape") {
|
||||||
|
if (getActiveElementNodeName() === "INPUT") {
|
||||||
|
;(event.target as HTMLInputElement).value = ""
|
||||||
|
if ((event.target as HTMLInputElement | undefined)?.id === "main-command-input") {
|
||||||
|
$appState.searchTerm = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<svelte:window on:keydown={onKeyDown} />
|
||||||
<Command.Root
|
<Command.Root
|
||||||
class={cn("rounded-lg border shadow-md", className)}
|
class={cn("rounded-lg border shadow-md", className)}
|
||||||
bind:value={$appState.highlightedCmd}
|
bind:value={$appState.highlightedCmd}
|
||||||
@ -44,6 +57,7 @@ passing everything through props will be very complicated and hard to maintain.
|
|||||||
>
|
>
|
||||||
<CustomCommandInput
|
<CustomCommandInput
|
||||||
autofocus
|
autofocus
|
||||||
|
id="main-command-input"
|
||||||
placeholder="Type a command or search..."
|
placeholder="Type a command or search..."
|
||||||
bind:value={$appState.searchTerm}
|
bind:value={$appState.searchTerm}
|
||||||
/>
|
/>
|
||||||
@ -51,7 +65,7 @@ passing everything through props will be very complicated and hard to maintain.
|
|||||||
<Command.Empty data-tauri-drag-region>No results found.</Command.Empty>
|
<Command.Empty data-tauri-drag-region>No results found.</Command.Empty>
|
||||||
<BuiltinCmds {builtinCmds} />
|
<BuiltinCmds {builtinCmds} />
|
||||||
<SystemCmds {systemCommands} />
|
<SystemCmds {systemCommands} />
|
||||||
{#if $appConfig.extensionPath && $devStoreExts.length > 0}
|
{#if $appConfig.extensionsInstallDir && $devStoreExts.length > 0}
|
||||||
<ExtCmdsGroup
|
<ExtCmdsGroup
|
||||||
extensions={$devStoreExts}
|
extensions={$devStoreExts}
|
||||||
heading="Dev Extensions"
|
heading="Dev Extensions"
|
||||||
@ -60,7 +74,7 @@ passing everything through props will be very complicated and hard to maintain.
|
|||||||
hmr={$appConfig.hmr}
|
hmr={$appConfig.hmr}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $appConfig.extensionPath && $installedStoreExts.length > 0}
|
{#if $appConfig.extensionsInstallDir && $installedStoreExts.length > 0}
|
||||||
<ExtCmdsGroup
|
<ExtCmdsGroup
|
||||||
extensions={$installedStoreExts}
|
extensions={$installedStoreExts}
|
||||||
heading="Extensions"
|
heading="Extensions"
|
||||||
|
@ -21,7 +21,7 @@ export const defaultAppConfig: AppConfig = {
|
|||||||
launchAtLogin: true,
|
launchAtLogin: true,
|
||||||
showInTray: true,
|
showInTray: true,
|
||||||
devExtensionPath: null,
|
devExtensionPath: null,
|
||||||
extensionPath: undefined,
|
extensionsInstallDir: undefined,
|
||||||
hmr: false,
|
hmr: false,
|
||||||
hideOnBlur: true,
|
hideOnBlur: true,
|
||||||
extensionAutoUpgrade: true,
|
extensionAutoUpgrade: true,
|
||||||
@ -40,20 +40,17 @@ function createAppConfig(): Writable<AppConfig> & AppConfigAPI {
|
|||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
debug("Initializing app config")
|
debug("Initializing app config")
|
||||||
const appDataDir = await path.appDataDir()
|
|
||||||
// const appConfigPath = await path.join(appDataDir, "appConfig.json")
|
|
||||||
// debug(`appConfigPath: ${appConfigPath}`)
|
|
||||||
const persistStore = await load("kk-config.json", { autoSave: true })
|
const persistStore = await load("kk-config.json", { autoSave: true })
|
||||||
const loadedConfig = await persistStore.get("config")
|
const loadedConfig = await persistStore.get("config")
|
||||||
const parseRes = v.safeParse(PersistedAppConfig, loadedConfig)
|
const parseRes = v.safeParse(PersistedAppConfig, loadedConfig)
|
||||||
if (parseRes.success) {
|
if (parseRes.success) {
|
||||||
console.log("Parse Persisted App Config Success", parseRes.output)
|
console.log("Parse Persisted App Config Success", parseRes.output)
|
||||||
const extensionPath = await path.join(appDataDir, "extensions")
|
const extensionsInstallDir = await getExtensionsFolder()
|
||||||
update((config) => ({
|
update((config) => ({
|
||||||
...config,
|
...config,
|
||||||
...parseRes.output,
|
...parseRes.output,
|
||||||
isInitialized: true,
|
isInitialized: true,
|
||||||
extensionPath,
|
extensionsInstallDir,
|
||||||
platform: os.platform()
|
platform: os.platform()
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
|
@ -25,7 +25,7 @@ function createExtensionsStore(): Writable<ExtPackageJsonExtra[]> & {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getExtensionsFromStore() {
|
function getExtensionsFromStore() {
|
||||||
const extContainerPath = get(appConfig).extensionPath
|
const extContainerPath = get(appConfig).extensionsInstallDir
|
||||||
if (!extContainerPath) return []
|
if (!extContainerPath) return []
|
||||||
return get(extensions).filter((ext) => !extAPI.isExtPathInDev(extContainerPath, ext.extPath))
|
return get(extensions).filter((ext) => !extAPI.isExtPathInDev(extContainerPath, ext.extPath))
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ function createExtensionsStore(): Writable<ExtPackageJsonExtra[]> & {
|
|||||||
identifier: string,
|
identifier: string,
|
||||||
tarballUrl: string
|
tarballUrl: string
|
||||||
): Promise<ExtPackageJsonExtra> {
|
): Promise<ExtPackageJsonExtra> {
|
||||||
const extsDir = get(appConfig).extensionPath
|
const extsDir = get(appConfig).extensionsInstallDir
|
||||||
if (!extsDir) throw new Error("Extension path not set")
|
if (!extsDir) throw new Error("Extension path not set")
|
||||||
return uninstallStoreExtensionByIdentifier(identifier).then(() =>
|
return uninstallStoreExtensionByIdentifier(identifier).then(() =>
|
||||||
installFromTarballUrl(tarballUrl, extsDir)
|
installFromTarballUrl(tarballUrl, extsDir)
|
||||||
@ -109,7 +109,7 @@ export const extensions = createExtensionsStore()
|
|||||||
export const installedStoreExts: Readable<ExtPackageJsonExtra[]> = derived(
|
export const installedStoreExts: Readable<ExtPackageJsonExtra[]> = derived(
|
||||||
extensions,
|
extensions,
|
||||||
($extensionsStore) => {
|
($extensionsStore) => {
|
||||||
const extContainerPath = get(appConfig).extensionPath
|
const extContainerPath = get(appConfig).extensionsInstallDir
|
||||||
if (!extContainerPath) return []
|
if (!extContainerPath) return []
|
||||||
return $extensionsStore.filter((ext) => !extAPI.isExtPathInDev(extContainerPath, ext.extPath))
|
return $extensionsStore.filter((ext) => !extAPI.isExtPathInDev(extContainerPath, ext.extPath))
|
||||||
}
|
}
|
||||||
@ -117,7 +117,7 @@ export const installedStoreExts: Readable<ExtPackageJsonExtra[]> = derived(
|
|||||||
export const devStoreExts: Readable<ExtPackageJsonExtra[]> = derived(
|
export const devStoreExts: Readable<ExtPackageJsonExtra[]> = derived(
|
||||||
extensions,
|
extensions,
|
||||||
($extensionsStore) => {
|
($extensionsStore) => {
|
||||||
const extContainerPath = get(appConfig).extensionPath
|
const extContainerPath = get(appConfig).extensionsInstallDir
|
||||||
if (!extContainerPath) return []
|
if (!extContainerPath) return []
|
||||||
return $extensionsStore.filter((ext) => extAPI.isExtPathInDev(extContainerPath, ext.extPath))
|
return $extensionsStore.filter((ext) => extAPI.isExtPathInDev(extContainerPath, ext.extPath))
|
||||||
}
|
}
|
||||||
|
3
apps/desktop/src/lib/utils/dom.ts
Normal file
3
apps/desktop/src/lib/utils/dom.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export function getActiveElementNodeName(): string | undefined {
|
||||||
|
return document.activeElement?.nodeName
|
||||||
|
}
|
@ -1,5 +1,12 @@
|
|||||||
|
import { getExtensionsFolder } from "@/constants"
|
||||||
|
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
|
||||||
// so we will use adapter-static to prerender the app (SSG)
|
// so we will use adapter-static to prerender the app (SSG)
|
||||||
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
|
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
|
||||||
export const prerender = true
|
export const prerender = true
|
||||||
export const ssr = false
|
export const ssr = false
|
||||||
|
|
||||||
|
export const load: LayoutLoad = async () => {
|
||||||
|
return { extsInstallDir: await getExtensionsFolder() }
|
||||||
|
}
|
||||||
|
@ -65,7 +65,6 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window on:keydown={goBackOnEscapeClearSearchTerm} />
|
<svelte:window on:keydown={goBackOnEscapeClearSearchTerm} />
|
||||||
|
|
||||||
{#snippet leftSlot()}
|
{#snippet leftSlot()}
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
@ -36,9 +36,9 @@
|
|||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
showBtn = {
|
showBtn = {
|
||||||
install: !installedExt,
|
install: !$installedExt,
|
||||||
upgrade: isUpgradable,
|
upgrade: isUpgradable,
|
||||||
uninstall: !!installedExt
|
uninstall: !!$installedExt
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -140,7 +140,6 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window on:keydown={handleKeydown} />
|
<svelte:window on:keydown={handleKeydown} />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="icon"
|
size="icon"
|
||||||
|
@ -23,6 +23,6 @@ export type PersistedAppConfig = v.InferOutput<typeof PersistedAppConfig>
|
|||||||
|
|
||||||
export type AppConfig = PersistedAppConfig & {
|
export type AppConfig = PersistedAppConfig & {
|
||||||
isInitialized: boolean
|
isInitialized: boolean
|
||||||
extensionPath?: string
|
extensionsInstallDir?: string
|
||||||
platform: Platform
|
platform: Platform
|
||||||
}
|
}
|
||||||
|
@ -125,8 +125,8 @@
|
|||||||
data-flip-id={`${Constants.CLASSNAMES.EXT_LOGO}-${ext.identifier}`}
|
data-flip-id={`${Constants.CLASSNAMES.EXT_LOGO}-${ext.identifier}`}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<div>
|
<div class="w-full">
|
||||||
<span class="flex items-center">
|
<span class="flex items-center w-full" use:autoAnimate>
|
||||||
<strong class="ext-name text-xl">{manifest?.name}</strong>
|
<strong class="ext-name text-xl">{manifest?.name}</strong>
|
||||||
{#if isInstalled}
|
{#if isInstalled}
|
||||||
<CircleCheckBigIcon class="ml-2 inline text-green-400" />
|
<CircleCheckBigIcon class="ml-2 inline text-green-400" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user