mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-02 19:02:28 +00:00
Implement search functionality for profiles and videos
- Modified `js/index.js` to handle search queries, detecting npubs for direct navigation. - Added `views/search.html` and `js/searchView.js` to implement search UI and logic. - Implemented dual-search strategy: - Profile search using NIP-50 on Kind 0. - Video search using NIP-50 on Kind 30078 and local cache search (robustness). - Registered new search view in `js/viewManager.js`. - Verified with Playwright tests.
This commit is contained in:
1 parent
2515ed9e8e
commit
be5c39f6e8
4 files changed
+303
-71
No files matched your search
+70
-31
@@ -284,50 +284,89 @@ async function performProfileSearch(query, token) {
|
||||
}
|
||||
|
||||
async function performVideoSearch(query, token) {
|
||||
if (!nostrClient || !nostrClient.pool) return [];
|
||||
if (!nostrClient) return [];
|
||||
|
||||
const isHashtag = query.startsWith("#");
|
||||
const term = isHashtag ? query.slice(1) : query;
|
||||
const lowerTerm = term.toLowerCase();
|
||||
|
||||
const filter = {
|
||||
kinds: [30078],
|
||||
limit: 50
|
||||
};
|
||||
// 1. Local Search (Cache)
|
||||
const localMatches = [];
|
||||
if (nostrClient.activeMap instanceof Map) {
|
||||
for (const video of nostrClient.activeMap.values()) {
|
||||
if (!video || video.deleted) continue;
|
||||
|
||||
if (isHashtag) {
|
||||
filter["#t"] = [term];
|
||||
} else {
|
||||
filter.search = term;
|
||||
}
|
||||
let matches = false;
|
||||
if (isHashtag) {
|
||||
// Check tags for 't'
|
||||
if (Array.isArray(video.tags)) {
|
||||
matches = video.tags.some(t => Array.isArray(t) && t[0] === "t" && t[1].toLowerCase() === lowerTerm);
|
||||
}
|
||||
} else {
|
||||
// Check title/description
|
||||
const title = video.title ? video.title.toLowerCase() : "";
|
||||
const desc = video.description ? video.description.toLowerCase() : "";
|
||||
if (title.includes(lowerTerm) || desc.includes(lowerTerm)) {
|
||||
matches = true;
|
||||
}
|
||||
}
|
||||
|
||||
const relays = nostrClient.relays || [];
|
||||
if (relays.length === 0) return [];
|
||||
|
||||
let events = [];
|
||||
try {
|
||||
events = await nostrClient.pool.list(relays, [filter]);
|
||||
} catch (e) {
|
||||
devLogger.warn("Video search error", e);
|
||||
return [];
|
||||
if (matches) {
|
||||
localMatches.push(video);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentSearchToken !== token) return [];
|
||||
|
||||
const { convertEventToVideo } = await import("./nostr/index.js");
|
||||
// 2. Relay Search
|
||||
let relayVideos = [];
|
||||
const relays = nostrClient.relays || [];
|
||||
|
||||
const videos = events.map(evt => {
|
||||
const vid = convertEventToVideo(evt);
|
||||
if (vid.invalid) return null;
|
||||
return vid;
|
||||
}).filter(Boolean);
|
||||
if (relays.length > 0 && nostrClient.pool) {
|
||||
const filter = {
|
||||
kinds: [30078],
|
||||
limit: 50
|
||||
};
|
||||
|
||||
// Deduplicate by ID (or root)
|
||||
const unique = new Map();
|
||||
for (const v of videos) {
|
||||
if (!unique.has(v.id)) {
|
||||
unique.set(v.id, v);
|
||||
if (isHashtag) {
|
||||
filter["#t"] = [term];
|
||||
} else {
|
||||
filter.search = term;
|
||||
}
|
||||
|
||||
try {
|
||||
const events = await nostrClient.pool.list(relays, [filter]);
|
||||
|
||||
if (currentSearchToken === token) {
|
||||
const { convertEventToVideo } = await import("./nostr/index.js");
|
||||
relayVideos = events.map(evt => {
|
||||
const vid = convertEventToVideo(evt);
|
||||
if (vid.invalid) return null;
|
||||
return vid;
|
||||
}).filter(Boolean);
|
||||
}
|
||||
} catch (e) {
|
||||
devLogger.warn("Video search error", e);
|
||||
// Continue with local matches if relay search fails
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(unique.values());
|
||||
if (currentSearchToken !== token) return [];
|
||||
|
||||
// Deduplicate by ID
|
||||
const unique = new Map();
|
||||
|
||||
// Add local matches first
|
||||
for (const v of localMatches) {
|
||||
if (!unique.has(v.id)) unique.set(v.id, v);
|
||||
}
|
||||
|
||||
// Add relay matches (overwriting local if needed, or ignoring duplicates)
|
||||
for (const v of relayVideos) {
|
||||
if (!unique.has(v.id)) unique.set(v.id, v);
|
||||
}
|
||||
|
||||
// Sort by creation date (newest first)
|
||||
return Array.from(unique.values()).sort((a, b) => (b.created_at || 0) - (a.created_at || 0));
|
||||
}
|
||||
Reference in new issue
Block a user