mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-17 10:15:27 -04:00
Improve space toggles and email warmup
This commit is contained in:
+10
-2
@@ -456,7 +456,8 @@ def setup_email_routes():
|
|||||||
_IMAP_POOL = {} # account_id → (conn, last_used_at)
|
_IMAP_POOL = {} # account_id → (conn, last_used_at)
|
||||||
_IMAP_IDLE_MAX = 60.0
|
_IMAP_IDLE_MAX = 60.0
|
||||||
_WARMING_READS = set()
|
_WARMING_READS = set()
|
||||||
_WARM_READ_LIMIT = 24
|
_WARM_READ_LIMIT = 3
|
||||||
|
_WARM_MAX_BYTES = 128 * 1024
|
||||||
_WARM_RECENT_SECONDS = 7 * 24 * 60 * 60
|
_WARM_RECENT_SECONDS = 7 * 24 * 60 * 60
|
||||||
_pool_lock = _threading.Lock()
|
_pool_lock = _threading.Lock()
|
||||||
|
|
||||||
@@ -1322,9 +1323,16 @@ def setup_email_routes():
|
|||||||
epoch = 0
|
epoch = 0
|
||||||
if epoch and now - epoch > _WARM_RECENT_SECONDS:
|
if epoch and now - epoch > _WARM_RECENT_SECONDS:
|
||||||
continue
|
continue
|
||||||
|
try:
|
||||||
|
size = int((em or {}).get("size") or 0)
|
||||||
|
except Exception:
|
||||||
|
size = 0
|
||||||
|
if size > _WARM_MAX_BYTES:
|
||||||
|
continue
|
||||||
ck = _read_cache_key(account_id, folder, uid, owner=owner)
|
ck = _read_cache_key(account_id, folder, uid, owner=owner)
|
||||||
if _read_cache_get(ck) is not None or ck in _WARMING_READS:
|
if _read_cache_get(ck) is not None or ck in _WARMING_READS:
|
||||||
continue
|
continue
|
||||||
|
_WARMING_READS.add(ck)
|
||||||
selected.append((uid, ck))
|
selected.append((uid, ck))
|
||||||
if len(selected) >= _WARM_READ_LIMIT:
|
if len(selected) >= _WARM_READ_LIMIT:
|
||||||
break
|
break
|
||||||
@@ -1334,8 +1342,8 @@ def setup_email_routes():
|
|||||||
async def _warm():
|
async def _warm():
|
||||||
for uid, ck in selected:
|
for uid, ck in selected:
|
||||||
if _read_cache_get(ck) is not None:
|
if _read_cache_get(ck) is not None:
|
||||||
|
_WARMING_READS.discard(ck)
|
||||||
continue
|
continue
|
||||||
_WARMING_READS.add(ck)
|
|
||||||
try:
|
try:
|
||||||
result = await _asyncio.to_thread(_read_email_sync, uid, folder, account_id, owner, False)
|
result = await _asyncio.to_thread(_read_email_sync, uid, folder, account_id, owner, False)
|
||||||
if result and not result.get("error"):
|
if result and not result.get("error"):
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
import { previewZoneAt, clearPreview, snapModalToZone } from './tileManager.js';
|
import { previewZoneAt, clearPreview, snapModalToZone } from './tileManager.js';
|
||||||
import { suspendDock, resumeDock, clearRightDock, applyEdgeDock } from './modalSnap.js';
|
import { suspendDock, resumeDock, clearRightDock, applyEdgeDock } from './modalSnap.js';
|
||||||
|
|
||||||
const _state = new Map(); // id -> { restoreFn, closeFn, railBtnId, isMinimized }
|
const _state = new Map(); // id -> { restoreFn, closeFn, railBtnId, isMinimized, restoreMinHeight }
|
||||||
|
|
||||||
const _rememberedDockKey = (id) => `odysseus-modal-remembered-dock-${id}`;
|
const _rememberedDockKey = (id) => `odysseus-modal-remembered-dock-${id}`;
|
||||||
function _rememberDock(id, side) {
|
function _rememberDock(id, side) {
|
||||||
@@ -73,6 +73,26 @@ function _emitModalOpened(id, modal) {
|
|||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _captureRestoreHeight(modal, state) {
|
||||||
|
if (!modal || !state) return;
|
||||||
|
const content = modal.querySelector('.modal-content');
|
||||||
|
if (!content) return;
|
||||||
|
const rect = content.getBoundingClientRect();
|
||||||
|
if (!rect || rect.height < 120) return;
|
||||||
|
const maxHeight = Math.max(180, window.innerHeight - 24);
|
||||||
|
state.restoreMinHeight = `${Math.round(Math.min(rect.height, maxHeight))}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _applyRestoreHeight(modal, state) {
|
||||||
|
if (!modal || !state?.restoreMinHeight) return;
|
||||||
|
const content = modal.querySelector('.modal-content');
|
||||||
|
if (!content) return;
|
||||||
|
const maxHeight = Math.max(180, window.innerHeight - 24);
|
||||||
|
const requested = parseInt(state.restoreMinHeight, 10);
|
||||||
|
const height = Number.isFinite(requested) ? Math.min(requested, maxHeight) : null;
|
||||||
|
if (height) content.style.minHeight = `${height}px`;
|
||||||
|
}
|
||||||
|
|
||||||
function _setBadge(btnIds, on) {
|
function _setBadge(btnIds, on) {
|
||||||
if (!btnIds) return;
|
if (!btnIds) return;
|
||||||
const ids = Array.isArray(btnIds) ? btnIds : [btnIds];
|
const ids = Array.isArray(btnIds) ? btnIds : [btnIds];
|
||||||
@@ -1109,6 +1129,7 @@ export function register(id, { restoreFn, closeFn, railBtnId, sidebarBtnId, labe
|
|||||||
closeFn: closeFn || (() => {}),
|
closeFn: closeFn || (() => {}),
|
||||||
btnIds,
|
btnIds,
|
||||||
isMinimized: false,
|
isMinimized: false,
|
||||||
|
restoreMinHeight: '',
|
||||||
});
|
});
|
||||||
// Auto-stack: whichever modal becomes visible last sits on top of any
|
// Auto-stack: whichever modal becomes visible last sits on top of any
|
||||||
// already-open modals. The various tool open() functions (gallery,
|
// already-open modals. The various tool open() functions (gallery,
|
||||||
@@ -1188,6 +1209,7 @@ export function minimize(id) {
|
|||||||
// and let the chip drive restore/close via the registered functions.
|
// and let the chip drive restore/close via the registered functions.
|
||||||
const modal = document.getElementById(id);
|
const modal = document.getElementById(id);
|
||||||
if (modal) {
|
if (modal) {
|
||||||
|
_captureRestoreHeight(modal, s);
|
||||||
// If this window is edge-docked (right/left), SUSPEND the dock: release
|
// If this window is edge-docked (right/left), SUSPEND the dock: release
|
||||||
// the body push so the chat returns to full width while the window is
|
// the body push so the chat returns to full width while the window is
|
||||||
// minimized, but keep the dock so restoring the chip snaps it back in.
|
// minimized, but keep the dock so restoring the chip snaps it back in.
|
||||||
@@ -1218,6 +1240,7 @@ export function restore(id) {
|
|||||||
if (modal) {
|
if (modal) {
|
||||||
modal.classList.remove('hidden', 'modal-minimized');
|
modal.classList.remove('hidden', 'modal-minimized');
|
||||||
modal.style.display = '';
|
modal.style.display = '';
|
||||||
|
_applyRestoreHeight(modal, s);
|
||||||
// Surface above any already-open tool window — restoring from the dock
|
// Surface above any already-open tool window — restoring from the dock
|
||||||
// should bring this tool to the front, not leave it stuck behind one with
|
// should bring this tool to the front, not leave it stuck behind one with
|
||||||
// a higher static z-index.
|
// a higher static z-index.
|
||||||
|
|||||||
+76
-6
@@ -5,10 +5,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import themeModule from './theme.js';
|
import themeModule from './theme.js';
|
||||||
|
import * as Modals from './modalManager.js';
|
||||||
|
|
||||||
let toastEl = null;
|
let toastEl = null;
|
||||||
let autoScrollEnabled = true;
|
let autoScrollEnabled = true;
|
||||||
let hoveredToggleCard = null;
|
let hoveredToggleCard = null;
|
||||||
|
let hoveredToggleWindow = null;
|
||||||
|
let hoveredDockChip = null;
|
||||||
|
|
||||||
// Smooth scroll state
|
// Smooth scroll state
|
||||||
let _scrollRafId = null;
|
let _scrollRafId = null;
|
||||||
@@ -19,25 +22,92 @@ function _isTextEditingTarget(target) {
|
|||||||
return !!(el && el.closest('input, textarea, select, [contenteditable="true"], [contenteditable=""]'));
|
return !!(el && el.closest('input, textarea, select, [contenteditable="true"], [contenteditable=""]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SPACE_CARD_SELECTOR = [
|
||||||
|
'#email-lib-modal .doclib-card',
|
||||||
|
'#doclib-modal .doclib-card',
|
||||||
|
'#memory-modal .doclib-card',
|
||||||
|
'#tasks-modal .task-card',
|
||||||
|
'#tasks-modal .task-log-row',
|
||||||
|
'#research-overlay [data-job-id]',
|
||||||
|
'#cookbook-modal .doclib-card',
|
||||||
|
'.email-reader-tab-modal .doclib-card',
|
||||||
|
'.email-window-modal .doclib-card',
|
||||||
|
].join(', ');
|
||||||
|
|
||||||
|
const SPACE_BLOCKED_SELECTOR = [
|
||||||
|
'button',
|
||||||
|
'a',
|
||||||
|
'input',
|
||||||
|
'textarea',
|
||||||
|
'select',
|
||||||
|
'[contenteditable="true"]',
|
||||||
|
'[contenteditable=""]',
|
||||||
|
'.recipient-chip',
|
||||||
|
'.doclib-card-dropdown',
|
||||||
|
'.email-card-dropdown',
|
||||||
|
'.task-log-row-actions',
|
||||||
|
'.modal-header',
|
||||||
|
].join(', ');
|
||||||
|
|
||||||
|
function _visibleModalForSpace(win) {
|
||||||
|
const modal = win?.closest?.('.modal[id]');
|
||||||
|
if (!modal || modal.classList.contains('hidden') || modal.classList.contains('modal-minimized')) return null;
|
||||||
|
return modal;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _isSpaceVisible(el) {
|
||||||
|
if (!el || !document.contains(el)) return false;
|
||||||
|
if (el.closest?.('.modal.hidden, .modal.modal-minimized, [hidden]')) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _spaceWindowId(win) {
|
||||||
|
if (!win || !document.contains(win)) return null;
|
||||||
|
const modal = _visibleModalForSpace(win);
|
||||||
|
if (modal && Modals.isRegistered(modal.id)) return modal.id;
|
||||||
|
if (win.closest?.('.doc-editor-pane') && Modals.isRegistered('doc-panel') && !Modals.isMinimized('doc-panel')) return 'doc-panel';
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function _initHoverCardSpaceToggle() {
|
function _initHoverCardSpaceToggle() {
|
||||||
if (document._odysseusHoverCardSpaceToggle) return;
|
if (document._odysseusHoverCardSpaceToggle) return;
|
||||||
document._odysseusHoverCardSpaceToggle = true;
|
document._odysseusHoverCardSpaceToggle = true;
|
||||||
document.addEventListener('pointerover', (e) => {
|
document.addEventListener('pointerover', (e) => {
|
||||||
const card = e.target?.closest?.('#email-lib-modal .doclib-card, #doclib-modal .doclib-card, .email-reader-tab-modal .doclib-card, .email-window-modal .doclib-card');
|
const chip = e.target?.closest?.('.minimized-dock-chip[data-modal-id]');
|
||||||
|
if (chip) hoveredDockChip = chip;
|
||||||
|
const card = e.target?.closest?.(SPACE_CARD_SELECTOR);
|
||||||
if (card) hoveredToggleCard = card;
|
if (card) hoveredToggleCard = card;
|
||||||
|
const win = e.target?.closest?.('.modal:not(.hidden):not(.modal-minimized) .modal-content, .doc-editor-pane');
|
||||||
|
if (win) hoveredToggleWindow = win;
|
||||||
}, true);
|
}, true);
|
||||||
document.addEventListener('pointerout', (e) => {
|
document.addEventListener('pointerout', (e) => {
|
||||||
if (!hoveredToggleCard) return;
|
|
||||||
const next = e.relatedTarget;
|
const next = e.relatedTarget;
|
||||||
if (!next || !hoveredToggleCard.contains(next)) hoveredToggleCard = null;
|
if (hoveredDockChip && (!next || !hoveredDockChip.contains(next))) hoveredDockChip = null;
|
||||||
|
if (hoveredToggleCard && (!next || !hoveredToggleCard.contains(next))) hoveredToggleCard = null;
|
||||||
|
if (hoveredToggleWindow && (!next || !hoveredToggleWindow.contains(next))) hoveredToggleWindow = null;
|
||||||
}, true);
|
}, true);
|
||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
if (e.code !== 'Space' || e.repeat || !hoveredToggleCard || !document.contains(hoveredToggleCard)) return;
|
if (e.code !== 'Space' || e.repeat) return;
|
||||||
if (_isTextEditingTarget(e.target)) return;
|
if (_isTextEditingTarget(e.target)) return;
|
||||||
const blocked = e.target?.closest?.('button, a, input, textarea, select, [contenteditable="true"], [contenteditable=""], .recipient-chip, .doclib-card-dropdown, .email-card-dropdown');
|
const blocked = e.target?.closest?.(SPACE_BLOCKED_SELECTOR);
|
||||||
if (blocked) return;
|
if (blocked) return;
|
||||||
|
if (hoveredToggleCard && _isSpaceVisible(hoveredToggleCard)) {
|
||||||
|
e.preventDefault();
|
||||||
|
hoveredToggleCard.click();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (hoveredDockChip && document.contains(hoveredDockChip)) {
|
||||||
|
const id = hoveredDockChip.dataset.modalId;
|
||||||
|
if (id && Modals.isRegistered(id)) {
|
||||||
|
e.preventDefault();
|
||||||
|
Modals.restore(id);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const id = _spaceWindowId(hoveredToggleWindow);
|
||||||
|
if (!id) return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
hoveredToggleCard.click();
|
Modals.minimize(id);
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user