mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-28 07:35:27 -04:00
Settings overhaul + UI polish pass
Two months of iteration on the Settings panel, integration forms, and small visual nudges across the app. Highlights: Settings restructure - Add Models: split into separate Local + API cards (no more in-card tabs); each fuses Type/Provider with the URL input. - Added Models: new dedicated sidebar tab, with Probe + Clear-offline pulled into its header; Local/API sub-section icons accent-tinted. - Search: Web Search and a new Deep Research card (Model + tuning), with a cross-link to AI Defaults. Provider hints use real clickable anchors; Web Search Test button shows a whirlpool spinner. - AI Defaults: Image Generation card returns; Research Model card carries only Endpoint+Model with a cross-link to Search; Vision / Default / Utility fallbacks unified under one numbered-row design matching Search's chain. - API Permissions (was 'API Tokens'): per-row rename, inline Permissions toggle that expands the scope-edit panel, in-field copy icons (icon→check on success). Empty state accent-tinted. - Integrations: + Add Integration drops a type-picker menu directly under the button (drop-up on tight viewports); each integration form (API, CalDAV, CardDAV, Email, Codex/Claude, Vault, MCP) uses the same accent-outlined Save/Test/Cancel buttons right-aligned. - Danger Zone: Wipe→Delete with trash icons; new 'Delete everything' row at the bottom that loops every category. AI Synthesis (Reminders) - Persona dropdown sourced from PROMPT_TEMPLATES + custom preset. - src/reminder_personas.py mirrors the five built-ins for the server-side synthesis path. - dispatch_reminder() reads reminder_llm_persona and uses the persona's system prompt; empty/unknown falls back to warm-neutral. Esc handling - Kebab menus and the provider picker intercept Esc in capture phase so dismissing a popup no longer closes the whole Settings modal. Accent tinting - Scoped CSS rule across data-settings-panel=ai/services/added-models/ search/integrations/reminders for card h2 icons + the Added Models sub-section icons. Codex/Claude integration form - No more auto-creation on form open — explicit Create token button. - New tokens start with every scope granted; existing tokens move out of the integration form into the API Permissions card. - Setup reveal: copy buttons inline inside the token + setup code blocks; shorter subtitle wording. Misc visual polish - Save/Test/Cancel uniformly accent-outlined and right-aligned on every integration form. - Provider logos render inline next to the search fallback selects and the Deep Research Search dropdown. - Trash icons in fallback rows bumped to 20x20 so they fill the 32px button. - Image generation default flipped to off.
This commit is contained in:
+28
-1
@@ -146,4 +146,31 @@ export function providerLabel(endpointUrl) {
|
||||
return host.replace(/^api\./i, "");
|
||||
}
|
||||
|
||||
export default { providerLogo, providerLabel };
|
||||
// Map endpoint URL → logo SVG using the same model-id regex catalog.
|
||||
// Tests host + port + path so loopback servers (e.g. Ollama on
|
||||
// localhost:11434) still match by port. Falls back to null when nothing
|
||||
// recognises the URL, so callers can render a neutral placeholder.
|
||||
export function providerLogoFromUrl(url) {
|
||||
if (!url) return null;
|
||||
let host = '', port = '', path = '';
|
||||
try {
|
||||
const u = new URL(url);
|
||||
host = u.hostname; port = u.port; path = u.pathname || '';
|
||||
} catch (_) {
|
||||
const raw = String(url).replace(/^[a-z]+:\/\//i, '');
|
||||
const slashIdx = raw.indexOf('/');
|
||||
const hostport = slashIdx >= 0 ? raw.slice(0, slashIdx) : raw;
|
||||
path = slashIdx >= 0 ? raw.slice(slashIdx) : '';
|
||||
const colon = hostport.lastIndexOf(':');
|
||||
host = colon >= 0 ? hostport.slice(0, colon) : hostport;
|
||||
port = colon >= 0 ? hostport.slice(colon + 1) : '';
|
||||
}
|
||||
// Build candidate strings to test against the provider catalog.
|
||||
const candidates = [host, port ? `${host}:${port}` : '', port ? `:${port}` : '', path].filter(Boolean);
|
||||
for (const [re, svg] of _PROVIDERS) {
|
||||
if (candidates.some(c => re.test(c))) return svg;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export default { providerLogo, providerLabel, providerLogoFromUrl };
|
||||
|
||||
Reference in New Issue
Block a user