Commit graph

9 commits

Author SHA1 Message Date
jtrzupek
567a8fb3b5 fix(mobile): scene-list scroll perf + native phone-side fpoxxx resolver
(1) Scroll jank/device load on long scene lists (report 5b7ca1e1): SceneTile is now React.memo'd so typing in search no longer re-renders every mounted tile, and sceneGridProps bounds the render window (windowSize 7 etc.) — required because removeClippedSubviews stays false to avoid thumbnail blanking. Applies to all scene grids. (2) fpoxxx played an ad instead of the video via the WebView fallback (reports f79beefb/cfa207c7). fpoxxx is KVS with an IP-bound + session-bound get_file token (cross-IP 403 confirmed), so it must resolve phone-side: new fpoxxxResolver fetches the page + follows get_file on the device (KVS real_url port for the function/0 case), wired into SceneDetailScreen like sxyprn/eporner. Verified from a residential IP: get_file -> CDN returns 206 video/mp4.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 11:02:21 +02:00
jtrzupek
00f4779abe feat(mobile): column toggle, duration filter, saved searches, screen protection (mobilism feedback)
Batch from user feedback: (1) Grid columns 1/2/3 setting (PreferencesContext, persisted) across all scene grids — default 2 was too small on phones. (2) Min-duration filter chips (5/10/20/30+ min) to hide ad-clips. (3) Saved-search chips + Save button (backed by /saved-searches). (4) Re-enabled screen-capture protection (Recents hide + screenshot block) for distributed users — verified active on emulator (screencap returns 0 bytes). (5) 'Checking for updates' gate before the PIN screen so a background OTA restart no longer causes a double PIN prompt. Changelog entry added. Published OTA runtime 1.1 (a9620b12).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 13:52:27 +02:00
jtrzupek
940d4872e3 fix(mobile): removeClippedSubviews=false on grids — stop thumbnails vanishing on scroll
Android FlatList defaults removeClippedSubviews=true, which detaches off-viewport
subviews; expo-image frequently fails to re-render them when they scroll back in →
blank thumbnails (bug-report f181d382 2026-06-07, recurring). Disable on all heavy
image grids: scene grids (Scenes/Site/Studio/Tag/Performer) + movie poster grids.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 10:18:48 +02:00
jtrzupek
24fc790691 mobile: skeleton grid while scene lists load (perceived perf)
Scene-list screens showed a small spinner while waiting on the API, so a slow
list read felt like a blank stall. Replace the initial-load spinner on
ScenesScreen and TagScenesScreen with a SceneGridSkeleton — a 2-col grid of
pulsing placeholder tiles laid out 1:1 with SceneTile (16:9 thumb + title + meta
lines). It paints instantly with zero data, so the screen feels responsive even
when the query takes a moment, and the skeleton->content swap doesn't reflow.

Pairs with the backend list-count fix (most filtered lists are now ~0.1s); the
skeleton also masks the residual slow path (enormous tags) so it no longer reads
as a freeze.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 12:03:33 +02:00
jtrzupek
5ae5dbb201 perf(scenes): bounded count + has_more for filtered scene lists
Filtered /scenes (tag/origin/q/studio/performer) ran exhaustive COUNT with
stub-filter EXISTS over 1.7M rows: TAG 5.1s, ORIGIN 4.9s, SEARCH 3.1s.
Mobile relied on `loaded < total` for infinite-scroll, making exact count
mandatory and ruling out approximate shortcuts.

Backend:
- SceneListOut gains has_more (bool) and total_capped (bool), both optional
  for backward compat with old mobile
- Filtered count uses LIMIT _COUNT_CAP+1 (1000) subquery — cost is
  O(min(matches, cap)) instead of O(all). Measured: TAG 5.1s→664ms,
  SEARCH 3.1s→138ms, ORIGIN 4.9s→1.07s (also fixes SiteScenes showing
  global count ~1M instead of per-site count)
- has_more from fetching per_page+1 rows (essentially free); extra row
  stripped before serialisation
- Pure-default list (no filters at all) keeps TTL-cached full count

Mobile:
- getNextPageParam uses has_more ?? fallback to loaded<total
- Display shows "{total}+" when total_capped=true (5 screens)

Verified on emulator: tag "Big Tits" → "1000 scenes" loaded, no 500s,
backward compat confirmed (old APK works against new backend).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 19:24:26 +02:00
jtrzupek
177a45eee7 style(mobile): SceneTile shared component, 2-col grid w 5 ekranach scen
Jan feedback po pierwszym overhaulu: layout 2-col tile pasuje, ale aktywnie
tylko na ScenesScreen - reszta ekranow scen (SiteScenes, PerformerScenes,
StudioScenes, TagScenes) dalej w full-width row layoucie.

Wyciagniety SceneTile do mobile/src/components/SceneTile.tsx ze wsparciem:
- secondLine: 'studio' | 'performers' | 'date' | 'none' - per-ekran dobor
  metadanej (Studio na SiteScenes/Performer, performers na Studio, etc)
- seenSince: ISO timestamp - pokazuje NEW badge gdy scene.created_at > seen
  (uzywane na Performer/Studio screens dla NEW od ostatniego markFavoriteSeen)
- onLongPress: opcjonalny custom handler (default = animated preview)

Refaktor 5 ekranow:
- ScenesScreen: usuwa lokalna kopie SceneTile, import shared
- SiteScenesScreen: SceneRow -> SceneTile (numColumns=2, secondLine='studio')
- PerformerScenesScreen: FavoriteSceneRow -> SceneTile (numColumns=2)
- StudioScenesScreen: FavoriteSceneRow -> SceneTile (numColumns=2, performers)
- TagScenesScreen: lokalna SceneRow -> SceneTile

FavoriteSceneRow component zostaje (legacy import w PerformerScenes - nie
ruszamy bo moze byc uzyty w innym kontekscie). gridRow style scaffold (gap+
marginBottom) dodany w kazdym StyleSheet osobno bo te ekrany maja rozne
paddingHorizontal w container.

OTA: 9eea7ac6-df72-460e-9660-22bf6c39c3ac live, runtime 1.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 15:16:09 +02:00
jtrzupek
aa647dcf97 style(mobile): UI overhaul - warm dark, oxblood, wordmark, 2-col grid
Audit przez impeccable.style/slop: aktualny theme byl literal "AI default
palette" - deep navy #08090F + purple #8B5CF6 + glow #A78BFA + brak custom
typography. Plus user feedback "wieksze miniaturki, mniej tekstu - to portal
video".

theme.ts:
- Warm dark: bg #15110D (charcoal z orange undertone), card #26201A, fg
  warm off-white #F5EDE0
- Accent: oxblood #B23A48 + amber secondary #D89B4A (brak purple, brak glow)
- type + space scale (1.25 ratio, 8/16/24/32 spacing) eksportowane
- Backwards-compat: accentDeep/Glow/Secondary/good/warn/bad zachowane
- Font scaffold: komentarz z instrukcja jak dodac General Sans + Geist Mono
  (Fontshare/Vercel free) - czeka na expo-font install

GoonWordmark + GoonMark: custom letterform SVG (4 litery jako path geometry,
flat ellipses + descender hook). Monogram standalone dla icon/splash.
Wstrzykniety do TopTabs (header) zamiast plain "" title.

ScenesScreen:
- 2-col 16:9 grid (SceneTile) zamiast full-width SceneRow (6 lini tekstu)
- Title 1 linijka, studio uppercase micro
- Wyrzucone z listy: performers, release_date, sources count, "watched"
  string - replaced check badge + dim
- Duration badge bottom-right thumb, fav badge top-left

OTA: faad1f92-541a-4241-81fd-9cf159173b7e live, runtime 1.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 15:06:34 +02:00
https://github.com/goon-foss/goon
b6e3b1cbb5 Origin/hoster filter w /scenes + Filter modal
Dotąd nie dało się docelować sceny konkretnego hostera — search faworyzuje
xnxx/xvideos (dominują bazę), brak filtra po źródle. Diagnostyka per-hoster
(test cookie-fix, luluvid, porntrex) wymagała trafienia sceny danego tube'a.

- /scenes?origin=<substr> — exists() na PlaybackSource.origin ilike, np.
  'hqporner' łapie tube:hqpornercom
- ScenesFilterModal: sekcja "Source / hoster" (TextInput) w FilterState.origin
- ScenesScreen: filter.origin → listScenes; liczone do activeCount

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 12:12:50 +02:00
goon-foss
ad0284585b Initial commit
Goon — self-hosted aggregator for adult-content scene metadata.

Indexes scenes from TPDB, StashDB, and 30+ public adult tube sites.
Cross-source deduplication via perceptual hash + Levenshtein distance.
FastAPI backend + APScheduler worker + React Native (Expo) mobile client.

FOSS, ad-free, donation-funded. See README for details.
2026-05-20 10:10:22 +02:00