mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-07-14 18:15:56 -04:00
feat(native): add iOS home screen widgets for continue watching and upcoming
- Add `ContinueWatching` (systemSmall) and `Upcoming` (systemSmall) SwiftUI widgets via `expo-widgets`, registered in `app.json` under the `group.com.jakejarvis.sofa` app group - Add `widget-images` local Expo module with a Swift `WidgetImagesModule` that downloads and resizes remote poster images into the shared app group container for use by widgets; also copies bundled assets (sofa icon fallback) - Add `src/lib/widgets.ts` to fetch dashboard data, cache poster images, and write a JSON timeline to the shared container via `expo-widgets` - Add `ContinueWatching` and `Upcoming` SwiftUI widget views in `src/widgets/` - Add `useWidgetRefresh` hook that refreshes widgets on foreground (throttled to once per minute) and on session ready - Debounce widget refresh in `invalidateTitleQueries` so rapid mutations (e.g. marking multiple episodes watched) batch into a single refresh - Expose `titles.upcoming` from the dashboard procedure and add `upcomingTitles` field to the dashboard schema - Bump iOS deployment target to 16.2 (required by WidgetKit timeline APIs)
This commit is contained in:
@@ -567,6 +567,8 @@ export const UpcomingItemSchema = z
|
||||
titleType: z.enum(["movie", "tv"]).describe("Media type"),
|
||||
posterPath: z.string().nullable().describe("Poster image path"),
|
||||
posterThumbHash: z.string().nullable().describe("ThumbHash blur placeholder"),
|
||||
backdropPath: z.string().nullable().describe("Backdrop image path"),
|
||||
backdropThumbHash: z.string().nullable().describe("ThumbHash blur placeholder for backdrop"),
|
||||
seasonNumber: z.number().nullable().describe("Season number (TV only)"),
|
||||
episodeNumber: z.number().nullable().describe("Episode number (TV only)"),
|
||||
episodeName: z.string().nullable().describe("Episode title (TV only)"),
|
||||
|
||||
@@ -359,6 +359,8 @@ export interface UpcomingItem {
|
||||
titleType: "movie" | "tv";
|
||||
posterPath: string | null;
|
||||
posterThumbHash: string | null;
|
||||
backdropPath: string | null;
|
||||
backdropThumbHash: string | null;
|
||||
seasonNumber: number | null;
|
||||
episodeNumber: number | null;
|
||||
episodeName: string | null;
|
||||
@@ -526,6 +528,8 @@ export function getUpcomingFeed(
|
||||
titleType: "tv",
|
||||
posterPath: r.posterPath,
|
||||
posterThumbHash: r.posterThumbHash,
|
||||
backdropPath: r.backdropPath ?? null,
|
||||
backdropThumbHash: r.backdropThumbHash ?? null,
|
||||
seasonNumber: r.seasonNumber,
|
||||
episodeNumber: r.episodeNumber,
|
||||
episodeName: isCollapsed ? null : r.episodeName,
|
||||
@@ -547,6 +551,8 @@ export function getUpcomingFeed(
|
||||
titleType: "movie",
|
||||
posterPath: r.posterPath,
|
||||
posterThumbHash: r.posterThumbHash,
|
||||
backdropPath: r.backdropPath ?? null,
|
||||
backdropThumbHash: r.backdropThumbHash ?? null,
|
||||
seasonNumber: null,
|
||||
episodeNumber: null,
|
||||
episodeName: null,
|
||||
|
||||
@@ -323,6 +323,8 @@ export function getUpcomingEpisodes(userId: string, fromDate: string, toDate: st
|
||||
titleName: titles.title,
|
||||
posterPath: titles.posterPath,
|
||||
posterThumbHash: titles.posterThumbHash,
|
||||
backdropPath: titles.backdropPath,
|
||||
backdropThumbHash: titles.backdropThumbHash,
|
||||
seasonNumber: seasons.seasonNumber,
|
||||
episodeNumber: episodes.episodeNumber,
|
||||
episodeName: episodes.name,
|
||||
@@ -348,6 +350,8 @@ export function getUpcomingMovies(userId: string, fromDate: string, toDate: stri
|
||||
titleName: titles.title,
|
||||
posterPath: titles.posterPath,
|
||||
posterThumbHash: titles.posterThumbHash,
|
||||
backdropPath: titles.backdropPath,
|
||||
backdropThumbHash: titles.backdropThumbHash,
|
||||
releaseDate: titles.releaseDate,
|
||||
userStatus: userTitleStatus.status,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user