From f3f16b5c670daadfb3c32651eaf4b116316d5cdb Mon Sep 17 00:00:00 2001 From: goon-foss Date: Thu, 13 Aug 2026 20:30:17 +0200 Subject: [PATCH] feat(favorites): ulubione studia licza takze filmy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Studio bywa WYLACZNIE filmowe: Jonathan Jordan XXX 0 scen / 654 filmy, Kink Clips 0/616, EAGLE 0/523. Lista ulubionych pokazywala wtedy samo "0 scenes", czyli wygladala na pusta, mimo ze badge "+N" liczyl filmy juz od 2026-07-28 (_merged_new_counts). Backend: `FavoriteStudioOut.movie_count`, liczony NA ZYWO. Ulubionych studiow jest kilkaset na urzadzenie, a filmow o rzedy wielkosci mniej niz scen, wiec agregat jest tani i nie trzeba kolejnej zdenormalizowanej kolumny do utrzymania. Apka pokazuje oba liczniki, a gdy jednego nie ma, pomija go, zeby nie robic z tego "0 scenes · 654 movies". Domyka to temat zaczety zakladka Movies na ekranie studia: dodanie do ulubionych od strony filmu juz dzialalo (gwiazdka w StudioMoviesScreen). --- app/api/favorites.py | 30 +++++++++++++++++++++++++- mobile/src/changelog.ts | 7 ++++++ mobile/src/screens/FavoritesScreen.tsx | 18 +++++++++++++++- mobile/src/types.ts | 3 +++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/app/api/favorites.py b/app/api/favorites.py index c469f2f..dd77635 100644 --- a/app/api/favorites.py +++ b/app/api/favorites.py @@ -27,7 +27,7 @@ from typing import Annotated from fastapi import APIRouter, Depends, HTTPException, status from pydantic import BaseModel -from sqlalchemy import exists, select +from sqlalchemy import exists, func, select from sqlalchemy.orm import Session from app.api.device import get_device_id @@ -307,6 +307,10 @@ class FavoriteStudioOut(BaseModel): slug: str network: str | None = None scene_count: int + #: Filmów z żywym playbackiem. Studio może mieć ZERO scen i setki filmów + #: (Jonathan Jordan XXX 0/654, Kink Clips 0/616, EAGLE 0/523), a lista ulubionych + #: pokazywała wtedy samo „0" i wyglądała na pustą, mimo że „+N" liczyło już filmy. + movie_count: int = 0 new_count: int last_seen_at: datetime created_at: datetime @@ -334,6 +338,29 @@ def list_favorite_studios( # scene_count: zdenormalizowany Studio.scene_count (refresh w tle, migracja 0019). scene_counts: dict = {st.id: st.scene_count for _, st in rows} + # movie_count liczymy NA ŻYWO: ulubionych studiów jest kilkaset na urządzenie, + # a filmów o rzędy wielkości mniej niż scen, więc agregat jest tani i nie trzeba + # kolejnej zdenormalizowanej kolumny do utrzymania. + from app.models.movie import Movie + from app.models.movie_playback_source import MoviePlaybackSource + + studio_ids = [st.id for _, st in rows] + movie_counts: dict = { + sid: n + for sid, n in session.execute( + select(Movie.studio_id, func.count()) + .where( + Movie.studio_id.in_(studio_ids), + exists( + select(1).where( + MoviePlaybackSource.movie_id == Movie.id, + MoviePlaybackSource.dead_at.is_(None), + ) + ), + ) + .group_by(Movie.studio_id) + ).all() + } new_counts = _merged_new_counts(session, device_id, kind="studio") items: list[FavoriteStudioOut] = [] @@ -348,6 +375,7 @@ def list_favorite_studios( slug=st.slug, network=st.network, scene_count=scene_counts.get(st.id, 0), + movie_count=movie_counts.get(st.id, 0), new_count=nc, last_seen_at=fav.last_seen_at, created_at=fav.created_at, diff --git a/mobile/src/changelog.ts b/mobile/src/changelog.ts index b660bd8..42b1619 100644 --- a/mobile/src/changelog.ts +++ b/mobile/src/changelog.ts @@ -16,6 +16,13 @@ export type ChangelogEntry = { }; export const CHANGELOG: ChangelogEntry[] = [ + { + id: '2026-08-13c', + date: 'August 2026', + items: [ + 'Followed studios now show how many movies they have, not just scenes. Studios that only put out movies used to look empty in your favourites.', + ], + }, { id: '2026-08-13b', date: 'August 2026', diff --git a/mobile/src/screens/FavoritesScreen.tsx b/mobile/src/screens/FavoritesScreen.tsx index eb68f69..410af7c 100644 --- a/mobile/src/screens/FavoritesScreen.tsx +++ b/mobile/src/screens/FavoritesScreen.tsx @@ -463,6 +463,22 @@ function MovieRow({ ); } +// Studio bywa WYŁĄCZNIE filmowe (Jonathan Jordan XXX 0 scen / 654 filmy, Kink Clips +// 0/616), a wiersz pokazywał wtedy „0 scenes", czyli wyglądał na pusty, mimo że badge +// „+N" liczył filmy od 2026-07-28. Pokazujemy oba, a gdy jednego nie ma, pomijamy go, +// żeby nie robić z tego „0 scenes · 654 movies". +function studioCounts(fav: FavoriteStudioOut): string { + const parts: string[] = []; + const movies = fav.movie_count ?? 0; + if (fav.scene_count > 0 || movies === 0) { + parts.push(`${formatCount(fav.scene_count)} ${fav.scene_count === 1 ? 'scene' : 'scenes'}`); + } + if (movies > 0) { + parts.push(`${formatCount(movies)} ${movies === 1 ? 'movie' : 'movies'}`); + } + return parts.join(' · '); +} + function StudioRow({ fav, onPress, @@ -487,7 +503,7 @@ function StudioRow({ {fav.name} - {formatCount(fav.scene_count)} {fav.scene_count === 1 ? 'scene' : 'scenes'} + {studioCounts(fav)} {fav.network ? ` · ${fav.network}` : ''} diff --git a/mobile/src/types.ts b/mobile/src/types.ts index 6ff8d40..8f367e1 100644 --- a/mobile/src/types.ts +++ b/mobile/src/types.ts @@ -347,6 +347,9 @@ export interface FavoriteStudioOut { slug: string; network: string | null; scene_count: number; + /** Filmów z żywym playbackiem. Studio bywa WYŁĄCZNIE filmowe (0 scen, + * setki filmów), a lista pokazywała wtedy samo „0 scenes". */ + movie_count?: number; new_count: number; last_seen_at: string; created_at: string;