100 Commits
Author SHA1 Message Date
jake a8294d977b chore(docs): bump deps and swap fumadocs-ui for base-ui package 2026-10-07 13:54:59 -04:00
jake 0de75606a8 chore: set up changesets for versioning and releases (#68) 2026-10-07 12:28:56 -04:00
jakeandClaude Opus 5.5 2487cd0199 feat(web): link to sofa.watch from the landing page
Add a quiet "Powered by Sofa" footer to the logged-out splash screen,
linking to sofa.watch. The footer sits in normal flow below the hero so
it can't overlap the buttons on short screens, and clears the bottom
safe-area inset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 21:53:59 -04:00
jake ac76898db4 feat(docs): redesign the marketing landing page
Rebuild the home page hero, feature sections, and footer with a new layout, integration logos component, and an app screenshot. Drop the scroll indicator in favour of the new structure.
2026-10-06 21:47:43 -04:00
jakeandClaude Opus 5.5 8084561a18 fix(native): keep analytics off until the user opts in
Default analytics to off, and name screen events from route patterns instead of pathnames and params so they carry no content IDs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:56:58 -04:00
jakeandClaude Opus 5.5 f48da5e6c4 ci: smoke-test backup and restore
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:50:18 -04:00
jakeandClaude Opus 5.5 a4439dddb1 feat(server): back up before applying migrations
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:48:56 -04:00
jakeandClaude Opus 5.5 dcaf509160 test(db): apply migrations to a populated v0.2.0 database
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:48:53 -04:00
jakeandClaude Opus 5.5 c6e414ecdb test(db): cover platform seeding, session cleanup, and import recovery
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:43:07 -04:00
jakeandClaude Opus 5.5 561a1b6361 fix(native): keep Library filters visible while results load or fail
Render the filter strip and a pull-to-refresh ScrollView for the pending,
error and empty states instead of replacing the whole screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:37:06 -04:00
jakeandClaude Opus 5.5 8a406626ba fix(native): show only actors in the title cast row
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:33:55 -04:00
jakeandClaude Opus 5.5 9140891dd5 fix(cron): keep failing titles from blocking the non-library refresh
Exclude library titles and order by lastFetchedAt in SQL, and stamp
lastFetchedAt when a non-library refresh fails so it moves to the back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:30:17 -04:00
jakeandClaude Opus 5.5 c4a322948b fix(discovery): exclude rated and watched titles from recommendations
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:26:36 -04:00
jakeandClaude Opus 5.5 4eadce286b fix(web): ignore title shortcuts while a dialog or menu is open
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:23:04 -04:00
jakeandClaude Opus 5.5 f36820321c fix(server): validate image and avatar names and serve them inert
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:12:13 -04:00
jakeandClaude Opus 5.5 bd46b17711 fix(server): add security headers and reject cross-site API posts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:04:06 -04:00
jakeandClaude Opus 5.5 c51a668ace chore(deps): upgrade oRPC to v2 (2.0.0-beta.42)
- Pin all @orpc/* catalog entries to 2.0.0-beta.42; @sofa/api now depends on @orpc/openapi
- Contract routes move from .route() to .meta(openapi(...)); schemas gain meta ids so the
  OpenAPI document hoists them as named components; publicInfo overrides document-level security
- OpenAPI generator/handler use v2 APIs (converters, base, spec plugin option, OpenAPI 3.1.1 output)
- Add restoreRootFileType routing interceptor so root-level File inputs (avatar upload, backup
  restore) keep their MIME type under Bun.serve
- Web/native links use origin + path url; native error classification derives HTTP status from
  COMMON_ERROR_STATUS_MAP / MalformedResponseError since ORPCError.status is gone
- router-auth test reads v2 orderedMiddlewares; regenerated docs/public/openapi.json

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:08:12 -04:00
jakeandClaude Opus 5.5 8da4cbbe52 fix(tracking): report when a title was already in the library
updateStatus now returns { alreadyAdded }. Native toasts say so instead of
claiming success, and the Explore hero hides Add to Watchlist for library titles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 22:50:04 -04:00
jakeandClaude Opus 5.5 d6abcbd2bb fix(native): regroup Upcoming when the day or language changes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 22:45:29 -04:00
jakeandClaude Opus 5.5 1dc38f91b9 fix(backup): migrate restored files before swapping them in
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 22:41:02 -04:00
jakeandClaude Opus 5.5 45667f3540 fix(native): keep widget refreshes after resets and don't claim nothing is upcoming
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 22:34:42 -04:00
jakeandClaude Opus 5.5 6b56e3eff3 fix(stats): align count windows with chart buckets and fix month rollover
Window starts now equal the first chart bucket, and year buckets are built from the 1st of each month so the 29th-31st no longer repeat or skip months.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 22:31:32 -04:00
jakeandClaude Opus 5.5 fcd8731a6a fix(web): settings toggles refresh cache, backup next-run from server, update toast once
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 22:28:20 -04:00
jakeandClaude Opus 5.5 436c463cc8 fix(web): show change-password validation messages and failure reason
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 22:27:30 -04:00
jakeandClaude Opus 5.5 a6d642616b fix(cron): start manual jobs in the background and report busy jobs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 22:23:28 -04:00
jakeandClaude Opus 5.5 085b681d8a fix(native): explain change-password failures and block double submit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 22:15:57 -04:00
jakeandClaude Opus 5.5 ea9cb3de8d fix(native): skip recently-viewed and theming in link previews
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 22:12:30 -04:00
jakeandClaude Opus 5.5 ee53f33a79 fix(native): load more titles in Explore rows
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 22:10:14 -04:00
jakeandClaude Sonnet 5.5 ecf119c98e fix(native): show errors for Explore rows, failed pages and Register
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 22:06:42 -04:00
jakeandClaude Sonnet 5.5 669fc74653 fix(native): report SSO sign-in failures
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 22:03:06 -04:00
jakeandClaude Sonnet 5.5 8a6c32f376 fix(native): translate the recently viewed row's accessibility label
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 21:57:24 -04:00
jakeandClaude Sonnet 5.5 3d219ed638 chore(cron): remove query helpers replaced by checked-at stamps
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 21:56:49 -04:00
jakeandClaude Sonnet 5.5 911dc7e5f1 fix(tracking): clamp same-day log-a-watch time to now
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 21:50:57 -04:00
jakeandClaude Sonnet 5.5 cb5e0c19e7 feat(tracking): remove a single watch and log a watch on a date
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 21:50:56 -04:00
jakeandClaude Sonnet 5.5 4669d3b76d feat(native): add a watch history screen and trim the web phone tab bar
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 21:50:53 -04:00
jakeandClaude Opus 5.5 6f0b3b597f fix(public-api): allowlist telemetry features and keep /v1/version cacheable
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 21:45:43 -04:00
jakeandClaude Sonnet 5.5 b292fe37ab feat(tracking): add a paginated watch history and Last watched library sort
Adds tracking.history (cursor-paginated, movies and episodes merged), a
last_watched library sort, and a /history web page.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 14:36:44 -04:00
jakeandClaude Sonnet 5.5 6cd99a39a9 fix(upcoming): omit direction in the default view so the loader prefetch key matches
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 14:30:44 -04:00
jakeandClaude Sonnet 5.5 e625f319a2 feat(upcoming): add a "Recently aired" view of unwatched episodes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 14:29:47 -04:00
jakeandClaude Sonnet 5.5 e3f7ccca07 fix(dashboard): block duplicate quick-watch clicks until refetch and use logical end inset
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 14:21:47 -04:00
jakeandClaude Sonnet 5.5 04bcb66436 feat(dashboard): mark episodes watched from Continue Watching and Upcoming
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 14:20:09 -04:00
jakeandClaude Sonnet 5.5 899be96316 fix(cron): judge stale seasons by the latest season fetch
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 14:15:05 -04:00
jakeandClaude Sonnet 5.5 6576f21235 perf(cron): refresh ended titles less often and only recent seasons of returning shows
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 14:13:28 -04:00
jakeandClaude Sonnet 5.5 66a5e80544 fix(imports): skip specials and refresh shows once for new episodes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 14:09:14 -04:00
jakeandClaude Sonnet 5.5 e7f55d30e9 chore(native): define the root error fallback outside RootLayout
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 14:06:01 -04:00
jakeandClaude Sonnet 5.5 51d193b411 perf(metadata): remember empty TMDB lookups instead of refetching every view
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 14:01:22 -04:00
jakeandClaude Sonnet 5.5 edd6eb541d fix(imports): keep date-only values on their calendar day
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:51:49 -04:00
jakeandClaude Sonnet 5.5 1ccc138144 test(i18n): cover month labels when Intl defaults to UTC like the native polyfill
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:48:29 -04:00
jakeandClaude Sonnet 5.5 c40b6844a0 fix(i18n): format Upcoming month headers in UTC so native shows the right month
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:47:15 -04:00
jakeandClaude Sonnet 5.5 b7887eef70 fix(native): make select sheets and row actions usable with VoiceOver and TalkBack
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:43:21 -04:00
jakeandClaude Sonnet 5.5 851a188f00 fix(native): recover from render errors and let Close leave deep-linked titles
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:40:39 -04:00
jakeandClaude Sonnet 5.5 9d0bede536 fix(native): keep Android headers from covering Upcoming filters and the modal Close button
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:37:47 -04:00
jakeandClaude Sonnet 5.5 9209214e98 fix(native): clear every episode's pending state and block taps during Mark All
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:35:27 -04:00
jakeandClaude Sonnet 5.5 7770e1a697 fix(native): let Android menus open from their trigger
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:33:15 -04:00
jakeandClaude Opus 5.5 ccaacfeae5 feat(native): follow the system language instead of an in-app picker
Declare the app's 12 languages to iOS and Android via expo-localization,
resolve the language from the device's preferred languages at start-up and
on Android runtime changes, and make Settings > Language open the system
settings page. Drops the MMKV-stored locale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 13:24:59 -04:00
jakeandClaude Sonnet 5.5 d012280f20 fix(native): add a local-network usage description for LAN servers
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:17:20 -04:00
jakeandClaude Sonnet 5.5 55552cd1bf chore(native): require iOS 17
Raise ios.deploymentTarget from 16.4 to 17.0 (app and widget extension) and state the requirement in the mobile app docs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:13:28 -04:00
jake 12294de522 chore(vscode): update TypeScript settings for improved path resolution and enable experimental features 2026-10-05 13:13:04 -04:00
jakeandClaude Sonnet 5.5 0afc60f28c fix(native): show account edits immediately and save name on first tap
Bypass the 5-minute session cookie cache when refetching after name/avatar edits, keep taps on Save/Cancel working with the keyboard open, add Return-to-save, trim the name, and guard against double submit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:07:54 -04:00
jakeandClaude Sonnet 5.5 fbc6ac90a3 fix(native): show "Session expired" for every session loss the user didn't start
Replace the session-rejected / server-change / cached-session-seeded flags with a single
session-end reason that deliberate sign-outs mark before signing out. The session-loss
effect now toasts only when no reason was recorded.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:03:35 -04:00
jakeandClaude Sonnet 5.5 786a4ba7c5 fix(native): re-probe the server on retry and rebuild the auth client before marking a new server reachable
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 12:59:59 -04:00
jakeandClaude Sonnet 5.5 b46bc4cdcb fix(native): make the server-URL check reactive so the reachability monitor and banner work after first setup
With the React Compiler, hasServerUrl read from MMKV during render was
memoized forever at the root. Read it through useSyncExternalStore instead.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 12:54:17 -04:00
jakeandClaude Sonnet 5.5 8f4cd03715 fix(native): persist the query cache per server+user and clear it with the session
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 12:51:00 -04:00
jakeandClaude Opus 5.5 870d130261 chore(i18n): extract catalogs after sharing client helpers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 04:28:17 -04:00
jakeandClaude Opus 5.5 778a1356d5 refactor(api): share tracking-dependent query key lists between web and native
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 04:27:43 -04:00
jakeandClaude Opus 5.5 88e777d5ce refactor(api): share sparkline path and luminance helpers between web and native
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 04:27:15 -04:00
jakeandClaude Opus 5.5 4b38303404 refactor(i18n): re-export error helpers by name to satisfy no-barrel-file
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 04:27:12 -04:00
jakeandClaude Opus 5.5 01a14157c6 refactor(i18n): share integration status text between web and native
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 04:26:05 -04:00
jakeandClaude Opus 5.5 4adaa4a73b refactor(i18n): share error message maps between web and native
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 04:25:28 -04:00
jakeandClaude Opus 5.5 d874ae9198 refactor(web): share one import-job flow between import dialogs
Extract the job loop into runImportJob (with tests), hold its UI state in
useImportJob, and move the importing/done steps and stat/option components
into import-dialog-parts. Both dialogs now close when an import continues in
the background or the connection drops.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 04:11:48 -04:00
b63fbce60d feat(search): find titles by IMDb ID
Search queries that look like an IMDb ID (e.g. tt0133093) are now resolved
through TMDB's find endpoint, respecting the movie/tv type filter.

Supersedes #60.

Co-authored-by: Gonçalo Fonseca <gcare.fonseca99@outlook.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 03:57:00 -04:00
jakeandClaude Opus 5.5 0f82de55cb refactor(core): move discover logic into @sofa/core/browse
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 03:56:10 -04:00
jakeandClaude Opus 5.5 07e8e79e51 test(server): characterize discover procedures
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 03:53:30 -04:00
jakeandClaude Opus 5.5 d6ac2324e7 fix(discover): map TV date sorts, clamp TMDB page counts, and pause infinite scroll after a failed page
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 03:31:06 -04:00
jakeandClaude Opus 5.5 7269209d43 fix(web): load more titles in Explore rows and show status in Discover
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 03:23:27 -04:00
jakeandClaude Opus 5.5 9aebca7121 perf(metadata): process episode art in the background with bounded concurrency
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 03:17:41 -04:00
jakeandClaude Opus 5.5 40517b5214 fix(native): add the Library tab and translated labels on Android
The Android tab bar only declared four tabs with hard-coded English
labels, so the Library route was never registered and "See all" on Home
did nothing. Match the iOS tab set and order and use LingUI labels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 03:11:21 -04:00
jakeandClaude Opus 5.5 67766298d8 fix(native): block duplicate watch taps, stop invalidating title details, and show refresh spinner only on pull
- invalidateTitleQueries no longer invalidates titles.get and returns a promise for tracking/library refetches; mutations return it from onSuccess so isPending covers the refetch
- per-episode pending guard (disabled + dimmed row) and disabled season "Mark All Watched" while pending
- add usePullToRefresh so RefreshControl only reflects user-initiated pulls (Home, Explore, Library, Upcoming)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 03:07:24 -04:00
jakeandClaude Opus 5.5 bc3ea712f9 fix(imports): poll device codes one request at a time
The Trakt/Simkl sign-in dialog polled with setInterval and no in-flight
guard, so while the first "authorized" poll was still fetching the
library, the next tick re-sent the redeemed device code. Trakt answers
409, which was mapped to "expired", producing a false "Device code
expired" error.

- public-api: map Trakt 409 (already redeemed) to pending
- web: add a single-flight device-code poller that drops late responses
  after stop() and aborts the in-flight request
- web: use it in the imports dialog and ignore device-code responses
  that arrive after the dialog was closed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 03:00:42 -04:00
jakeandClaude Opus 5.5 feb41e3149 fix(native): sync React Query online state with server reachability
Probe the health endpoint while unreachable, refetch errored queries when the server
returns, and keep gcTime at least as long as the persister maxAge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 02:51:59 -04:00
jakeandClaude Opus 5.5 07ea8f68f2 fix(native): keep cached screens on refetch errors and show errors instead of empty states
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 02:51:57 -04:00
jakeandClaude Opus 5.5 25cf4f1bc8 fix(native): route to the right screen when the session is lost
The session-loss effect never ran because sessionLost was computed in a
render that also called setState, so the committed value was always false.
Compare against a ref inside the effect instead, re-validate the session on
401s, stop retrying 4xx errors, and show the change-server link on
OIDC-only login screens.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 02:39:54 -04:00
jakeandClaude Sonnet 5.5 e5209f80fe fix(auth): key rate limits on the resolved client IP and restrict the Expo auth proxy
Resolve the client IP from the TCP peer plus trusted-proxy X-Forwarded-For hops
(TRUSTED_PROXIES) and hand it to Better Auth in an internal header, so spoofed
forwarding headers can no longer rotate sign-in rate-limit buckets. The Expo
authorization proxy now only redirects to the OIDC provider's authorization endpoint.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 00:09:53 -04:00
jakeandClaude Opus 5.5 b8b5b31fa1 fix(i18n): render mapped error messages and stop showing raw server errors
Helpers that took Lingui's `t` as a parameter rendered empty strings because
the macro only transforms `t` imported from the macro. Use msg descriptors
plus i18n._ instead, so mapped error toasts and native server-URL errors are
real, extractable strings. Also map Better Auth error codes to localized
messages instead of showing raw server text, and send a REGISTRATION_CLOSED
code from the auth hook.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 23:44:10 -04:00
jakeandClaude Opus 5.5 4c58b550b1 fix(server): cap request bodies and require a session before large uploads
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 23:33:36 -04:00
jakeandClaude Opus 5.5 e9fb4797e5 perf(imports): poll job progress without the payload and drop it when done
readImportJob now selects only progress columns instead of the multi-MB
payload, processImportJob empties the payload once a job reaches a terminal
status, and server startup clears payloads of previously finished jobs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 23:27:04 -04:00
jake 0b7d75a59b chore(native): bump version to 0.3.0 2026-10-04 23:26:50 -04:00
jakeandClaude Opus 5.5 82f0bb11e2 perf(db): collect planner statistics on connect and after imports
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 23:18:25 -04:00
jakeandClaude Opus 5.5 6620f0b76f test(server): add test harness and auth coverage for every procedure
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 23:14:56 -04:00
jakeandClaude Opus 5.5 810bbecf78 fix(imports): cap uncompressed size and entry count of uploaded ZIPs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 23:06:34 -04:00
jakeandClaude Sonnet 5.5 69b252e99b fix(native): serialize widget refreshes and fall back to other artwork
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 18:02:06 -04:00
jakeandClaude Sonnet 5.5 c62ef6b620 fix(native): keep widget timelines current and localize widget text
expo-widgets rebuilds each widget timeline from the stored entries when it
ends, so five entries 15 minutes apart left the widgets stuck on the last
entry (the 5th show, or the furthest-away release) after an hour.

Continue Watching now rotates through up to five shows every 30 minutes for
12 hours, then rests on the top show. Upcoming writes one entry per local
midnight at which the shown item or its Today/Tomorrow label changes, moves
on after each air date and ends on the empty state once everything has aired.

All widget text is now produced in widgets.ts through LingUI and passed to the
widget extension as string props, replacing the hard-coded English labels and
month table. The widget catalogs gain "S{seasonNum} E{epNum}", "Nothing to
watch" and "Nothing upcoming"; the rest reuse existing messages. The refresh
now waits for the locale catalog so English labels are not baked in first.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 17:47:52 -04:00
jakeandClaude Sonnet 5.5 b4fdf6164f fix(native): cache widget artwork at its real pixel size
UIGraphicsImageRenderer(size:) uses the screen scale by default, so the cached JPEGs came out about 1395px wide instead of the intended 465px. WidgetKit refuses to render images whose pixel area is far beyond the widget's, and the extension has a tight memory limit, so oversized art could blank the widget.

Render at scale 1 into a center-cropped 510px square (systemSmall is at most 170pt, or 510px at 3x) and bump JPEG quality to 0.8 now that the files are much smaller.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 17:38:04 -04:00
jakeandClaude Sonnet 5.5 9bbe36b2d4 fix(native): give home-screen widgets a container background and full-bleed artwork
iOS 17+ rendered 'Please adopt containerBackground API' because expo-widgets 56 dropped its hard-coded container background and neither widget applied the modifier. Artwork also drew at its raw pixel size because the images were never resizable, and the layout assumed a fixed 155pt box with default content margins.

Apply containerBackground, make the artwork resizable, aspect-filled and clipped, replace the flat overlay with a gradient scrim, left-align the text block, use a native linear ProgressView, and disable content margins via the plugin's ios config. Also correct the Continue Watching description, since the feed only contains TV episodes.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 17:37:08 -04:00
jakeandClaude Sonnet 5.5 6a1b753a49 fix(public-api): paginate Trakt sign-in import and keep it under the response limit
Follow Trakt's pagination headers, slim items to the fields Sofa reads,
keep the most recent plays when the payload would exceed Vercel's 4.5 MB
response limit, surface failed/truncated lists as warnings, and return a
readable fetch_error instead of an oversized response for every provider.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 17:27:26 -04:00
jakeandClaude Sonnet 5.5 57aaa5e7d2 fix(core): allow scheduler jitter in update-check and telemetry throttles
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 17:17:18 -04:00
jakeandClaude Sonnet 5.5 98fd236b5c fix(auth): refresh the session cookie cache after first-admin promotion
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 17:10:49 -04:00
jakeandClaude Sonnet 5.5 d42a022a30 fix(i18n): format date-only values in UTC and share an age helper
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 17:05:33 -04:00
jakeandClaude Sonnet 5.5 5a96fd39f1 fix(webhooks): accept native Emby payloads, ignore episode TMDB ids, refresh on missing episodes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 16:46:00 -04:00
jakeandClaude Sonnet 5.5 f05e63bab7 fix(public-api): treat Simkl KO as pending and unwrap all-items responses
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 16:41:00 -04:00