aboutsummaryrefslogtreecommitdiffstats
path: root/src/app.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-11-14 22:03:23 -0700
committerAdam Soltys <[email protected]>2026-11-14 22:03:23 -0700
commit933e85020c2cc56b511ff47a73943c92ea1d044a (patch)
treee12f9ffd835cd9c1fc9bffa81b76f910e194be80 /src/app.js
parent065d1b96afa32781f1a0805e0b4a02d32bf883ee (diff)
downloadcoinosv3-933e85020c2cc56b511ff47a73943c92ea1d044a.tar.gz
coinosv3-933e85020c2cc56b511ff47a73943c92ea1d044a.zip
Search inside someone's posts: their profile puts them in the search field, and "franca wildwood" is understood. "i found him by searching franca but then i was wanting some way to search his feed for something … i was wanting to search 'franca wildwood' but knew it wouldn't work … we couldn't just have a clever way of guessing what the user is trying to do?" (Adam, 2026-11-14). No second field: on a profile the header field (and the phone's search page opened from a profile) carries the person as a chip, "Search their posts, or anyone…"; Enter searches only their posts, people still show below for picking someone else, and × or Backspace on the empty field searches everywhere again. Words that begin or end with someone's name (first/last one or two words, matched at the start of a word of their name or address) are offered as "“wildwood” in Franca Yibisi's posts" at the top of the results; when that's someone you follow or whose profile you opened this session, it's the Enter choice (↵), otherwise only a row ("bitcoin wallet" is not Bitcoin Magazine's posts), and never when the whole query is someone's name. The search is a feed like any text search, /feed?q=wildwood&p=npub…: the NIP-50 relays asked with the author, plus the author's own recent posts (home, archive and their own relays, up to four pages of 400 until ten match) checked here word by word, since few people are in a search index; what their profile already loaded shows at once. tools/search-scope-test.js (real relays): chip on fiatjaf's profile, "relay" → only his posts, every one saying it; "fiatjaf relay" guessed and taken by Enter; × and Backspace; phone width. profile-stream, post-search, search-avatar-loading and features-smoke pass
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01VMan6UKGJyuGyZFxddYRxS
Diffstat (limited to 'src/app.js')
-rw-r--r--src/app.js22
1 files changed, 16 insertions, 6 deletions
diff --git a/src/app.js b/src/app.js
index b7580e5..3f1daf3 100644
--- a/src/app.js
+++ b/src/app.js
@@ -3072,15 +3072,24 @@ function lockBtn() {
// Find anyone on nostr from the header — results open their profile.
// Wide screens trade the search icon for a field in the header or sticky
// wallet sidebar. It drives the search page, which drops its own copy.
+// On a profile the field searches that person's posts: their chip sits in
+// it (× or Backspace on an empty field searches everywhere again).
function headerSearch() {
if (!featureHook('userSearchAvailable')) return null;
- return h('input', {
- type: 'text', class: 'header-search', placeholder: t('searchUsers') + '…', 'aria-label': t('searchUsers'),
- value: (ui.userSearch && ui.userSearch.q) || '', autocapitalize: 'none', autocomplete: 'off', spellcheck: 'false',
- onInput: (e) => { clearFeatureNavKeepSearch(); featureHook('userSearchQuery', e.target.value); },
+ const chip = featureHook('userSearchScopeChip');
+ const input = h('input', {
+ type: 'text', class: chip ? 'header-search-field' : 'header-search',
+ placeholder: chip ? t('searchScopedHint') : t('searchUsers') + '…', 'aria-label': t('searchUsers'),
+ // a profile on screen starts a fresh query; the old one waits behind Back
+ value: (!ui.profilePk && ui.userSearch && ui.userSearch.q) || '', autocapitalize: 'none', autocomplete: 'off', spellcheck: 'false',
+ onInput: (e) => { featureHook('userSearchHoldScope'); clearFeatureNavKeepSearch(); featureHook('userSearchQuery', e.target.value); },
// Enter without picking a suggestion: full-text search over notes
- onKeydown: (e) => { if (e.key === 'Enter' && !e.isComposing && e.target.value.trim()) { e.preventDefault(); featureHook('userSearchSubmit', e.target.value); e.target.blur(); } },
+ onKeydown: (e) => {
+ if (e.key === 'Enter' && !e.isComposing && e.target.value.trim()) { e.preventDefault(); featureHook('userSearchSubmit', e.target.value); e.target.blur(); }
+ else if (e.key === 'Backspace' && !e.target.value && chip) { e.preventDefault(); featureHook('userSearchUnscope'); }
+ },
});
+ return chip ? h('div', { class: 'header-search header-search-scoped' }, chip, input) : input;
}
// Typing in the header field: whatever page is open steps aside for the
// results, but the search itself (its query and rows) stays. It used to do
@@ -3102,8 +3111,9 @@ function searchBtn() {
title: t('searchUsers'),
'aria-label': t('searchUsers'),
onClick: () => {
+ const scope = featureHook('userSearchScopePk'); // from a profile: search inside its person's posts
clearFeatureNav(); ui.screen = 'wallet';
- featureHook('openUserSearch');
+ featureHook('openUserSearch', scope);
render();
setTimeout(() => document.querySelector('.user-search-input')?.focus(), 60);
},