mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-03-18 23:36:22 +00:00
refactor: Feature/offline mode rework (#859)
Co-authored-by: lostb1t <coding-mosses0z@icloud.com> Co-authored-by: Fredrik Burmester <fredrik.burmester@gmail.com> Co-authored-by: Gauvain <68083474+Gauvino@users.noreply.github.com> Co-authored-by: Gauvino <uruknarb20@gmail.com> Co-authored-by: storm1er <le.storm1er@gmail.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Chris <182387676+whoopsi-daisy@users.noreply.github.com> Co-authored-by: arch-fan <55891793+arch-fan@users.noreply.github.com> Co-authored-by: Alex Kim <alexkim@Alexs-MacBook-Pro.local>
This commit is contained in:
@@ -1,34 +1,17 @@
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { useRouter } from "expo-router";
|
||||
import { useMemo } from "react";
|
||||
import { Platform, Switch, TouchableOpacity } from "react-native";
|
||||
import { Stepper } from "@/components/inputs/Stepper";
|
||||
import { useDownload } from "@/providers/DownloadProvider";
|
||||
import {
|
||||
DownloadMethod,
|
||||
type Settings,
|
||||
useSettings,
|
||||
} from "@/utils/atoms/settings";
|
||||
|
||||
const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Stepper } from "@/components/inputs/Stepper";
|
||||
import DisabledSetting from "@/components/settings/DisabledSetting";
|
||||
import { Text } from "../common/Text";
|
||||
import { type Settings, useSettings } from "@/utils/atoms/settings";
|
||||
import { ListGroup } from "../list/ListGroup";
|
||||
import { ListItem } from "../list/ListItem";
|
||||
|
||||
export default function DownloadSettings({ ...props }) {
|
||||
const [settings, updateSettings, pluginSettings] = useSettings();
|
||||
const { setProcesses } = useDownload();
|
||||
const router = useRouter();
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const allDisabled = useMemo(
|
||||
() =>
|
||||
pluginSettings?.downloadMethod?.locked === true &&
|
||||
pluginSettings?.remuxConcurrentLimit?.locked === true &&
|
||||
pluginSettings?.autoDownload.locked === true,
|
||||
[pluginSettings],
|
||||
@@ -39,70 +22,9 @@ export default function DownloadSettings({ ...props }) {
|
||||
return (
|
||||
<DisabledSetting disabled={allDisabled} {...props} className='mb-4'>
|
||||
<ListGroup title={t("home.settings.downloads.downloads_title")}>
|
||||
<ListItem
|
||||
title={t("home.settings.downloads.download_method")}
|
||||
disabled={pluginSettings?.downloadMethod?.locked}
|
||||
>
|
||||
<DropdownMenu.Root>
|
||||
<DropdownMenu.Trigger>
|
||||
<TouchableOpacity className='flex flex-row items-center justify-between py-3 pl-3'>
|
||||
<Text className='mr-1 text-[#8E8D91]'>
|
||||
{settings.downloadMethod === DownloadMethod.Remux
|
||||
? t("home.settings.downloads.default")
|
||||
: t("home.settings.downloads.optimized")}
|
||||
</Text>
|
||||
<Ionicons
|
||||
name='chevron-expand-sharp'
|
||||
size={18}
|
||||
color='#5A5960'
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content
|
||||
loop={true}
|
||||
side='bottom'
|
||||
align='start'
|
||||
alignOffset={0}
|
||||
avoidCollisions={true}
|
||||
collisionPadding={8}
|
||||
sideOffset={8}
|
||||
>
|
||||
<DropdownMenu.Label>
|
||||
{t("home.settings.downloads.download_method")}
|
||||
</DropdownMenu.Label>
|
||||
<DropdownMenu.Item
|
||||
key='1'
|
||||
onSelect={() => {
|
||||
updateSettings({ downloadMethod: DownloadMethod.Remux });
|
||||
setProcesses([]);
|
||||
}}
|
||||
>
|
||||
<DropdownMenu.ItemTitle>
|
||||
{t("home.settings.downloads.default")}
|
||||
</DropdownMenu.ItemTitle>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Item
|
||||
key='2'
|
||||
onSelect={() => {
|
||||
updateSettings({ downloadMethod: DownloadMethod.Optimized });
|
||||
setProcesses([]);
|
||||
queryClient.invalidateQueries({ queryKey: ["search"] });
|
||||
}}
|
||||
>
|
||||
<DropdownMenu.ItemTitle>
|
||||
{t("home.settings.downloads.optimized")}
|
||||
</DropdownMenu.ItemTitle>
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
</ListItem>
|
||||
|
||||
<ListItem
|
||||
title={t("home.settings.downloads.remux_max_download")}
|
||||
disabled={
|
||||
pluginSettings?.remuxConcurrentLimit?.locked ||
|
||||
settings.downloadMethod !== DownloadMethod.Remux
|
||||
}
|
||||
disabled={pluginSettings?.remuxConcurrentLimit?.locked}
|
||||
>
|
||||
<Stepper
|
||||
value={settings.remuxConcurrentLimit}
|
||||
@@ -116,33 +38,6 @@ export default function DownloadSettings({ ...props }) {
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem
|
||||
title={t("home.settings.downloads.auto_download")}
|
||||
disabled={
|
||||
pluginSettings?.autoDownload?.locked ||
|
||||
settings.downloadMethod !== DownloadMethod.Optimized
|
||||
}
|
||||
>
|
||||
<Switch
|
||||
disabled={
|
||||
pluginSettings?.autoDownload?.locked ||
|
||||
settings.downloadMethod !== DownloadMethod.Optimized
|
||||
}
|
||||
value={settings.autoDownload}
|
||||
onValueChange={(value) => updateSettings({ autoDownload: value })}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem
|
||||
disabled={
|
||||
pluginSettings?.optimizedVersionsServerUrl?.locked ||
|
||||
settings.downloadMethod !== DownloadMethod.Optimized
|
||||
}
|
||||
onPress={() => router.push("/settings/optimized-server/page")}
|
||||
showArrow
|
||||
title={t("home.settings.downloads.optimized_versions_server")}
|
||||
/>
|
||||
</ListGroup>
|
||||
</DisabledSetting>
|
||||
);
|
||||
|
||||
@@ -82,6 +82,17 @@ export const HomeIndex = () => {
|
||||
const scrollViewRef = useRef<ScrollView>(null);
|
||||
|
||||
const { downloadedFiles, cleanCacheDirectory } = useDownload();
|
||||
const prevIsConnected = useRef<boolean | null>(false);
|
||||
const invalidateCache = useInvalidatePlaybackProgressCache();
|
||||
useEffect(() => {
|
||||
// Only invalidate cache when transitioning from offline to online
|
||||
if (isConnected && !prevIsConnected.current) {
|
||||
invalidateCache();
|
||||
}
|
||||
// Update the ref to the current state for the next render
|
||||
prevIsConnected.current = isConnected;
|
||||
}, [isConnected, invalidateCache]);
|
||||
|
||||
useEffect(() => {
|
||||
if (Platform.isTV) {
|
||||
navigation.setOptions({
|
||||
@@ -144,10 +155,6 @@ export const HomeIndex = () => {
|
||||
setIsConnected(state.isConnected);
|
||||
});
|
||||
|
||||
// cleanCacheDirectory().catch((e) =>
|
||||
// console.error("Something went wrong cleaning cache directory")
|
||||
// );
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
@@ -188,8 +195,6 @@ export const HomeIndex = () => {
|
||||
);
|
||||
}, [userViews]);
|
||||
|
||||
const invalidateCache = useInvalidatePlaybackProgressCache();
|
||||
|
||||
const refetch = async () => {
|
||||
setLoading(true);
|
||||
await refreshStreamyfinPluginSettings();
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Linking, TextInput, View } from "react-native";
|
||||
import { Text } from "../common/Text";
|
||||
|
||||
interface Props {
|
||||
value: string;
|
||||
onChangeValue: (value: string) => void;
|
||||
}
|
||||
|
||||
export const OptimizedServerForm: React.FC<Props> = ({
|
||||
value,
|
||||
onChangeValue,
|
||||
}) => {
|
||||
const handleOpenLink = () => {
|
||||
Linking.openURL("https://github.com/streamyfin/optimized-versions-server");
|
||||
};
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<View>
|
||||
<View className='flex flex-col rounded-xl overflow-hidden pl-4 bg-neutral-900 px-4'>
|
||||
<View className={"flex flex-row items-center bg-neutral-900 h-11 pr-4"}>
|
||||
<Text className='mr-4'>{t("home.settings.downloads.url")}</Text>
|
||||
<TextInput
|
||||
className='text-white'
|
||||
placeholder={t("home.settings.downloads.server_url_placeholder")}
|
||||
value={value}
|
||||
keyboardType='url'
|
||||
returnKeyType='done'
|
||||
autoCapitalize='none'
|
||||
textContentType='URL'
|
||||
onChangeText={(text) => onChangeValue(text)}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<Text className='px-4 text-xs text-neutral-500 mt-1'>
|
||||
{t("home.settings.downloads.optimized_version_hint")}{" "}
|
||||
<Text className='text-blue-500' onPress={handleOpenLink}>
|
||||
{t("home.settings.downloads.read_more_about_optimized_server")}
|
||||
</Text>
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -17,9 +17,9 @@ export const StorageSettings = () => {
|
||||
const errorHapticFeedback = useHaptic("error");
|
||||
|
||||
const { data: size } = useQuery({
|
||||
queryKey: ["appSize", appSizeUsage],
|
||||
queryKey: ["appSize"],
|
||||
queryFn: async () => {
|
||||
const app = await appSizeUsage;
|
||||
const app = await appSizeUsage();
|
||||
|
||||
const remaining = await FileSystem.getFreeDiskStorageAsync();
|
||||
const total = await FileSystem.getTotalDiskCapacityAsync();
|
||||
@@ -58,7 +58,7 @@ export const StorageSettings = () => {
|
||||
</View>
|
||||
<View className='h-3 w-full bg-gray-100/10 rounded-md overflow-hidden flex flex-row'>
|
||||
{size && (
|
||||
<>
|
||||
<View className='flex flex-row'>
|
||||
<View
|
||||
style={{
|
||||
width: `${(size.app / size.total) * 100}%`,
|
||||
@@ -67,19 +67,16 @@ export const StorageSettings = () => {
|
||||
/>
|
||||
<View
|
||||
style={{
|
||||
width: `${
|
||||
((size.total - size.remaining - size.app) / size.total) *
|
||||
100
|
||||
}%`,
|
||||
width: `${((size.total - size.remaining - size.app) / size.total) * 100}%`,
|
||||
backgroundColor: Colors.primaryLightRGB,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<View className='flex flex-row gap-x-2'>
|
||||
{size && (
|
||||
<>
|
||||
<View className='flex flex-row gap-x-2'>
|
||||
<View className='flex flex-row items-center'>
|
||||
<View className='w-3 h-3 rounded-full bg-purple-600 mr-1' />
|
||||
<Text className='text-white text-xs'>
|
||||
@@ -99,7 +96,7 @@ export const StorageSettings = () => {
|
||||
})}
|
||||
</Text>
|
||||
</View>
|
||||
</>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user