diff options
Diffstat (limited to 'packages/app/src/pages')
| -rw-r--r-- | packages/app/src/pages/directory-layout.tsx | 70 | ||||
| -rw-r--r-- | packages/app/src/pages/layout.tsx | 62 |
2 files changed, 62 insertions, 70 deletions
diff --git a/packages/app/src/pages/directory-layout.tsx b/packages/app/src/pages/directory-layout.tsx index 6d3b04be9..cd5e079a6 100644 --- a/packages/app/src/pages/directory-layout.tsx +++ b/packages/app/src/pages/directory-layout.tsx @@ -2,7 +2,8 @@ import { DataProvider } from "@opencode-ai/ui/context" import { showToast } from "@opencode-ai/ui/toast" import { base64Encode } from "@opencode-ai/util/encode" import { useLocation, useNavigate, useParams } from "@solidjs/router" -import { createEffect, createMemo, type ParentProps, Show } from "solid-js" +import { createMemo, createResource, type ParentProps, Show } from "solid-js" +import { useGlobalSDK } from "@/context/global-sdk" import { useLanguage } from "@/context/language" import { LocalProvider } from "@/context/local" import { SDKProvider } from "@/context/sdk" @@ -10,18 +11,10 @@ import { SyncProvider, useSync } from "@/context/sync" import { decode64 } from "@/utils/base64" function DirectoryDataProvider(props: ParentProps<{ directory: string }>) { - const location = useLocation() const navigate = useNavigate() const sync = useSync() const slug = createMemo(() => base64Encode(props.directory)) - createEffect(() => { - const next = sync.data.path.directory - if (!next || next === props.directory) return - const path = location.pathname.slice(slug().length + 1) - navigate(`/${base64Encode(next)}${path}${location.search}${location.hash}`, { replace: true }) - }) - return ( <DataProvider data={sync.data} @@ -36,31 +29,50 @@ function DirectoryDataProvider(props: ParentProps<{ directory: string }>) { export default function Layout(props: ParentProps) { const params = useParams() + const location = useLocation() const language = useLanguage() + const globalSDK = useGlobalSDK() const navigate = useNavigate() let invalid = "" - const resolved = createMemo(() => { - if (!params.dir) return "" - return decode64(params.dir) ?? "" - }) + const [resolved] = createResource( + () => { + if (params.dir) return [location.pathname, params.dir] as const + }, + async ([pathname, b64Dir]) => { + const directory = decode64(b64Dir) - createEffect(() => { - const dir = params.dir - if (!dir) return - if (resolved()) { - invalid = "" - return - } - if (invalid === dir) return - invalid = dir - showToast({ - variant: "error", - title: language.t("common.requestFailed"), - description: language.t("directory.error.invalidUrl"), - }) - navigate("/", { replace: true }) - }) + if (!directory) { + if (invalid === params.dir) return + invalid = b64Dir + showToast({ + variant: "error", + title: language.t("common.requestFailed"), + description: language.t("directory.error.invalidUrl"), + }) + navigate("/", { replace: true }) + return + } + + return await globalSDK + .createClient({ + directory, + throwOnError: true, + }) + .path.get() + .then((x) => { + const next = x.data?.directory ?? directory + invalid = "" + if (next === directory) return next + const path = pathname.slice(b64Dir.length + 1) + navigate(`/${base64Encode(next)}${path}${location.search}${location.hash}`, { replace: true }) + }) + .catch(() => { + invalid = "" + return directory + }) + }, + ) return ( <Show when={resolved()} keyed> diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index 731f0fe5b..1300f88a8 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -49,16 +49,21 @@ import { useNotification } from "@/context/notification" import { usePermission } from "@/context/permission" import { Binary } from "@opencode-ai/util/binary" import { retry } from "@opencode-ai/util/retry" -import { playSoundById } from "@/utils/sound" +import { playSound, soundSrc } from "@/utils/sound" import { createAim } from "@/utils/aim" import { setNavigate } from "@/utils/notification-click" import { Worktree as WorktreeState } from "@/utils/worktree" import { setSessionHandoff } from "@/pages/session/handoff" import { useDialog } from "@opencode-ai/ui/context/dialog" -import { useTheme, type ColorScheme } from "@opencode-ai/ui/theme/context" +import { useTheme, type ColorScheme } from "@opencode-ai/ui/theme" +import { DialogSelectProvider } from "@/components/dialog-select-provider" +import { DialogSelectServer } from "@/components/dialog-select-server" +import { DialogSettings } from "@/components/dialog-settings" import { useCommand, type CommandOption } from "@/context/command" import { ConstrainDragXAxis, getDraggableId } from "@/utils/solid-dnd" +import { DialogSelectDirectory } from "@/components/dialog-select-directory" +import { DialogEditProject } from "@/components/dialog-edit-project" import { DebugBar } from "@/components/debug-bar" import { Titlebar } from "@/components/titlebar" import { useServer } from "@/context/server" @@ -105,8 +110,6 @@ export default function Layout(props: ParentProps) { const pageReady = createMemo(() => ready()) let scrollContainerRef: HTMLDivElement | undefined - let dialogRun = 0 - let dialogDead = false const params = useParams() const globalSDK = useGlobalSDK() @@ -136,7 +139,7 @@ export default function Layout(props: ParentProps) { dir: globalSync.peek(dir, { bootstrap: false })[0].path.directory || dir, } }) - const availableThemeEntries = createMemo(() => theme.ids().map((id) => [id, theme.themes()[id]] as const)) + const availableThemeEntries = createMemo(() => Object.entries(theme.themes())) const colorSchemeOrder: ColorScheme[] = ["system", "light", "dark"] const colorSchemeKey: Record<ColorScheme, "theme.scheme.system" | "theme.scheme.light" | "theme.scheme.dark"> = { system: "theme.scheme.system", @@ -198,8 +201,6 @@ export default function Layout(props: ParentProps) { }) onCleanup(() => { - dialogDead = true - dialogRun += 1 if (navLeave.current !== undefined) clearTimeout(navLeave.current) clearTimeout(sortNowTimeout) if (sortNowInterval) clearInterval(sortNowInterval) @@ -335,9 +336,10 @@ export default function Layout(props: ParentProps) { const nextIndex = currentIndex === -1 ? 0 : (currentIndex + direction + ids.length) % ids.length const nextThemeId = ids[nextIndex] theme.setTheme(nextThemeId) + const nextTheme = theme.themes()[nextThemeId] showToast({ title: language.t("toast.theme.title"), - description: theme.name(nextThemeId), + description: nextTheme?.name ?? nextThemeId, }) } @@ -492,7 +494,7 @@ export default function Layout(props: ParentProps) { if (e.details.type === "permission.asked") { if (settings.sounds.permissionsEnabled()) { - void playSoundById(settings.sounds.permissions()) + playSound(soundSrc(settings.sounds.permissions())) } if (settings.notifications.permissions()) { void platform.notify(title, description, href) @@ -1150,10 +1152,10 @@ export default function Layout(props: ParentProps) { }, ] - for (const [id] of availableThemeEntries()) { + for (const [id, definition] of availableThemeEntries()) { commands.push({ id: `theme.set.${id}`, - title: language.t("command.theme.set", { theme: theme.name(id) }), + title: language.t("command.theme.set", { theme: definition.name ?? id }), category: language.t("command.category.theme"), onSelect: () => theme.commitPreview(), onHighlight: () => { @@ -1204,27 +1206,15 @@ export default function Layout(props: ParentProps) { }) function connectProvider() { - const run = ++dialogRun - void import("@/components/dialog-select-provider").then((x) => { - if (dialogDead || dialogRun !== run) return - dialog.show(() => <x.DialogSelectProvider />) - }) + dialog.show(() => <DialogSelectProvider />) } function openServer() { - const run = ++dialogRun - void import("@/components/dialog-select-server").then((x) => { - if (dialogDead || dialogRun !== run) return - dialog.show(() => <x.DialogSelectServer />) - }) + dialog.show(() => <DialogSelectServer />) } function openSettings() { - const run = ++dialogRun - void import("@/components/dialog-settings").then((x) => { - if (dialogDead || dialogRun !== run) return - dialog.show(() => <x.DialogSettings />) - }) + dialog.show(() => <DialogSettings />) } function projectRoot(directory: string) { @@ -1451,13 +1441,7 @@ export default function Layout(props: ParentProps) { layout.sidebar.toggleWorkspaces(project.worktree) } - const showEditProjectDialog = (project: LocalProject) => { - const run = ++dialogRun - void import("@/components/dialog-edit-project").then((x) => { - if (dialogDead || dialogRun !== run) return - dialog.show(() => <x.DialogEditProject project={project} />) - }) - } + const showEditProjectDialog = (project: LocalProject) => dialog.show(() => <DialogEditProject project={project} />) async function chooseProject() { function resolve(result: string | string[] | null) { @@ -1478,14 +1462,10 @@ export default function Layout(props: ParentProps) { }) resolve(result) } else { - const run = ++dialogRun - void import("@/components/dialog-select-directory").then((x) => { - if (dialogDead || dialogRun !== run) return - dialog.show( - () => <x.DialogSelectDirectory multiple={true} onSelect={resolve} />, - () => resolve(null), - ) - }) + dialog.show( + () => <DialogSelectDirectory multiple={true} onSelect={resolve} />, + () => resolve(null), + ) } } |
