Follow-up cleanup from the ultra-review (behaviour-preserving, verified equivalent): - scenes.py: extract live_playback_exists / blacklist_clauses / stub_exclusion_clause; list_scenes and favorites now share ONE definition of "visible scene" (was a hand-kept copy in favorites -> the count-vs-list drift class). Verified identical: helper vs old inline both count 1,853,327 scenes. - favorites.py: replace the two copy-pasted count blocks with one _new_counts(kind=...) that counts in SQL (count(*) FILTER over the windowed subquery) instead of streaming up to N*200 rows to Python; joins the favorite table for per-row last_seen. Deployed _new_counts verified == hand SQL (studios 364). Dropped now-unused imports. - mobile: extract lib/newScenes.ts (isNewScene / sortNewFirst); SceneTile + Performer/ StudioScenes use it (was triplicated, already drifted once in the deleted FavoriteSceneRow). - SceneDetail: fold tube:pornxpph into the phoneResolver map (was a verbatim-duplicated block). - deep_crawl: persist the cursor after every completed page (was once at run end), so a mid-page hard-kill past the soft budget can't lose progress (GOON-V hardening). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
26 lines
1.2 KiB
TypeScript
26 lines
1.2 KiB
TypeScript
// Jedna definicja "co jest NOWĄ sceną" dla favorite-driven widoków (PerformerScenes,
|
|
// StudioScenes, SceneTile). Wcześniej reguła była skopiowana w 3-4 miejscach i dryfowała
|
|
// (martwy FavoriteSceneRow miał starą wersję bez backfillu). Trzymaj tu.
|
|
import type { SceneOut } from '../types';
|
|
|
|
/**
|
|
* NEW = dodane od ostatniej wizyty (created_at > seenSince), ale NIE backfill (masowy
|
|
* import starego katalogu, tube podaje datę importu jako release_date, więc udawałby
|
|
* świeżość). Spójne z licznikiem "+N" w backendzie (app/api/favorites.py _new_counts).
|
|
*/
|
|
export function isNewScene(scene: SceneOut, seenSince: string | undefined): boolean {
|
|
return !!(seenSince && scene.created_at && scene.created_at > seenSince && !scene.backfill);
|
|
}
|
|
|
|
/** NEW-first: nowe sceny na górę (zachowując kolejność), reszta bez zmian. Bez seenSince
|
|
* zwraca listę jak jest. */
|
|
export function sortNewFirst(items: SceneOut[], seenSince: string | undefined): SceneOut[] {
|
|
if (!seenSince) return items;
|
|
const newOnes: SceneOut[] = [];
|
|
const rest: SceneOut[] = [];
|
|
for (const s of items) {
|
|
if (isNewScene(s, seenSince)) newOnes.push(s);
|
|
else rest.push(s);
|
|
}
|
|
return [...newOnes, ...rest];
|
|
}
|