Order the latest-reviews strip by created_at alone.
The home page carousel floated reviews whose author had a kind 0 ahead of everything else, capped at 90 days old, so a named review from two months ago sat between two reviews from this week. Under a heading that says "Latest reviews", with each card's foot printing the very timestamp being overruled, that reads as broken rather than as curation. Strict recency now, newest first, as the last thing that happens to the list, with the event id breaking ties so two builds of the same events agree. Names and avatars are still resolved and still shown; they no longer decide the order. The candidate scan stops at the limit rather than gathering twelve times it: the scan already runs newest first, so nothing further down can outrank what it has, and the build resolves ten profiles per locale instead of a hundred and twenty. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
860a4de009
commit
1eade490c8
+16
-28
@@ -55,19 +55,6 @@ export interface BuildReview {
|
|||||||
* characters or matching a common test string do not qualify. They still appear in
|
* characters or matching a common test string do not qualify. They still appear in
|
||||||
* full on the mint page, nothing is hidden, this strip is just a shop window.
|
* full on the mint page, nothing is hidden, this strip is just a shop window.
|
||||||
*/
|
*/
|
||||||
/** How many candidates to gather per card shown, so the ordering has a real choice. */
|
|
||||||
const POOL_FACTOR = 12;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* How recent a review must still be to be promoted for having a named author.
|
|
||||||
*
|
|
||||||
* The ordering below prefers reviews whose author has a kind 0, and this is the leash
|
|
||||||
* on that preference. Without it the strip would headline a named review from two
|
|
||||||
* years ago under a heading that says "Latest reviews"; with it, a named review from
|
|
||||||
* within the season can lead and anything older cannot.
|
|
||||||
*/
|
|
||||||
const PROMOTE_MAX_AGE_S = 90 * 24 * 60 * 60;
|
|
||||||
|
|
||||||
const TEST_STRINGS = new Set([
|
const TEST_STRINGS = new Set([
|
||||||
'test', 'testing', 'test test', 'hello', 'hi', 'ok', 'okay', 'good', 'nice',
|
'test', 'testing', 'test test', 'hello', 'hi', 'ok', 'okay', 'good', 'nice',
|
||||||
'great', 'cool', 'gm', 'a', '.', '..', '...', 'asdf', 'qwerty', '123',
|
'great', 'cool', 'gm', 'a', '.', '..', '...', 'asdf', 'qwerty', '123',
|
||||||
@@ -227,29 +214,30 @@ export async function fetchLatestReviews(
|
|||||||
profile: null,
|
profile: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (candidates.length >= limit * POOL_FACTOR) break;
|
// The scan runs newest first, so the first `limit` survivors are the latest
|
||||||
|
// `limit` reviews. Nothing further down the list can outrank them.
|
||||||
|
if (candidates.length >= limit) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const profiles = await fetchProfiles(candidates.map((c) => c.pubkey));
|
const profiles = await fetchProfiles(candidates.map((c) => c.pubkey));
|
||||||
for (const review of candidates) review.profile = profiles.get(review.pubkey) ?? null;
|
for (const review of candidates) review.profile = profiles.get(review.pubkey) ?? null;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Recent reviews with a named author come first; everything else stays newest
|
* Strict recency, newest first, as the last thing that happens to this list.
|
||||||
* first behind them.
|
|
||||||
*
|
*
|
||||||
* Most review keys have published exactly one event in their life: the review
|
* The heading says "Latest reviews", so the order under it is the event
|
||||||
* itself. Nothing can be fetched for them, so a strict recency order fills this
|
* `created_at` and nothing else. This used to float reviews whose author had a
|
||||||
* strip with anonymous npubs while a named review sits a few rows below the
|
* kind 0 to the front, which read as broken on the page: a named review from two
|
||||||
* cut. This is the home page shop window, which already drops junk bodies, so
|
* months ago sat between two reviews from this week, and the card feet said so,
|
||||||
* it prefers a review a reader can attach a person to. Nothing is hidden:
|
* because the "2mo ago" label is formatted from the very same `created_at` this
|
||||||
* every review is on its mint page, and PROMOTE_MAX_AGE_S keeps "latest"
|
* sorts on. Author names are still resolved and still shown — they just no longer
|
||||||
* meaning latest.
|
* decide the order.
|
||||||
|
*
|
||||||
|
* Sorted here rather than left to the scan above, so that the invariant holds
|
||||||
|
* whatever the gathering loop does later, and `id` breaks ties between two events
|
||||||
|
* that share a second so two builds of the same events agree.
|
||||||
*/
|
*/
|
||||||
const cutoff = Math.floor(Date.now() / 1000) - PROMOTE_MAX_AGE_S;
|
candidates.sort((a, b) => b.created_at - a.created_at || a.id.localeCompare(b.id));
|
||||||
const promoted = (review: BuildReview): number =>
|
|
||||||
review.profile?.found && review.created_at >= cutoff ? 1 : 0;
|
|
||||||
|
|
||||||
candidates.sort((a, b) => promoted(b) - promoted(a) || b.created_at - a.created_at);
|
|
||||||
|
|
||||||
return candidates.slice(0, limit);
|
return candidates.slice(0, limit);
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
Reference in New Issue
Block a user