mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-28 00:12:25 +00:00
Restore canonical watch history snapshot format
This commit is contained in:
1 parent
af7738b4d8
commit
ecd3f4026e
6 files changed
+122
-8
No files matched your search
@@ -63,14 +63,14 @@ export const WATCH_HISTORY_KIND = 30078;
|
||||
* BitVid deployments that share relays, but keep it stable once clients begin
|
||||
* syncing history.
|
||||
*/
|
||||
export const WATCH_HISTORY_LIST_IDENTIFIER = "watch-history:v2:index";
|
||||
export const WATCH_HISTORY_LIST_IDENTIFIER = "watch-history";
|
||||
|
||||
/**
|
||||
* Legacy identifiers that BitVid clients should continue honoring when
|
||||
* fetching historical watch-history snapshots.
|
||||
*/
|
||||
export const WATCH_HISTORY_LEGACY_LIST_IDENTIFIERS = Object.freeze([
|
||||
"watch-history",
|
||||
"watch-history:v2:index",
|
||||
]);
|
||||
|
||||
/**
|
||||
|
||||
@@ -64,10 +64,12 @@ builders inherit the same debugging knobs.
|
||||
### Watch history identifiers
|
||||
|
||||
Watch-history snapshots now publish a dedicated index event with
|
||||
`#d ${WATCH_HISTORY_LIST_IDENTIFIER}` (defaults to `watch-history:v2:index`). The
|
||||
`#d ${WATCH_HISTORY_LIST_IDENTIFIER}` (defaults to `watch-history`). The
|
||||
index advertises the active snapshot id, total chunk count, and a pointer to
|
||||
each chunk via `a` tags so clients can fetch the encrypted payloads without
|
||||
guessing identifiers.
|
||||
guessing identifiers. Deployments that previously used
|
||||
`watch-history:v2:index` continue to resolve thanks to the legacy identifier
|
||||
list.
|
||||
|
||||
Every chunk event uses a unique `d` tag such as
|
||||
`watch-history:v2/<snapshot>/<chunkIndex>`. Legacy snapshots created before the
|
||||
|
||||
@@ -4283,6 +4283,29 @@ class bitvidApp {
|
||||
}
|
||||
button.dataset.navBound = "true";
|
||||
button.addEventListener("click", () => {
|
||||
if (name === "history") {
|
||||
let actorCandidate;
|
||||
if (typeof this.pubkey === "string" && this.pubkey.trim()) {
|
||||
actorCandidate = this.pubkey.trim();
|
||||
} else if (
|
||||
typeof window?.app?.pubkey === "string" &&
|
||||
window.app.pubkey.trim()
|
||||
) {
|
||||
actorCandidate = window.app.pubkey.trim();
|
||||
}
|
||||
|
||||
void nostrClient
|
||||
.fetchWatchHistory(actorCandidate, { forceRefresh: true })
|
||||
.catch((error) => {
|
||||
if (isDevMode) {
|
||||
console.warn(
|
||||
"[profileModal] Failed to prefetch watch history on navigation:",
|
||||
error
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.selectProfilePane(name);
|
||||
});
|
||||
});
|
||||
|
||||
+47
@@ -2,6 +2,45 @@
|
||||
|
||||
import "./bufferPolyfill.js";
|
||||
import { trackPageView } from "./analytics.js";
|
||||
import { nostrClient } from "./nostr.js";
|
||||
|
||||
const HISTORY_PREFETCH_DEBOUNCE_MS = 250;
|
||||
|
||||
function prefetchWatchHistory(options = {}) {
|
||||
if (typeof nostrClient?.fetchWatchHistory !== "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
const force = options.force === true;
|
||||
const now = Date.now();
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
const last =
|
||||
typeof window.__bitvidLastHistoryPrefetch === "number"
|
||||
? window.__bitvidLastHistoryPrefetch
|
||||
: 0;
|
||||
|
||||
if (!force && now - last < HISTORY_PREFETCH_DEBOUNCE_MS) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.__bitvidLastHistoryPrefetch = now;
|
||||
}
|
||||
|
||||
let actor;
|
||||
if (typeof window?.app?.pubkey === "string" && window.app.pubkey.trim()) {
|
||||
actor = window.app.pubkey.trim();
|
||||
}
|
||||
|
||||
void nostrClient
|
||||
.fetchWatchHistory(actor, { forceRefresh: true })
|
||||
.catch((error) => {
|
||||
console.warn(
|
||||
"[index] Failed to prefetch watch history during navigation:",
|
||||
error
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
const INTERFACE_FADE_IN_ANIMATION = "interface-fade-in";
|
||||
const VIDEO_THUMBNAIL_FADE_IN_ANIMATION = "video-thumbnail-fade-in";
|
||||
@@ -257,6 +296,11 @@ export function setHashView(viewName) {
|
||||
url.searchParams.delete("v");
|
||||
const newUrl = url.pathname + url.search + `#view=${viewName}`;
|
||||
window.history.replaceState({}, "", newUrl);
|
||||
|
||||
if (typeof viewName === "string" && viewName.toLowerCase() === "history") {
|
||||
prefetchWatchHistory({ force: true });
|
||||
}
|
||||
|
||||
handleHashChange();
|
||||
}
|
||||
|
||||
@@ -403,6 +447,9 @@ async function handleHashChange() {
|
||||
}
|
||||
|
||||
const viewName = match[1]; // only the chunk before any '&'
|
||||
if (typeof viewName === "string" && viewName.toLowerCase() === "history") {
|
||||
prefetchWatchHistory();
|
||||
}
|
||||
const viewUrl = `views/${viewName}.html`;
|
||||
|
||||
// Now dynamically load that partial, then call its init function
|
||||
|
||||
+22
-1
@@ -58,7 +58,28 @@ const WATCH_HISTORY_INDEX_IDENTIFIER_LOWER =
|
||||
? WATCH_HISTORY_LIST_IDENTIFIER.trim().toLowerCase()
|
||||
: "";
|
||||
|
||||
const WATCH_HISTORY_CHUNK_V2_PREFIX = "watch-history:v2";
|
||||
const WATCH_HISTORY_CHUNK_V2_PREFIX = (() => {
|
||||
const rawIdentifier =
|
||||
typeof WATCH_HISTORY_LIST_IDENTIFIER === "string"
|
||||
? WATCH_HISTORY_LIST_IDENTIFIER.trim()
|
||||
: "";
|
||||
|
||||
if (rawIdentifier) {
|
||||
const trimmed = rawIdentifier.replace(/\/+$/, "");
|
||||
if (/[:/]index$/i.test(trimmed)) {
|
||||
const base = trimmed.replace(/[:/]index$/i, "").replace(/\/+$/, "");
|
||||
return base || "watch-history:v2";
|
||||
}
|
||||
|
||||
if (/:v\d+$/i.test(trimmed)) {
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
return `${trimmed}:v2`;
|
||||
}
|
||||
|
||||
return "watch-history:v2";
|
||||
})();
|
||||
|
||||
const LEGACY_WATCH_HISTORY_CHUNK_IDENTIFIER_PREFIX = (() => {
|
||||
const rawIdentifier =
|
||||
|
||||
@@ -109,9 +109,30 @@ function createDecryptClient(actorPubkey) {
|
||||
}
|
||||
|
||||
const ACTOR = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
|
||||
const WATCH_HISTORY_CHUNK_PREFIX = WATCH_HISTORY_LIST_IDENTIFIER.replace(
|
||||
/[:/]index$/i,
|
||||
""
|
||||
function deriveChunkPrefix(identifier) {
|
||||
if (typeof identifier !== "string") {
|
||||
return "watch-history:v2";
|
||||
}
|
||||
|
||||
const trimmed = identifier.trim().replace(/\/+$/, "");
|
||||
if (!trimmed) {
|
||||
return "watch-history:v2";
|
||||
}
|
||||
|
||||
if (/[:/]index$/i.test(trimmed)) {
|
||||
const base = trimmed.replace(/[:/]index$/i, "").replace(/\/+$/, "");
|
||||
return base || "watch-history:v2";
|
||||
}
|
||||
|
||||
if (/:v\d+$/i.test(trimmed)) {
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
return `${trimmed}:v2`;
|
||||
}
|
||||
|
||||
const WATCH_HISTORY_CHUNK_PREFIX = deriveChunkPrefix(
|
||||
WATCH_HISTORY_LIST_IDENTIFIER
|
||||
);
|
||||
|
||||
const indexSchema = getNostrEventSchema(NOTE_TYPES.WATCH_HISTORY_INDEX);
|
||||
|
||||
Reference in new issue
Block a user