Add @sofa/native Expo React Native app (#7)

This commit is contained in:
2026-03-12 19:39:54 -04:00
committed by GitHub
parent a326c968b7
commit 83839a0cd7
130 changed files with 9015 additions and 971 deletions
+20 -2
View File
@@ -487,8 +487,26 @@ export function getRecommendationsForTitle(titleId: string) {
if (recs.length === 0) return [];
const sourcePriority = {
tmdb_recommendations: 0,
tmdb_similar: 1,
} as const;
const orderedRecs = [...recs].sort(
(a, b) =>
a.rank - b.rank || sourcePriority[a.source] - sourcePriority[b.source],
);
const seenRecommendedTitleIds = new Set<string>();
const uniqueRecs = orderedRecs.filter((rec) => {
if (seenRecommendedTitleIds.has(rec.recommendedTitleId)) {
return false;
}
seenRecommendedTitleIds.add(rec.recommendedTitleId);
return true;
});
// Batch fetch all recommended titles (1 query)
const recTitleIds = recs.map((r) => r.recommendedTitleId);
const recTitleIds = uniqueRecs.map((r) => r.recommendedTitleId);
const recTitles = db
.select()
.from(titles)
@@ -496,7 +514,7 @@ export function getRecommendationsForTitle(titleId: string) {
.all();
const recTitleMap = new Map(recTitles.map((t) => [t.id, t]));
return recs
return uniqueRecs
.map((rec) => {
const r = recTitleMap.get(rec.recommendedTitleId);
if (!r) return null;
+1 -1
View File
@@ -213,7 +213,7 @@ async function getImageCacheHealth(): Promise<SystemHealthData["imageCache"]> {
return { enabled: false, totalSizeBytes: 0, imageCount: 0, categories: {} };
}
const categoryNames = ["posters", "backdrops", "stills", "logos"];
const categoryNames = ["posters", "backdrops", "stills", "logos", "profiles"];
const categories: Record<string, { count: number; sizeBytes: number }> = {};
let totalSizeBytes = 0;
let imageCount = 0;
+22
View File
@@ -336,4 +336,26 @@ describe("getRecommendationsForTitle", () => {
const recs = getRecommendationsForTitle("m1");
expect(recs).toHaveLength(0);
});
test("deduplicates titles returned by multiple recommendation sources", () => {
insertTitle({ id: "m1", tmdbId: 1 });
insertTitle({ id: "rec1", tmdbId: 10, title: "Rec One" });
insertTitle({ id: "rec2", tmdbId: 20, title: "Rec Two" });
insertRecommendation("m1", "rec1", {
source: "tmdb_similar",
rank: 1,
});
insertRecommendation("m1", "rec1", {
source: "tmdb_recommendations",
rank: 2,
});
insertRecommendation("m1", "rec2", {
source: "tmdb_recommendations",
rank: 3,
});
const recs = getRecommendationsForTitle("m1");
expect(recs).toHaveLength(2);
expect(recs.map((rec) => rec.id)).toEqual(["rec1", "rec2"]);
});
});