From 9ecf46bfea75fec98e2bfaebc466a61c4418f0e4 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Fri, 7 Aug 2026 19:27:49 +1000 Subject: [PATCH] feat(app): align settings with project scopes --- .../src/components/dialog-edit-project-v2.css | 238 +++++++++++++ .../src/components/dialog-edit-project-v2.tsx | 325 +++++++++++------- .../project-settings-extensions.tsx | 240 +++++++++++++ .../src/components/server/server-row-menu.tsx | 15 +- .../app/src/components/settings-keybinds.tsx | 5 +- .../src/components/settings-server-picker.tsx | 86 +---- .../src/components/settings-v2/appearance.tsx | 40 +-- .../src/components/settings-v2/extensions.tsx | 13 +- .../src/components/settings-v2/general.tsx | 18 +- .../app/src/components/settings-v2/models.tsx | 5 +- .../components/settings-v2/notifications.tsx | 8 +- .../settings-v2/parts/server-select.tsx | 40 ++- .../src/components/settings-v2/projects.tsx | 137 +++++--- .../src/components/settings-v2/providers.tsx | 5 +- .../src/components/settings-v2/servers.tsx | 14 +- .../components/settings-v2/settings-v2.css | 14 +- packages/app/src/i18n/en.ts | 29 +- packages/app/src/i18n/parity.test.ts | 21 ++ .../pages/home/home-projects-controller.tsx | 2 +- .../app/src/pages/home/home-projects-view.tsx | 2 +- packages/app/src/wsl/settings.tsx | 4 + 21 files changed, 917 insertions(+), 344 deletions(-) create mode 100644 packages/app/src/components/dialog-edit-project-v2.css create mode 100644 packages/app/src/components/project-settings-extensions.tsx diff --git a/packages/app/src/components/dialog-edit-project-v2.css b/packages/app/src/components/dialog-edit-project-v2.css new file mode 100644 index 0000000000..e52dc7e012 --- /dev/null +++ b/packages/app/src/components/dialog-edit-project-v2.css @@ -0,0 +1,238 @@ +.project-settings-v2-dialog [data-slot="dialog-container"] { + background: var(--v2-background-bg-base); +} + +.project-settings-v2-dialog [data-slot="dialog-body"] { + padding: 0; + overflow: hidden; +} + +.project-settings-v2 { + height: 100%; +} + +.project-settings-v2-nav { + display: flex; + flex-direction: column; + gap: 4px; + width: 100%; +} + +.project-settings-v2-panel { + display: flex; + flex-direction: column; + height: 100%; + min-width: 0; + overflow: hidden !important; + user-select: none; +} + +.project-settings-v2-panel :is(input, textarea, [contenteditable="true"]) { + user-select: text; +} + +.project-settings-v2-form { + display: flex; + flex-direction: column; + height: 100%; + min-height: 0; +} + +.project-settings-v2-scroll { + display: flex; + flex: 1; + flex-direction: column; + gap: 24px; + min-height: 0; + padding: 40px; + overflow-y: auto; +} + +.project-settings-page-header { + display: flex; + flex-direction: column; + gap: 6px; +} + +.project-settings-page-header h2 { + color: var(--v2-text-text-base); + font-size: 15px; + font-weight: 640; + line-height: 1; +} + +.project-settings-page-header > span { + color: var(--v2-text-text-muted); + font-size: 11px; + font-weight: 440; + line-height: 1; +} + +.project-settings-extensions { + display: flex; + flex-direction: column; + height: 100%; + min-height: 0; + padding: 40px; +} + +.project-settings-extension-tabs { + flex: 1; + height: auto; + min-height: 0; + margin-top: 24px; + overflow: visible; +} + +.project-settings-extension-tabs[data-component="tabs-v2"][data-variant="pill"] > [data-slot="tabs-v2-list"] { + width: auto; + padding-inline: 0 !important; +} + +.project-settings-extension-tabs[data-component="tabs-v2"][data-variant="pill"] > [data-slot="tabs-v2-list"]::before { + display: none; +} + +.project-settings-extension-tabs[data-component="tabs-v2"][data-variant="pill"] + > [data-slot="tabs-v2-list"] + [data-slot="tabs-v2-trigger-wrapper"] { + border-radius: 6px; +} + +.project-settings-extension-tabs[data-component="tabs-v2"][data-variant="pill"] + > [data-slot="tabs-v2-list"] + [data-slot="tabs-v2-trigger"] { + padding-inline: 8px; +} + +.project-settings-extension-tabs [data-slot="tabs-v2-content"] { + overflow-y: auto; +} + +.project-settings-extension-section { + display: flex; + flex-direction: column; + gap: 16px; + padding-top: 20px; +} + +.project-settings-extension-section-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + color: var(--v2-text-text-base); + font-size: 13px; + font-weight: 530; + line-height: 1; +} + +.project-settings-extension-section-header > :last-child { + color: var(--v2-text-text-faint); + font-size: 11px; + font-weight: 440; +} + +.project-settings-extension-link { + color: var(--v2-text-text-accent) !important; + text-decoration: none; +} + +.project-settings-extension-link:hover { + text-decoration: underline; +} + +.project-settings-extension-card { + padding-inline: 12px; + overflow: hidden; + border: 0.5px solid var(--v2-border-border-base); + border-radius: 8px; + background: var(--v2-background-bg-base); +} + +.project-settings-extension-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + min-height: 48px; + border-bottom: 0.5px solid var(--v2-border-border-base); +} + +.project-settings-extension-row:last-child { + border-bottom: 0; +} + +.project-settings-extension-row-main { + display: flex; + flex: 1; + align-items: center; + gap: 10px; + min-width: 0; +} + +.project-settings-extension-row-icon { + flex-shrink: 0; + color: var(--v2-icon-icon-muted); +} + +.project-settings-extension-row-name { + min-width: 0; + overflow: hidden; + color: var(--v2-text-text-base); + font-size: 13px; + font-weight: 530; + text-overflow: ellipsis; + white-space: nowrap; +} + +.project-settings-extension-row-status { + display: flex; + align-items: center; + gap: 6px; + flex-shrink: 0; + color: var(--v2-text-text-muted); + font-size: 11px; +} + +.project-settings-extension-row-status-dot { + width: 5px; + height: 5px; + border-radius: 50%; + background: var(--v2-state-fg-warning); +} + +.project-settings-shared { + display: flex; + flex-direction: column; + gap: 12px; +} + +.project-settings-shared-trigger { + display: flex; + align-items: center; + align-self: flex-start; + gap: 6px; + color: var(--v2-text-text-base); + font-size: 11px; + font-weight: 530; +} + +.project-settings-shared-chevron { + width: 12px; + height: 12px; + color: var(--v2-icon-icon-muted); + transition: transform 120ms ease; +} + +.project-settings-shared-chevron.open { + transform: rotate(90deg); +} + +.project-settings-shared-count { + padding: 1px 4px; + border-radius: 3px; + background: var(--v2-background-bg-layer-02); + color: var(--v2-text-text-muted); + font-size: 9px; +} diff --git a/packages/app/src/components/dialog-edit-project-v2.tsx b/packages/app/src/components/dialog-edit-project-v2.tsx index 77adec7b1c..cfed789c79 100644 --- a/packages/app/src/components/dialog-edit-project-v2.tsx +++ b/packages/app/src/components/dialog-edit-project-v2.tsx @@ -1,156 +1,223 @@ import { ButtonV2 } from "@opencode-ai/ui/v2/button-v2" -import { Dialog, DialogBody, DialogFooter, DialogHeader, DialogTitle } from "@opencode-ai/ui/v2/dialog-v2" -import { DividerV2 } from "@opencode-ai/ui/v2/divider-v2" +import { Dialog, DialogFooter } from "@opencode-ai/ui/v2/dialog-v2" import { Field } from "@opencode-ai/ui/v2/field-v2" -import { Icon } from "@opencode-ai/ui/v2/icon" +import { Icon as IconV2 } from "@opencode-ai/ui/v2/icon" +import { Icon } from "@opencode-ai/ui/icon" import { ProjectAvatar, PROJECT_AVATAR_VARIANTS } from "@opencode-ai/ui/v2/project-avatar-v2" +import { TabsV2 } from "@opencode-ai/ui/v2/tabs-v2" import { TextareaV2 } from "@opencode-ai/ui/v2/textarea-v2" import { TextInputV2 } from "@opencode-ai/ui/v2/text-input-v2" -import { For, Show } from "solid-js" +import { For, Show, createSignal, startTransition } from "solid-js" import { useLanguage } from "@/context/language" import { getProjectAvatarVariant, type LocalProject } from "@/context/layout" +import { SDKProvider } from "@/context/sdk" import { ServerConnection } from "@/context/server" -import { getProjectAvatarSource } from "@/pages/layout/helpers" +import { displayName, getProjectAvatarSource } from "@/pages/layout/helpers" import { createEditProjectModel } from "./edit-project" +import { ProjectSettingsExtensions } from "./project-settings-extensions" +import { SettingsServerDataScope } from "./settings-server-picker" +import "./settings-v2/settings-v2.css" +import "./dialog-edit-project-v2.css" export function DialogEditProjectV2(props: { project: LocalProject; server: ServerConnection.Any }) { + return ( + + + + + + ) +} + +function ProjectSettingsDialog(props: { project: LocalProject; server: ServerConnection.Any }) { const language = useLanguage() const model = createEditProjectModel(props) + const projectName = () => displayName(props.project) + const [tab, setTab] = createSignal("general") + + const Footer = () => ( + + + {language.t("common.cancel")} + + + {model.save.isPending ? language.t("common.saving") : language.t("common.save")} + + + ) return ( - -
- - {language.t("dialog.project.edit.title")} - - - - - {language.t("dialog.project.edit.name")} - model.setStore("name", event.currentTarget.value)} - /> - - -
-
- {language.t("dialog.project.edit.icon")} -
-
- - { - model.setIconInput(element) - }} - type="file" - accept="image/*" - class="hidden" - onChange={model.inputChange} + + void startTransition(() => setTab(value))} + class="project-settings-v2" + > + +
+ + -
- {language.t("dialog.project.edit.icon.hint")} - {language.t("dialog.project.edit.icon.recommended")} -
-
+ {projectName()} + + + + {language.t("project.settings.scripts")} + + + + {language.t("settings.tab.extensions")} +
+ - -
-
- {language.t("dialog.project.edit.color")} + + +
+
+

{language.t("dialog.project.edit.title")}

+ {language.t("project.settings.general.description")}
-
- - {(color) => ( - - )} - + + + + model.setIconInput(element)} + type="file" + accept="image/*" + class="hidden" + onChange={model.inputChange} + /> +
+ {language.t("dialog.project.edit.icon.hint")} + {language.t("dialog.project.edit.icon.recommended")} +
+
-
- - - {language.t("dialog.project.edit.worktree.startup")} - {language.t("dialog.project.edit.worktree.startup.description")} - model.setStore("startup", event.currentTarget.value)} - /> - - - - - {language.t("common.cancel")} - - - {model.save.isPending ? language.t("common.saving") : language.t("common.save")} - - - + +
+
+ {language.t("dialog.project.edit.color")} +
+
+ + {(color) => ( + + )} + +
+
+
+
+
) } diff --git a/packages/app/src/components/project-settings-extensions.tsx b/packages/app/src/components/project-settings-extensions.tsx new file mode 100644 index 0000000000..9505c71d6a --- /dev/null +++ b/packages/app/src/components/project-settings-extensions.tsx @@ -0,0 +1,240 @@ +import { Icon } from "@opencode-ai/ui/icon" +import { Switch } from "@opencode-ai/ui/v2/switch-v2" +import { TabsV2 } from "@opencode-ai/ui/v2/tabs-v2" +import { type Component, For, Show, createMemo, createResource, createSignal } from "solid-js" +import { useLanguage } from "@/context/language" +import { useMcpToggle } from "@/context/mcp" +import { useSDK } from "@/context/sdk" +import { useServerSDK } from "@/context/server-sdk" +import { useServerSync } from "@/context/server-sync" +import { useSync } from "@/context/sync" +import { ExternalLink } from "./external-link" + +type SkillItem = { + name: string + location: string +} + +const pluginName = (item: string | [string, Record]) => (typeof item === "string" ? item : item[0]) +const skillKey = (item: SkillItem) => `${item.name}\n${item.location}` + +const ExtensionCard: Component<{ children: unknown }> = (props) => ( +
{props.children as any}
+) + +const ExtensionRow: Component<{ + icon: "mcp" | "cube" | "post-skill" | "code" + name: string + status?: string + children?: unknown +}> = (props) => ( +
+
+ + {props.name} +
+ + {(status) => ( + + + {status()} + + )} + + {props.children as any} +
+) + +const SharedSection: Component<{ + count: number + children: unknown +}> = (props) => { + const language = useLanguage() + const [open, setOpen] = createSignal(false) + return ( + 0}> +
+ + + {props.children} + +
+
+ ) +} + +export const ProjectSettingsExtensions: Component = () => { + const language = useLanguage() + const serverSDK = useServerSDK() + const directorySDK = useSDK() + const serverSync = useServerSync() + const sync = useSync() + const toggleMcp = useMcpToggle() + + const [serverMcp] = createResource( + serverSDK, + (sdk) => + sdk.api.mcp + .list() + .then((result) => Object.fromEntries(result.data.map((server) => [server.name, server.status]))) + .catch(() => ({})), + { initialValue: {} }, + ) + const globalMcpNames = createMemo(() => + [...new Set([...Object.keys(serverSync().data.config.mcp ?? {}), ...Object.keys(serverMcp.latest)])].sort(), + ) + const projectMcpNames = createMemo(() => { + const shared = new Set(globalMcpNames()) + const configured = Object.keys(sync().data.config.mcp ?? {}).filter((name) => !shared.has(name)) + if (configured.length > 0) return configured.sort() + return Object.keys(sync().data.mcp ?? {}) + .filter((name) => !shared.has(name)) + .sort() + }) + const mcpEnabled = (name: string) => sync().data.mcp?.[name]?.status === "connected" + + const globalPlugins = createMemo(() => (serverSync().data.config.plugin ?? []).map(pluginName)) + const projectPlugins = createMemo(() => { + const shared = new Set(globalPlugins()) + return (sync().data.config.plugin ?? []).map(pluginName).filter((name) => !shared.has(name)) + }) + + const [serverSkills] = createResource( + serverSDK, + (sdk): Promise => + sdk.api.skill + .list() + .then((result) => result.data.map((item) => ({ name: item.name, location: item.location }))), + { initialValue: [] }, + ) + const [directorySkills] = createResource( + directorySDK, + (sdk): Promise => + sdk.api.skill + .list({ location: { directory: sdk.directory } }) + .then((result) => result.data.map((item) => ({ name: item.name, location: item.location }))), + { initialValue: [] }, + ) + const projectSkills = createMemo(() => { + const shared = new Set(serverSkills.latest.map(skillKey)) + return directorySkills.latest.filter((item) => !shared.has(skillKey(item))) + }) + + const mcpRows = (items: string[]) => ( + + {(name) => ( + + { + if (toggleMcp.isPending) return + toggleMcp.mutate(name) + }} + > + {name} + + + )} + + ) + + const pluginRows = (items: string[]) => {(name) => } + + const skillRows = (items: SkillItem[]) => ( + {(item) => } + ) + + return ( +
+
+

{language.t("settings.tab.extensions")}

+ {language.t("project.settings.extensions.description")} +
+ + + + {language.t("settings.extensions.tab.mcps")} + {language.t("status.popover.tab.plugins")} + {language.t("settings.extensions.tab.skills")} + {language.t("project.settings.extensions.tab.lsps")} + + + +
+
+ {language.t("project.settings.extensions.added")} + {language.t("settings.extensions.manageConfig")} +
+ 0}> + {mcpRows(projectMcpNames())} + + {mcpRows(globalMcpNames())} +
+
+ + +
+
+ {language.t("project.settings.extensions.added")} + {language.t("settings.extensions.manageConfig")} +
+ 0}> + {pluginRows(projectPlugins())} + + {pluginRows(globalPlugins())} +
+
+ + +
+
+ {language.t("project.settings.extensions.added")} + + {language.t("settings.extensions.addSkills")} + +
+ 0}> + {skillRows(projectSkills())} + + {skillRows(serverSkills.latest)} +
+
+ + +
+
+ {language.t("project.settings.extensions.lsp.detected")} + {language.t("project.settings.extensions.lsp.description")} +
+ 0}> + + + {(item) => ( + + )} + + + +
+
+
+
+ ) +} diff --git a/packages/app/src/components/server/server-row-menu.tsx b/packages/app/src/components/server/server-row-menu.tsx index 619c8a50be..aedcae8537 100644 --- a/packages/app/src/components/server/server-row-menu.tsx +++ b/packages/app/src/components/server/server-row-menu.tsx @@ -9,7 +9,7 @@ import { ServerConnection } from "@/context/server" export const ServerRowMenu: Component<{ server: ServerConnection.Any domain: ServerActionsController - onEdit: (server: ServerConnection.Http) => void + onEdit: (server: ServerConnection.Any) => void open?: boolean onOpenChange?: (open: boolean) => void }> = (props) => { @@ -49,7 +49,7 @@ export const ServerRowMenuView: Component<{ canDefault: boolean isDefault: boolean canRemove: boolean - onEdit: (server: ServerConnection.Http) => void + onEdit: (server: ServerConnection.Any) => void onSetDefault: () => void onRemoveDefault: () => void onRemove: () => void @@ -57,7 +57,6 @@ export const ServerRowMenuView: Component<{ onOpenChange?: (open: boolean) => void }> = (props) => { const builtin = () => ServerConnection.builtin(props.server) - const httpServer = () => (props.server.type === "http" ? props.server : undefined) return ( {props.labels.server} - { - const server = httpServer() - if (server) props.onEdit(server) - }} - > - {props.labels.edit} - + props.onEdit(props.server)}>{props.labels.edit} {props.labels.default} diff --git a/packages/app/src/components/settings-keybinds.tsx b/packages/app/src/components/settings-keybinds.tsx index ce74be4586..57d71c0d6d 100644 --- a/packages/app/src/components/settings-keybinds.tsx +++ b/packages/app/src/components/settings-keybinds.tsx @@ -451,7 +451,10 @@ function SettingsKeybindsV2View(props: { <>
-

{language.t("settings.shortcuts.title")}

+
+

{language.t("settings.shortcuts.title")}

+ {language.t("settings.shortcuts.description")} +
{language.t("settings.shortcuts.reset.button")} diff --git a/packages/app/src/components/settings-server-picker.tsx b/packages/app/src/components/settings-server-picker.tsx index d9fd4d40c0..16fb3ac34d 100644 --- a/packages/app/src/components/settings-server-picker.tsx +++ b/packages/app/src/components/settings-server-picker.tsx @@ -1,33 +1,23 @@ -import { Button } from "@opencode-ai/ui/button" -import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu" -import { Icon } from "@opencode-ai/ui/icon" import { QueryClientProvider } from "@tanstack/solid-query" -import { createMemo, For, type ParentProps, Show } from "solid-js" -import { ServerHealthIndicator, ServerRow } from "@/components/server/server-row" +import { type ParentProps, Show } from "solid-js" +import { useGlobal } from "@/context/global" import { ModelsProvider } from "@/context/models" import { ServerConnection } from "@/context/server" import { ServerSDKProvider } from "@/context/server-sdk" import { ServerSyncProvider } from "@/context/server-sync" -import { useGlobal } from "@/context/global" -import { useSettings } from "@/context/settings" export function SettingsServerScope(props: ParentProps) { const global = useGlobal() - const settings = useSettings() - return ( - - - {(server) => {props.children}} - + + {(server) => {props.children}} ) } -function SettingsServerDataProviders(props: ParentProps<{ server: ServerConnection.Any }>) { +export function SettingsServerDataScope(props: ParentProps<{ server: ServerConnection.Any }>) { const global = useGlobal() const serverCtx = () => global.ensureServerCtx(props.server) - return ( props.server}> @@ -38,69 +28,3 @@ function SettingsServerDataProviders(props: ParentProps<{ server: ServerConnecti ) } - -export function SettingsServerPicker() { - const global = useGlobal() - const settings = useSettings() - const selected = createMemo(() => - settings.general.newLayoutDesigns() ? global.settings.server.selected() : undefined, - ) - - return ( - - {(conn) => ( - - - - - - - - - { - if (typeof key === "string") global.settings.server.set(ServerConnection.Key.make(key)) - }} - > - - {(item) => { - const key = ServerConnection.key(item) - const blocked = () => global.servers.health[key]?.healthy === false - return ( - - - - - - - - ) - }} - - - - - - )} - - ) -} diff --git a/packages/app/src/components/settings-v2/appearance.tsx b/packages/app/src/components/settings-v2/appearance.tsx index 91fd36597d..beb72b0b85 100644 --- a/packages/app/src/components/settings-v2/appearance.tsx +++ b/packages/app/src/components/settings-v2/appearance.tsx @@ -1,9 +1,7 @@ -import { Component, Show, createMemo, createResource } from "solid-js" +import { Component, createMemo } from "solid-js" 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" @@ -65,28 +63,16 @@ const FontSetting: Component<{ export const SettingsAppearanceV2: Component = () => { const language = useLanguage() - const platform = usePlatform() const appearance = createAppearanceSettingsController() - const desktop = createMemo(() => platform.platform === "desktop") - - 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)) - } return ( <>
-

{language.t("settings.general.section.appearance")}

+
+

{language.t("settings.general.section.appearance")}

+ {language.t("settings.appearance.description")} +
@@ -142,22 +128,6 @@ export const SettingsAppearanceV2: Component = () => {
- - -
-

{language.t("settings.general.section.display")}

- - -
- -
-
-
-
-
) diff --git a/packages/app/src/components/settings-v2/extensions.tsx b/packages/app/src/components/settings-v2/extensions.tsx index baa0448442..bbe4e26453 100644 --- a/packages/app/src/components/settings-v2/extensions.tsx +++ b/packages/app/src/components/settings-v2/extensions.tsx @@ -50,11 +50,8 @@ export const SettingsExtensionsV2: Component = () => { }) const [skills] = createResource( - () => serverSdk(), - async (sdk) => { - const result = await sdk.client.v2.skill.list(undefined, { throwOnError: true }) - return result.data.data - }, + serverSdk, + (sdk) => sdk.api.skill.list().then((result) => result.data), { initialValue: [] }, ) @@ -64,7 +61,7 @@ export const SettingsExtensionsV2: Component = () => {

{language.t("settings.tab.extensions")}

- {language.t("settings.mcps.description")} + {language.t("settings.extensions.description")}
@@ -73,9 +70,9 @@ export const SettingsExtensionsV2: Component = () => {
- {language.t("status.popover.tab.mcp")} + {language.t("settings.extensions.tab.mcps")} {language.t("status.popover.tab.plugins")} - {language.t("settings.permissions.tool.skill.title")} + {language.t("settings.extensions.tab.skills")} diff --git a/packages/app/src/components/settings-v2/general.tsx b/packages/app/src/components/settings-v2/general.tsx index 66b8ccd69c..2c51252857 100644 --- a/packages/app/src/components/settings-v2/general.tsx +++ b/packages/app/src/components/settings-v2/general.tsx @@ -279,8 +279,6 @@ export const SettingsGeneralV2: Component<{ const updater = useUpdaterAction() const permissionScope = createPermissionScopeController(() => props.sessionID) const shell = createShellSettingsController() - const appearance = createAppearanceSettingsController() - const sounds = createSoundSettingsController() const desktop = createMemo(() => platform.platform === "desktop") const [pinchZoom, { mutate: setPinchZoom }] = createResource( @@ -298,6 +296,7 @@ export const SettingsGeneralV2: Component<{ const GeneralSection = () => (
+

{language.t("settings.general.section.general")}

@@ -510,18 +509,19 @@ export const SettingsGeneralV2: Component<{ return ( <>
-

{language.t("settings.tab.general")}

+
+
+

{language.t("settings.tab.preferences")}

+ + {language.t("settings.preferences.description")} + +
+
- - - - - - diff --git a/packages/app/src/components/settings-v2/models.tsx b/packages/app/src/components/settings-v2/models.tsx index deb5b97c12..738d282d72 100644 --- a/packages/app/src/components/settings-v2/models.tsx +++ b/packages/app/src/components/settings-v2/models.tsx @@ -55,7 +55,10 @@ export const SettingsModelsV2: Component = () => { <>
-

{language.t("settings.models.title")}

+
+

{language.t("settings.models.title")}

+ {language.t("settings.models.description")} +