From 57a1587ab5aecf4055d2c748ddbfc7fb53323673 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Sun, 26 Oct 2025 12:11:53 -0400 Subject: [PATCH] Sort video grid by original posted time --- js/ui/views/VideoListView.js | 41 +++++++++++++-- tests/ui/video-list-view-sorting.test.mjs | 64 +++++++++++++++++++++++ 2 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 tests/ui/video-list-view-sorting.test.mjs diff --git a/js/ui/views/VideoListView.js b/js/ui/views/VideoListView.js index 6d5ddf26..09be79bb 100644 --- a/js/ui/views/VideoListView.js +++ b/js/ui/views/VideoListView.js @@ -455,7 +455,10 @@ export class VideoListView { return displayVideos; } - displayVideos.sort((a, b) => (b?.created_at || 0) - (a?.created_at || 0)); + displayVideos.sort( + (a, b) => + this.getVideoPostedAtForSort(b) - this.getVideoPostedAtForSort(a), + ); this.currentVideos = displayVideos.slice(); const signaturePayload = displayVideos.map((video) => ({ @@ -463,6 +466,10 @@ export class VideoListView { createdAt: Number.isFinite(video?.created_at) ? video.created_at : Number(video?.created_at) || 0, + postedAt: (() => { + const timestamp = this.getVideoPostedAtForSort(video); + return Number.isFinite(timestamp) ? timestamp : 0; + })(), deleted: Boolean(video?.deleted), isPrivate: Boolean(video?.isPrivate), isNsfw: Boolean(video?.isNsfw), @@ -530,9 +537,10 @@ export class VideoListView { const fallbackTimestamp = normalizedPostedAt !== null ? normalizedPostedAt - : Number.isFinite(video?.created_at) - ? Math.floor(video.created_at) - : null; + : (() => { + const sortTimestamp = this.getVideoPostedAtForSort(video); + return Number.isFinite(sortTimestamp) ? sortTimestamp : null; + })(); const timeAgo = fallbackTimestamp !== null ? this.formatters.formatTimeAgo(fallbackTimestamp) @@ -928,6 +936,31 @@ export class VideoListView { return next; } + getVideoPostedAtForSort(video) { + if (!video || typeof video !== "object") { + return Number.NEGATIVE_INFINITY; + } + + const known = this.utils.getKnownVideoPostedAt(video); + if (Number.isFinite(known)) { + return Math.floor(known); + } + + if (Number.isFinite(video?.rootCreatedAt)) { + return Math.floor(video.rootCreatedAt); + } + + if (Number.isFinite(video?.nip71Source?.created_at)) { + return Math.floor(video.nip71Source.created_at); + } + + if (Number.isFinite(video?.created_at)) { + return Math.floor(video.created_at); + } + + return Number.NEGATIVE_INFINITY; + } + computeShareBase() { const explicit = this.utils.getShareUrlBase(); if (explicit) { diff --git a/tests/ui/video-list-view-sorting.test.mjs b/tests/ui/video-list-view-sorting.test.mjs new file mode 100644 index 00000000..b52b5902 --- /dev/null +++ b/tests/ui/video-list-view-sorting.test.mjs @@ -0,0 +1,64 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { JSDOM } from "jsdom"; + +import { VideoListView } from "../../js/ui/views/VideoListView.js"; + +function createViewDom() { + const dom = new JSDOM( + "