mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-12 15:52:30 +00:00
[upload] Suggest one-tap hashtag chips from the user's past videos (#45)
The upload modal's Hashtags section now shows chips of the user's most-used past
hashtags ("Reuse a tag from your videos:"). Clicking one adds it to the NIP-71 't'
repeater; already-added chips dim + disable; the row is hidden for users with no
past tags.
- js/utils/hashtagSuggestions.js: pure rankHashtagsByFrequency(videos) — count =
number of the user's videos using each tag, normalized (case + '#') and deduped
per video, ranked by count then alphabetically. Reads video.nip71.hashtags, falls
back to raw event 't' tags minus bitvid's fixed t=video marker.
- app.getUserHashtagSuggestions() sources the user's own videos via
nostrService.getActiveVideosByAuthors([pubkey]) and ranks them (top 12), injected
into the modal as getHashtagSuggestions.
- UploadModal renders the chips on open and wires clicks through the existing
Nip71FormManager (addRepeaterEntry + setFieldValue, dedup via collectRepeaterValues).
Tests: tests/hashtag-suggestions.test.mjs (5 — per-video counting, normalization,
marker exclusion, tie-break + limit, empty input). Lint + build green.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
6bdf28fb30
commit
3df398d7ad
7 files changed
+318
-5
No files matched your search
@@ -99,6 +99,7 @@ import {
|
||||
logoutSigner,
|
||||
} from "./nostrClientRegistry.js";
|
||||
import { resolveSignerCapabilities } from "./nostr/signerCapabilities.js";
|
||||
import { rankHashtagsByFrequency } from "./utils/hashtagSuggestions.js";
|
||||
import {
|
||||
decideSignerEnsure,
|
||||
isSignerCapable,
|
||||
@@ -3633,6 +3634,29 @@ class Application {
|
||||
return this._ui.updateActiveProfileUI(...args);
|
||||
}
|
||||
|
||||
// The active user's most-used hashtags (frequency-ranked from their own past
|
||||
// uploads) for the upload modal's one-tap suggestion chips (TODO #45).
|
||||
getUserHashtagSuggestions({ limit = 12 } = {}) {
|
||||
const pubkey = this.normalizeHexPubkey(this.pubkey);
|
||||
if (
|
||||
!pubkey ||
|
||||
typeof this.nostrService?.getActiveVideosByAuthors !== "function"
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
let videos = [];
|
||||
try {
|
||||
videos = this.nostrService.getActiveVideosByAuthors([pubkey]) || [];
|
||||
} catch (error) {
|
||||
devLogger.warn(
|
||||
"[Application] Failed to read user videos for hashtag suggestions:",
|
||||
error,
|
||||
);
|
||||
return [];
|
||||
}
|
||||
return rankHashtagsByFrequency(videos, { limit });
|
||||
}
|
||||
|
||||
async hydrateNwcSettingsForPubkey(pubkey) {
|
||||
return this.nwcSettingsService.hydrateNwcSettingsForPubkey(pubkey);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user