app.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import "@/index.css"
  2. import { ErrorBoundary, Show, lazy, type ParentProps } from "solid-js"
  3. import { Router, Route, Navigate } from "@solidjs/router"
  4. import { MetaProvider } from "@solidjs/meta"
  5. import { Font } from "@opencode-ai/ui/font"
  6. import { MarkedProvider } from "@opencode-ai/ui/context/marked"
  7. import { DiffComponentProvider } from "@opencode-ai/ui/context/diff"
  8. import { CodeComponentProvider } from "@opencode-ai/ui/context/code"
  9. import { Diff } from "@opencode-ai/ui/diff"
  10. import { Code } from "@opencode-ai/ui/code"
  11. import { ThemeProvider } from "@opencode-ai/ui/theme"
  12. import { GlobalSyncProvider } from "@/context/global-sync"
  13. import { PermissionProvider } from "@/context/permission"
  14. import { LayoutProvider } from "@/context/layout"
  15. import { GlobalSDKProvider } from "@/context/global-sdk"
  16. import { ServerProvider, useServer } from "@/context/server"
  17. import { TerminalProvider } from "@/context/terminal"
  18. import { PromptProvider } from "@/context/prompt"
  19. import { FileProvider } from "@/context/file"
  20. import { NotificationProvider } from "@/context/notification"
  21. import { DialogProvider } from "@opencode-ai/ui/context/dialog"
  22. import { CommandProvider } from "@/context/command"
  23. import { Logo } from "@opencode-ai/ui/logo"
  24. import Layout from "@/pages/layout"
  25. import DirectoryLayout from "@/pages/directory-layout"
  26. import { ErrorPage } from "./pages/error"
  27. import { iife } from "@opencode-ai/util/iife"
  28. import { Suspense } from "solid-js"
  29. const Home = lazy(() => import("@/pages/home"))
  30. const Session = lazy(() => import("@/pages/session"))
  31. const Loading = () => <div class="size-full flex items-center justify-center text-text-weak">Loading...</div>
  32. declare global {
  33. interface Window {
  34. __OPENCODE__?: { updaterEnabled?: boolean; serverPassword?: string }
  35. }
  36. }
  37. export function AppBaseProviders(props: ParentProps) {
  38. return (
  39. <MetaProvider>
  40. <Font />
  41. <ThemeProvider>
  42. <ErrorBoundary fallback={(error) => <ErrorPage error={error} />}>
  43. <DialogProvider>
  44. <MarkedProvider>
  45. <DiffComponentProvider component={Diff}>
  46. <CodeComponentProvider component={Code}>{props.children}</CodeComponentProvider>
  47. </DiffComponentProvider>
  48. </MarkedProvider>
  49. </DialogProvider>
  50. </ErrorBoundary>
  51. </ThemeProvider>
  52. </MetaProvider>
  53. )
  54. }
  55. function ServerKey(props: ParentProps) {
  56. const server = useServer()
  57. return (
  58. <Show when={server.url} keyed>
  59. {props.children}
  60. </Show>
  61. )
  62. }
  63. export function AppInterface(props: { defaultUrl?: string }) {
  64. const defaultServerUrl = () => {
  65. if (props.defaultUrl) return props.defaultUrl
  66. if (location.hostname.includes("opencode.ai")) return "http://localhost:4096"
  67. if (import.meta.env.DEV)
  68. return `http://${import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "localhost"}:${import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"}`
  69. return window.location.origin
  70. }
  71. return (
  72. <ServerProvider defaultUrl={defaultServerUrl()}>
  73. <ServerKey>
  74. <GlobalSDKProvider>
  75. <GlobalSyncProvider>
  76. <Router
  77. root={(props) => (
  78. <PermissionProvider>
  79. <LayoutProvider>
  80. <NotificationProvider>
  81. <CommandProvider>
  82. <Layout>{props.children}</Layout>
  83. </CommandProvider>
  84. </NotificationProvider>
  85. </LayoutProvider>
  86. </PermissionProvider>
  87. )}
  88. >
  89. <Route
  90. path="/"
  91. component={() => (
  92. <Suspense fallback={<Loading />}>
  93. <Home />
  94. </Suspense>
  95. )}
  96. />
  97. <Route path="/:dir" component={DirectoryLayout}>
  98. <Route path="/" component={() => <Navigate href="session" />} />
  99. <Route
  100. path="/session/:id?"
  101. component={() => (
  102. <TerminalProvider>
  103. <FileProvider>
  104. <PromptProvider>
  105. <Suspense fallback={<Loading />}>
  106. <Session />
  107. </Suspense>
  108. </PromptProvider>
  109. </FileProvider>
  110. </TerminalProvider>
  111. )}
  112. />
  113. </Route>
  114. </Router>
  115. </GlobalSyncProvider>
  116. </GlobalSDKProvider>
  117. </ServerKey>
  118. </ServerProvider>
  119. )
  120. }