Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions packages/app/src/components/settings-general.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, createMemo, type JSX } from "solid-js"
import { Component, createMemo, Show, 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"
Expand Down Expand Up @@ -410,6 +410,27 @@ export const SettingsGeneral: Component = () => {
</SettingsRow>
</div>
</div>

{/* Desktop Section - Desktop only */}
<Show when={platform.platform === "desktop"}>
<div class="flex flex-col gap-1">
<h3 class="text-14-medium text-text-strong pb-2">{language.t("settings.general.section.desktop")}</h3>

<div class="bg-surface-raised-base px-4 rounded-lg">
<SettingsRow
title={language.t("settings.general.desktop.openLinksExternally.title")}
description={language.t("settings.general.desktop.openLinksExternally.description")}
>
<div data-action="settings-open-links-externally">
<Switch
checked={settings.browser.openLinksExternally()}
onChange={(checked) => settings.browser.setOpenLinksExternally(checked)}
/>
</div>
</SettingsRow>
</div>
</div>
</Show>
</div>
</div>
)
Expand All @@ -423,8 +444,8 @@ interface SettingsRowProps {

const SettingsRow: Component<SettingsRowProps> = (props) => {
return (
<div class="flex flex-wrap items-center justify-between gap-4 py-3 border-b border-border-weak-base last:border-none">
<div class="flex flex-col gap-0.5 min-w-0">
<div class="flex items-center justify-between gap-4 py-3 border-b border-border-weak-base last:border-none">
<div class="flex flex-col gap-0.5 min-w-0 flex-1">
<span class="text-14-medium text-text-strong">{props.title}</span>
<span class="text-12-regular text-text-weak">{props.description}</span>
</div>
Expand Down
16 changes: 16 additions & 0 deletions packages/app/src/context/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export interface SoundSettings {
errors: string
}

export interface BrowserSettings {
openLinksExternally: boolean
}

export interface Settings {
general: {
autoSave: boolean
Expand All @@ -33,6 +37,7 @@ export interface Settings {
}
notifications: NotificationSettings
sounds: SoundSettings
browser: BrowserSettings
}

const defaultSettings: Settings = {
Expand Down Expand Up @@ -61,6 +66,9 @@ const defaultSettings: Settings = {
permissions: "staplebops-02",
errors: "nope-03",
},
browser: {
openLinksExternally: true,
},
}

const monoFallback =
Expand Down Expand Up @@ -172,6 +180,14 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont
setStore("sounds", "errors", value)
},
},
browser: {
openLinksExternally: createMemo(
() => store.browser?.openLinksExternally ?? defaultSettings.browser.openLinksExternally,
),
setOpenLinksExternally(value: boolean) {
setStore("browser", "openLinksExternally", value)
},
},
}
},
})
4 changes: 4 additions & 0 deletions packages/app/src/i18n/ar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,10 @@ export const dict = {
"settings.general.section.notifications": "إشعارات النظام",
"settings.general.section.updates": "التحديثات",
"settings.general.section.sounds": "المؤثرات الصوتية",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "فتح الروابط في متصفح خارجي",
"settings.general.desktop.openLinksExternally.description":
"عند التفعيل، سيتم فتح الروابط في متصفح النظام الافتراضي بدلاً من داخل التطبيق",

"settings.general.row.language.title": "اللغة",
"settings.general.row.language.description": "تغيير لغة العرض لـ OpenCode",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/br.ts
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,10 @@ export const dict = {
"settings.general.section.notifications": "Notificações do sistema",
"settings.general.section.updates": "Atualizações",
"settings.general.section.sounds": "Efeitos sonoros",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "Abrir links no navegador externo",
"settings.general.desktop.openLinksExternally.description":
"Quando ativado, clicar em links os abrirá no navegador padrão do sistema em vez de dentro do app",

"settings.general.row.language.title": "Idioma",
"settings.general.row.language.description": "Alterar o idioma de exibição do OpenCode",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/da.ts
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,10 @@ export const dict = {
"settings.general.section.notifications": "Systemmeddelelser",
"settings.general.section.updates": "Opdateringer",
"settings.general.section.sounds": "Lydeffekter",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "Åbn links i ekstern browser",
"settings.general.desktop.openLinksExternally.description":
"Når aktiveret, åbnes links i din standard systembrowser i stedet for i appen",

"settings.general.row.language.title": "Sprog",
"settings.general.row.language.description": "Ændr visningssproget for OpenCode",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,10 @@ export const dict = {
"settings.general.section.notifications": "Systembenachrichtigungen",
"settings.general.section.updates": "Updates",
"settings.general.section.sounds": "Soundeffekte",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "Links im externen Browser öffnen",
"settings.general.desktop.openLinksExternally.description":
"Wenn aktiviert, werden Links in Ihrem Standard-Systembrowser geöffnet anstatt innerhalb der App",

"settings.general.row.language.title": "Sprache",
"settings.general.row.language.description": "Die Anzeigesprache für OpenCode ändern",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,10 @@ export const dict = {
"settings.general.section.notifications": "System notifications",
"settings.general.section.updates": "Updates",
"settings.general.section.sounds": "Sound effects",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "Open links in external browser",
"settings.general.desktop.openLinksExternally.description":
"When enabled, clicking links will open them in your default system browser instead of within the app",

"settings.general.row.language.title": "Language",
"settings.general.row.language.description": "Change the display language for OpenCode",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,10 @@ export const dict = {
"settings.general.section.notifications": "Notificaciones del sistema",
"settings.general.section.updates": "Actualizaciones",
"settings.general.section.sounds": "Efectos de sonido",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "Abrir enlaces en navegador externo",
"settings.general.desktop.openLinksExternally.description":
"Al activarse, los enlaces se abrirán en el navegador predeterminado del sistema en lugar de dentro de la app",

"settings.general.row.language.title": "Idioma",
"settings.general.row.language.description": "Cambiar el idioma de visualización para OpenCode",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,10 @@ export const dict = {
"settings.general.section.notifications": "Notifications système",
"settings.general.section.updates": "Mises à jour",
"settings.general.section.sounds": "Effets sonores",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "Ouvrir les liens dans un navigateur externe",
"settings.general.desktop.openLinksExternally.description":
"Lorsqu'activé, les liens s'ouvriront dans votre navigateur système par défaut au lieu de l'application",

"settings.general.row.language.title": "Langue",
"settings.general.row.language.description": "Changer la langue d'affichage pour OpenCode",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,10 @@ export const dict = {
"settings.general.section.notifications": "システム通知",
"settings.general.section.updates": "アップデート",
"settings.general.section.sounds": "効果音",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "外部ブラウザでリンクを開く",
"settings.general.desktop.openLinksExternally.description":
"有効にすると、リンクをクリックするとアプリ内ではなくシステムの既定ブラウザで開きます",

"settings.general.row.language.title": "言語",
"settings.general.row.language.description": "OpenCodeの表示言語を変更します",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,10 @@ export const dict = {
"settings.general.section.notifications": "시스템 알림",
"settings.general.section.updates": "업데이트",
"settings.general.section.sounds": "효과음",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "외부 브라우저에서 링크 열기",
"settings.general.desktop.openLinksExternally.description":
"활성화하면 링크를 클릭할 때 앱 내부가 아닌 기본 시스템 브라우저에서 열립니다",

"settings.general.row.language.title": "언어",
"settings.general.row.language.description": "OpenCode 표시 언어 변경",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/no.ts
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,10 @@ export const dict = {
"settings.general.section.notifications": "Systemvarsler",
"settings.general.section.updates": "Oppdateringer",
"settings.general.section.sounds": "Lydeffekter",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "Åpne lenker i ekstern nettleser",
"settings.general.desktop.openLinksExternally.description":
"Når aktivert, åpnes lenker i standard systemnettleseren i stedet for i appen",

"settings.general.row.language.title": "Språk",
"settings.general.row.language.description": "Endre visningsspråket for OpenCode",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,10 @@ export const dict = {
"settings.general.section.notifications": "Powiadomienia systemowe",
"settings.general.section.updates": "Aktualizacje",
"settings.general.section.sounds": "Efekty dźwiękowe",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "Otwieraj linki w zewnętrznej przeglądarce",
"settings.general.desktop.openLinksExternally.description":
"Po włączeniu linki będą otwierane w domyślnej przeglądarce systemowej zamiast w aplikacji",

"settings.general.row.language.title": "Język",
"settings.general.row.language.description": "Zmień język wyświetlania dla OpenCode",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,10 @@ export const dict = {
"settings.general.section.notifications": "Системные уведомления",
"settings.general.section.updates": "Обновления",
"settings.general.section.sounds": "Звуковые эффекты",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "Открывать ссылки во внешнем браузере",
"settings.general.desktop.openLinksExternally.description":
"При включении ссылки будут открываться в системном браузере по умолчанию, а не внутри приложения",

"settings.general.row.language.title": "Язык",
"settings.general.row.language.description": "Изменить язык отображения OpenCode",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/th.ts
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,10 @@ export const dict = {
"settings.general.section.notifications": "การแจ้งเตือนระบบ",
"settings.general.section.updates": "การอัปเดต",
"settings.general.section.sounds": "เสียงเอฟเฟกต์",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "เปิดลิงก์ในเบราว์เซอร์ภายนอก",
"settings.general.desktop.openLinksExternally.description":
"เมื่อเปิดใช้งาน การคลิกลิงก์จะเปิดในเบราว์เซอร์เริ่มต้นของระบบแทนที่จะเปิดในแอป",

"settings.general.row.language.title": "ภาษา",
"settings.general.row.language.description": "เปลี่ยนภาษาที่แสดงสำหรับ OpenCode",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,10 @@ export const dict = {
"settings.general.section.notifications": "系统通知",
"settings.general.section.updates": "更新",
"settings.general.section.sounds": "音效",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "在外部浏览器中打开链接",
"settings.general.desktop.openLinksExternally.description":
"启用后,点击链接将在系统默认浏览器中打开,而不是在应用内打开",

"settings.general.row.language.title": "语言",
"settings.general.row.language.description": "更改 OpenCode 的显示语言",
Expand Down
4 changes: 4 additions & 0 deletions packages/app/src/i18n/zht.ts
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,10 @@ export const dict = {
"settings.general.section.notifications": "系統通知",
"settings.general.section.updates": "更新",
"settings.general.section.sounds": "音效",
"settings.general.section.desktop": "Desktop",
"settings.general.desktop.openLinksExternally.title": "在外部瀏覽器中開啟連結",
"settings.general.desktop.openLinksExternally.description":
"啟用後,點擊連結將在系統預設瀏覽器中開啟,而非在應用程式內開啟",

"settings.general.row.language.title": "語言",
"settings.general.row.language.description": "變更 OpenCode 的顯示語言",
Expand Down
43 changes: 38 additions & 5 deletions packages/desktop/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,24 @@ const listenForDeepLinks = async () => {
await onOpenUrl((urls) => emitDeepLinks(urls)).catch(() => undefined)
}

// Settings key for reading browser preferences
const SETTINGS_KEY = "settings.v3"

// Read browser settings from store to check if links should open externally
async function shouldOpenLinksExternally(): Promise<boolean> {
try {
const store = await Store.load("opencode.global.dat")
const settings = await store.get(SETTINGS_KEY)
if (settings && typeof settings === "object" && "browser" in (settings as object)) {
const browser = (settings as { browser?: { openLinksExternally?: boolean } }).browser
return browser?.openLinksExternally !== false // Default to true
}
} catch {
// Ignore errors, default to true
}
return true // Default: open links externally
}

const createPlatform = (password: Accessor<string | null>): Platform => ({
platform: "desktop",
os: (() => {
Expand Down Expand Up @@ -356,11 +374,26 @@ render(() => {
const platform = createPlatform(() => serverPassword())

function handleClick(e: MouseEvent) {
const link = (e.target as HTMLElement).closest("a.external-link") as HTMLAnchorElement | null
if (link?.href) {
e.preventDefault()
platform.openLink(link.href)
}
const link = (e.target as HTMLElement).closest("a") as HTMLAnchorElement | null
if (!link?.href) return

// Check if it's an external link (http/https)
const isExternal = link.href.startsWith("http://") || link.href.startsWith("https://")
if (!isExternal) return

// MUST preventDefault immediately (before any async), otherwise browser handles it
e.preventDefault()
const url = link.href

// Check user preference and handle accordingly
shouldOpenLinksExternally().then((openExternally) => {
if (openExternally) {
platform.openLink(url)
} else {
// Open in app by navigating
window.location.href = url
}
})
}

onMount(() => {
Expand Down
Loading