mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-16 01:35:36 -04:00
Email reader: collapse To/Cc behind Gmail-style chevron
Only the From row shows by default. When the email has To and/or Cc recipients, a small chevron sits next to the From chip — click it to inline-expand the To/Cc rows below (rotates 180deg open). Trims the header to a single visible row in the common case, leaving the action cluster plenty of vertical headroom to stay on a single row.
This commit is contained in:
@@ -129,6 +129,20 @@ async function _copyTextToClipboard(text) {
|
||||
}
|
||||
}
|
||||
|
||||
function _wireMetaToggle(root) {
|
||||
const toggle = root && root.querySelector('.email-reader-meta-toggle');
|
||||
const details = root && root.querySelector('.email-reader-meta-details');
|
||||
if (!toggle || !details) return;
|
||||
toggle.addEventListener('click', (ev) => {
|
||||
ev.stopPropagation();
|
||||
const open = details.hasAttribute('hidden');
|
||||
if (open) details.removeAttribute('hidden');
|
||||
else details.setAttribute('hidden', '');
|
||||
toggle.setAttribute('aria-expanded', String(open));
|
||||
toggle.classList.toggle('open', open);
|
||||
});
|
||||
}
|
||||
|
||||
function _recipientChipHtml(full, label, extraClass = '') {
|
||||
const fullText = String(full || '').trim();
|
||||
const addr = _emailAddressFromRecipientText(fullText);
|
||||
@@ -2874,9 +2888,11 @@ async function _toggleCardPreview(card, em) {
|
||||
reader.innerHTML = `
|
||||
<div class="email-reader-header">
|
||||
<div class="email-reader-meta">
|
||||
<div class="email-reader-meta-row"><strong>From:</strong><span class="recipient-chips">${fromChip}</span></div>
|
||||
${data.to ? `<div class="email-reader-meta-row"><strong>To:</strong><span class="recipient-chips">${buildRecipients(data.to)}</span></div>` : ''}
|
||||
${data.cc ? `<div class="email-reader-meta-row"><strong>Cc:</strong><span class="recipient-chips">${buildRecipients(data.cc)}</span></div>` : ''}
|
||||
<div class="email-reader-meta-row email-reader-meta-from"><strong>From:</strong><span class="recipient-chips">${fromChip}</span>${(data.to || data.cc) ? `<button class="email-reader-meta-toggle" type="button" aria-expanded="false" title="Show recipients"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></button>` : ''}</div>
|
||||
${(data.to || data.cc) ? `<div class="email-reader-meta-details" hidden>
|
||||
${data.to ? `<div class="email-reader-meta-row"><strong>To:</strong><span class="recipient-chips">${buildRecipients(data.to)}</span></div>` : ''}
|
||||
${data.cc ? `<div class="email-reader-meta-row"><strong>Cc:</strong><span class="recipient-chips">${buildRecipients(data.cc)}</span></div>` : ''}
|
||||
</div>` : ''}
|
||||
</div>
|
||||
<div class="email-reader-actions">
|
||||
<div class="email-reader-actions-row email-reader-actions-row-primary">
|
||||
@@ -2954,6 +2970,7 @@ async function _toggleCardPreview(card, em) {
|
||||
ev.stopPropagation();
|
||||
await _summarizeEmail(reader, data, ev.currentTarget);
|
||||
});
|
||||
_wireMetaToggle(reader);
|
||||
// from-sender / thread-search Search button is DISABLED for now —
|
||||
// the search + threaded sidebar UX is too buggy to ship. Physically
|
||||
// remove it from every reader render path. Re-enable by deleting
|
||||
@@ -4569,9 +4586,11 @@ async function _openEmailAsTab(em, folder) {
|
||||
reader.innerHTML = `
|
||||
<div class="email-reader-header">
|
||||
<div class="email-reader-meta">
|
||||
<div class="email-reader-meta-row"><strong>From:</strong><span class="recipient-chips">${fromChip}</span></div>
|
||||
${data.to ? `<div class="email-reader-meta-row"><strong>To:</strong><span class="recipient-chips">${buildChips(data.to)}</span></div>` : ''}
|
||||
${data.cc ? `<div class="email-reader-meta-row"><strong>Cc:</strong><span class="recipient-chips">${buildChips(data.cc)}</span></div>` : ''}
|
||||
<div class="email-reader-meta-row email-reader-meta-from"><strong>From:</strong><span class="recipient-chips">${fromChip}</span>${(data.to || data.cc) ? `<button class="email-reader-meta-toggle" type="button" aria-expanded="false" title="Show recipients"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></button>` : ''}</div>
|
||||
${(data.to || data.cc) ? `<div class="email-reader-meta-details" hidden>
|
||||
${data.to ? `<div class="email-reader-meta-row"><strong>To:</strong><span class="recipient-chips">${buildChips(data.to)}</span></div>` : ''}
|
||||
${data.cc ? `<div class="email-reader-meta-row"><strong>Cc:</strong><span class="recipient-chips">${buildChips(data.cc)}</span></div>` : ''}
|
||||
</div>` : ''}
|
||||
</div>
|
||||
<div class="email-reader-actions">
|
||||
<div class="email-reader-actions-row email-reader-actions-row-primary">
|
||||
@@ -4619,6 +4638,7 @@ async function _openEmailAsTab(em, folder) {
|
||||
ev.stopPropagation();
|
||||
try { await _summarizeEmail(reader, data, ev.currentTarget); } catch {}
|
||||
});
|
||||
_wireMetaToggle(reader);
|
||||
reader.querySelector('[data-act="from-sender"]')?.remove();
|
||||
reader.querySelector('[data-act="from-sender"]')?.addEventListener('click', async (ev) => {
|
||||
ev.stopPropagation();
|
||||
@@ -4723,9 +4743,11 @@ async function _openEmailWindow(em, folder) {
|
||||
bodyEl.innerHTML = `
|
||||
<div class="email-reader-header">
|
||||
<div class="email-reader-meta">
|
||||
<div class="email-reader-meta-row"><strong>From:</strong><span class="recipient-chips">${fromChip}</span></div>
|
||||
${data.to ? `<div class="email-reader-meta-row"><strong>To:</strong><span class="recipient-chips">${_chipsFor(data.to)}</span></div>` : ''}
|
||||
${data.cc ? `<div class="email-reader-meta-row"><strong>Cc:</strong><span class="recipient-chips">${_chipsFor(data.cc)}</span></div>` : ''}
|
||||
<div class="email-reader-meta-row email-reader-meta-from"><strong>From:</strong><span class="recipient-chips">${fromChip}</span>${(data.to || data.cc) ? `<button class="email-reader-meta-toggle" type="button" aria-expanded="false" title="Show recipients"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg></button>` : ''}</div>
|
||||
${(data.to || data.cc) ? `<div class="email-reader-meta-details" hidden>
|
||||
${data.to ? `<div class="email-reader-meta-row"><strong>To:</strong><span class="recipient-chips">${_chipsFor(data.to)}</span></div>` : ''}
|
||||
${data.cc ? `<div class="email-reader-meta-row"><strong>Cc:</strong><span class="recipient-chips">${_chipsFor(data.cc)}</span></div>` : ''}
|
||||
</div>` : ''}
|
||||
</div>
|
||||
<div class="email-reader-actions">
|
||||
<div class="email-reader-actions-row email-reader-actions-row-primary">
|
||||
@@ -4773,6 +4795,7 @@ async function _openEmailWindow(em, folder) {
|
||||
ev.stopPropagation();
|
||||
try { await _summarizeEmail(bodyEl, data, ev.currentTarget); } catch {}
|
||||
});
|
||||
_wireMetaToggle(bodyEl);
|
||||
bodyEl.querySelector('[data-act="from-sender"]')?.remove();
|
||||
bodyEl.querySelector('[data-act="from-sender"]')?.addEventListener('click', async (ev) => {
|
||||
ev.stopPropagation();
|
||||
|
||||
@@ -28059,6 +28059,34 @@ button .spinner-whirlpool {
|
||||
floating action cluster on first paint. */
|
||||
padding-right: 180px;
|
||||
}
|
||||
/* Gmail-style chevron — collapsed view shows only From; the chevron
|
||||
reveals the To/Cc details inline below. */
|
||||
.email-reader-meta-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-left: 4px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
opacity: 0.55;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.email-reader-meta-toggle:hover { opacity: 1; background: color-mix(in srgb, currentColor 10%, transparent); }
|
||||
.email-reader-meta-toggle svg { transition: transform 0.15s ease; }
|
||||
.email-reader-meta-toggle.open svg { transform: rotate(180deg); }
|
||||
.email-reader-meta-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.email-reader-meta-details[hidden] { display: none; }
|
||||
.email-reader-header > .email-reader-meta {
|
||||
flex: 1; min-width: 0;
|
||||
opacity: 0.85; line-height: 1.7; font-size: 11px;
|
||||
|
||||
Reference in New Issue
Block a user