Show posted and edited times from root history

This commit is contained in:
thePR0M3TH3AN committed 2025-10-08 20:45:59 -04:00
1 parent 7d389bb33d
commit c99f6834cd
3 files changed
+242 -12

No files matched your search

+7 -3
View File
@@ -237,10 +237,14 @@
<!-- Video Timestamp -->
<div
class="flex items-center justify-between text-sm text-gray-400 mb-4"
class="flex items-start justify-between text-sm text-gray-400 mb-4"
>
<div class="flex items-center gap-2 modal-meta">
<span id="videoTimestamp">just now</span>
<div class="flex flex-wrap items-center gap-2 modal-meta">
<span id="videoTimestamp">Posted just now</span>
<span
id="videoEditedTimestamp"
class="hidden"
>Last edited just now</span>
<span id="videoViewCount" class="modal-view-count">– views</span>
</div>
<div id="modalStatus" class="text-gray-300">
+196 -2
View File
@@ -6226,6 +6226,11 @@ class Application {
hasUrl: !!trimmedUrl,
});
const knownPostedAt = this.getKnownVideoPostedAt(video);
const normalizedEditedAt = Number.isFinite(video.created_at)
? Math.floor(video.created_at)
: null;
this.currentVideo = {
...video,
url: trimmedUrl,
@@ -6235,8 +6240,15 @@ class Application {
torrentSupported: magnetSupported,
legacyInfoHash: video.legacyInfoHash || legacyInfoHash,
lightningAddress: null,
lastEditedAt: normalizedEditedAt,
};
if (Number.isFinite(knownPostedAt)) {
this.cacheVideoRootCreatedAt(this.currentVideo, knownPostedAt);
} else if (this.currentVideo.rootCreatedAt) {
delete this.currentVideo.rootCreatedAt;
}
const dTagValue = (this.extractDTagValue(video.tags) || "").trim();
const pointerInfo = resolveVideoPointer({
kind: video.kind,
@@ -6320,12 +6332,15 @@ class Application {
const creatorNpub = this.safeEncodeNpub(video.pubkey) || video.pubkey;
if (this.videoModal) {
const formattedTimestamp = this.formatTimeAgo(video.created_at);
const timestampPayload = this.buildModalTimestampPayload({
postedAt: this.currentVideo?.rootCreatedAt ?? null,
editedAt: normalizedEditedAt,
});
const displayNpub = `${creatorNpub.slice(0, 8)}...${creatorNpub.slice(-4)}`;
this.videoModal.updateMetadata({
title: video.title || "Untitled",
description: video.description || "No description available.",
timestamp: formattedTimestamp,
timestamps: timestampPayload,
creator: {
name: creatorProfile.name,
avatarUrl: creatorProfile.picture,
@@ -6334,6 +6349,8 @@ class Application {
});
}
this.ensureModalPostedTimestamp(this.currentVideo);
const playbackResult =
playbackPromise && typeof playbackPromise.then === "function"
? await playbackPromise
@@ -6342,6 +6359,183 @@ class Application {
return playbackResult;
}
buildModalTimestampPayload({ postedAt = null, editedAt = null } = {}) {
const normalizedPostedAt = Number.isFinite(postedAt)
? Math.floor(postedAt)
: null;
const normalizedEditedAt = Number.isFinite(editedAt)
? Math.floor(editedAt)
: null;
const payload = {
posted: "",
edited: "",
};
const effectivePostedAt =
normalizedPostedAt !== null ? normalizedPostedAt : normalizedEditedAt;
if (effectivePostedAt !== null) {
payload.posted = `Posted ${this.formatTimeAgo(effectivePostedAt)}`;
}
const shouldShowEdited =
normalizedEditedAt !== null &&
(normalizedPostedAt === null || normalizedEditedAt - normalizedPostedAt >= 60);
if (shouldShowEdited) {
payload.edited = `Last edited ${this.formatTimeAgo(normalizedEditedAt)}`;
}
return payload;
}
getKnownVideoPostedAt(video) {
if (!video || typeof video !== "object") {
return null;
}
const directValue = Number.isFinite(video.rootCreatedAt)
? Math.floor(video.rootCreatedAt)
: null;
if (directValue !== null) {
return directValue;
}
if (video.id && this.videosMap instanceof Map) {
const stored = this.videosMap.get(video.id);
const storedValue = Number.isFinite(stored?.rootCreatedAt)
? Math.floor(stored.rootCreatedAt)
: null;
if (storedValue !== null) {
video.rootCreatedAt = storedValue;
return storedValue;
}
}
const nip71Created = Number.isFinite(video?.nip71Source?.created_at)
? Math.floor(video.nip71Source.created_at)
: null;
if (nip71Created !== null) {
return nip71Created;
}
return null;
}
cacheVideoRootCreatedAt(video, timestamp) {
if (!Number.isFinite(timestamp)) {
return;
}
const normalized = Math.floor(timestamp);
if (video && typeof video === "object") {
video.rootCreatedAt = normalized;
}
if (video?.id && this.videosMap instanceof Map) {
const existing = this.videosMap.get(video.id);
if (existing && typeof existing === "object") {
existing.rootCreatedAt = normalized;
}
}
}
async resolveVideoPostedAt(video) {
if (!video || typeof video !== "object") {
return null;
}
const cached = this.getKnownVideoPostedAt(video);
if (cached !== null) {
return cached;
}
if (!nostrClient || typeof nostrClient.hydrateVideoHistory !== "function") {
const fallback = Number.isFinite(video.created_at)
? Math.floor(video.created_at)
: null;
if (fallback !== null) {
this.cacheVideoRootCreatedAt(video, fallback);
}
return fallback;
}
try {
const history = await nostrClient.hydrateVideoHistory(video);
if (Array.isArray(history) && history.length) {
let earliest = null;
for (const entry of history) {
if (!entry || entry.deleted) {
continue;
}
const created = Number.isFinite(entry.created_at)
? Math.floor(entry.created_at)
: null;
if (created === null) {
continue;
}
if (earliest === null || created < earliest) {
earliest = created;
}
}
if (earliest === null) {
const lastEntry = history[history.length - 1];
if (Number.isFinite(lastEntry?.created_at)) {
earliest = Math.floor(lastEntry.created_at);
}
}
if (earliest !== null) {
this.cacheVideoRootCreatedAt(video, earliest);
return earliest;
}
}
} catch (error) {
if (isDevMode) {
console.warn(
"[Application] Failed to hydrate video history for timestamps:",
error
);
}
}
const fallback = Number.isFinite(video.created_at)
? Math.floor(video.created_at)
: null;
if (fallback !== null) {
this.cacheVideoRootCreatedAt(video, fallback);
}
return fallback;
}
async ensureModalPostedTimestamp(video) {
if (!video || !this.videoModal) {
return;
}
const postedAt = await this.resolveVideoPostedAt(video);
if (!this.videoModal || this.currentVideo !== video) {
return;
}
const editedAt = Number.isFinite(video.lastEditedAt)
? Math.floor(video.lastEditedAt)
: Number.isFinite(video.created_at)
? Math.floor(video.created_at)
: null;
const payload = this.buildModalTimestampPayload({
postedAt,
editedAt,
});
this.videoModal.updateMetadata({ timestamps: payload });
}
async playVideoWithoutEvent({
url = "",
magnet = "",
+39 -7
View File
@@ -35,6 +35,7 @@ export class VideoModal {
this.videoTitle = null;
this.videoDescription = null;
this.videoTimestamp = null;
this.videoEditedTimestamp = null;
this.videoViewCountEl = null;
this.creatorAvatar = null;
this.creatorName = null;
@@ -185,6 +186,8 @@ export class VideoModal {
playerModal.querySelector("#videoDescription") || null;
this.videoTimestamp =
playerModal.querySelector("#videoTimestamp") || null;
this.videoEditedTimestamp =
playerModal.querySelector("#videoEditedTimestamp") || null;
this.videoViewCountEl =
playerModal.querySelector("#videoViewCount") || null;
this.creatorAvatar =
@@ -933,26 +936,55 @@ export class VideoModal {
title,
description,
timestamp,
timestamps,
viewCount,
creator,
} = {}) {
if (this.videoTitle) {
if (this.videoTitle && title !== undefined) {
this.videoTitle.textContent = title || "Untitled";
}
if (this.videoDescription) {
if (this.videoDescription && description !== undefined) {
this.videoDescription.textContent = description || "";
}
if (this.videoTimestamp) {
this.videoTimestamp.textContent = timestamp || "";
if (timestamps) {
this.updateTimestamps(timestamps);
} else if (timestamp !== undefined) {
this.updateTimestamps({ posted: timestamp });
}
if (typeof viewCount === "string") {
this.updateViewCountLabel(viewCount);
if (this.videoViewCountEl && viewCount !== undefined) {
if (typeof viewCount === "string") {
this.updateViewCountLabel(viewCount);
} else {
this.updateViewCountLabel("");
}
}
if (creator) {
if (creator !== undefined) {
this.updateCreator(creator);
}
}
updateTimestamps({ posted, edited } = {}) {
if (this.videoTimestamp) {
if (posted) {
this.videoTimestamp.textContent = posted;
this.videoTimestamp.classList.remove("hidden");
} else {
this.videoTimestamp.textContent = "";
this.videoTimestamp.classList.add("hidden");
}
}
if (this.videoEditedTimestamp) {
if (edited) {
this.videoEditedTimestamp.textContent = edited;
this.videoEditedTimestamp.classList.remove("hidden");
} else {
this.videoEditedTimestamp.textContent = "";
this.videoEditedTimestamp.classList.add("hidden");
}
}
}
updateCreator({ name, avatarUrl, npub } = {}) {
if (this.creatorName) {
this.creatorName.textContent = name || "Unknown";