forked from Ninjalama/streamyfin_mirror
Compare commits
5 Commits
feature/mp
...
feature/li
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89e02f315a | ||
|
|
87880f1989 | ||
|
|
192bc9d05a | ||
|
|
9df7ffccc5 | ||
|
|
3fa2747593 |
@@ -1 +0,0 @@
|
||||
EXPO_PUBLIC_WRITE_DEBUG=1
|
||||
@@ -1 +0,0 @@
|
||||
EXPO_PUBLIC_WRITE_DEBUG=0
|
||||
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -43,7 +43,6 @@ body:
|
||||
label: Version
|
||||
description: What version of Streamyfin are you running?
|
||||
options:
|
||||
- 0.28.0
|
||||
- 0.27.0
|
||||
- 0.26.1
|
||||
- 0.26.0
|
||||
|
||||
28
.github/workflows/lint.yaml
vendored
28
.github/workflows/lint.yaml
vendored
@@ -1,28 +0,0 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ develop, master ]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '20.x'
|
||||
|
||||
- name: Setup Bun
|
||||
uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install
|
||||
|
||||
- name: Run linting checks
|
||||
run: bun run check
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -45,6 +45,3 @@ credentials.json
|
||||
.idea/
|
||||
.ruby-lsp
|
||||
modules/hls-downloader/android/build
|
||||
streamyfin-4fec1-firebase-adminsdk.json
|
||||
.env
|
||||
.env.local
|
||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"prettier.printWidth": 120,
|
||||
"[swift]": {
|
||||
"editor.defaultFormatter": "swiftlang.swift-vscode"
|
||||
"editor.defaultFormatter": "sswg.swift-lang"
|
||||
},
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "biomejs.biome",
|
||||
|
||||
@@ -86,7 +86,6 @@ We welcome any help to make Streamyfin better. If you'd like to contribute, plea
|
||||
1. Use node `>20`
|
||||
2. Install dependencies `bun i && bun run submodule-reload`
|
||||
3. Make sure you have xcode and/or android studio installed. (follow the guides for expo: https://docs.expo.dev/workflow/android-studio-emulator/)
|
||||
4. Install BiomeJS extension in VSCode/Your IDE (https://biomejs.dev/)
|
||||
4. run `npm run prebuild`
|
||||
5. Create an expo dev build by running `npm run ios` or `npm run android`. This will open a simulator on your computer and run the app.
|
||||
|
||||
@@ -124,10 +123,6 @@ Streamyfin is developed by [Fredrik Burmester](https://github.com/fredrikburmest
|
||||
|
||||
## ✨ Acknowledgements
|
||||
|
||||
We would like to thank the Jellyfin team for their great software and awesome support on discord.
|
||||
|
||||
Special shoutout to the JF official clients for being an inspiration to ours.
|
||||
|
||||
### Core Developers
|
||||
|
||||
Thanks to the following contributors for their significant contributions:
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
module.exports = ({ config }) => {
|
||||
if (process.env.EXPO_TV !== "1") {
|
||||
if (process.env.EXPO_TV != "1") {
|
||||
config.plugins.push([
|
||||
"react-native-google-cast",
|
||||
{ useDefaultExpandedMediaControls: true },
|
||||
]);
|
||||
}
|
||||
return {
|
||||
android: {
|
||||
googleServicesFile: process.env.GOOGLE_SERVICES_JSON,
|
||||
},
|
||||
...config,
|
||||
};
|
||||
};
|
||||
|
||||
7
app.json
7
app.json
@@ -2,7 +2,7 @@
|
||||
"expo": {
|
||||
"name": "Streamyfin",
|
||||
"slug": "streamyfin",
|
||||
"version": "0.28.0",
|
||||
"version": "0.27.0",
|
||||
"orientation": "default",
|
||||
"icon": "./assets/images/icon.png",
|
||||
"scheme": "streamyfin",
|
||||
@@ -31,7 +31,7 @@
|
||||
},
|
||||
"android": {
|
||||
"jsEngine": "hermes",
|
||||
"versionCode": 54,
|
||||
"versionCode": 53,
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/images/adaptive_icon.png",
|
||||
"backgroundColor": "#464646"
|
||||
@@ -41,8 +41,7 @@
|
||||
"android.permission.FOREGROUND_SERVICE",
|
||||
"android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK",
|
||||
"android.permission.WRITE_SETTINGS"
|
||||
],
|
||||
"googleServicesFile": "./google-services.json"
|
||||
]
|
||||
},
|
||||
"plugins": [
|
||||
"@react-native-tvos/config-tv",
|
||||
|
||||
@@ -26,11 +26,11 @@ export default function menuLinks() {
|
||||
const getMenuLinks = useCallback(async () => {
|
||||
try {
|
||||
const response = await api?.axiosInstance.get(
|
||||
`${api?.basePath}/web/config.json`,
|
||||
api?.basePath + "/web/config.json",
|
||||
);
|
||||
const config = response?.data;
|
||||
|
||||
if (!config && !Object.hasOwn(config, "menuLinks")) {
|
||||
if (!config && !config.hasOwnProperty("menuLinks")) {
|
||||
console.error("Menu links not found");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export default function SearchLayout() {
|
||||
backgroundColor: "black",
|
||||
},
|
||||
headerBlurEffect: "prominent",
|
||||
headerTransparent: Platform.OS === "ios",
|
||||
headerTransparent: Platform.OS === "ios" ? true : false,
|
||||
headerShadowVisible: false,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -32,7 +32,7 @@ export default function IndexLayout() {
|
||||
{!Platform.isTV && (
|
||||
<>
|
||||
<Chromecast.Chromecast />
|
||||
{user?.Policy?.IsAdministrator && <SessionsButton />}
|
||||
{user && user.Policy?.IsAdministrator && <SessionsButton />}
|
||||
<SettingsButton />
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -29,7 +29,7 @@ export default function page() {
|
||||
try {
|
||||
return (
|
||||
downloadedFiles
|
||||
?.filter((f) => f.item.SeriesId === seriesId)
|
||||
?.filter((f) => f.item.SeriesId == seriesId)
|
||||
?.sort(
|
||||
(a, b) => a?.item.ParentIndexNumber! - b.item.ParentIndexNumber!,
|
||||
) || []
|
||||
|
||||
@@ -36,7 +36,7 @@ export default function page() {
|
||||
</View>
|
||||
);
|
||||
|
||||
if (!sessions || sessions.length === 0)
|
||||
if (!sessions || sessions.length == 0)
|
||||
return (
|
||||
<View className='h-full w-full flex justify-center items-center'>
|
||||
<Text className='text-lg text-neutral-500'>
|
||||
@@ -175,7 +175,7 @@ const SessionCard = ({ session }: SessionCardProps) => {
|
||||
</View>
|
||||
<View className='align-bottom bg-gray-800 h-1'>
|
||||
<View
|
||||
className={"bg-purple-600 h-full"}
|
||||
className={`bg-purple-600 h-full`}
|
||||
style={{
|
||||
width: `${getProgressPercentage()}%`,
|
||||
}}
|
||||
@@ -298,7 +298,7 @@ const TranscodingStreamView = ({
|
||||
const TranscodingView = ({ session }: SessionCardProps) => {
|
||||
const videoStream = useMemo(() => {
|
||||
return session.NowPlayingItem?.MediaStreams?.filter(
|
||||
(s) => s.Type === "Video",
|
||||
(s) => s.Type == "Video",
|
||||
)[0];
|
||||
}, [session]);
|
||||
|
||||
@@ -318,7 +318,7 @@ const TranscodingView = ({ session }: SessionCardProps) => {
|
||||
|
||||
const isTranscoding = useMemo(() => {
|
||||
return (
|
||||
session.PlayState?.PlayMethod === "Transcode" && session.TranscodingInfo
|
||||
session.PlayState?.PlayMethod == "Transcode" && session.TranscodingInfo
|
||||
);
|
||||
}, [session.PlayState?.PlayMethod, session.TranscodingInfo]);
|
||||
|
||||
@@ -341,7 +341,9 @@ const TranscodingView = ({ session }: SessionCardProps) => {
|
||||
codec: session.TranscodingInfo?.VideoCodec,
|
||||
}}
|
||||
isTranscoding={
|
||||
!!(isTranscoding && !session.TranscodingInfo?.IsVideoDirect)
|
||||
isTranscoding && !session.TranscodingInfo?.IsVideoDirect
|
||||
? true
|
||||
: false
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -358,20 +360,24 @@ const TranscodingView = ({ session }: SessionCardProps) => {
|
||||
audioChannels: session.TranscodingInfo?.AudioChannels?.toString(),
|
||||
}}
|
||||
isTranscoding={
|
||||
!!(isTranscoding && !session.TranscodingInfo?.IsVideoDirect)
|
||||
isTranscoding && !session.TranscodingInfo?.IsVideoDirect
|
||||
? true
|
||||
: false
|
||||
}
|
||||
/>
|
||||
|
||||
{subtitleStream && (
|
||||
<TranscodingStreamView
|
||||
title='Subtitle'
|
||||
isTranscoding={false}
|
||||
properties={{
|
||||
language: subtitleStream?.Language,
|
||||
codec: subtitleStream?.Codec,
|
||||
}}
|
||||
transcodeValue={null}
|
||||
/>
|
||||
<>
|
||||
<TranscodingStreamView
|
||||
title='Subtitle'
|
||||
isTranscoding={false}
|
||||
properties={{
|
||||
language: subtitleStream?.Language,
|
||||
codec: subtitleStream?.Codec,
|
||||
}}
|
||||
transcodeValue={null}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -1,157 +1,37 @@
|
||||
import { Loader } from "@/components/Loader";
|
||||
import { Text } from "@/components/common/Text";
|
||||
import { FilterButton } from "@/components/filters/FilterButton";
|
||||
import { LogLevel, useLog, writeErrorLog } from "@/utils/log";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
import { useNavigation } from "expo-router";
|
||||
import * as Sharing from "expo-sharing";
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useLog } from "@/utils/log";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ScrollView, TouchableOpacity, View } from "react-native";
|
||||
import Collapsible from "react-native-collapsible";
|
||||
import { ScrollView, View } from "react-native";
|
||||
|
||||
export default function page() {
|
||||
const navigation = useNavigation();
|
||||
const { logs } = useLog();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const defaultLevels: LogLevel[] = ["INFO", "ERROR", "DEBUG", "WARN"];
|
||||
const codeBlockStyle = {
|
||||
backgroundColor: "#000",
|
||||
padding: 10,
|
||||
fontFamily: "monospace",
|
||||
maxHeight: 300,
|
||||
};
|
||||
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [state, setState] = useState<Record<string, boolean>>({});
|
||||
|
||||
const [order, setOrder] = useState<"asc" | "desc">("desc");
|
||||
const [levels, setLevels] = useState<LogLevel[]>(defaultLevels);
|
||||
|
||||
const filteredLogs = useMemo(
|
||||
() =>
|
||||
logs
|
||||
?.filter((log) => levels.includes(log.level))
|
||||
?.[
|
||||
// Already in asc order as they are recorded. just reverse for desc
|
||||
order === "desc" ? "reverse" : "concat"
|
||||
]?.(),
|
||||
[logs, order, levels],
|
||||
);
|
||||
|
||||
// Sharing it as txt while its formatted allows us to share it with many more applications
|
||||
const share = useCallback(async () => {
|
||||
const uri = `${FileSystem.documentDirectory}logs.txt`;
|
||||
|
||||
setLoading(true);
|
||||
FileSystem.writeAsStringAsync(uri, JSON.stringify(filteredLogs))
|
||||
.then(() => {
|
||||
setLoading(false);
|
||||
Sharing.shareAsync(uri, { mimeType: "txt", UTI: "txt" });
|
||||
})
|
||||
.catch((e) =>
|
||||
writeErrorLog("Something went wrong attempting to export", e),
|
||||
)
|
||||
.finally(() => setLoading(false));
|
||||
}, [filteredLogs]);
|
||||
|
||||
useEffect(() => {
|
||||
navigation.setOptions({
|
||||
headerRight: () =>
|
||||
loading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<TouchableOpacity onPress={share}>
|
||||
<Text>{t("home.settings.logs.export_logs")}</Text>
|
||||
</TouchableOpacity>
|
||||
),
|
||||
});
|
||||
}, [share, loading]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<View className='flex flex-row justify-end py-2 px-4 space-x-2'>
|
||||
<FilterButton
|
||||
id='order'
|
||||
queryKey='log'
|
||||
queryFn={async () => ["asc", "desc"]}
|
||||
set={(values) => setOrder(values[0])}
|
||||
values={[order]}
|
||||
title={t("library.filters.sort_order")}
|
||||
renderItemLabel={(order) => t(`library.filters.${order}`)}
|
||||
showSearch={false}
|
||||
/>
|
||||
<FilterButton
|
||||
id='levels'
|
||||
queryKey='log'
|
||||
queryFn={async () => defaultLevels}
|
||||
set={setLevels}
|
||||
values={levels}
|
||||
title={t("home.settings.logs.level")}
|
||||
renderItemLabel={(level) => level}
|
||||
showSearch={false}
|
||||
multiple={true}
|
||||
/>
|
||||
</View>
|
||||
<ScrollView className='pb-4 px-4'>
|
||||
<View className='flex flex-col space-y-2'>
|
||||
{filteredLogs?.map((log, index) => (
|
||||
<View className='bg-neutral-900 rounded-xl p-3' key={index}>
|
||||
<TouchableOpacity
|
||||
disabled={!log.data}
|
||||
onPress={() =>
|
||||
setState((v) => ({
|
||||
...v,
|
||||
[log.timestamp]: !v[log.timestamp],
|
||||
}))
|
||||
}
|
||||
>
|
||||
<View className='flex flex-row justify-between'>
|
||||
<Text
|
||||
className={`mb-1
|
||||
${log.level === "INFO" && "text-blue-500"}
|
||||
${log.level === "ERROR" && "text-red-500"}
|
||||
${log.level === "DEBUG" && "text-purple-500"}
|
||||
`}
|
||||
>
|
||||
{log.level}
|
||||
</Text>
|
||||
|
||||
<Text className='text-xs'>
|
||||
{new Date(log.timestamp).toLocaleString()}
|
||||
</Text>
|
||||
</View>
|
||||
<Text uiTextView selectable className='text-xs'>
|
||||
{log.message}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
{log.data && (
|
||||
<>
|
||||
{!state[log.timestamp] && (
|
||||
<Text className='text-xs mt-0.5'>
|
||||
{t("home.settings.logs.click_for_more_info")}
|
||||
</Text>
|
||||
)}
|
||||
<Collapsible collapsed={!state[log.timestamp]}>
|
||||
<View className='mt-2 flex flex-col space-y-2'>
|
||||
<ScrollView className='rounded-xl' style={codeBlockStyle}>
|
||||
<Text>{JSON.stringify(log.data, null, 2)}</Text>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</Collapsible>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
))}
|
||||
{filteredLogs?.length === 0 && (
|
||||
<Text className='opacity-50'>
|
||||
{t("home.settings.logs.no_logs_available")}
|
||||
<ScrollView className='p-4'>
|
||||
<View className='flex flex-col space-y-2'>
|
||||
{logs?.map((log, index) => (
|
||||
<View key={index} className='bg-neutral-900 rounded-xl p-3'>
|
||||
<Text
|
||||
className={`
|
||||
mb-1
|
||||
${log.level === "INFO" && "text-blue-500"}
|
||||
${log.level === "ERROR" && "text-red-500"}
|
||||
`}
|
||||
>
|
||||
{log.level}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</>
|
||||
<Text uiTextView selectable className='text-xs'>
|
||||
{log.message}
|
||||
</Text>
|
||||
</View>
|
||||
))}
|
||||
{logs?.length === 0 && (
|
||||
<Text className='opacity-50'>
|
||||
{t("home.settings.logs.no_logs_available")}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ export default function page() {
|
||||
showText={!pluginSettings?.searchEngine?.locked}
|
||||
className='mt-2 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"}>
|
||||
<View className={`flex flex-row items-center bg-neutral-900 h-11 pr-4`}>
|
||||
<Text className='mr-4'>
|
||||
{t("home.settings.plugins.marlin_search.url")}
|
||||
</Text>
|
||||
|
||||
@@ -31,7 +31,7 @@ export default function page() {
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedUrl = newVal.endsWith("/") ? newVal : `${newVal}/`;
|
||||
const updatedUrl = newVal.endsWith("/") ? newVal : newVal + "/";
|
||||
|
||||
updateSettings({
|
||||
optimizedVersionsServerUrl: updatedUrl,
|
||||
|
||||
@@ -133,7 +133,7 @@ const page: React.FC = () => {
|
||||
queryFn={fetchItems}
|
||||
queryKey={["actor", "movies", actorId]}
|
||||
/>
|
||||
<View className='h-12' />
|
||||
<View className='h-12'></View>
|
||||
</View>
|
||||
</ParallaxScrollView>
|
||||
);
|
||||
|
||||
@@ -157,8 +157,9 @@ const page: React.FC = () => {
|
||||
|
||||
if (accumulatedItems < totalItems) {
|
||||
return lastPage?.Items?.length * pages.length;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
initialPageParam: 0,
|
||||
enabled: !!api && !!user?.Id && !!collection,
|
||||
@@ -233,7 +234,7 @@ const page: React.FC = () => {
|
||||
component: (
|
||||
<FilterButton
|
||||
className='mr-1'
|
||||
id={collectionId}
|
||||
collectionId={collectionId}
|
||||
queryKey='genreFilter'
|
||||
queryFn={async () => {
|
||||
if (!api) return null;
|
||||
@@ -260,7 +261,7 @@ const page: React.FC = () => {
|
||||
component: (
|
||||
<FilterButton
|
||||
className='mr-1'
|
||||
id={collectionId}
|
||||
collectionId={collectionId}
|
||||
queryKey='yearFilter'
|
||||
queryFn={async () => {
|
||||
if (!api) return null;
|
||||
@@ -285,7 +286,7 @@ const page: React.FC = () => {
|
||||
component: (
|
||||
<FilterButton
|
||||
className='mr-1'
|
||||
id={collectionId}
|
||||
collectionId={collectionId}
|
||||
queryKey='tagsFilter'
|
||||
queryFn={async () => {
|
||||
if (!api) return null;
|
||||
@@ -312,7 +313,7 @@ const page: React.FC = () => {
|
||||
component: (
|
||||
<FilterButton
|
||||
className='mr-1'
|
||||
id={collectionId}
|
||||
collectionId={collectionId}
|
||||
queryKey='sortBy'
|
||||
queryFn={async () => sortOptions.map((s) => s.key)}
|
||||
set={setSortBy}
|
||||
@@ -332,7 +333,7 @@ const page: React.FC = () => {
|
||||
component: (
|
||||
<FilterButton
|
||||
className='mr-1'
|
||||
id={collectionId}
|
||||
collectionId={collectionId}
|
||||
queryKey='sortOrder'
|
||||
queryFn={async () => sortOrderOptions.map((s) => s.key)}
|
||||
set={setSortOrder}
|
||||
@@ -411,7 +412,7 @@ const page: React.FC = () => {
|
||||
width: 10,
|
||||
height: 10,
|
||||
}}
|
||||
/>
|
||||
></View>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -93,19 +93,19 @@ const Page: React.FC = () => {
|
||||
height: item?.Type === "Episode" ? 300 : 450,
|
||||
}}
|
||||
className='bg-transparent rounded-lg mb-4 w-full'
|
||||
/>
|
||||
<View className='h-6 bg-neutral-900 rounded mb-4 w-14' />
|
||||
<View className='h-10 bg-neutral-900 rounded-lg mb-2 w-1/2' />
|
||||
<View className='h-3 bg-neutral-900 rounded mb-3 w-8' />
|
||||
></View>
|
||||
<View className='h-6 bg-neutral-900 rounded mb-4 w-14'></View>
|
||||
<View className='h-10 bg-neutral-900 rounded-lg mb-2 w-1/2'></View>
|
||||
<View className='h-3 bg-neutral-900 rounded mb-3 w-8'></View>
|
||||
<View className='flex flex-row space-x-1 mb-8'>
|
||||
<View className='h-6 bg-neutral-900 rounded mb-3 w-14' />
|
||||
<View className='h-6 bg-neutral-900 rounded mb-3 w-14' />
|
||||
<View className='h-6 bg-neutral-900 rounded mb-3 w-14' />
|
||||
<View className='h-6 bg-neutral-900 rounded mb-3 w-14'></View>
|
||||
<View className='h-6 bg-neutral-900 rounded mb-3 w-14'></View>
|
||||
<View className='h-6 bg-neutral-900 rounded mb-3 w-14'></View>
|
||||
</View>
|
||||
<View className='h-3 bg-neutral-900 rounded w-2/3 mb-1' />
|
||||
<View className='h-10 bg-neutral-900 rounded-lg w-full mb-2' />
|
||||
<View className='h-12 bg-neutral-900 rounded-lg w-full mb-2' />
|
||||
<View className='h-24 bg-neutral-900 rounded-lg mb-1 w-full' />
|
||||
<View className='h-3 bg-neutral-900 rounded w-2/3 mb-1'></View>
|
||||
<View className='h-10 bg-neutral-900 rounded-lg w-full mb-2'></View>
|
||||
<View className='h-12 bg-neutral-900 rounded-lg w-full mb-2'></View>
|
||||
<View className='h-24 bg-neutral-900 rounded-lg mb-1 w-full'></View>
|
||||
</Animated.View>
|
||||
{item && <ItemContent item={item} />}
|
||||
</View>
|
||||
|
||||
@@ -33,11 +33,9 @@ export default function page() {
|
||||
};
|
||||
|
||||
return jellyseerrApi?.discover(
|
||||
`${
|
||||
type === DiscoverSliderType.NETWORKS
|
||||
? Endpoints.DISCOVER_TV_NETWORK
|
||||
: Endpoints.DISCOVER_MOVIES_STUDIO
|
||||
}/${companyId}`,
|
||||
(type == DiscoverSliderType.NETWORKS
|
||||
? Endpoints.DISCOVER_TV_NETWORK
|
||||
: Endpoints.DISCOVER_MOVIES_STUDIO) + `/${companyId}`,
|
||||
params,
|
||||
);
|
||||
},
|
||||
|
||||
@@ -36,7 +36,7 @@ export default function page() {
|
||||
};
|
||||
|
||||
return jellyseerrApi?.discover(
|
||||
type === DiscoverSliderType.MOVIE_GENRES
|
||||
type == DiscoverSliderType.MOVIE_GENRES
|
||||
? Endpoints.DISCOVER_MOVIES
|
||||
: Endpoints.DISCOVER_TV,
|
||||
params,
|
||||
|
||||
@@ -240,7 +240,7 @@ const Page: React.FC = () => {
|
||||
<GenreTags genres={details?.genres?.map((g) => g.name) || []} />
|
||||
</View>
|
||||
{isLoading || isFetching ? (
|
||||
<Button loading={true} disabled={true} color='purple' />
|
||||
<Button loading={true} disabled={true} color='purple'></Button>
|
||||
) : canRequest ? (
|
||||
<Button color='purple' onPress={request}>
|
||||
{t("jellyseerr.request_button")}
|
||||
|
||||
@@ -124,7 +124,7 @@ export default function page() {
|
||||
height: HOUR_HEIGHT,
|
||||
}}
|
||||
className='bg-neutral-800'
|
||||
/>
|
||||
></View>
|
||||
{channels?.Items?.map((c, i) => (
|
||||
<View className='h-16 w-16 mr-4 rounded-lg overflow-hidden' key={i}>
|
||||
<ItemImage
|
||||
|
||||
@@ -87,21 +87,23 @@ const page: React.FC = () => {
|
||||
<View className='flex flex-row items-center space-x-2'>
|
||||
<AddToFavorites item={item} />
|
||||
{!Platform.isTV && (
|
||||
<DownloadItems
|
||||
size='large'
|
||||
title={t("item_card.download.download_series")}
|
||||
items={allEpisodes || []}
|
||||
MissingDownloadIconComponent={() => (
|
||||
<Ionicons name='download' size={22} color='white' />
|
||||
)}
|
||||
DownloadedIconComponent={() => (
|
||||
<Ionicons
|
||||
name='checkmark-done-outline'
|
||||
size={24}
|
||||
color='#9333ea'
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<>
|
||||
<DownloadItems
|
||||
size='large'
|
||||
title={t("item_card.download.download_series")}
|
||||
items={allEpisodes || []}
|
||||
MissingDownloadIconComponent={() => (
|
||||
<Ionicons name='download' size={22} color='white' />
|
||||
)}
|
||||
DownloadedIconComponent={() => (
|
||||
<Ionicons
|
||||
name='checkmark-done-outline'
|
||||
size={24}
|
||||
color='#9333ea'
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
),
|
||||
@@ -125,18 +127,20 @@ const page: React.FC = () => {
|
||||
/>
|
||||
}
|
||||
logo={
|
||||
logoUrl ? (
|
||||
<Image
|
||||
source={{
|
||||
uri: logoUrl,
|
||||
}}
|
||||
style={{
|
||||
height: 130,
|
||||
width: "100%",
|
||||
resizeMode: "contain",
|
||||
}}
|
||||
/>
|
||||
) : null
|
||||
<>
|
||||
{logoUrl ? (
|
||||
<Image
|
||||
source={{
|
||||
uri: logoUrl,
|
||||
}}
|
||||
style={{
|
||||
height: 130,
|
||||
width: "100%",
|
||||
resizeMode: "contain",
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<View className='flex flex-col pt-4'>
|
||||
|
||||
@@ -216,8 +216,9 @@ const Page = () => {
|
||||
|
||||
if (accumulatedItems < totalItems) {
|
||||
return lastPage?.Items?.length * pages.length;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
initialPageParam: 0,
|
||||
enabled: !!api && !!user?.Id && !!library,
|
||||
@@ -286,7 +287,7 @@ const Page = () => {
|
||||
component: (
|
||||
<FilterButton
|
||||
className='mr-1'
|
||||
id={libraryId}
|
||||
collectionId={libraryId}
|
||||
queryKey='genreFilter'
|
||||
queryFn={async () => {
|
||||
if (!api) return null;
|
||||
@@ -313,7 +314,7 @@ const Page = () => {
|
||||
component: (
|
||||
<FilterButton
|
||||
className='mr-1'
|
||||
id={libraryId}
|
||||
collectionId={libraryId}
|
||||
queryKey='yearFilter'
|
||||
queryFn={async () => {
|
||||
if (!api) return null;
|
||||
@@ -338,7 +339,7 @@ const Page = () => {
|
||||
component: (
|
||||
<FilterButton
|
||||
className='mr-1'
|
||||
id={libraryId}
|
||||
collectionId={libraryId}
|
||||
queryKey='tagsFilter'
|
||||
queryFn={async () => {
|
||||
if (!api) return null;
|
||||
@@ -365,7 +366,7 @@ const Page = () => {
|
||||
component: (
|
||||
<FilterButton
|
||||
className='mr-1'
|
||||
id={libraryId}
|
||||
collectionId={libraryId}
|
||||
queryKey='sortBy'
|
||||
queryFn={async () => sortOptions.map((s) => s.key)}
|
||||
set={setSortBy}
|
||||
@@ -385,7 +386,7 @@ const Page = () => {
|
||||
component: (
|
||||
<FilterButton
|
||||
className='mr-1'
|
||||
id={libraryId}
|
||||
collectionId={libraryId}
|
||||
queryKey='sortOrder'
|
||||
queryFn={async () => sortOrderOptions.map((s) => s.key)}
|
||||
set={setSortOrder}
|
||||
@@ -477,7 +478,7 @@ const Page = () => {
|
||||
width: 10,
|
||||
height: 10,
|
||||
}}
|
||||
/>
|
||||
></View>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -25,7 +25,7 @@ export default function IndexLayout() {
|
||||
headerLargeStyle: {
|
||||
backgroundColor: "black",
|
||||
},
|
||||
headerTransparent: Platform.OS === "ios",
|
||||
headerTransparent: Platform.OS === "ios" ? true : false,
|
||||
headerShadowVisible: false,
|
||||
headerRight: () =>
|
||||
!pluginSettings?.libraryOptions?.locked &&
|
||||
@@ -159,7 +159,7 @@ export default function IndexLayout() {
|
||||
updateSettings({
|
||||
libraryOptions: {
|
||||
...settings.libraryOptions,
|
||||
showTitles: newValue === "on",
|
||||
showTitles: newValue === "on" ? true : false,
|
||||
},
|
||||
});
|
||||
}}
|
||||
@@ -176,7 +176,7 @@ export default function IndexLayout() {
|
||||
updateSettings({
|
||||
libraryOptions: {
|
||||
...settings.libraryOptions,
|
||||
showStats: newValue === "on",
|
||||
showStats: newValue === "on" ? true : false,
|
||||
},
|
||||
});
|
||||
}}
|
||||
@@ -200,7 +200,7 @@ export default function IndexLayout() {
|
||||
title: "",
|
||||
headerShown: true,
|
||||
headerBlurEffect: "prominent",
|
||||
headerTransparent: Platform.OS === "ios",
|
||||
headerTransparent: Platform.OS === "ios" ? true : false,
|
||||
headerShadowVisible: false,
|
||||
}}
|
||||
/>
|
||||
@@ -213,7 +213,7 @@ export default function IndexLayout() {
|
||||
title: "",
|
||||
headerShown: true,
|
||||
headerBlurEffect: "prominent",
|
||||
headerTransparent: Platform.OS === "ios",
|
||||
headerTransparent: Platform.OS === "ios" ? true : false,
|
||||
headerShadowVisible: false,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -100,7 +100,7 @@ export default function index() {
|
||||
height: StyleSheet.hairlineWidth,
|
||||
}}
|
||||
className='bg-neutral-800 mx-2 my-4'
|
||||
/>
|
||||
></View>
|
||||
) : (
|
||||
<View className='h-4' />
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@ export default function SearchLayout() {
|
||||
backgroundColor: "black",
|
||||
},
|
||||
headerBlurEffect: "prominent",
|
||||
headerTransparent: Platform.OS === "ios",
|
||||
headerTransparent: Platform.OS === "ios" ? true : false,
|
||||
headerShadowVisible: false,
|
||||
}}
|
||||
/>
|
||||
@@ -33,7 +33,7 @@ export default function SearchLayout() {
|
||||
title: "",
|
||||
headerShown: true,
|
||||
headerBlurEffect: "prominent",
|
||||
headerTransparent: Platform.OS === "ios",
|
||||
headerTransparent: Platform.OS === "ios" ? true : false,
|
||||
headerShadowVisible: false,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -14,6 +14,7 @@ import { LoadingSkeleton } from "@/components/search/LoadingSkeleton";
|
||||
import { SearchItemWrapper } from "@/components/search/SearchItemWrapper";
|
||||
import { useJellyseerr } from "@/hooks/useJellyseerr";
|
||||
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
|
||||
import { sortOrderOptions } from "@/utils/atoms/filters";
|
||||
import { useSettings } from "@/utils/atoms/settings";
|
||||
import { eventBus } from "@/utils/eventBus";
|
||||
import type {
|
||||
@@ -53,8 +54,6 @@ export default function search() {
|
||||
const params = useLocalSearchParams();
|
||||
const insets = useSafeAreaInsets();
|
||||
|
||||
const [user] = useAtom(userAtom);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { q } = params as { q: string };
|
||||
@@ -65,6 +64,7 @@ export default function search() {
|
||||
const [debouncedSearch] = useDebounce(search, 500);
|
||||
|
||||
const [api] = useAtom(apiAtom);
|
||||
const [user] = useAtom(userAtom);
|
||||
|
||||
const [settings] = useSettings();
|
||||
const { jellyseerrApi } = useJellyseerr();
|
||||
@@ -83,9 +83,7 @@ export default function search() {
|
||||
}, [settings]);
|
||||
|
||||
useEffect(() => {
|
||||
if (q && q.length > 0) {
|
||||
setSearch(q);
|
||||
}
|
||||
if (q && q.length > 0) setSearch(q);
|
||||
}, [q]);
|
||||
|
||||
const searchFn = useCallback(
|
||||
@@ -96,46 +94,39 @@ export default function search() {
|
||||
types: BaseItemKind[];
|
||||
query: string;
|
||||
}): Promise<BaseItemDto[]> => {
|
||||
if (!api || !query) {
|
||||
return [];
|
||||
}
|
||||
if (!api || !query) return [];
|
||||
|
||||
try {
|
||||
if (searchEngine === "Jellyfin") {
|
||||
const searchApi = await getItemsApi(api).getItems({
|
||||
const searchApi = await getSearchApi(api).getSearchHints({
|
||||
searchTerm: query,
|
||||
limit: 10,
|
||||
includeItemTypes: types,
|
||||
recursive: true,
|
||||
userId: user?.Id,
|
||||
});
|
||||
|
||||
return (searchApi.data.Items as BaseItemDto[]) || [];
|
||||
return (searchApi.data.SearchHints as BaseItemDto[]) || [];
|
||||
} else {
|
||||
if (!settings?.marlinServerUrl) return [];
|
||||
|
||||
const url = `${
|
||||
settings.marlinServerUrl
|
||||
}/search?q=${encodeURIComponent(query)}&includeItemTypes=${types
|
||||
.map((type) => encodeURIComponent(type))
|
||||
.join("&includeItemTypes=")}`;
|
||||
|
||||
const response1 = await axios.get(url);
|
||||
|
||||
const ids = response1.data.ids;
|
||||
|
||||
if (!ids || !ids.length) return [];
|
||||
|
||||
const response2 = await getItemsApi(api).getItems({
|
||||
ids,
|
||||
enableImageTypes: ["Primary", "Backdrop", "Thumb"],
|
||||
});
|
||||
|
||||
return (response2.data.Items as BaseItemDto[]) || [];
|
||||
}
|
||||
if (!settings?.marlinServerUrl) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const url = `${
|
||||
settings.marlinServerUrl
|
||||
}/search?q=${encodeURIComponent(query)}&includeItemTypes=${types
|
||||
.map((type) => encodeURIComponent(type))
|
||||
.join("&includeItemTypes=")}`;
|
||||
|
||||
const response1 = await axios.get(url);
|
||||
|
||||
const ids = response1.data.ids;
|
||||
|
||||
if (!ids || !ids.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const response2 = await getItemsApi(api).getItems({
|
||||
ids,
|
||||
enableImageTypes: ["Primary", "Backdrop", "Thumb"],
|
||||
});
|
||||
|
||||
return (response2.data.Items as BaseItemDto[]) || [];
|
||||
} catch (error) {
|
||||
console.error("Error during search:", error);
|
||||
return []; // Ensure an empty array is returned in case of an error
|
||||
@@ -171,10 +162,8 @@ export default function search() {
|
||||
|
||||
useEffect(() => {
|
||||
const unsubscribe = eventBus.on("searchTabPressed", () => {
|
||||
// Screen not active
|
||||
if (!searchBarRef.current) {
|
||||
return;
|
||||
}
|
||||
// Screen not actuve
|
||||
if (!searchBarRef.current) return;
|
||||
// Screen is active, focus search bar
|
||||
searchBarRef.current?.focus();
|
||||
});
|
||||
@@ -265,62 +254,64 @@ export default function search() {
|
||||
}}
|
||||
>
|
||||
{jellyseerrApi && (
|
||||
<ScrollView
|
||||
horizontal
|
||||
className='flex flex-row flex-wrap space-x-2 px-4 mb-2'
|
||||
>
|
||||
<TouchableOpacity onPress={() => setSearchType("Library")}>
|
||||
<Tag
|
||||
text={t("search.library")}
|
||||
textClass='p-1'
|
||||
className={
|
||||
searchType === "Library" ? "bg-purple-600" : undefined
|
||||
}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => setSearchType("Discover")}>
|
||||
<Tag
|
||||
text={t("search.discover")}
|
||||
textClass='p-1'
|
||||
className={
|
||||
searchType === "Discover" ? "bg-purple-600" : undefined
|
||||
}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
{searchType === "Discover" &&
|
||||
!loading &&
|
||||
noResults &&
|
||||
debouncedSearch.length > 0 && (
|
||||
<View className='flex flex-row justify-end items-center space-x-1'>
|
||||
<FilterButton
|
||||
id='search'
|
||||
queryKey='jellyseerr_search'
|
||||
queryFn={async () =>
|
||||
Object.keys(JellyseerrSearchSort).filter((v) =>
|
||||
Number.isNaN(Number(v)),
|
||||
)
|
||||
}
|
||||
set={(value) => setJellyseerrOrderBy(value[0])}
|
||||
values={[jellyseerrOrderBy]}
|
||||
title={t("library.filters.sort_by")}
|
||||
renderItemLabel={(item) =>
|
||||
t(`home.settings.plugins.jellyseerr.order_by.${item}`)
|
||||
}
|
||||
showSearch={false}
|
||||
/>
|
||||
<FilterButton
|
||||
id='order'
|
||||
queryKey='jellysearr_search'
|
||||
queryFn={async () => ["asc", "desc"]}
|
||||
set={(value) => setJellyseerrSortOrder(value[0])}
|
||||
values={[jellyseerrSortOrder]}
|
||||
title={t("library.filters.sort_order")}
|
||||
renderItemLabel={(item) => t(`library.filters.${item}`)}
|
||||
showSearch={false}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</ScrollView>
|
||||
<>
|
||||
<ScrollView
|
||||
horizontal
|
||||
className='flex flex-row flex-wrap space-x-2 px-4 mb-2'
|
||||
>
|
||||
<TouchableOpacity onPress={() => setSearchType("Library")}>
|
||||
<Tag
|
||||
text={t("search.library")}
|
||||
textClass='p-1'
|
||||
className={
|
||||
searchType === "Library" ? "bg-purple-600" : undefined
|
||||
}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => setSearchType("Discover")}>
|
||||
<Tag
|
||||
text={t("search.discover")}
|
||||
textClass='p-1'
|
||||
className={
|
||||
searchType === "Discover" ? "bg-purple-600" : undefined
|
||||
}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
{searchType === "Discover" &&
|
||||
!loading &&
|
||||
noResults &&
|
||||
debouncedSearch.length > 0 && (
|
||||
<View className='flex flex-row justify-end items-center space-x-1'>
|
||||
<FilterButton
|
||||
collectionId='search'
|
||||
queryKey='jellyseerr_search'
|
||||
queryFn={async () =>
|
||||
Object.keys(JellyseerrSearchSort).filter((v) =>
|
||||
isNaN(Number(v)),
|
||||
)
|
||||
}
|
||||
set={(value) => setJellyseerrOrderBy(value[0])}
|
||||
values={[jellyseerrOrderBy]}
|
||||
title={t("library.filters.sort_by")}
|
||||
renderItemLabel={(item) =>
|
||||
t(`home.settings.plugins.jellyseerr.order_by.${item}`)
|
||||
}
|
||||
showSearch={false}
|
||||
/>
|
||||
<FilterButton
|
||||
collectionId='order'
|
||||
queryKey='jellysearr_search'
|
||||
queryFn={async () => ["asc", "desc"]}
|
||||
set={(value) => setJellyseerrSortOrder(value[0])}
|
||||
values={[jellyseerrSortOrder]}
|
||||
title={t("library.filters.sort_order")}
|
||||
renderItemLabel={(item) => t(`library.filters.${item}`)}
|
||||
showSearch={false}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</ScrollView>
|
||||
</>
|
||||
)}
|
||||
|
||||
<View className='mt-2'>
|
||||
@@ -420,29 +411,32 @@ export default function search() {
|
||||
/>
|
||||
)}
|
||||
|
||||
{searchType === "Library" &&
|
||||
(!loading && noResults && debouncedSearch.length > 0 ? (
|
||||
<View>
|
||||
<Text className='text-center text-lg font-bold mt-4'>
|
||||
{t("search.no_results_found_for")}
|
||||
</Text>
|
||||
<Text className='text-xs text-purple-600 text-center'>
|
||||
"{debouncedSearch}"
|
||||
</Text>
|
||||
</View>
|
||||
) : debouncedSearch.length === 0 ? (
|
||||
<View className='mt-4 flex flex-col items-center space-y-2'>
|
||||
{exampleSearches.map((e) => (
|
||||
<TouchableOpacity
|
||||
onPress={() => setSearch(e)}
|
||||
key={e}
|
||||
className='mb-2'
|
||||
>
|
||||
<Text className='text-purple-600'>{e}</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
) : null)}
|
||||
{searchType === "Library" && (
|
||||
<>
|
||||
{!loading && noResults && debouncedSearch.length > 0 ? (
|
||||
<View>
|
||||
<Text className='text-center text-lg font-bold mt-4'>
|
||||
{t("search.no_results_found_for")}
|
||||
</Text>
|
||||
<Text className='text-xs text-purple-600 text-center'>
|
||||
"{debouncedSearch}"
|
||||
</Text>
|
||||
</View>
|
||||
) : debouncedSearch.length === 0 ? (
|
||||
<View className='mt-4 flex flex-col items-center space-y-2'>
|
||||
{exampleSearches.map((e) => (
|
||||
<TouchableOpacity
|
||||
onPress={() => setSearch(e)}
|
||||
key={e}
|
||||
className='mb-2'
|
||||
>
|
||||
<Text className='text-purple-600'>{e}</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</>
|
||||
|
||||
@@ -72,7 +72,7 @@ export default function TabLayout() {
|
||||
options={{
|
||||
title: t("tabs.home"),
|
||||
tabBarIcon:
|
||||
Platform.OS === "android"
|
||||
Platform.OS == "android"
|
||||
? ({ color, focused, size }) =>
|
||||
require("@/assets/icons/house.fill.png")
|
||||
: ({ focused }) =>
|
||||
@@ -91,7 +91,7 @@ export default function TabLayout() {
|
||||
options={{
|
||||
title: t("tabs.search"),
|
||||
tabBarIcon:
|
||||
Platform.OS === "android"
|
||||
Platform.OS == "android"
|
||||
? ({ color, focused, size }) =>
|
||||
require("@/assets/icons/magnifyingglass.png")
|
||||
: ({ focused }) =>
|
||||
@@ -105,7 +105,7 @@ export default function TabLayout() {
|
||||
options={{
|
||||
title: t("tabs.favorites"),
|
||||
tabBarIcon:
|
||||
Platform.OS === "android"
|
||||
Platform.OS == "android"
|
||||
? ({ color, focused, size }) =>
|
||||
focused
|
||||
? require("@/assets/icons/heart.fill.png")
|
||||
@@ -121,7 +121,7 @@ export default function TabLayout() {
|
||||
options={{
|
||||
title: t("tabs.library"),
|
||||
tabBarIcon:
|
||||
Platform.OS === "android"
|
||||
Platform.OS == "android"
|
||||
? ({ color, focused, size }) =>
|
||||
require("@/assets/icons/server.rack.png")
|
||||
: ({ focused }) =>
|
||||
@@ -135,9 +135,9 @@ export default function TabLayout() {
|
||||
options={{
|
||||
title: t("tabs.custom_links"),
|
||||
// @ts-expect-error
|
||||
tabBarItemHidden: !settings?.showCustomMenuLinks,
|
||||
tabBarItemHidden: settings?.showCustomMenuLinks ? false : true,
|
||||
tabBarIcon:
|
||||
Platform.OS === "android"
|
||||
Platform.OS == "android"
|
||||
? ({ focused }) => require("@/assets/icons/list.png")
|
||||
: ({ focused }) =>
|
||||
focused
|
||||
|
||||
@@ -6,19 +6,13 @@ import { getDownloadedFileUrl } from "@/hooks/useDownloadedFileOpener";
|
||||
import { useHaptic } from "@/hooks/useHaptic";
|
||||
import { useInvalidatePlaybackProgressCache } from "@/hooks/useRevalidatePlaybackProgressCache";
|
||||
import { useWebSocket } from "@/hooks/useWebsockets";
|
||||
import { MpvPlayerView, ProgressUpdatePayload, VlcPlayerView } from "@/modules";
|
||||
// import type {
|
||||
// PipStartedPayload,
|
||||
// PlaybackStatePayload,
|
||||
// ProgressUpdatePayload,
|
||||
// VlcPlayerViewRef,
|
||||
// } from "@/modules/VlcPlayer.types";
|
||||
|
||||
import { VlcPlayerView } from "@/modules";
|
||||
import type {
|
||||
MpvPlayerViewRef,
|
||||
PipStartedPayload,
|
||||
PlaybackStatePayload,
|
||||
} from "@/modules/MpvPlayer.types";
|
||||
ProgressUpdatePayload,
|
||||
VlcPlayerViewRef,
|
||||
} from "@/modules/VlcPlayer.types";
|
||||
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
|
||||
import { useSettings } from "@/utils/atoms/settings";
|
||||
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
|
||||
@@ -30,7 +24,6 @@ import {
|
||||
type MediaSourceInfo,
|
||||
PlaybackOrder,
|
||||
type PlaybackProgressInfo,
|
||||
PlaybackStartInfo,
|
||||
RepeatMode,
|
||||
} from "@jellyfin/sdk/lib/generated-client";
|
||||
import {
|
||||
@@ -56,7 +49,7 @@ const downloadProvider = !Platform.isTV
|
||||
: null;
|
||||
|
||||
export default function page() {
|
||||
const videoRef = useRef<MpvPlayerViewRef>(null);
|
||||
const videoRef = useRef<VlcPlayerViewRef>(null);
|
||||
const user = useAtomValue(userAtom);
|
||||
const api = useAtomValue(apiAtom);
|
||||
const { t } = useTranslation();
|
||||
@@ -208,29 +201,13 @@ export default function page() {
|
||||
fetchStreamData();
|
||||
}, [itemId, mediaSourceId, bitrateValue, api, item, user?.Id]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!stream) return;
|
||||
|
||||
const reportPlaybackStart = async () => {
|
||||
await getPlaystateApi(api!).reportPlaybackStart({
|
||||
playbackStartInfo: currentPlayStateInfo() as PlaybackStartInfo,
|
||||
});
|
||||
};
|
||||
|
||||
reportPlaybackStart();
|
||||
}, [stream]);
|
||||
|
||||
const togglePlay = async () => {
|
||||
lightHapticFeedback();
|
||||
setIsPlaying(!isPlaying);
|
||||
if (isPlaying) {
|
||||
await videoRef.current?.pause();
|
||||
reportPlaybackStopped();
|
||||
} else {
|
||||
videoRef.current?.play();
|
||||
await getPlaystateApi(api!).reportPlaybackStart({
|
||||
playbackStartInfo: currentPlayStateInfo() as PlaybackStartInfo,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -397,23 +374,20 @@ export default function page() {
|
||||
const chosenAudioTrack = allAudio.find((audio) => audio.Index === audioIndex);
|
||||
|
||||
const notTranscoding = !stream?.mediaSource.TranscodingUrl;
|
||||
const initOptions = [
|
||||
`--sub-text-scale=${settings.subtitleSize}`,
|
||||
`--start=${startPosition}`,
|
||||
];
|
||||
// if (
|
||||
// chosenSubtitleTrack &&
|
||||
// (notTranscoding || chosenSubtitleTrack.IsTextSubtitleStream)
|
||||
// ) {
|
||||
// const finalIndex = notTranscoding
|
||||
// ? allSubs.indexOf(chosenSubtitleTrack)
|
||||
// : textSubs.indexOf(chosenSubtitleTrack);
|
||||
// initOptions.push(`--sub-track=${finalIndex}`);
|
||||
// }
|
||||
const initOptions = [`--sub-text-scale=${settings.subtitleSize}`];
|
||||
if (
|
||||
chosenSubtitleTrack &&
|
||||
(notTranscoding || chosenSubtitleTrack.IsTextSubtitleStream)
|
||||
) {
|
||||
const finalIndex = notTranscoding
|
||||
? allSubs.indexOf(chosenSubtitleTrack)
|
||||
: textSubs.indexOf(chosenSubtitleTrack);
|
||||
initOptions.push(`--sub-track=${finalIndex}`);
|
||||
}
|
||||
|
||||
// if (notTranscoding && chosenAudioTrack) {
|
||||
// initOptions.push(`--audio-track=${allAudio.indexOf(chosenAudioTrack)}`);
|
||||
// }
|
||||
if (notTranscoding && chosenAudioTrack) {
|
||||
initOptions.push(`--audio-track=${allAudio.indexOf(chosenAudioTrack)}`);
|
||||
}
|
||||
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
|
||||
@@ -452,7 +426,7 @@ export default function page() {
|
||||
paddingRight: ignoreSafeAreas ? 0 : insets.right,
|
||||
}}
|
||||
>
|
||||
<MpvPlayerView
|
||||
<VlcPlayerView
|
||||
ref={videoRef}
|
||||
source={{
|
||||
uri: stream?.url || "",
|
||||
@@ -496,6 +470,7 @@ export default function page() {
|
||||
setIgnoreSafeAreas={setIgnoreSafeAreas}
|
||||
ignoreSafeAreas={ignoreSafeAreas}
|
||||
isVideoLoaded={isVideoLoaded}
|
||||
startPictureInPicture={videoRef?.current?.startPictureInPicture}
|
||||
play={videoRef.current?.play}
|
||||
pause={videoRef.current?.pause}
|
||||
seek={videoRef.current?.seekTo}
|
||||
|
||||
@@ -16,12 +16,7 @@ import {
|
||||
BACKGROUND_FETCH_TASK_SESSIONS,
|
||||
registerBackgroundFetchAsyncSessions,
|
||||
} from "@/utils/background-tasks";
|
||||
import {
|
||||
LogProvider,
|
||||
writeDebugLog,
|
||||
writeErrorLog,
|
||||
writeToLog,
|
||||
} from "@/utils/log";
|
||||
import { LogProvider, writeErrorLog, writeToLog } from "@/utils/log";
|
||||
import { storage } from "@/utils/mmkv";
|
||||
import { cancelJobById, getAllJobsByDeviceId } from "@/utils/optimize-server";
|
||||
import { ActionSheetProvider } from "@expo/react-native-action-sheet";
|
||||
@@ -36,7 +31,6 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
const BackgroundFetch = !Platform.isTV
|
||||
? require("expo-background-fetch")
|
||||
: null;
|
||||
import * as Device from "expo-device";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
const Notifications = !Platform.isTV ? require("expo-notifications") : null;
|
||||
import * as ScreenOrientation from "@/packages/expo-screen-orientation";
|
||||
@@ -166,7 +160,7 @@ if (!Platform.isTV) {
|
||||
|
||||
for (const job of jobs) {
|
||||
if (job.status === "completed") {
|
||||
const downloadUrl = `${url}download/${job.id}`;
|
||||
const downloadUrl = url + "download/" + job.id;
|
||||
const tasks = await BackGroundDownloader.checkForExistingDownloads();
|
||||
|
||||
if (tasks.find((task: { id: string }) => task.id === job.id)) {
|
||||
@@ -199,7 +193,7 @@ if (!Platform.isTV) {
|
||||
title: job.item.Name,
|
||||
body: "Download completed",
|
||||
data: {
|
||||
url: "/downloads",
|
||||
url: `/downloads`,
|
||||
},
|
||||
},
|
||||
trigger: null,
|
||||
@@ -213,7 +207,7 @@ if (!Platform.isTV) {
|
||||
title: job.item.Name,
|
||||
body: "Download failed",
|
||||
data: {
|
||||
url: "/downloads",
|
||||
url: `/downloads`,
|
||||
},
|
||||
},
|
||||
trigger: null,
|
||||
@@ -337,12 +331,9 @@ function Layout() {
|
||||
await registerBackgroundFetchAsyncSessions();
|
||||
}
|
||||
|
||||
// only create push token for real devices (pointless for emulators)
|
||||
if (Device.isDevice) {
|
||||
Notifications?.getExpoPushTokenAsync()
|
||||
.then((token: ExpoPushToken) => token && setExpoPushToken(token))
|
||||
.catch((reason: any) => console.log("Failed to get token", reason));
|
||||
}
|
||||
Notifications?.getExpoPushTokenAsync()
|
||||
.then((token: ExpoPushToken) => token && setExpoPushToken(token))
|
||||
.catch((reason: any) => console.log("Failed to get token", reason));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@@ -361,43 +352,7 @@ function Layout() {
|
||||
responseListener.current =
|
||||
Notifications?.addNotificationResponseReceivedListener(
|
||||
(response: NotificationResponse) => {
|
||||
// Currently the notifications supported by the plugin will send data for deep links.
|
||||
const { title, data } = response.notification.request.content;
|
||||
|
||||
writeDebugLog(
|
||||
`Notification ${title} opened`,
|
||||
response.notification.request.content,
|
||||
);
|
||||
|
||||
if (data && Object.keys(data).length > 0) {
|
||||
const type = data?.type?.toLower?.();
|
||||
const itemId = data?.id;
|
||||
|
||||
switch (type) {
|
||||
case "movie":
|
||||
router.push(`/(auth)/(tabs)/home/items/page?id=${itemId}`);
|
||||
break;
|
||||
case "episode":
|
||||
// We just clicked a notification for an individual episode.
|
||||
if (itemId) {
|
||||
router.push(`/(auth)/(tabs)/home/items/page?id=${itemId}`);
|
||||
}
|
||||
// summarized season notification for multiple episodes. Bring them to series season
|
||||
else {
|
||||
const seriesId = data.seriesId;
|
||||
const seasonIndex = data.seasonIndex;
|
||||
|
||||
if (seasonIndex) {
|
||||
router.push(
|
||||
`/(auth)/(tabs)/home/series/${seriesId}?seasonIndex=${seasonIndex}`,
|
||||
);
|
||||
} else {
|
||||
router.push(`/(auth)/(tabs)/home/series/${seriesId}`);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
console.log("Notification interacted with", response);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -218,14 +218,16 @@ const Login: React.FC = () => {
|
||||
<View className='px-4 -mt-20 w-full'>
|
||||
<View className='flex flex-col space-y-2'>
|
||||
<Text className='text-2xl font-bold -mb-2'>
|
||||
{serverName ? (
|
||||
<>
|
||||
{`${t("login.login_to_title")} `}
|
||||
<Text className='text-purple-600'>{serverName}</Text>
|
||||
</>
|
||||
) : (
|
||||
t("login.login_title")
|
||||
)}
|
||||
<>
|
||||
{serverName ? (
|
||||
<>
|
||||
{t("login.login_to_title") + " "}
|
||||
<Text className='text-purple-600'>{serverName}</Text>
|
||||
</>
|
||||
) : (
|
||||
t("login.login_title")
|
||||
)}
|
||||
</>
|
||||
</Text>
|
||||
<Text className='text-xs text-neutral-400'>
|
||||
{api.basePath}
|
||||
@@ -282,7 +284,7 @@ const Login: React.FC = () => {
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className='absolute bottom-0 left-0 w-full px-4 mb-2' />
|
||||
<View className='absolute bottom-0 left-0 w-full px-4 mb-2'></View>
|
||||
</View>
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -17,7 +17,9 @@ Number.prototype.bytesToReadable = function (decimals = 2) {
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
return `${Number.parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`;
|
||||
return (
|
||||
Number.parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i]
|
||||
);
|
||||
};
|
||||
|
||||
Number.prototype.secondsToMilliseconds = function () {
|
||||
|
||||
25
biome.json
25
biome.json
@@ -3,33 +3,22 @@
|
||||
"organizeImports": {
|
||||
"enabled": true
|
||||
},
|
||||
"files": {
|
||||
"ignore": [
|
||||
"node_modules",
|
||||
"ios",
|
||||
"android",
|
||||
"Streamyfin.app",
|
||||
"utils/jellyseerr",
|
||||
".expo"
|
||||
]
|
||||
},
|
||||
"files": {},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"style": {
|
||||
"useImportType": "off",
|
||||
"noNonNullAssertion": "off",
|
||||
"noParameterAssign": "off",
|
||||
"useLiteralEnumMembers": "off"
|
||||
},
|
||||
"complexity": {
|
||||
"noForEach": "off"
|
||||
"noNonNullAssertion": "off"
|
||||
},
|
||||
"recommended": true,
|
||||
"style": {
|
||||
"useImportType": "off",
|
||||
"noNonNullAssertion": "off"
|
||||
},
|
||||
"correctness": { "useExhaustiveDependencies": "off" },
|
||||
"suspicious": {
|
||||
"noExplicitAny": "off",
|
||||
"noArrayIndexKey": "off"
|
||||
"noExplicitAny": "off"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
208
bun.lock
208
bun.lock
@@ -44,13 +44,13 @@
|
||||
"expo-router": "~4.0.17",
|
||||
"expo-screen-orientation": "~8.0.4",
|
||||
"expo-sensors": "~14.0.2",
|
||||
"expo-sharing": "~13.1.0",
|
||||
"expo-splash-screen": "~0.29.22",
|
||||
"expo-status-bar": "~2.0.1",
|
||||
"expo-system-ui": "~4.0.8",
|
||||
"expo-task-manager": "~12.0.5",
|
||||
"expo-updates": "~0.26.17",
|
||||
"expo-web-browser": "~14.0.2",
|
||||
"ffmpeg-kit-react-native": "^6.0.2",
|
||||
"i18next": "^24.2.2",
|
||||
"jotai": "^2.11.3",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -62,7 +62,6 @@
|
||||
"react-native-awesome-slider": "^2.9.0",
|
||||
"react-native-bottom-tabs": "0.8.6",
|
||||
"react-native-circular-progress": "^1.4.1",
|
||||
"react-native-collapsible": "^1.6.2",
|
||||
"react-native-compressor": "^1.10.3",
|
||||
"react-native-country-flag": "^2.0.2",
|
||||
"react-native-device-info": "^14.0.4",
|
||||
@@ -108,8 +107,7 @@
|
||||
"@types/react-native-vector-icons": "^6.4.18",
|
||||
"@types/react-test-renderer": "^19.0.0",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^15.5.0",
|
||||
"patch-package": "^8.0.0",
|
||||
"postinstall-postinstall": "^2.1.0",
|
||||
"react-test-renderer": "19.0.0",
|
||||
"typescript": "~5.7.3",
|
||||
@@ -761,6 +759,8 @@
|
||||
|
||||
"@xmldom/xmldom": ["@xmldom/xmldom@0.7.13", "", {}, "sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g=="],
|
||||
|
||||
"@yarnpkg/lockfile": ["@yarnpkg/lockfile@1.1.0", "", {}, "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ=="],
|
||||
|
||||
"@zxing/text-encoding": ["@zxing/text-encoding@0.9.0", "", {}, "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA=="],
|
||||
|
||||
"abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
|
||||
@@ -781,7 +781,7 @@
|
||||
|
||||
"anser": ["anser@1.4.10", "", {}, "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww=="],
|
||||
|
||||
"ansi-escapes": ["ansi-escapes@7.0.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw=="],
|
||||
"ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
|
||||
|
||||
"ansi-fragments": ["ansi-fragments@0.2.1", "", { "dependencies": { "colorette": "^1.0.7", "slice-ansi": "^2.0.0", "strip-ansi": "^5.0.0" } }, "sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w=="],
|
||||
|
||||
@@ -939,8 +939,6 @@
|
||||
|
||||
"cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
|
||||
|
||||
"cli-truncate": ["cli-truncate@4.0.0", "", { "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" } }, "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA=="],
|
||||
|
||||
"client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
|
||||
|
||||
"cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
|
||||
@@ -957,7 +955,7 @@
|
||||
|
||||
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
|
||||
|
||||
"colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="],
|
||||
"colorette": ["colorette@1.4.0", "", {}, "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g=="],
|
||||
|
||||
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
||||
|
||||
@@ -1093,8 +1091,6 @@
|
||||
|
||||
"envinfo": ["envinfo@7.14.0", "", { "bin": { "envinfo": "dist/cli.js" } }, "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg=="],
|
||||
|
||||
"environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="],
|
||||
|
||||
"eol": ["eol@0.9.1", "", {}, "sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg=="],
|
||||
|
||||
"error-ex": ["error-ex@1.3.2", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="],
|
||||
@@ -1125,8 +1121,6 @@
|
||||
|
||||
"event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
|
||||
|
||||
"eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="],
|
||||
|
||||
"events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="],
|
||||
|
||||
"exec-async": ["exec-async@2.2.0", "", {}, "sha512-87OpwcEiMia/DeiKFzaQNBNFeN3XkkpYIh9FyOqq5mS2oKv3CBE67PXoEKcr6nodWdXNogTiQ0jE2NGuoffXPw=="],
|
||||
@@ -1173,7 +1167,7 @@
|
||||
|
||||
"expo-haptics": ["expo-haptics@14.0.1", "", { "peerDependencies": { "expo": "*" } }, "sha512-V81FZ7xRUfqM6uSI6FA1KnZ+QpEKnISqafob/xEfcx1ymwhm4V3snuLWWFjmAz+XaZQTqlYa8z3QbqEXz7G63w=="],
|
||||
|
||||
"expo-image": ["expo-image@2.0.7", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-kv40OIJOkItwznhdqFmKxTMC5O8GkpyTf8ng7Py4Hy6IBiH59dkeP6vUZQhzPhJOm5v1kZK4XldbskBosqzOug=="],
|
||||
"expo-image": ["expo-image@2.0.6", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-NHpIZmGnrPbyDadil6eK+sUgyFMQfapEVb7YaGgxSFWBUQ1rSpjqdIQrCD24IZTO9uSH8V+hMh2ROxrAjAixzQ=="],
|
||||
|
||||
"expo-json-utils": ["expo-json-utils@0.14.0", "", {}, "sha512-xjGfK9dL0B1wLnOqNkX0jM9p48Y0I5xEPzHude28LY67UmamUyAACkqhZGaPClyPNfdzczk7Ej6WaRMT3HfXvw=="],
|
||||
|
||||
@@ -1201,8 +1195,6 @@
|
||||
|
||||
"expo-sensors": ["expo-sensors@14.0.2", "", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-nCb1Q3ctb0oVTZ9p6eFmQ2fINa6KoxXXIhagPpdN0qR82p00YosP27IuyxjVB3fnCJFeC4TffNxNjBxwAUk+nA=="],
|
||||
|
||||
"expo-sharing": ["expo-sharing@13.1.3", "", { "peerDependencies": { "expo": "*" } }, "sha512-7O29Bdm95v6aBXBhrbKx9FBqL5loQcK0nvCMFSbZHMy1r7Z6vb6sTMsaGbvknfOH+tEzn+LIleTw5TreoxNT9g=="],
|
||||
|
||||
"expo-splash-screen": ["expo-splash-screen@0.29.22", "", { "dependencies": { "@expo/prebuild-config": "^8.0.27" }, "peerDependencies": { "expo": "*" } }, "sha512-f+bPpF06bqiuW1Fbrd3nxeaSsmTVTBEKEYe3epYt4IE6y4Ulli3qEUamMLlRQiDGuIXPU6zQlscpy2mdBUI5cA=="],
|
||||
|
||||
"expo-status-bar": ["expo-status-bar@2.0.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-AkIPX7jWHRPp83UBZ1iXtVvyr0g+DgBVvIXTtlmPtmUsm8Vq9Bb5IGj86PW8osuFlgoTVAg7HI/+Ok7yEYwiRg=="],
|
||||
@@ -1249,6 +1241,8 @@
|
||||
|
||||
"fetch-retry": ["fetch-retry@4.1.1", "", {}, "sha512-e6eB7zN6UBSwGVwrbWVH+gdLnkW9WwHhmq2YDK1Sh30pzx1onRVGBvogTlUeWxwTa+L86NYdo4hFkh7O8ZjSnA=="],
|
||||
|
||||
"ffmpeg-kit-react-native": ["ffmpeg-kit-react-native@6.0.2", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-r9uSmahq8TeyIb7fXf3ft+uUXyoeWRFa99+khjo0TAzWO9y0z9wU7eGnab9JLw1MmCB9v64o4yojNluJhVm9nQ=="],
|
||||
|
||||
"file-type": ["file-type@16.5.4", "", { "dependencies": { "readable-web-to-node-stream": "^3.0.0", "strtok3": "^6.2.4", "token-types": "^4.1.1" } }, "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw=="],
|
||||
|
||||
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
|
||||
@@ -1261,6 +1255,8 @@
|
||||
|
||||
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
|
||||
|
||||
"find-yarn-workspace-root": ["find-yarn-workspace-root@2.0.0", "", { "dependencies": { "micromatch": "^4.0.2" } }, "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ=="],
|
||||
|
||||
"flow-enums-runtime": ["flow-enums-runtime@0.0.6", "", {}, "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw=="],
|
||||
|
||||
"flow-parser": ["flow-parser@0.261.2", "", {}, "sha512-RtunoakA3YjtpAxPSOBVW6lmP5NYmETwkpAfNkdr8Ovf86ENkbD3mtPWnswFTIUtRvjwv0i8ZSkHK+AzsUg1JA=="],
|
||||
@@ -1293,8 +1289,6 @@
|
||||
|
||||
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
|
||||
|
||||
"get-east-asian-width": ["get-east-asian-width@1.3.0", "", {}, "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ=="],
|
||||
|
||||
"get-intrinsic": ["get-intrinsic@1.2.7", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", "get-proto": "^1.0.0", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA=="],
|
||||
|
||||
"get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="],
|
||||
@@ -1349,8 +1343,6 @@
|
||||
|
||||
"human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
|
||||
|
||||
"husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="],
|
||||
|
||||
"hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="],
|
||||
|
||||
"i18next": ["i18next@24.2.2", "", { "dependencies": { "@babel/runtime": "^7.23.2" }, "peerDependencies": { "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-NE6i86lBCKRYZa5TaUDkU5S4HFgLIEJRLr3Whf2psgaxBleQ2LC1YW1Vc+SCgkAW7VEzndT6al6+CzegSUHcTQ=="],
|
||||
@@ -1433,6 +1425,8 @@
|
||||
|
||||
"is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="],
|
||||
|
||||
"isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"isobject": ["isobject@3.0.1", "", {}, "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="],
|
||||
@@ -1495,12 +1489,18 @@
|
||||
|
||||
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||
|
||||
"json-stable-stringify": ["json-stable-stringify@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "isarray": "^2.0.5", "jsonify": "^0.0.1", "object-keys": "^1.1.1" } }, "sha512-Lp6HbbBgosLmJbjx0pBLbgvx68FaFU1sdkmBuckmhhJ88kL13OA51CDtR2yJB50eCNMH9wRqtQNNiAqQH4YXnA=="],
|
||||
|
||||
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
|
||||
|
||||
"jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="],
|
||||
|
||||
"jsonify": ["jsonify@0.0.1", "", {}, "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg=="],
|
||||
|
||||
"kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="],
|
||||
|
||||
"klaw-sync": ["klaw-sync@6.0.0", "", { "dependencies": { "graceful-fs": "^4.1.11" } }, "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ=="],
|
||||
|
||||
"kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
|
||||
|
||||
"leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="],
|
||||
@@ -1529,14 +1529,10 @@
|
||||
|
||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.27.0", "", { "os": "win32", "cpu": "x64" }, "sha512-/OJLj94Zm/waZShL8nB5jsNj3CfNATLCTyFxZyouilfTmSoLDX7VlVAmhPHoZWVFp4vdmoiEbPEYC8HID3m6yw=="],
|
||||
|
||||
"lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],
|
||||
"lilconfig": ["lilconfig@2.1.0", "", {}, "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ=="],
|
||||
|
||||
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
|
||||
|
||||
"lint-staged": ["lint-staged@15.5.0", "", { "dependencies": { "chalk": "^5.4.1", "commander": "^13.1.0", "debug": "^4.4.0", "execa": "^8.0.1", "lilconfig": "^3.1.3", "listr2": "^8.2.5", "micromatch": "^4.0.8", "pidtree": "^0.6.0", "string-argv": "^0.3.2", "yaml": "^2.7.0" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-WyCzSbfYGhK7cU+UuDDkzUiytbfbi0ZdPy2orwtM75P3WTtQBzmG40cCxIa8Ii2+XjfxzLH6Be46tUfWS85Xfg=="],
|
||||
|
||||
"listr2": ["listr2@8.2.5", "", { "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ=="],
|
||||
|
||||
"load-bmfont": ["load-bmfont@1.4.2", "", { "dependencies": { "buffer-equal": "0.0.1", "mime": "^1.3.4", "parse-bmfont-ascii": "^1.0.3", "parse-bmfont-binary": "^1.0.5", "parse-bmfont-xml": "^1.1.4", "phin": "^3.7.1", "xhr": "^2.0.1", "xtend": "^4.0.0" } }, "sha512-qElWkmjW9Oq1F9EI5Gt7aD9zcdHb9spJCW1L/dmPf7KzCCEJxq8nhHz5eCgI9aMf7vrG/wyaCqdsI+Iy9ZTlog=="],
|
||||
|
||||
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
||||
@@ -1549,8 +1545,6 @@
|
||||
|
||||
"log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="],
|
||||
|
||||
"log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="],
|
||||
|
||||
"logkitty": ["logkitty@0.7.1", "", { "dependencies": { "ansi-fragments": "^0.2.1", "dayjs": "^1.8.15", "yargs": "^15.1.0" }, "bin": { "logkitty": "bin/logkitty.js" } }, "sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ=="],
|
||||
|
||||
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
|
||||
@@ -1615,8 +1609,6 @@
|
||||
|
||||
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
||||
|
||||
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
|
||||
|
||||
"min-document": ["min-document@2.19.0", "", { "dependencies": { "dom-walk": "^0.1.0" } }, "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ=="],
|
||||
|
||||
"minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
@@ -1703,7 +1695,7 @@
|
||||
|
||||
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
|
||||
|
||||
"open": ["open@6.4.0", "", { "dependencies": { "is-wsl": "^1.1.0" } }, "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg=="],
|
||||
"open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="],
|
||||
|
||||
"ora": ["ora@5.4.1", "", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="],
|
||||
|
||||
@@ -1741,6 +1733,8 @@
|
||||
|
||||
"password-prompt": ["password-prompt@1.1.3", "", { "dependencies": { "ansi-escapes": "^4.3.2", "cross-spawn": "^7.0.3" } }, "sha512-HkrjG2aJlvF0t2BMH0e2LB/EHf3Lcq3fNMzy4GYHcQblAvOl+QQji1Lx7WRBMqpVK8p+KR7bCg7oqAMXtdgqyw=="],
|
||||
|
||||
"patch-package": ["patch-package@8.0.0", "", { "dependencies": { "@yarnpkg/lockfile": "^1.1.0", "chalk": "^4.1.2", "ci-info": "^3.7.0", "cross-spawn": "^7.0.3", "find-yarn-workspace-root": "^2.0.0", "fs-extra": "^9.0.0", "json-stable-stringify": "^1.0.2", "klaw-sync": "^6.0.0", "minimist": "^1.2.6", "open": "^7.4.2", "rimraf": "^2.6.3", "semver": "^7.5.3", "slash": "^2.0.0", "tmp": "^0.0.33", "yaml": "^2.2.2" }, "bin": { "patch-package": "index.js" } }, "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA=="],
|
||||
|
||||
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
|
||||
|
||||
"path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="],
|
||||
@@ -1759,9 +1753,7 @@
|
||||
|
||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||
|
||||
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"pidtree": ["pidtree@0.6.0", "", { "bin": { "pidtree": "bin/pidtree.js" } }, "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g=="],
|
||||
"picomatch": ["picomatch@3.0.1", "", {}, "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag=="],
|
||||
|
||||
"pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="],
|
||||
|
||||
@@ -1859,8 +1851,6 @@
|
||||
|
||||
"react-native-circular-progress": ["react-native-circular-progress@1.4.1", "", { "dependencies": { "prop-types": "^15.8.1" }, "peerDependencies": { "react": ">=16.0.0", "react-native": ">=0.50.0", "react-native-svg": ">=7.0.0" } }, "sha512-HEzvI0WPuWvsCgWE3Ff2HBTMgAEQB2GvTFw0KHyD/t1STAlDDRiolu0mEGhVvihKR3jJu3v3V4qzvSklY/7XzQ=="],
|
||||
|
||||
"react-native-collapsible": ["react-native-collapsible@1.6.2", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-MCOBVJWqHNjnDaGkvxX997VONmJeebh6wyJxnHEgg0L1PrlcXU1e/bo6eK+CDVFuMrCafw8Qh4DOv/C4V/+Iew=="],
|
||||
|
||||
"react-native-compressor": ["react-native-compressor@1.10.4", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-58gbmJ+8IvsKP8JKK1E8XW5trfQY3dNuH7S0hYw0tSRQc6l0GZ3k8TYtoUbySOc1xcQSrUo51o0Chwe8x7mUTg=="],
|
||||
|
||||
"react-native-country-flag": ["react-native-country-flag@2.0.2", "", {}, "sha512-5LMWxS79ZQ0Q9ntYgDYzWp794+HcQGXQmzzZNBR1AT7z5HcJHtX7rlk8RHi7RVzfp5gW6plWSZ4dKjRpu/OafQ=="],
|
||||
@@ -1981,9 +1971,7 @@
|
||||
|
||||
"reusify": ["reusify@1.0.4", "", {}, "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="],
|
||||
|
||||
"rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
|
||||
|
||||
"rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
|
||||
"rimraf": ["rimraf@2.7.1", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w=="],
|
||||
|
||||
"rtl-detect": ["rtl-detect@1.1.2", "", {}, "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ=="],
|
||||
|
||||
@@ -2049,9 +2037,9 @@
|
||||
|
||||
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
||||
|
||||
"slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||
"slash": ["slash@2.0.0", "", {}, "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A=="],
|
||||
|
||||
"slice-ansi": ["slice-ansi@5.0.0", "", { "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" } }, "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ=="],
|
||||
"slice-ansi": ["slice-ansi@2.1.0", "", { "dependencies": { "ansi-styles": "^3.2.0", "astral-regex": "^1.0.0", "is-fullwidth-code-point": "^2.0.0" } }, "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ=="],
|
||||
|
||||
"slugify": ["slugify@1.6.6", "", {}, "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw=="],
|
||||
|
||||
@@ -2085,8 +2073,6 @@
|
||||
|
||||
"strict-uri-encode": ["strict-uri-encode@2.0.0", "", {}, "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="],
|
||||
|
||||
"string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="],
|
||||
|
||||
"string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
@@ -2263,7 +2249,7 @@
|
||||
|
||||
"wonka": ["wonka@6.3.4", "", {}, "sha512-CjpbqNtBGNAeyNS/9W6q3kSkKE52+FjIj7AkFlLr11s/VWGUu6a2CdYSdGxocIhIVjaW/zchesBQUKPVU69Cqg=="],
|
||||
|
||||
"wrap-ansi": ["wrap-ansi@9.0.0", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q=="],
|
||||
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
@@ -2327,12 +2313,8 @@
|
||||
|
||||
"@expo/cli/ora": ["ora@3.4.0", "", { "dependencies": { "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-spinners": "^2.0.0", "log-symbols": "^2.2.0", "strip-ansi": "^5.2.0", "wcwidth": "^1.0.1" } }, "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg=="],
|
||||
|
||||
"@expo/cli/picomatch": ["picomatch@3.0.1", "", {}, "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag=="],
|
||||
|
||||
"@expo/cli/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
|
||||
"@expo/cli/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
"@expo/cli/ws": ["ws@8.18.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w=="],
|
||||
|
||||
"@expo/config/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
||||
@@ -2341,6 +2323,8 @@
|
||||
|
||||
"@expo/config-plugins/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
|
||||
"@expo/config-plugins/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||
|
||||
"@expo/devcert/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||
|
||||
"@expo/devcert/sudo-prompt": ["sudo-prompt@8.2.5", "", {}, "sha512-rlBo3HU/1zAJUrkY6jNxDOC9eVYliG6nS4JA8u8KAshITd07tafMc/Br7xQwCSseXwJ2iCcHCE8SNWX3q8Z+kw=="],
|
||||
@@ -2389,6 +2373,8 @@
|
||||
|
||||
"@istanbuljs/load-nyc-config/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
|
||||
|
||||
"@jest/transform/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||
|
||||
"@jest/transform/write-file-atomic": ["write-file-atomic@4.0.2", "", { "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" } }, "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg=="],
|
||||
|
||||
"@npmcli/fs/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
@@ -2421,6 +2407,8 @@
|
||||
|
||||
"@react-native-community/cli-server-api/pretty-format": ["pretty-format@26.6.2", "", { "dependencies": { "@jest/types": "^26.6.2", "ansi-regex": "^5.0.0", "ansi-styles": "^4.0.0", "react-is": "^17.0.1" } }, "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg=="],
|
||||
|
||||
"@react-native-community/cli-tools/open": ["open@6.4.0", "", { "dependencies": { "is-wsl": "^1.1.0" } }, "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg=="],
|
||||
|
||||
"@react-native-community/cli-tools/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
|
||||
"@react-native/babel-plugin-codegen/@react-native/codegen": ["@react-native/codegen@0.76.7", "", { "dependencies": { "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.23.1", "invariant": "^2.2.4", "jscodeshift": "^0.14.0", "mkdirp": "^0.5.1", "nullthrows": "^1.1.1", "yargs": "^17.6.2" }, "peerDependencies": { "@babel/preset-env": "^7.1.6" } }, "sha512-FAn585Ll65YvkSrKDyAcsdjHhhAGiMlSTUpHh0x7J5ntudUns+voYms0xMP+pEPt0XuLdjhD7zLIIlAWP407+g=="],
|
||||
@@ -2435,8 +2423,6 @@
|
||||
|
||||
"@react-native/dev-middleware/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||
|
||||
"@react-native/dev-middleware/open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="],
|
||||
|
||||
"@react-native/metro-babel-transformer/@react-native/babel-preset": ["@react-native/babel-preset@0.77.0", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.24.7", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-computed-properties": "^7.24.7", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-function-name": "^7.25.1", "@babel/plugin-transform-literals": "^7.25.2", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-numeric-separator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", "@react-native/babel-plugin-codegen": "0.77.0", "babel-plugin-syntax-hermes-parser": "0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-Z4yxE66OvPyQ/iAlaETI1ptRLcDm7Tk6ZLqtCPuUX3AMg+JNgIA86979T4RSk486/JrBUBH5WZe2xjj7eEHXsA=="],
|
||||
|
||||
"@react-navigation/core/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
||||
@@ -2445,9 +2431,11 @@
|
||||
|
||||
"accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
|
||||
|
||||
"ansi-fragments/colorette": ["colorette@1.4.0", "", {}, "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g=="],
|
||||
"ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
|
||||
|
||||
"ansi-fragments/slice-ansi": ["slice-ansi@2.1.0", "", { "dependencies": { "ansi-styles": "^3.2.0", "astral-regex": "^1.0.0", "is-fullwidth-code-point": "^2.0.0" } }, "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ=="],
|
||||
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"babel-jest/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||
|
||||
"better-opn/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="],
|
||||
|
||||
@@ -2459,12 +2447,10 @@
|
||||
|
||||
"chromium-edge-launcher/mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
|
||||
|
||||
"cli-truncate/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
||||
"chromium-edge-launcher/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
|
||||
|
||||
"cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
"compressible/mime-db": ["mime-db@1.53.0", "", {}, "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg=="],
|
||||
|
||||
"compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||
@@ -2475,6 +2461,10 @@
|
||||
|
||||
"default-gateway/execa": ["execa@1.0.0", "", { "dependencies": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" } }, "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA=="],
|
||||
|
||||
"del/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
|
||||
|
||||
"del/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||
|
||||
"error-ex/is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="],
|
||||
|
||||
"expo-build-properties/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
@@ -2503,6 +2493,8 @@
|
||||
|
||||
"foreground-child/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
||||
|
||||
"globby/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||
|
||||
"hoist-non-react-statics/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||
|
||||
"hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
@@ -2511,6 +2503,10 @@
|
||||
|
||||
"import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
||||
|
||||
"jest-message-util/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||
|
||||
"jest-util/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||
|
||||
"jscodeshift/tmp": ["tmp@0.2.3", "", {}, "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w=="],
|
||||
@@ -2519,22 +2515,10 @@
|
||||
|
||||
"lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||
|
||||
"lint-staged/chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="],
|
||||
|
||||
"lint-staged/commander": ["commander@13.1.0", "", {}, "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="],
|
||||
|
||||
"lint-staged/execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
|
||||
|
||||
"load-bmfont/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="],
|
||||
|
||||
"load-bmfont/phin": ["phin@3.7.1", "", { "dependencies": { "centra": "^2.7.0" } }, "sha512-GEazpTWwTZaEQ9RhL7Nyz0WwqilbqgLahDM3D0hxWwmVDI52nXEybHqiN6/elwpkJBhcuj+WbBu+QfT0uhPGfQ=="],
|
||||
|
||||
"log-update/cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
|
||||
|
||||
"log-update/slice-ansi": ["slice-ansi@7.1.0", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg=="],
|
||||
|
||||
"log-update/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
|
||||
|
||||
"logkitty/yargs": ["yargs@15.4.1", "", { "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.2" } }, "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A=="],
|
||||
|
||||
"make-dir/pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="],
|
||||
@@ -2551,6 +2535,8 @@
|
||||
|
||||
"metro-file-map/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||
|
||||
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
@@ -2567,13 +2553,13 @@
|
||||
|
||||
"npm-package-arg/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
|
||||
"open/is-wsl": ["is-wsl@1.1.0", "", {}, "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw=="],
|
||||
|
||||
"ora/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"parse-bmfont-xml/xml2js": ["xml2js@0.5.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA=="],
|
||||
|
||||
"password-prompt/ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
|
||||
"patch-package/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="],
|
||||
|
||||
"patch-package/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
||||
|
||||
"path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
@@ -2585,6 +2571,8 @@
|
||||
|
||||
"postcss-css-variables/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
||||
|
||||
"postcss-load-config/lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],
|
||||
|
||||
"pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
|
||||
|
||||
"pretty-format/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
||||
@@ -2621,6 +2609,8 @@
|
||||
|
||||
"readable-web-to-node-stream/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="],
|
||||
|
||||
"readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="],
|
||||
@@ -2639,9 +2629,9 @@
|
||||
|
||||
"simple-plist/bplist-parser": ["bplist-parser@0.3.1", "", { "dependencies": { "big-integer": "1.6.x" } }, "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA=="],
|
||||
|
||||
"slice-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
|
||||
"slice-ansi/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
||||
|
||||
"slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@4.0.0", "", {}, "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ=="],
|
||||
"slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@2.0.0", "", {}, "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w=="],
|
||||
|
||||
"source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
@@ -2657,8 +2647,6 @@
|
||||
|
||||
"tailwindcss/arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="],
|
||||
|
||||
"tailwindcss/lilconfig": ["lilconfig@2.1.0", "", {}, "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ=="],
|
||||
|
||||
"tailwindcss/postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="],
|
||||
|
||||
"tar/fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="],
|
||||
@@ -2673,8 +2661,6 @@
|
||||
|
||||
"tempy/type-fest": ["type-fest@0.16.0", "", {}, "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg=="],
|
||||
|
||||
"terminal-link/ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
|
||||
|
||||
"terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
||||
|
||||
"test-exclude/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||
@@ -2685,11 +2671,7 @@
|
||||
|
||||
"whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
|
||||
|
||||
"wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
|
||||
|
||||
"wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
||||
|
||||
"wrap-ansi/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
|
||||
"wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
@@ -2711,8 +2693,6 @@
|
||||
|
||||
"@expo/cli/ora/log-symbols": ["log-symbols@2.2.0", "", { "dependencies": { "chalk": "^2.0.1" } }, "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg=="],
|
||||
|
||||
"@expo/cli/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"@expo/fingerprint/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
||||
|
||||
"@expo/image-utils/fs-extra/jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="],
|
||||
@@ -2753,6 +2733,8 @@
|
||||
|
||||
"@react-native-community/cli-server-api/pretty-format/react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
|
||||
|
||||
"@react-native-community/cli-tools/open/is-wsl": ["is-wsl@1.1.0", "", {}, "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw=="],
|
||||
|
||||
"@react-native/babel-plugin-codegen/@react-native/codegen/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||
|
||||
"@react-native/babel-plugin-codegen/@react-native/codegen/hermes-parser": ["hermes-parser@0.23.1", "", { "dependencies": { "hermes-estree": "0.23.1" } }, "sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA=="],
|
||||
@@ -2763,21 +2745,13 @@
|
||||
|
||||
"@react-native/community-cli-plugin/@react-native/dev-middleware/@react-native/debugger-frontend": ["@react-native/debugger-frontend@0.77.0", "", {}, "sha512-glOvSEjCbVXw+KtfiOAmrq21FuLE1VsmBsyT7qud4KWbXP43aUEhzn70mWyFuiIdxnzVPKe2u8iWTQTdJksR1w=="],
|
||||
|
||||
"@react-native/community-cli-plugin/@react-native/dev-middleware/open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="],
|
||||
|
||||
"@react-native/community-cli-plugin/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
||||
"@react-native/dev-middleware/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
||||
"@react-native/metro-babel-transformer/@react-native/babel-preset/@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.77.0", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.77.0" } }, "sha512-5TYPn1k+jdDOZJU4EVb1kZ0p9TCVICXK3uplRev5Gul57oWesAaiWGZOzfRS3lonWeuR4ij8v8PFfIHOaq0vmA=="],
|
||||
|
||||
"ansi-fragments/slice-ansi/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
||||
|
||||
"ansi-fragments/slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@2.0.0", "", {}, "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w=="],
|
||||
|
||||
"cli-truncate/string-width/emoji-regex": ["emoji-regex@10.4.0", "", {}, "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="],
|
||||
|
||||
"cli-truncate/string-width/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
|
||||
"chromium-edge-launcher/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||
|
||||
"compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
||||
@@ -2791,6 +2765,8 @@
|
||||
|
||||
"default-gateway/execa/npm-run-path": ["npm-run-path@2.0.2", "", { "dependencies": { "path-key": "^2.0.0" } }, "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw=="],
|
||||
|
||||
"del/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||
|
||||
"expo-modules-autolinking/fs-extra/jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="],
|
||||
|
||||
"expo-modules-autolinking/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
|
||||
@@ -2801,28 +2777,6 @@
|
||||
|
||||
"lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
||||
"lint-staged/execa/get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="],
|
||||
|
||||
"lint-staged/execa/human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="],
|
||||
|
||||
"lint-staged/execa/is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="],
|
||||
|
||||
"lint-staged/execa/npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="],
|
||||
|
||||
"lint-staged/execa/onetime": ["onetime@6.0.0", "", { "dependencies": { "mimic-fn": "^4.0.0" } }, "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ=="],
|
||||
|
||||
"lint-staged/execa/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
||||
|
||||
"lint-staged/execa/strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
|
||||
|
||||
"log-update/cli-cursor/restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="],
|
||||
|
||||
"log-update/slice-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
|
||||
|
||||
"log-update/slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.0.0", "", { "dependencies": { "get-east-asian-width": "^1.0.0" } }, "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA=="],
|
||||
|
||||
"log-update/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
|
||||
|
||||
"logkitty/yargs/cliui": ["cliui@6.0.0", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } }, "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ=="],
|
||||
|
||||
"logkitty/yargs/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],
|
||||
@@ -2849,7 +2803,9 @@
|
||||
|
||||
"parse-bmfont-xml/xml2js/xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="],
|
||||
|
||||
"password-prompt/ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
|
||||
"patch-package/fs-extra/jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="],
|
||||
|
||||
"patch-package/fs-extra/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
|
||||
|
||||
"pkg-dir/find-up/locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="],
|
||||
|
||||
@@ -2863,18 +2819,14 @@
|
||||
|
||||
"send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
||||
"slice-ansi/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
|
||||
"tar/fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"temp/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||
|
||||
"terminal-link/ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
|
||||
|
||||
"test-exclude/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
||||
|
||||
"wrap-ansi/string-width/emoji-regex": ["emoji-regex@10.4.0", "", {}, "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="],
|
||||
|
||||
"wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
|
||||
|
||||
"@babel/highlight/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
|
||||
"@babel/highlight/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
||||
@@ -2909,9 +2861,7 @@
|
||||
|
||||
"@react-native/codegen/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
||||
|
||||
"ansi-fragments/slice-ansi/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
|
||||
"cli-truncate/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
|
||||
"chromium-edge-launcher/rimraf/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||
|
||||
"default-gateway/execa/cross-spawn/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="],
|
||||
|
||||
@@ -2923,13 +2873,7 @@
|
||||
|
||||
"default-gateway/execa/npm-run-path/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="],
|
||||
|
||||
"lint-staged/execa/npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
||||
|
||||
"lint-staged/execa/onetime/mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="],
|
||||
|
||||
"log-update/cli-cursor/restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
|
||||
|
||||
"log-update/cli-cursor/restore-cursor/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
||||
"del/rimraf/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||
|
||||
"logkitty/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
@@ -2953,6 +2897,8 @@
|
||||
|
||||
"rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
||||
|
||||
"slice-ansi/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||
|
||||
"temp/rimraf/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||
|
||||
"@babel/highlight/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||
@@ -2977,10 +2923,12 @@
|
||||
|
||||
"@react-native/babel-plugin-codegen/@react-native/codegen/jscodeshift/recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"ansi-fragments/slice-ansi/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||
"chromium-edge-launcher/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
||||
|
||||
"default-gateway/execa/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="],
|
||||
|
||||
"del/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
|
||||
|
||||
"logkitty/yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
||||
|
||||
"pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
||||
|
||||
@@ -73,7 +73,7 @@ export const Button: React.FC<PropsWithChildren<ButtonProps>> = ({
|
||||
flex flex-row items-center justify-between w-full
|
||||
${justify === "between" ? "justify-between" : "justify-center"}`}
|
||||
>
|
||||
{iconLeft ? iconLeft : <View className='w-4' />}
|
||||
{iconLeft ? iconLeft : <View className='w-4'></View>}
|
||||
<Text
|
||||
className={`
|
||||
text-white font-bold text-base
|
||||
@@ -85,7 +85,7 @@ export const Button: React.FC<PropsWithChildren<ButtonProps>> = ({
|
||||
>
|
||||
{children}
|
||||
</Text>
|
||||
{iconRight ? iconRight : <View className='w-4' />}
|
||||
{iconRight ? iconRight : <View className='w-4'></View>}
|
||||
</View>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
|
||||
@@ -27,39 +27,33 @@ const ContinueWatchingPoster: React.FC<ContinueWatchingPosterProps> = ({
|
||||
* Get horizontal poster for movie and episode, with failover to primary.
|
||||
*/
|
||||
const url = useMemo(() => {
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
if (!api) return;
|
||||
if (item.Type === "Episode" && useEpisodePoster) {
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
|
||||
}
|
||||
if (item.Type === "Episode") {
|
||||
if (item.ParentBackdropItemId && item.ParentThumbImageTag) {
|
||||
if (item.ParentBackdropItemId && item.ParentThumbImageTag)
|
||||
return `${api?.basePath}/Items/${item.ParentBackdropItemId}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ParentThumbImageTag}`;
|
||||
}
|
||||
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
|
||||
else
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
|
||||
}
|
||||
if (item.Type === "Movie") {
|
||||
if (item.ImageTags?.Thumb) {
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ImageTags?.Thumb}`;
|
||||
}
|
||||
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
|
||||
if (item.ImageTags?.["Thumb"])
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ImageTags?.["Thumb"]}`;
|
||||
else
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
|
||||
}
|
||||
if (item.Type === "Program") {
|
||||
if (item.ImageTags?.Thumb) {
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ImageTags?.Thumb}`;
|
||||
}
|
||||
if (item.ImageTags?.["Thumb"])
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ImageTags?.["Thumb"]}`;
|
||||
else
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
|
||||
}
|
||||
|
||||
if (item.ImageTags?.["Thumb"])
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ImageTags?.["Thumb"]}`;
|
||||
else
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
|
||||
}
|
||||
|
||||
if (item.ImageTags?.Thumb) {
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ImageTags?.Thumb}`;
|
||||
}
|
||||
|
||||
return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
|
||||
}, [item]);
|
||||
|
||||
const progress = useMemo(() => {
|
||||
@@ -70,12 +64,15 @@ const ContinueWatchingPoster: React.FC<ContinueWatchingPosterProps> = ({
|
||||
const total = endDate.getTime() - startDate.getTime();
|
||||
const elapsed = now.getTime() - startDate.getTime();
|
||||
return (elapsed / total) * 100;
|
||||
} else {
|
||||
return item.UserData?.PlayedPercentage || 0;
|
||||
}
|
||||
return item.UserData?.PlayedPercentage || 0;
|
||||
}, [item]);
|
||||
|
||||
if (!url)
|
||||
return <View className='aspect-video border border-neutral-800 w-44' />;
|
||||
return (
|
||||
<View className='aspect-video border border-neutral-800 w-44'></View>
|
||||
);
|
||||
|
||||
return (
|
||||
<View
|
||||
@@ -105,16 +102,14 @@ const ContinueWatchingPoster: React.FC<ContinueWatchingPosterProps> = ({
|
||||
{progress > 0 && (
|
||||
<>
|
||||
<View
|
||||
className={
|
||||
"absolute w-100 bottom-0 left-0 h-1 bg-neutral-700 opacity-80 w-full"
|
||||
}
|
||||
/>
|
||||
className={`absolute w-100 bottom-0 left-0 h-1 bg-neutral-700 opacity-80 w-full`}
|
||||
></View>
|
||||
<View
|
||||
style={{
|
||||
width: `${progress}%`,
|
||||
}}
|
||||
className={"absolute bottom-0 left-0 h-1 bg-purple-600 w-full"}
|
||||
/>
|
||||
className={`absolute bottom-0 left-0 h-1 bg-purple-600 w-full`}
|
||||
></View>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//import { useRemuxHlsToMp4 } from "@/hooks/useRemuxHlsToMp4";
|
||||
import { useRemuxHlsToMp4 } from "@/hooks/useRemuxHlsToMp4";
|
||||
import { useDownload } from "@/providers/DownloadProvider";
|
||||
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
|
||||
import { queueActions, queueAtom } from "@/utils/atoms/queue";
|
||||
@@ -59,7 +59,7 @@ export const DownloadItems: React.FC<DownloadProps> = ({
|
||||
const [settings] = useSettings();
|
||||
|
||||
const { processes, startBackgroundDownload, downloadedFiles } = useDownload();
|
||||
//const { startRemuxing } = useRemuxHlsToMp4();
|
||||
const { startRemuxing } = useRemuxHlsToMp4();
|
||||
|
||||
const [selectedMediaSource, setSelectedMediaSource] = useState<
|
||||
MediaSourceInfo | undefined | null
|
||||
@@ -113,7 +113,7 @@ export const DownloadItems: React.FC<DownloadProps> = ({
|
||||
);
|
||||
|
||||
const progress = useMemo(() => {
|
||||
if (itemIds.length === 1)
|
||||
if (itemIds.length == 1)
|
||||
return itemsProcesses.reduce((acc, p) => acc + p.progress, 0);
|
||||
return (
|
||||
((itemIds.length -
|
||||
@@ -126,7 +126,7 @@ export const DownloadItems: React.FC<DownloadProps> = ({
|
||||
const itemsQueued = useMemo(() => {
|
||||
return (
|
||||
itemsNotDownloaded.length > 0 &&
|
||||
itemsNotDownloaded.every((p) => queue.some((q) => p.Id === q.item.Id))
|
||||
itemsNotDownloaded.every((p) => queue.some((q) => p.Id == q.item.Id))
|
||||
);
|
||||
}, [queue, itemsNotDownloaded]);
|
||||
const navigateToDownloads = () => router.push("/downloads");
|
||||
@@ -230,11 +230,12 @@ export const DownloadItems: React.FC<DownloadProps> = ({
|
||||
|
||||
if (!url || !source) throw new Error("No url");
|
||||
|
||||
saveDownloadItemInfoToDiskTmp(item, source, url);
|
||||
|
||||
if (usingOptimizedServer) {
|
||||
saveDownloadItemInfoToDiskTmp(item, source, url);
|
||||
await startBackgroundDownload(url, item, source);
|
||||
} else {
|
||||
//await startRemuxing(item, url, source);
|
||||
await startRemuxing(item, url, source);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -249,7 +250,7 @@ export const DownloadItems: React.FC<DownloadProps> = ({
|
||||
maxBitrate,
|
||||
usingOptimizedServer,
|
||||
startBackgroundDownload,
|
||||
//startRemuxing,
|
||||
startRemuxing,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -278,7 +279,7 @@ export const DownloadItems: React.FC<DownloadProps> = ({
|
||||
);
|
||||
|
||||
const renderButtonContent = () => {
|
||||
if (processes.length > 0 && itemsProcesses.length > 0) {
|
||||
if (processes && itemsProcesses.length > 0) {
|
||||
return progress === 0 ? (
|
||||
<Loader />
|
||||
) : (
|
||||
@@ -292,17 +293,13 @@ export const DownloadItems: React.FC<DownloadProps> = ({
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
if (itemsQueued) {
|
||||
} else if (itemsQueued) {
|
||||
return <Ionicons name='hourglass' size={24} color='white' />;
|
||||
}
|
||||
|
||||
if (allItemsDownloaded) {
|
||||
} else if (allItemsDownloaded) {
|
||||
return <DownloadedIconComponent />;
|
||||
} else {
|
||||
return <MissingDownloadIconComponent />;
|
||||
}
|
||||
|
||||
return <MissingDownloadIconComponent />;
|
||||
};
|
||||
|
||||
const onButtonPress = () => {
|
||||
@@ -408,7 +405,7 @@ export const DownloadSingleItem: React.FC<{
|
||||
<DownloadItems
|
||||
size={size}
|
||||
title={
|
||||
item.Type === "Episode"
|
||||
item.Type == "Episode"
|
||||
? t("item_card.download.download_episode")
|
||||
: t("item_card.download.download_movie")
|
||||
}
|
||||
|
||||
@@ -147,20 +147,22 @@ export const ItemContent: React.FC<{ item: BaseItemDto }> = React.memo(
|
||||
</View>
|
||||
}
|
||||
logo={
|
||||
logoUrl ? (
|
||||
<Image
|
||||
source={{
|
||||
uri: logoUrl,
|
||||
}}
|
||||
style={{
|
||||
height: 130,
|
||||
width: "100%",
|
||||
resizeMode: "contain",
|
||||
}}
|
||||
onLoad={() => setLoadingLogo(false)}
|
||||
onError={() => setLoadingLogo(false)}
|
||||
/>
|
||||
) : null
|
||||
<>
|
||||
{logoUrl ? (
|
||||
<Image
|
||||
source={{
|
||||
uri: logoUrl,
|
||||
}}
|
||||
style={{
|
||||
height: 130,
|
||||
width: "100%",
|
||||
resizeMode: "contain",
|
||||
}}
|
||||
onLoad={() => setLoadingLogo(false)}
|
||||
onError={() => setLoadingLogo(false)}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<View className='flex flex-col bg-transparent shrink'>
|
||||
|
||||
@@ -237,5 +237,5 @@ const formatFileSize = (bytes?: number | null) => {
|
||||
const i = Number.parseInt(
|
||||
Math.floor(Math.log(bytes) / Math.log(1024)).toString(),
|
||||
);
|
||||
return `${Math.round((bytes / 1024 ** i) * 100) / 100} ${sizes[i]}`;
|
||||
return Math.round((bytes / Math.pow(1024, i)) * 100) / 100 + " " + sizes[i];
|
||||
};
|
||||
|
||||
@@ -63,8 +63,9 @@ export const MoreMoviesWithActor: React.FC<Props> = ({
|
||||
const x = acc.find((item) => item.Id === current.Id);
|
||||
if (!x) {
|
||||
return acc.concat([current]);
|
||||
} else {
|
||||
return acc;
|
||||
}
|
||||
return acc;
|
||||
}, [] as BaseItemDto[]) || [];
|
||||
|
||||
return uniqueItems;
|
||||
|
||||
@@ -239,7 +239,7 @@ export const PlayButton: React.FC<Props> = ({
|
||||
const derivedTargetWidth = useDerivedValue(() => {
|
||||
if (!item || !item.RunTimeTicks) return 0;
|
||||
const userData = item.UserData;
|
||||
if (userData?.PlaybackPositionTicks) {
|
||||
if (userData && userData.PlaybackPositionTicks) {
|
||||
return userData.PlaybackPositionTicks > 0
|
||||
? Math.max(
|
||||
(userData.PlaybackPositionTicks / item.RunTimeTicks) * 100,
|
||||
@@ -331,7 +331,7 @@ export const PlayButton: React.FC<Props> = ({
|
||||
accessibilityLabel='Play button'
|
||||
accessibilityHint='Tap to play the media'
|
||||
onPress={onPress}
|
||||
className={"relative"}
|
||||
className={`relative`}
|
||||
{...props}
|
||||
>
|
||||
<View className='absolute w-full h-full top-0 left-0 rounded-xl z-10 overflow-hidden'>
|
||||
|
||||
@@ -85,7 +85,7 @@ export const PlayButton: React.FC<Props> = ({
|
||||
const derivedTargetWidth = useDerivedValue(() => {
|
||||
if (!item || !item.RunTimeTicks) return 0;
|
||||
const userData = item.UserData;
|
||||
if (userData?.PlaybackPositionTicks) {
|
||||
if (userData && userData.PlaybackPositionTicks) {
|
||||
return userData.PlaybackPositionTicks > 0
|
||||
? Math.max(
|
||||
(userData.PlaybackPositionTicks / item.RunTimeTicks) * 100,
|
||||
@@ -176,7 +176,7 @@ export const PlayButton: React.FC<Props> = ({
|
||||
accessibilityLabel='Play button'
|
||||
accessibilityHint='Tap to play the media'
|
||||
onPress={onPress}
|
||||
className={"relative"}
|
||||
className={`relative`}
|
||||
{...props}
|
||||
>
|
||||
<View className='absolute w-full h-full top-0 left-0 rounded-xl z-10 overflow-hidden'>
|
||||
|
||||
@@ -7,7 +7,7 @@ export const WatchedIndicator: React.FC<{ item: BaseItemDto }> = ({ item }) => {
|
||||
<>
|
||||
{item.UserData?.Played === false &&
|
||||
(item.Type === "Movie" || item.Type === "Episode") && (
|
||||
<View className='bg-purple-600 w-8 h-8 absolute -top-4 -right-4 rotate-45' />
|
||||
<View className='bg-purple-600 w-8 h-8 absolute -top-4 -right-4 rotate-45'></View>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,7 @@ import renderer from "react-test-renderer";
|
||||
|
||||
import { ThemedText } from "../ThemedText";
|
||||
|
||||
it("renders correctly", () => {
|
||||
it(`renders correctly`, () => {
|
||||
const tree = renderer
|
||||
.create(<ThemedText>Snapshot test!</ThemedText>)
|
||||
.toJSON();
|
||||
|
||||
@@ -6,7 +6,7 @@ interface Props extends ViewProps {}
|
||||
export const TitleHeader: React.FC<Props> = ({ ...props }) => {
|
||||
return (
|
||||
<View {...props}>
|
||||
<Text />
|
||||
<Text></Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -75,7 +75,7 @@ const Dropdown = <T,>({
|
||||
multiple ? (
|
||||
<DropdownMenu.CheckboxItem
|
||||
value={
|
||||
selected?.some((s) => keyExtractor(s) === keyExtractor(item))
|
||||
selected?.some((s) => keyExtractor(s) == keyExtractor(item))
|
||||
? "on"
|
||||
: "off"
|
||||
}
|
||||
@@ -83,7 +83,7 @@ const Dropdown = <T,>({
|
||||
onValueChange={(next: "on" | "off", previous: "on" | "off") => {
|
||||
setSelected((p) => {
|
||||
const prev = p || [];
|
||||
if (next === "on") {
|
||||
if (next == "on") {
|
||||
return [...prev, item];
|
||||
}
|
||||
return [
|
||||
|
||||
@@ -65,13 +65,17 @@ export const HorizontalScroll = forwardRef<
|
||||
}: {
|
||||
item: T;
|
||||
index: number;
|
||||
}) => <View className='mr-2'>{renderItem(item, index)}</View>;
|
||||
}) => (
|
||||
<View className='mr-2'>
|
||||
<React.Fragment>{renderItem(item, index)}</React.Fragment>
|
||||
</View>
|
||||
);
|
||||
|
||||
if (!data || loading) {
|
||||
return (
|
||||
<View className='px-4 mb-2'>
|
||||
<View className='bg-neutral-950 h-24 w-full rounded-md mb-2' />
|
||||
<View className='bg-neutral-950 h-10 w-full rounded-md mb-1' />
|
||||
<View className='bg-neutral-950 h-24 w-full rounded-md mb-2'></View>
|
||||
<View className='bg-neutral-950 h-10 w-full rounded-md mb-1'></View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -75,8 +75,9 @@ export function InfiniteHorizontalScroll({
|
||||
|
||||
if (accumulatedItems < totalItems) {
|
||||
return lastPage?.Items?.length * pages.length;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
initialPageParam: 0,
|
||||
enabled: !!api && !!user?.Id,
|
||||
@@ -117,7 +118,9 @@ export function InfiniteHorizontalScroll({
|
||||
<FlashList
|
||||
data={flatData}
|
||||
renderItem={({ item, index }) => (
|
||||
<View className='mr-2'>{renderItem(item, index)}</View>
|
||||
<View className='mr-2'>
|
||||
<React.Fragment>{renderItem(item, index)}</React.Fragment>
|
||||
</View>
|
||||
)}
|
||||
estimatedItemSize={height}
|
||||
horizontal
|
||||
|
||||
@@ -36,7 +36,7 @@ export const ItemImage: FC<Props> = ({
|
||||
|
||||
const source = useMemo(() => {
|
||||
if (!api) {
|
||||
onError?.();
|
||||
onError && onError();
|
||||
return;
|
||||
}
|
||||
return getItemImage({
|
||||
|
||||
@@ -5,7 +5,7 @@ export const LargePoster: React.FC<{ url?: string | null }> = ({ url }) => {
|
||||
if (!url)
|
||||
return (
|
||||
<View className='p-4 rounded-xl overflow-hidden '>
|
||||
<View className='w-full aspect-video rounded-xl overflow-hidden border border-neutral-800' />
|
||||
<View className='w-full aspect-video rounded-xl overflow-hidden border border-neutral-800'></View>
|
||||
</View>
|
||||
);
|
||||
|
||||
|
||||
@@ -16,12 +16,12 @@ export function Text(
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<UITextView
|
||||
allowFontScaling={false}
|
||||
style={[{ color: "white" }, style]}
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
else
|
||||
return (
|
||||
<UITextView
|
||||
allowFontScaling={false}
|
||||
style={[{ color: "white" }, style]}
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,10 +20,10 @@ export const VerticalSkeleton: React.FC<Props> = ({ index, ...props }) => {
|
||||
aspectRatio: "10/15",
|
||||
}}
|
||||
className='w-full bg-neutral-800 mb-2 rounded-lg'
|
||||
/>
|
||||
<View className='h-2 bg-neutral-800 rounded-full mb-1' />
|
||||
<View className='h-2 bg-neutral-800 rounded-full mb-1' />
|
||||
<View className='h-2 bg-neutral-800 rounded-full mb-2 w-1/2' />
|
||||
></View>
|
||||
<View className='h-2 bg-neutral-800 rounded-full mb-1'></View>
|
||||
<View className='h-2 bg-neutral-800 rounded-full mb-1'></View>
|
||||
<View className='h-2 bg-neutral-800 rounded-full mb-2 w-1/2'></View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -23,9 +23,9 @@ import { Button } from "../Button";
|
||||
const BackGroundDownloader = !Platform.isTV
|
||||
? require("@kesha-antonov/react-native-background-downloader")
|
||||
: null;
|
||||
//const FFmpegKitProvider = !Platform.isTV
|
||||
// ? require("ffmpeg-kit-react-native")
|
||||
// : null;
|
||||
const FFmpegKitProvider = !Platform.isTV
|
||||
? require("ffmpeg-kit-react-native")
|
||||
: null;
|
||||
|
||||
interface Props extends ViewProps {}
|
||||
|
||||
@@ -80,12 +80,14 @@ const DownloadCard = ({ process, ...props }: DownloadCardProps) => {
|
||||
task.stop();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
await removeProcess(id);
|
||||
await queryClient.refetchQueries({ queryKey: ["jobs"] });
|
||||
}
|
||||
} else {
|
||||
//FFmpegKitProvider.FFmpegKit.cancel(Number(id));
|
||||
FFmpegKitProvider.FFmpegKit.cancel(Number(id));
|
||||
setProcesses((prev: any[]) =>
|
||||
prev.filter((p: { id: string }) => p.id !== id),
|
||||
);
|
||||
@@ -129,7 +131,7 @@ const DownloadCard = ({ process, ...props }: DownloadCardProps) => {
|
||||
? `${Math.max(5, process.progress)}%`
|
||||
: "5%",
|
||||
}}
|
||||
/>
|
||||
></View>
|
||||
)}
|
||||
<View className='px-3 py-1.5 flex flex-col w-full'>
|
||||
<View className='flex flex-row items-center w-full'>
|
||||
|
||||
@@ -31,7 +31,7 @@ export const SeriesCard: React.FC<{ items: BaseItemDto[] }> = ({ items }) => {
|
||||
destructiveButtonIndex,
|
||||
},
|
||||
(selectedIndex) => {
|
||||
if (selectedIndex === destructiveButtonIndex) {
|
||||
if (selectedIndex == destructiveButtonIndex) {
|
||||
deleteSeries();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@ import { TouchableOpacity, View, type ViewProps } from "react-native";
|
||||
import { FilterSheet } from "./FilterSheet";
|
||||
|
||||
interface FilterButtonProps<T> extends ViewProps {
|
||||
id: string;
|
||||
collectionId: string;
|
||||
showSearch?: boolean;
|
||||
queryKey: string;
|
||||
values: T[];
|
||||
@@ -15,12 +15,11 @@ interface FilterButtonProps<T> extends ViewProps {
|
||||
queryFn: (params: any) => Promise<any>;
|
||||
searchFilter?: (item: T, query: string) => boolean;
|
||||
renderItemLabel: (item: T) => React.ReactNode;
|
||||
multiple?: boolean;
|
||||
icon?: "filter" | "sort";
|
||||
}
|
||||
|
||||
export const FilterButton = <T,>({
|
||||
id,
|
||||
collectionId,
|
||||
queryFn,
|
||||
queryKey,
|
||||
set,
|
||||
@@ -29,17 +28,16 @@ export const FilterButton = <T,>({
|
||||
renderItemLabel,
|
||||
searchFilter,
|
||||
showSearch = true,
|
||||
multiple = false,
|
||||
icon = "filter",
|
||||
...props
|
||||
}: FilterButtonProps<T>) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const { data: filters } = useQuery<T[]>({
|
||||
queryKey: ["filters", title, queryKey, id],
|
||||
queryKey: ["filters", title, queryKey, collectionId],
|
||||
queryFn,
|
||||
staleTime: 0,
|
||||
enabled: !!id && !!queryFn && !!queryKey,
|
||||
enabled: !!collectionId && !!queryFn && !!queryKey,
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -95,7 +93,6 @@ export const FilterButton = <T,>({
|
||||
renderItemLabel={renderItemLabel}
|
||||
searchFilter={searchFilter}
|
||||
showSearch={showSearch}
|
||||
multiple={multiple}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -31,7 +31,6 @@ interface Props<T> extends ViewProps {
|
||||
searchFilter?: (item: T, query: string) => boolean;
|
||||
renderItemLabel: (item: T) => React.ReactNode;
|
||||
showSearch?: boolean;
|
||||
multiple?: boolean;
|
||||
}
|
||||
|
||||
const LIMIT = 100;
|
||||
@@ -74,7 +73,6 @@ export const FilterSheet = <T,>({
|
||||
searchFilter,
|
||||
renderItemLabel,
|
||||
showSearch = true,
|
||||
multiple = false,
|
||||
...props
|
||||
}: Props<T>) => {
|
||||
const bottomSheetModalRef = useRef<BottomSheetModal>(null);
|
||||
@@ -182,20 +180,11 @@ export const FilterSheet = <T,>({
|
||||
<View key={index}>
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
if (multiple) {
|
||||
if (!values.includes(item)) set(values.concat(item));
|
||||
else set(values.filter((v) => v !== item));
|
||||
|
||||
if (!values.includes(item)) {
|
||||
set([item]);
|
||||
setTimeout(() => {
|
||||
setOpen(false);
|
||||
}, 250);
|
||||
} else {
|
||||
if (!values.includes(item)) {
|
||||
set([item]);
|
||||
setTimeout(() => {
|
||||
setOpen(false);
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
}}
|
||||
className=' bg-neutral-800 px-4 py-3 flex flex-row items-center justify-between'
|
||||
@@ -212,7 +201,7 @@ export const FilterSheet = <T,>({
|
||||
height: StyleSheet.hairlineWidth,
|
||||
}}
|
||||
className='h-1 divide-neutral-700 '
|
||||
/>
|
||||
></View>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
|
||||
@@ -63,7 +63,7 @@ export const ScrollingCollectionList: React.FC<Props> = ({
|
||||
>
|
||||
{[1, 2, 3].map((i) => (
|
||||
<View className='w-44' key={i}>
|
||||
<View className='bg-neutral-900 h-24 w-full rounded-md mb-1' />
|
||||
<View className='bg-neutral-900 h-24 w-full rounded-md mb-1'></View>
|
||||
<View className='rounded-md overflow-hidden mb-1 self-start'>
|
||||
<Text
|
||||
className='text-neutral-900 bg-neutral-900 rounded-md'
|
||||
|
||||
@@ -34,7 +34,10 @@ export const Stepper: React.FC<StepperProps> = ({
|
||||
<Text>-</Text>
|
||||
</TouchableOpacity>
|
||||
<Text
|
||||
className={`w-auto h-8 bg-neutral-800 py-2 px-1 flex items-center justify-center${appendValue ? "first-letter:px-2" : ""}`}
|
||||
className={
|
||||
"w-auto h-8 bg-neutral-800 py-2 px-1 flex items-center justify-center" +
|
||||
(appendValue ? "first-letter:px-2" : "")
|
||||
}
|
||||
>
|
||||
{value}
|
||||
{appendValue}
|
||||
|
||||
@@ -52,7 +52,7 @@ export const JellyserrIndexPage: React.FC<Props> = ({
|
||||
} = useReactNavigationQuery({
|
||||
queryKey: ["search", "jellyseerr", "discoverSettings", searchQuery],
|
||||
queryFn: async () => jellyseerrApi?.discoverSettings(),
|
||||
enabled: !!jellyseerrApi && searchQuery.length === 0,
|
||||
enabled: !!jellyseerrApi && searchQuery.length == 0,
|
||||
});
|
||||
|
||||
const {
|
||||
@@ -110,7 +110,7 @@ export const JellyserrIndexPage: React.FC<Props> = ({
|
||||
(r) => r.mediaType === MediaType.MOVIE,
|
||||
) as MovieResult[],
|
||||
sortingType || [
|
||||
(m) => m.title.toLowerCase() === searchQuery.toLowerCase(),
|
||||
(m) => m.title.toLowerCase() == searchQuery.toLowerCase(),
|
||||
],
|
||||
order || "desc",
|
||||
),
|
||||
@@ -124,7 +124,7 @@ export const JellyserrIndexPage: React.FC<Props> = ({
|
||||
(r) => r.mediaType === MediaType.TV,
|
||||
) as TvResult[],
|
||||
sortingType || [
|
||||
(t) => t.name.toLowerCase() === searchQuery.toLowerCase(),
|
||||
(t) => t.name.toLowerCase() == searchQuery.toLowerCase(),
|
||||
],
|
||||
order || "desc",
|
||||
),
|
||||
@@ -138,7 +138,7 @@ export const JellyserrIndexPage: React.FC<Props> = ({
|
||||
(r) => r.mediaType === "person",
|
||||
) as PersonResult[],
|
||||
sortingType || [
|
||||
(p) => p.name.toLowerCase() === searchQuery.toLowerCase(),
|
||||
(p) => p.name.toLowerCase() == searchQuery.toLowerCase(),
|
||||
],
|
||||
order || "desc",
|
||||
),
|
||||
|
||||
@@ -62,7 +62,7 @@ const JellyseerrStatusIcon: React.FC<Props & ViewProps> = ({
|
||||
|
||||
return (
|
||||
badgeIcon && (
|
||||
<TouchableOpacity onPress={onPress} disabled={onPress === undefined}>
|
||||
<TouchableOpacity onPress={onPress} disabled={onPress == undefined}>
|
||||
<View
|
||||
className={`${badgeStyle ?? "bg-purple-600"} rounded-full h-6 w-6 flex items-center justify-center ${props.className}`}
|
||||
{...props}
|
||||
|
||||
@@ -123,9 +123,11 @@ const ParallaxSlideShow = <T,>({
|
||||
>
|
||||
<View className='flex flex-col space-y-4 px-4'>
|
||||
<View className='flex flex-row justify-between w-full'>
|
||||
<View className='flex flex-col w-full'>{HeaderContent?.()}</View>
|
||||
<View className='flex flex-col w-full'>
|
||||
{HeaderContent && HeaderContent()}
|
||||
</View>
|
||||
</View>
|
||||
{MainContent?.()}
|
||||
{MainContent && MainContent()}
|
||||
<View>
|
||||
<FlashList
|
||||
data={data}
|
||||
|
||||
@@ -9,7 +9,6 @@ import type {
|
||||
} from "@/utils/jellyseerr/server/api/servarr/base";
|
||||
import type { MediaType } from "@/utils/jellyseerr/server/constants/media";
|
||||
import type { MediaRequestBody } from "@/utils/jellyseerr/server/interfaces/api/requestInterfaces";
|
||||
import { writeDebugLog } from "@/utils/log";
|
||||
import {
|
||||
BottomSheetBackdrop,
|
||||
type BottomSheetBackdropProps,
|
||||
@@ -62,7 +61,7 @@ const RequestModal = forwardRef<
|
||||
const { data: serviceSettings } = useQuery({
|
||||
queryKey: ["jellyseerr", "request", type, "service"],
|
||||
queryFn: async () =>
|
||||
jellyseerrApi?.service(type === "movie" ? "radarr" : "sonarr"),
|
||||
jellyseerrApi?.service(type == "movie" ? "radarr" : "sonarr"),
|
||||
enabled: !!jellyseerrApi && !!jellyseerrUser,
|
||||
refetchOnMount: "always",
|
||||
});
|
||||
@@ -148,20 +147,16 @@ const RequestModal = forwardRef<
|
||||
}, [requestBody?.seasons]);
|
||||
|
||||
const request = useCallback(() => {
|
||||
const body = {
|
||||
is4k: defaultService?.is4k || defaultServiceDetails?.server.is4k,
|
||||
profileId: defaultProfile?.id,
|
||||
rootFolder: defaultFolder?.path,
|
||||
tags: defaultTags.map((t) => t.id),
|
||||
...requestBody,
|
||||
...requestOverrides,
|
||||
};
|
||||
|
||||
writeDebugLog("Sending Jellyseerr advanced request", body);
|
||||
|
||||
requestMedia(
|
||||
seasonTitle ? `${title}, ${seasonTitle}` : title,
|
||||
body,
|
||||
{
|
||||
is4k: defaultService?.is4k || defaultServiceDetails?.server.is4k,
|
||||
profileId: defaultProfile.id,
|
||||
rootFolder: defaultFolder.path,
|
||||
tags: defaultTags.map((t) => t.id),
|
||||
...requestBody,
|
||||
...requestOverrides,
|
||||
},
|
||||
onRequested,
|
||||
);
|
||||
}, [
|
||||
|
||||
@@ -28,7 +28,7 @@ const GenreSlide: React.FC<SlideProps & ViewProps> = ({ slide, ...props }) => {
|
||||
queryKey: ["jellyseerr", "discover", slide.type, slide.id],
|
||||
queryFn: async () => {
|
||||
return jellyseerrApi?.getGenreSliders(
|
||||
slide.type === DiscoverSliderType.MOVIE_GENRES
|
||||
slide.type == DiscoverSliderType.MOVIE_GENRES
|
||||
? Endpoints.MOVIE
|
||||
: Endpoints.TV,
|
||||
);
|
||||
|
||||
@@ -23,7 +23,7 @@ const RequestCard: React.FC<{ request: MediaRequest }> = ({ request }) => {
|
||||
request.media.tmdbId,
|
||||
],
|
||||
queryFn: async () => {
|
||||
return request.media.mediaType === MediaType.MOVIE
|
||||
return request.media.mediaType == MediaType.MOVIE
|
||||
? jellyseerrApi?.movieDetails(request.media.tmdbId)
|
||||
: jellyseerrApi?.tvDetails(request.media.tmdbId);
|
||||
},
|
||||
|
||||
@@ -35,7 +35,7 @@ const Slide = <T,>({
|
||||
return (
|
||||
<View {...props}>
|
||||
<Text className='font-bold text-lg mb-2 px-4'>
|
||||
{t(`search.${DiscoverSliderType[slide.type].toString().toLowerCase()}`)}
|
||||
{t("search." + DiscoverSliderType[slide.type].toString().toLowerCase())}
|
||||
</Text>
|
||||
<FlashList
|
||||
horizontal
|
||||
|
||||
@@ -29,8 +29,8 @@ export const EpisodePoster: React.FC<MoviePosterProps> = ({
|
||||
);
|
||||
|
||||
const blurhash = useMemo(() => {
|
||||
const key = item.ImageTags?.Primary as string;
|
||||
return item.ImageBlurHashes?.Primary?.[key];
|
||||
const key = item.ImageTags?.["Primary"] as string;
|
||||
return item.ImageBlurHashes?.["Primary"]?.[key];
|
||||
}, [item]);
|
||||
|
||||
return (
|
||||
@@ -57,7 +57,7 @@ export const EpisodePoster: React.FC<MoviePosterProps> = ({
|
||||
/>
|
||||
<WatchedIndicator item={item} />
|
||||
{showProgress && progress > 0 && (
|
||||
<View className='h-1 bg-red-600 w-full' />
|
||||
<View className='h-1 bg-red-600 w-full'></View>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -37,7 +37,7 @@ export const ItemPoster: React.FC<Props> = ({
|
||||
/>
|
||||
<WatchedIndicator item={item} />
|
||||
{showProgress && progress > 0 && (
|
||||
<View className='h-1 bg-red-600 w-full' />
|
||||
<View className='h-1 bg-red-600 w-full'></View>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -129,7 +129,7 @@ const JellyseerrPoster: React.FC<Props> = ({
|
||||
posterSrc={posterSrc!}
|
||||
mediaType={mediaType}
|
||||
>
|
||||
<View className={"flex flex-col mr-2 h-auto"}>
|
||||
<View className={`flex flex-col mr-2 h-auto`}>
|
||||
<View
|
||||
className={`relative rounded-lg overflow-hidden border border-neutral-900 ${size} aspect-[${ratio}]`}
|
||||
>
|
||||
|
||||
@@ -31,8 +31,8 @@ const MoviePoster: React.FC<MoviePosterProps> = ({
|
||||
);
|
||||
|
||||
const blurhash = useMemo(() => {
|
||||
const key = item.ImageTags?.Primary as string;
|
||||
return item.ImageBlurHashes?.Primary?.[key];
|
||||
const key = item.ImageTags?.["Primary"] as string;
|
||||
return item.ImageBlurHashes?.["Primary"]?.[key];
|
||||
}, [item]);
|
||||
|
||||
return (
|
||||
@@ -59,7 +59,7 @@ const MoviePoster: React.FC<MoviePosterProps> = ({
|
||||
/>
|
||||
<WatchedIndicator item={item} />
|
||||
{showProgress && progress > 0 && (
|
||||
<View className='h-1 bg-red-600 w-full' />
|
||||
<View className='h-1 bg-red-600 w-full'></View>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -24,7 +24,7 @@ const ParentPoster: React.FC<PosterProps> = ({ id }) => {
|
||||
style={{
|
||||
aspectRatio: "10/15",
|
||||
}}
|
||||
/>
|
||||
></View>
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -16,7 +16,7 @@ const Poster: React.FC<PosterProps> = ({ id, url, blurhash }) => {
|
||||
style={{
|
||||
aspectRatio: "10/15",
|
||||
}}
|
||||
/>
|
||||
></View>
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -27,8 +27,8 @@ const SeriesPoster: React.FC<MoviePosterProps> = ({ item }) => {
|
||||
}, [item]);
|
||||
|
||||
const blurhash = useMemo(() => {
|
||||
const key = item.ImageTags?.Primary as string;
|
||||
return item.ImageBlurHashes?.Primary?.[key];
|
||||
const key = item.ImageTags?.["Primary"] as string;
|
||||
return item.ImageBlurHashes?.["Primary"]?.[key];
|
||||
}, [item]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -35,11 +35,11 @@ export const LoadingSkeleton: React.FC<Props> = ({ isLoading }) => {
|
||||
<Animated.View style={animatedStyle} className='mt-2 absolute w-full'>
|
||||
{[1, 2, 3].map((s) => (
|
||||
<View className='px-4 mb-4' key={s}>
|
||||
<View className='w-1/2 bg-neutral-900 h-6 mb-2 rounded-lg' />
|
||||
<View className='w-1/2 bg-neutral-900 h-6 mb-2 rounded-lg'></View>
|
||||
<View className='flex flex-row gap-2'>
|
||||
{[1, 2, 3].map((i) => (
|
||||
<View className='w-28' key={i}>
|
||||
<View className='bg-neutral-900 h-40 w-full rounded-md mb-1' />
|
||||
<View className='bg-neutral-900 h-40 w-full rounded-md mb-1'></View>
|
||||
<View className='rounded-md overflow-hidden mb-1 self-start'>
|
||||
<Text
|
||||
className='text-neutral-900 bg-neutral-900 rounded-md'
|
||||
|
||||
@@ -57,7 +57,7 @@ export const NextItemButton: React.FC<Props> = ({
|
||||
return (
|
||||
<Button
|
||||
onPress={() => router.setParams({ id: nextItem?.Id })}
|
||||
className={"h-12 aspect-square"}
|
||||
className={`h-12 aspect-square`}
|
||||
disabled={disabled}
|
||||
{...props}
|
||||
>
|
||||
|
||||
@@ -146,7 +146,7 @@ export const SeasonPicker: React.FC<Props> = ({ item, initialSeasonIndex }) => {
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
{episodes?.length ? (
|
||||
{episodes?.length || 0 > 0 ? (
|
||||
<View className='flex flex-row items-center space-x-2'>
|
||||
<DownloadItems
|
||||
title={t("item_card.download.download_season")}
|
||||
|
||||
@@ -19,7 +19,7 @@ export const Dashboard = () => {
|
||||
<View>
|
||||
<ListGroup title={t("home.settings.dashboard.title")} className='mt-4'>
|
||||
<ListItem
|
||||
className={sessions.length !== 0 ? "bg-purple-900" : ""}
|
||||
className={sessions.length != 0 ? "bg-purple-900" : ""}
|
||||
onPress={() => router.push("/settings/dashboard/sessions")}
|
||||
title={t("home.settings.dashboard.sessions_title")}
|
||||
showArrow
|
||||
|
||||
@@ -140,7 +140,7 @@ export default function DownloadSettings({ ...props }) {
|
||||
onPress={() => router.push("/settings/optimized-server/page")}
|
||||
showArrow
|
||||
title={t("home.settings.downloads.optimized_versions_server")}
|
||||
/>
|
||||
></ListItem>
|
||||
</ListGroup>
|
||||
</DisabledSetting>
|
||||
);
|
||||
|
||||
@@ -51,13 +51,13 @@ type ScrollingCollectionListSection = {
|
||||
orientation?: "horizontal" | "vertical";
|
||||
};
|
||||
|
||||
type MediaListSectionType = {
|
||||
type MediaListSection = {
|
||||
type: "MediaListSection";
|
||||
queryKey: (string | undefined)[];
|
||||
queryFn: QueryFunction<BaseItemDto>;
|
||||
};
|
||||
|
||||
type Section = ScrollingCollectionListSection | MediaListSectionType;
|
||||
type Section = ScrollingCollectionListSection | MediaListSection;
|
||||
|
||||
export const HomeIndex = () => {
|
||||
const router = useRouter();
|
||||
@@ -133,7 +133,7 @@ export const HomeIndex = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const unsubscribe = NetInfo.addEventListener((state) => {
|
||||
if (state.isConnected === false || state.isInternetReachable === false)
|
||||
if (state.isConnected == false || state.isInternetReachable === false)
|
||||
setIsConnected(false);
|
||||
else setIsConnected(true);
|
||||
});
|
||||
@@ -236,7 +236,7 @@ export const HomeIndex = () => {
|
||||
const title = t("home.recently_added_in", { libraryName: c.Name });
|
||||
const queryKey = [
|
||||
"home",
|
||||
`recentlyAddedIn${c.CollectionType}`,
|
||||
"recentlyAddedIn" + c.CollectionType,
|
||||
user?.Id!,
|
||||
c.Id!,
|
||||
];
|
||||
@@ -353,29 +353,17 @@ export const HomeIndex = () => {
|
||||
parentId: section.items?.parentId,
|
||||
});
|
||||
return response.data.Items || [];
|
||||
}
|
||||
if (section.nextUp) {
|
||||
} else if (section.nextUp) {
|
||||
const response = await getTvShowsApi(api).getNextUp({
|
||||
userId: user?.Id,
|
||||
fields: ["MediaSourceCount"],
|
||||
limit: section.items?.limit || 25,
|
||||
enableImageTypes: ["Primary", "Backdrop", "Thumb"],
|
||||
enableResumable: section.items?.enableResumable,
|
||||
enableRewatching: section.items?.enableRewatching,
|
||||
enableResumable: section.items?.enableResumable || false,
|
||||
enableRewatching: section.items?.enableRewatching || false,
|
||||
});
|
||||
return response.data.Items || [];
|
||||
}
|
||||
|
||||
if (section.latest) {
|
||||
const response = await getUserLibraryApi(api).getLatestMedia({
|
||||
userId: user?.Id,
|
||||
includeItemTypes: section.latest?.includeItemTypes,
|
||||
limit: section.latest?.limit || 25,
|
||||
isPlayed: section.latest?.isPlayed,
|
||||
groupItems: section.latest?.groupItems,
|
||||
});
|
||||
return response.data || [];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
type: "ScrollingCollectionList",
|
||||
@@ -475,8 +463,7 @@ export const HomeIndex = () => {
|
||||
hideIfEmpty
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (section.type === "MediaListSection") {
|
||||
} else if (section.type === "MediaListSection") {
|
||||
return (
|
||||
<MediaListSection
|
||||
key={index}
|
||||
|
||||
@@ -20,7 +20,7 @@ export const OptimizedServerForm: React.FC<Props> = ({
|
||||
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"}>
|
||||
<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'
|
||||
|
||||
@@ -81,7 +81,7 @@ export const StorageSettings = () => {
|
||||
{size && (
|
||||
<>
|
||||
<View className='flex flex-row items-center'>
|
||||
<View className='w-3 h-3 rounded-full bg-purple-600 mr-1' />
|
||||
<View className='w-3 h-3 rounded-full bg-purple-600 mr-1'></View>
|
||||
<Text className='text-white text-xs'>
|
||||
{t("home.settings.storage.app_usage", {
|
||||
usedSpace: calculatePercentage(size.app, size.total),
|
||||
@@ -89,7 +89,7 @@ export const StorageSettings = () => {
|
||||
</Text>
|
||||
</View>
|
||||
<View className='flex flex-row items-center'>
|
||||
<View className='w-3 h-3 rounded-full bg-purple-400 mr-1' />
|
||||
<View className='w-3 h-3 rounded-full bg-purple-400 mr-1'></View>
|
||||
<Text className='text-white text-xs'>
|
||||
{t("home.settings.storage.device_usage", {
|
||||
availableSpace: calculatePercentage(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { apiAtom, useJellyfin, userAtom } from "@/providers/JellyfinProvider";
|
||||
import * as Application from "expo-application";
|
||||
import Application from "expo-application";
|
||||
import Constants from "expo-constants";
|
||||
import { useAtom } from "jotai";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@@ -5,8 +5,7 @@ import { useCreditSkipper } from "@/hooks/useCreditSkipper";
|
||||
import { useHaptic } from "@/hooks/useHaptic";
|
||||
import { useIntroSkipper } from "@/hooks/useIntroSkipper";
|
||||
import { useTrickplay } from "@/hooks/useTrickplay";
|
||||
import type { MpvPlayerViewRef, TrackInfo } from "@/modules/MpvPlayer.types";
|
||||
import { VlcPlayerViewRef } from "@/modules/VlcPlayer.types";
|
||||
import type { TrackInfo, VlcPlayerViewRef } from "@/modules/VlcPlayer.types";
|
||||
import * as ScreenOrientation from "@/packages/expo-screen-orientation";
|
||||
import { apiAtom } from "@/providers/JellyfinProvider";
|
||||
import { VideoPlayer, useSettings } from "@/utils/atoms/settings";
|
||||
@@ -66,7 +65,7 @@ import { useControlsTimeout } from "./useControlsTimeout";
|
||||
|
||||
interface Props {
|
||||
item: BaseItemDto;
|
||||
videoRef: MutableRefObject<VlcPlayerViewRef | MpvPlayerViewRef | null>;
|
||||
videoRef: MutableRefObject<VlcPlayerViewRef | null>;
|
||||
isPlaying: boolean;
|
||||
isSeeking: SharedValue<boolean>;
|
||||
cacheProgress: SharedValue<number>;
|
||||
@@ -82,7 +81,7 @@ interface Props {
|
||||
isVideoLoaded?: boolean;
|
||||
mediaSource?: MediaSourceInfo | null;
|
||||
seek: (ticks: number) => void;
|
||||
startPictureInPicture?: () => Promise<void>;
|
||||
startPictureInPicture: () => Promise<void>;
|
||||
play: (() => Promise<void>) | (() => void);
|
||||
pause: () => void;
|
||||
getAudioTracks?: (() => Promise<TrackInfo[] | null>) | (() => TrackInfo[]);
|
||||
@@ -455,9 +454,9 @@ export const Controls: FC<Props> = ({
|
||||
|
||||
const onClose = async () => {
|
||||
lightHapticFeedback();
|
||||
// await ScreenOrientation.lockAsync(
|
||||
// ScreenOrientation.OrientationLock.PORTRAIT_UP,
|
||||
// );
|
||||
await ScreenOrientation.lockAsync(
|
||||
ScreenOrientation.OrientationLock.PORTRAIT_UP,
|
||||
);
|
||||
router.back();
|
||||
};
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ export const EpisodeList: React.FC<Props> = ({ item, close, goToItem }) => {
|
||||
style={{
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
className={"flex flex-row items-center space-x-2 z-10 p-4"}
|
||||
className={`flex flex-row items-center space-x-2 z-10 p-4`}
|
||||
>
|
||||
{seriesItem && (
|
||||
<SeasonDropdown
|
||||
|
||||
@@ -47,7 +47,7 @@ const SliderScrubber: React.FC<SliderScrubberProps> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<View className={"flex flex-col w-full shrink"}>
|
||||
<View className={`flex flex-col w-full shrink`}>
|
||||
<Slider
|
||||
theme={{
|
||||
maximumTrackTintColor: "rgba(255,255,255,0.2)",
|
||||
|
||||
@@ -115,7 +115,7 @@ export const VideoProvider: React.FC<VideoProviderProps> = ({
|
||||
});
|
||||
return;
|
||||
}
|
||||
setTrack?.(index);
|
||||
setTrack && setTrack(index);
|
||||
router.setParams({
|
||||
[paramKey]: serverIndex.toString(),
|
||||
});
|
||||
@@ -126,8 +126,6 @@ export const VideoProvider: React.FC<VideoProviderProps> = ({
|
||||
if (getSubtitleTracks) {
|
||||
const subtitleData = await getSubtitleTracks();
|
||||
|
||||
console.log("subtitleData", subtitleData);
|
||||
|
||||
// Step 1: Move external subs to the end, because VLC puts external subs at the end
|
||||
const sortedSubs = allSubs.sort(
|
||||
(a, b) => Number(a.IsExternal) - Number(b.IsExternal),
|
||||
@@ -172,7 +170,6 @@ export const VideoProvider: React.FC<VideoProviderProps> = ({
|
||||
});
|
||||
setSubtitleTracks(subtitles);
|
||||
}
|
||||
|
||||
if (getAudioTracks) {
|
||||
const audioData = await getAudioTracks();
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ export const useTapDetection = ({
|
||||
|
||||
const touchDuration = touchEndTime - touchStartTime.current;
|
||||
const touchDistance = Math.sqrt(
|
||||
(touchEndPosition.x - touchStartPosition.current.x) ** 2 +
|
||||
(touchEndPosition.y - touchStartPosition.current.y) ** 2,
|
||||
Math.pow(touchEndPosition.x - touchStartPosition.current.x, 2) +
|
||||
Math.pow(touchEndPosition.y - touchStartPosition.current.y, 2),
|
||||
);
|
||||
|
||||
if (touchDuration < maxDuration && touchDistance < maxDistance) {
|
||||
|
||||
@@ -45,17 +45,19 @@ export const VideoDebugInfo: React.FC<Props> = ({ playerRef, ...props }) => {
|
||||
>
|
||||
<Text className='font-bold'>{t("player.playback_state")}</Text>
|
||||
<Text className='font-bold mt-2.5'>{t("player.audio_tracks")}</Text>
|
||||
{audioTracks?.map((track, index) => (
|
||||
<Text key={index}>
|
||||
{track.name} ({t("player.index")} {track.index})
|
||||
</Text>
|
||||
))}
|
||||
{audioTracks &&
|
||||
audioTracks.map((track, index) => (
|
||||
<Text key={index}>
|
||||
{track.name} ({t("player.index")} {track.index})
|
||||
</Text>
|
||||
))}
|
||||
<Text className='font-bold mt-2.5'>{t("player.subtitles_tracks")}</Text>
|
||||
{subtitleTracks?.map((track, index) => (
|
||||
<Text key={index}>
|
||||
{track.name} ({t("player.index")} {track.index})
|
||||
</Text>
|
||||
))}
|
||||
{subtitleTracks &&
|
||||
subtitleTracks.map((track, index) => (
|
||||
<Text key={index}>
|
||||
{track.name} ({t("player.index")} {track.index})
|
||||
</Text>
|
||||
))}
|
||||
<TouchableOpacity
|
||||
className='mt-2.5 bg-blue-500 p-2 rounded'
|
||||
onPress={() => {
|
||||
|
||||
27
eas.json
27
eas.json
@@ -5,64 +5,47 @@
|
||||
},
|
||||
"build": {
|
||||
"development": {
|
||||
"environment": "development",
|
||||
"developmentClient": true,
|
||||
"distribution": "internal",
|
||||
"android": {
|
||||
"buildType": "apk"
|
||||
},
|
||||
"env": {
|
||||
"EXPO_PUBLIC_WRITE_DEBUG": "1"
|
||||
}
|
||||
},
|
||||
"development_tv": {
|
||||
"environment": "development",
|
||||
"developmentClient": true,
|
||||
"distribution": "internal",
|
||||
"android": {
|
||||
"buildType": "apk"
|
||||
},
|
||||
"env": {
|
||||
"EXPO_TV": "1",
|
||||
"EXPO_PUBLIC_WRITE_DEBUG": "1"
|
||||
"EXPO_TV": "1"
|
||||
}
|
||||
},
|
||||
"preview": {
|
||||
"environment": "development",
|
||||
"distribution": "internal",
|
||||
"env": {
|
||||
"EXPO_PUBLIC_WRITE_DEBUG": "1"
|
||||
}
|
||||
"distribution": "internal"
|
||||
},
|
||||
"development-simulator": {
|
||||
"environment": "development",
|
||||
"developmentClient": true,
|
||||
"distribution": "internal",
|
||||
"ios": {
|
||||
"simulator": true
|
||||
},
|
||||
"env": {
|
||||
"EXPO_PUBLIC_WRITE_DEBUG": "1"
|
||||
}
|
||||
},
|
||||
"production": {
|
||||
"environment": "production",
|
||||
"channel": "0.28.0",
|
||||
"channel": "0.27.0",
|
||||
"android": {
|
||||
"image": "latest"
|
||||
}
|
||||
},
|
||||
"production-apk": {
|
||||
"environment": "production",
|
||||
"channel": "0.28.0",
|
||||
"channel": "0.27.0",
|
||||
"android": {
|
||||
"buildType": "apk",
|
||||
"image": "latest"
|
||||
}
|
||||
},
|
||||
"production-apk-tv": {
|
||||
"environment": "production",
|
||||
"channel": "0.28.0",
|
||||
"channel": "0.27.0",
|
||||
"android": {
|
||||
"buildType": "apk",
|
||||
"image": "latest"
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "1039325086281",
|
||||
"project_id": "streamyfin-4fec1",
|
||||
"storage_bucket": "streamyfin-4fec1.firebasestorage.app"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:1039325086281:android:b270168004aa30c1e1f598",
|
||||
"android_client_info": {
|
||||
"package_name": "com.fredrikburmester.streamyfin"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyABKBTRL9dvGuZbx009YFLUAPurFIDovFQ"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
@@ -35,7 +35,7 @@ export const useDownloadedFileOpener = () => {
|
||||
async (item: BaseItemDto) => {
|
||||
try {
|
||||
// @ts-expect-error
|
||||
router.push(`/player/direct-player?offline=true&itemId=${item.Id}`);
|
||||
router.push("/player/direct-player?offline=true&itemId=" + item.Id);
|
||||
} catch (error) {
|
||||
writeToLog("ERROR", "Error opening file", error);
|
||||
console.error("Error opening file:", error);
|
||||
|
||||
@@ -38,7 +38,7 @@ export const useImageColors = ({
|
||||
const source = useMemo(() => {
|
||||
if (!api) return;
|
||||
if (url) return { uri: url };
|
||||
if (item)
|
||||
else if (item)
|
||||
return getItemImage({
|
||||
item,
|
||||
api,
|
||||
@@ -46,7 +46,7 @@ export const useImageColors = ({
|
||||
quality: 80,
|
||||
width: 300,
|
||||
});
|
||||
return null;
|
||||
else return null;
|
||||
}, [api, item]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -87,11 +87,11 @@ export enum Endpoints {
|
||||
STUDIO = "/studio",
|
||||
GENRE_SLIDER = "/genreslider",
|
||||
DISCOVER = "/discover",
|
||||
DISCOVER_TRENDING = `${DISCOVER}/trending`,
|
||||
DISCOVER_MOVIES = `${DISCOVER}/movies`,
|
||||
DISCOVER_TRENDING = DISCOVER + "/trending",
|
||||
DISCOVER_MOVIES = DISCOVER + "/movies",
|
||||
DISCOVER_TV = DISCOVER + TV,
|
||||
DISCOVER_TV_NETWORK = DISCOVER + TV + NETWORK,
|
||||
DISCOVER_MOVIES_STUDIO = `${DISCOVER}${MOVIE}s${STUDIO}`,
|
||||
DISCOVER_MOVIES_STUDIO = DISCOVER + `${MOVIE}s` + STUDIO,
|
||||
AUTH_JELLYFIN = "/auth/jellyfin",
|
||||
}
|
||||
|
||||
@@ -159,8 +159,10 @@ export class JellyseerrApi {
|
||||
}
|
||||
toast.error(t("jellyseerr.toasts.jellyseerr_test_failed"));
|
||||
writeErrorLog(
|
||||
`Jellyseerr returned a ${status} for url:\n${response.config.url}`,
|
||||
response.data,
|
||||
`Jellyseerr returned a ${status} for url:\n` +
|
||||
response.config.url +
|
||||
"\n" +
|
||||
JSON.stringify(response.data),
|
||||
);
|
||||
return {
|
||||
isValid: false,
|
||||
@@ -239,7 +241,7 @@ export class JellyseerrApi {
|
||||
|
||||
async getRequest(id: number): Promise<MediaRequest> {
|
||||
return this.axios
|
||||
?.get<MediaRequest>(`${Endpoints.API_V1 + Endpoints.REQUEST}/${id}`)
|
||||
?.get<MediaRequest>(Endpoints.API_V1 + Endpoints.REQUEST + `/${id}`)
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
@@ -260,7 +262,7 @@ export class JellyseerrApi {
|
||||
|
||||
async movieDetails(id: number) {
|
||||
return this.axios
|
||||
?.get<MovieDetails>(`${Endpoints.API_V1 + Endpoints.MOVIE}/${id}`)
|
||||
?.get<MovieDetails>(Endpoints.API_V1 + Endpoints.MOVIE + `/${id}`)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
});
|
||||
@@ -268,7 +270,7 @@ export class JellyseerrApi {
|
||||
|
||||
async personDetails(id: number | string): Promise<PersonDetails> {
|
||||
return this.axios
|
||||
?.get<PersonDetails>(`${Endpoints.API_V1 + Endpoints.PERSON}/${id}`)
|
||||
?.get<PersonDetails>(Endpoints.API_V1 + Endpoints.PERSON + `/${id}`)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
});
|
||||
@@ -277,9 +279,10 @@ export class JellyseerrApi {
|
||||
async personCombinedCredits(id: number | string): Promise<CombinedCredit> {
|
||||
return this.axios
|
||||
?.get<CombinedCredit>(
|
||||
`${
|
||||
Endpoints.API_V1 + Endpoints.PERSON
|
||||
}/${id}${Endpoints.COMBINED_CREDITS}`,
|
||||
Endpoints.API_V1 +
|
||||
Endpoints.PERSON +
|
||||
`/${id}` +
|
||||
Endpoints.COMBINED_CREDITS,
|
||||
)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
@@ -330,10 +333,13 @@ export class JellyseerrApi {
|
||||
|
||||
imageProxy(path?: string, filter = "original", width = 1920, quality = 75) {
|
||||
return path
|
||||
? `${this.axios.defaults.baseURL}/_next/image?${new URLSearchParams(
|
||||
`url=https://image.tmdb.org/t/p/${filter}/${path}&w=${width}&q=${quality}`,
|
||||
).toString()}`
|
||||
: `${this.axios?.defaults.baseURL}/images/overseerr_poster_not_found_logo_top.png`;
|
||||
? this.axios.defaults.baseURL +
|
||||
`/_next/image?` +
|
||||
new URLSearchParams(
|
||||
`url=https://image.tmdb.org/t/p/${filter}/${path}&w=${width}&q=${quality}`,
|
||||
).toString()
|
||||
: this.axios?.defaults.baseURL +
|
||||
`/images/overseerr_poster_not_found_logo_top.png`;
|
||||
}
|
||||
|
||||
async submitIssue(mediaId: number, issueType: IssueType, message: string) {
|
||||
@@ -356,7 +362,7 @@ export class JellyseerrApi {
|
||||
async service(type: "radarr" | "sonarr") {
|
||||
return this.axios
|
||||
?.get<ServiceCommonServer[]>(
|
||||
`${Endpoints.API_V1 + Endpoints.SERVICE}/${type}`,
|
||||
Endpoints.API_V1 + Endpoints.SERVICE + `/${type}`,
|
||||
)
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
@@ -364,7 +370,7 @@ export class JellyseerrApi {
|
||||
async serviceDetails(type: "radarr" | "sonarr", id: number) {
|
||||
return this.axios
|
||||
?.get<ServiceCommonServerWithDetails>(
|
||||
`${Endpoints.API_V1 + Endpoints.SERVICE}/${type}/${id}`,
|
||||
Endpoints.API_V1 + Endpoints.SERVICE + `/${type}` + `/${id}`,
|
||||
)
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
@@ -382,9 +388,15 @@ export class JellyseerrApi {
|
||||
return response;
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
const errorMsg = "Jellyseerr response error";
|
||||
console.error(errorMsg, error, error.response?.data);
|
||||
writeErrorLog(
|
||||
`Jellyseerr response error\nerror: ${error.toString()}\nurl: ${error?.config?.url}`,
|
||||
error.response?.data,
|
||||
errorMsg +
|
||||
`\n` +
|
||||
`error: ${error.toString()}\n` +
|
||||
`url: ${error?.config?.url}\n` +
|
||||
`data:\n` +
|
||||
JSON.stringify(error.response?.data),
|
||||
);
|
||||
if (error.status === 403) {
|
||||
clearJellyseerrStorageData();
|
||||
@@ -400,7 +412,7 @@ export class JellyseerrApi {
|
||||
const headerName = this.axios.defaults.xsrfHeaderName!;
|
||||
const xsrfToken = cookies
|
||||
.find((c) => c.includes(headerName))
|
||||
?.split(`${headerName}=`)?.[1];
|
||||
?.split(headerName + "=")?.[1];
|
||||
if (xsrfToken) {
|
||||
config.headers[headerName] = xsrfToken;
|
||||
}
|
||||
@@ -472,7 +484,7 @@ export const useJellyseerr = () => {
|
||||
return (
|
||||
items &&
|
||||
Object.hasOwn(items, "mediaType") &&
|
||||
Object.values(MediaType).includes(items.mediaType)
|
||||
Object.values(MediaType).includes(items["mediaType"])
|
||||
);
|
||||
};
|
||||
|
||||
@@ -480,10 +492,10 @@ export const useJellyseerr = () => {
|
||||
item?: TvResult | TvDetails | MovieResult | MovieDetails,
|
||||
) => {
|
||||
return isJellyseerrResult(item)
|
||||
? item.mediaType === MediaType.MOVIE
|
||||
? item.mediaType == MediaType.MOVIE
|
||||
? item?.title
|
||||
: item?.name
|
||||
: item?.mediaInfo.mediaType === MediaType.MOVIE
|
||||
: item?.mediaInfo.mediaType == MediaType.MOVIE
|
||||
? (item as MovieDetails)?.title
|
||||
: (item as TvDetails)?.name;
|
||||
};
|
||||
@@ -493,10 +505,10 @@ export const useJellyseerr = () => {
|
||||
) => {
|
||||
return new Date(
|
||||
(isJellyseerrResult(item)
|
||||
? item.mediaType === MediaType.MOVIE
|
||||
? item.mediaType == MediaType.MOVIE
|
||||
? item?.releaseDate
|
||||
: item?.firstAirDate
|
||||
: item?.mediaInfo.mediaType === MediaType.MOVIE
|
||||
: item?.mediaInfo.mediaType == MediaType.MOVIE
|
||||
? (item as MovieDetails)?.releaseDate
|
||||
: (item as TvDetails)?.firstAirDate) || "",
|
||||
)?.getFullYear?.();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useDownload } from "@/providers/DownloadProvider";
|
||||
import { apiAtom } from "@/providers/JellyfinProvider";
|
||||
import { getItemImage } from "@/utils/getItemImage";
|
||||
import { writeErrorLog, writeInfoLog } from "@/utils/log";
|
||||
import { writeErrorLog, writeInfoLog, writeToLog } from "@/utils/log";
|
||||
import type {
|
||||
BaseItemDto,
|
||||
MediaSourceInfo,
|
||||
@@ -132,8 +132,8 @@ export const useRemuxHlsToMp4 = () => {
|
||||
totalFrames > 0 ? Math.floor((processedFrames / totalFrames) * 100) : 0;
|
||||
|
||||
if (!item.Id) throw new Error("Item is undefined");
|
||||
setProcesses((prev: JobStatus[]) => {
|
||||
return prev.map((process: JobStatus) => {
|
||||
setProcesses((prev: any[]) => {
|
||||
return prev.map((process: { itemId: string | undefined }) => {
|
||||
if (process.itemId === item.Id) {
|
||||
return {
|
||||
...process,
|
||||
@@ -160,7 +160,7 @@ export const useRemuxHlsToMp4 = () => {
|
||||
});
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
8
i18n.ts
8
i18n.ts
@@ -10,9 +10,7 @@ import it from "./translations/it.json";
|
||||
import ja from "./translations/ja.json";
|
||||
import nl from "./translations/nl.json";
|
||||
import pl from "./translations/pl.json";
|
||||
import ptBR from "./translations/pt-BR.json";
|
||||
import sv from "./translations/sv.json";
|
||||
import ru from "./translations/ru.json";
|
||||
import tr from "./translations/tr.json";
|
||||
import ua from "./translations/ua.json";
|
||||
import zhCN from "./translations/zh-CN.json";
|
||||
@@ -27,10 +25,8 @@ export const APP_LANGUAGES = [
|
||||
{ label: "日本語", value: "ja" },
|
||||
{ label: "Türkçe", value: "tr" },
|
||||
{ label: "Nederlands", value: "nl" },
|
||||
{ label: "Polski", value: "pl" },
|
||||
{ label: "Português (Brasil)", value: "pt-BR" },
|
||||
{ label: 'Polski', value: 'pl' },
|
||||
{ label: "Svenska", value: "sv" },
|
||||
{ label: "Русский", value: "ru" },
|
||||
{ label: "Українська", value: "ua" },
|
||||
{ label: "简体中文", value: "zh-CN" },
|
||||
{ label: "繁體中文", value: "zh-TW" },
|
||||
@@ -47,9 +43,7 @@ i18n.use(initReactI18next).init({
|
||||
ja: { translation: ja },
|
||||
nl: { translation: nl },
|
||||
pl: { translation: pl },
|
||||
"pt-BR": { translation: ptBR },
|
||||
sv: { translation: sv },
|
||||
ru: { translation: ru },
|
||||
tr: { translation: tr },
|
||||
ua: { translation: ua },
|
||||
"zh-CN": { translation: zhCN },
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
import { ViewStyle } from "react-native";
|
||||
|
||||
export type PlaybackStatePayload = {
|
||||
nativeEvent: {
|
||||
target: number;
|
||||
state: "Opening" | "Buffering" | "Playing" | "Paused" | "Error";
|
||||
currentTime: number;
|
||||
duration: number;
|
||||
isBuffering: boolean;
|
||||
isPlaying: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export type ProgressUpdatePayload = {
|
||||
nativeEvent: {
|
||||
currentTime: number;
|
||||
duration: number;
|
||||
isPlaying: boolean;
|
||||
isBuffering: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export type VideoLoadStartPayload = {
|
||||
nativeEvent: {
|
||||
target: number;
|
||||
};
|
||||
};
|
||||
|
||||
export type PipStartedPayload = {
|
||||
nativeEvent: {
|
||||
pipStarted: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export type VideoStateChangePayload = PlaybackStatePayload;
|
||||
|
||||
export type VideoProgressPayload = ProgressUpdatePayload;
|
||||
|
||||
export type MpvPlayerSource = {
|
||||
uri: string;
|
||||
type?: string;
|
||||
isNetwork?: boolean;
|
||||
autoplay?: boolean;
|
||||
externalSubtitles: { name: string; DeliveryUrl: string }[];
|
||||
initOptions?: any[];
|
||||
mediaOptions?: { [key: string]: any };
|
||||
startPosition?: number;
|
||||
};
|
||||
|
||||
export type TrackInfo = {
|
||||
name: string;
|
||||
index: number;
|
||||
language?: string;
|
||||
};
|
||||
|
||||
export type ChapterInfo = {
|
||||
name: string;
|
||||
timeOffset: number;
|
||||
duration: number;
|
||||
};
|
||||
|
||||
export type MpvPlayerViewProps = {
|
||||
source: MpvPlayerSource;
|
||||
style?: ViewStyle | ViewStyle[];
|
||||
progressUpdateInterval?: number;
|
||||
paused?: boolean;
|
||||
muted?: boolean;
|
||||
volume?: number;
|
||||
videoAspectRatio?: string;
|
||||
onVideoProgress?: (event: ProgressUpdatePayload) => void;
|
||||
onVideoStateChange?: (event: PlaybackStatePayload) => void;
|
||||
onVideoLoadStart?: (event: VideoLoadStartPayload) => void;
|
||||
onVideoLoadEnd?: (event: VideoLoadStartPayload) => void;
|
||||
onVideoError?: (event: PlaybackStatePayload) => void;
|
||||
onPipStarted?: (event: PipStartedPayload) => void;
|
||||
};
|
||||
|
||||
export interface MpvPlayerViewRef {
|
||||
startPictureInPicture: () => Promise<void>;
|
||||
play: () => Promise<void>;
|
||||
pause: () => Promise<void>;
|
||||
stop: () => Promise<void>;
|
||||
seekTo: (time: number) => Promise<void>;
|
||||
setAudioTrack: (trackIndex: number) => Promise<void>;
|
||||
getAudioTracks: () => Promise<TrackInfo[] | null>;
|
||||
setSubtitleTrack: (trackIndex: number) => Promise<void>;
|
||||
getSubtitleTracks: () => Promise<TrackInfo[] | null>;
|
||||
setSubtitleDelay: (delay: number) => Promise<void>;
|
||||
setAudioDelay: (delay: number) => Promise<void>;
|
||||
takeSnapshot: (path: string, width: number, height: number) => Promise<void>;
|
||||
setRate: (rate: number) => Promise<void>;
|
||||
nextChapter: () => Promise<void>;
|
||||
previousChapter: () => Promise<void>;
|
||||
getChapters: () => Promise<ChapterInfo[] | null>;
|
||||
setVideoCropGeometry: (geometry: string | null) => Promise<void>;
|
||||
getVideoCropGeometry: () => Promise<string | null>;
|
||||
setSubtitleURL: (url: string, name: string) => Promise<void>;
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
import { requireNativeViewManager } from "expo-modules-core";
|
||||
import * as React from "react";
|
||||
import { ViewStyle } from "react-native";
|
||||
import type {
|
||||
MpvPlayerSource,
|
||||
MpvPlayerViewProps,
|
||||
MpvPlayerViewRef,
|
||||
} from "./MpvPlayer.types";
|
||||
|
||||
interface NativeViewRef extends MpvPlayerViewRef {
|
||||
setNativeProps?: (props: Partial<MpvPlayerViewProps>) => void;
|
||||
}
|
||||
|
||||
const MpvViewManager = requireNativeViewManager("MpvPlayer");
|
||||
|
||||
// Create a forwarded ref version of the native view
|
||||
const NativeView = React.forwardRef<NativeViewRef, MpvPlayerViewProps>(
|
||||
(props, ref) => {
|
||||
return <MpvViewManager {...props} ref={ref} />;
|
||||
},
|
||||
);
|
||||
|
||||
const MpvPlayerView = React.forwardRef<MpvPlayerViewRef, MpvPlayerViewProps>(
|
||||
(props, ref) => {
|
||||
const nativeRef = React.useRef<NativeViewRef>(null);
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
startPictureInPicture: async () => {
|
||||
await nativeRef.current?.startPictureInPicture();
|
||||
},
|
||||
play: async () => {
|
||||
await nativeRef.current?.play();
|
||||
},
|
||||
pause: async () => {
|
||||
await nativeRef.current?.pause();
|
||||
},
|
||||
stop: async () => {
|
||||
await nativeRef.current?.stop();
|
||||
},
|
||||
seekTo: async (time: number) => {
|
||||
await nativeRef.current?.seekTo(time);
|
||||
},
|
||||
setAudioTrack: async (trackIndex: number) => {
|
||||
await nativeRef.current?.setAudioTrack(trackIndex);
|
||||
},
|
||||
getAudioTracks: async () => {
|
||||
const tracks = await nativeRef.current?.getAudioTracks();
|
||||
return tracks ?? null;
|
||||
},
|
||||
setSubtitleTrack: async (trackIndex: number) => {
|
||||
await nativeRef.current?.setSubtitleTrack(trackIndex);
|
||||
},
|
||||
getSubtitleTracks: async () => {
|
||||
const tracks = await nativeRef.current?.getSubtitleTracks();
|
||||
return tracks ?? null;
|
||||
},
|
||||
setSubtitleDelay: async (delay: number) => {
|
||||
await nativeRef.current?.setSubtitleDelay(delay);
|
||||
},
|
||||
setAudioDelay: async (delay: number) => {
|
||||
await nativeRef.current?.setAudioDelay(delay);
|
||||
},
|
||||
takeSnapshot: async (path: string, width: number, height: number) => {
|
||||
await nativeRef.current?.takeSnapshot(path, width, height);
|
||||
},
|
||||
setRate: async (rate: number) => {
|
||||
await nativeRef.current?.setRate(rate);
|
||||
},
|
||||
nextChapter: async () => {
|
||||
await nativeRef.current?.nextChapter();
|
||||
},
|
||||
previousChapter: async () => {
|
||||
await nativeRef.current?.previousChapter();
|
||||
},
|
||||
getChapters: async () => {
|
||||
const chapters = await nativeRef.current?.getChapters();
|
||||
return chapters ?? null;
|
||||
},
|
||||
setVideoCropGeometry: async (geometry: string | null) => {
|
||||
await nativeRef.current?.setVideoCropGeometry(geometry);
|
||||
},
|
||||
getVideoCropGeometry: async () => {
|
||||
const geometry = await nativeRef.current?.getVideoCropGeometry();
|
||||
return geometry ?? null;
|
||||
},
|
||||
setSubtitleURL: async (url: string, name: string) => {
|
||||
await nativeRef.current?.setSubtitleURL(url, name);
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
source,
|
||||
style,
|
||||
progressUpdateInterval = 500,
|
||||
paused,
|
||||
muted,
|
||||
volume,
|
||||
videoAspectRatio,
|
||||
onVideoLoadStart,
|
||||
onVideoStateChange,
|
||||
onVideoProgress,
|
||||
onVideoLoadEnd,
|
||||
onVideoError,
|
||||
onPipStarted,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
const processedSource: MpvPlayerSource =
|
||||
typeof source === "string"
|
||||
? ({ uri: source } as unknown as MpvPlayerSource)
|
||||
: source;
|
||||
|
||||
if (processedSource.startPosition !== undefined) {
|
||||
processedSource.startPosition = Math.floor(processedSource.startPosition);
|
||||
}
|
||||
|
||||
return (
|
||||
<NativeView
|
||||
{...otherProps}
|
||||
ref={nativeRef}
|
||||
source={processedSource}
|
||||
style={[{ width: "100%", height: "100%" }, style as ViewStyle]}
|
||||
progressUpdateInterval={progressUpdateInterval}
|
||||
paused={paused}
|
||||
muted={muted}
|
||||
volume={volume}
|
||||
videoAspectRatio={videoAspectRatio}
|
||||
onVideoLoadStart={onVideoLoadStart}
|
||||
onVideoLoadEnd={onVideoLoadEnd}
|
||||
onVideoStateChange={onVideoStateChange}
|
||||
onVideoProgress={onVideoProgress}
|
||||
onVideoError={onVideoError}
|
||||
onPipStarted={onPipStarted}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export default MpvPlayerView;
|
||||
@@ -1,5 +1,3 @@
|
||||
import { ViewStyle } from "react-native";
|
||||
|
||||
export type PlaybackStatePayload = {
|
||||
nativeEvent: {
|
||||
target: number;
|
||||
@@ -61,7 +59,7 @@ export type ChapterInfo = {
|
||||
|
||||
export type VlcPlayerViewProps = {
|
||||
source: VlcPlayerSource;
|
||||
style?: ViewStyle | ViewStyle[];
|
||||
style?: Object;
|
||||
progressUpdateInterval?: number;
|
||||
paused?: boolean;
|
||||
muted?: boolean;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user