From 3522dbabef8168cdb7290e227a8cbaba6bf52eb7 Mon Sep 17 00:00:00 2001 From: MarekWo Date: Sun, 19 Jul 2026 19:42:42 +0200 Subject: [PATCH] feat(pathanalyzer): message text filter Free-text case-insensitive substring filter on message content, next to the other toolbar filters; combines with them and is reset by Clear. Verified live via Playwright: content match returns only matching rows (5/606), combines with the sender filter, Clear restores the full set. Co-Authored-By: Claude Fable 5 --- app/static/js/path-analyzer.js | 10 ++++++++-- app/templates/path-analyzer.html | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/static/js/path-analyzer.js b/app/static/js/path-analyzer.js index c224c26..56eb573 100644 --- a/app/static/js/path-analyzer.js +++ b/app/static/js/path-analyzer.js @@ -83,7 +83,7 @@ function showNotification(message, type = 'info') { // ================================================================ let paMessages = []; -let paFilters = { hops: 'any', hashSize: 'any', token: '', sender: '' }; +let paFilters = { hops: 'any', hashSize: 'any', token: '', sender: '', content: '' }; let paCurrentView = 'messages'; // 'messages' | 'stats' let paContacts = []; // /api/contacts/cached?format=full let paStatsSort = { key: 'relayed', dir: -1 }; @@ -140,12 +140,15 @@ function paMessageMatchesFilters(msg) { if (paFilters.sender) { if (!(msg.sender || '').toLowerCase().includes(paFilters.sender)) return false; } + if (paFilters.content) { + if (!(msg.content || '').toLowerCase().includes(paFilters.content)) return false; + } return true; } function paFiltersActive() { return paFilters.hops !== 'any' || paFilters.hashSize !== 'any' - || paFilters.token !== '' || paFilters.sender !== ''; + || paFilters.token !== '' || paFilters.sender !== '' || paFilters.content !== ''; } function paFormatTime(msg) { @@ -755,6 +758,7 @@ function paReadFilters() { paFilters.token = document.getElementById('paTokenFilter').value .replace(/[^0-9a-fA-F]/g, '').toUpperCase(); paFilters.sender = document.getElementById('paSenderFilter').value.trim().toLowerCase(); + paFilters.content = document.getElementById('paContentFilter').value.trim().toLowerCase(); document.getElementById('paClearFiltersBtn').classList.toggle('d-none', !paFiltersActive()); } @@ -770,6 +774,7 @@ function paClearFilters() { document.getElementById('paHashSizeFilter').value = 'any'; document.getElementById('paTokenFilter').value = ''; document.getElementById('paSenderFilter').value = ''; + document.getElementById('paContentFilter').value = ''; paApplyFilters(); } @@ -791,6 +796,7 @@ document.addEventListener('DOMContentLoaded', () => { document.getElementById('paHashSizeFilter').addEventListener('change', paApplyFilters); document.getElementById('paTokenFilter').addEventListener('input', debouncedApply); document.getElementById('paSenderFilter').addEventListener('input', debouncedApply); + document.getElementById('paContentFilter').addEventListener('input', debouncedApply); document.getElementById('paClearFiltersBtn').addEventListener('click', paClearFilters); document.getElementById('paViewMessagesBtn').addEventListener('click', () => paSwitchView('messages')); diff --git a/app/templates/path-analyzer.html b/app/templates/path-analyzer.html index 8662f87..ae36ad6 100644 --- a/app/templates/path-analyzer.html +++ b/app/templates/path-analyzer.html @@ -371,6 +371,8 @@ placeholder="Repeater hash (3B)" title="Match a repeater hash anywhere in a path (prefix match)"> +