feat: add toggle for showing draft starters on new sessions
Persists draft starter visibility across desktop and web settings Adds a new OpenChamber visual setting with localization and search support Hides the draft starter chips when the setting is off
This commit is contained in:
@@ -32,6 +32,7 @@ import { useI18n } from '@/lib/i18n';
|
|||||||
import { useThemeSystem } from '@/contexts/useThemeSystem';
|
import { useThemeSystem } from '@/contexts/useThemeSystem';
|
||||||
import { useDeviceInfo } from '@/lib/device';
|
import { useDeviceInfo } from '@/lib/device';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
import { useUIStore } from '@/stores/useUIStore';
|
||||||
import {
|
import {
|
||||||
useDraftStarters,
|
useDraftStarters,
|
||||||
type ResolvedStarter,
|
type ResolvedStarter,
|
||||||
@@ -254,7 +255,7 @@ const AddStarterPicker: React.FC<{
|
|||||||
* Reorder is constrained to within a chip's own group; cross-group hovers are
|
* Reorder is constrained to within a chip's own group; cross-group hovers are
|
||||||
* ignored.
|
* ignored.
|
||||||
*/
|
*/
|
||||||
export const DraftPresetChips: React.FC<DraftPresetChipsProps> = ({ onSubmit, className }) => {
|
const DraftPresetChipsContent: React.FC<DraftPresetChipsProps> = ({ onSubmit, className }) => {
|
||||||
const { global, project, pinnable, ensureLoaded, addStarter, removeStarter, reorder } = useDraftStarters();
|
const { global, project, pinnable, ensureLoaded, addStarter, removeStarter, reorder } = useDraftStarters();
|
||||||
const { isMobile } = useDeviceInfo();
|
const { isMobile } = useDeviceInfo();
|
||||||
const [isDragging, setIsDragging] = React.useState(false);
|
const [isDragging, setIsDragging] = React.useState(false);
|
||||||
@@ -331,3 +332,8 @@ export const DraftPresetChips: React.FC<DraftPresetChipsProps> = ({ onSubmit, cl
|
|||||||
</DndContext>
|
</DndContext>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DraftPresetChips: React.FC<DraftPresetChipsProps> = (props) => {
|
||||||
|
const visible = useUIStore((state) => state.draftStartersVisible);
|
||||||
|
return visible ? <DraftPresetChipsContent {...props} /> : null;
|
||||||
|
};
|
||||||
|
|||||||
@@ -381,6 +381,8 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
|||||||
const setShowSplitAssistantMessageActions = useUIStore(state => state.setShowSplitAssistantMessageActions);
|
const setShowSplitAssistantMessageActions = useUIStore(state => state.setShowSplitAssistantMessageActions);
|
||||||
const allowPromptingSubagentSessions = useUIStore(state => state.allowPromptingSubagentSessions);
|
const allowPromptingSubagentSessions = useUIStore(state => state.allowPromptingSubagentSessions);
|
||||||
const setAllowPromptingSubagentSessions = useUIStore(state => state.setAllowPromptingSubagentSessions);
|
const setAllowPromptingSubagentSessions = useUIStore(state => state.setAllowPromptingSubagentSessions);
|
||||||
|
const draftStartersVisible = useUIStore(state => state.draftStartersVisible);
|
||||||
|
const setDraftStartersVisible = useUIStore(state => state.setDraftStartersVisible);
|
||||||
const messageStreamTransport = useConfigStore((state) => state.settingsMessageStreamTransport);
|
const messageStreamTransport = useConfigStore((state) => state.settingsMessageStreamTransport);
|
||||||
const setMessageStreamTransport = useConfigStore((state) => state.setSettingsMessageStreamTransport);
|
const setMessageStreamTransport = useConfigStore((state) => state.setSettingsMessageStreamTransport);
|
||||||
const effectiveMessageStreamTransport = messageStreamTransport;
|
const effectiveMessageStreamTransport = messageStreamTransport;
|
||||||
@@ -500,6 +502,11 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
|||||||
void updateDesktopSettings({ promptNavigatorEnabled: enabled });
|
void updateDesktopSettings({ promptNavigatorEnabled: enabled });
|
||||||
}, [setPromptNavigatorEnabled]);
|
}, [setPromptNavigatorEnabled]);
|
||||||
|
|
||||||
|
const handleDraftStartersVisibleChange = React.useCallback((enabled: boolean) => {
|
||||||
|
setDraftStartersVisible(enabled);
|
||||||
|
void updateDesktopSettings({ draftStartersVisible: enabled });
|
||||||
|
}, [setDraftStartersVisible]);
|
||||||
|
|
||||||
const handleExpandedEditorToolbarChange = React.useCallback((enabled: boolean) => {
|
const handleExpandedEditorToolbarChange = React.useCallback((enabled: boolean) => {
|
||||||
setExpandedEditorToolbar(enabled);
|
setExpandedEditorToolbar(enabled);
|
||||||
void updateDesktopSettings({ expandedEditorToolbar: enabled });
|
void updateDesktopSettings({ expandedEditorToolbar: enabled });
|
||||||
@@ -1766,12 +1773,18 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
|||||||
/>
|
/>
|
||||||
</SettingsSection>
|
</SettingsSection>
|
||||||
)}
|
)}
|
||||||
{(shouldShow('sessionAssist') || shouldShow('subagentReadOnlyBanner')) && (
|
<SettingsSection
|
||||||
<SettingsSection
|
title={t('settings.openchamber.visual.section.sessionAssistance')}
|
||||||
title={t('settings.openchamber.visual.section.sessionAssistance')}
|
settingsItem="chat.session-assistance"
|
||||||
settingsItem="chat.session-assistance"
|
contentClassName={SETTINGS_OPTION_STACK_CLASS}
|
||||||
contentClassName={SETTINGS_OPTION_STACK_CLASS}
|
>
|
||||||
>
|
<SettingsCheckboxRow
|
||||||
|
checked={draftStartersVisible}
|
||||||
|
onChange={handleDraftStartersVisibleChange}
|
||||||
|
label={t('settings.openchamber.visual.field.draftStartersVisible')}
|
||||||
|
ariaLabel={t('settings.openchamber.visual.field.draftStartersVisibleAria')}
|
||||||
|
settingsItem="chat.draft-starters-visible"
|
||||||
|
/>
|
||||||
{shouldShow('sessionAssist') && (
|
{shouldShow('sessionAssist') && (
|
||||||
<>
|
<>
|
||||||
<SettingsCheckboxRow
|
<SettingsCheckboxRow
|
||||||
@@ -1799,8 +1812,7 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
|||||||
settingsItem="chat.subagent-read-only-banner"
|
settingsItem="chat.subagent-read-only-banner"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</SettingsSection>
|
</SettingsSection>
|
||||||
)}
|
|
||||||
{/* The goal loop runs in the web server — VS Code only renders
|
{/* The goal loop runs in the web server — VS Code only renders
|
||||||
goal state, so the settings section is hidden there too. */}
|
goal state, so the settings section is hidden there too. */}
|
||||||
{shouldShow('sessionGoal') && !isVSCode && (
|
{shouldShow('sessionGoal') && !isVSCode && (
|
||||||
|
|||||||
@@ -676,6 +676,7 @@ export interface SettingsPayload {
|
|||||||
pwaAppName?: string;
|
pwaAppName?: string;
|
||||||
mobileKeyboardMode?: 'native' | 'resize-content';
|
mobileKeyboardMode?: 'native' | 'resize-content';
|
||||||
draftStarters?: DraftStarterRef[];
|
draftStarters?: DraftStarterRef[];
|
||||||
|
draftStartersVisible?: boolean;
|
||||||
draftStartersCraftGoalAdded?: boolean;
|
draftStartersCraftGoalAdded?: boolean;
|
||||||
|
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ export type DesktopSettings = {
|
|||||||
sttLanguage?: string;
|
sttLanguage?: string;
|
||||||
// Global draft welcome starters (pinned commands/skills), persisted to settings.json
|
// Global draft welcome starters (pinned commands/skills), persisted to settings.json
|
||||||
draftStarters?: DraftStarterRef[];
|
draftStarters?: DraftStarterRef[];
|
||||||
|
draftStartersVisible?: boolean;
|
||||||
// One-time migration marker: Craft a Goal was offered in the starter row.
|
// One-time migration marker: Craft a Goal was offered in the starter row.
|
||||||
draftStartersCraftGoalAdded?: boolean;
|
draftStartersCraftGoalAdded?: boolean;
|
||||||
draftStartersScheduleTaskAdded?: boolean;
|
draftStartersScheduleTaskAdded?: boolean;
|
||||||
|
|||||||
@@ -1884,6 +1884,8 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': 'Show Copy Answer, Save as image, and Read aloud on assistant text blocks that appear before later tool calls in the same response.',
|
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': 'Show Copy Answer, Save as image, and Read aloud on assistant text blocks that appear before later tool calls in the same response.',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': 'Allow prompting subagent sessions',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': 'Allow prompting subagent sessions',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessions': 'Allow Prompting Subagent Sessions',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessions': 'Allow Prompting Subagent Sessions',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisible': 'Show Starters on New Session Screen',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisibleAria': 'Show starters on the new session screen',
|
||||||
'settings.openchamber.visual.field.showToolFileIconsAria': 'Show tool file icons',
|
'settings.openchamber.visual.field.showToolFileIconsAria': 'Show tool file icons',
|
||||||
'settings.openchamber.visual.field.showToolFileIcons': 'Show Tool File Icons',
|
'settings.openchamber.visual.field.showToolFileIcons': 'Show Tool File Icons',
|
||||||
'settings.openchamber.visual.field.showTurnChangedFilesAria': 'Show changed files for completed turns',
|
'settings.openchamber.visual.field.showTurnChangedFilesAria': 'Show changed files for completed turns',
|
||||||
|
|||||||
@@ -1849,6 +1849,8 @@ export const settingsDict = {
|
|||||||
"settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip": "Muestra Copiar respuesta, Guardar como imagen y Leer en voz alta en bloques de texto del asistente que aparecen antes de llamadas a herramientas posteriores dentro de la misma respuesta.",
|
"settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip": "Muestra Copiar respuesta, Guardar como imagen y Leer en voz alta en bloques de texto del asistente que aparecen antes de llamadas a herramientas posteriores dentro de la misma respuesta.",
|
||||||
"settings.openchamber.visual.field.allowPromptingSubagentSessionsAria": "Permitir enviar solicitudes a sesiones de subagentes",
|
"settings.openchamber.visual.field.allowPromptingSubagentSessionsAria": "Permitir enviar solicitudes a sesiones de subagentes",
|
||||||
"settings.openchamber.visual.field.allowPromptingSubagentSessions": "Permitir solicitudes en sesiones de subagentes",
|
"settings.openchamber.visual.field.allowPromptingSubagentSessions": "Permitir solicitudes en sesiones de subagentes",
|
||||||
|
"settings.openchamber.visual.field.draftStartersVisible": "Mostrar iniciadores en la pantalla de nueva sesión",
|
||||||
|
"settings.openchamber.visual.field.draftStartersVisibleAria": "Mostrar iniciadores en la pantalla de nueva sesión",
|
||||||
"settings.openchamber.visual.field.showToolFileIconsAria": "Mostrar iconos de archivos de herramientas",
|
"settings.openchamber.visual.field.showToolFileIconsAria": "Mostrar iconos de archivos de herramientas",
|
||||||
"settings.openchamber.visual.field.codeBlockLineWrapAria": "Ajustar líneas de bloques de código",
|
"settings.openchamber.visual.field.codeBlockLineWrapAria": "Ajustar líneas de bloques de código",
|
||||||
"settings.openchamber.visual.field.codeBlockLineWrap": "Ajustar líneas de bloques de código",
|
"settings.openchamber.visual.field.codeBlockLineWrap": "Ajustar líneas de bloques de código",
|
||||||
|
|||||||
@@ -1754,6 +1754,8 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': 'Afficher Copier la réponse, Enregistrer en image et Lire à haute voix sur les blocs de texte de l\'assistant qui apparaissent avant les appels d\'outil suivants dans la même réponse.',
|
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': 'Afficher Copier la réponse, Enregistrer en image et Lire à haute voix sur les blocs de texte de l\'assistant qui apparaissent avant les appels d\'outil suivants dans la même réponse.',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': 'Autoriser les requêtes dans les sessions de sous-agents',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': 'Autoriser les requêtes dans les sessions de sous-agents',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessions': 'Autoriser les requêtes dans les sessions de sous-agents',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessions': 'Autoriser les requêtes dans les sessions de sous-agents',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisible': 'Afficher les raccourcis sur l’écran de nouvelle session',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisibleAria': 'Afficher les raccourcis sur l’écran de nouvelle session',
|
||||||
'settings.openchamber.visual.field.showToolFileIconsAria': 'Afficher les icônes des fichiers d\'outils',
|
'settings.openchamber.visual.field.showToolFileIconsAria': 'Afficher les icônes des fichiers d\'outils',
|
||||||
'settings.openchamber.visual.field.codeBlockLineWrapAria': 'Renvoyer à la ligne les blocs de code',
|
'settings.openchamber.visual.field.codeBlockLineWrapAria': 'Renvoyer à la ligne les blocs de code',
|
||||||
'settings.openchamber.visual.field.codeBlockLineWrap': 'Renvoyer à la ligne les blocs de code',
|
'settings.openchamber.visual.field.codeBlockLineWrap': 'Renvoyer à la ligne les blocs de code',
|
||||||
|
|||||||
@@ -1882,6 +1882,8 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': '同じ応答内の後のツール呼び出しの前に表示されるアシスタントテキストブロックに、回答コピー、画像保存、読み上げを表示します。',
|
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': '同じ応答内の後のツール呼び出しの前に表示されるアシスタントテキストブロックに、回答コピー、画像保存、読み上げを表示します。',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': 'サブエージェントセッションへのプロンプトを許可',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': 'サブエージェントセッションへのプロンプトを許可',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessions': 'サブエージェントセッションへのプロンプトを許可',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessions': 'サブエージェントセッションへのプロンプトを許可',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisible': '新規セッション画面にスターターを表示',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisibleAria': '新規セッション画面にスターターを表示',
|
||||||
'settings.openchamber.visual.field.showToolFileIconsAria': 'ツールファイルアイコンを表示',
|
'settings.openchamber.visual.field.showToolFileIconsAria': 'ツールファイルアイコンを表示',
|
||||||
'settings.openchamber.visual.field.codeBlockLineWrapAria': 'コードブロックの行を折り返す',
|
'settings.openchamber.visual.field.codeBlockLineWrapAria': 'コードブロックの行を折り返す',
|
||||||
'settings.openchamber.visual.field.codeBlockLineWrap': 'コードブロックの行を折り返す',
|
'settings.openchamber.visual.field.codeBlockLineWrap': 'コードブロックの行を折り返す',
|
||||||
|
|||||||
@@ -1849,6 +1849,8 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': '같은 응답에서 이후 도구 호출 앞에 나타나는 어시스턴트 텍스트 블록에 답변 복사, 이미지로 저장, 소리 내어 읽기 작업을 표시합니다.',
|
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': '같은 응답에서 이후 도구 호출 앞에 나타나는 어시스턴트 텍스트 블록에 답변 복사, 이미지로 저장, 소리 내어 읽기 작업을 표시합니다.',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': '하위 에이전트 세션에 프롬프트 허용',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': '하위 에이전트 세션에 프롬프트 허용',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessions': '하위 에이전트 세션에 프롬프트 허용',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessions': '하위 에이전트 세션에 프롬프트 허용',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisible': '새 세션 화면에 시작 항목 표시',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisibleAria': '새 세션 화면에 시작 항목 표시',
|
||||||
'settings.openchamber.visual.field.showToolFileIconsAria': '도구 파일 아이콘 표시',
|
'settings.openchamber.visual.field.showToolFileIconsAria': '도구 파일 아이콘 표시',
|
||||||
'settings.openchamber.visual.field.codeBlockLineWrapAria': '코드 블록 줄 바꿈',
|
'settings.openchamber.visual.field.codeBlockLineWrapAria': '코드 블록 줄 바꿈',
|
||||||
'settings.openchamber.visual.field.codeBlockLineWrap': '코드 블록 줄 바꿈',
|
'settings.openchamber.visual.field.codeBlockLineWrap': '코드 블록 줄 바꿈',
|
||||||
|
|||||||
@@ -1067,6 +1067,8 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': 'Pokaż Kopiuj odpowiedź, Zapisz jako obraz i Odczytaj na głos w blokach tekstu asystenta, które pojawiają się przed późniejszymi wywołaniami narzędzi w tej samej odpowiedzi.',
|
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': 'Pokaż Kopiuj odpowiedź, Zapisz jako obraz i Odczytaj na głos w blokach tekstu asystenta, które pojawiają się przed późniejszymi wywołaniami narzędzi w tej samej odpowiedzi.',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': 'Zezwalaj na wysyłanie promptów do sesji podagentów',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': 'Zezwalaj na wysyłanie promptów do sesji podagentów',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessions': 'Zezwalaj na prompty w sesjach podagentów',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessions': 'Zezwalaj na prompty w sesjach podagentów',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisible': 'Pokazuj startery na ekranie nowej sesji',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisibleAria': 'Pokazuj startery na ekranie nowej sesji',
|
||||||
'settings.openchamber.visual.field.showToolFileIcons': 'Pokaż ikony plików narzędzi',
|
'settings.openchamber.visual.field.showToolFileIcons': 'Pokaż ikony plików narzędzi',
|
||||||
'settings.openchamber.visual.field.showToolFileIconsAria': 'Pokaż ikony plików narzędzi',
|
'settings.openchamber.visual.field.showToolFileIconsAria': 'Pokaż ikony plików narzędzi',
|
||||||
'settings.openchamber.visual.field.codeBlockLineWrapAria': 'Zawijaj wiersze bloków kodu',
|
'settings.openchamber.visual.field.codeBlockLineWrapAria': 'Zawijaj wiersze bloków kodu',
|
||||||
|
|||||||
@@ -1849,6 +1849,8 @@ export const settingsDict = {
|
|||||||
"settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip": "Mostra Copiar resposta, Salvar como imagem e Ler em voz alta em blocos de texto do assistente que aparecem antes de chamadas de ferramenta posteriores na mesma resposta.",
|
"settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip": "Mostra Copiar resposta, Salvar como imagem e Ler em voz alta em blocos de texto do assistente que aparecem antes de chamadas de ferramenta posteriores na mesma resposta.",
|
||||||
"settings.openchamber.visual.field.allowPromptingSubagentSessionsAria": "Permitir prompts em sessões de subagentes",
|
"settings.openchamber.visual.field.allowPromptingSubagentSessionsAria": "Permitir prompts em sessões de subagentes",
|
||||||
"settings.openchamber.visual.field.allowPromptingSubagentSessions": "Permitir prompts em sessões de subagentes",
|
"settings.openchamber.visual.field.allowPromptingSubagentSessions": "Permitir prompts em sessões de subagentes",
|
||||||
|
"settings.openchamber.visual.field.draftStartersVisible": "Mostrar atalhos na tela de nova sessão",
|
||||||
|
"settings.openchamber.visual.field.draftStartersVisibleAria": "Mostrar atalhos na tela de nova sessão",
|
||||||
"settings.openchamber.visual.field.showToolFileIconsAria": "Mostrar ícones de arquivos de ferramentas",
|
"settings.openchamber.visual.field.showToolFileIconsAria": "Mostrar ícones de arquivos de ferramentas",
|
||||||
"settings.openchamber.visual.field.codeBlockLineWrapAria": "Quebrar linhas de blocos de código",
|
"settings.openchamber.visual.field.codeBlockLineWrapAria": "Quebrar linhas de blocos de código",
|
||||||
"settings.openchamber.visual.field.codeBlockLineWrap": "Quebrar linhas de blocos de código",
|
"settings.openchamber.visual.field.codeBlockLineWrap": "Quebrar linhas de blocos de código",
|
||||||
|
|||||||
@@ -1849,6 +1849,8 @@ export const settingsDict = {
|
|||||||
"settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip": "Показує «Скопіювати відповідь», «Зберегти як зображення» та озвучення для текстових блоків асистента, які з’являються перед пізнішими викликами інструментів у тій самій відповіді.",
|
"settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip": "Показує «Скопіювати відповідь», «Зберегти як зображення» та озвучення для текстових блоків асистента, які з’являються перед пізнішими викликами інструментів у тій самій відповіді.",
|
||||||
"settings.openchamber.visual.field.allowPromptingSubagentSessionsAria": "Дозволити надсилати запити в сесії субагентів",
|
"settings.openchamber.visual.field.allowPromptingSubagentSessionsAria": "Дозволити надсилати запити в сесії субагентів",
|
||||||
"settings.openchamber.visual.field.allowPromptingSubagentSessions": "Дозволити запити в сесіях субагентів",
|
"settings.openchamber.visual.field.allowPromptingSubagentSessions": "Дозволити запити в сесіях субагентів",
|
||||||
|
"settings.openchamber.visual.field.draftStartersVisible": "Показувати стартери на екрані нової сесії",
|
||||||
|
"settings.openchamber.visual.field.draftStartersVisibleAria": "Показувати стартери на екрані нової сесії",
|
||||||
"settings.openchamber.visual.field.showToolFileIconsAria": "Показати значки файлів інструментів",
|
"settings.openchamber.visual.field.showToolFileIconsAria": "Показати значки файлів інструментів",
|
||||||
"settings.openchamber.visual.field.codeBlockLineWrapAria": "Переносити рядки блоків коду",
|
"settings.openchamber.visual.field.codeBlockLineWrapAria": "Переносити рядки блоків коду",
|
||||||
"settings.openchamber.visual.field.codeBlockLineWrap": "Переносити рядки блоків коду",
|
"settings.openchamber.visual.field.codeBlockLineWrap": "Переносити рядки блоків коду",
|
||||||
|
|||||||
@@ -1849,6 +1849,8 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': '在同一条回复中,如果助手文本块后面还有工具调用,则显示“复制回答”“保存为图片”和“朗读”操作。',
|
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': '在同一条回复中,如果助手文本块后面还有工具调用,则显示“复制回答”“保存为图片”和“朗读”操作。',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': '允许向子智能体会话发送提示',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': '允许向子智能体会话发送提示',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessions': '允许向子智能体会话发送提示',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessions': '允许向子智能体会话发送提示',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisible': '在新会话页面显示快捷入口',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisibleAria': '在新会话页面显示快捷入口',
|
||||||
'settings.openchamber.visual.field.showToolFileIconsAria': '显示工具文件图标',
|
'settings.openchamber.visual.field.showToolFileIconsAria': '显示工具文件图标',
|
||||||
'settings.openchamber.visual.field.codeBlockLineWrapAria': '代码块自动换行',
|
'settings.openchamber.visual.field.codeBlockLineWrapAria': '代码块自动换行',
|
||||||
'settings.openchamber.visual.field.codeBlockLineWrap': '代码块自动换行',
|
'settings.openchamber.visual.field.codeBlockLineWrap': '代码块自动换行',
|
||||||
|
|||||||
@@ -1755,6 +1755,8 @@
|
|||||||
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': '在同一則回覆中,如果助理文字區塊後方還有工具呼叫,則顯示「複製回答」「儲存為圖片」和「朗讀」操作。',
|
'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip': '在同一則回覆中,如果助理文字區塊後方還有工具呼叫,則顯示「複製回答」「儲存為圖片」和「朗讀」操作。',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': '允許向子 Agent 工作階段傳送提示',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessionsAria': '允許向子 Agent 工作階段傳送提示',
|
||||||
'settings.openchamber.visual.field.allowPromptingSubagentSessions': '允許向子 Agent 工作階段傳送提示',
|
'settings.openchamber.visual.field.allowPromptingSubagentSessions': '允許向子 Agent 工作階段傳送提示',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisible': '在新工作階段畫面顯示快速啟動項目',
|
||||||
|
'settings.openchamber.visual.field.draftStartersVisibleAria': '在新工作階段畫面顯示快速啟動項目',
|
||||||
'settings.openchamber.visual.field.showToolFileIconsAria': '顯示工具檔案圖示',
|
'settings.openchamber.visual.field.showToolFileIconsAria': '顯示工具檔案圖示',
|
||||||
'settings.openchamber.visual.field.codeBlockLineWrapAria': '程式碼區塊自動換行',
|
'settings.openchamber.visual.field.codeBlockLineWrapAria': '程式碼區塊自動換行',
|
||||||
'settings.openchamber.visual.field.codeBlockLineWrap': '程式碼區塊自動換行',
|
'settings.openchamber.visual.field.codeBlockLineWrap': '程式碼區塊自動換行',
|
||||||
|
|||||||
@@ -360,6 +360,7 @@ describe('updateDesktopSettings', () => {
|
|||||||
favoriteModels: [{ providerID: 'anthropic', modelID: 'claude-sonnet-4' }],
|
favoriteModels: [{ providerID: 'anthropic', modelID: 'claude-sonnet-4' }],
|
||||||
followUpBehavior: 'steer',
|
followUpBehavior: 'steer',
|
||||||
draftStarters: [{ type: 'command', name: 'runtime-a' }],
|
draftStarters: [{ type: 'command', name: 'runtime-a' }],
|
||||||
|
draftStartersVisible: false,
|
||||||
draftStartersCraftGoalAdded: true, draftStartersScheduleTaskAdded: true,
|
draftStartersCraftGoalAdded: true, draftStartersScheduleTaskAdded: true,
|
||||||
},
|
},
|
||||||
source: 'web',
|
source: 'web',
|
||||||
@@ -370,6 +371,7 @@ describe('updateDesktopSettings', () => {
|
|||||||
expect(useUIStore.getState().terminalShell).toBe('fish');
|
expect(useUIStore.getState().terminalShell).toBe('fish');
|
||||||
expect(useUIStore.getState().favoriteModels).toHaveLength(1);
|
expect(useUIStore.getState().favoriteModels).toHaveLength(1);
|
||||||
expect(useUIStore.getState().globalDraftStarters).toEqual([{ type: 'command', name: 'runtime-a' }]);
|
expect(useUIStore.getState().globalDraftStarters).toEqual([{ type: 'command', name: 'runtime-a' }]);
|
||||||
|
expect(useUIStore.getState().draftStartersVisible).toBe(false);
|
||||||
expect(useMessageQueueStore.getState().followUpBehavior).toBe('steer');
|
expect(useMessageQueueStore.getState().followUpBehavior).toBe('steer');
|
||||||
|
|
||||||
switchRuntimeEndpoint({ apiBaseUrl: 'https://preferences-b.example', runtimeKey: 'preferences-b' });
|
switchRuntimeEndpoint({ apiBaseUrl: 'https://preferences-b.example', runtimeKey: 'preferences-b' });
|
||||||
@@ -383,6 +385,7 @@ describe('updateDesktopSettings', () => {
|
|||||||
expect(useUIStore.getState().terminalShell).toBe('auto');
|
expect(useUIStore.getState().terminalShell).toBe('auto');
|
||||||
expect(useUIStore.getState().favoriteModels).toEqual([]);
|
expect(useUIStore.getState().favoriteModels).toEqual([]);
|
||||||
expect(useUIStore.getState().globalDraftStarters).toBeNull();
|
expect(useUIStore.getState().globalDraftStarters).toBeNull();
|
||||||
|
expect(useUIStore.getState().draftStartersVisible).toBe(true);
|
||||||
expect(useMessageQueueStore.getState().followUpBehavior).toBe('queue');
|
expect(useMessageQueueStore.getState().followUpBehavior).toBe('queue');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -568,6 +568,7 @@ const materializeAuthoritativeUiSettings = (settings: DesktopSettings): DesktopS
|
|||||||
expandedEditorToolbar: defaults.expandedEditorToolbar,
|
expandedEditorToolbar: defaults.expandedEditorToolbar,
|
||||||
wideChatLayoutEnabled: defaults.wideChatLayoutEnabled,
|
wideChatLayoutEnabled: defaults.wideChatLayoutEnabled,
|
||||||
showSplitAssistantMessageActions: defaults.showSplitAssistantMessageActions,
|
showSplitAssistantMessageActions: defaults.showSplitAssistantMessageActions,
|
||||||
|
draftStartersVisible: defaults.draftStartersVisible,
|
||||||
reportUsage: defaults.reportUsage,
|
reportUsage: defaults.reportUsage,
|
||||||
fontSize: defaults.fontSize,
|
fontSize: defaults.fontSize,
|
||||||
terminalFontSize: defaults.terminalFontSize,
|
terminalFontSize: defaults.terminalFontSize,
|
||||||
@@ -839,6 +840,9 @@ const applyDesktopUiPreferences = (settings: DesktopSettings) => {
|
|||||||
settings.draftStartersScheduleTaskAdded = true;
|
settings.draftStartersScheduleTaskAdded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (typeof settings.draftStartersVisible === 'boolean' && settings.draftStartersVisible !== store.draftStartersVisible) {
|
||||||
|
store.setDraftStartersVisible(settings.draftStartersVisible);
|
||||||
|
}
|
||||||
if (typeof settings.terminalFontSize === 'number' && Number.isFinite(settings.terminalFontSize) && settings.terminalFontSize !== store.terminalFontSize) {
|
if (typeof settings.terminalFontSize === 'number' && Number.isFinite(settings.terminalFontSize) && settings.terminalFontSize !== store.terminalFontSize) {
|
||||||
store.setTerminalFontSize(settings.terminalFontSize);
|
store.setTerminalFontSize(settings.terminalFontSize);
|
||||||
}
|
}
|
||||||
@@ -1043,6 +1047,9 @@ const sanitizeWebSettings = (payload: unknown): DesktopSettings | null => {
|
|||||||
if (Array.isArray(candidate.draftStarters)) {
|
if (Array.isArray(candidate.draftStarters)) {
|
||||||
result.draftStarters = sanitizeStarterRefs(candidate.draftStarters);
|
result.draftStarters = sanitizeStarterRefs(candidate.draftStarters);
|
||||||
}
|
}
|
||||||
|
if (typeof candidate.draftStartersVisible === 'boolean') {
|
||||||
|
result.draftStartersVisible = candidate.draftStartersVisible;
|
||||||
|
}
|
||||||
if (typeof candidate.draftStartersCraftGoalAdded === 'boolean') {
|
if (typeof candidate.draftStartersCraftGoalAdded === 'boolean') {
|
||||||
result.draftStartersCraftGoalAdded = candidate.draftStartersCraftGoalAdded;
|
result.draftStartersCraftGoalAdded = candidate.draftStartersCraftGoalAdded;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -275,6 +275,12 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
|
|||||||
descriptionKey: 'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip',
|
descriptionKey: 'settings.openchamber.visual.field.showSplitAssistantMessageActionsTooltip',
|
||||||
keywords: ['copy', 'save image', 'read aloud'],
|
keywords: ['copy', 'save image', 'read aloud'],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'chat.draft-starters-visible',
|
||||||
|
page: 'chat',
|
||||||
|
titleKey: 'settings.openchamber.visual.field.draftStartersVisible',
|
||||||
|
keywords: ['starter', 'starters', 'new session', 'welcome', 'suggestions'],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'chat.subagent-read-only-banner',
|
id: 'chat.subagent-read-only-banner',
|
||||||
page: 'chat',
|
page: 'chat',
|
||||||
|
|||||||
@@ -591,6 +591,7 @@ interface UIStore {
|
|||||||
fontSize: number;
|
fontSize: number;
|
||||||
// Global draft welcome starters; null = unset (use the default built-in set).
|
// Global draft welcome starters; null = unset (use the default built-in set).
|
||||||
globalDraftStarters: DraftStarterRef[] | null;
|
globalDraftStarters: DraftStarterRef[] | null;
|
||||||
|
draftStartersVisible: boolean;
|
||||||
terminalFontSize: number;
|
terminalFontSize: number;
|
||||||
terminalShell: TerminalShell;
|
terminalShell: TerminalShell;
|
||||||
terminalLoginShells: TerminalShell[];
|
terminalLoginShells: TerminalShell[];
|
||||||
@@ -751,6 +752,7 @@ interface UIStore {
|
|||||||
setMessageLimit: (value: number) => void;
|
setMessageLimit: (value: number) => void;
|
||||||
setFontSize: (size: number) => void;
|
setFontSize: (size: number) => void;
|
||||||
setGlobalDraftStarters: (refs: DraftStarterRef[]) => void;
|
setGlobalDraftStarters: (refs: DraftStarterRef[]) => void;
|
||||||
|
setDraftStartersVisible: (value: boolean) => void;
|
||||||
setTerminalFontSize: (size: number) => void;
|
setTerminalFontSize: (size: number) => void;
|
||||||
setTerminalShell: (shell: TerminalShell) => void;
|
setTerminalShell: (shell: TerminalShell) => void;
|
||||||
setTerminalLoginShells: (shells: TerminalShell[]) => void;
|
setTerminalLoginShells: (shells: TerminalShell[]) => void;
|
||||||
@@ -978,6 +980,7 @@ export const useUIStore = create<UIStore>()(
|
|||||||
expandedEditorToolbar: false,
|
expandedEditorToolbar: false,
|
||||||
showSplitAssistantMessageActions: false,
|
showSplitAssistantMessageActions: false,
|
||||||
allowPromptingSubagentSessions: false,
|
allowPromptingSubagentSessions: false,
|
||||||
|
draftStartersVisible: true,
|
||||||
isMobileSessionStatusBarCollapsed: false,
|
isMobileSessionStatusBarCollapsed: false,
|
||||||
mobileSessionPanelOpen: false,
|
mobileSessionPanelOpen: false,
|
||||||
mobileSessionFilterProjectId: null,
|
mobileSessionFilterProjectId: null,
|
||||||
@@ -1675,6 +1678,10 @@ export const useUIStore = create<UIStore>()(
|
|||||||
set({ globalDraftStarters: refs });
|
set({ globalDraftStarters: refs });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setDraftStartersVisible: (value) => {
|
||||||
|
set({ draftStartersVisible: value });
|
||||||
|
},
|
||||||
|
|
||||||
setTerminalFontSize: (size) => {
|
setTerminalFontSize: (size) => {
|
||||||
const rounded = Math.round(size);
|
const rounded = Math.round(size);
|
||||||
const clamped = Math.max(9, Math.min(52, rounded));
|
const clamped = Math.max(9, Math.min(52, rounded));
|
||||||
@@ -2420,6 +2427,7 @@ export const useUIStore = create<UIStore>()(
|
|||||||
expandedEditorToolbar: state.expandedEditorToolbar,
|
expandedEditorToolbar: state.expandedEditorToolbar,
|
||||||
showSplitAssistantMessageActions: state.showSplitAssistantMessageActions,
|
showSplitAssistantMessageActions: state.showSplitAssistantMessageActions,
|
||||||
allowPromptingSubagentSessions: state.allowPromptingSubagentSessions,
|
allowPromptingSubagentSessions: state.allowPromptingSubagentSessions,
|
||||||
|
draftStartersVisible: state.draftStartersVisible,
|
||||||
isMobileSessionStatusBarCollapsed: state.isMobileSessionStatusBarCollapsed,
|
isMobileSessionStatusBarCollapsed: state.isMobileSessionStatusBarCollapsed,
|
||||||
mobileSessionFilterProjectId: state.mobileSessionFilterProjectId,
|
mobileSessionFilterProjectId: state.mobileSessionFilterProjectId,
|
||||||
shortcutOverrides: state.shortcutOverrides,
|
shortcutOverrides: state.shortcutOverrides,
|
||||||
|
|||||||
@@ -248,6 +248,9 @@ export const createSettingsHelpers = (dependencies) => {
|
|||||||
}
|
}
|
||||||
result.draftStarters = starters;
|
result.draftStarters = starters;
|
||||||
}
|
}
|
||||||
|
if (typeof candidate.draftStartersVisible === 'boolean') {
|
||||||
|
result.draftStartersVisible = candidate.draftStartersVisible;
|
||||||
|
}
|
||||||
if (typeof candidate.draftStartersCraftGoalAdded === 'boolean') {
|
if (typeof candidate.draftStartersCraftGoalAdded === 'boolean') {
|
||||||
result.draftStartersCraftGoalAdded = candidate.draftStartersCraftGoalAdded;
|
result.draftStartersCraftGoalAdded = candidate.draftStartersCraftGoalAdded;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,14 @@ const createTestHelpersWithRealSanitizers = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
describe('settings helpers', () => {
|
describe('settings helpers', () => {
|
||||||
|
it('accepts only booleans for draft starter visibility', () => {
|
||||||
|
const helpers = createTestHelpers();
|
||||||
|
|
||||||
|
expect(helpers.sanitizeSettingsUpdate({ draftStartersVisible: true })).toEqual({ draftStartersVisible: true });
|
||||||
|
expect(helpers.sanitizeSettingsUpdate({ draftStartersVisible: false })).toEqual({ draftStartersVisible: false });
|
||||||
|
expect(helpers.sanitizeSettingsUpdate({ draftStartersVisible: 'false' })).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
it('accepts messageStreamTransport as a persisted shared setting', () => {
|
it('accepts messageStreamTransport as a persisted shared setting', () => {
|
||||||
const helpers = createTestHelpers();
|
const helpers = createTestHelpers();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user