From 62fc6f9a70dc0eb3f570d9be6090fd6e75cc8186 Mon Sep 17 00:00:00 2001 From: Alex <111128610+Alexk2309@users.noreply.github.com> Date: Sun, 31 May 2026 22:12:13 +1000 Subject: [PATCH 1/3] fix(progress-bar): Fix progress bar not reporting watch times (#1611) Co-authored-by: Gauvain --- components/common/ProgressBar.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/components/common/ProgressBar.tsx b/components/common/ProgressBar.tsx index 23ff1249a..9c754cdc8 100644 --- a/components/common/ProgressBar.tsx +++ b/components/common/ProgressBar.tsx @@ -37,11 +37,12 @@ export const ProgressBar: React.FC = ({ item }) => { } /> ); From c981f59a50e91d57028e42cb0816f773ff7805f0 Mon Sep 17 00:00:00 2001 From: Fredrik Burmester Date: Sun, 31 May 2026 14:58:23 +0200 Subject: [PATCH 2/3] fix(downloads): repair bottom sheets on iOS and restore downloads delete sheet Bump @gorhom/bottom-sheet 5.2.8 -> 5.2.14, which fixes BottomSheetModal present() silently no-opping under Reanimated 4 / New Architecture (SDK 56). Affected every sheet app-wide: present() was called with a valid ref but nothing rendered (not even the backdrop). Verified on the iOS simulator that the download options sheet now opens. Also restore the downloads-page delete sheet (delete movies/series/other/all) that was accidentally dropped in the Expo 54 rewrite (#1174), which left an orphaned trigger button and underscore-silenced handlers. --- app/(auth)/(tabs)/(home)/downloads/index.tsx | 55 ++++++++++++++++++-- bun.lock | 4 +- package.json | 2 +- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/app/(auth)/(tabs)/(home)/downloads/index.tsx b/app/(auth)/(tabs)/(home)/downloads/index.tsx index 884b1fbb2..da4a8272c 100644 --- a/app/(auth)/(tabs)/(home)/downloads/index.tsx +++ b/app/(auth)/(tabs)/(home)/downloads/index.tsx @@ -1,4 +1,9 @@ -import { BottomSheetModal } from "@gorhom/bottom-sheet"; +import { + BottomSheetBackdrop, + type BottomSheetBackdropProps, + BottomSheetModal, + BottomSheetView, +} from "@gorhom/bottom-sheet"; import { useNavigation } from "expo-router"; import { useAtom } from "jotai"; import { useEffect, useMemo, useRef, useState } from "react"; @@ -7,6 +12,7 @@ import { Alert, Platform, ScrollView, View } from "react-native"; import { Pressable } from "react-native-gesture-handler"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { toast } from "sonner-native"; +import { Button } from "@/components/Button"; import { Text } from "@/components/common/Text"; import { TouchableItemRouter } from "@/components/common/TouchableItemRouter"; import ActiveDownloads from "@/components/downloads/ActiveDownloads"; @@ -101,7 +107,7 @@ export default function DownloadsPage() { navigation.setOptions({ headerRight: () => ( bottomSheetModalRef.current?.present()} className='px-2' > f.item) || []} /> @@ -116,7 +122,7 @@ export default function DownloadsPage() { } }, [showMigration]); - const _deleteMovies = () => + const deleteMovies = () => deleteFileByType("Movie") .then(() => toast.success( @@ -127,7 +133,7 @@ export default function DownloadsPage() { writeToLog("ERROR", reason); toast.error(t("home.downloads.toasts.failed_to_delete_all_movies")); }); - const _deleteShows = () => + const deleteShows = () => deleteFileByType("Episode") .then(() => toast.success( @@ -138,7 +144,7 @@ export default function DownloadsPage() { writeToLog("ERROR", reason); toast.error(t("home.downloads.toasts.failed_to_delete_all_tvseries")); }); - const _deleteOtherMedia = () => + const deleteOtherMedia = () => Promise.all( otherMedia .filter((item) => item.item.Type) @@ -162,6 +168,9 @@ export default function DownloadsPage() { ), ); + const deleteAllMedia = async () => + await Promise.all([deleteMovies(), deleteShows(), deleteOtherMedia()]); + return ( + ( + + )} + > + + + + + {otherMedia.length > 0 && ( + + )} + + + + ); } diff --git a/bun.lock b/bun.lock index 70f387822..cf5844776 100644 --- a/bun.lock +++ b/bun.lock @@ -11,7 +11,7 @@ "@expo/react-native-action-sheet": "^4.1.1", "@expo/ui": "~56.0.14", "@expo/vector-icons": "^15.0.3", - "@gorhom/bottom-sheet": "5.2.8", + "@gorhom/bottom-sheet": "5.2.14", "@jellyfin/sdk": "^0.13.0", "@react-native-community/netinfo": "^12.0.0", "@react-navigation/material-top-tabs": "7.4.28", @@ -365,7 +365,7 @@ "@expo/xcpretty": ["@expo/xcpretty@4.4.4", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "chalk": "^4.1.0", "js-yaml": "^4.1.0" }, "bin": { "excpretty": "build/cli.js" } }, "sha512-4aQzz9vgxcNXFfo/iyNgDDYfsU5XGKKxWxZopw0cVotHiW+U8IJbIxMaxsINs6bHhtkG3StKNPcOrn3eBuxKPw=="], - "@gorhom/bottom-sheet": ["@gorhom/bottom-sheet@5.2.8", "", { "dependencies": { "@gorhom/portal": "1.0.14", "invariant": "^2.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-native": "*", "react": "*", "react-native": "*", "react-native-gesture-handler": ">=2.16.1", "react-native-reanimated": ">=3.16.0 || >=4.0.0-" }, "optionalPeers": ["@types/react", "@types/react-native"] }, "sha512-+N27SMpbBxXZQ/IA2nlEV6RGxL/qSFHKfdFKcygvW+HqPG5jVNb1OqehLQsGfBP+Up42i0gW5ppI+DhpB7UCzA=="], + "@gorhom/bottom-sheet": ["@gorhom/bottom-sheet@5.2.14", "", { "dependencies": { "@gorhom/portal": "1.0.14", "invariant": "^2.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-native": "*", "react": "*", "react-native": "*", "react-native-gesture-handler": ">=2.16.1", "react-native-reanimated": ">=3.16.0 || >=4.0.0-" }, "optionalPeers": ["@types/react", "@types/react-native"] }, "sha512-uLQFlDjp9z+jrOFcMSEldPqL5JdaXL3vXOh+juhwoNvXgTsEorJLjHTugXu+YccAG/0KJnShzKCrb71MHBsvJg=="], "@gorhom/portal": ["@gorhom/portal@1.0.14", "", { "dependencies": { "nanoid": "^3.3.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A=="], diff --git a/package.json b/package.json index 8bc2b3c64..ccabd2f47 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "@expo/react-native-action-sheet": "^4.1.1", "@expo/ui": "~56.0.14", "@expo/vector-icons": "^15.0.3", - "@gorhom/bottom-sheet": "5.2.8", + "@gorhom/bottom-sheet": "5.2.14", "@jellyfin/sdk": "^0.13.0", "@react-native-community/netinfo": "^12.0.0", "@react-navigation/material-top-tabs": "7.4.28", From 52e6f562207db74cf3f6d7c6fe29c730f89d9403 Mon Sep 17 00:00:00 2001 From: Alex <111128610+Alexk2309@users.noreply.github.com> Date: Mon, 1 Jun 2026 05:52:41 +1000 Subject: [PATCH 3/3] fix(auth): clear stored user on logout to prevent empty home on relaunch (#1622) --- providers/JellyfinProvider.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/providers/JellyfinProvider.tsx b/providers/JellyfinProvider.tsx index e6f9853ae..8608222b8 100644 --- a/providers/JellyfinProvider.tsx +++ b/providers/JellyfinProvider.tsx @@ -69,6 +69,13 @@ const initialApi = (() => { const initialUser = (() => { try { + // Only return a stored user if we also have a token. Otherwise the + // user atom would be populated while the api atom is null (e.g. after + // a logout that left stale user JSON in storage), which causes + // useProtectedRoute to keep us inside the (auth) group instead of + // redirecting to /login. + const token = storage.getString("token"); + if (!token) return null; const userStr = storage.getString("user"); if (userStr) { return JSON.parse(userStr) as UserDto; @@ -402,6 +409,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({ ); storage.remove("token"); + storage.remove("user"); clearTVDiscoverySafely(); setUser(null); setApi(null);