platform.tsx 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import { createSimpleContext } from "@opencode-ai/ui/context"
  2. import type { AsyncStorage, SyncStorage } from "@solid-primitives/storage"
  3. import type { Accessor } from "solid-js"
  4. import type { DesktopMenuAction } from "../desktop-menu"
  5. import { ServerConnection } from "./server"
  6. import type { WslServersPlatform } from "../wsl/types"
  7. import type { UpdaterPlatform } from "../updater"
  8. type PickerPaths = string | string[] | null
  9. type OpenDirectoryPickerOptions = { title?: string; multiple?: boolean }
  10. type OpenAttachmentPickerOptions = {
  11. title?: string
  12. multiple?: boolean
  13. accept?: string[]
  14. extensions?: string[]
  15. defaultPath?: string
  16. }
  17. type SaveFilePickerOptions = { title?: string; defaultPath?: string }
  18. type PlatformName = "web" | "desktop"
  19. type DesktopOS = "macos" | "windows" | "linux"
  20. export type FatalRendererErrorLog = {
  21. error: string
  22. url: string
  23. version?: string
  24. platform: PlatformName
  25. os?: DesktopOS
  26. }
  27. type PlatformBase = {
  28. /** App version */
  29. version?: string
  30. /** Open a URL in the default browser */
  31. openLink(url: string): void
  32. /** Open a local path in a local app (desktop only) */
  33. openPath?(path: string, app?: string): Promise<void>
  34. /** Restart the app */
  35. restart(): Promise<void>
  36. /** Navigate back in history */
  37. back(): void
  38. /** Navigate forward in history */
  39. forward(): void
  40. /** Send a system notification (optional deep link) */
  41. notify(title: string, description?: string, href?: string): Promise<void>
  42. /** Open a native attachment picker and read selected files sequentially (desktop only) */
  43. openAttachmentPickerDialog?(
  44. opts: OpenAttachmentPickerOptions,
  45. onFile: (file: File) => Promise<unknown>,
  46. ): Promise<void>
  47. /** Resolve the native source path for a desktop File. */
  48. getPathForFile?(file: File): string
  49. /** Open a native save file picker dialog (desktop only) */
  50. saveFilePickerDialog?(opts?: SaveFilePickerOptions): Promise<string | null>
  51. /** Storage mechanism, defaults to localStorage */
  52. storage?: (name?: string) => SyncStorage | AsyncStorage
  53. /** Stable platform window identity for window-scoped persistence */
  54. windowID?: string
  55. /** Application-global desktop updater */
  56. updater?: UpdaterPlatform
  57. /** Fetch override */
  58. fetch?: typeof fetch
  59. /** Get the configured default server URL (platform-specific) */
  60. getDefaultServer?(): Promise<ServerConnection.Key | null>
  61. /** Set the default server URL to use on app startup (platform-specific) */
  62. setDefaultServer?(url: ServerConnection.Key | null): Promise<void> | void
  63. /** Manage WSL sidecar servers (Electron on Windows only) */
  64. wslServers?: WslServersPlatform
  65. /** Get the preferred display backend (desktop only) */
  66. getDisplayBackend?(): Promise<DisplayBackend | null> | DisplayBackend | null
  67. /** Set the preferred display backend (desktop only) */
  68. setDisplayBackend?(backend: DisplayBackend): Promise<void>
  69. /** Parse markdown to HTML using native parser (desktop only, returns unprocessed code blocks) */
  70. parseMarkdown?(markdown: string): Promise<string>
  71. /** Webview zoom level (desktop only) */
  72. webviewZoom?: Accessor<number>
  73. /** Get whether native pinch/Ctrl-scroll zoom gestures are enabled (desktop only) */
  74. getPinchZoomEnabled?(): Promise<boolean> | boolean
  75. /** Allow native pinch/Ctrl-scroll zoom gestures (desktop only) */
  76. setPinchZoomEnabled?(enabled: boolean): Promise<void> | void
  77. /** Run a desktop-only menu action from the app chrome */
  78. runDesktopMenuAction?(action: DesktopMenuAction): Promise<void> | void
  79. /** Check if an editor app exists (desktop only) */
  80. checkAppExists?(appName: string): Promise<boolean>
  81. /** Read image from clipboard (desktop only) */
  82. readClipboardImage?(): Promise<File | null>
  83. /** Export collected diagnostic logs (desktop only) */
  84. exportDebugLogs?(): Promise<string>
  85. /** Record a fatal renderer error in platform logs (desktop only) */
  86. recordFatalRendererError?(error: FatalRendererErrorLog): Promise<void>
  87. }
  88. export type Platform = PlatformBase &
  89. (
  90. | { platform: "web"; os?: never }
  91. | {
  92. platform: "desktop"
  93. os?: DesktopOS
  94. openDirectoryPickerDialog(opts?: OpenDirectoryPickerOptions): Promise<PickerPaths>
  95. }
  96. )
  97. export type DisplayBackend = "auto" | "wayland"
  98. export const { use: usePlatform, provider: PlatformProvider } = createSimpleContext({
  99. name: "Platform",
  100. init: (props: { value: Platform }) => {
  101. return props.value
  102. },
  103. })