mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-06-01 03:28:27 +01:00
Merge branch 'develop' into fix/qr-code-scanning-ios
This commit is contained in:
@@ -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: () => (
|
||||
<Pressable
|
||||
onPress={bottomSheetModalRef.current?.present}
|
||||
onPress={() => bottomSheetModalRef.current?.present()}
|
||||
className='px-2'
|
||||
>
|
||||
<DownloadSize items={downloadedFiles?.map((f) => 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 (
|
||||
<OfflineModeProvider isOffline={true}>
|
||||
<ScrollView
|
||||
@@ -256,6 +265,42 @@ export default function DownloadsPage() {
|
||||
)}
|
||||
</View>
|
||||
</ScrollView>
|
||||
<BottomSheetModal
|
||||
ref={bottomSheetModalRef}
|
||||
enableDynamicSizing
|
||||
handleIndicatorStyle={{
|
||||
backgroundColor: "white",
|
||||
}}
|
||||
backgroundStyle={{
|
||||
backgroundColor: "#171717",
|
||||
}}
|
||||
backdropComponent={(props: BottomSheetBackdropProps) => (
|
||||
<BottomSheetBackdrop
|
||||
{...props}
|
||||
disappearsOnIndex={-1}
|
||||
appearsOnIndex={0}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
<BottomSheetView>
|
||||
<View className='p-4 space-y-4 mb-4'>
|
||||
<Button color='purple' onPress={deleteMovies}>
|
||||
{t("home.downloads.delete_all_movies_button")}
|
||||
</Button>
|
||||
<Button color='purple' onPress={deleteShows}>
|
||||
{t("home.downloads.delete_all_tvseries_button")}
|
||||
</Button>
|
||||
{otherMedia.length > 0 && (
|
||||
<Button color='purple' onPress={deleteOtherMedia}>
|
||||
{t("home.downloads.delete_all_other_media_button")}
|
||||
</Button>
|
||||
)}
|
||||
<Button color='red' onPress={deleteAllMedia}>
|
||||
{t("home.downloads.delete_all_button")}
|
||||
</Button>
|
||||
</View>
|
||||
</BottomSheetView>
|
||||
</BottomSheetModal>
|
||||
</OfflineModeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
4
bun.lock
4
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=="],
|
||||
|
||||
|
||||
@@ -37,11 +37,12 @@ export const ProgressBar: React.FC<ProgressBarProps> = ({ item }) => {
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={{
|
||||
width: `${progress}%`,
|
||||
backgroundColor: Platform.isTV ? "#ffffff" : undefined,
|
||||
}}
|
||||
className={`absolute bottom-0 left-0 h-1 w-full ${Platform.isTV ? "" : "bg-purple-600"}`}
|
||||
style={
|
||||
Platform.isTV
|
||||
? { width: `${progress}%`, backgroundColor: "#ffffff" }
|
||||
: { width: `${progress}%` }
|
||||
}
|
||||
className={`absolute bottom-0 left-0 h-1 ${Platform.isTV ? "" : "bg-purple-600"}`}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user