feat(favorites): ulubione studia licza takze filmy
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).
This commit is contained in:
parent
1a75433281
commit
f3f16b5c67
4 changed files with 56 additions and 2 deletions
|
|
@ -27,7 +27,7 @@ from typing import Annotated
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException, status
|
from fastapi import APIRouter, Depends, HTTPException, status
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from sqlalchemy import exists, select
|
from sqlalchemy import exists, func, select
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.api.device import get_device_id
|
from app.api.device import get_device_id
|
||||||
|
|
@ -307,6 +307,10 @@ class FavoriteStudioOut(BaseModel):
|
||||||
slug: str
|
slug: str
|
||||||
network: str | None = None
|
network: str | None = None
|
||||||
scene_count: int
|
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
|
new_count: int
|
||||||
last_seen_at: datetime
|
last_seen_at: datetime
|
||||||
created_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_count: zdenormalizowany Studio.scene_count (refresh w tle, migracja 0019).
|
||||||
scene_counts: dict = {st.id: st.scene_count for _, st in rows}
|
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")
|
new_counts = _merged_new_counts(session, device_id, kind="studio")
|
||||||
|
|
||||||
items: list[FavoriteStudioOut] = []
|
items: list[FavoriteStudioOut] = []
|
||||||
|
|
@ -348,6 +375,7 @@ def list_favorite_studios(
|
||||||
slug=st.slug,
|
slug=st.slug,
|
||||||
network=st.network,
|
network=st.network,
|
||||||
scene_count=scene_counts.get(st.id, 0),
|
scene_count=scene_counts.get(st.id, 0),
|
||||||
|
movie_count=movie_counts.get(st.id, 0),
|
||||||
new_count=nc,
|
new_count=nc,
|
||||||
last_seen_at=fav.last_seen_at,
|
last_seen_at=fav.last_seen_at,
|
||||||
created_at=fav.created_at,
|
created_at=fav.created_at,
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,13 @@ export type ChangelogEntry = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CHANGELOG: 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',
|
id: '2026-08-13b',
|
||||||
date: 'August 2026',
|
date: 'August 2026',
|
||||||
|
|
|
||||||
|
|
@ -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({
|
function StudioRow({
|
||||||
fav,
|
fav,
|
||||||
onPress,
|
onPress,
|
||||||
|
|
@ -487,7 +503,7 @@ function StudioRow({
|
||||||
{fav.name}
|
{fav.name}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={styles.rowMuted}>
|
<Text style={styles.rowMuted}>
|
||||||
{formatCount(fav.scene_count)} {fav.scene_count === 1 ? 'scene' : 'scenes'}
|
{studioCounts(fav)}
|
||||||
{fav.network ? ` · ${fav.network}` : ''}
|
{fav.network ? ` · ${fav.network}` : ''}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
||||||
|
|
@ -347,6 +347,9 @@ export interface FavoriteStudioOut {
|
||||||
slug: string;
|
slug: string;
|
||||||
network: string | null;
|
network: string | null;
|
||||||
scene_count: number;
|
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;
|
new_count: number;
|
||||||
last_seen_at: string;
|
last_seen_at: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue