Polish email send and card toggles

This commit is contained in:
pewdiepie-archdaemon
2026-06-01 13:52:07 +09:00
parent 7023468cea
commit 8218421733
3 changed files with 131 additions and 3 deletions

View File

@@ -2824,8 +2824,9 @@ import * as Modals from './modalManager.js';
onAction: () => { canceled = true; },
});
}
detachedEmailDoc = _detachActiveEmailForBackground(sendDocId);
await _sleep(1200);
await _sleep(1000);
if (!canceled) detachedEmailDoc = _detachActiveEmailForBackground(sendDocId);
await _sleep(200);
if (canceled) {
_restoreDetachedEmailDoc(detachedEmailDoc);
detachedEmailDoc = null;
@@ -2837,6 +2838,7 @@ import * as Modals from './modalManager.js';
if (uiModule) {
uiModule.showToast('Message sent', {
duration: 2200,
leadingIcon: 'check',
action: 'Undo',
actionHint: 'undo send',
onAction: () => { undone = true; },
@@ -2868,6 +2870,7 @@ import * as Modals from './modalManager.js';
if (uiModule) {
uiModule.showToast('Message sent', {
duration: 7000,
leadingIcon: 'check',
action: 'View Message',
onAction: () => {
import('./emailLibrary.js').then(mod => {

View File

@@ -8,11 +8,41 @@ import themeModule from './theme.js';
let toastEl = null;
let autoScrollEnabled = true;
let hoveredToggleCard = null;
// Smooth scroll state
let _scrollRafId = null;
let _scrollBox = null;
function _isTextEditingTarget(target) {
const el = target && target.nodeType === 1 ? target : target?.parentElement;
return !!(el && el.closest('input, textarea, select, [contenteditable="true"], [contenteditable=""]'));
}
function _initHoverCardSpaceToggle() {
if (document._odysseusHoverCardSpaceToggle) return;
document._odysseusHoverCardSpaceToggle = true;
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');
if (card) hoveredToggleCard = card;
}, true);
document.addEventListener('pointerout', (e) => {
if (!hoveredToggleCard) return;
const next = e.relatedTarget;
if (!next || !hoveredToggleCard.contains(next)) hoveredToggleCard = null;
}, true);
document.addEventListener('keydown', (e) => {
if (e.code !== 'Space' || e.repeat || !hoveredToggleCard || !document.contains(hoveredToggleCard)) 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');
if (blocked) return;
e.preventDefault();
hoveredToggleCard.click();
}, true);
}
_initHoverCardSpaceToggle();
/**
* Copy text to clipboard
*/
@@ -104,18 +134,25 @@ export function showToast(msg, durationOrOpts) {
toastEl.textContent = '';
toastEl.classList.remove('error');
let duration = 1200, actionLabel = null, onAction = null, actionHint = null, actionIcon = null;
let duration = 1200, actionLabel = null, onAction = null, actionHint = null, actionIcon = null, leadingIcon = null;
if (typeof durationOrOpts === 'object' && durationOrOpts) {
duration = durationOrOpts.duration || 5000;
actionLabel = durationOrOpts.action;
onAction = durationOrOpts.onAction;
actionHint = durationOrOpts.actionHint || null;
actionIcon = durationOrOpts.actionIcon || null;
leadingIcon = durationOrOpts.leadingIcon || null;
} else if (typeof durationOrOpts === 'number') {
duration = durationOrOpts;
}
const textSpan = document.createElement('span');
if (leadingIcon === 'check') {
const icon = document.createElement('span');
icon.className = 'toast-checkmark';
icon.innerHTML = '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"/></svg>';
toastEl.appendChild(icon);
}
textSpan.textContent = msg;
toastEl.appendChild(textSpan);

View File

@@ -3534,6 +3534,32 @@ body.bg-pattern-sparkles {
max-width: min(360px, calc(100vw - 32px));
}
.toast.show { opacity:1; transform: translateX(0); }
.toast .toast-checkmark {
display: inline-flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
margin-right: 7px;
color: var(--green, #50fa7b);
vertical-align: -3px;
transform: scale(0.65);
opacity: 0;
animation: toastCheckPop 360ms cubic-bezier(0.2, 0.9, 0.25, 1.25) forwards;
}
.toast .toast-checkmark svg polyline {
stroke-dasharray: 24;
stroke-dashoffset: 24;
animation: toastCheckDraw 420ms ease-out 120ms forwards;
}
@keyframes toastCheckPop {
0% { opacity: 0; transform: scale(0.65); }
65% { opacity: 1; transform: scale(1.16); }
100% { opacity: 1; transform: scale(1); }
}
@keyframes toastCheckDraw {
to { stroke-dashoffset: 0; }
}
.toast.exiting {
opacity: 0;
transform: translateX(-120%);
@@ -10654,6 +10680,8 @@ textarea.memory-add-input {
flex: 1;
min-width: 0;
max-width: 70vw;
container-type: inline-size;
container-name: docpane;
display: flex;
flex-direction: column;
background: var(--bg);
@@ -14210,6 +14238,30 @@ body.left-dock-active {
#doclib-modal.doclib-fullscreen .doclib-modal-content {
transition: none !important;
}
.modal.modal-right-docked .email-reader-header,
.modal.modal-left-docked .email-reader-header {
flex-direction: column;
gap: 6px;
}
.modal.modal-right-docked .email-reader-actions,
.modal.modal-left-docked .email-reader-actions {
align-self: flex-end;
}
.modal.modal-right-docked .email-reader-meta-row,
.modal.modal-left-docked .email-reader-meta-row {
display: grid;
grid-template-columns: 1fr;
gap: 2px;
align-items: start;
}
.modal.modal-right-docked .email-reader-meta-row strong,
.modal.modal-left-docked .email-reader-meta-row strong {
min-width: 0;
}
.modal.modal-right-docked .recipient-chip,
.modal.modal-left-docked .recipient-chip {
max-width: 100%;
}
.archive-list {
margin-top: 8px;
border-top: 1px solid var(--border);
@@ -26101,6 +26153,27 @@ button .spinner-whirlpool {
border-color: var(--accent-primary, var(--red));
max-width: 500px;
}
@container docpane (max-width: 460px) {
.email-reader-header {
flex-direction: column;
gap: 6px;
}
.email-reader-actions {
align-self: flex-end;
}
.email-reader-meta-row {
display: grid;
grid-template-columns: 1fr;
gap: 2px;
align-items: start;
}
.email-reader-meta-row strong {
min-width: 0;
}
.recipient-chip {
max-width: 100%;
}
}
.email-reader-actions {
display: flex; gap: 4px; flex-wrap: nowrap; align-items: center;
flex-shrink: 0;
@@ -27564,6 +27637,21 @@ body.doc-find-active mark.doc-find-mark.current {
min-width: 0;
}
.email-field input:focus { border-color: var(--accent, #4a9eff); }
@container docpane (max-width: 460px) {
.doc-email-header .email-field {
display: grid;
grid-template-columns: 1fr;
gap: 3px;
align-items: stretch;
}
.doc-email-header .email-field label {
min-width: 0;
text-align: left;
}
.doc-email-header .email-field input {
width: 100%;
}
}
/* Cc toggle and attach button are absolute so they don't steal width from the To input */
.email-field .email-cc-toggle {
position: absolute; right: 6px; top: 50%; transform: translateY(-50%);