settings.tsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import { createStore, reconcile } from "solid-js/store"
  2. import { createEffect, createMemo } from "solid-js"
  3. import { createSimpleContext } from "@opencode-ai/ui/context"
  4. import { persisted } from "@/utils/persist"
  5. export interface NotificationSettings {
  6. agent: boolean
  7. permissions: boolean
  8. errors: boolean
  9. }
  10. export interface SoundSettings {
  11. agent: string
  12. permissions: string
  13. errors: string
  14. }
  15. export interface Settings {
  16. general: {
  17. autoSave: boolean
  18. }
  19. appearance: {
  20. fontSize: number
  21. font: string
  22. }
  23. keybinds: Record<string, string>
  24. permissions: {
  25. autoApprove: boolean
  26. }
  27. notifications: NotificationSettings
  28. sounds: SoundSettings
  29. }
  30. const defaultSettings: Settings = {
  31. general: {
  32. autoSave: true,
  33. },
  34. appearance: {
  35. fontSize: 14,
  36. font: "ibm-plex-mono",
  37. },
  38. keybinds: {},
  39. permissions: {
  40. autoApprove: false,
  41. },
  42. notifications: {
  43. agent: true,
  44. permissions: true,
  45. errors: false,
  46. },
  47. sounds: {
  48. agent: "staplebops-01",
  49. permissions: "staplebops-02",
  50. errors: "nope-03",
  51. },
  52. }
  53. const monoFallback =
  54. 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace'
  55. const monoFonts: Record<string, string> = {
  56. "ibm-plex-mono": `"IBM Plex Mono", "IBM Plex Mono Fallback", ${monoFallback}`,
  57. "cascadia-code": `"Cascadia Code Nerd Font", "Cascadia Code NF", "Cascadia Mono NF", "IBM Plex Mono", "IBM Plex Mono Fallback", ${monoFallback}`,
  58. "fira-code": `"Fira Code Nerd Font", "FiraMono Nerd Font", "FiraMono Nerd Font Mono", "IBM Plex Mono", "IBM Plex Mono Fallback", ${monoFallback}`,
  59. hack: `"Hack Nerd Font", "Hack Nerd Font Mono", "IBM Plex Mono", "IBM Plex Mono Fallback", ${monoFallback}`,
  60. inconsolata: `"Inconsolata Nerd Font", "Inconsolata Nerd Font Mono","IBM Plex Mono", "IBM Plex Mono Fallback", ${monoFallback}`,
  61. "intel-one-mono": `"Intel One Mono Nerd Font", "IntoneMono Nerd Font", "IntoneMono Nerd Font Mono", "IBM Plex Mono", "IBM Plex Mono Fallback", ${monoFallback}`,
  62. iosevka: `"Iosevka Nerd Font", "Iosevka Nerd Font Mono", "IBM Plex Mono", "IBM Plex Mono Fallback", ${monoFallback}`,
  63. "jetbrains-mono": `"JetBrains Mono Nerd Font", "JetBrainsMono Nerd Font Mono", "JetBrainsMonoNL Nerd Font", "JetBrainsMonoNL Nerd Font Mono", "IBM Plex Mono", "IBM Plex Mono Fallback", ${monoFallback}`,
  64. "meslo-lgs": `"Meslo LGS Nerd Font", "MesloLGS Nerd Font", "MesloLGM Nerd Font", "IBM Plex Mono", "IBM Plex Mono Fallback", ${monoFallback}`,
  65. "roboto-mono": `"Roboto Mono Nerd Font", "RobotoMono Nerd Font", "RobotoMono Nerd Font Mono", "IBM Plex Mono", "IBM Plex Mono Fallback", ${monoFallback}`,
  66. "source-code-pro": `"Source Code Pro Nerd Font", "SauceCodePro Nerd Font", "SauceCodePro Nerd Font Mono", "IBM Plex Mono", "IBM Plex Mono Fallback", ${monoFallback}`,
  67. "ubuntu-mono": `"Ubuntu Mono Nerd Font", "UbuntuMono Nerd Font", "UbuntuMono Nerd Font Mono", "IBM Plex Mono", "IBM Plex Mono Fallback", ${monoFallback}`,
  68. }
  69. export function monoFontFamily(font: string | undefined) {
  70. return monoFonts[font ?? defaultSettings.appearance.font] ?? monoFonts[defaultSettings.appearance.font]
  71. }
  72. export const { use: useSettings, provider: SettingsProvider } = createSimpleContext({
  73. name: "Settings",
  74. init: () => {
  75. const [store, setStore, _, ready] = persisted("settings.v3", createStore<Settings>(defaultSettings))
  76. createEffect(() => {
  77. if (typeof document === "undefined") return
  78. document.documentElement.style.setProperty("--font-family-mono", monoFontFamily(store.appearance?.font))
  79. })
  80. return {
  81. ready,
  82. get current() {
  83. return store
  84. },
  85. general: {
  86. autoSave: createMemo(() => store.general?.autoSave ?? defaultSettings.general.autoSave),
  87. setAutoSave(value: boolean) {
  88. setStore("general", "autoSave", value)
  89. },
  90. },
  91. appearance: {
  92. fontSize: createMemo(() => store.appearance?.fontSize ?? defaultSettings.appearance.fontSize),
  93. setFontSize(value: number) {
  94. setStore("appearance", "fontSize", value)
  95. },
  96. font: createMemo(() => store.appearance?.font ?? defaultSettings.appearance.font),
  97. setFont(value: string) {
  98. setStore("appearance", "font", value)
  99. },
  100. },
  101. keybinds: {
  102. get: (action: string) => store.keybinds?.[action],
  103. set(action: string, keybind: string) {
  104. setStore("keybinds", action, keybind)
  105. },
  106. reset(action: string) {
  107. setStore("keybinds", action, undefined!)
  108. },
  109. resetAll() {
  110. setStore("keybinds", reconcile({}))
  111. },
  112. },
  113. permissions: {
  114. autoApprove: createMemo(() => store.permissions?.autoApprove ?? defaultSettings.permissions.autoApprove),
  115. setAutoApprove(value: boolean) {
  116. setStore("permissions", "autoApprove", value)
  117. },
  118. },
  119. notifications: {
  120. agent: createMemo(() => store.notifications?.agent ?? defaultSettings.notifications.agent),
  121. setAgent(value: boolean) {
  122. setStore("notifications", "agent", value)
  123. },
  124. permissions: createMemo(() => store.notifications?.permissions ?? defaultSettings.notifications.permissions),
  125. setPermissions(value: boolean) {
  126. setStore("notifications", "permissions", value)
  127. },
  128. errors: createMemo(() => store.notifications?.errors ?? defaultSettings.notifications.errors),
  129. setErrors(value: boolean) {
  130. setStore("notifications", "errors", value)
  131. },
  132. },
  133. sounds: {
  134. agent: createMemo(() => store.sounds?.agent ?? defaultSettings.sounds.agent),
  135. setAgent(value: string) {
  136. setStore("sounds", "agent", value)
  137. },
  138. permissions: createMemo(() => store.sounds?.permissions ?? defaultSettings.sounds.permissions),
  139. setPermissions(value: string) {
  140. setStore("sounds", "permissions", value)
  141. },
  142. errors: createMemo(() => store.sounds?.errors ?? defaultSettings.sounds.errors),
  143. setErrors(value: string) {
  144. setStore("sounds", "errors", value)
  145. },
  146. },
  147. }
  148. },
  149. })