Changeset 0.7.3 (#41)

This commit is contained in:
2026-02-21 21:59:38 +00:00
parent 416e5439ea
commit 1ec392879b
26 changed files with 1084 additions and 319 deletions

View File

@@ -6,11 +6,13 @@
<base href="%%BASE_HREF%%">
<script>window.__BASE__ = '%%BASE_PATH%%';</script>
<script>window.__VERSION__ = '%%APP_VERSION%%'; if (window.__VERSION__.includes('%%')) window.__VERSION__ = 'dev';</script>
<script>try { window.__BRANDING__ = %%BRANDING_JSON%%; } catch(e) { window.__BRANDING__ = {}; }</script>
<title>Chat Switchboard</title>
<link rel="icon" type="image/svg+xml" href="favicon.svg">
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32.png">
<link rel="apple-touch-icon" sizes="192x192" href="favicon-192.png">
<link rel="stylesheet" href="css/styles.css?v=%%APP_VERSION%%">
<link rel="stylesheet" href="branding/custom.css" onerror="this.remove()">
</head>
<body>
@@ -25,9 +27,9 @@
<aside class="sidebar" id="sidebar">
<div class="sidebar-top">
<button class="sb-brand" id="sidebarToggle" title="Toggle sidebar">
<span class="brand-logo">🔀</span>
<span class="brand-logo" id="brandSidebarLogo">🔀</span>
<svg class="brand-collapse" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="9" y1="3" x2="9" y2="21"/></svg>
<span class="sb-label brand-text">Chat Switchboard</span>
<span class="sb-label brand-text" id="brandSidebarText">Chat Switchboard</span>
</button>
<div class="split-btn" style="position:relative">
<button class="split-btn-main" id="newChatBtn" title="New Chat">
@@ -147,7 +149,8 @@
<div class="splash-hero">
<div class="hero-content">
<div class="hero-logo-row">
<svg class="hero-logo-mark" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<div class="hero-logo-mark" id="brandLogo">
<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<rect width="64" height="64" rx="12" fill="#1a1a2e"/>
<path d="M12 48 L36 16" stroke="#6c9fff" stroke-width="5.5" stroke-linecap="round" fill="none"/>
<polygon points="42,12 34,14 38,22" fill="#6c9fff"/>
@@ -155,11 +158,12 @@
<path d="M30 38 L36 48" stroke="#a78bfa" stroke-width="5.5" stroke-linecap="round" fill="none"/>
<polygon points="42,52 34,50 38,42" fill="#a78bfa"/>
</svg>
<div class="hero-wordmark">Chat <span>Switchboard</span></div>
</div>
<div class="hero-wordmark" id="brandWordmark">Chat <span>Switchboard</span></div>
</div>
<h1 class="hero-headline">One interface.<br>Every AI model.</h1>
<p class="hero-sub">Route conversations to OpenAI, Anthropic, and any OpenAI-compatible provider from a single, self-hosted chat interface. Bring your own keys. Keep your data.</p>
<div class="hero-features">
<h1 class="hero-headline" id="brandHeadline">One interface.<br>Every AI model.</h1>
<p class="hero-sub" id="brandTagline">Route conversations to OpenAI, Anthropic, and any OpenAI-compatible provider from a single, self-hosted chat interface. Bring your own keys. Keep your data.</p>
<div class="hero-features" id="brandPills">
<div class="hero-pill accent"><span class="pill-icon"></span> Streaming responses</div>
<div class="hero-pill purple"><span class="pill-icon">🔀</span> Multi-provider routing</div>
<div class="hero-pill"><span class="pill-icon">🔑</span> Bring your own API keys</div>
@@ -196,7 +200,7 @@
<button class="btn-primary btn-full" id="authRegisterBtn" data-label="Create Account" onclick="handleRegister()" style="display:none">Create Account</button>
</div>
<div class="auth-footer">
<p>Self-hosted AI chat &middot; Your keys, your data</p>
<p id="brandAuthFooter">Self-hosted AI chat &middot; Your keys, your data</p>
</div>
</div>
</div>
@@ -217,6 +221,17 @@
<div class="settings-tab-content" id="settingsGeneralTab">
<section class="settings-section">
<h3>Profile</h3>
<div class="avatar-upload-row">
<div class="avatar-preview" id="avatarPreview">
<span id="avatarPreviewLetter">?</span>
</div>
<div class="avatar-actions">
<button class="btn-small" id="avatarUploadBtn">Upload Photo</button>
<button class="btn-small btn-danger" id="avatarRemoveBtn" style="display:none">Remove</button>
<input type="file" id="avatarFileInput" accept="image/png,image/jpeg,image/gif" style="display:none">
<div class="form-hint">Auto-resized to 128×128</div>
</div>
</div>
<div class="form-group"><label>Display Name</label><input type="text" id="profileDisplayName"></div>
<div class="form-group"><label>Email</label><input type="email" id="profileEmail"></div>
<button class="btn-small" id="profileChangePwBtn">Change Password</button>
@@ -350,6 +365,17 @@
<div class="form-group"><label>Name</label><input type="text" id="adminPresetName" placeholder="Code Reviewer"></div>
<div class="form-group"><label>Icon</label><input type="text" id="adminPresetIcon" placeholder="🔍" maxlength="4" style="width:60px"></div>
</div>
<div class="avatar-upload-row" style="margin-bottom:0.75rem">
<div class="avatar-preview avatar-preview-sm" id="presetAvatarPreview">
<span id="presetAvatarPlaceholder">🤖</span>
</div>
<div class="avatar-actions">
<button class="btn-small" type="button" id="presetAvatarUploadBtn">Upload Avatar</button>
<button class="btn-small btn-danger" type="button" id="presetAvatarRemoveBtn" style="display:none">Remove</button>
<input type="file" id="presetAvatarFileInput" accept="image/png,image/jpeg,image/gif" style="display:none">
<div class="form-hint">Optional · 128×128 · shown in chat</div>
</div>
</div>
<div class="form-group"><label>Description</label><input type="text" id="adminPresetDesc" placeholder="Reviews code for best practices"></div>
<div class="form-row">
<div class="form-group"><label>Base Model</label><select id="adminPresetModel"></select></div>