entry.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // @refresh reload
  2. import { render } from "solid-js/web"
  3. import { AppBaseProviders, AppInterface } from "@/app"
  4. import { Platform, PlatformProvider } from "@/context/platform"
  5. import { dict as en } from "@/i18n/en"
  6. import { dict as zh } from "@/i18n/zh"
  7. import pkg from "../package.json"
  8. const DEFAULT_SERVER_URL_KEY = "opencode.settings.dat:defaultServerUrl"
  9. const root = document.getElementById("root")
  10. if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
  11. const locale = (() => {
  12. if (typeof navigator !== "object") return "en" as const
  13. const languages = navigator.languages?.length ? navigator.languages : [navigator.language]
  14. for (const language of languages) {
  15. if (!language) continue
  16. if (language.toLowerCase().startsWith("zh")) return "zh" as const
  17. }
  18. return "en" as const
  19. })()
  20. const key = "error.dev.rootNotFound" as const
  21. const message = locale === "zh" ? (zh[key] ?? en[key]) : en[key]
  22. throw new Error(message)
  23. }
  24. const platform: Platform = {
  25. platform: "web",
  26. version: pkg.version,
  27. openLink(url: string) {
  28. window.open(url, "_blank")
  29. },
  30. back() {
  31. window.history.back()
  32. },
  33. forward() {
  34. window.history.forward()
  35. },
  36. restart: async () => {
  37. window.location.reload()
  38. },
  39. notify: async (title, description, href) => {
  40. if (!("Notification" in window)) return
  41. const permission =
  42. Notification.permission === "default"
  43. ? await Notification.requestPermission().catch(() => "denied")
  44. : Notification.permission
  45. if (permission !== "granted") return
  46. const inView = document.visibilityState === "visible" && document.hasFocus()
  47. if (inView) return
  48. await Promise.resolve()
  49. .then(() => {
  50. const notification = new Notification(title, {
  51. body: description ?? "",
  52. icon: "https://opencode.ai/favicon-96x96-v3.png",
  53. })
  54. notification.onclick = () => {
  55. window.focus()
  56. if (href) {
  57. window.history.pushState(null, "", href)
  58. window.dispatchEvent(new PopStateEvent("popstate"))
  59. }
  60. notification.close()
  61. }
  62. })
  63. .catch(() => undefined)
  64. },
  65. getDefaultServerUrl: () => {
  66. if (typeof localStorage === "undefined") return null
  67. try {
  68. return localStorage.getItem(DEFAULT_SERVER_URL_KEY)
  69. } catch {
  70. return null
  71. }
  72. },
  73. setDefaultServerUrl: (url) => {
  74. if (typeof localStorage === "undefined") return
  75. try {
  76. if (url) {
  77. localStorage.setItem(DEFAULT_SERVER_URL_KEY, url)
  78. return
  79. }
  80. localStorage.removeItem(DEFAULT_SERVER_URL_KEY)
  81. } catch {
  82. return
  83. }
  84. },
  85. }
  86. render(
  87. () => (
  88. <PlatformProvider value={platform}>
  89. <AppBaseProviders>
  90. <AppInterface />
  91. </AppBaseProviders>
  92. </PlatformProvider>
  93. ),
  94. root!,
  95. )