feat(app): redesign non-modal settings

This commit is contained in:
LukeParkerDev 2026-08-06 21:26:00 +10:00
parent 2092350cfa
commit 5f139c9612
27 changed files with 1520 additions and 54 deletions

View file

@ -80,11 +80,10 @@ export const ServerRowMenuView: Component<{
>
{props.labels.edit}
</MenuV2.Item>
<Show when={props.canDefault && !props.isDefault}>
<MenuV2.Item onSelect={props.onSetDefault}>{props.labels.default}</MenuV2.Item>
</Show>
<Show when={props.canDefault && props.isDefault}>
<MenuV2.Item onSelect={props.onRemoveDefault}>{props.labels.defaultRemove}</MenuV2.Item>
<Show when={props.canDefault}>
<MenuV2.Item disabled={props.isDefault} onSelect={props.onSetDefault}>
{props.labels.default}
</MenuV2.Item>
</Show>
<Show when={props.canRemove}>
<MenuV2.Separator />

View file

@ -0,0 +1,202 @@
import { Component, Show, createMemo, createResource, createSignal } from "solid-js"
import { ButtonV2 } from "@opencode-ai/ui/v2/button-v2"
import { SelectV2 } from "@opencode-ai/ui/v2/select-v2"
import { Switch } from "@opencode-ai/ui/v2/switch-v2"
import { TextInputV2 } from "@opencode-ai/ui/v2/text-input-v2"
import { useLanguage } from "@/context/language"
import { usePlatform } from "@/context/platform"
import { ExternalLink } from "../external-link"
import { SettingsListV2 } from "./parts/list"
import { SettingsRowV2 } from "./parts/row"
import {
createAppearanceSettingsController,
type AppearanceSettingsController,
} from "./general-controllers"
import "./settings-v2.css"
const schemeOptions: ("system" | "light" | "dark")[] = ["system", "light", "dark"]
const densityOptions: ("compact" | "default" | "comfortable")[] = ["compact", "default", "comfortable"]
const fontSettings = {
ui: {
action: "settings-ui-font",
title: "settings.general.row.uiFont.title",
description: "settings.general.row.uiFont.description",
font: "ui",
input: "setUI",
},
code: {
action: "settings-code-font",
title: "settings.general.row.font.title",
description: "settings.general.row.font.description",
font: "code",
input: "setCode",
},
terminal: {
action: "settings-terminal-font",
title: "settings.general.row.terminalFont.title",
description: "settings.general.row.terminalFont.description",
font: "terminal",
input: "setTerminal",
},
} as const
const FontSetting: Component<{
kind: "ui" | "code" | "terminal"
fonts: AppearanceSettingsController["fonts"]
}> = (props) => {
const language = useLanguage()
const config = () => fontSettings[props.kind]
return (
<SettingsRowV2 title={language.t(config().title)} description={language.t(config().description)}>
<div class="w-full sm:w-[220px]">
<TextInputV2
data-action={config().action}
type="text"
appearance="base"
value={props.fonts[config().font]().value}
onInput={(event) => props.fonts[config().input](event.currentTarget.value)}
placeholder={props.fonts[config().font]().placeholder}
spellcheck={false}
autocorrect="off"
autocomplete="off"
autocapitalize="off"
aria-label={language.t(config().title)}
style={{ "font-family": props.fonts[config().font]().family }}
/>
</div>
</SettingsRowV2>
)
}
export const SettingsAppearanceV2: Component = () => {
const language = useLanguage()
const platform = usePlatform()
const appearance = createAppearanceSettingsController()
const desktop = createMemo(() => platform.platform === "desktop")
const [density, setDensity] = createSignal<"compact" | "default" | "comfortable">("default")
const [pinchZoom, { mutate: setPinchZoom }] = createResource(
() => desktop() && "getPinchZoomEnabled" in platform,
() => Promise.resolve(platform.getPinchZoomEnabled?.() ?? false).catch(() => false),
{ initialValue: false },
)
const onPinchZoomChange = (checked: boolean) => {
setPinchZoom(checked)
const update = platform.setPinchZoomEnabled?.(checked)
if (!update) return
void update.catch(() => setPinchZoom(!checked))
}
const restoreDefaults = () => {
appearance.scheme.select("system")
appearance.fonts.setUI("")
appearance.fonts.setCode("")
appearance.fonts.setTerminal("")
setDensity("default")
}
return (
<>
<div class="settings-v2-tab-header">
<div class="settings-v2-tab-header-row">
<h2 class="settings-v2-tab-title">{language.t("settings.tab.appearance")}</h2>
<ButtonV2 size="small" variant="ghost-muted" onClick={restoreDefaults}>
{language.t("settings.action.restoreDefaults")}
</ButtonV2>
</div>
</div>
<div class="settings-v2-tab-body">
<div class="settings-v2-section">
<SettingsListV2>
<SettingsRowV2
title={language.t("settings.general.row.colorScheme.title")}
description={language.t("settings.general.row.colorScheme.description")}
>
<SelectV2
appearance="inline"
data-action="settings-color-scheme"
options={schemeOptions}
current={schemeOptions.find((option) => option === appearance.scheme.current())}
placement="bottom-end"
gutter={6}
label={(option) => {
if (option === "system") return language.t("theme.scheme.system")
if (option === "light") return language.t("theme.scheme.light")
return language.t("theme.scheme.dark")
}}
onSelect={(option) => option && appearance.scheme.select(option)}
/>
</SettingsRowV2>
<SettingsRowV2
title={language.t("settings.general.row.theme.title")}
description={
<>
{language.t("settings.general.row.theme.description")}{" "}
<ExternalLink class="settings-v2-link" href="https://opencode.ai/docs/themes/">
{language.t("common.learnMore")}
</ExternalLink>
</>
}
>
<SelectV2
appearance="inline"
data-action="settings-theme"
options={appearance.theme.options()}
current={appearance.theme.current()}
placement="bottom-end"
gutter={6}
value={(option) => option.id}
label={(option) => option.name}
onSelect={appearance.theme.select}
/>
</SettingsRowV2>
<SettingsRowV2
title={language.t("settings.appearance.density.title")}
description={language.t("settings.appearance.density.description")}
>
<SelectV2
appearance="inline"
data-action="settings-density"
options={densityOptions}
current={density()}
placement="bottom-end"
gutter={6}
label={(option) => {
if (option === "compact") return language.t("settings.appearance.density.compact")
if (option === "comfortable") return language.t("settings.appearance.density.comfortable")
return language.t("settings.appearance.density.default")
}}
onSelect={(option) => option && setDensity(option)}
/>
</SettingsRowV2>
<FontSetting kind="ui" fonts={appearance.fonts} />
<FontSetting kind="code" fonts={appearance.fonts} />
<FontSetting kind="terminal" fonts={appearance.fonts} />
</SettingsListV2>
</div>
<Show when={desktop()}>
<div class="settings-v2-section">
<h3 class="settings-v2-section-title">{language.t("settings.general.section.display")}</h3>
<SettingsListV2>
<SettingsRowV2
title={language.t("settings.general.row.pinchZoom.title")}
description={language.t("settings.general.row.pinchZoom.description")}
>
<div data-action="settings-pinch-zoom">
<Switch checked={pinchZoom.latest} onChange={onPinchZoomChange} />
</div>
</SettingsRowV2>
</SettingsListV2>
</div>
</Show>
</div>
</>
)
}

View file

@ -5,15 +5,19 @@ import { Icon } from "@opencode-ai/ui/icon"
import { useLanguage } from "@/context/language"
import { usePlatform } from "@/context/platform"
import { SettingsGeneralV2 } from "./general"
import { SettingsAppearanceV2 } from "./appearance"
import { SettingsKeybinds } from "../settings-keybinds"
import { SettingsNotificationsV2 } from "./notifications"
import { SettingsProvidersV2 } from "./providers"
import { SettingsModelsV2 } from "./models"
import "./settings-v2.css"
import { SettingsServersV2 } from "./servers"
import { SettingsProjectsV2 } from "./projects"
import { SettingsExtensionsV2 } from "./extensions"
import { useDialog } from "@opencode-ai/ui/context/dialog"
import { useLayout } from "@/context/layout"
import { useTabs } from "@/context/tabs"
import { useServerSync } from "@/context/server-sync"
import "./settings-v2.css"
export const DialogSettings: Component<{
sessionID?: string
@ -52,62 +56,90 @@ export const DialogSettings: Component<{
>
<TabsV2.List>
<div class="flex flex-col justify-between h-full w-full">
<div class="flex flex-col gap-3 w-full">
<div class="flex flex-col gap-3">
<div class="flex flex-col gap-1.5">
<TabsV2.SectionTitle>{language.t("settings.section.desktop")}</TabsV2.SectionTitle>
<div class="flex flex-col gap-1.5 w-full">
<TabsV2.Trigger value="general">
<Icon name="sliders" />
{language.t("settings.tab.general")}
</TabsV2.Trigger>
<TabsV2.Trigger value="shortcuts">
<Icon name="keyboard" />
{language.t("settings.tab.shortcuts")}
</TabsV2.Trigger>
</div>
</div>
<div class="flex flex-col gap-4 w-full">
{/* Group 1: Preferences */}
<div class="flex flex-col gap-1 w-full">
<TabsV2.Trigger value="general">
<Icon name="sliders" />
{language.t("settings.tab.general")}
</TabsV2.Trigger>
<TabsV2.Trigger value="appearance">
<Icon name="appearance" />
{language.t("settings.tab.appearance")}
</TabsV2.Trigger>
<TabsV2.Trigger value="notifications">
<Icon name="notifications" />
{language.t("settings.tab.notifications")}
</TabsV2.Trigger>
<TabsV2.Trigger value="shortcuts">
<Icon name="keyboard" />
{language.t("settings.tab.shortcuts")}
</TabsV2.Trigger>
</div>
<div class="flex flex-col gap-1.5">
<TabsV2.SectionTitle>{language.t("settings.section.server")}</TabsV2.SectionTitle>
<div class="flex flex-col gap-1.5 w-full">
<TabsV2.Trigger value="servers">
<Icon name="server" />
{language.t("status.popover.tab.servers")}
</TabsV2.Trigger>
<TabsV2.Trigger value="providers">
<Icon name="providers" />
{language.t("settings.providers.title")}
</TabsV2.Trigger>
<TabsV2.Trigger value="models">
<Icon name="models" />
{language.t("settings.models.title")}
</TabsV2.Trigger>
</div>
</div>
{/* Group 2: Environment & Workspaces */}
<div class="flex flex-col gap-1 w-full">
<TabsV2.Trigger value="servers">
<Icon name="server" />
{language.t("settings.tab.servers")}
</TabsV2.Trigger>
<TabsV2.Trigger value="projects">
<Icon name="folder" />
{language.t("settings.tab.projects")}
</TabsV2.Trigger>
</div>
{/* Group 3: Capabilities & Extensions */}
<div class="flex flex-col gap-1 w-full">
<TabsV2.Trigger value="providers">
<Icon name="providers" />
{language.t("settings.tab.providers")}
</TabsV2.Trigger>
<TabsV2.Trigger value="models">
<Icon name="models" />
{language.t("settings.tab.models")}
</TabsV2.Trigger>
<TabsV2.Trigger value="extensions">
<Icon name="extensions" />
{language.t("settings.tab.extensions")}
</TabsV2.Trigger>
</div>
</div>
<div class="settings-v2-nav-footer">
<span>{language.t("app.name.desktop")}</span>
<span>v{platform.version}</span>
</div>
</div>
</TabsV2.List>
<TabsV2.Content value="general" class="settings-v2-panel">
<SettingsGeneralV2 sessionID={props.sessionID} />
</TabsV2.Content>
<TabsV2.Content value="appearance" class="settings-v2-panel">
<SettingsAppearanceV2 />
</TabsV2.Content>
<TabsV2.Content value="notifications" class="settings-v2-panel">
<SettingsNotificationsV2 />
</TabsV2.Content>
<TabsV2.Content value="shortcuts" class="settings-v2-panel">
<SettingsKeybinds v2 />
</TabsV2.Content>
<TabsV2.Content value="servers" class="settings-v2-panel">
<SettingsServersV2 />
</TabsV2.Content>
<TabsV2.Content value="projects" class="settings-v2-panel">
<SettingsProjectsV2 />
</TabsV2.Content>
<TabsV2.Content value="providers" class="settings-v2-panel">
<SettingsProvidersV2 directory={directory} onBack={showProviders} />
</TabsV2.Content>
<TabsV2.Content value="models" class="settings-v2-panel">
<SettingsModelsV2 />
</TabsV2.Content>
<TabsV2.Content value="extensions" class="settings-v2-panel">
<SettingsExtensionsV2 />
</TabsV2.Content>
</TabsV2>
</Dialog>
)

View file

@ -0,0 +1,214 @@
import { Component, For, Show, createMemo, createSignal } from "solid-js"
import { Icon } from "@opencode-ai/ui/icon"
import { Switch } from "@opencode-ai/ui/v2/switch-v2"
import { useLanguage } from "@/context/language"
import { ServerConnection, useServer } from "@/context/server"
import { useServerSync } from "@/context/server-sync"
import { ExternalLink } from "../external-link"
import { InlineServerSelect } from "./parts/server-select"
import "./settings-v2.css"
type ExtensionSubTab = "mcps" | "plugins" | "skills"
interface McpRowItem {
name: string
status?: string
}
interface PluginRowItem {
name: string
}
interface SkillRowItem {
name: string
}
export const SettingsExtensionsV2: Component = () => {
const language = useLanguage()
const server = useServer()
const serverSync = useServerSync()
const [selectedServer, setSelectedServer] = createSignal<ServerConnection.Key | "all">(server.key)
const [activeSubTab, setActiveSubTab] = createSignal<ExtensionSubTab>("mcps")
const [mcpOverrides, setMcpOverrides] = createSignal<Record<string, boolean>>({})
const mcps = createMemo<McpRowItem[]>(() => {
const configMcp = (serverSync().data.config as { mcp?: Record<string, { disabled?: boolean }> })?.mcp ?? {}
const configEntries = Object.entries(configMcp).map(([name, conf]) => ({
name,
status: conf.disabled ? "disabled" : "connected",
}))
const firstProject = server.projects.list()[0]?.worktree
const childMcp = firstProject ? serverSync().child(firstProject, { mcp: true })[0].mcp : {}
const childEntries = Object.entries(childMcp ?? {}).map(([name, stat]) => ({
name,
status: stat?.status,
}))
const map = new Map<string, McpRowItem>()
for (const item of configEntries) map.set(item.name, item)
for (const item of childEntries) {
const existing = map.get(item.name)
map.set(item.name, { ...existing, ...item })
}
return Array.from(map.values()).sort((a, b) => a.name.localeCompare(b.name))
})
const isMcpEnabled = (item: McpRowItem) => {
if (mcpOverrides()[item.name] !== undefined) return mcpOverrides()[item.name]
return item.status === "connected"
}
const handleMcpToggle = (item: McpRowItem, checked: boolean) => {
setMcpOverrides((prev) => ({ ...prev, [item.name]: checked }))
const firstProject = server.projects.list()[0]?.worktree
if (firstProject) {
void serverSync().mcp.toggle(firstProject, item.name)
}
}
const plugins = createMemo<PluginRowItem[]>(() => {
const raw = serverSync().data.config.plugin ?? []
return raw.map((item) => {
const name = typeof item === "string" ? item : item[0]
return { name }
})
})
const skills = createMemo<SkillRowItem[]>(() => {
const configSkills = (serverSync().data.config as { skills?: string[] })?.skills ?? []
return configSkills.map((name) => ({ name }))
})
return (
<>
<div class="settings-v2-tab-header">
<div class="settings-v2-tab-header-row">
<div class="flex flex-col gap-1">
<h2 class="settings-v2-tab-title">{language.t("settings.tab.extensions")}</h2>
<span class="text-11-regular text-v2-text-text-muted">{language.t("settings.mcps.description")}</span>
</div>
<InlineServerSelect value={selectedServer()} onChange={setSelectedServer} includeAll />
</div>
</div>
<div class="settings-v2-tab-body">
{/* Sub-Tabs Pill Strip */}
<div class="settings-v2-extensions-tabs" role="tablist">
<button
type="button"
role="tab"
aria-selected={activeSubTab() === "mcps"}
data-selected={activeSubTab() === "mcps" ? "" : undefined}
onClick={() => setActiveSubTab("mcps")}
>
{language.t("settings.tab.mcps")}
</button>
<button
type="button"
role="tab"
aria-selected={activeSubTab() === "plugins"}
data-selected={activeSubTab() === "plugins" ? "" : undefined}
onClick={() => setActiveSubTab("plugins")}
>
{language.t("settings.tab.plugins")}
</button>
<button
type="button"
role="tab"
aria-selected={activeSubTab() === "skills"}
data-selected={activeSubTab() === "skills" ? "" : undefined}
onClick={() => setActiveSubTab("skills")}
>
{language.t("settings.tab.skills")}
</button>
</div>
{/* MCPs Sub-Tab */}
<Show when={activeSubTab() === "mcps"}>
<div class="settings-v2-section">
<div class="flex items-center justify-between">
<span class="text-13-medium text-v2-text-text-base">
{language.t("settings.extensions.availableAll")}
</span>
<span class="text-13-regular text-v2-text-faint">{language.t("settings.extensions.manageConfig")}</span>
</div>
<div class="bg-[var(--v2-background-bg-base)] border-[0.5px] border-[var(--v2-border-border-base)] rounded-[8px] pl-4 pr-3 overflow-hidden">
<For each={mcps()}>
{(item) => (
<div class="py-4 flex items-center justify-between border-b-[0.5px] border-[var(--v2-border-border-base)] last:border-b-0">
<div class="flex items-center gap-2.5 min-w-0">
<Icon name="mcp" class="text-v2-icon-icon-muted shrink-0" />
<span class="text-13-medium text-v2-text-text-base truncate">{item.name}</span>
</div>
<Switch
checked={isMcpEnabled(item)}
onChange={(checked) => handleMcpToggle(item, checked)}
hideLabel
>
{item.name}
</Switch>
</div>
)}
</For>
</div>
</div>
</Show>
{/* Plugins Sub-Tab */}
<Show when={activeSubTab() === "plugins"}>
<div class="settings-v2-section">
<div class="flex items-center justify-between">
<span class="text-13-medium text-v2-text-text-base">
{language.t("settings.extensions.availableAll")}
</span>
<span class="text-13-regular text-v2-text-faint">{language.t("settings.extensions.manageConfig")}</span>
</div>
<div class="bg-[var(--v2-background-bg-base)] border-[0.5px] border-[var(--v2-border-border-base)] rounded-[8px] pl-4 pr-3 overflow-hidden">
<For each={plugins()}>
{(plugin) => (
<div class="py-4 flex items-center justify-between border-b-[0.5px] border-[var(--v2-border-border-base)] last:border-b-0">
<div class="flex items-center gap-2.5 min-w-0">
<Icon name="cube" class="text-v2-icon-icon-muted shrink-0" />
<span class="text-13-medium text-v2-text-text-base truncate font-mono">{plugin.name}</span>
</div>
</div>
)}
</For>
</div>
</div>
</Show>
{/* Skills Sub-Tab */}
<Show when={activeSubTab() === "skills"}>
<div class="settings-v2-section">
<div class="flex items-center justify-between">
<span class="text-13-medium text-v2-text-text-base">
{language.t("settings.extensions.availableAll")}
</span>
<ExternalLink
class="text-13-regular text-v2-text-accent hover:underline"
href="https://opencode.ai/docs/skills/"
>
{language.t("settings.extensions.addSkills")}
</ExternalLink>
</div>
<div class="bg-[var(--v2-background-bg-base)] border-[0.5px] border-[var(--v2-border-border-base)] rounded-[8px] pl-4 pr-3 overflow-hidden">
<For each={skills()}>
{(skill) => (
<div class="py-4 flex items-center justify-between border-b-[0.5px] border-[var(--v2-border-border-base)] last:border-b-0">
<div class="flex items-center gap-2.5 min-w-0">
<Icon name="post-skill" class="text-v2-icon-icon-muted shrink-0" />
<span class="text-13-medium text-v2-text-text-base truncate">{skill.name}</span>
</div>
</div>
)}
</For>
</div>
</div>
</Show>
</div>
</>
)
}

View file

@ -1 +1,9 @@
export { DialogSettings } from "./dialog-settings-v2"
export { SettingsGeneralV2 } from "./general"
export { SettingsAppearanceV2 } from "./appearance"
export { SettingsNotificationsV2 } from "./notifications"
export { SettingsProvidersV2 } from "./providers"
export { SettingsModelsV2 } from "./models"
export { SettingsServersV2 } from "./servers"
export { SettingsProjectsV2 } from "./projects"
export { SettingsExtensionsV2 } from "./extensions"

View file

@ -4,13 +4,15 @@ import { Switch } from "@opencode-ai/ui/v2/switch-v2"
import { Icon as IconV2 } from "@opencode-ai/ui/v2/icon"
import { IconButtonV2 } from "@opencode-ai/ui/v2/icon-button-v2"
import { TextInputV2 } from "@opencode-ai/ui/v2/text-input-v2"
import { type Component, For, Show } from "solid-js"
import { type Component, For, Show, createSignal } from "solid-js"
import { createStore } from "solid-js/store"
import { useLanguage } from "@/context/language"
import { useModels } from "@/context/models"
import { useServerSDK } from "@/context/server-sdk"
import { ServerConnection, useServer } from "@/context/server"
import { popularProviders } from "@/hooks/use-providers"
import { Persist, persisted } from "@/utils/persist"
import { InlineServerSelect } from "./parts/server-select"
import { SettingsListV2 } from "./parts/list"
import { SettingsRowV2 } from "./parts/row"
import "./settings-v2.css"
@ -22,7 +24,9 @@ const PROVIDER_ICON_SIZE = 16
export const SettingsModelsV2: Component = () => {
const language = useLanguage()
const models = useModels()
const server = useServer()
const serverSdk = useServerSDK()
const [selectedServer, setSelectedServer] = createSignal<ServerConnection.Key | "all">(server.key)
const [store, setStore] = persisted(
Persist.serverGlobal(serverSdk().scope, "settings-v2.models.providers"),
createStore({ collapsed: {} as Record<string, boolean> }),
@ -53,7 +57,14 @@ export const SettingsModelsV2: Component = () => {
return (
<>
<div class="settings-v2-tab-header settings-v2-tab-header--stacked">
<h2 class="settings-v2-tab-title">{language.t("settings.models.title")}</h2>
<div class="settings-v2-tab-header-row">
<h2 class="settings-v2-tab-title">{language.t("settings.models.title")}</h2>
<InlineServerSelect
value={selectedServer()}
onChange={setSelectedServer}
includeAll
/>
</div>
<div class="settings-v2-tab-search">
<TextInputV2
type="search"

View file

@ -0,0 +1,183 @@
import { Component, createSignal } from "solid-js"
import { ButtonV2 } from "@opencode-ai/ui/v2/button-v2"
import { SelectV2 } from "@opencode-ai/ui/v2/select-v2"
import { Switch } from "@opencode-ai/ui/v2/switch-v2"
import { useLanguage } from "@/context/language"
import { useSettings } from "@/context/settings"
import { SettingsListV2 } from "./parts/list"
import { SettingsRowV2 } from "./parts/row"
import {
createSoundSettingsController,
soundOptions,
type SoundSettingsController,
} from "./general-controllers"
import "./settings-v2.css"
const badgeOptions: ("count" | "dot" | "none")[] = ["count", "dot", "none"]
const focusOptions: ("auto" | "always" | "never")[] = ["auto", "always", "never"]
const soundSettings = {
agent: {
action: "settings-sounds-agent",
title: "settings.general.sounds.agent.title",
description: "settings.general.sounds.agent.description",
},
permissions: {
action: "settings-sounds-permissions",
title: "settings.general.sounds.permissions.title",
description: "settings.general.sounds.permissions.description",
},
errors: {
action: "settings-sounds-errors",
title: "settings.general.sounds.errors.title",
description: "settings.general.sounds.errors.description",
},
} as const
const SoundSetting: Component<{
kind: "agent" | "permissions" | "errors"
channel: SoundSettingsController["agent"]
}> = (props) => {
const language = useLanguage()
const config = () => soundSettings[props.kind]
return (
<SettingsRowV2 title={language.t(config().title)} description={language.t(config().description)}>
<SelectV2
appearance="inline"
data-action={config().action}
options={soundOptions}
current={props.channel.current()}
value={(option) => option.id}
label={(option) => language.t(option.label)}
onHighlight={props.channel.highlight}
onSelect={props.channel.select}
placement="bottom-end"
gutter={6}
/>
</SettingsRowV2>
)
}
export const SettingsNotificationsV2: Component = () => {
const language = useLanguage()
const settings = useSettings()
const sounds = createSoundSettingsController()
const [unreadBadge, setUnreadBadge] = createSignal<"count" | "dot" | "none">("count")
const [focusMode, setFocusMode] = createSignal<"auto" | "always" | "never">("auto")
const restoreDefaults = () => {
settings.notifications.setAgent(true)
settings.notifications.setPermissions(true)
settings.notifications.setErrors(true)
settings.sounds.setAgent("bip-bop-01")
settings.sounds.setPermissions("alert-01")
settings.sounds.setErrors("nope-01")
setUnreadBadge("count")
setFocusMode("auto")
}
return (
<>
<div class="settings-v2-tab-header">
<div class="settings-v2-tab-header-row">
<h2 class="settings-v2-tab-title">{language.t("settings.tab.notifications")}</h2>
<ButtonV2 size="small" variant="ghost-muted" onClick={restoreDefaults}>
{language.t("settings.action.restoreDefaults")}
</ButtonV2>
</div>
</div>
<div class="settings-v2-tab-body">
<div class="settings-v2-section">
<h3 class="settings-v2-section-title">{language.t("settings.general.section.notifications")}</h3>
<SettingsListV2>
<SettingsRowV2
title={language.t("settings.general.notifications.agent.title")}
description={language.t("settings.general.notifications.agent.description")}
>
<div data-action="settings-notifications-agent">
<Switch
checked={settings.notifications.agent()}
onChange={(checked) => settings.notifications.setAgent(checked)}
/>
</div>
</SettingsRowV2>
<SettingsRowV2
title={language.t("settings.general.notifications.permissions.title")}
description={language.t("settings.general.notifications.permissions.description")}
>
<div data-action="settings-notifications-permissions">
<Switch
checked={settings.notifications.permissions()}
onChange={(checked) => settings.notifications.setPermissions(checked)}
/>
</div>
</SettingsRowV2>
<SettingsRowV2
title={language.t("settings.general.notifications.errors.title")}
description={language.t("settings.general.notifications.errors.description")}
>
<div data-action="settings-notifications-errors">
<Switch
checked={settings.notifications.errors()}
onChange={(checked) => settings.notifications.setErrors(checked)}
/>
</div>
</SettingsRowV2>
</SettingsListV2>
</div>
<div class="settings-v2-section">
<h3 class="settings-v2-section-title">{language.t("settings.general.section.sounds")}</h3>
<SettingsListV2>
<SoundSetting kind="agent" channel={sounds.agent} />
<SoundSetting kind="permissions" channel={sounds.permissions} />
<SoundSetting kind="errors" channel={sounds.errors} />
<SettingsRowV2
title={language.t("settings.notifications.unreadBadge.title")}
description={language.t("settings.notifications.unreadBadge.description")}
>
<SelectV2
appearance="inline"
data-action="settings-unread-badge"
options={badgeOptions}
current={unreadBadge()}
placement="bottom-end"
gutter={6}
label={(option) => {
if (option === "dot") return language.t("settings.notifications.unreadBadge.dot")
if (option === "none") return language.t("settings.notifications.unreadBadge.none")
return language.t("settings.notifications.unreadBadge.count")
}}
onSelect={(option) => option && setUnreadBadge(option)}
/>
</SettingsRowV2>
<SettingsRowV2
title={language.t("settings.notifications.focusMode.title")}
description={language.t("settings.notifications.focusMode.description")}
>
<SelectV2
appearance="inline"
data-action="settings-focus-mode"
options={focusOptions}
current={focusMode()}
placement="bottom-end"
gutter={6}
label={(option) => {
if (option === "always") return language.t("settings.notifications.focusMode.always")
if (option === "never") return language.t("settings.notifications.focusMode.never")
return language.t("settings.notifications.focusMode.auto")
}}
onSelect={(option) => option && setFocusMode(option)}
/>
</SettingsRowV2>
</SettingsListV2>
</div>
</div>
</>
)
}

View file

@ -0,0 +1,72 @@
import { Show, createMemo, type Component } from "solid-js"
import { SelectV2 } from "@opencode-ai/ui/v2/select-v2"
import { useGlobal } from "@/context/global"
import { useLanguage } from "@/context/language"
import { ServerConnection, serverName, useServer } from "@/context/server"
export interface ServerSelectOption {
key: ServerConnection.Key | "all"
label: string
isDefault?: boolean
isAll?: boolean
}
export const InlineServerSelect: Component<{
value: ServerConnection.Key | "all"
onChange: (key: ServerConnection.Key | "all") => void
includeAll?: boolean
disabled?: boolean
}> = (props) => {
const language = useLanguage()
const global = useGlobal()
const server = useServer()
const hasMultipleServers = createMemo(() => global.servers.list().length > 1)
const options = createMemo<ServerSelectOption[]>(() => {
const list: ServerSelectOption[] = []
if (props.includeAll) {
list.push({
key: "all",
label: language.t("settings.server.all"),
isAll: true,
})
}
const servers = global.servers.list()
for (const item of servers) {
const key = ServerConnection.key(item)
const isDefault = key === server.key
list.push({
key,
label: serverName(item) || key,
isDefault,
})
}
return list
})
const currentOption = createMemo(() => {
return options().find((opt) => opt.key === props.value) ?? options()[0]
})
return (
<Show when={hasMultipleServers()}>
<SelectV2
appearance="inline"
data-action="settings-server-select"
options={options()}
current={currentOption()}
value={(opt) => opt.key}
label={(opt) => opt.label}
disabled={props.disabled}
placement="bottom-end"
gutter={6}
onSelect={(opt) => {
if (opt) props.onChange(opt.key)
}}
/>
</Show>
)
}

View file

@ -0,0 +1,97 @@
import { Component, For, Show, createMemo, createSignal } from "solid-js"
import { IconButtonV2 } from "@opencode-ai/ui/v2/icon-button-v2"
import { Icon as IconV2 } from "@opencode-ai/ui/v2/icon"
import { ProjectAvatar } from "@opencode-ai/ui/v2/project-avatar-v2"
import { useDialog } from "@opencode-ai/ui/context/dialog"
import { useLanguage } from "@/context/language"
import { ServerConnection, useServer } from "@/context/server"
import { useGlobal } from "@/context/global"
import { useLayout, getProjectAvatarVariant } from "@/context/layout"
import { InlineServerSelect } from "./parts/server-select"
import { DialogEditProjectV2 } from "../dialog-edit-project-v2"
import "./settings-v2.css"
export const SettingsProjectsV2: Component = () => {
const dialog = useDialog()
const language = useLanguage()
const server = useServer()
const global = useGlobal()
const layout = useLayout()
const [selectedServer, setSelectedServer] = createSignal<ServerConnection.Key | "all">(server.key)
const projects = createMemo(() => {
return layout.projects.list()
})
const openProjectSettings = (project: ReturnType<typeof layout.projects.list>[number]) => {
const currentServer = server.current ?? global.servers.list()[0]
if (!currentServer) return
dialog.push(() => <DialogEditProjectV2 project={project} server={currentServer} />)
}
return (
<>
<div class="settings-v2-tab-header">
<div class="settings-v2-tab-header-row">
<div class="flex flex-col gap-1">
<h2 class="settings-v2-tab-title">{language.t("settings.projects.title")}</h2>
<span class="text-11-regular text-v2-text-text-muted">{language.t("settings.projects.description")}</span>
</div>
<InlineServerSelect
value={selectedServer()}
onChange={setSelectedServer}
includeAll
/>
</div>
</div>
<div class="settings-v2-tab-body">
<div class="flex flex-col gap-2 w-full">
<Show
when={projects().length > 0}
fallback={
<div class="py-12 text-center text-v2-text-text-muted text-13-regular">
{language.t("settings.projects.empty")}
</div>
}
>
<For each={projects()}>
{(project) => {
const name = () => project.name || project.worktree.split(/[/\\]/).pop() || project.worktree
const color = () => getProjectAvatarVariant(project.icon?.color)
return (
<div
class="group flex items-center justify-between gap-5 px-4 py-2.5 rounded-lg bg-v2-background-bg-base shadow-[var(--v2-elevation-raised)] cursor-pointer transition-all hover:bg-v2-background-bg-layer-01"
onClick={() => openProjectSettings(project)}
>
<div class="flex items-center gap-2.5 min-w-0 flex-1">
<ProjectAvatar
fallback={name()}
variant={color()}
class="shrink-0"
/>
<span class="text-13-medium text-v2-text-text-base truncate">{name()}</span>
</div>
<div class="flex items-center gap-2 shrink-0 opacity-0 group-hover:opacity-100 transition-opacity">
<IconButtonV2
type="button"
variant="ghost-muted"
size="small"
icon={<IconV2 name="settings-gear" size="small" class="text-v2-icon-icon-muted" />}
onClick={(e: MouseEvent) => {
e.stopPropagation()
openProjectSettings(project)
}}
/>
</div>
</div>
)
}}
</For>
</Show>
</div>
</div>
</>
)
}

View file

@ -4,12 +4,14 @@ import { useDialog } from "@opencode-ai/ui/context/dialog"
import { ProviderIcon } from "@opencode-ai/ui/provider-icon"
import { showToast } from "@/utils/toast"
import { popularProviders, useProviders } from "@/hooks/use-providers"
import { createMemo, type Accessor, type Component, For, Show } from "solid-js"
import { createMemo, createSignal, type Accessor, type Component, For, Show } from "solid-js"
import { useLanguage } from "@/context/language"
import { useServerSDK } from "@/context/server-sdk"
import { useServerSync } from "@/context/server-sync"
import { ServerConnection, useServer } from "@/context/server"
import { DialogConnectProvider, useProviderConnectController } from "../dialog-connect-provider"
import { DialogCustomProvider } from "../dialog-custom-provider"
import { InlineServerSelect } from "./parts/server-select"
import { SettingsListV2 } from "./parts/list"
import "./settings-v2.css"
@ -40,6 +42,9 @@ export const SettingsProvidersV2: Component<{
const providers = useProviders(props.directory)
const providerConnect = useProviderConnectController({ onBack: props.onBack })
const server = useServer()
const [selectedServer, setSelectedServer] = createSignal<ServerConnection.Key | "all">(server.key)
const connect = (provider?: string) => {
providerConnect.select(provider)
void dialog.show(() => <DialogConnectProvider directory={props.directory} controller={providerConnect} />)
@ -143,7 +148,14 @@ export const SettingsProvidersV2: Component<{
return (
<>
<div class="settings-v2-tab-header">
<h2 class="settings-v2-tab-title">{language.t("settings.providers.title")}</h2>
<div class="settings-v2-tab-header-row">
<h2 class="settings-v2-tab-title">{language.t("settings.providers.title")}</h2>
<InlineServerSelect
value={selectedServer()}
onChange={setSelectedServer}
includeAll
/>
</div>
</div>
<div class="settings-v2-tab-body settings-v2-providers">

View file

@ -9,7 +9,7 @@ import { createStore } from "solid-js/store"
import { ServerRowMenu } from "@/components/server/server-row-menu"
import { ServerHealthIndicator } from "@/components/server/server-row"
import { useLanguage } from "@/context/language"
import { ServerConnection, serverName } from "@/context/server"
import { ServerConnection, serverName, useServer } from "@/context/server"
import { useServerManagementController } from "../dialog-select-server"
import { DialogServerV2 } from "./dialog-server-v2"
import { SettingsListV2 } from "./parts/list"
@ -19,6 +19,7 @@ import "./settings-v2.css"
export const SettingsServersV2: Component = () => {
const dialog = useDialog()
const language = useLanguage()
const server = useServer()
const controller = useServerManagementController()
const [store, setStore] = createStore({ filter: "" })
const wslServers = useFilteredWslServers(() => store.filter)
@ -27,15 +28,38 @@ export const SettingsServersV2: Component = () => {
() => controller.sortedItems().filter((item) => !isWslServer(item)).length + wslServers().length > 1,
)
const isLocal = (item: ServerConnection.Any) => ServerConnection.local(item)
const isDefaultServer = (key: ServerConnection.Key, item: ServerConnection.Any) => {
const def = controller.defaultKey()
if (!def) return isLocal(item)
return def === key
}
const filtered = createMemo(() => {
const items = controller.sortedItems().filter((item) => !isWslServer(item))
const query = store.filter.trim()
if (!query) return items
if (!query) {
return items.slice().sort((a, b) => {
const aLocal = isLocal(a)
const bLocal = isLocal(b)
if (aLocal && !bLocal) return -1
if (!aLocal && bLocal) return 1
return 0
})
}
return fuzzysort
.go(query, items, {
keys: [(item) => serverName(item), (item) => item.http.url],
})
.map((result) => result.obj)
.sort((a, b) => {
const aLocal = isLocal(a)
const bLocal = isLocal(b)
if (aLocal && !bLocal) return -1
if (!aLocal && bLocal) return 1
return 0
})
})
const openAdd = () => {
@ -97,12 +121,11 @@ export const SettingsServersV2: Component = () => {
}
>
<SettingsListV2>
<WslServerSettings controller={controller} servers={wslServers} />
<For each={filtered()}>
{(item) => {
const key = ServerConnection.key(item)
const health = () => controller.status()[key]
const isDefault = () => controller.defaultKey() === key
const isDefault = () => isDefaultServer(key, item)
return (
<div class="settings-v2-servers-row">
<div class="settings-v2-servers-lead">
@ -131,6 +154,7 @@ export const SettingsServersV2: Component = () => {
)
}}
</For>
<WslServerSettings controller={controller} servers={wslServers} />
</SettingsListV2>
</Show>
</div>

View file

@ -39,6 +39,14 @@
background: linear-gradient(to bottom, var(--v2-background-bg-base) calc(100% - 24px), transparent);
}
.settings-v2-tab-header-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
width: 100%;
}
.settings-v2-tab-title {
font-size: 15px;
font-weight: 640;
@ -727,3 +735,40 @@
line-height: 1;
color: var(--v2-state-fg-danger);
}
.settings-v2-extensions-tabs {
display: flex;
align-items: flex-start;
gap: 6px;
width: 280px;
height: 32px;
overflow: visible;
}
.settings-v2-extensions-tabs > button {
display: flex;
align-items: center;
justify-content: center;
flex: none;
height: 24px;
padding: 0 8px;
border: 0.5px solid transparent;
border-radius: 6px;
background: transparent;
color: var(--v2-text-text-muted);
font-size: 13px;
font-weight: 440;
line-height: 1;
letter-spacing: -0.04px;
}
.settings-v2-extensions-tabs > button[data-selected] {
border-color: var(--v2-border-border-muted);
background: var(--v2-background-bg-layer-03);
color: var(--v2-text-text-base);
}
.settings-v2-extensions-tabs > button:focus-visible {
outline: 2px solid var(--v2-border-border-focus);
outline-offset: 2px;
}

View file

@ -1005,4 +1005,48 @@ export const dict = {
"error.childStore.persistedProjectIconCreateFailed": "فشل إنشاء أيقونة المشروع الدائمة",
"error.childStore.storeCreateFailed": "فشل إنشاء المخزن",
"terminal.connectionLost.abnormalClose": "تم إغلاق WebSocket بشكل غير طبيعي: {{code}}",
"command.session.export": "Export session",
"command.session.export.description": "Export the full session transcript as JSON",
"context.export.session": "Export session",
"toast.session.export.success.title": "Session exported",
"toast.session.export.success.description": "Saved session to {{filename}}",
"toast.session.export.failed.title": "Failed to export session",
"toast.session.export.failed.description": "An error occurred while exporting the session",
"common.export": "Export",
"settings.tab.appearance": "Appearance",
"settings.tab.notifications": "Notifications",
"settings.tab.providers": "Providers",
"settings.tab.models": "Models",
"settings.tab.servers": "Servers",
"settings.tab.projects": "Projects",
"settings.tab.extensions": "Extensions",
"settings.tab.mcps": "MCPs",
"settings.tab.plugins": "Plugins",
"settings.tab.skills": "Skills",
"settings.server.all": "All servers",
"settings.action.restoreDefaults": "Restore defaults",
"settings.action.resetAll": "Reset all settings",
"settings.action.resetAll.description": "Revert all settings and preferences back to default values",
"settings.appearance.density.title": "Interface density",
"settings.appearance.density.description": "Adjust padding and spacing across the application",
"settings.appearance.density.compact": "Compact",
"settings.appearance.density.default": "Default",
"settings.appearance.density.comfortable": "Comfortable",
"settings.notifications.unreadBadge.title": "Unread badge",
"settings.notifications.unreadBadge.description": "Show unread session indicator badge on the app icon",
"settings.notifications.unreadBadge.count": "Count",
"settings.notifications.unreadBadge.dot": "Dot",
"settings.notifications.unreadBadge.none": "None",
"settings.notifications.focusMode.title": "Focus mode",
"settings.notifications.focusMode.description": "Suppress desktop notifications while presenting or in fullscreen",
"settings.notifications.focusMode.auto": "Auto",
"settings.notifications.focusMode.always": "Always",
"settings.notifications.focusMode.never": "Never",
"settings.projects.title": "Projects",
"settings.projects.description": "View and configure projects on this server",
"settings.projects.empty": "No projects found",
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
"settings.extensions.availableAll": "Available to all projects",
"settings.extensions.manageConfig": "Manage in opencode.json",
"settings.extensions.addSkills": "How to add skills",
}

View file

@ -1021,4 +1021,48 @@ export const dict = {
"error.childStore.persistedProjectIconCreateFailed": "Falha ao criar ícone de projeto persistente",
"error.childStore.storeCreateFailed": "Falha ao criar armazenamento",
"terminal.connectionLost.abnormalClose": "WebSocket fechado anormalmente: {{code}}",
"command.session.export": "Export session",
"command.session.export.description": "Export the full session transcript as JSON",
"context.export.session": "Export session",
"toast.session.export.success.title": "Session exported",
"toast.session.export.success.description": "Saved session to {{filename}}",
"toast.session.export.failed.title": "Failed to export session",
"toast.session.export.failed.description": "An error occurred while exporting the session",
"common.export": "Export",
"settings.tab.appearance": "Appearance",
"settings.tab.notifications": "Notifications",
"settings.tab.providers": "Providers",
"settings.tab.models": "Models",
"settings.tab.servers": "Servers",
"settings.tab.projects": "Projects",
"settings.tab.extensions": "Extensions",
"settings.tab.mcps": "MCPs",
"settings.tab.plugins": "Plugins",
"settings.tab.skills": "Skills",
"settings.server.all": "All servers",
"settings.action.restoreDefaults": "Restore defaults",
"settings.action.resetAll": "Reset all settings",
"settings.action.resetAll.description": "Revert all settings and preferences back to default values",
"settings.appearance.density.title": "Interface density",
"settings.appearance.density.description": "Adjust padding and spacing across the application",
"settings.appearance.density.compact": "Compact",
"settings.appearance.density.default": "Default",
"settings.appearance.density.comfortable": "Comfortable",
"settings.notifications.unreadBadge.title": "Unread badge",
"settings.notifications.unreadBadge.description": "Show unread session indicator badge on the app icon",
"settings.notifications.unreadBadge.count": "Count",
"settings.notifications.unreadBadge.dot": "Dot",
"settings.notifications.unreadBadge.none": "None",
"settings.notifications.focusMode.title": "Focus mode",
"settings.notifications.focusMode.description": "Suppress desktop notifications while presenting or in fullscreen",
"settings.notifications.focusMode.auto": "Auto",
"settings.notifications.focusMode.always": "Always",
"settings.notifications.focusMode.never": "Never",
"settings.projects.title": "Projects",
"settings.projects.description": "View and configure projects on this server",
"settings.projects.empty": "No projects found",
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
"settings.extensions.availableAll": "Available to all projects",
"settings.extensions.manageConfig": "Manage in opencode.json",
"settings.extensions.addSkills": "How to add skills",
}

View file

@ -1097,4 +1097,48 @@ export const dict = {
"error.childStore.persistedProjectIconCreateFailed": "Nije uspjelo kreiranje trajne ikone projekta",
"error.childStore.storeCreateFailed": "Nije uspjelo kreiranje skladišta",
"terminal.connectionLost.abnormalClose": "WebSocket zatvoren nenormalno: {{code}}",
"command.session.export": "Export session",
"command.session.export.description": "Export the full session transcript as JSON",
"context.export.session": "Export session",
"toast.session.export.success.title": "Session exported",
"toast.session.export.success.description": "Saved session to {{filename}}",
"toast.session.export.failed.title": "Failed to export session",
"toast.session.export.failed.description": "An error occurred while exporting the session",
"common.export": "Export",
"settings.tab.appearance": "Appearance",
"settings.tab.notifications": "Notifications",
"settings.tab.providers": "Providers",
"settings.tab.models": "Models",
"settings.tab.servers": "Servers",
"settings.tab.projects": "Projects",
"settings.tab.extensions": "Extensions",
"settings.tab.mcps": "MCPs",
"settings.tab.plugins": "Plugins",
"settings.tab.skills": "Skills",
"settings.server.all": "All servers",
"settings.action.restoreDefaults": "Restore defaults",
"settings.action.resetAll": "Reset all settings",
"settings.action.resetAll.description": "Revert all settings and preferences back to default values",
"settings.appearance.density.title": "Interface density",
"settings.appearance.density.description": "Adjust padding and spacing across the application",
"settings.appearance.density.compact": "Compact",
"settings.appearance.density.default": "Default",
"settings.appearance.density.comfortable": "Comfortable",
"settings.notifications.unreadBadge.title": "Unread badge",
"settings.notifications.unreadBadge.description": "Show unread session indicator badge on the app icon",
"settings.notifications.unreadBadge.count": "Count",
"settings.notifications.unreadBadge.dot": "Dot",
"settings.notifications.unreadBadge.none": "None",
"settings.notifications.focusMode.title": "Focus mode",
"settings.notifications.focusMode.description": "Suppress desktop notifications while presenting or in fullscreen",
"settings.notifications.focusMode.auto": "Auto",
"settings.notifications.focusMode.always": "Always",
"settings.notifications.focusMode.never": "Never",
"settings.projects.title": "Projects",
"settings.projects.description": "View and configure projects on this server",
"settings.projects.empty": "No projects found",
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
"settings.extensions.availableAll": "Available to all projects",
"settings.extensions.manageConfig": "Manage in opencode.json",
"settings.extensions.addSkills": "How to add skills",
}

View file

@ -843,8 +843,44 @@ export const dict = {
"settings.section.desktop": "Desktop",
"settings.section.server": "Server",
"settings.tab.general": "General",
"settings.tab.general": "Preferences",
"settings.tab.appearance": "Appearance",
"settings.tab.shortcuts": "Shortcuts",
"settings.tab.notifications": "Notifications",
"settings.tab.providers": "Providers",
"settings.tab.models": "Models",
"settings.tab.servers": "Servers",
"settings.tab.projects": "Projects",
"settings.tab.extensions": "Extensions",
"settings.tab.mcps": "MCPs",
"settings.tab.plugins": "Plugins",
"settings.tab.skills": "Skills",
"settings.server.all": "All servers",
"settings.action.restoreDefaults": "Restore defaults",
"settings.action.resetAll": "Reset all settings",
"settings.action.resetAll.description": "Revert all settings and preferences back to default values",
"settings.appearance.density.title": "Interface density",
"settings.appearance.density.description": "Adjust padding and spacing across the application",
"settings.appearance.density.compact": "Compact",
"settings.appearance.density.default": "Default",
"settings.appearance.density.comfortable": "Comfortable",
"settings.notifications.unreadBadge.title": "Unread badge",
"settings.notifications.unreadBadge.description": "Show unread session indicator badge on the app icon",
"settings.notifications.unreadBadge.count": "Count",
"settings.notifications.unreadBadge.dot": "Dot",
"settings.notifications.unreadBadge.none": "None",
"settings.notifications.focusMode.title": "Focus mode",
"settings.notifications.focusMode.description": "Suppress desktop notifications while presenting or in fullscreen",
"settings.notifications.focusMode.auto": "Auto",
"settings.notifications.focusMode.always": "Always",
"settings.notifications.focusMode.never": "Never",
"settings.projects.title": "Projects",
"settings.projects.description": "View and configure projects on this server",
"settings.projects.empty": "No projects found",
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
"settings.extensions.availableAll": "Available to all projects",
"settings.extensions.manageConfig": "Manage in opencode.json",
"settings.extensions.addSkills": "How to add skills",
"settings.desktop.section.wsl": "WSL",
"settings.desktop.wsl.title": "WSL integration",
"settings.desktop.wsl.description": "Run the OpenCode server inside WSL on Windows.",

View file

@ -1105,4 +1105,48 @@ export const dict = {
"error.childStore.persistedProjectIconCreateFailed": "Error al crear icono de proyecto persistente",
"error.childStore.storeCreateFailed": "Error al crear almacén",
"terminal.connectionLost.abnormalClose": "WebSocket cerrado anormalmente: {{code}}",
"command.session.export": "Export session",
"command.session.export.description": "Export the full session transcript as JSON",
"context.export.session": "Export session",
"toast.session.export.success.title": "Session exported",
"toast.session.export.success.description": "Saved session to {{filename}}",
"toast.session.export.failed.title": "Failed to export session",
"toast.session.export.failed.description": "An error occurred while exporting the session",
"common.export": "Export",
"settings.tab.appearance": "Appearance",
"settings.tab.notifications": "Notifications",
"settings.tab.providers": "Providers",
"settings.tab.models": "Models",
"settings.tab.servers": "Servers",
"settings.tab.projects": "Projects",
"settings.tab.extensions": "Extensions",
"settings.tab.mcps": "MCPs",
"settings.tab.plugins": "Plugins",
"settings.tab.skills": "Skills",
"settings.server.all": "All servers",
"settings.action.restoreDefaults": "Restore defaults",
"settings.action.resetAll": "Reset all settings",
"settings.action.resetAll.description": "Revert all settings and preferences back to default values",
"settings.appearance.density.title": "Interface density",
"settings.appearance.density.description": "Adjust padding and spacing across the application",
"settings.appearance.density.compact": "Compact",
"settings.appearance.density.default": "Default",
"settings.appearance.density.comfortable": "Comfortable",
"settings.notifications.unreadBadge.title": "Unread badge",
"settings.notifications.unreadBadge.description": "Show unread session indicator badge on the app icon",
"settings.notifications.unreadBadge.count": "Count",
"settings.notifications.unreadBadge.dot": "Dot",
"settings.notifications.unreadBadge.none": "None",
"settings.notifications.focusMode.title": "Focus mode",
"settings.notifications.focusMode.description": "Suppress desktop notifications while presenting or in fullscreen",
"settings.notifications.focusMode.auto": "Auto",
"settings.notifications.focusMode.always": "Always",
"settings.notifications.focusMode.never": "Never",
"settings.projects.title": "Projects",
"settings.projects.description": "View and configure projects on this server",
"settings.projects.empty": "No projects found",
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
"settings.extensions.availableAll": "Available to all projects",
"settings.extensions.manageConfig": "Manage in opencode.json",
"settings.extensions.addSkills": "How to add skills",
}

View file

@ -1108,4 +1108,48 @@ export const dict = {
"settings.general.row.pinchZoom.description": "Tillat knipebevegelser på styreflaten og Ctrl-rulling for å zoome",
"settings.updates.action.downloading": "Laster ned...",
"settings.updates.action.installing": "Installerer...",
"command.session.export": "Export session",
"command.session.export.description": "Export the full session transcript as JSON",
"context.export.session": "Export session",
"toast.session.export.success.title": "Session exported",
"toast.session.export.success.description": "Saved session to {{filename}}",
"toast.session.export.failed.title": "Failed to export session",
"toast.session.export.failed.description": "An error occurred while exporting the session",
"common.export": "Export",
"settings.tab.appearance": "Appearance",
"settings.tab.notifications": "Notifications",
"settings.tab.providers": "Providers",
"settings.tab.models": "Models",
"settings.tab.servers": "Servers",
"settings.tab.projects": "Projects",
"settings.tab.extensions": "Extensions",
"settings.tab.mcps": "MCPs",
"settings.tab.plugins": "Plugins",
"settings.tab.skills": "Skills",
"settings.server.all": "All servers",
"settings.action.restoreDefaults": "Restore defaults",
"settings.action.resetAll": "Reset all settings",
"settings.action.resetAll.description": "Revert all settings and preferences back to default values",
"settings.appearance.density.title": "Interface density",
"settings.appearance.density.description": "Adjust padding and spacing across the application",
"settings.appearance.density.compact": "Compact",
"settings.appearance.density.default": "Default",
"settings.appearance.density.comfortable": "Comfortable",
"settings.notifications.unreadBadge.title": "Unread badge",
"settings.notifications.unreadBadge.description": "Show unread session indicator badge on the app icon",
"settings.notifications.unreadBadge.count": "Count",
"settings.notifications.unreadBadge.dot": "Dot",
"settings.notifications.unreadBadge.none": "None",
"settings.notifications.focusMode.title": "Focus mode",
"settings.notifications.focusMode.description": "Suppress desktop notifications while presenting or in fullscreen",
"settings.notifications.focusMode.auto": "Auto",
"settings.notifications.focusMode.always": "Always",
"settings.notifications.focusMode.never": "Never",
"settings.projects.title": "Projects",
"settings.projects.description": "View and configure projects on this server",
"settings.projects.empty": "No projects found",
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
"settings.extensions.availableAll": "Available to all projects",
"settings.extensions.manageConfig": "Manage in opencode.json",
"settings.extensions.addSkills": "How to add skills",
} satisfies Partial<Record<Keys, string>>

View file

@ -1021,4 +1021,48 @@ export const dict = {
"error.childStore.persistedProjectIconCreateFailed": "Nie udało się utworzyć trwałej ikony projektu",
"error.childStore.storeCreateFailed": "Nie udało się utworzyć magazynu",
"terminal.connectionLost.abnormalClose": "WebSocket zamknięty nieprawidłowo: {{code}}",
"command.session.export": "Export session",
"command.session.export.description": "Export the full session transcript as JSON",
"context.export.session": "Export session",
"toast.session.export.success.title": "Session exported",
"toast.session.export.success.description": "Saved session to {{filename}}",
"toast.session.export.failed.title": "Failed to export session",
"toast.session.export.failed.description": "An error occurred while exporting the session",
"common.export": "Export",
"settings.tab.appearance": "Appearance",
"settings.tab.notifications": "Notifications",
"settings.tab.providers": "Providers",
"settings.tab.models": "Models",
"settings.tab.servers": "Servers",
"settings.tab.projects": "Projects",
"settings.tab.extensions": "Extensions",
"settings.tab.mcps": "MCPs",
"settings.tab.plugins": "Plugins",
"settings.tab.skills": "Skills",
"settings.server.all": "All servers",
"settings.action.restoreDefaults": "Restore defaults",
"settings.action.resetAll": "Reset all settings",
"settings.action.resetAll.description": "Revert all settings and preferences back to default values",
"settings.appearance.density.title": "Interface density",
"settings.appearance.density.description": "Adjust padding and spacing across the application",
"settings.appearance.density.compact": "Compact",
"settings.appearance.density.default": "Default",
"settings.appearance.density.comfortable": "Comfortable",
"settings.notifications.unreadBadge.title": "Unread badge",
"settings.notifications.unreadBadge.description": "Show unread session indicator badge on the app icon",
"settings.notifications.unreadBadge.count": "Count",
"settings.notifications.unreadBadge.dot": "Dot",
"settings.notifications.unreadBadge.none": "None",
"settings.notifications.focusMode.title": "Focus mode",
"settings.notifications.focusMode.description": "Suppress desktop notifications while presenting or in fullscreen",
"settings.notifications.focusMode.auto": "Auto",
"settings.notifications.focusMode.always": "Always",
"settings.notifications.focusMode.never": "Never",
"settings.projects.title": "Projects",
"settings.projects.description": "View and configure projects on this server",
"settings.projects.empty": "No projects found",
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
"settings.extensions.availableAll": "Available to all projects",
"settings.extensions.manageConfig": "Manage in opencode.json",
"settings.extensions.addSkills": "How to add skills",
}

View file

@ -1100,4 +1100,48 @@ export const dict = {
"error.childStore.persistedProjectIconCreateFailed": "Не удалось создать постоянный значок проекта",
"error.childStore.storeCreateFailed": "Не удалось создать хранилище",
"terminal.connectionLost.abnormalClose": "WebSocket закрыт аварийно: {{code}}",
"command.session.export": "Export session",
"command.session.export.description": "Export the full session transcript as JSON",
"context.export.session": "Export session",
"toast.session.export.success.title": "Session exported",
"toast.session.export.success.description": "Saved session to {{filename}}",
"toast.session.export.failed.title": "Failed to export session",
"toast.session.export.failed.description": "An error occurred while exporting the session",
"common.export": "Export",
"settings.tab.appearance": "Appearance",
"settings.tab.notifications": "Notifications",
"settings.tab.providers": "Providers",
"settings.tab.models": "Models",
"settings.tab.servers": "Servers",
"settings.tab.projects": "Projects",
"settings.tab.extensions": "Extensions",
"settings.tab.mcps": "MCPs",
"settings.tab.plugins": "Plugins",
"settings.tab.skills": "Skills",
"settings.server.all": "All servers",
"settings.action.restoreDefaults": "Restore defaults",
"settings.action.resetAll": "Reset all settings",
"settings.action.resetAll.description": "Revert all settings and preferences back to default values",
"settings.appearance.density.title": "Interface density",
"settings.appearance.density.description": "Adjust padding and spacing across the application",
"settings.appearance.density.compact": "Compact",
"settings.appearance.density.default": "Default",
"settings.appearance.density.comfortable": "Comfortable",
"settings.notifications.unreadBadge.title": "Unread badge",
"settings.notifications.unreadBadge.description": "Show unread session indicator badge on the app icon",
"settings.notifications.unreadBadge.count": "Count",
"settings.notifications.unreadBadge.dot": "Dot",
"settings.notifications.unreadBadge.none": "None",
"settings.notifications.focusMode.title": "Focus mode",
"settings.notifications.focusMode.description": "Suppress desktop notifications while presenting or in fullscreen",
"settings.notifications.focusMode.auto": "Auto",
"settings.notifications.focusMode.always": "Always",
"settings.notifications.focusMode.never": "Never",
"settings.projects.title": "Projects",
"settings.projects.description": "View and configure projects on this server",
"settings.projects.empty": "No projects found",
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
"settings.extensions.availableAll": "Available to all projects",
"settings.extensions.manageConfig": "Manage in opencode.json",
"settings.extensions.addSkills": "How to add skills",
}

View file

@ -1084,4 +1084,48 @@ export const dict = {
"error.childStore.persistedProjectIconCreateFailed": "ไม่สามารถสร้างไอคอนโปรเจกต์ถาวร",
"error.childStore.storeCreateFailed": "ไม่สามารถสร้างที่เก็บ",
"terminal.connectionLost.abnormalClose": "WebSocket ปิดอย่างผิดปกติ: {{code}}",
"command.session.export": "Export session",
"command.session.export.description": "Export the full session transcript as JSON",
"context.export.session": "Export session",
"toast.session.export.success.title": "Session exported",
"toast.session.export.success.description": "Saved session to {{filename}}",
"toast.session.export.failed.title": "Failed to export session",
"toast.session.export.failed.description": "An error occurred while exporting the session",
"common.export": "Export",
"settings.tab.appearance": "Appearance",
"settings.tab.notifications": "Notifications",
"settings.tab.providers": "Providers",
"settings.tab.models": "Models",
"settings.tab.servers": "Servers",
"settings.tab.projects": "Projects",
"settings.tab.extensions": "Extensions",
"settings.tab.mcps": "MCPs",
"settings.tab.plugins": "Plugins",
"settings.tab.skills": "Skills",
"settings.server.all": "All servers",
"settings.action.restoreDefaults": "Restore defaults",
"settings.action.resetAll": "Reset all settings",
"settings.action.resetAll.description": "Revert all settings and preferences back to default values",
"settings.appearance.density.title": "Interface density",
"settings.appearance.density.description": "Adjust padding and spacing across the application",
"settings.appearance.density.compact": "Compact",
"settings.appearance.density.default": "Default",
"settings.appearance.density.comfortable": "Comfortable",
"settings.notifications.unreadBadge.title": "Unread badge",
"settings.notifications.unreadBadge.description": "Show unread session indicator badge on the app icon",
"settings.notifications.unreadBadge.count": "Count",
"settings.notifications.unreadBadge.dot": "Dot",
"settings.notifications.unreadBadge.none": "None",
"settings.notifications.focusMode.title": "Focus mode",
"settings.notifications.focusMode.description": "Suppress desktop notifications while presenting or in fullscreen",
"settings.notifications.focusMode.auto": "Auto",
"settings.notifications.focusMode.always": "Always",
"settings.notifications.focusMode.never": "Never",
"settings.projects.title": "Projects",
"settings.projects.description": "View and configure projects on this server",
"settings.projects.empty": "No projects found",
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
"settings.extensions.availableAll": "Available to all projects",
"settings.extensions.manageConfig": "Manage in opencode.json",
"settings.extensions.addSkills": "How to add skills",
}

View file

@ -1103,4 +1103,48 @@ export const dict = {
"error.childStore.persistedProjectIconCreateFailed": "Kalıcı proje simgesi oluşturulamadı",
"error.childStore.storeCreateFailed": "Depo oluşturulamadı",
"terminal.connectionLost.abnormalClose": "WebSocket anormal şekilde kapandı: {{code}}",
"command.session.export": "Export session",
"command.session.export.description": "Export the full session transcript as JSON",
"context.export.session": "Export session",
"toast.session.export.success.title": "Session exported",
"toast.session.export.success.description": "Saved session to {{filename}}",
"toast.session.export.failed.title": "Failed to export session",
"toast.session.export.failed.description": "An error occurred while exporting the session",
"common.export": "Export",
"settings.tab.appearance": "Appearance",
"settings.tab.notifications": "Notifications",
"settings.tab.providers": "Providers",
"settings.tab.models": "Models",
"settings.tab.servers": "Servers",
"settings.tab.projects": "Projects",
"settings.tab.extensions": "Extensions",
"settings.tab.mcps": "MCPs",
"settings.tab.plugins": "Plugins",
"settings.tab.skills": "Skills",
"settings.server.all": "All servers",
"settings.action.restoreDefaults": "Restore defaults",
"settings.action.resetAll": "Reset all settings",
"settings.action.resetAll.description": "Revert all settings and preferences back to default values",
"settings.appearance.density.title": "Interface density",
"settings.appearance.density.description": "Adjust padding and spacing across the application",
"settings.appearance.density.compact": "Compact",
"settings.appearance.density.default": "Default",
"settings.appearance.density.comfortable": "Comfortable",
"settings.notifications.unreadBadge.title": "Unread badge",
"settings.notifications.unreadBadge.description": "Show unread session indicator badge on the app icon",
"settings.notifications.unreadBadge.count": "Count",
"settings.notifications.unreadBadge.dot": "Dot",
"settings.notifications.unreadBadge.none": "None",
"settings.notifications.focusMode.title": "Focus mode",
"settings.notifications.focusMode.description": "Suppress desktop notifications while presenting or in fullscreen",
"settings.notifications.focusMode.auto": "Auto",
"settings.notifications.focusMode.always": "Always",
"settings.notifications.focusMode.never": "Never",
"settings.projects.title": "Projects",
"settings.projects.description": "View and configure projects on this server",
"settings.projects.empty": "No projects found",
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
"settings.extensions.availableAll": "Available to all projects",
"settings.extensions.manageConfig": "Manage in opencode.json",
"settings.extensions.addSkills": "How to add skills",
} satisfies Partial<Record<Keys, string>>

View file

@ -1102,4 +1102,48 @@ export const dict = {
"workspace.reset.archived.one": "1 сесію буде заархівовано.",
"workspace.reset.archived.many": "{{count}} сесій буде заархівовано.",
"workspace.reset.note": "Це скине робочу область, щоб вона відповідала гілці за замовчуванням.",
"command.session.export": "Export session",
"command.session.export.description": "Export the full session transcript as JSON",
"context.export.session": "Export session",
"toast.session.export.success.title": "Session exported",
"toast.session.export.success.description": "Saved session to {{filename}}",
"toast.session.export.failed.title": "Failed to export session",
"toast.session.export.failed.description": "An error occurred while exporting the session",
"common.export": "Export",
"settings.tab.appearance": "Appearance",
"settings.tab.notifications": "Notifications",
"settings.tab.providers": "Providers",
"settings.tab.models": "Models",
"settings.tab.servers": "Servers",
"settings.tab.projects": "Projects",
"settings.tab.extensions": "Extensions",
"settings.tab.mcps": "MCPs",
"settings.tab.plugins": "Plugins",
"settings.tab.skills": "Skills",
"settings.server.all": "All servers",
"settings.action.restoreDefaults": "Restore defaults",
"settings.action.resetAll": "Reset all settings",
"settings.action.resetAll.description": "Revert all settings and preferences back to default values",
"settings.appearance.density.title": "Interface density",
"settings.appearance.density.description": "Adjust padding and spacing across the application",
"settings.appearance.density.compact": "Compact",
"settings.appearance.density.default": "Default",
"settings.appearance.density.comfortable": "Comfortable",
"settings.notifications.unreadBadge.title": "Unread badge",
"settings.notifications.unreadBadge.description": "Show unread session indicator badge on the app icon",
"settings.notifications.unreadBadge.count": "Count",
"settings.notifications.unreadBadge.dot": "Dot",
"settings.notifications.unreadBadge.none": "None",
"settings.notifications.focusMode.title": "Focus mode",
"settings.notifications.focusMode.description": "Suppress desktop notifications while presenting or in fullscreen",
"settings.notifications.focusMode.auto": "Auto",
"settings.notifications.focusMode.always": "Always",
"settings.notifications.focusMode.never": "Never",
"settings.projects.title": "Projects",
"settings.projects.description": "View and configure projects on this server",
"settings.projects.empty": "No projects found",
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
"settings.extensions.availableAll": "Available to all projects",
"settings.extensions.manageConfig": "Manage in opencode.json",
"settings.extensions.addSkills": "How to add skills",
}

View file

@ -1075,4 +1075,48 @@ export const dict = {
"error.childStore.persistedProjectIconCreateFailed": "创建持久化项目图标失败",
"error.childStore.storeCreateFailed": "创建存储失败",
"terminal.connectionLost.abnormalClose": "WebSocket 异常关闭:{{code}}",
"command.session.export": "Export session",
"command.session.export.description": "Export the full session transcript as JSON",
"context.export.session": "Export session",
"toast.session.export.success.title": "Session exported",
"toast.session.export.success.description": "Saved session to {{filename}}",
"toast.session.export.failed.title": "Failed to export session",
"toast.session.export.failed.description": "An error occurred while exporting the session",
"common.export": "Export",
"settings.tab.appearance": "Appearance",
"settings.tab.notifications": "Notifications",
"settings.tab.providers": "Providers",
"settings.tab.models": "Models",
"settings.tab.servers": "Servers",
"settings.tab.projects": "Projects",
"settings.tab.extensions": "Extensions",
"settings.tab.mcps": "MCPs",
"settings.tab.plugins": "Plugins",
"settings.tab.skills": "Skills",
"settings.server.all": "All servers",
"settings.action.restoreDefaults": "Restore defaults",
"settings.action.resetAll": "Reset all settings",
"settings.action.resetAll.description": "Revert all settings and preferences back to default values",
"settings.appearance.density.title": "Interface density",
"settings.appearance.density.description": "Adjust padding and spacing across the application",
"settings.appearance.density.compact": "Compact",
"settings.appearance.density.default": "Default",
"settings.appearance.density.comfortable": "Comfortable",
"settings.notifications.unreadBadge.title": "Unread badge",
"settings.notifications.unreadBadge.description": "Show unread session indicator badge on the app icon",
"settings.notifications.unreadBadge.count": "Count",
"settings.notifications.unreadBadge.dot": "Dot",
"settings.notifications.unreadBadge.none": "None",
"settings.notifications.focusMode.title": "Focus mode",
"settings.notifications.focusMode.description": "Suppress desktop notifications while presenting or in fullscreen",
"settings.notifications.focusMode.auto": "Auto",
"settings.notifications.focusMode.always": "Always",
"settings.notifications.focusMode.never": "Never",
"settings.projects.title": "Projects",
"settings.projects.description": "View and configure projects on this server",
"settings.projects.empty": "No projects found",
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
"settings.extensions.availableAll": "Available to all projects",
"settings.extensions.manageConfig": "Manage in opencode.json",
"settings.extensions.addSkills": "How to add skills",
} satisfies Partial<Record<Keys, string>>

View file

@ -1071,4 +1071,48 @@ export const dict = {
"error.childStore.persistedProjectIconCreateFailed": "建立持續性專案圖示失敗",
"error.childStore.storeCreateFailed": "建立儲存區失敗",
"terminal.connectionLost.abnormalClose": "WebSocket 異常關閉:{{code}}",
"command.session.export": "Export session",
"command.session.export.description": "Export the full session transcript as JSON",
"context.export.session": "Export session",
"toast.session.export.success.title": "Session exported",
"toast.session.export.success.description": "Saved session to {{filename}}",
"toast.session.export.failed.title": "Failed to export session",
"toast.session.export.failed.description": "An error occurred while exporting the session",
"common.export": "Export",
"settings.tab.appearance": "Appearance",
"settings.tab.notifications": "Notifications",
"settings.tab.providers": "Providers",
"settings.tab.models": "Models",
"settings.tab.servers": "Servers",
"settings.tab.projects": "Projects",
"settings.tab.extensions": "Extensions",
"settings.tab.mcps": "MCPs",
"settings.tab.plugins": "Plugins",
"settings.tab.skills": "Skills",
"settings.server.all": "All servers",
"settings.action.restoreDefaults": "Restore defaults",
"settings.action.resetAll": "Reset all settings",
"settings.action.resetAll.description": "Revert all settings and preferences back to default values",
"settings.appearance.density.title": "Interface density",
"settings.appearance.density.description": "Adjust padding and spacing across the application",
"settings.appearance.density.compact": "Compact",
"settings.appearance.density.default": "Default",
"settings.appearance.density.comfortable": "Comfortable",
"settings.notifications.unreadBadge.title": "Unread badge",
"settings.notifications.unreadBadge.description": "Show unread session indicator badge on the app icon",
"settings.notifications.unreadBadge.count": "Count",
"settings.notifications.unreadBadge.dot": "Dot",
"settings.notifications.unreadBadge.none": "None",
"settings.notifications.focusMode.title": "Focus mode",
"settings.notifications.focusMode.description": "Suppress desktop notifications while presenting or in fullscreen",
"settings.notifications.focusMode.auto": "Auto",
"settings.notifications.focusMode.always": "Always",
"settings.notifications.focusMode.never": "Never",
"settings.projects.title": "Projects",
"settings.projects.description": "View and configure projects on this server",
"settings.projects.empty": "No projects found",
"settings.mcps.description": "Manage Model Context Protocol (MCP) servers and tools",
"settings.extensions.availableAll": "Available to all projects",
"settings.extensions.manageConfig": "Manage in opencode.json",
"settings.extensions.addSkills": "How to add skills",
} satisfies Partial<Record<Keys, string>>

View file

@ -145,16 +145,14 @@ export function WslServerSettings(props: {
{language.t("wsl.server.retryStart")}
</MenuV2.Item>
</Show>
<Show when={props.controller.canDefault() && props.controller.defaultKey() !== key}>
<MenuV2.Item onSelect={() => props.controller.setDefault(key)}>
<Show when={props.controller.canDefault()}>
<MenuV2.Item
disabled={props.controller.defaultKey() === key}
onSelect={() => props.controller.setDefault(key)}
>
{language.t("dialog.server.menu.default")}
</MenuV2.Item>
</Show>
<Show when={props.controller.canDefault() && props.controller.defaultKey() === key}>
<MenuV2.Item onSelect={() => props.controller.setDefault(null)}>
{language.t("dialog.server.menu.defaultRemove")}
</MenuV2.Item>
</Show>
<MenuV2.Separator />
<MenuV2.Item onSelect={() => remove(key)}>
{language.t("dialog.server.menu.delete")}

View file

@ -103,6 +103,11 @@ const icons = {
link: `<path d="M2.08334 12.0833L1.72979 11.7298L1.37624 12.0833L1.72979 12.4369L2.08334 12.0833ZM7.91668 17.9167L7.56312 18.2702L7.91668 18.6238L8.27023 18.2702L7.91668 17.9167ZM17.9167 7.91666L18.2702 8.27022L18.6238 7.91666L18.2702 7.56311L17.9167 7.91666ZM12.0833 2.08333L12.4369 1.72977L12.0833 1.37622L11.7298 1.72977L12.0833 2.08333ZM8.39646 5.06311L8.0429 5.41666L8.75001 6.12377L9.10356 5.77021L8.75001 5.41666L8.39646 5.06311ZM5.77023 9.10355L6.12378 8.74999L5.41668 8.04289L5.06312 8.39644L5.41668 8.74999L5.77023 9.10355ZM14.2298 10.8964L13.8762 11.25L14.5833 11.9571L14.9369 11.6035L14.5833 11.25L14.2298 10.8964ZM11.6036 14.9369L11.9571 14.5833L11.25 13.8762L10.8965 14.2298L11.25 14.5833L11.6036 14.9369ZM7.14646 12.1464L6.7929 12.5L7.50001 13.2071L7.85356 12.8535L7.50001 12.5L7.14646 12.1464ZM12.8536 7.85355L13.2071 7.49999L12.5 6.79289L12.1465 7.14644L12.5 7.49999L12.8536 7.85355ZM2.08334 12.0833L1.72979 12.4369L7.56312 18.2702L7.91668 17.9167L8.27023 17.5631L2.4369 11.7298L2.08334 12.0833ZM17.9167 7.91666L18.2702 7.56311L12.4369 1.72977L12.0833 2.08333L11.7298 2.43688L17.5631 8.27022L17.9167 7.91666ZM12.0833 2.08333L11.7298 1.72977L8.39646 5.06311L8.75001 5.41666L9.10356 5.77021L12.4369 2.43688L12.0833 2.08333ZM5.41668 8.74999L5.06312 8.39644L1.72979 11.7298L2.08334 12.0833L2.4369 12.4369L5.77023 9.10355L5.41668 8.74999ZM14.5833 11.25L14.9369 11.6035L18.2702 8.27022L17.9167 7.91666L17.5631 7.56311L14.2298 10.8964L14.5833 11.25ZM7.91668 17.9167L8.27023 18.2702L11.6036 14.9369L11.25 14.5833L10.8965 14.2298L7.56312 17.5631L7.91668 17.9167ZM7.50001 12.5L7.85356 12.8535L12.8536 7.85355L12.5 7.49999L12.1465 7.14644L7.14646 12.1464L7.50001 12.5Z" fill="currentColor"/>`,
providers: `<path d="M10.0001 4.37562V2.875M13 4.37793V2.87793M7.00014 4.37793V2.875M10 17.1279V15.6279M13 17.1279V15.6279M7 17.1279V15.6279M15.625 13.0029H17.125M15.625 7.00293H17.125M15.625 10.0029H17.125M2.875 10.0029H4.375M2.875 13.0029H4.375M2.875 7.00293H4.375M4.375 4.37793H15.625V15.6279H4.375V4.37793ZM12.6241 10.0022C12.6241 11.4519 11.4488 12.6272 9.99908 12.6272C8.54934 12.6272 7.37408 11.4519 7.37408 10.0022C7.37408 8.55245 8.54934 7.3772 9.99908 7.3772C11.4488 7.3772 12.6241 8.55245 12.6241 10.0022Z" stroke="currentColor" stroke-linecap="square"/>`,
models: `<path fill-rule="evenodd" clip-rule="evenodd" d="M17.5 10C12.2917 10 10 12.2917 10 17.5C10 12.2917 7.70833 10 2.5 10C7.70833 10 10 7.70833 10 2.5C10 7.70833 12.2917 10 17.5 10Z" stroke="currentColor"/>`,
appearance: `<path d="M2.707 14.707L14.707 2.707M2.707 9.06L9.06 2.707M2.707 3.413L3.413 2.707M8.354 14.707L14.707 8.354M14.000 14.706L14.706 14.000" stroke="currentColor" stroke-linecap="square"/>`,
notifications: `<path d="M15.389 7.278V9.611C15.389 10.593 15.389 11.389 15.389 11.389H11.833M6.056 11.389H2.5C2.5 11.389 2.5 10.593 2.5 9.611V4.278C2.5 3.296 2.5 2.5 2.5 2.5H9.945M6.056 11.389V13.611H8.944H11.833V11.389M6.056 11.389H11.833" stroke="currentColor"/><circle cx="14.5" cy="4.5" r="2" stroke="currentColor" fill="currentColor"/>`,
extensions: `<path d="M9.166 6.805V9.305M11.834 6.805V9.305M6.5 6.805V9.305M2.5 2.5V13.61H15.833V2.5H2.5Z" stroke="currentColor" stroke-linecap="square"/>`,
cube: `<path d="M10 2.5L16.5 6.25V13.75L10 17.5L3.5 13.75V6.25L10 2.5Z" stroke="currentColor"/><path d="M10 10L16.5 6.25M10 10V17.5M10 10L3.5 6.25" stroke="currentColor"/>`,
"post-skill": `<rect x="2.5" y="3.5" width="15" height="13" rx="1.5" stroke="currentColor"/><path d="M5.5 7.5H10.5M5.5 10.5H14.5" stroke="currentColor"/>`,
"arrow-undo-down": `<path d="M4.08333 11.0859L1.75 8.7526L4.08333 6.41927M2.33333 8.7526L12.5417 8.7526L12.5417 3.21094L7 3.21094" stroke="currentColor" stroke-width="1" stroke-linecap="square"/>`,
}