mirror of
https://github.com/kunkunsh/kunkun.git
synced 2025-04-14 18:54:34 +00:00
UI (#94)
* feat: add publisher link to extension detail * fix: improve IconMultiplexer and StoreExtDetail component rendering * feat: add published date to extension details view * chore: add moment.js and clean up imports in StoreExtDetail * fix: support cloudflare worker Otherwise cloudflare worker gets html instead of json * refactor: move AppsCmds component to desktop app * bump: version to 0.1.1 * fix: package.json fetching cors error * fix: improve files field validation in verify command
This commit is contained in:
parent
e49c0f5da5
commit
490368428e
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "kksh",
|
"name": "kksh",
|
||||||
"module": "dist/cli.js",
|
"module": "dist/cli.js",
|
||||||
"version": "0.0.32",
|
"version": "0.1.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bin": {
|
"bin": {
|
||||||
"kksh": "./dist/cli.js",
|
"kksh": "./dist/cli.js",
|
||||||
|
@ -52,7 +52,8 @@ export function verifySingleProject(projectPath: string): boolean {
|
|||||||
logger.info(`name`, pkg.name)
|
logger.info(`name`, pkg.name)
|
||||||
logger.info(`version`, pkg.version)
|
logger.info(`version`, pkg.version)
|
||||||
logger.info(`identifier`, pkg.kunkun.identifier)
|
logger.info(`identifier`, pkg.kunkun.identifier)
|
||||||
if (pkg.files?.length ?? 0 === 0) {
|
|
||||||
|
if ((pkg.files?.length ?? 0) === 0) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`"files" field is empty, it is recommended to include only the necessary files, e.g. dist`
|
`"files" field is empty, it is recommended to include only the necessary files, e.g. dist`
|
||||||
)
|
)
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { IconEnum, type AppInfo } from "@kksh/api/models"
|
import { IconEnum, type AppInfo } from "@kksh/api/models"
|
||||||
import { Command } from "@kksh/svelte5"
|
import { Command } from "@kksh/svelte5"
|
||||||
|
import { IconMultiplexer } from "@kksh/ui"
|
||||||
|
import { DraggableCommandGroup } from "@kksh/ui/custom"
|
||||||
import { convertFileSrc } from "@tauri-apps/api/core"
|
import { convertFileSrc } from "@tauri-apps/api/core"
|
||||||
import * as os from "@tauri-apps/plugin-os"
|
import * as os from "@tauri-apps/plugin-os"
|
||||||
import { toast } from "svelte-sonner"
|
import { toast } from "svelte-sonner"
|
||||||
import { executeBashScript, open } from "tauri-plugin-shellx-api"
|
import { open } from "tauri-plugin-shellx-api"
|
||||||
import IconMultiplexer from "../common/IconMultiplexer.svelte"
|
|
||||||
import { DraggableCommandGroup } from "../custom"
|
|
||||||
|
|
||||||
const platform = os.platform()
|
const platform = os.platform()
|
||||||
let { apps }: { apps: AppInfo[] } = $props()
|
let { apps }: { apps: AppInfo[] } = $props()
|
||||||
// let appsDisplay = $derived(apps.length > 20 ? apps.slice(0, 20) : apps)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DraggableCommandGroup heading="Apps">
|
<DraggableCommandGroup heading="Apps">
|
@ -3,6 +3,7 @@
|
|||||||
import { commandLaunchers } from "@/cmds"
|
import { commandLaunchers } from "@/cmds"
|
||||||
import { builtinCmds } from "@/cmds/builtin"
|
import { builtinCmds } from "@/cmds/builtin"
|
||||||
import { systemCommands } from "@/cmds/system"
|
import { systemCommands } from "@/cmds/system"
|
||||||
|
import AppsCmds from "@/components/main/AppsCmds.svelte"
|
||||||
import { i18n } from "@/i18n"
|
import { i18n } from "@/i18n"
|
||||||
import * as m from "@/paraglide/messages"
|
import * as m from "@/paraglide/messages"
|
||||||
import {
|
import {
|
||||||
@ -21,10 +22,9 @@
|
|||||||
import { cmdQueries } from "@/stores/cmdQuery"
|
import { cmdQueries } from "@/stores/cmdQuery"
|
||||||
import { isKeyboardEventFromInputElement } from "@/utils/dom"
|
import { isKeyboardEventFromInputElement } from "@/utils/dom"
|
||||||
import Icon from "@iconify/svelte"
|
import Icon from "@iconify/svelte"
|
||||||
import { db, toggleDevTools } from "@kksh/api/commands"
|
import { toggleDevTools } from "@kksh/api/commands"
|
||||||
import { Button, Command, DropdownMenu } from "@kksh/svelte5"
|
import { Button, Command, DropdownMenu } from "@kksh/svelte5"
|
||||||
import {
|
import {
|
||||||
AppsCmds,
|
|
||||||
BuiltinCmds,
|
BuiltinCmds,
|
||||||
CustomCommandInput,
|
CustomCommandInput,
|
||||||
ExtCmdsGroup,
|
ExtCmdsGroup,
|
||||||
|
@ -21,7 +21,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.1.0"
|
export const version = "0.1.1"
|
||||||
|
|
||||||
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)
|
||||||
|
@ -119,9 +119,7 @@ export function getJsrPackageSrcFile(
|
|||||||
file: string
|
file: string
|
||||||
): Promise<string | undefined> {
|
): Promise<string | undefined> {
|
||||||
const url = `https://jsr.io/@${scope}/${name}/${version}/${file}`
|
const url = `https://jsr.io/@${scope}/${name}/${version}/${file}`
|
||||||
return fetch(url)
|
return fetch(url).then((res) => res.text())
|
||||||
.then((res) => res.text())
|
|
||||||
.catch(() => undefined)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
## Permission Table
|
## Permission Table
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
@ -6,6 +7,7 @@
|
|||||||
<th>Description</th>
|
<th>Description</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
"@std/semver": "npm:@jsr/std__semver@^1.0.3",
|
"@std/semver": "npm:@jsr/std__semver@^1.0.3",
|
||||||
"dompurify": "^3.2.3",
|
"dompurify": "^3.2.3",
|
||||||
"gsap": "^3.12.7",
|
"gsap": "^3.12.7",
|
||||||
|
"moment": "^2.30.1",
|
||||||
"pretty-bytes": "^6.1.1",
|
"pretty-bytes": "^6.1.1",
|
||||||
"shiki-magic-move": "^0.5.2",
|
"shiki-magic-move": "^0.5.2",
|
||||||
"svelte-markdown": "^0.4.1",
|
"svelte-markdown": "^0.4.1",
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (icon.type === IconEnum.Svg) {
|
if (icon.type === IconEnum.Svg) {
|
||||||
cleanedSvg = DOMPurify.sanitize(icon.value)
|
cleanedSvg = DOMPurify.sanitize(icon.value)
|
||||||
|
cleanedSvg = cleanedSvg.replace("<svg", `<svg class="${className}"`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@ -96,7 +97,7 @@
|
|||||||
{:else if icon.type === IconEnum.Svg}
|
{:else if icon.type === IconEnum.Svg}
|
||||||
<span
|
<span
|
||||||
{...restProps}
|
{...restProps}
|
||||||
class={cn(className, { invert: icon.invert, "dark:invert": icon.darkInvert })}
|
class={cn({ invert: icon.invert, "dark:invert": icon.darkInvert }, className)}
|
||||||
{style}
|
{style}
|
||||||
>
|
>
|
||||||
<!-- eslint-disable svelte/no-at-html-tags -->
|
<!-- eslint-disable svelte/no-at-html-tags -->
|
||||||
|
@ -8,8 +8,10 @@
|
|||||||
import { Constants, IconMultiplexer } from "@kksh/ui"
|
import { Constants, IconMultiplexer } from "@kksh/ui"
|
||||||
import { cn } from "@kksh/ui/utils"
|
import { cn } from "@kksh/ui/utils"
|
||||||
import { CircleCheckBigIcon, MoveRightIcon, Trash2Icon } from "lucide-svelte"
|
import { CircleCheckBigIcon, MoveRightIcon, Trash2Icon } from "lucide-svelte"
|
||||||
|
import moment from "moment"
|
||||||
import prettyBytes from "pretty-bytes"
|
import prettyBytes from "pretty-bytes"
|
||||||
import * as v from "valibot"
|
import * as v from "valibot"
|
||||||
|
import { isInTauri } from "../../utils/tauri"
|
||||||
import DialogImageCarousel from "../common/DialogImageCarousel.svelte"
|
import DialogImageCarousel from "../common/DialogImageCarousel.svelte"
|
||||||
import PlatformsIcons from "../common/PlatformsIcons.svelte"
|
import PlatformsIcons from "../common/PlatformsIcons.svelte"
|
||||||
import TauriLink from "../common/TauriLink.svelte"
|
import TauriLink from "../common/TauriLink.svelte"
|
||||||
@ -20,6 +22,7 @@
|
|||||||
let {
|
let {
|
||||||
extPublish,
|
extPublish,
|
||||||
ext,
|
ext,
|
||||||
|
author,
|
||||||
installedExt,
|
installedExt,
|
||||||
manifest,
|
manifest,
|
||||||
demoImages,
|
demoImages,
|
||||||
@ -35,6 +38,10 @@
|
|||||||
}: {
|
}: {
|
||||||
extPublish: Tables<"ext_publish">
|
extPublish: Tables<"ext_publish">
|
||||||
ext: Tables<"extensions">
|
ext: Tables<"extensions">
|
||||||
|
author?: {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
} | null
|
||||||
installedExt?: ExtPackageJson
|
installedExt?: ExtPackageJson
|
||||||
packageJson: ExtPackageJson | null
|
packageJson: ExtPackageJson | null
|
||||||
manifest: KunkunExtManifest
|
manifest: KunkunExtManifest
|
||||||
@ -150,7 +157,7 @@
|
|||||||
<ScrollArea class={cn("w-full pb-12", className)}>
|
<ScrollArea class={cn("w-full pb-12", className)}>
|
||||||
<div class="flex flex-col items-center justify-between gap-4 sm:flex-row">
|
<div class="flex flex-col items-center justify-between gap-4 sm:flex-row">
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<span class="h-12 w-12">
|
<span class="h-20 w-20">
|
||||||
<IconMultiplexer
|
<IconMultiplexer
|
||||||
icon={manifest.icon}
|
icon={manifest.icon}
|
||||||
class={cn(Constants.CLASSNAMES.EXT_LOGO, "h-full w-full")}
|
class={cn(Constants.CLASSNAMES.EXT_LOGO, "h-full w-full")}
|
||||||
@ -167,9 +174,12 @@
|
|||||||
<pre class="text-muted-foreground text-xs">{extPublish.identifier}</pre>
|
<pre class="text-muted-foreground text-xs">{extPublish.identifier}</pre>
|
||||||
<pre class="text-muted-foreground text-xs">Version: {extPublish.version}</pre>
|
<pre class="text-muted-foreground text-xs">Version: {extPublish.version}</pre>
|
||||||
<pre class="text-muted-foreground text-xs">Downloads: {ext.downloads}</pre>
|
<pre class="text-muted-foreground text-xs">Downloads: {ext.downloads}</pre>
|
||||||
<pre class="text-muted-foreground text-xs">
|
<pre class="text-muted-foreground text-xs">Size: {prettyBytes(
|
||||||
Size: {prettyBytes(extPublish.tarball_size)}
|
extPublish.tarball_size
|
||||||
</pre>
|
)}</pre>
|
||||||
|
<pre class="text-muted-foreground text-xs">Published At: {moment(
|
||||||
|
new Date(extPublish.created_at)
|
||||||
|
).format("YYYY-MM-DD HH:mm")}</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
@ -266,6 +276,18 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
<h2 class="text-lg font-bold">Publisher Profile</h2>
|
||||||
|
{#if !isInTauri && author}
|
||||||
|
<ul class="list-disc pl-5">
|
||||||
|
<li>
|
||||||
|
<a class="text-blue-500 hover:text-blue-600" href={`/user/${author.id}`}
|
||||||
|
>{author.name}</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{:else}
|
||||||
|
<TauriLink href={`https://kunkun.sh/user/${ext.author_id}`}>{ext.author_id}</TauriLink>
|
||||||
|
{/if}
|
||||||
<h2 class="text-lg font-bold">Author</h2>
|
<h2 class="text-lg font-bold">Author</h2>
|
||||||
{#if packageJson?.author}
|
{#if packageJson?.author}
|
||||||
<ul class="list-disc pl-5">
|
<ul class="list-disc pl-5">
|
||||||
|
@ -4,5 +4,4 @@ export { default as GlobalCommandPaletteFooter } from "./GlobalCommandPaletteFoo
|
|||||||
export { default as ExtCmdsGroup } from "./ExtCmdsGroup.svelte"
|
export { default as ExtCmdsGroup } from "./ExtCmdsGroup.svelte"
|
||||||
export { default as SystemCmds } from "./SystemCmds.svelte"
|
export { default as SystemCmds } from "./SystemCmds.svelte"
|
||||||
export { default as QuickLinks } from "./QuickLinks.svelte"
|
export { default as QuickLinks } from "./QuickLinks.svelte"
|
||||||
export { default as AppsCmds } from "./AppsCmds.svelte"
|
|
||||||
export * from "./types"
|
export * from "./types"
|
||||||
|
4
packages/ui/src/utils/tauri.ts
Normal file
4
packages/ui/src/utils/tauri.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { browser } from "$app/environment"
|
||||||
|
|
||||||
|
// @ts-expect-error window.__TAURI_INTERNALS__ is not defined in the browser
|
||||||
|
export const isInTauri = browser ? !!window.__TAURI_INTERNALS__ : false
|
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@ -1198,6 +1198,9 @@ importers:
|
|||||||
gsap:
|
gsap:
|
||||||
specifier: ^3.12.7
|
specifier: ^3.12.7
|
||||||
version: 3.12.7
|
version: 3.12.7
|
||||||
|
moment:
|
||||||
|
specifier: ^2.30.1
|
||||||
|
version: 2.30.1
|
||||||
pretty-bytes:
|
pretty-bytes:
|
||||||
specifier: ^6.1.1
|
specifier: ^6.1.1
|
||||||
version: 6.1.1
|
version: 6.1.1
|
||||||
@ -8829,6 +8832,9 @@ packages:
|
|||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
moment@2.30.1:
|
||||||
|
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
|
||||||
|
|
||||||
mri@1.2.0:
|
mri@1.2.0:
|
||||||
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@ -21098,6 +21104,8 @@ snapshots:
|
|||||||
requirejs: 2.3.7
|
requirejs: 2.3.7
|
||||||
requirejs-config-file: 4.0.0
|
requirejs-config-file: 4.0.0
|
||||||
|
|
||||||
|
moment@2.30.1: {}
|
||||||
|
|
||||||
mri@1.2.0: {}
|
mri@1.2.0: {}
|
||||||
|
|
||||||
mrmime@2.0.0: {}
|
mrmime@2.0.0: {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user