Huakun Shen caa252b4dd
feature: splashscreen (#36)
* feat: move all pages to app folder, add splashscreen

* feat: use Dance as splashscreen

* feat: add zoom in for splashscreen logo

* refactor: move svelte files into app folder

* fix: url prefix with /app

* refactor: remove platform-specific tauri conf

Merge windows back to main tauri config. The reason I separated them was
because I need decoration: true on mac and false on windows and linux.
Now I use tauri rust API to set decorations to false for win and linux.
2024-12-21 04:04:05 -05:00

125 lines
3.3 KiB
Svelte

<script lang="ts">
import { goBackOnEscape } from "@/utils/key"
import { goBack } from "@/utils/route"
import { db } from "@kksh/api/commands"
import { loadExtensionManifestFromDisk } from "@kksh/extension"
import { Button, Dialog, ScrollArea, Table } from "@kksh/svelte5"
import { join } from "@tauri-apps/api/path"
import { exists } from "@tauri-apps/plugin-fs"
import { ArrowLeftIcon } from "lucide-svelte"
import { onMount } from "svelte"
import { toast } from "svelte-sonner"
import { open } from "tauri-plugin-shellx-api"
type Result = {
identifier: string
path: string
error?: string
}
let results = $state<Result[]>([])
let isDialogOpen = $state(false)
let errorMsg = $state<string | undefined>()
const sortedResults = $derived.by(() =>
results.slice().sort((a, b) => {
return a.error ? -1 : 1
})
)
async function check() {
results = []
const tmpResults = []
const extensions = await db.getAllExtensions()
for (const ext of extensions) {
if (!ext.path) continue
const _exists = await exists(ext.path)
let error: string | undefined = undefined
if (!_exists) {
error = `Extension path (${ext.path}) does not exist`
}
const pkgJsonPath = await join(ext.path, "package.json")
const _pkgJsonExists = await exists(pkgJsonPath)
if (!_pkgJsonExists) {
error = `Extension package.json (${pkgJsonPath}) does not exist`
}
try {
const manifest = await loadExtensionManifestFromDisk(pkgJsonPath)
} catch (err: any) {
error = `Failed to load manifest from ${pkgJsonPath}: ${err.message}`
}
tmpResults.push({
identifier: ext.identifier,
path: ext.path,
error
})
}
results = tmpResults
const numErrors = results.filter((r) => r.error).length
const toastFn = numErrors > 0 ? toast.error : toast.info
toastFn(`${numErrors} errors found`, {
description: numErrors > 0 ? "Click on an error to see more details" : undefined
})
}
function onErrorClick(errMsg?: string) {
if (errMsg) {
isDialogOpen = true
errorMsg = errMsg
} else {
toast.info("No error message")
}
}
onMount(() => {
check()
})
</script>
<div class="container">
<h1 class="text-2xl font-bold">Extension Loading Troubleshooter</h1>
<Button class="my-2" onclick={check}>Check</Button>
<Dialog.Root bind:open={isDialogOpen}>
<Dialog.Content class="sm:max-w-[425px]">
<Dialog.Header>
<Dialog.Title>Error Details</Dialog.Title>
</Dialog.Header>
{errorMsg}
</Dialog.Content>
</Dialog.Root>
<Table.Root>
<Table.Caption>A list of your extensions.</Table.Caption>
<Table.Header>
<Table.Row>
<Table.Head class="">Identifier</Table.Head>
<Table.Head>Path</Table.Head>
<Table.Head>Error</Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{#each sortedResults as row}
<Table.Row>
<Table.Cell class="font-medium"><pre>{row.identifier}</pre></Table.Cell>
<Table.Cell class="">
<button onclick={() => open(row.path)} class="text-left">
<pre class="cursor-pointer text-wrap">{row.path}</pre>
</button>
</Table.Cell>
<Table.Cell class="text-right">
<button onclick={() => onErrorClick(row.error)}>
{row.error ? "⚠️" : "✅"}
</button>
</Table.Cell>
</Table.Row>
{/each}
</Table.Body>
</Table.Root>
</div>
<style>
:global(body) {
overflow-x: hidden;
}
</style>