chore: merge dev into v2 (#34788)
Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com> Co-authored-by: Kit Langton <kit.langton@gmail.com> Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com> Co-authored-by: Affan Ali <93028901+affanali2k3@users.noreply.github.com> Co-authored-by: affanali2k3 <affanalikhanxx@gmail.com> Co-authored-by: Frank <frank@anoma.ly> Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com> Co-authored-by: 𝓛𝓲𝓽𝓽𝓵𝓮 𝓕𝓻𝓪𝓷𝓴 <little-frank@opencord.local> Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Co-authored-by: Jay V <air@live.ca> Co-authored-by: Dax Raad <d@ironbay.co> Co-authored-by: Aarav Sareen <96787824+arvsrn@users.noreply.github.com> Co-authored-by: OpeOginni <107570612+OpeOginni@users.noreply.github.com> Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com> Co-authored-by: Ben Guthrie <benjee.012@gmail.com> Co-authored-by: Dax <mail@thdxr.com> Co-authored-by: Filip <34747899+neriousy@users.noreply.github.com> Co-authored-by: Max Anderson <max.a.anderson95@gmail.com> Co-authored-by: Brendan Allan <git@brendonovich.dev> Co-authored-by: Jack <jack@anoma.ly> Co-authored-by: Shoubhit Dash <shoubhit2005@gmail.com> Co-authored-by: Dustin Deus <deusdustin@gmail.com> Co-authored-by: starptech <starptech@starptechs-MBP.fritz.box> Co-authored-by: Aiden Cline <aidenpcline@gmail.com> Co-authored-by: usrnk1 <7547651+usrnk1@users.noreply.github.com> Co-authored-by: Jay <53023+jayair@users.noreply.github.com> Co-authored-by: runvip <164729189+runvip@users.noreply.github.com> Co-authored-by: opencode <opencode@sst.dev> Co-authored-by: Julian Coy <julian@ex-machina.co> Co-authored-by: Vladimir Glafirov <vglafirov@gitlab.com>
This commit is contained in:
parent
932a40cfd9
commit
8c94e9005f
590 changed files with 15772 additions and 5530 deletions
|
|
@ -17,7 +17,7 @@ import {
|
|||
import type { UpdaterState } from "@opencode-ai/app/updater"
|
||||
import * as Sentry from "@sentry/solid"
|
||||
import type { AsyncStorage } from "@solid-primitives/storage"
|
||||
import { MemoryRouter } from "@solidjs/router"
|
||||
import { createMemoryHistory, MemoryRouter, type BaseRouterProps } from "@solidjs/router"
|
||||
import { createEffect, createMemo, createResource, createSignal, onCleanup, onMount, Show } from "solid-js"
|
||||
import { render } from "solid-js/web"
|
||||
import pkg from "../../package.json"
|
||||
|
|
@ -64,6 +64,10 @@ void window.api.updater.subscribe(setUpdaterState)
|
|||
|
||||
const deepLinkEvent = "opencode:deep-link"
|
||||
|
||||
type DesktopWindowState = {
|
||||
id?: string
|
||||
}
|
||||
|
||||
const emitDeepLinks = (urls: string[]) => {
|
||||
if (urls.length === 0) return
|
||||
window.__OPENCODE__ ??= {}
|
||||
|
|
@ -77,7 +81,35 @@ const listenForDeepLinks = () => {
|
|||
return window.api.onDeepLink((urls) => emitDeepLinks(urls))
|
||||
}
|
||||
|
||||
const createPlatform = (): Platform => {
|
||||
function windowLastActiveUrlKey(windowID: string) {
|
||||
return `opencode.desktop.window.${windowID}.last-active-url`
|
||||
}
|
||||
|
||||
function getLastActiveUrl(windowID: string) {
|
||||
if (typeof localStorage !== "object") return "/"
|
||||
try {
|
||||
const value = localStorage.getItem(windowLastActiveUrlKey(windowID))
|
||||
if (value?.startsWith("/") && !value.startsWith("//")) return value
|
||||
} catch {}
|
||||
return "/"
|
||||
}
|
||||
|
||||
function setLastActiveUrl(windowID: string, value: string) {
|
||||
if (typeof localStorage !== "object") return
|
||||
try {
|
||||
localStorage.setItem(windowLastActiveUrlKey(windowID), value)
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function DesktopMemoryRouter(props: BaseRouterProps & { windowID: string }) {
|
||||
const history = createMemoryHistory()
|
||||
const initialUrl = getLastActiveUrl(props.windowID)
|
||||
if (initialUrl !== "/") history.set({ value: initialUrl, replace: true, scroll: false })
|
||||
onCleanup(history.listen((value) => setLastActiveUrl(props.windowID, value)))
|
||||
return <MemoryRouter {...props} history={history} />
|
||||
}
|
||||
|
||||
const createPlatform = (windowState: DesktopWindowState): Platform => {
|
||||
const attachmentPaths = new WeakMap<File, string>()
|
||||
const os = (() => {
|
||||
const ua = navigator.userAgent
|
||||
|
|
@ -136,6 +168,7 @@ const createPlatform = (): Platform => {
|
|||
platform: "desktop",
|
||||
os,
|
||||
version: pkg.version,
|
||||
windowID: windowState.id,
|
||||
|
||||
async openDirectoryPickerDialog(opts) {
|
||||
return window.api.openDirectoryPicker({
|
||||
|
|
@ -282,8 +315,16 @@ window.api.onMenuCommand((id) => {
|
|||
})
|
||||
listenForDeepLinks()
|
||||
|
||||
render(() => {
|
||||
const platform = createPlatform()
|
||||
function LoadingSplash() {
|
||||
return (
|
||||
<div class="h-dvh w-screen flex flex-col items-center justify-center bg-background-base">
|
||||
<Splash class="w-16 h-20 opacity-50 animate-pulse" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function DesktopRoot(props: { windowState: DesktopWindowState }) {
|
||||
const platform = createPlatform(props.windowState)
|
||||
const loadLocale = async () => {
|
||||
const current = await platform.storage?.("opencode.global.dat").getItem("language")
|
||||
const legacy = current ? undefined : await platform.storage?.().getItem("language.v1")
|
||||
|
|
@ -303,6 +344,9 @@ render(() => {
|
|||
|
||||
const [defaultServer] = createResource(() => platform.getDefaultServer?.())
|
||||
const [locale] = createResource(loadLocale)
|
||||
const router = (props: BaseRouterProps) => (
|
||||
<DesktopMemoryRouter {...props} windowID={platform.windowID ?? "browser"} />
|
||||
)
|
||||
|
||||
function handleClick(e: MouseEvent) {
|
||||
const link = (e.target as HTMLElement).closest("a.external-link") as HTMLAnchorElement | null
|
||||
|
|
@ -332,12 +376,6 @@ render(() => {
|
|||
|
||||
function App() {
|
||||
const wslServers = useWslServers()
|
||||
const splash = (
|
||||
<div class="h-dvh w-screen flex flex-col items-center justify-center bg-background-base">
|
||||
<Splash class="w-16 h-20 opacity-50 animate-pulse" />
|
||||
</div>
|
||||
)
|
||||
|
||||
const ready = createMemo(
|
||||
() => !defaultServer.loading && !sidecar.loading && !windowCount.loading && !locale.loading,
|
||||
)
|
||||
|
|
@ -364,10 +402,10 @@ render(() => {
|
|||
)
|
||||
|
||||
return (
|
||||
<Show when={ready()} fallback={splash}>
|
||||
<Show when={ready()} fallback={<LoadingSplash />}>
|
||||
<Show when={effectiveDefaultServer()} keyed>
|
||||
{(key) => (
|
||||
<AppInterface defaultServer={key} servers={servers()} router={MemoryRouter}>
|
||||
<AppInterface defaultServer={key} servers={servers()} router={router}>
|
||||
<Inner />
|
||||
</AppInterface>
|
||||
)}
|
||||
|
|
@ -390,4 +428,19 @@ render(() => {
|
|||
</AppBaseProviders>
|
||||
</PlatformProvider>
|
||||
)
|
||||
}
|
||||
|
||||
render(() => {
|
||||
const [windowState] = createResource(async () => {
|
||||
const api = window.api as typeof window.api & {
|
||||
getWindowID?: () => Promise<string>
|
||||
}
|
||||
return { id: await api.getWindowID?.() }
|
||||
})
|
||||
|
||||
return (
|
||||
<Show when={windowState.latest} fallback={<LoadingSplash />} keyed>
|
||||
{(state) => <DesktopRoot windowState={state} />}
|
||||
</Show>
|
||||
)
|
||||
}, root!)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue