mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-03-20 16:26:24 +00:00
WIP
This commit is contained in:
@@ -13,7 +13,7 @@ import { orientationAtom } from "@/utils/atoms/orientation";
|
||||
import { Settings, useSettings } from "@/utils/atoms/settings";
|
||||
import { BACKGROUND_FETCH_TASK } from "@/utils/background-tasks";
|
||||
import { LogProvider, writeToLog } from "@/utils/log";
|
||||
import { storage } from "@/utils/mmkv";
|
||||
import { formatItemName, storage } from "@/utils/mmkv";
|
||||
import { cancelJobById, getAllJobsByDeviceId } from "@/utils/optimize-server";
|
||||
import { ActionSheetProvider } from "@expo/react-native-action-sheet";
|
||||
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
|
||||
@@ -385,18 +385,15 @@ function Layout() {
|
||||
function saveDownloadedItemInfo(item: BaseItemDto) {
|
||||
try {
|
||||
const downloadedItems = storage.getString("downloadedItems");
|
||||
let items: BaseItemDto[] = downloadedItems
|
||||
let items: { [key: string]: BaseItemDto } = downloadedItems
|
||||
? JSON.parse(downloadedItems)
|
||||
: [];
|
||||
: {};
|
||||
|
||||
const existingItemIndex = items.findIndex((i) => i.Id === item.Id);
|
||||
if (existingItemIndex !== -1) {
|
||||
items[existingItemIndex] = item;
|
||||
} else {
|
||||
items.push(item);
|
||||
if (item.Id) {
|
||||
item.Path = `${FileSystem.documentDirectory}${formatItemName(item)}.mp4`;
|
||||
items[item.Id] = item;
|
||||
storage.set("downloadedItems", JSON.stringify(items));
|
||||
}
|
||||
|
||||
storage.set("downloadedItems", JSON.stringify(items));
|
||||
} catch (error) {
|
||||
writeToLog("ERROR", "Failed to save downloaded item information:", error);
|
||||
console.error("Failed to save downloaded item information:", error);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { usePlaySettings } from "@/providers/PlaySettingsProvider";
|
||||
import { writeToLog } from "@/utils/log";
|
||||
import { getFilePathFromItemId } from "@/utils/mmkv";
|
||||
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
import { useRouter } from "expo-router";
|
||||
@@ -17,13 +18,13 @@ export const getDownloadedFileUrl = async (itemId: string): Promise<string> => {
|
||||
}
|
||||
|
||||
const files = await FileSystem.readDirectoryAsync(directory);
|
||||
const path = itemId!;
|
||||
const matchingFile = files.find((file) => file.startsWith(path));
|
||||
const filePath = getFilePathFromItemId(itemId);
|
||||
|
||||
const matchingFile = files.find((file) => file === filePath);
|
||||
|
||||
if (!matchingFile) {
|
||||
throw new Error(`No file found for item ${path}`);
|
||||
throw new Error(`No file found for item ${filePath}`);
|
||||
}
|
||||
|
||||
return `${directory}${matchingFile}`;
|
||||
};
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import useDownloadHelper from "@/utils/download";
|
||||
import { Api } from "@jellyfin/sdk";
|
||||
import { useSettings } from "@/utils/atoms/settings";
|
||||
import { JobStatus } from "@/utils/optimize-server";
|
||||
import { formatItemName } from "@/utils/mmkv";
|
||||
|
||||
const createFFmpegCommand = (url: string, output: string) => [
|
||||
"-y", // overwrite output files without asking
|
||||
@@ -53,7 +54,12 @@ export const useRemuxHlsToMp4 = () => {
|
||||
const [settings] = useSettings();
|
||||
const { saveImage } = useImageStorage();
|
||||
const { saveSeriesPrimaryImage } = useDownloadHelper();
|
||||
const { saveDownloadedItemInfo, setProcesses, processes, APP_CACHE_DOWNLOAD_DIRECTORY } = useDownload();
|
||||
const {
|
||||
saveDownloadedItemInfo,
|
||||
setProcesses,
|
||||
processes,
|
||||
APP_CACHE_DOWNLOAD_DIRECTORY,
|
||||
} = useDownload();
|
||||
|
||||
const onSaveAssets = async (api: Api, item: BaseItemDto) => {
|
||||
await saveSeriesPrimaryImage(item);
|
||||
@@ -73,13 +79,12 @@ export const useRemuxHlsToMp4 = () => {
|
||||
try {
|
||||
console.log("completeCallback");
|
||||
const returnCode = await session.getReturnCode();
|
||||
|
||||
if (returnCode.isValueSuccess()) {
|
||||
const stat = await session.getLastReceivedStatistics();
|
||||
await FileSystem.moveAsync({
|
||||
from: `${APP_CACHE_DOWNLOAD_DIRECTORY}${item.Id}.mp4`,
|
||||
to: `${FileSystem.documentDirectory}${item.Id}.mp4`
|
||||
})
|
||||
from: `${APP_CACHE_DOWNLOAD_DIRECTORY}${item.Id}.mp4`,
|
||||
to: `${FileSystem.documentDirectory}${formatItemName(item)}.mp4`,
|
||||
});
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: ["downloadedItems"],
|
||||
});
|
||||
@@ -131,12 +136,16 @@ export const useRemuxHlsToMp4 = () => {
|
||||
|
||||
const startRemuxing = useCallback(
|
||||
async (item: BaseItemDto, url: string, mediaSource: MediaSourceInfo) => {
|
||||
const cacheDir = await FileSystem.getInfoAsync(APP_CACHE_DOWNLOAD_DIRECTORY);
|
||||
const cacheDir = await FileSystem.getInfoAsync(
|
||||
APP_CACHE_DOWNLOAD_DIRECTORY
|
||||
);
|
||||
if (!cacheDir.exists) {
|
||||
await FileSystem.makeDirectoryAsync(APP_CACHE_DOWNLOAD_DIRECTORY, {intermediates: true})
|
||||
await FileSystem.makeDirectoryAsync(APP_CACHE_DOWNLOAD_DIRECTORY, {
|
||||
intermediates: true,
|
||||
});
|
||||
}
|
||||
|
||||
const output = APP_CACHE_DOWNLOAD_DIRECTORY + `${item.Id}.mp4`
|
||||
const output = APP_CACHE_DOWNLOAD_DIRECTORY + `${item.Id}.mp4`;
|
||||
|
||||
if (!api) throw new Error("API is not defined");
|
||||
if (!item.Id) throw new Error("Item must have an Id");
|
||||
|
||||
673
providers/DownloadItem.tsx
Normal file
673
providers/DownloadItem.tsx
Normal file
@@ -0,0 +1,673 @@
|
||||
/**
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* Do not edit the class manually.
|
||||
*
|
||||
* Jellyfin API
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { ExtraType } from "@jellyfin/sdk/lib/generated-client";
|
||||
|
||||
/**
|
||||
* This is strictly used as a data transfer object from the api layer. This holds information about a BaseItem in a format that is convenient for the client.
|
||||
* @export
|
||||
* @interface BaseItemDto
|
||||
*/
|
||||
export interface BaseItemDto {
|
||||
/**
|
||||
* Gets or sets the name.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Name?: string | null;
|
||||
/**
|
||||
* Gets or sets the id.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Id?: string;
|
||||
/**
|
||||
* Gets or sets the playlist item identifier.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
PlaylistItemId?: string | null;
|
||||
|
||||
/**
|
||||
*
|
||||
* @type {ExtraType}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ExtraType?: ExtraType;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Container?: string | null;
|
||||
/**
|
||||
* Gets or sets the name of the sort.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
SortName?: string | null;
|
||||
Path?: string | null;
|
||||
/**
|
||||
* Gets or sets the overview.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Overview?: string | null;
|
||||
/**
|
||||
* Gets or sets the cumulative run time ticks.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
CumulativeRunTimeTicks?: number | null;
|
||||
/**
|
||||
* Gets or sets the run time ticks.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
RunTimeTicks?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {PlayAccess}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
PlayAccess?: PlayAccess;
|
||||
/**
|
||||
* Gets or sets the aspect ratio.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
AspectRatio?: string | null;
|
||||
/**
|
||||
* Gets or sets the production year.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ProductionYear?: number | null;
|
||||
/**
|
||||
* Gets or sets a value indicating whether this instance is place holder.
|
||||
* @type {boolean}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
IsPlaceHolder?: boolean | null;
|
||||
/**
|
||||
* Gets or sets the number.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Number?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ChannelNumber?: string | null;
|
||||
/**
|
||||
* Gets or sets the index number.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
IndexNumber?: number | null;
|
||||
/**
|
||||
* Gets or sets the index number end.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
IndexNumberEnd?: number | null;
|
||||
/**
|
||||
* Gets or sets the parent index number.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ParentIndexNumber?: number | null;
|
||||
/**
|
||||
* Gets or sets the trailer urls.
|
||||
* @type {Array<MediaUrl>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
RemoteTrailers?: Array<MediaUrl> | null;
|
||||
/**
|
||||
* Gets or sets the provider ids.
|
||||
* @type {{ [key: string]: string | null; }}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ProviderIds?: {
|
||||
[key: string]: string | null;
|
||||
} | null;
|
||||
/**
|
||||
* Gets or sets a value indicating whether this instance is HD.
|
||||
* @type {boolean}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
IsHD?: boolean | null;
|
||||
/**
|
||||
* Gets or sets a value indicating whether this instance is folder.
|
||||
* @type {boolean}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
IsFolder?: boolean | null;
|
||||
/**
|
||||
* Gets or sets the parent id.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ParentId?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {BaseItemKind}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Type?: BaseItemKind;
|
||||
/**
|
||||
* Gets or sets the people.
|
||||
* @type {Array<BaseItemPerson>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
People?: Array<BaseItemPerson> | null;
|
||||
/**
|
||||
* Gets or sets the studios.
|
||||
* @type {Array<NameGuidPair>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Studios?: Array<NameGuidPair> | null;
|
||||
/**
|
||||
*
|
||||
* @type {Array<NameGuidPair>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
GenreItems?: Array<NameGuidPair> | null;
|
||||
/**
|
||||
* Gets or sets whether the item has a logo, this will hold the Id of the Parent that has one.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ParentLogoItemId?: string | null;
|
||||
/**
|
||||
* Gets or sets whether the item has any backdrops, this will hold the Id of the Parent that has one.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ParentBackdropItemId?: string | null;
|
||||
/**
|
||||
* Gets or sets the parent backdrop image tags.
|
||||
* @type {Array<string>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ParentBackdropImageTags?: Array<string> | null;
|
||||
/**
|
||||
* Gets or sets the local trailer count.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
LocalTrailerCount?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {UserItemDataDto}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
UserData?: UserItemDataDto;
|
||||
/**
|
||||
* Gets or sets the recursive item count.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
RecursiveItemCount?: number | null;
|
||||
/**
|
||||
* Gets or sets the child count.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ChildCount?: number | null;
|
||||
/**
|
||||
* Gets or sets the name of the series.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
SeriesName?: string | null;
|
||||
/**
|
||||
* Gets or sets the series id.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
SeriesId?: string | null;
|
||||
/**
|
||||
* Gets or sets the season identifier.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
SeasonId?: string | null;
|
||||
/**
|
||||
* Gets or sets the special feature count.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
SpecialFeatureCount?: number | null;
|
||||
/**
|
||||
* Gets or sets the display preferences id.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
DisplayPreferencesId?: string | null;
|
||||
/**
|
||||
* Gets or sets the status.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Status?: string | null;
|
||||
/**
|
||||
* Gets or sets the air time.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
AirTime?: string | null;
|
||||
/**
|
||||
* Gets or sets the air days.
|
||||
* @type {Array<DayOfWeek>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
AirDays?: Array<DayOfWeek> | null;
|
||||
/**
|
||||
* Gets or sets the tags.
|
||||
* @type {Array<string>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Tags?: Array<string> | null;
|
||||
/**
|
||||
* Gets or sets the primary image aspect ratio, after image enhancements.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
PrimaryImageAspectRatio?: number | null;
|
||||
/**
|
||||
* Gets or sets the artists.
|
||||
* @type {Array<string>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Artists?: Array<string> | null;
|
||||
/**
|
||||
* Gets or sets the artist items.
|
||||
* @type {Array<NameGuidPair>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ArtistItems?: Array<NameGuidPair> | null;
|
||||
/**
|
||||
* Gets or sets the album.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Album?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {CollectionType}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
CollectionType?: CollectionType;
|
||||
/**
|
||||
* Gets or sets the display order.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
DisplayOrder?: string | null;
|
||||
/**
|
||||
* Gets or sets the album id.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
AlbumId?: string | null;
|
||||
/**
|
||||
* Gets or sets the album image tag.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
AlbumPrimaryImageTag?: string | null;
|
||||
/**
|
||||
* Gets or sets the series primary image tag.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
SeriesPrimaryImageTag?: string | null;
|
||||
/**
|
||||
* Gets or sets the album artist.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
AlbumArtist?: string | null;
|
||||
/**
|
||||
* Gets or sets the album artists.
|
||||
* @type {Array<NameGuidPair>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
AlbumArtists?: Array<NameGuidPair> | null;
|
||||
/**
|
||||
* Gets or sets the name of the season.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
SeasonName?: string | null;
|
||||
/**
|
||||
* Gets or sets the media streams.
|
||||
* @type {Array<MediaStream>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
MediaStreams?: Array<MediaStream> | null;
|
||||
/**
|
||||
*
|
||||
* @type {VideoType}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
VideoType?: VideoType;
|
||||
/**
|
||||
* Gets or sets the part count.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
PartCount?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
MediaSourceCount?: number | null;
|
||||
/**
|
||||
* Gets or sets the image tags.
|
||||
* @type {{ [key: string]: string; }}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ImageTags?: {
|
||||
[key: string]: string;
|
||||
} | null;
|
||||
/**
|
||||
* Gets or sets the backdrop image tags.
|
||||
* @type {Array<string>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
BackdropImageTags?: Array<string> | null;
|
||||
/**
|
||||
* Gets or sets the screenshot image tags.
|
||||
* @type {Array<string>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ScreenshotImageTags?: Array<string> | null;
|
||||
/**
|
||||
* Gets or sets the parent logo image tag.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ParentLogoImageTag?: string | null;
|
||||
/**
|
||||
* Gets or sets whether the item has fan art, this will hold the Id of the Parent that has one.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ParentArtItemId?: string | null;
|
||||
/**
|
||||
* Gets or sets the parent art image tag.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ParentArtImageTag?: string | null;
|
||||
/**
|
||||
* Gets or sets the series thumb image tag.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
SeriesThumbImageTag?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {BaseItemDtoImageBlurHashes}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ImageBlurHashes?: BaseItemDtoImageBlurHashes | null;
|
||||
/**
|
||||
* Gets or sets the series studio.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
SeriesStudio?: string | null;
|
||||
/**
|
||||
* Gets or sets the parent thumb item id.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ParentThumbItemId?: string | null;
|
||||
/**
|
||||
* Gets or sets the parent thumb image tag.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ParentThumbImageTag?: string | null;
|
||||
/**
|
||||
* Gets or sets the parent primary image item identifier.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ParentPrimaryImageItemId?: string | null;
|
||||
/**
|
||||
* Gets or sets the parent primary image tag.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ParentPrimaryImageTag?: string | null;
|
||||
/**
|
||||
* Gets or sets the chapters.
|
||||
* @type {Array<ChapterInfo>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Chapters?: Array<ChapterInfo> | null;
|
||||
/**
|
||||
* Gets or sets the trickplay manifest.
|
||||
* @type {{ [key: string]: { [key: string]: TrickplayInfo; }; }}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Trickplay?: {
|
||||
[key: string]: {
|
||||
[key: string]: TrickplayInfo;
|
||||
};
|
||||
} | null;
|
||||
/**
|
||||
*
|
||||
* @type {LocationType}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
LocationType?: LocationType;
|
||||
/**
|
||||
*
|
||||
* @type {IsoType}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
IsoType?: IsoType;
|
||||
/**
|
||||
*
|
||||
* @type {MediaType}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
MediaType?: MediaType;
|
||||
/**
|
||||
* Gets or sets the end date.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
EndDate?: string | null;
|
||||
/**
|
||||
* Gets or sets the locked fields.
|
||||
* @type {Array<MetadataField>}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
LockedFields?: Array<MetadataField> | null;
|
||||
/**
|
||||
* Gets or sets the trailer count.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
TrailerCount?: number | null;
|
||||
/**
|
||||
* Gets or sets the movie count.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
MovieCount?: number | null;
|
||||
/**
|
||||
* Gets or sets the series count.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
SeriesCount?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ProgramCount?: number | null;
|
||||
/**
|
||||
* Gets or sets the episode count.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
EpisodeCount?: number | null;
|
||||
/**
|
||||
* Gets or sets the song count.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
SongCount?: number | null;
|
||||
/**
|
||||
* Gets or sets the album count.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
AlbumCount?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ArtistCount?: number | null;
|
||||
/**
|
||||
* Gets or sets the music video count.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
MusicVideoCount?: number | null;
|
||||
/**
|
||||
* Gets or sets a value indicating whether [enable internet providers].
|
||||
* @type {boolean}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
LockData?: boolean | null;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Width?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Height?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
CameraMake?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
CameraModel?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Software?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ExposureTime?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
FocalLength?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {ImageOrientation}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ImageOrientation?: ImageOrientation;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Aperture?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ShutterSpeed?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Latitude?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Longitude?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
Altitude?: number | null;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
IsoSpeedRating?: number | null;
|
||||
/**
|
||||
* Gets or sets the series timer identifier.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
SeriesTimerId?: string | null;
|
||||
/**
|
||||
* Gets or sets the program identifier.
|
||||
* @type {string}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
ProgramId?: string | null;
|
||||
|
||||
/**
|
||||
* Gets or sets the completion percentage.
|
||||
* @type {number}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
CompletionPercentage?: number | null;
|
||||
/**
|
||||
* Gets or sets a value indicating whether this instance is repeat.
|
||||
* @type {boolean}
|
||||
* @memberof BaseItemDto
|
||||
*/
|
||||
IsRepeat?: boolean | null;
|
||||
}
|
||||
@@ -19,14 +19,7 @@ import {
|
||||
download,
|
||||
setConfig,
|
||||
} from "@kesha-antonov/react-native-background-downloader";
|
||||
import MMKV from "react-native-mmkv";
|
||||
import {
|
||||
focusManager,
|
||||
QueryClient,
|
||||
QueryClientProvider,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
} from "@tanstack/react-query";
|
||||
import { focusManager, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
import { useRouter } from "expo-router";
|
||||
@@ -45,7 +38,7 @@ import { apiAtom } from "./JellyfinProvider";
|
||||
import * as Notifications from "expo-notifications";
|
||||
import { getItemImage } from "@/utils/getItemImage";
|
||||
import useImageStorage from "@/hooks/useImageStorage";
|
||||
import { storage } from "@/utils/mmkv";
|
||||
import { formatItemName, saveItemMapping, storage } from "@/utils/mmkv";
|
||||
import useDownloadHelper from "@/utils/download";
|
||||
import { FileInfo } from "expo-file-system";
|
||||
import * as Haptics from "expo-haptics";
|
||||
@@ -54,8 +47,11 @@ import * as Application from "expo-application";
|
||||
export type DownloadedItem = {
|
||||
item: Partial<BaseItemDto>;
|
||||
mediaSource: MediaSourceInfo;
|
||||
fileSize: number;
|
||||
};
|
||||
|
||||
export type DownloadedItem2 = {};
|
||||
|
||||
export const processesAtom = atom<JobStatus[]>([]);
|
||||
|
||||
function onAppStateChange(status: AppStateStatus) {
|
||||
@@ -512,8 +508,10 @@ function useDownloadProvider() {
|
||||
|
||||
const downloadedItems = storage.getString("downloadedItems");
|
||||
if (downloadedItems) {
|
||||
let items = JSON.parse(downloadedItems) as DownloadedItem[];
|
||||
items = items.filter((item) => item.item.Id !== id);
|
||||
let items: { [key: string]: BaseItemDto } = downloadedItems
|
||||
? JSON.parse(downloadedItems)
|
||||
: {};
|
||||
delete items[id];
|
||||
storage.set("downloadedItems", JSON.stringify(items));
|
||||
}
|
||||
|
||||
@@ -586,7 +584,7 @@ function useDownloadProvider() {
|
||||
const appSizeUsage = useMemo(async () => {
|
||||
const sizes: number[] =
|
||||
downloadedFiles?.map((d) => {
|
||||
return getDownloadedItemSize(d.item.Id!!);
|
||||
return d.fileSize;
|
||||
}) || [];
|
||||
|
||||
await forEveryDocumentDirFile(
|
||||
@@ -608,8 +606,10 @@ function useDownloadProvider() {
|
||||
try {
|
||||
const downloadedItems = storage.getString("downloadedItems");
|
||||
if (downloadedItems) {
|
||||
const items: DownloadedItem[] = JSON.parse(downloadedItems);
|
||||
const item = items.find((i) => i.item.Id === itemId);
|
||||
const items: { [key: string]: BaseItemDto } = downloadedItems
|
||||
? JSON.parse(downloadedItems)
|
||||
: {};
|
||||
const item = items[itemId] as DownloadedItem;
|
||||
return item || null;
|
||||
}
|
||||
return null;
|
||||
@@ -623,7 +623,7 @@ function useDownloadProvider() {
|
||||
try {
|
||||
const downloadedItems = storage.getString("downloadedItems");
|
||||
if (downloadedItems) {
|
||||
return JSON.parse(downloadedItems) as DownloadedItem[];
|
||||
return Object.values(JSON.parse(downloadedItems)) as DownloadedItem[];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
@@ -636,11 +636,11 @@ function useDownloadProvider() {
|
||||
function saveDownloadedItemInfo(item: BaseItemDto, size: number = 0) {
|
||||
try {
|
||||
const downloadedItems = storage.getString("downloadedItems");
|
||||
let items: DownloadedItem[] = downloadedItems
|
||||
const items: { [key: string]: BaseItemDto } = downloadedItems
|
||||
? JSON.parse(downloadedItems)
|
||||
: [];
|
||||
: {};
|
||||
|
||||
const existingItemIndex = items.findIndex((i) => i.item.Id === item.Id);
|
||||
const chosenItem = items[item.Id!] || {};
|
||||
|
||||
const data = getDownloadItemInfoFromDiskTmp(item.Id!);
|
||||
|
||||
@@ -651,12 +651,6 @@ function useDownloadProvider() {
|
||||
|
||||
const newItem = { item, mediaSource: data.mediaSource };
|
||||
|
||||
if (existingItemIndex !== -1) {
|
||||
items[existingItemIndex] = newItem;
|
||||
} else {
|
||||
items.push(newItem);
|
||||
}
|
||||
|
||||
deleteDownloadItemInfoFromDiskTmp(item.Id!);
|
||||
|
||||
storage.set("downloadedItems", JSON.stringify(items));
|
||||
|
||||
@@ -1,3 +1,30 @@
|
||||
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
|
||||
import { MMKV } from "react-native-mmkv";
|
||||
|
||||
export const storage = new MMKV();
|
||||
const storage = new MMKV();
|
||||
|
||||
const saveItemMapping = (itemId: string | undefined, fileName: string) => {
|
||||
if (!itemId) return;
|
||||
storage.set(itemId, fileName);
|
||||
};
|
||||
|
||||
const getFilePathFromItemId = (itemId: string): string | undefined => {
|
||||
return storage.getString(itemId);
|
||||
};
|
||||
|
||||
const formatItemName = (item: BaseItemDto) => {
|
||||
if (item.Type === "Episode") {
|
||||
const formattedParentIndexNumber = (item.ParentIndexNumber ?? 0)
|
||||
.toString()
|
||||
.padStart(2, "0");
|
||||
const formattedIndexNumber = (item.IndexNumber ?? 0)
|
||||
.toString()
|
||||
.padStart(2, "0");
|
||||
|
||||
const formattedString = `S${formattedParentIndexNumber}E${formattedIndexNumber}`;
|
||||
return `${item.SeriesName} - ${formattedString} - ${item.Name}`;
|
||||
}
|
||||
return item.Name;
|
||||
};
|
||||
|
||||
export { saveItemMapping, getFilePathFromItemId, storage, formatItemName };
|
||||
|
||||
Reference in New Issue
Block a user