summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdam <[email protected]>2025-12-09 06:12:04 -0600
committerAdam <[email protected]>2025-12-09 06:12:09 -0600
commit20662e21014216dfb42690d52b900d43666892fc (patch)
tree8dd9f9e8088b5a44d02533728a1a218efdb1ba92
parent0a357be160d672791bb99a36fc7d7c1299d5493d (diff)
downloadopencode-20662e21014216dfb42690d52b900d43666892fc.tar.gz
opencode-20662e21014216dfb42690d52b900d43666892fc.zip
wip(desktop): progress
-rw-r--r--packages/desktop/src/PlatformContext.tsx14
-rw-r--r--packages/desktop/src/app.tsx (renamed from packages/desktop/src/DesktopInterface.tsx)2
-rw-r--r--packages/desktop/src/context/platform.tsx25
-rw-r--r--packages/desktop/src/entry.tsx13
-rw-r--r--packages/desktop/src/index.ts4
-rw-r--r--packages/desktop/src/pages/layout.tsx2
-rw-r--r--packages/tauri/src/index.tsx40
7 files changed, 75 insertions, 25 deletions
diff --git a/packages/desktop/src/PlatformContext.tsx b/packages/desktop/src/PlatformContext.tsx
deleted file mode 100644
index 5b510a8d4..000000000
--- a/packages/desktop/src/PlatformContext.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { createContext } from "solid-js"
-import { useContext } from "solid-js"
-
-export interface Platform {}
-
-const PlatformContext = createContext<Platform>()
-
-export const PlatformProvider = PlatformContext.Provider
-
-export function usePlatform() {
- const ctx = useContext(PlatformContext)
- if (!ctx) throw new Error("usePlatform must be used within a PlatformProvider")
- return ctx
-}
diff --git a/packages/desktop/src/DesktopInterface.tsx b/packages/desktop/src/app.tsx
index 31d52863d..0ca4d5e6b 100644
--- a/packages/desktop/src/DesktopInterface.tsx
+++ b/packages/desktop/src/app.tsx
@@ -24,7 +24,7 @@ const url =
? `http://${host}:${port}`
: "/")
-export function DesktopInterface() {
+export function App() {
return (
<MarkedProvider>
<DiffComponentProvider component={Diff}>
diff --git a/packages/desktop/src/context/platform.tsx b/packages/desktop/src/context/platform.tsx
new file mode 100644
index 000000000..21be49cbd
--- /dev/null
+++ b/packages/desktop/src/context/platform.tsx
@@ -0,0 +1,25 @@
+import { createSimpleContext } from "@opencode-ai/ui/context"
+
+export type Platform = {
+ /** Platform discriminator */
+ platform: "web" | "tauri"
+
+ /** Open native directory picker dialog (Tauri only) */
+ openDirectoryPickerDialog?(opts?: { title?: string; multiple?: boolean }): Promise<string | string[] | null>
+
+ /** Open native file picker dialog (Tauri only) */
+ openFilePickerDialog?(opts?: { title?: string; multiple?: boolean }): Promise<string | string[] | null>
+
+ /** Save file picker dialog (Tauri only) */
+ saveFilePickerDialog?(opts?: { title?: string; defaultPath?: string }): Promise<string | null>
+
+ /** Open a URL in the default browser */
+ openLink(url: string): void
+}
+
+export const { use: usePlatform, provider: PlatformProvider } = createSimpleContext({
+ name: "Platform",
+ init: (props: { value: Platform }) => {
+ return props.value
+ },
+})
diff --git a/packages/desktop/src/entry.tsx b/packages/desktop/src/entry.tsx
index 82c5dd331..eec6396e9 100644
--- a/packages/desktop/src/entry.tsx
+++ b/packages/desktop/src/entry.tsx
@@ -1,7 +1,7 @@
// @refresh reload
import { render } from "solid-js/web"
-import { DesktopInterface } from "@/DesktopInterface"
-import { Platform, PlatformProvider } from "@/PlatformContext"
+import { App } from "@/app"
+import { Platform, PlatformProvider } from "@/context/platform"
const root = document.getElementById("root")
if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
@@ -10,12 +10,17 @@ if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
)
}
-const platform: Platform = {}
+const platform: Platform = {
+ platform: "web",
+ openLink(url: string) {
+ window.open(url, "_blank")
+ },
+}
render(
() => (
<PlatformProvider value={platform}>
- <DesktopInterface />
+ <App />
</PlatformProvider>
),
root!,
diff --git a/packages/desktop/src/index.ts b/packages/desktop/src/index.ts
index 2142e4886..cf5be9f51 100644
--- a/packages/desktop/src/index.ts
+++ b/packages/desktop/src/index.ts
@@ -1,2 +1,2 @@
-export { PlatformProvider, type Platform } from "./PlatformContext"
-export { DesktopInterface } from "./DesktopInterface"
+export { PlatformProvider, type Platform } from "./context/platform"
+export { App } from "./app"
diff --git a/packages/desktop/src/pages/layout.tsx b/packages/desktop/src/pages/layout.tsx
index 03eeedfb1..25e3aafb6 100644
--- a/packages/desktop/src/pages/layout.tsx
+++ b/packages/desktop/src/pages/layout.tsx
@@ -196,7 +196,7 @@ export default function Layout(props: ParentProps) {
return (
<Switch>
<Match when={layout.sidebar.opened()}>
- <Collapsible variant="ghost" defaultOpen class="gap-2">
+ <Collapsible variant="ghost" defaultOpen>
<Button
as={"div"}
variant="ghost"
diff --git a/packages/tauri/src/index.tsx b/packages/tauri/src/index.tsx
index 61b67d264..6b9ce88e0 100644
--- a/packages/tauri/src/index.tsx
+++ b/packages/tauri/src/index.tsx
@@ -1,8 +1,10 @@
// @refresh reload
import { render } from "solid-js/web"
-import { DesktopInterface, PlatformProvider, Platform } from "@opencode-ai/desktop"
+import { App, PlatformProvider, Platform } from "@opencode-ai/desktop"
import { runUpdater } from "./updater"
import { onMount } from "solid-js"
+import { open, save } from "@tauri-apps/plugin-dialog"
+import { open as shellOpen } from "@tauri-apps/plugin-shell"
const root = document.getElementById("root")
if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
@@ -11,7 +13,39 @@ if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
)
}
-const platform: Platform = {}
+const platform: Platform = {
+ platform: "tauri",
+
+ async openDirectoryPickerDialog(opts) {
+ const result = await open({
+ directory: true,
+ multiple: opts?.multiple ?? false,
+ title: opts?.title ?? "Choose a folder",
+ })
+ return result
+ },
+
+ async openFilePickerDialog(opts) {
+ const result = await open({
+ directory: false,
+ multiple: opts?.multiple ?? false,
+ title: opts?.title ?? "Choose a file",
+ })
+ return result
+ },
+
+ async saveFilePickerDialog(opts) {
+ const result = await save({
+ title: opts?.title ?? "Save file",
+ defaultPath: opts?.defaultPath,
+ })
+ return result
+ },
+
+ openLink(url: string) {
+ shellOpen(url)
+ },
+}
declare global {
interface Window {
@@ -26,7 +60,7 @@ render(() => {
return (
<PlatformProvider value={platform}>
- <DesktopInterface />
+ <App />
</PlatformProvider>
)
}, root!)