summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/components
diff options
context:
space:
mode:
authoradamelmore <[email protected]>2026-01-27 08:30:23 -0600
committeradamelmore <[email protected]>2026-01-27 11:38:35 -0600
commit2f5a238b511e3ac4d8235da4d6e7fdbaf06c9b84 (patch)
tree1bcbd4d51758721d6cbcc3d36e97c6a76ceef5c9 /packages/app/src/components
parent173faca3c6a8d29e4502fbedaa7a56cdddd05c10 (diff)
downloadopencode-2f5a238b511e3ac4d8235da4d6e7fdbaf06c9b84.tar.gz
opencode-2f5a238b511e3ac4d8235da4d6e7fdbaf06c9b84.zip
feat(app): update settings in general settings
Diffstat (limited to 'packages/app/src/components')
-rw-r--r--packages/app/src/components/settings-general.tsx124
1 files changed, 107 insertions, 17 deletions
diff --git a/packages/app/src/components/settings-general.tsx b/packages/app/src/components/settings-general.tsx
index 57efcfdfa..180a99c73 100644
--- a/packages/app/src/components/settings-general.tsx
+++ b/packages/app/src/components/settings-general.tsx
@@ -1,8 +1,12 @@
import { Component, createMemo, type JSX } from "solid-js"
+import { createStore } from "solid-js/store"
+import { Button } from "@opencode-ai/ui/button"
import { Select } from "@opencode-ai/ui/select"
import { Switch } from "@opencode-ai/ui/switch"
import { useTheme, type ColorScheme } from "@opencode-ai/ui/theme"
+import { showToast } from "@opencode-ai/ui/toast"
import { useLanguage } from "@/context/language"
+import { usePlatform } from "@/context/platform"
import { useSettings, monoFontFamily } from "@/context/settings"
import { playSound, SOUND_OPTIONS } from "@/utils/sound"
import { Link } from "./link"
@@ -29,8 +33,67 @@ const playDemoSound = (src: string) => {
export const SettingsGeneral: Component = () => {
const theme = useTheme()
const language = useLanguage()
+ const platform = usePlatform()
const settings = useSettings()
+ const [store, setStore] = createStore({
+ checking: false,
+ })
+
+ const check = () => {
+ if (!platform.checkUpdate) return
+ setStore("checking", true)
+
+ void platform
+ .checkUpdate()
+ .then((result) => {
+ if (!result.updateAvailable) {
+ showToast({
+ variant: "success",
+ icon: "circle-check",
+ title: language.t("settings.updates.toast.latest.title"),
+ description: language.t("settings.updates.toast.latest.description", { version: platform.version ?? "" }),
+ })
+ return
+ }
+
+ const actions =
+ platform.update && platform.restart
+ ? [
+ {
+ label: language.t("toast.update.action.installRestart"),
+ onClick: async () => {
+ await platform.update!()
+ await platform.restart!()
+ },
+ },
+ {
+ label: language.t("toast.update.action.notYet"),
+ onClick: "dismiss" as const,
+ },
+ ]
+ : [
+ {
+ label: language.t("toast.update.action.notYet"),
+ onClick: "dismiss" as const,
+ },
+ ]
+
+ showToast({
+ persistent: true,
+ icon: "download",
+ title: language.t("toast.update.title"),
+ description: language.t("toast.update.description", { version: result.version ?? "" }),
+ actions,
+ })
+ })
+ .catch((err: unknown) => {
+ const message = err instanceof Error ? err.message : String(err)
+ showToast({ title: language.t("common.requestFailed"), description: message })
+ })
+ .finally(() => setStore("checking", false))
+ }
+
const themeOptions = createMemo(() =>
Object.entries(theme.themes()).map(([id, def]) => ({ id, name: def.name ?? id })),
)
@@ -208,23 +271,6 @@ export const SettingsGeneral: Component = () => {
</div>
</div>
- {/* Updates Section */}
- <div class="flex flex-col gap-1">
- <h3 class="text-14-medium text-text-strong pb-2">{language.t("settings.general.section.updates")}</h3>
-
- <div class="bg-surface-raised-base px-4 rounded-lg">
- <SettingsRow
- title={language.t("settings.general.row.releaseNotes.title")}
- description={language.t("settings.general.row.releaseNotes.description")}
- >
- <Switch
- checked={settings.general.releaseNotes()}
- onChange={(checked) => settings.general.setReleaseNotes(checked)}
- />
- </SettingsRow>
- </div>
- </div>
-
{/* Sound effects Section */}
<div class="flex flex-col gap-1">
<h3 class="text-14-medium text-text-strong pb-2">{language.t("settings.general.section.sounds")}</h3>
@@ -303,6 +349,50 @@ export const SettingsGeneral: Component = () => {
</SettingsRow>
</div>
</div>
+
+ {/* Updates Section */}
+ <div class="flex flex-col gap-1">
+ <h3 class="text-14-medium text-text-strong pb-2">{language.t("settings.general.section.updates")}</h3>
+
+ <div class="bg-surface-raised-base px-4 rounded-lg">
+ <SettingsRow
+ title={language.t("settings.updates.row.startup.title")}
+ description={language.t("settings.updates.row.startup.description")}
+ >
+ <Switch
+ checked={settings.updates.startup()}
+ disabled={!platform.checkUpdate}
+ onChange={(checked) => settings.updates.setStartup(checked)}
+ />
+ </SettingsRow>
+
+ <SettingsRow
+ title={language.t("settings.general.row.releaseNotes.title")}
+ description={language.t("settings.general.row.releaseNotes.description")}
+ >
+ <Switch
+ checked={settings.general.releaseNotes()}
+ onChange={(checked) => settings.general.setReleaseNotes(checked)}
+ />
+ </SettingsRow>
+
+ <SettingsRow
+ title={language.t("settings.updates.row.check.title")}
+ description={language.t("settings.updates.row.check.description")}
+ >
+ <Button
+ size="small"
+ variant="secondary"
+ disabled={store.checking || !platform.checkUpdate}
+ onClick={check}
+ >
+ {store.checking
+ ? language.t("settings.updates.action.checking")
+ : language.t("settings.updates.action.checkNow")}
+ </Button>
+ </SettingsRow>
+ </div>
+ </div>
</div>
</div>
)