Merge branch 'pr/238'

This commit is contained in:
Fredrik Burmester
2024-12-02 11:35:22 +01:00
4 changed files with 61 additions and 18 deletions

View File

@@ -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>

View File

@@ -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"],

View File

@@ -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;

View File

@@ -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 }