personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add hide-matched toggle to speakers sentence list

Implement CSS-only sentence filtering using a data-match attribute on sentence rows and container-scoped styles.

Persist filter toggle state in-session across segment switches by reapplying button/container state during sentence re-render.

Update sentence count text to show filtered-visible vs total when filtering is active.

+70 -2
+70 -2
apps/speakers/workspace.html
··· 180 180 background: #d1d5db; 181 181 } 182 182 183 + .spk-filter-toggle { 184 + padding: 4px 8px; 185 + background: #e5e7eb; 186 + border: none; 187 + border-radius: 4px; 188 + font-size: 12px; 189 + cursor: pointer; 190 + white-space: nowrap; 191 + color: #374151; 192 + transition: background 0.15s; 193 + margin-left: auto; 194 + } 195 + 196 + .spk-filter-toggle:hover { 197 + background: #d1d5db; 198 + } 199 + 200 + .spk-filter-toggle.spk-filter-active { 201 + background: #3b82f6; 202 + color: #fff; 203 + } 204 + 205 + .spk-filter-toggle.spk-filter-active:hover { 206 + background: #2563eb; 207 + } 208 + 209 + .spk-filter-unmatched .spk-sentence[data-match="high"] { 210 + display: none; 211 + } 212 + 183 213 /* Sentence list */ 184 214 .spk-sentences { 185 215 margin-top: 16px; 186 216 } 187 217 188 218 .spk-sentences-title { 219 + display: flex; 220 + align-items: center; 221 + gap: 8px; 189 222 font-size: 14px; 190 223 font-weight: 600; 191 224 color: #374151; ··· 477 510 let audioPlayer = null; 478 511 let currentSentences = []; // Sentence data with offsets for time tracking 479 512 let playingSentenceId = null; // Currently playing/highlighted sentence 513 + let filterMatched = false; // Toggle: hide high-confidence matches 480 514 481 515 // Load segments on page load 482 516 loadSegments(); ··· 715 749 } 716 750 717 751 container.innerHTML = ` 718 - <div class="spk-sentences-title">Sentences (${sentences.length})</div> 752 + <div class="spk-sentences-title"> 753 + <span id="spkSentenceCount">Sentences (${sentences.length})</span> 754 + <button class="spk-filter-toggle${filterMatched ? ' spk-filter-active' : ''}" id="spkFilterToggle">Hide matched</button> 755 + </div> 719 756 ${sentences.map(s => renderSentence(s, all_entities)).join('')} 720 757 `; 721 758 722 759 // Setup event handlers 723 760 setupSentenceHandlers(source); 761 + 762 + // Setup filter toggle 763 + const filterBtn = document.getElementById('spkFilterToggle'); 764 + if (filterBtn) { 765 + filterBtn.addEventListener('click', () => { 766 + filterMatched = !filterMatched; 767 + filterBtn.classList.toggle('spk-filter-active', filterMatched); 768 + container.classList.toggle('spk-filter-unmatched', filterMatched); 769 + updateSentenceCount(); 770 + }); 771 + } 772 + 773 + // Apply persisted filter state 774 + if (filterMatched) { 775 + container.classList.add('spk-filter-unmatched'); 776 + } 777 + updateSentenceCount(); 778 + } 779 + 780 + function updateSentenceCount() { 781 + const countEl = document.getElementById('spkSentenceCount'); 782 + if (!countEl) return; 783 + const total = currentSentences.length; 784 + if (filterMatched) { 785 + const visible = currentSentences.filter(s => !s.match || s.match.score < 0.7).length; 786 + countEl.textContent = `Sentences (${visible} of ${total})`; 787 + } else { 788 + countEl.textContent = `Sentences (${total})`; 789 + } 724 790 } 725 791 726 792 function setupAudioListeners() { ··· 822 888 const timeStr = formatOffset(sentence.offset); 823 889 const match = sentence.match; 824 890 let matchHtml = '<span class="spk-no-match">No match</span>'; 891 + let matchTier = 'none'; 825 892 826 893 if (match) { 827 894 const scorePct = Math.round(match.score * 100); 828 895 const scoreClass = match.score >= 0.7 ? 'high' : match.score >= 0.5 ? 'med' : 'low'; 896 + matchTier = scoreClass; 829 897 const confirmBtn = match.score >= 0.5 830 898 ? `<button class="spk-btn spk-btn-confirm spk-confirm-match-btn" data-entity="${escapeHtml(match.entity)}" title="Confirm ${escapeHtml(match.entity)}">&#10003;</button>` 831 899 : ''; ··· 833 901 } 834 902 835 903 return ` 836 - <div class="spk-sentence" data-id="${sentence.id}" data-offset="${sentence.offset}"> 904 + <div class="spk-sentence" data-id="${sentence.id}" data-offset="${sentence.offset}" data-match="${matchTier}"> 837 905 <div class="spk-sentence-time">${timeStr}</div> 838 906 <div class="spk-sentence-content"> 839 907 <div class="spk-sentence-text">${escapeHtml(sentence.text)}</div>