diff --git a/src/settings/archived-section.tsx b/src/settings/archived-section.tsx index 32a7e7b6..20a189cb 100644 --- a/src/settings/archived-section.tsx +++ b/src/settings/archived-section.tsx @@ -19,19 +19,11 @@ export function ArchivedThreadSection({ state }: { state: ArchivedThreadSectionS return ( <> - + - + {state.contentAvailable ? ( ) : !state.loading && state.status ? ( @@ -45,10 +37,7 @@ export function ArchivedThreadSection({ state }: { state: ArchivedThreadSectionS function ArchiveExportSettings({ state }: { state: ArchivedThreadSectionState }): UiNode { return ( - + { @@ -56,7 +45,7 @@ function ArchiveExportSettings({ state }: { state: ArchivedThreadSectionState }) }} /> - + - + - + - + {state.contentAvailable ? ( ) : !state.loading && state.status ? ( diff --git a/src/settings/tab.tsx b/src/settings/tab.tsx index 69a618d1..52b47387 100644 --- a/src/settings/tab.tsx +++ b/src/settings/tab.tsx @@ -10,8 +10,7 @@ import type { CodexPanelSettingTabHost } from "./host"; import { HookSection } from "./hook-section"; import type { SettingsSectionsState } from "./section-state"; -const SETTINGS_INTRO_TEXT = - "Codex Panel stores only panel preferences. Models, sandboxing, approvals, MCP servers, hooks, and network access still come from Codex config."; +const SETTINGS_INTRO_TEXT = "Codex Panel stores panel preferences only. Runtime settings still come from Codex."; const SEND_SHORTCUT_LABELS = { enter: "Enter", "mod-enter": "Cmd/Ctrl+Enter", @@ -103,7 +102,7 @@ export class CodexPanelSettingTab extends PluginSettingTab { new Setting(configItems) .setName("Codex executable") - .setDesc("Path used to start `codex app-server`. Use an absolute path if Obsidian cannot find `codex`.") + .setDesc("Command used to start `codex app-server`; use an absolute path if needed.") .addText((text) => { text.setPlaceholder(DEFAULT_CODEX_PATH).setValue(this.plugin.settings.codexPath); const commitCodexPath = () => { @@ -119,7 +118,7 @@ export class CodexPanelSettingTab extends PluginSettingTab { }); new Setting(configItems) .setName("Show chat toolbar") - .setDesc("Show the chat panel toolbar. Slash commands, composer status controls, and the threads view remain available when hidden.") + .setDesc("Show the toolbar above the chat panel.") .addToggle((toggle) => { toggle.setValue(this.plugin.settings.showToolbar).onChange(async (value) => { this.plugin.settings.showToolbar = value; @@ -133,9 +132,7 @@ export class CodexPanelSettingTab extends PluginSettingTab { const composerItems = createSettingsItems(composerSection); new Setting(composerItems) .setName("Send shortcut") - .setDesc( - "Choose how the composer sends messages. Shift+Enter inserts a newline when Enter sends. Obsidian hotkeys may intercept Cmd/Ctrl+Enter.", - ) + .setDesc("Pick Enter or Cmd/Ctrl+Enter. Shift+Enter adds a newline when Enter sends.") .addDropdown((dropdown) => { dropdown.addOption("enter", SEND_SHORTCUT_LABELS.enter); dropdown.addOption("mod-enter", SEND_SHORTCUT_LABELS["mod-enter"]); @@ -147,7 +144,7 @@ export class CodexPanelSettingTab extends PluginSettingTab { }); new Setting(composerItems) .setName("Scroll thread from composer edges") - .setDesc("When enabled, Up/Ctrl+P on the first composer line and Down/Ctrl+N on the last line scroll the thread.") + .setDesc("Use Up/Ctrl+P and Down/Ctrl+N at composer edges to scroll the thread.") .addToggle((toggle) => { toggle.setValue(this.plugin.settings.scrollThreadFromComposerEdges).onChange(async (value) => { this.plugin.settings.scrollThreadFromComposerEdges = value; diff --git a/tests/settings/settings-tab.test.ts b/tests/settings/settings-tab.test.ts index 8676e4c9..9060e5e3 100644 --- a/tests/settings/settings-tab.test.ts +++ b/tests/settings/settings-tab.test.ts @@ -72,7 +72,7 @@ describe("settings tab", () => { expect(buttonTexts(tab)).not.toContain("Load archive list"); expect( tab.containerEl.querySelector(".codex-panel-settings__header.setting-item-heading .setting-item-description")?.textContent, - ).toContain("Codex Panel stores only panel preferences"); + ).toContain("Codex Panel stores panel preferences only"); expect(tab.containerEl.querySelector(".codex-panel-settings__header button")?.getAttribute("data-icon")).toBe("refresh-cw"); expect(tab.containerEl.querySelector("h2")).toBeNull(); expect(tab.containerEl.querySelector(".codex-panel-settings__general-section.setting-group > .setting-items")?.children).toHaveLength( @@ -85,14 +85,14 @@ describe("settings tab", () => { expect( tab.containerEl.querySelector(".codex-panel-settings__archived-section > .setting-item-heading .setting-item-description") ?.textContent, - ).toContain("Choose the default archive behavior"); + ).toContain("Set the default archive action"); expect( tab.containerEl.querySelector(".codex-panel-settings__archived-threads-section > .setting-item-heading .setting-item-description") ?.textContent, - ).toContain("Restore archived threads"); + ).toContain("Restore or permanently delete"); expect( tab.containerEl.querySelector(".codex-panel-settings__hook-section > .setting-item-heading .setting-item-description")?.textContent, - ).toContain("Review discovered hooks"); + ).toContain("Trust, enable, or disable"); expect( tab.containerEl.querySelector( ".codex-panel-settings__archived-section.setting-group > .setting-items:not(.codex-panel-settings__dynamic-list)", @@ -117,7 +117,7 @@ describe("settings tab", () => { ]); }); - it("saves the send shortcut setting and warns about Obsidian hotkeys", async () => { + it("saves the send shortcut setting and describes newline behavior", async () => { const saveSettings = vi.fn().mockResolvedValue(undefined); const tab = newSettingsTab({ saveSettings }); @@ -131,8 +131,8 @@ describe("settings tab", () => { await flushPromises(); expect(saveSettings).toHaveBeenCalledOnce(); - expect(settingDesc(tab, "Send shortcut")).toContain("Obsidian hotkeys"); - expect(tab.containerEl.querySelector(".codex-panel-settings__section-status")?.textContent ?? "").not.toContain("Obsidian hotkeys"); + expect(settingDesc(tab, "Send shortcut")).toContain("Shift+Enter adds a newline"); + expect(tab.containerEl.querySelector(".codex-panel-settings__section-status")?.textContent ?? "").not.toContain("Shift+Enter"); }); it("saves the toolbar visibility setting and refreshes open panels", async () => { @@ -150,7 +150,7 @@ describe("settings tab", () => { expect(saveSettings).toHaveBeenCalledOnce(); expect(refreshOpenViews).toHaveBeenCalledOnce(); - expect(settingDesc(tab, "Show chat toolbar")).toContain("Slash commands"); + expect(settingDesc(tab, "Show chat toolbar")).toContain("toolbar above the chat panel"); }); it("saves the composer edge scroll setting", async () => { @@ -198,10 +198,9 @@ describe("settings tab", () => { await flushPromises(); expect(saveSettings).toHaveBeenCalledTimes(4); - expect(tab.containerEl.textContent).toContain("title, thread_id, created, and optional tags"); expect(settingDesc(tab, "Save note by default")).toContain("default archive action"); - expect(settingDesc(tab, "Save note by default")).toContain("If saving fails"); - expect(settingDesc(tab, "Saved note tags")).toContain("Leave empty to omit tags"); + expect(settingDesc(tab, "Saved note filename")).toContain("{{shortId}}"); + expect(settingDesc(tab, "Saved note tags")).toContain("separated by commas"); }); it("refreshes models, hooks, and archived threads from the global refresh button", async () => { @@ -730,7 +729,7 @@ describe("settings tab", () => { tab.display(); await flushPromises(); - expect(tab.containerEl.textContent).toContain("Restore archived threads, or permanently delete archived threads you no longer need."); + expect(tab.containerEl.textContent).toContain("Restore or permanently delete archived Codex threads."); expect(tab.containerEl.textContent).not.toContain("Loaded 1 hook from Codex app server."); expect(tab.containerEl.textContent).not.toContain("Loaded 1 archived thread from Codex app server."); expect(tab.containerEl.querySelector(".codex-panel-settings__hook-section .setting-item-heading")?.textContent).toContain(