mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-04-22 08:44:41 +01:00
Merge branch 'pr/238'
This commit is contained in:
@@ -2,19 +2,49 @@ import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
|
|||||||
import React, {useEffect, useMemo, useState} from "react";
|
import React, {useEffect, useMemo, useState} from "react";
|
||||||
import {Text} from "@/components/common/Text";
|
import {Text} from "@/components/common/Text";
|
||||||
import useDownloadHelper from "@/utils/download";
|
import useDownloadHelper from "@/utils/download";
|
||||||
|
import {useDownload} from "@/providers/DownloadProvider";
|
||||||
|
|
||||||
interface DownloadSizeProps {
|
interface DownloadSizeProps {
|
||||||
items: BaseItemDto[];
|
items: BaseItemDto[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DownloadSizes {
|
||||||
|
knownSize: number;
|
||||||
|
itemsNeedingSize: BaseItemDto[];
|
||||||
|
}
|
||||||
|
|
||||||
export const DownloadSize: React.FC<DownloadSizeProps> = ({ items }) => {
|
export const DownloadSize: React.FC<DownloadSizeProps> = ({ items }) => {
|
||||||
|
const { downloadedFiles, saveDownloadedItemInfo } = useDownload();
|
||||||
const { getDownloadSize } = useDownloadHelper();
|
const { getDownloadSize } = useDownloadHelper();
|
||||||
const [size, setSize] = useState<string | undefined>();
|
const [size, setSize] = useState<string | undefined>();
|
||||||
|
|
||||||
|
const itemIds = useMemo(() => items.map(i => i.Id), [items])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getDownloadSize(...items).then(setSize)
|
if (!downloadedFiles)
|
||||||
|
return
|
||||||
|
|
||||||
|
const {knownSize, itemsNeedingSize} = downloadedFiles
|
||||||
|
.filter(f => itemIds.includes(f.item.Id))
|
||||||
|
?.reduce<DownloadSizes>((acc, file) => {
|
||||||
|
if (file?.size && file.size > 0)
|
||||||
|
acc.knownSize += file.size
|
||||||
|
else
|
||||||
|
acc.itemsNeedingSize.push(file.item)
|
||||||
|
return acc
|
||||||
|
}, {
|
||||||
|
knownSize: 0,
|
||||||
|
itemsNeedingSize: []
|
||||||
|
})
|
||||||
|
|
||||||
|
getDownloadSize(
|
||||||
|
(item, size) => saveDownloadedItemInfo(item, size),
|
||||||
|
...itemsNeedingSize
|
||||||
|
).then(sizeSum => {
|
||||||
|
setSize(bytesToReadable((sizeSum + knownSize)))
|
||||||
|
})
|
||||||
},
|
},
|
||||||
[items]
|
[items, itemIds]
|
||||||
);
|
);
|
||||||
|
|
||||||
const sizeText = useMemo(() => {
|
const sizeText = useMemo(() => {
|
||||||
@@ -23,6 +53,14 @@ export const DownloadSize: React.FC<DownloadSizeProps> = ({ items }) => {
|
|||||||
return size
|
return size
|
||||||
}, [size])
|
}, [size])
|
||||||
|
|
||||||
|
const bytesToReadable = (bytes: number) => {
|
||||||
|
const gb = bytes / 1e+9;
|
||||||
|
|
||||||
|
if (gb >= 1)
|
||||||
|
return `${gb.toFixed(2)} GB`
|
||||||
|
return `${(bytes / 1024 / 1024).toFixed(2)} MB`
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Text className="text-xs text-neutral-500">{sizeText}</Text>
|
<Text className="text-xs text-neutral-500">{sizeText}</Text>
|
||||||
|
|||||||
@@ -128,7 +128,8 @@ export const useRemuxHlsToMp4 = () => {
|
|||||||
}s`
|
}s`
|
||||||
);
|
);
|
||||||
if (!item) throw new Error("Item is undefined");
|
if (!item) throw new Error("Item is undefined");
|
||||||
await saveDownloadedItemInfo(item);
|
const stat = await session.getLastReceivedStatistics();
|
||||||
|
await saveDownloadedItemInfo(item, stat.getSize());
|
||||||
toast.success("Download completed");
|
toast.success("Download completed");
|
||||||
await queryClient.invalidateQueries({
|
await queryClient.invalidateQueries({
|
||||||
queryKey: ["downloadedItems"],
|
queryKey: ["downloadedItems"],
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import useDownloadHelper from "@/utils/download";
|
|||||||
export type DownloadedItem = {
|
export type DownloadedItem = {
|
||||||
item: Partial<BaseItemDto>;
|
item: Partial<BaseItemDto>;
|
||||||
mediaSource: MediaSourceInfo;
|
mediaSource: MediaSourceInfo;
|
||||||
|
size: number | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
function onAppStateChange(status: AppStateStatus) {
|
function onAppStateChange(status: AppStateStatus) {
|
||||||
@@ -260,8 +261,8 @@ function useDownloadProvider() {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.done(async () => {
|
.done(async (doneHandler) => {
|
||||||
await saveDownloadedItemInfo(process.item);
|
await saveDownloadedItemInfo(process.item, doneHandler.bytesDownloaded);
|
||||||
toast.success(`Download completed for ${process.item.Name}`, {
|
toast.success(`Download completed for ${process.item.Name}`, {
|
||||||
duration: 3000,
|
duration: 3000,
|
||||||
action: {
|
action: {
|
||||||
@@ -522,7 +523,7 @@ function useDownloadProvider() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveDownloadedItemInfo(item: BaseItemDto) {
|
function saveDownloadedItemInfo(item: BaseItemDto, size: number = 0) {
|
||||||
try {
|
try {
|
||||||
const downloadedItems = storage.getString("downloadedItems");
|
const downloadedItems = storage.getString("downloadedItems");
|
||||||
let items: DownloadedItem[] = downloadedItems
|
let items: DownloadedItem[] = downloadedItems
|
||||||
@@ -538,7 +539,7 @@ function useDownloadProvider() {
|
|||||||
"Media source not found in tmp storage. Did you forget to save it before starting download?"
|
"Media source not found in tmp storage. Did you forget to save it before starting download?"
|
||||||
);
|
);
|
||||||
|
|
||||||
const newItem = { item, mediaSource: data.mediaSource };
|
const newItem = { item, size, mediaSource: data.mediaSource };
|
||||||
|
|
||||||
if (existingItemIndex !== -1) {
|
if (existingItemIndex !== -1) {
|
||||||
items[existingItemIndex] = newItem;
|
items[existingItemIndex] = newItem;
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import {apiAtom} from "@/providers/JellyfinProvider";
|
|||||||
import {useAtom} from "jotai";
|
import {useAtom} from "jotai";
|
||||||
import {storage} from "@/utils/mmkv";
|
import {storage} from "@/utils/mmkv";
|
||||||
import {getDownloadedFileUrl} from "@/hooks/useDownloadedFileOpener";
|
import {getDownloadedFileUrl} from "@/hooks/useDownloadedFileOpener";
|
||||||
import * as FileSystem from 'expo-file-system'
|
import * as FileSystem from 'expo-file-system';
|
||||||
import {FileInfo} from "expo-file-system";
|
import {FileInfo} from "expo-file-system";
|
||||||
|
|
||||||
|
|
||||||
const useDownloadHelper = () => {
|
const useDownloadHelper = () => {
|
||||||
const [api] = useAtom(apiAtom);
|
const [api] = useAtom(apiAtom);
|
||||||
const {saveImage} = useImageStorage();
|
const {saveImage} = useImageStorage();
|
||||||
@@ -18,7 +19,10 @@ const useDownloadHelper = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getDownloadSize = async (...items: BaseItemDto[]) => {
|
const getDownloadSize = async (
|
||||||
|
onNewItemSizeFetched: (item: BaseItemDto, size: number) => void,
|
||||||
|
...items: BaseItemDto[]
|
||||||
|
) => {
|
||||||
const sizes: number[] = [];
|
const sizes: number[] = [];
|
||||||
|
|
||||||
await Promise.all(items.map(item => {
|
await Promise.all(items.map(item => {
|
||||||
@@ -26,18 +30,17 @@ const useDownloadHelper = () => {
|
|||||||
const url = await getDownloadedFileUrl(item.Id!);
|
const url = await getDownloadedFileUrl(item.Id!);
|
||||||
if (url) {
|
if (url) {
|
||||||
const fileInfo: FileInfo = await FileSystem.getInfoAsync(url);
|
const fileInfo: FileInfo = await FileSystem.getInfoAsync(url);
|
||||||
sizes.push(fileInfo.size);
|
if (fileInfo.exists) {
|
||||||
resolve(sizes);
|
onNewItemSizeFetched(item, fileInfo.size)
|
||||||
} else reject();
|
sizes.push(fileInfo.size);
|
||||||
|
resolve(sizes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reject();
|
||||||
})
|
})
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const size = sizes.reduce((sum, size) => sum + size, 0);
|
return sizes.reduce((sum, size) => sum + size, 0);
|
||||||
const gb = size / 1e+9;
|
|
||||||
|
|
||||||
if (gb >= 1)
|
|
||||||
return `${gb.toFixed(2)} GB`;
|
|
||||||
return `${(size / 1024 / 1024).toFixed(2)} MB`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { saveSeriesPrimaryImage, getDownloadSize }
|
return { saveSeriesPrimaryImage, getDownloadSize }
|
||||||
|
|||||||
Reference in New Issue
Block a user