Refactor GeneralSettings.jsx to organize settings by panel and improve UI structure
This commit is contained in:
@@ -503,29 +503,36 @@ export default function GeneralSettings({
|
||||
const rerankingModelOptions = buildSelectOptions(rerankingModels, rerankModel, 'saved model unavailable', showMissingModelLabel);
|
||||
const transcriptionModelOptions = buildSelectOptions(whisperModels, transcriptionModel, 'saved model unavailable', showMissingModelLabel);
|
||||
|
||||
if (panel === 'AI Models') {
|
||||
return (
|
||||
<div className="settings-content-panel">
|
||||
<div className="setting-section">
|
||||
<h3>Heimgeist Backend URL</h3>
|
||||
<input
|
||||
type="text"
|
||||
className="input"
|
||||
value={backendApiUrl}
|
||||
onChange={handleBackendUrlChange}
|
||||
placeholder={`e.g., ${DEFAULT_BACKEND_API_URL}`}
|
||||
/>
|
||||
<p className="setting-description">Internal UI requests like chats, sessions, and databases go to this URL.</p>
|
||||
<h3>Chat Model</h3>
|
||||
<select
|
||||
className="select"
|
||||
value={selectedModel}
|
||||
onChange={handleModelChange}
|
||||
>
|
||||
{chatModelOptions.length === 0 && <option value="">{isLoadingModelCatalog ? 'Loading models…' : '— No chat models available —'}</option>}
|
||||
{chatModelOptions.map(model => <option key={model.value} value={model.value}>{model.label}</option>)}
|
||||
</select>
|
||||
<p className="setting-description">
|
||||
Heimgeist uses this model for normal text chat.
|
||||
</p>
|
||||
</div>
|
||||
<div className="setting-section">
|
||||
<h3>Ollama URL</h3>
|
||||
<input
|
||||
type="text"
|
||||
className="input"
|
||||
value={ollamaApiUrl}
|
||||
onChange={handleOllamaUrlChange}
|
||||
placeholder={`e.g., ${DEFAULT_OLLAMA_API_URL}`}
|
||||
/>
|
||||
<p className="setting-description">Heimgeist uses this URL to talk to Ollama for models and chat generation.</p>
|
||||
<h3>Vision Model</h3>
|
||||
<select
|
||||
className="select"
|
||||
value={visionModel}
|
||||
onChange={handleVisionModelChange}
|
||||
>
|
||||
{visionModelOptions.length === 0 && <option value="">{isLoadingModelCatalog ? 'Loading models…' : '— No vision models available —'}</option>}
|
||||
{visionModelOptions.map(model => <option key={model.value} value={model.value}>{model.label}</option>)}
|
||||
</select>
|
||||
<p className="setting-description">
|
||||
Heimgeist uses this model when a chat message includes image attachments.
|
||||
</p>
|
||||
</div>
|
||||
<div className="setting-section">
|
||||
<h3>Embedding Model</h3>
|
||||
@@ -560,27 +567,11 @@ export default function GeneralSettings({
|
||||
</p>
|
||||
</div>
|
||||
<div className="setting-section">
|
||||
<h3>Audio Input</h3>
|
||||
<label className="toggle-switch">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={audioInputEnabled}
|
||||
onChange={handleAudioInputToggle}
|
||||
disabled={!audioInputSupported}
|
||||
/>
|
||||
<span className="slider"></span>
|
||||
</label>
|
||||
<p className="setting-description">
|
||||
Enables microphone transcription in the chat composer. Heimgeist records locally and sends the clip to the local Whisper runtime.
|
||||
</p>
|
||||
{audioInputEnabled && (
|
||||
<>
|
||||
<div className="setting-control-row">
|
||||
<h3>Transcription Model</h3>
|
||||
<select
|
||||
className="select"
|
||||
value={transcriptionModel}
|
||||
onChange={handleTranscriptionModelChange}
|
||||
disabled={!audioInputSupported}
|
||||
>
|
||||
{transcriptionModelOptions.length === 0 && <option value="">{isLoadingModelCatalog ? 'Loading models…' : '— No Whisper models available —'}</option>}
|
||||
{transcriptionModelOptions.map(model => (
|
||||
@@ -589,6 +580,20 @@ export default function GeneralSettings({
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<p className="setting-description">
|
||||
Heimgeist uses this Whisper model for microphone transcription.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (panel === 'Microphone') {
|
||||
return (
|
||||
<div className="settings-content-panel">
|
||||
<div className="setting-section">
|
||||
<h3>Microphone</h3>
|
||||
<div className="setting-control-row">
|
||||
<select
|
||||
className="select"
|
||||
value={audioInputDeviceId}
|
||||
@@ -627,53 +632,19 @@ export default function GeneralSettings({
|
||||
<p className={`setting-status ${audioInputStatus.tone}`}>{audioInputStatus.message}</p>
|
||||
)}
|
||||
<p className="setting-description">
|
||||
Select the Whisper model Heimgeist should use for microphone transcription.
|
||||
Microphone input is available in the chat composer. Heimgeist records locally and sends the clip to the configured Whisper model.
|
||||
</p>
|
||||
<p className="setting-description">
|
||||
Whisper can auto-detect the spoken language, but you can force a fixed input language here when auto-detection drifts.
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="setting-section">
|
||||
<h3>Chat Model</h3>
|
||||
<select
|
||||
className="select"
|
||||
value={selectedModel}
|
||||
onChange={handleModelChange}
|
||||
>
|
||||
{chatModelOptions.length === 0 && <option value="">{isLoadingModelCatalog ? 'Loading models…' : '— No chat models available —'}</option>}
|
||||
{chatModelOptions.map(model => <option key={model.value} value={model.value}>{model.label}</option>)}
|
||||
</select>
|
||||
<p className="setting-description">
|
||||
Heimgeist uses this model for normal text chat.
|
||||
</p>
|
||||
</div>
|
||||
<div className="setting-section">
|
||||
<h3>Vision Model</h3>
|
||||
<select
|
||||
className="select"
|
||||
value={visionModel}
|
||||
onChange={handleVisionModelChange}
|
||||
>
|
||||
{visionModelOptions.length === 0 && <option value="">{isLoadingModelCatalog ? 'Loading models…' : '— No vision models available —'}</option>}
|
||||
{visionModelOptions.map(model => <option key={model.value} value={model.value}>{model.label}</option>)}
|
||||
</select>
|
||||
<p className="setting-description">
|
||||
Heimgeist uses this model when a chat message includes image attachments.
|
||||
</p>
|
||||
</div>
|
||||
<div className="setting-section">
|
||||
<h3>Stream Output</h3>
|
||||
<label className="toggle-switch">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={streamOutput}
|
||||
onChange={handleStreamToggle}
|
||||
/>
|
||||
<span className="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (panel === 'Updates') {
|
||||
return (
|
||||
<div className="settings-content-panel">
|
||||
<div className="setting-section">
|
||||
<h3>Updates</h3>
|
||||
<div className="setting-control-row">
|
||||
@@ -702,6 +673,13 @@ export default function GeneralSettings({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (panel === 'Advanced') {
|
||||
return (
|
||||
<div className="settings-content-panel">
|
||||
<div className="setting-section danger-zone">
|
||||
<h3>Purge Databases</h3>
|
||||
<div className="setting-control-row">
|
||||
@@ -726,3 +704,6 @@ export default function GeneralSettings({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user