mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-20 19:55:25 -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:
@@ -22,6 +22,7 @@ import {
|
||||
_tryFoldHintSig, _foldSignature, _SIG_ICON, _QUOTE_ICON,
|
||||
} from './emailLibrary/signatureFold.js';
|
||||
import { state } from './emailLibrary/state.js';
|
||||
import { collapseSidebarToRail } from './modalSnap.js';
|
||||
|
||||
const API_BASE = window.location.origin;
|
||||
let _emailUnreadChipClickWired = false;
|
||||
@@ -406,7 +407,14 @@ function _clearEmailDocumentSplit() {
|
||||
].forEach(prop => docPane.style.removeProperty(prop));
|
||||
}
|
||||
|
||||
function _hasDesktopRoomForEmailAndDocument(modal) {
|
||||
// Compute the left-edge x assuming the wide sidebar has collapsed to the
|
||||
// rail. Used by the "try collapsing the sidebar first" path so we can decide
|
||||
// whether collapsing recovers enough room before minimizing email.
|
||||
function _emailSplitLeftEdgeIfSidebarCollapsed() {
|
||||
return _readCssPx('--icon-rail-w');
|
||||
}
|
||||
|
||||
function _hasDesktopRoomForEmailAndDocument(modal, opts = {}) {
|
||||
if (window.innerWidth <= 768) return false;
|
||||
if (window.innerWidth >= 1100) return true;
|
||||
const content = modal?.querySelector?.('.modal-content');
|
||||
@@ -416,9 +424,12 @@ function _hasDesktopRoomForEmailAndDocument(modal) {
|
||||
const emailWidth = isFullscreen
|
||||
? Math.min(440, Math.max(360, Math.round(window.innerWidth * 0.30)))
|
||||
: Math.max(360, Math.round(rect?.width || 440));
|
||||
const docMinWidth = 560;
|
||||
const breathingRoom = 72;
|
||||
const leftEdge = isFullscreen ? _emailSplitLeftEdge() : Math.max(0, Math.round(rect?.left || _emailSplitLeftEdge()));
|
||||
// Relaxed thresholds — the old 560 + 72 forced an unnecessary tab-down
|
||||
// on ~1200–1300px viewports where there was visually plenty of room.
|
||||
const docMinWidth = 460;
|
||||
const breathingRoom = 40;
|
||||
const leftEdgeNow = isFullscreen ? _emailSplitLeftEdge() : Math.max(0, Math.round(rect?.left || _emailSplitLeftEdge()));
|
||||
const leftEdge = opts.assumeSidebarCollapsed ? _emailSplitLeftEdgeIfSidebarCollapsed() : leftEdgeNow;
|
||||
return (window.innerWidth - leftEdge - emailWidth) >= (docMinWidth + breathingRoom);
|
||||
}
|
||||
|
||||
@@ -426,8 +437,18 @@ function _prepareEmailWindowForDocument(modal) {
|
||||
if (window.innerWidth <= 768) return true;
|
||||
if (!modal) return false;
|
||||
if (!_hasDesktopRoomForEmailAndDocument(modal)) {
|
||||
_clearEmailDocumentSplit();
|
||||
return true;
|
||||
// Before giving up and minimizing email, see if collapsing the wide
|
||||
// sidebar to the rail would recover enough space. The route-collapse
|
||||
// marker that collapseSidebarToRail() sets makes the existing
|
||||
// auto-restore logic put the sidebar back when the doc closes.
|
||||
const sidebar = document.getElementById('sidebar');
|
||||
const sidebarWasOpen = sidebar && !sidebar.classList.contains('hidden');
|
||||
if (sidebarWasOpen && _hasDesktopRoomForEmailAndDocument(modal, { assumeSidebarCollapsed: true })) {
|
||||
try { collapseSidebarToRail(); } catch (_) {}
|
||||
} else {
|
||||
_clearEmailDocumentSplit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (modal.classList.contains('modal-left-docked')) {
|
||||
const content = modal.querySelector('.modal-content');
|
||||
|
||||
Reference in New Issue
Block a user