From 682ec11003f2887e86a50b566658807e5cd5ef39 Mon Sep 17 00:00:00 2001 From: pewdiepie-archdaemon Date: Thu, 11 Jun 2026 19:02:05 +0900 Subject: [PATCH] Email library: gallery-style chip-input search with contact autocomplete MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the single text-input + IMAP search round-trip with a deterministic local chip-bar filter modelled on the gallery's tag pills. What lives in the bar - Each filter is a pill: { type: 'contact', name, email } or { type: 'text', text }. - Click anywhere in the bar lands the cursor in the input field. - Typing populates a dropdown of matching contacts + recently-seen senders (cached per modal open via _buildSuggestionSource). - Tab / Enter on a highlighted suggestion → adds a contact pill. - Enter on free text with no suggestion match → adds a text pill. - Backspace on empty input → pops the last pill. - × on a pill removes that one. - Arrow keys navigate the suggestion list. Filtering - _applyPillFilter snapshots the loaded list once, then for every render shows emails where ANY pill matches: contact pill — from_address equals OR to/cc contains the pill's email text pill — broad substring match across subject/from/snippet Click-to-add - Capture-phase click handler on .recipient-chip inside the email reader drops the person into the library as a contact pill (and reopens the library window if it was closed/minimized). Removed the debounced /api/email/search IMAP call and its 'Loading emails' side effect. The dropped server search was the source of the 'type jonathan, get stuck on Loading' bug. --- static/js/emailLibrary.js | 334 +++++++++++++++++++++++++++++++++++--- 1 file changed, 307 insertions(+), 27 deletions(-) diff --git a/static/js/emailLibrary.js b/static/js/emailLibrary.js index f7cfb9472..bed503194 100644 --- a/static/js/emailLibrary.js +++ b/static/js/emailLibrary.js @@ -773,6 +773,9 @@ export function openEmailLibrary(opts = {}) { state._libEmails = []; state._libOffset = 0; state._libSearch = ''; + state._libSearchDraft = ''; + state._libSearchPills = []; + _libSuggestionCache = null; state._libFilter = 'all'; state._libHasAttachments = false; // Animate the very first card render with a domino cascade (same as the @@ -857,7 +860,11 @@ export function openEmailLibrary(opts = {}) {