diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 1ac06eda..a38e5f84 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -43,7 +43,9 @@ body:
label: Version
description: What version of Streamyfin are you running?
options:
+ - 0.25.0
- 0.24.0
+ - 0.23.0
- 0.22.0
- 0.21.0
- older
diff --git a/.github/workflows/lint-pr.yaml b/.github/workflows/lint-pr.yaml
new file mode 100644
index 00000000..68e2bd8e
--- /dev/null
+++ b/.github/workflows/lint-pr.yaml
@@ -0,0 +1,41 @@
+name: "Lint PR"
+
+on:
+ pull_request_target:
+ types:
+ - opened
+ - edited
+ - synchronize
+ - reopened
+
+permissions:
+ pull-requests: write
+
+jobs:
+ main:
+ name: Validate PR title
+ runs-on: ubuntu-latest
+ steps:
+ - uses: amannn/action-semantic-pull-request@v5
+ id: lint_pr_title
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ - uses: marocchino/sticky-pull-request-comment@v2
+ if: always() && (steps.lint_pr_title.outputs.error_message != null)
+ with:
+ header: pr-title-lint-error
+ message: |
+ Hey there and thank you for opening this pull request! ๐๐ผ
+
+ We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted.
+
+ Details:
+
+ ```
+ ${{ steps.lint_pr_title.outputs.error_message }}
+ ```
+ - if: ${{ steps.lint_pr_title.outputs.error_message == null }}
+ uses: marocchino/sticky-pull-request-comment@v2
+ with:
+ header: pr-title-lint-error
+ delete: true
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index b14fd39c..496a7870 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,4 +39,6 @@ credentials.json
*.ipa
.continuerc.json
-.vscode/
\ No newline at end of file
+.vscode/
+.idea/
+.ruby-lsp
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 26d33521..00000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/.idea/caches/deviceStreaming.xml b/.idea/caches/deviceStreaming.xml
deleted file mode 100644
index b81700b5..00000000
--- a/.idea/caches/deviceStreaming.xml
+++ /dev/null
@@ -1,329 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 639900d1..00000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index ba6d5c31..00000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/streamyfin.iml b/.idea/streamyfin.iml
deleted file mode 100644
index d6ebd480..00000000
--- a/.idea/streamyfin.iml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 35eb1ddf..00000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index 6b3bcf99..533dd65f 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Welcome to Streamyfin, a simple and user-friendly Jellyfin client built with Exp
-
+
## ๐ Features
@@ -32,22 +32,17 @@ Downloading works by using ffmpeg to convert an HLS stream into a video file on
Chromecast support is still in development, and we're working on improving it. Currently, it supports casting videos and audio, but we're working on adding support for subtitles and other features.
-## Plugins
+### Streamyfin Plugin
-In Streamyfin we have built-in support for a few plugins. These plugins are not required to use Streamyfin, but they add some extra functionality.
+The Jellyfin Plugin for Streamyfin is a plugin you install into Jellyfin that hold all settings for the client Streamyfin. This allows you to syncronize settings accross all your users, like:
-### Collection rows
+- Auto log in to Jellyseerr without the user having to do anythin
+- Choose the default languages
+- Set download method and search provider
+- Customize homescreen
+- And more...
-Jellyfin collections can be shown as rows or carousel on the home screen.
-The following tags can be added to a collection to provide this functionality.
-
-Available tags:
-
-- sf_promoted: will make the collection a row at home
-- sf_carousel: will make the collection a carousel on home.
-
-A plugin exists to create collections based on external sources like mdblist. This make the automatic process of managing collections such as trending, most watched, etc.
-See [Collection Import Plugin](https://github.com/lostb1t/jellyfin-plugin-collection-import) for more info.
+[Streamyfin Plugin](https://github.com/streamyfin/jellyfin-plugin-streamyfin)
### Jellysearch
@@ -70,7 +65,7 @@ Or download the APKs [here on GitHub](https://github.com/streamyfin/streamyfin/r
### Beta testing
-To access the Streamyfin beta, you need to subscribe to the Member tier (or higher) on [Patreon](https://www.patreon.com/streamyfin). This will give you immediate access to the โ ๐งช-public-beta channel on Discord and i'll know that you have subscribed. This is where i'll post APKs and IPAs. This won't give automatic access to the TestFlight however, so you need to send me a DM with the email you use for Apple so that i can manually add you.
+To access the Streamyfin beta, you need to subscribe to the Member tier (or higher) on [Patreon](https://www.patreon.com/streamyfin). This will give you immediate access to the โ ๐งช-public-beta channel on Discord and i'll know that you have subscribed. This is where I post APKs and IPAs. This won't give automatic access to the TestFlight, however, so you need to send me a DM with the email you use for Apple so that i can manually add you.
**Note**: Everyone who is actively contributing to the source code of Streamyfin will have automatic access to the betas.
@@ -90,7 +85,7 @@ 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.
-4. Create an expo dev build by running `npx expo run:ios` or `npx expo run:android`. This will open a simulator on you computer and run the app.
+4. Create an expo dev build by running `npx expo run:ios` or `npx expo run:android`. This will open a simulator on your computer and run the app.
## ๐ License
diff --git a/app.config.js b/app.config.js
index a6b72ec0..30ae0d5b 100644
--- a/app.config.js
+++ b/app.config.js
@@ -1,5 +1,5 @@
module.exports = ({ config }) => {
- if (process.env.EXPO_TV === "1") {
+ if (process.env.EXPO_TV != "1") {
config.plugins.push([
"react-native-google-cast",
{ useDefaultExpandedMediaControls: true },
diff --git a/app.json b/app.json
index d5f972c5..fd31d80f 100644
--- a/app.json
+++ b/app.json
@@ -2,15 +2,14 @@
"expo": {
"name": "Streamyfin",
"slug": "streamyfin",
- "version": "0.24.0",
+ "version": "0.25.0",
"orientation": "default",
"icon": "./assets/images/icon.png",
"scheme": "streamyfin",
"userInterfaceStyle": "dark",
"splash": {
"image": "./assets/images/splash.png",
- "resizeMode": "contain",
- "backgroundColor": "#2E2E2E"
+ "resizeMode": "contain"
},
"jsEngine": "hermes",
"assetBundlePatterns": [
@@ -91,7 +90,9 @@
"jniLibs": {
"useLegacyPackaging": true
}
- }
+ },
+ "useAndroidX": true,
+ "enableJetifier": true
}
}
],
@@ -107,6 +108,7 @@
"motionPermission": "Allow Streamyfin to access your device motion for landscape video watching."
}
],
+ "expo-localization",
"expo-asset",
[
"react-native-edge-to-edge",
@@ -121,6 +123,12 @@
],
[
"./plugins/withChangeNativeAndroidTextToWhite.js"
+ ],
+ [
+ "./plugins/withGoogleCastActivity.js"
+ ],
+ [
+ "./plugins/withTrustLocalCerts.js"
]
],
"experiments": {
diff --git a/app/(auth)/(tabs)/(custom-links)/_layout.tsx b/app/(auth)/(tabs)/(custom-links)/_layout.tsx
index ed0529d4..c270b95d 100644
--- a/app/(auth)/(tabs)/(custom-links)/_layout.tsx
+++ b/app/(auth)/(tabs)/(custom-links)/_layout.tsx
@@ -1,7 +1,9 @@
import {Stack} from "expo-router";
import { Platform } from "react-native";
+import { useTranslation } from "react-i18next";
export default function CustomMenuLayout() {
+ const { t } = useTranslation();
return (
([]);
+ const { t } = useTranslation();
const getMenuLinks = useCallback(async () => {
try {
@@ -75,7 +77,7 @@ export default function menuLinks() {
)}
ListEmptyComponent={
- No links
+ {t("custom_links.no_links")}
}
/>
diff --git a/app/(auth)/(tabs)/(favorites)/_layout.tsx b/app/(auth)/(tabs)/(favorites)/_layout.tsx
index d48dc614..b408eab6 100644
--- a/app/(auth)/(tabs)/(favorites)/_layout.tsx
+++ b/app/(auth)/(tabs)/(favorites)/_layout.tsx
@@ -1,8 +1,10 @@
import { nestedTabPageScreenOptions } from "@/components/stacks/NestedTabPageStack";
import { Stack } from "expo-router";
import { Platform } from "react-native";
+import { useTranslation } from "react-i18next";
export default function SearchLayout() {
+ const { t } = useTranslation();
return (
import("@/components/Chromecast"));
export default function IndexLayout() {
const router = useRouter();
+ const { t } = useTranslation();
return (
+
+
{Object.entries(nestedTabPageScreenOptions).map(([name, options]) => (
))}
diff --git a/app/(auth)/(tabs)/(home)/downloads/index.tsx b/app/(auth)/(tabs)/(home)/downloads/index.tsx
index 56f21af3..51991f1b 100644
--- a/app/(auth)/(tabs)/(home)/downloads/index.tsx
+++ b/app/(auth)/(tabs)/(home)/downloads/index.tsx
@@ -4,7 +4,7 @@ import { MovieCard } from "@/components/downloads/MovieCard";
import { SeriesCard } from "@/components/downloads/SeriesCard";
import { DownloadedItem, useDownload } from "@/providers/DownloadProvider";
import { queueAtom } from "@/utils/atoms/queue";
-import { useSettings } from "@/utils/atoms/settings";
+import {DownloadMethod, useSettings} from "@/utils/atoms/settings";
import { Ionicons } from "@expo/vector-icons";
import { useNavigation, useRouter } from "expo-router";
import { useAtom } from "jotai";
@@ -12,6 +12,8 @@ import React, { useEffect, useMemo, useRef } from "react";
import { Alert, ScrollView, TouchableOpacity, View } from "react-native";
import { Button } from "@/components/Button";
import { useSafeAreaInsets } from "react-native-safe-area-context";
+import { useTranslation } from "react-i18next";
+import { t } from 'i18next';
import { DownloadSize } from "@/components/downloads/DownloadSize";
import {
BottomSheetBackdrop,
@@ -24,6 +26,7 @@ import { writeToLog } from "@/utils/log";
export default function page() {
const navigation = useNavigation();
+ const { t } = useTranslation();
const [queue, setQueue] = useAtom(queueAtom);
const { removeProcess, downloadedFiles, deleteFileByType } = useDownload();
const router = useRouter();
@@ -70,17 +73,17 @@ export default function page() {
const deleteMovies = () =>
deleteFileByType("Movie")
- .then(() => toast.success("Deleted all movies successfully!"))
+ .then(() => toast.success(t("home.downloads.toasts.deleted_all_movies_successfully")))
.catch((reason) => {
writeToLog("ERROR", reason);
- toast.error("Failed to delete all movies");
+ toast.error(t("home.downloads.toasts.failed_to_delete_all_movies"));
});
const deleteShows = () =>
deleteFileByType("Episode")
- .then(() => toast.success("Deleted all TV-Series successfully!"))
+ .then(() => toast.success(t("home.downloads.toasts.deleted_all_tvseries_successfully")))
.catch((reason) => {
writeToLog("ERROR", reason);
- toast.error("Failed to delete all TV-Series");
+ toast.error(t("home.downloads.toasts.failed_to_delete_all_tvseries"));
});
const deleteAllMedia = async () =>
await Promise.all([deleteMovies(), deleteShows()]);
@@ -96,11 +99,11 @@ export default function page() {
>
- {settings?.downloadMethod === "remux" && (
+ {settings?.downloadMethod === DownloadMethod.Remux && (
- Queue
+ {t("home.downloads.queue")}
- Queue and active downloads will be lost on app restart
+ {t("home.downloads.queue_hint")}
{queue.map((q, index) => (
@@ -133,7 +136,7 @@ export default function page() {
{queue.length === 0 && (
- No items in queue
+ {t("home.downloads.no_items_in_queue")}
)}
)}
@@ -144,7 +147,7 @@ export default function page() {
{movies.length > 0 && (
- Movies
+ {t("home.downloads.movies")}
{movies?.length}
@@ -163,7 +166,7 @@ export default function page() {
{groupedBySeries.length > 0 && (
- TV-Series
+ {t("home.downloads.tvseries")}
{groupedBySeries?.length}
@@ -189,7 +192,7 @@ export default function page() {
)}
{downloadedFiles?.length === 0 && (
- No downloaded items
+ {t("home.downloads.no_downloaded_items")}
)}
@@ -214,13 +217,13 @@ export default function page() {
@@ -233,15 +236,15 @@ function migration_20241124() {
const router = useRouter();
const { deleteAllFiles } = useDownload();
Alert.alert(
- "New app version requires re-download",
- "The new update reqires content to be downloaded again. Please remove all downloaded content and try again.",
+ t("home.downloads.new_app_version_requires_re_download"),
+ t("home.downloads.new_app_version_requires_re_download_description"),
[
{
- text: "Back",
+ text: t("home.downloads.back"),
onPress: () => router.back(),
},
{
- text: "Delete",
+ text: t("home.downloads.delete"),
style: "destructive",
onPress: async () => await deleteAllFiles(),
},
diff --git a/app/(auth)/(tabs)/(home)/index.tsx b/app/(auth)/(tabs)/(home)/index.tsx
index 76964325..0a1d8fca 100644
--- a/app/(auth)/(tabs)/(home)/index.tsx
+++ b/app/(auth)/(tabs)/(home)/index.tsx
@@ -23,11 +23,12 @@ import {
getUserViewsApi,
} from "@jellyfin/sdk/lib/utils/api";
import NetInfo from "@react-native-community/netinfo";
-import { QueryFunction, useQuery, useQueryClient } from "@tanstack/react-query";
+import { QueryFunction, useQuery } from "@tanstack/react-query";
import { useNavigation, useRouter } from "expo-router";
import { useAtomValue } from "jotai";
import { useCallback, useEffect, useMemo, useState } from "react";
import { Platform } from "react-native";
+import { useTranslation } from "react-i18next";
import {
ActivityIndicator,
RefreshControl,
@@ -36,6 +37,10 @@ import {
View,
} from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
+import {
+ useSplashScreenLoading,
+ useSplashScreenVisible,
+} from "@/providers/SplashScreenProvider";
type ScrollingCollectionListSection = {
type: "ScrollingCollectionList";
@@ -56,11 +61,19 @@ type Section = ScrollingCollectionListSection | MediaListSection;
export default function index() {
const router = useRouter();
+ const { t } = useTranslation();
+
const api = useAtomValue(apiAtom);
const user = useAtomValue(userAtom);
const [loading, setLoading] = useState(false);
- const [settings, _] = useSettings();
+ const [
+ settings,
+ updateSettings,
+ pluginSettings,
+ setPluginSettings,
+ refreshStreamyfinPluginSettings,
+ ] = useSettings();
const [isConnected, setIsConnected] = useState(null);
const [loadingRetry, setLoadingRetry] = useState(false);
@@ -116,13 +129,17 @@ export default function index() {
setIsConnected(state.isConnected);
});
+ // cleanCacheDirectory().catch((e) =>
+ // console.error("Something went wrong cleaning cache directory")
+ // );
+
return () => {
unsubscribe();
};
}, []);
const {
- data: userViews,
+ data,
isError: e1,
isLoading: l1,
} = useQuery({
@@ -142,28 +159,14 @@ export default function index() {
staleTime: 60 * 1000,
});
- const {
- data: mediaListCollections,
- isError: e2,
- isLoading: l2,
- } = useQuery({
- queryKey: ["home", "sf_promoted", user?.Id, settings?.usePopularPlugin],
- queryFn: async () => {
- if (!api || !user?.Id) return [];
+ // show splash screen until query loaded
+ useSplashScreenLoading(l1);
+ const splashScreenVisible = useSplashScreenVisible();
- const response = await getItemsApi(api).getItems({
- userId: user.Id,
- tags: ["sf_promoted"],
- recursive: true,
- fields: ["Tags"],
- includeItemTypes: ["BoxSet"],
- });
-
- return response.data.Items || [];
- },
- enabled: !!api && !!user?.Id && settings?.usePopularPlugin === true,
- staleTime: 60 * 1000,
- });
+ const userViews = useMemo(
+ () => data?.filter((l) => !settings?.hiddenLibraries?.includes(l.Id!)),
+ [data, settings?.hiddenLibraries]
+ );
const collections = useMemo(() => {
const allow = ["movies", "tvshows"];
@@ -178,6 +181,7 @@ export default function index() {
const refetch = useCallback(async () => {
setLoading(true);
+ await refreshStreamyfinPluginSettings();
await invalidateCache();
setLoading(false);
}, []);
@@ -212,114 +216,161 @@ export default function index() {
[api, user?.Id]
);
- const sections = useMemo(() => {
- if (!api || !user?.Id) return [];
+ let sections: Section[] = [];
+ if (!settings?.home || !settings?.home?.sections) {
+ sections = useMemo(() => {
+ if (!api || !user?.Id) return [];
- const latestMediaViews = collections.map((c) => {
- const includeItemTypes: BaseItemKind[] =
- c.CollectionType === "tvshows" ? ["Series"] : ["Movie"];
- const title = "Recently Added in " + c.Name;
- const queryKey = [
- "home",
- "recentlyAddedIn" + c.CollectionType,
- user?.Id!,
- c.Id!,
- ];
- return createCollectionConfig(
- title || "",
- queryKey,
- includeItemTypes,
- c.Id
- );
- });
+ const latestMediaViews = collections.map((c) => {
+ const includeItemTypes: BaseItemKind[] =
+ c.CollectionType === "tvshows" ? ["Series"] : ["Movie"];
+ const title = t("home.recently_added_in", { libraryName: c.Name });
+ const queryKey = [
+ "home",
+ "recentlyAddedIn" + c.CollectionType,
+ user?.Id!,
+ c.Id!,
+ ];
+ return createCollectionConfig(
+ title || "",
+ queryKey,
+ includeItemTypes,
+ c.Id
+ );
+ });
- const ss: Section[] = [
- {
- title: "Continue Watching",
- queryKey: ["home", "resumeItems"],
- queryFn: async () =>
- (
- await getItemsApi(api).getResumeItems({
- userId: user.Id,
- enableImageTypes: ["Primary", "Backdrop", "Thumb"],
- includeItemTypes: ["Movie", "Series", "Episode"],
- })
- ).data.Items || [],
- type: "ScrollingCollectionList",
- orientation: "horizontal",
- },
- {
- title: "Next Up",
- queryKey: ["home", "nextUp-all"],
- queryFn: async () =>
- (
- await getTvShowsApi(api).getNextUp({
- userId: user?.Id,
- fields: ["MediaSourceCount"],
- limit: 20,
- enableImageTypes: ["Primary", "Backdrop", "Thumb"],
- enableResumable: false,
- })
- ).data.Items || [],
- type: "ScrollingCollectionList",
- orientation: "horizontal",
- },
- ...latestMediaViews,
- ...(mediaListCollections?.map(
- (ml) =>
- ({
- title: ml.Name,
- queryKey: ["home", "mediaList", ml.Id!],
- queryFn: async () => ml,
- type: "MediaListSection",
- orientation: "vertical",
- } as Section)
- ) || []),
- {
- title: "Suggested Movies",
- queryKey: ["home", "suggestedMovies", user?.Id],
- queryFn: async () =>
- (
- await getSuggestionsApi(api).getSuggestions({
- userId: user?.Id,
- limit: 10,
- mediaType: ["Video"],
- type: ["Movie"],
- })
- ).data.Items || [],
- type: "ScrollingCollectionList",
- orientation: "vertical",
- },
- {
- title: "Suggested Episodes",
- queryKey: ["home", "suggestedEpisodes", user?.Id],
- queryFn: async () => {
- try {
- const suggestions = await getSuggestions(api, user.Id);
- const nextUpPromises = suggestions.map((series) =>
- getNextUp(api, user.Id, series.Id)
- );
- const nextUpResults = await Promise.all(nextUpPromises);
-
- return nextUpResults.filter((item) => item !== null) || [];
- } catch (error) {
- console.error("Error fetching data:", error);
- return [];
- }
+ const ss: Section[] = [
+ {
+ title: t("home.continue_watching"),
+ queryKey: ["home", "resumeItems"],
+ queryFn: async () =>
+ (
+ await getItemsApi(api).getResumeItems({
+ userId: user.Id,
+ enableImageTypes: ["Primary", "Backdrop", "Thumb"],
+ includeItemTypes: ["Movie", "Series", "Episode"],
+ })
+ ).data.Items || [],
+ type: "ScrollingCollectionList",
+ orientation: "horizontal",
},
- type: "ScrollingCollectionList",
- orientation: "horizontal",
- },
- ];
- return ss;
- }, [api, user?.Id, collections, mediaListCollections]);
+ {
+ title: t("home.next_up"),
+ queryKey: ["home", "nextUp-all"],
+ queryFn: async () =>
+ (
+ await getTvShowsApi(api).getNextUp({
+ userId: user?.Id,
+ fields: ["MediaSourceCount"],
+ limit: 20,
+ enableImageTypes: ["Primary", "Backdrop", "Thumb"],
+ enableResumable: false,
+ })
+ ).data.Items || [],
+ type: "ScrollingCollectionList",
+ orientation: "horizontal",
+ },
+ ...latestMediaViews,
+ // ...(mediaListCollections?.map(
+ // (ml) =>
+ // ({
+ // title: ml.Name,
+ // queryKey: ["home", "mediaList", ml.Id!],
+ // queryFn: async () => ml,
+ // type: "MediaListSection",
+ // orientation: "vertical",
+ // } as Section)
+ // ) || []),
+ {
+ title: t("home.suggested_movies"),
+ queryKey: ["home", "suggestedMovies", user?.Id],
+ queryFn: async () =>
+ (
+ await getSuggestionsApi(api).getSuggestions({
+ userId: user?.Id,
+ limit: 10,
+ mediaType: ["Video"],
+ type: ["Movie"],
+ })
+ ).data.Items || [],
+ type: "ScrollingCollectionList",
+ orientation: "vertical",
+ },
+ {
+ title: t("home.suggested_episodes"),
+ queryKey: ["home", "suggestedEpisodes", user?.Id],
+ queryFn: async () => {
+ try {
+ const suggestions = await getSuggestions(api, user.Id);
+ const nextUpPromises = suggestions.map((series) =>
+ getNextUp(api, user.Id, series.Id)
+ );
+ const nextUpResults = await Promise.all(nextUpPromises);
+
+ return nextUpResults.filter((item) => item !== null) || [];
+ } catch (error) {
+ console.error("Error fetching data:", error);
+ return [];
+ }
+ },
+ type: "ScrollingCollectionList",
+ orientation: "horizontal",
+ },
+ ];
+ return ss;
+ }, [api, user?.Id, collections]);
+ } else {
+ sections = useMemo(() => {
+ if (!api || !user?.Id) return [];
+ const ss: Section[] = [];
+
+ for (const key in settings.home?.sections) {
+ // @ts-expect-error
+ const section = settings.home?.sections[key];
+ const id = section.title || key;
+ ss.push({
+ title: id,
+ queryKey: ["home", id],
+ queryFn: async () => {
+ if (section.items) {
+ const response = await getItemsApi(api).getItems({
+ userId: user?.Id,
+ limit: section.items?.limit || 25,
+ recursive: true,
+ includeItemTypes: section.items?.includeItemTypes,
+ sortBy: section.items?.sortBy,
+ sortOrder: section.items?.sortOrder,
+ filters: section.items?.filters,
+ parentId: section.items?.parentId,
+ });
+ return response.data.Items || [];
+ } 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 || false,
+ enableRewatching: section.items?.enableRewatching || false,
+ });
+ return response.data.Items || [];
+ }
+ return [];
+ },
+ type: "ScrollingCollectionList",
+ orientation: section?.orientation || "vertical",
+ });
+ }
+ return ss;
+ }, [api, user?.Id, settings.home?.sections]);
+ }
if (isConnected === false) {
return (
- No Internet
+ {t("home.no_internet")}
- No worries, you can still watch{"\n"}downloaded content.
+ {t("home.no_internet_message")}
}
>
- Go to downloads
+ {t("home.go_to_downloads")}
);
- if (l1 || l2)
+ // this spinner should only show up, when user navigates here
+ // on launch the splash screen is used for loading
+ if (l1 && !splashScreenVisible)
return (
@@ -398,6 +451,7 @@ export default function index() {
queryKey={section.queryKey}
queryFn={section.queryFn}
orientation={section.orientation}
+ hideIfEmpty
/>
);
} else if (section.type === "MediaListSection") {
diff --git a/app/(auth)/(tabs)/(home)/intro/page.tsx b/app/(auth)/(tabs)/(home)/intro/page.tsx
new file mode 100644
index 00000000..7aae4ae2
--- /dev/null
+++ b/app/(auth)/(tabs)/(home)/intro/page.tsx
@@ -0,0 +1,135 @@
+import { Button } from "@/components/Button";
+import { Text } from "@/components/common/Text";
+import { storage } from "@/utils/mmkv";
+import { Feather, Ionicons } from "@expo/vector-icons";
+import { Image } from "expo-image";
+import { useFocusEffect, useRouter } from "expo-router";
+import { useCallback } from "react";
+import {useTranslation } from "react-i18next";
+import { Linking, TouchableOpacity, View } from "react-native";
+
+export default function page() {
+ const router = useRouter();
+ const { t } = useTranslation();
+
+ useFocusEffect(
+ useCallback(() => {
+ storage.set("hasShownIntro", true);
+ }, [])
+ );
+
+ return (
+
+
+
+ {t("home.intro.welcome_to_streamyfin")}
+
+
+ {t("home.intro.a_free_and_open_source_client_for_jellyfin")}
+
+
+
+
+ {t("home.intro.features_title")}
+
+ {t("home.intro.features_description")}
+
+
+
+
+ Jellyseerr
+
+ {t("home.intro.jellyseerr_feature_description")}
+
+
+
+
+
+
+
+
+ {t("home.intro.downloads_feature_title")}
+
+ {t("home.intro.downloads_feature_description")}
+
+
+
+
+
+
+
+
+ Chromecast
+
+ {t("home.intro.chromecast_feature_description")}
+
+
+
+
+
+
+
+
+ {t("home.intro.centralised_settings_plugin_title")}
+
+ {t("home.intro.centralised_settings_plugin_description")}{" "}
+ {
+ Linking.openURL(
+ "https://github.com/streamyfin/jellyfin-plugin-streamyfin"
+ );
+ }}
+ >
+ {t("home.intro.read_more")}
+
+
+
+
+
+
+
+ {
+ router.back();
+ router.push("/settings");
+ }}
+ className="mt-4"
+ >
+ {t("home.intro.go_to_settings_button")}
+
+
+
+ );
+}
diff --git a/app/(auth)/(tabs)/(home)/settings.tsx b/app/(auth)/(tabs)/(home)/settings.tsx
index 4c14f754..5828c88f 100644
--- a/app/(auth)/(tabs)/(home)/settings.tsx
+++ b/app/(auth)/(tabs)/(home)/settings.tsx
@@ -3,7 +3,6 @@ import { Text } from "@/components/common/Text";
import { ListGroup } from "@/components/list/ListGroup";
import { ListItem } from "@/components/list/ListItem";
import { AudioToggles } from "@/components/settings/AudioToggles";
-import { DownloadSettings } from "@/components/settings/DownloadSettings";
import { MediaProvider } from "@/components/settings/MediaContext";
import { MediaToggles } from "@/components/settings/MediaToggles";
import { OtherSettings } from "@/components/settings/OtherSettings";
@@ -11,26 +10,30 @@ import { PluginSettings } from "@/components/settings/PluginSettings";
import { QuickConnect } from "@/components/settings/QuickConnect";
import { StorageSettings } from "@/components/settings/StorageSettings";
import { SubtitleToggles } from "@/components/settings/SubtitleToggles";
+import { AppLanguageSelector } from "@/components/settings/AppLanguageSelector";
import { UserInfo } from "@/components/settings/UserInfo";
import { useJellyfin } from "@/providers/JellyfinProvider";
import { clearLogs } from "@/utils/log";
-// const Haptics = !Platform.isTV ? require("expo-haptics") : null;
-import * as Haptics from "@/packages/expo-haptics";
+import { useHaptic } from "@/hooks/useHaptic";
import { useNavigation, useRouter } from "expo-router";
-import { useEffect } from "react";
+import { t } from "i18next";
+import React, { lazy, useEffect } from "react";
import { ScrollView, TouchableOpacity, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
+import { storage } from "@/utils/mmkv";
+const DownloadSettings = lazy(
+ () => import("@/components/settings/DownloadSettings")
+);
export default function settings() {
const router = useRouter();
const insets = useSafeAreaInsets();
const { logout } = useJellyfin();
+ const successHapticFeedback = useHaptic("success");
const onClearLogsClicked = async () => {
clearLogs();
- if (!Platform.isTV) {
- Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
- }
+ successHapticFeedback();
};
const navigation = useNavigation();
@@ -42,7 +45,9 @@ export default function settings() {
logout();
}}
>
- Log out
+
+ {t("home.settings.log_out_button")}
+
),
});
@@ -66,21 +71,40 @@ export default function settings() {
-
+
+ {!Platform.isTV && }
+
+
+
+ {
+ router.push("/intro/page");
+ }}
+ title={t("home.settings.intro.show_intro")}
+ />
+ {
+ storage.set("hasShownIntro", false);
+ }}
+ title={t("home.settings.intro.reset_intro")}
+ />
+
+
-
+
router.push("/settings/logs/page")}
showArrow
- title={"Logs"}
+ title={t("home.settings.logs.logs_title")}
/>
diff --git a/app/(auth)/(tabs)/(home)/settings/hide-libraries/page.tsx b/app/(auth)/(tabs)/(home)/settings/hide-libraries/page.tsx
new file mode 100644
index 00000000..5b96ddbc
--- /dev/null
+++ b/app/(auth)/(tabs)/(home)/settings/hide-libraries/page.tsx
@@ -0,0 +1,67 @@
+import { Text } from "@/components/common/Text";
+import { ListGroup } from "@/components/list/ListGroup";
+import { ListItem } from "@/components/list/ListItem";
+import { Loader } from "@/components/Loader";
+import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
+import { useSettings } from "@/utils/atoms/settings";
+import { getUserViewsApi } from "@jellyfin/sdk/lib/utils/api";
+import { useQuery } from "@tanstack/react-query";
+import { useAtomValue } from "jotai";
+import { Switch, View } from "react-native";
+import { useTranslation } from "react-i18next";
+import DisabledSetting from "@/components/settings/DisabledSetting";
+
+export default function page() {
+ const [settings, updateSettings, pluginSettings] = useSettings();
+ const user = useAtomValue(userAtom);
+ const api = useAtomValue(apiAtom);
+
+ const { t } = useTranslation();
+
+ const { data, isLoading: isLoading } = useQuery({
+ queryKey: ["user-views", user?.Id],
+ queryFn: async () => {
+ const response = await getUserViewsApi(api!).getUserViews({
+ userId: user?.Id,
+ });
+
+ return response.data.Items || null;
+ },
+ });
+
+ if (!settings) return null;
+
+ if (isLoading)
+ return (
+
+
+
+ );
+
+ return (
+
+
+ {data?.map((view) => (
+ {}}>
+ {
+ updateSettings({
+ hiddenLibraries: value
+ ? [...(settings.hiddenLibraries || []), view.Id!]
+ : settings.hiddenLibraries?.filter((id) => id !== view.Id),
+ });
+ }}
+ />
+
+ ))}
+
+
+ {t("home.settings.other.select_liraries_you_want_to_hide")}
+
+
+ );
+}
diff --git a/app/(auth)/(tabs)/(home)/settings/jellyseerr/page.tsx b/app/(auth)/(tabs)/(home)/settings/jellyseerr/page.tsx
index af4247d5..5da08ff1 100644
--- a/app/(auth)/(tabs)/(home)/settings/jellyseerr/page.tsx
+++ b/app/(auth)/(tabs)/(home)/settings/jellyseerr/page.tsx
@@ -1,78 +1,16 @@
-import { Text } from "@/components/common/Text";
import { JellyseerrSettings } from "@/components/settings/Jellyseerr";
-import { OptimizedServerForm } from "@/components/settings/OptimizedServerForm";
-import { apiAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings";
-import { getOrSetDeviceId } from "@/utils/device";
-import { getStatistics } from "@/utils/optimize-server";
-import { useMutation } from "@tanstack/react-query";
-import { useNavigation } from "expo-router";
-import { useAtom } from "jotai";
-import { useEffect, useState } from "react";
-import { ActivityIndicator, TouchableOpacity, View } from "react-native";
-import { toast } from "sonner-native";
+import DisabledSetting from "@/components/settings/DisabledSetting";
export default function page() {
- const navigation = useNavigation();
-
- const [api] = useAtom(apiAtom);
- const [settings, updateSettings] = useSettings();
-
- const [optimizedVersionsServerUrl, setOptimizedVersionsServerUrl] =
- useState(settings?.optimizedVersionsServerUrl || "");
-
- const saveMutation = useMutation({
- mutationFn: async (newVal: string) => {
- if (newVal.length === 0 || !newVal.startsWith("http")) {
- toast.error("Invalid URL");
- return;
- }
-
- const updatedUrl = newVal.endsWith("/") ? newVal : newVal + "/";
-
- updateSettings({
- optimizedVersionsServerUrl: updatedUrl,
- });
-
- return await getStatistics({
- url: settings?.optimizedVersionsServerUrl,
- authHeader: api?.accessToken,
- deviceId: getOrSetDeviceId(),
- });
- },
- onSuccess: (data) => {
- if (data) {
- toast.success("Connected");
- } else {
- toast.error("Could not connect");
- }
- },
- onError: () => {
- toast.error("Could not connect");
- },
- });
-
- const onSave = (newVal: string) => {
- saveMutation.mutate(newVal);
- };
-
- // useEffect(() => {
- // navigation.setOptions({
- // title: "Optimized Server",
- // headerRight: () =>
- // saveMutation.isPending ? (
- //
- // ) : (
- // onSave(optimizedVersionsServerUrl)}>
- // Save
- //
- // ),
- // });
- // }, [navigation, optimizedVersionsServerUrl, saveMutation.isPending]);
+ const [settings, updateSettings, pluginSettings] = useSettings();
return (
-
+
-
+
);
}
diff --git a/app/(auth)/(tabs)/(home)/settings/logs/page.tsx b/app/(auth)/(tabs)/(home)/settings/logs/page.tsx
index 2e023c7d..1c59ba15 100644
--- a/app/(auth)/(tabs)/(home)/settings/logs/page.tsx
+++ b/app/(auth)/(tabs)/(home)/settings/logs/page.tsx
@@ -1,9 +1,11 @@
import { Text } from "@/components/common/Text";
import { useLog } from "@/utils/log";
import { ScrollView, View } from "react-native";
+import { useTranslation } from "react-i18next";
export default function page() {
const { logs } = useLog();
+ const { t } = useTranslation();
return (
@@ -25,7 +27,7 @@ export default function page() {
))}
{logs?.length === 0 && (
- No logs available
+ {t("home.settings.logs.no_logs_available")}
)}
diff --git a/app/(auth)/(tabs)/(home)/settings/marlin-search/page.tsx b/app/(auth)/(tabs)/(home)/settings/marlin-search/page.tsx
index b8255c6e..b67f6ea0 100644
--- a/app/(auth)/(tabs)/(home)/settings/marlin-search/page.tsx
+++ b/app/(auth)/(tabs)/(home)/settings/marlin-search/page.tsx
@@ -1,12 +1,12 @@
import { Text } from "@/components/common/Text";
import { ListGroup } from "@/components/list/ListGroup";
import { ListItem } from "@/components/list/ListItem";
-import { apiAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings";
import { useQueryClient } from "@tanstack/react-query";
import { useNavigation } from "expo-router";
-import { useAtom } from "jotai";
-import { useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+
+import React, {useEffect, useMemo, useState} from "react";
import {
Linking,
Switch,
@@ -15,11 +15,14 @@ import {
View,
} from "react-native";
import { toast } from "sonner-native";
+import DisabledSetting from "@/components/settings/DisabledSetting";
export default function page() {
const navigation = useNavigation();
- const [settings, updateSettings] = useSettings();
+ const { t } = useTranslation();
+
+ const [settings, updateSettings, pluginSettings] = useSettings();
const queryClient = useQueryClient();
const [value, setValue] = useState(settings?.marlinServerUrl || "");
@@ -28,76 +31,87 @@ export default function page() {
updateSettings({
marlinServerUrl: !val.endsWith("/") ? val : val.slice(0, -1),
});
- toast.success("Saved");
+ toast.success(t("home.settings.plugins.marlin_search.toasts.saved"));
};
const handleOpenLink = () => {
Linking.openURL("https://github.com/fredrikburmester/marlin-search");
};
+ const disabled = useMemo(() => {
+ return pluginSettings?.searchEngine?.locked === true && pluginSettings?.marlinServerUrl?.locked === true
+ }, [pluginSettings]);
+
useEffect(() => {
- navigation.setOptions({
- headerRight: () => (
- onSave(value)}>
- Save
-
- ),
- });
+ if (!pluginSettings?.marlinServerUrl?.locked) {
+ navigation.setOptions({
+ headerRight: () => (
+ onSave(value)}>
+ {t("home.settings.plugins.marlin_search.save_button")}
+
+ ),
+ });
+ }
}, [navigation, value]);
if (!settings) return null;
return (
-
+
- {
- updateSettings({ searchEngine: "Jellyfin" });
- queryClient.invalidateQueries({ queryKey: ["search"] });
- }}
+
- {
- updateSettings({ searchEngine: value ? "Marlin" : "Jellyfin" });
+ {
+ updateSettings({ searchEngine: "Jellyfin" });
queryClient.invalidateQueries({ queryKey: ["search"] });
}}
- />
-
+ >
+ {
+ updateSettings({ searchEngine: value ? "Marlin" : "Jellyfin" });
+ queryClient.invalidateQueries({ queryKey: ["search"] });
+ }}
+ />
+
+
-
-
-
- URL
- setValue(text)}
- />
-
+
+ {t("home.settings.plugins.marlin_search.url")}
+ setValue(text)}
+ />
-
- Enter the URL for the Marlin server. The URL should include http or
- https and optionally the port.{" "}
-
- Read more about Marlin.
-
+
+
+ {t("home.settings.plugins.marlin_search.marlin_search_hint")}{" "}
+
+ {t("home.settings.plugins.marlin_search.read_more_about_marlin")}
-
-
+
+
);
}
diff --git a/app/(auth)/(tabs)/(home)/settings/optimized-server/page.tsx b/app/(auth)/(tabs)/(home)/settings/optimized-server/page.tsx
index b47d565f..988651f0 100644
--- a/app/(auth)/(tabs)/(home)/settings/optimized-server/page.tsx
+++ b/app/(auth)/(tabs)/(home)/settings/optimized-server/page.tsx
@@ -10,12 +10,16 @@ import { useAtom } from "jotai";
import { useEffect, useState } from "react";
import { ActivityIndicator, TouchableOpacity, View } from "react-native";
import { toast } from "sonner-native";
+import { useTranslation } from "react-i18next";
+import DisabledSetting from "@/components/settings/DisabledSetting";
export default function page() {
const navigation = useNavigation();
+ const { t } = useTranslation();
+
const [api] = useAtom(apiAtom);
- const [settings, updateSettings] = useSettings();
+ const [settings, updateSettings, pluginSettings] = useSettings();
const [optimizedVersionsServerUrl, setOptimizedVersionsServerUrl] =
useState(settings?.optimizedVersionsServerUrl || "");
@@ -23,7 +27,7 @@ export default function page() {
const saveMutation = useMutation({
mutationFn: async (newVal: string) => {
if (newVal.length === 0 || !newVal.startsWith("http")) {
- toast.error("Invalid URL");
+ toast.error(t("home.settings.toasts.invalid_url"));
return;
}
@@ -41,13 +45,13 @@ export default function page() {
},
onSuccess: (data) => {
if (data) {
- toast.success("Connected");
+ toast.success(t("home.settings.toasts.connected"));
} else {
- toast.error("Could not connect");
+ toast.error(t("home.settings.toasts.could_not_connect"));
}
},
onError: () => {
- toast.error("Could not connect");
+ toast.error(t("home.settings.toasts.could_not_connect"));
},
});
@@ -56,25 +60,30 @@ export default function page() {
};
useEffect(() => {
- navigation.setOptions({
- title: "Optimized Server",
- headerRight: () =>
- saveMutation.isPending ? (
-
- ) : (
- onSave(optimizedVersionsServerUrl)}>
- Save
-
- ),
- });
+ if (!pluginSettings?.optimizedVersionsServerUrl?.locked) {
+ navigation.setOptions({
+ title: t("home.settings.downloads.optimized_server"),
+ headerRight: () =>
+ saveMutation.isPending ? (
+
+ ) : (
+ onSave(optimizedVersionsServerUrl)}>
+ {t("home.settings.downloads.save_button")}
+
+ ),
+ });
+ }
}, [navigation, optimizedVersionsServerUrl, saveMutation.isPending]);
return (
-
+
-
+
);
}
diff --git a/app/(auth)/(tabs)/(home)/settings/popular-lists/page.tsx b/app/(auth)/(tabs)/(home)/settings/popular-lists/page.tsx
deleted file mode 100644
index 43cf76c4..00000000
--- a/app/(auth)/(tabs)/(home)/settings/popular-lists/page.tsx
+++ /dev/null
@@ -1,135 +0,0 @@
-import { Text } from "@/components/common/Text";
-import { ListGroup } from "@/components/list/ListGroup";
-import { ListItem } from "@/components/list/ListItem";
-import { Loader } from "@/components/Loader";
-import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
-import { useSettings } from "@/utils/atoms/settings";
-import { getItemsApi } from "@jellyfin/sdk/lib/utils/api";
-import { useQuery, useQueryClient } from "@tanstack/react-query";
-import { useNavigation } from "expo-router";
-import { useAtom } from "jotai";
-import { Linking, Switch, View } from "react-native";
-
-export default function page() {
- const navigation = useNavigation();
-
- const [api] = useAtom(apiAtom);
- const [user] = useAtom(userAtom);
-
- const [settings, updateSettings] = useSettings();
-
- const handleOpenLink = () => {
- Linking.openURL(
- "https://github.com/lostb1t/jellyfin-plugin-collection-import"
- );
- };
-
- const queryClient = useQueryClient();
-
- const {
- data: mediaListCollections,
- isLoading: isLoadingMediaListCollections,
- } = useQuery({
- queryKey: ["sf_promoted", user?.Id, settings?.usePopularPlugin],
- queryFn: async () => {
- if (!api || !user?.Id) return [];
-
- const response = await getItemsApi(api).getItems({
- userId: user.Id,
- tags: ["sf_promoted"],
- recursive: true,
- fields: ["Tags"],
- includeItemTypes: ["BoxSet"],
- });
-
- return response.data.Items ?? [];
- },
- enabled: !!api && !!user?.Id && settings?.usePopularPlugin === true,
- staleTime: 0,
- });
-
- if (!settings) return null;
-
- return (
-
-
- {
- updateSettings({ usePopularPlugin: true });
- queryClient.invalidateQueries({ queryKey: ["search"] });
- }}
- >
- {
- updateSettings({ usePopularPlugin: value });
- }}
- />
-
-
-
- Popular Lists is a plugin that enables you to show custom Jellyfin lists
- on the Streamyfin home page.{" "}
-
- Read more about Popular Lists.
-
-
-
- {settings.usePopularPlugin && (
- <>
- {!isLoadingMediaListCollections ? (
- <>
- {mediaListCollections?.length === 0 ? (
-
- No collections found. Add some in Jellyfin.
-
- ) : (
- <>
-
- {mediaListCollections?.map((mlc) => (
-
- {
- if (!settings.mediaListCollectionIds) {
- updateSettings({
- mediaListCollectionIds: [mlc.Id!],
- });
- return;
- }
-
- updateSettings({
- mediaListCollectionIds:
- settings.mediaListCollectionIds.includes(
- mlc.Id!
- )
- ? settings.mediaListCollectionIds.filter(
- (id) => id !== mlc.Id
- )
- : [
- ...settings.mediaListCollectionIds,
- mlc.Id!,
- ],
- });
- }}
- />
-
- ))}
-
-
- Select the lists you want displayed on the home screen.
-
- >
- )}
- >
- ) : (
-
- )}
- >
- )}
-
- );
-}
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/actors/[actorId].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/actors/[actorId].tsx
index 45dc8a4d..d2c15c3d 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/actors/[actorId].tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/actors/[actorId].tsx
@@ -18,10 +18,12 @@ import { useLocalSearchParams } from "expo-router";
import { useAtom } from "jotai";
import { useCallback, useMemo } from "react";
import { View } from "react-native";
+import { useTranslation } from "react-i18next";
const page: React.FC = () => {
const local = useLocalSearchParams();
const { actorId } = local as { actorId: string };
+ const { t } = useTranslation();
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
@@ -110,7 +112,7 @@ const page: React.FC = () => {
- Appeared In
+ {t("item_card.appeared_in")}
{
const searchParams = useLocalSearchParams();
@@ -45,6 +46,8 @@ const page: React.FC = () => {
ScreenOrientation.Orientation.PORTRAIT_UP
);
+ const { t } = useTranslation();
+
const [selectedGenres, setSelectedGenres] = useAtom(genreFilterAtom);
const [selectedYears, setSelectedYears] = useAtom(yearFilterAtom);
const [selectedTags, setSelectedTags] = useAtom(tagsFilterAtom);
@@ -109,7 +112,7 @@ const page: React.FC = () => {
genres: selectedGenres,
tags: selectedTags,
years: selectedYears.map((year) => parseInt(year)),
- includeItemTypes: ["Movie", "Series", "MusicAlbum"],
+ includeItemTypes: ["Movie", "Series"],
});
return response.data || null;
@@ -244,7 +247,7 @@ const page: React.FC = () => {
}}
set={setSelectedGenres}
values={selectedGenres}
- title="Genres"
+ title={t("library.filters.genres")}
renderItemLabel={(item) => item.toString()}
searchFilter={(item, search) =>
item.toLowerCase().includes(search.toLowerCase())
@@ -271,7 +274,7 @@ const page: React.FC = () => {
}}
set={setSelectedYears}
values={selectedYears}
- title="Years"
+ title={t("library.filters.years")}
renderItemLabel={(item) => item.toString()}
searchFilter={(item, search) => item.includes(search)}
/>
@@ -296,7 +299,7 @@ const page: React.FC = () => {
}}
set={setSelectedTags}
values={selectedTags}
- title="Tags"
+ title={t("library.filters.tags")}
renderItemLabel={(item) => item.toString()}
searchFilter={(item, search) =>
item.toLowerCase().includes(search.toLowerCase())
@@ -314,7 +317,7 @@ const page: React.FC = () => {
queryFn={async () => sortOptions.map((s) => s.key)}
set={setSortBy}
values={sortBy}
- title="Sort By"
+ title={t("library.filters.sort_by")}
renderItemLabel={(item) =>
sortOptions.find((i) => i.key === item)?.value || ""
}
@@ -334,7 +337,7 @@ const page: React.FC = () => {
queryFn={async () => sortOrderOptions.map((s) => s.key)}
set={setSortOrder}
values={sortOrder}
- title="Sort Order"
+ title={t("library.filters.sort_order")}
renderItemLabel={(item) =>
sortOrderOptions.find((i) => i.key === item)?.value || ""
}
@@ -374,7 +377,7 @@ const page: React.FC = () => {
- No results
+ {t("search.no_results")}
}
extraData={[
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/items/page.tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/items/page.tsx
index 38b0115d..a61114bd 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/items/page.tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/items/page.tsx
@@ -13,11 +13,13 @@ import Animated, {
useSharedValue,
withTiming,
} from "react-native-reanimated";
+import { useTranslation } from "react-i18next";
const Page: React.FC = () => {
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
const { id } = useLocalSearchParams() as { id: string };
+ const { t } = useTranslation();
const { data: item, isError } = useQuery({
queryKey: ["item", id],
@@ -74,7 +76,7 @@ const Page: React.FC = () => {
if (isError)
return (
- Could not load item
+ {t("item_card.could_not_load_item")}
);
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/[personId].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/[personId].tsx
deleted file mode 100644
index 5a930982..00000000
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/[personId].tsx
+++ /dev/null
@@ -1,247 +0,0 @@
-import {
- router,
- useLocalSearchParams,
- useNavigation,
- useSegments,
-} from "expo-router";
-import React, {
- useCallback,
- useEffect,
- useMemo,
- useRef,
- useState,
-} from "react";
-import { TouchableOpacity, View } from "react-native";
-import { useQuery } from "@tanstack/react-query";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
-import { useSafeAreaInsets } from "react-native-safe-area-context";
-import { ParallaxScrollView } from "@/components/ParallaxPage";
-import { Text } from "@/components/common/Text";
-import { Animated } from "react-native";
-import { Image } from "expo-image";
-import { OverviewText } from "@/components/OverviewText";
-import { orderBy } from "lodash";
-import { FlashList } from "@shopify/flash-list";
-import { PersonCreditCast } from "@/utils/jellyseerr/server/models/Person";
-import Poster from "@/components/posters/Poster";
-import JellyseerrMediaIcon from "@/components/jellyseerr/JellyseerrMediaIcon";
-
-const ANIMATION_ENTER = 250;
-const ANIMATION_EXIT = 250;
-const BACKDROP_DURATION = 5000;
-
-export default function page() {
- const insets = useSafeAreaInsets();
- const local = useLocalSearchParams();
- const segments = useSegments();
- const { jellyseerrApi, jellyseerrUser } = useJellyseerr();
-
- const { personId } = local as { personId: string };
- const from = segments[2];
-
- const [currentIndex, setCurrentIndex] = useState(0);
- const fadeAnim = useRef(new Animated.Value(0)).current;
-
- const { data, isLoading, isFetching } = useQuery({
- queryKey: ["jellyseerr", "person", personId],
- queryFn: async () => ({
- details: await jellyseerrApi?.personDetails(personId),
- combinedCredits: await jellyseerrApi?.personCombinedCredits(personId),
- }),
- enabled: !!jellyseerrApi && !!personId,
- });
-
- const locale = useMemo(() => {
- return jellyseerrUser?.settings?.locale || "en";
- }, [jellyseerrUser]);
-
- const region = useMemo(
- () => jellyseerrUser?.settings?.region || "US",
- [jellyseerrUser]
- );
-
- const castedRoles: PersonCreditCast[] = useMemo(
- () =>
- orderBy(
- data?.combinedCredits?.cast,
- ["voteCount", "voteAverage"],
- "desc"
- ),
- [data?.combinedCredits]
- );
-
- const backdrops = useMemo(
- () => castedRoles.map((c) => c.backdropPath),
- [data?.combinedCredits]
- );
-
- const enterAnimation = useCallback(
- () =>
- Animated.timing(fadeAnim, {
- toValue: 1,
- duration: ANIMATION_ENTER,
- useNativeDriver: true,
- }),
- [fadeAnim]
- );
-
- const exitAnimation = useCallback(
- () =>
- Animated.timing(fadeAnim, {
- toValue: 0,
- duration: ANIMATION_EXIT,
- useNativeDriver: true,
- }),
- [fadeAnim]
- );
-
- useEffect(() => {
- if (backdrops?.length) {
- enterAnimation().start();
- const intervalId = setInterval(() => {
- exitAnimation().start((end) => {
- if (end.finished)
- setCurrentIndex((prevIndex) => (prevIndex + 1) % backdrops?.length);
- });
- }, BACKDROP_DURATION);
-
- return () => clearInterval(intervalId);
- }
- }, [backdrops, enterAnimation, exitAnimation, setCurrentIndex, currentIndex]);
-
- const viewDetails = (credit: PersonCreditCast) => {
- router.push({
- //@ts-ignore
- pathname: `/(auth)/(tabs)/${from}/jellyseerr/page`,
- //@ts-ignore
- params: {
- ...credit,
- mediaTitle: credit.title,
- releaseYear: new Date(credit.releaseDate).getFullYear(),
- canRequest: "false",
- posterSrc: jellyseerrApi?.imageProxy(
- credit.posterPath,
- "w300_and_h450_face"
- ),
- },
- });
- };
-
- return (
-
-
- }
- logo={
-
- }
- >
-
-
-
-
- {data?.details?.name}
-
-
- Born{" "}
- {new Date(data?.details?.birthday!!).toLocaleDateString(
- `${locale}-${region}`,
- {
- year: "numeric",
- month: "long",
- day: "numeric",
- }
- )}{" "}
- | {data?.details?.placeOfBirth}
-
-
-
-
-
-
-
-
- No results
-
-
- }
- contentInsetAdjustmentBehavior="automatic"
- ListHeaderComponent={
- Appearances
- }
- renderItem={({ item }) => (
- viewDetails(item)}
- >
-
-
- {/*{item.title}*/}
- {item.character && (
-
- as {item.character}
-
- )}
-
- )}
- keyExtractor={(item) => item.id.toString()}
- estimatedItemSize={255}
- numColumns={3}
- contentContainerStyle={{ paddingBottom: 24 }}
- ItemSeparatorComponent={() => }
- />
-
-
-
-
- );
-}
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/company/[companyId].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/company/[companyId].tsx
new file mode 100644
index 00000000..c5eda557
--- /dev/null
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/company/[companyId].tsx
@@ -0,0 +1,95 @@
+import {router, useLocalSearchParams, useSegments,} from "expo-router";
+import React, {useMemo,} from "react";
+import {TouchableOpacity} from "react-native";
+import {useInfiniteQuery} from "@tanstack/react-query";
+import {Endpoints, useJellyseerr} from "@/hooks/useJellyseerr";
+import {Text} from "@/components/common/Text";
+import {Image} from "expo-image";
+import Poster from "@/components/posters/Poster";
+import JellyseerrMediaIcon from "@/components/jellyseerr/JellyseerrMediaIcon";
+import {DiscoverSliderType} from "@/utils/jellyseerr/server/constants/discover";
+import ParallaxSlideShow from "@/components/jellyseerr/ParallaxSlideShow";
+import {MovieResult, Results, TvResult} from "@/utils/jellyseerr/server/models/Search";
+import {COMPANY_LOGO_IMAGE_FILTER} from "@/utils/jellyseerr/src/components/Discover/NetworkSlider";
+import {uniqBy} from "lodash";
+import JellyseerrPoster from "@/components/posters/JellyseerrPoster";
+
+export default function page() {
+ const local = useLocalSearchParams();
+ const {jellyseerrApi} = useJellyseerr();
+
+ const {companyId, name, image, type} = local as unknown as {
+ companyId: string,
+ name: string,
+ image: string,
+ type: DiscoverSliderType
+ };
+
+ const {data, fetchNextPage, hasNextPage} = useInfiniteQuery({
+ queryKey: ["jellyseerr", "company", type, companyId],
+ queryFn: async ({pageParam}) => {
+ let params: any = {
+ page: Number(pageParam),
+ };
+
+ return jellyseerrApi?.discover(
+ (
+ type == DiscoverSliderType.NETWORKS
+ ? Endpoints.DISCOVER_TV_NETWORK
+ : Endpoints.DISCOVER_MOVIES_STUDIO
+ ) + `/${companyId}`,
+ params
+ )
+ },
+ enabled: !!jellyseerrApi && !!companyId,
+ initialPageParam: 1,
+ getNextPageParam: (lastPage, pages) =>
+ (lastPage?.page || pages?.findLast((p) => p?.results.length)?.page || 1) +
+ 1,
+ staleTime: 0,
+ });
+
+ const flatData = useMemo(
+ () => uniqBy(data?.pages?.filter((p) => p?.results.length).flatMap((p) => p?.results ?? []), "id")?? [],
+ [data]
+ );
+
+ const backdrops = useMemo(
+ () => jellyseerrApi
+ ? flatData.map((r) => jellyseerrApi.imageProxy((r as TvResult | MovieResult).backdropPath, "w1920_and_h800_multi_faces"))
+ : [],
+ [jellyseerrApi, flatData]
+ );
+
+ return (
+ item.id.toString()}
+ onEndReached={() => {
+ if (hasNextPage) {
+ fetchNextPage()
+ }
+ }}
+ logo={
+
+ }
+ renderItem={(item, index) =>
+
+ }
+ />
+ );
+}
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/genre/[genreId].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/genre/[genreId].tsx
new file mode 100644
index 00000000..dbbce320
--- /dev/null
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/genre/[genreId].tsx
@@ -0,0 +1,87 @@
+import {router, useLocalSearchParams, useSegments,} from "expo-router";
+import React, {useMemo,} from "react";
+import {TouchableOpacity} from "react-native";
+import {useInfiniteQuery} from "@tanstack/react-query";
+import {Endpoints, useJellyseerr} from "@/hooks/useJellyseerr";
+import {Text} from "@/components/common/Text";
+import Poster from "@/components/posters/Poster";
+import JellyseerrMediaIcon from "@/components/jellyseerr/JellyseerrMediaIcon";
+import {DiscoverSliderType} from "@/utils/jellyseerr/server/constants/discover";
+import ParallaxSlideShow from "@/components/jellyseerr/ParallaxSlideShow";
+import {MovieResult, Results, TvResult} from "@/utils/jellyseerr/server/models/Search";
+import {uniqBy} from "lodash";
+import {textShadowStyle} from "@/components/jellyseerr/discover/GenericSlideCard";
+import JellyseerrPoster from "@/components/posters/JellyseerrPoster";
+
+export default function page() {
+ const local = useLocalSearchParams();
+ const {jellyseerrApi} = useJellyseerr();
+
+ const {genreId, name, type} = local as unknown as {
+ genreId: string,
+ name: string,
+ type: DiscoverSliderType
+ };
+
+ const {data, fetchNextPage, hasNextPage} = useInfiniteQuery({
+ queryKey: ["jellyseerr", "company", type, genreId],
+ queryFn: async ({pageParam}) => {
+ let params: any = {
+ page: Number(pageParam),
+ genre: genreId
+ };
+
+ return jellyseerrApi?.discover(
+ type == DiscoverSliderType.MOVIE_GENRES
+ ? Endpoints.DISCOVER_MOVIES
+ : Endpoints.DISCOVER_TV,
+ params
+ )
+ },
+ enabled: !!jellyseerrApi && !!genreId,
+ initialPageParam: 1,
+ getNextPageParam: (lastPage, pages) =>
+ (lastPage?.page || pages?.findLast((p) => p?.results.length)?.page || 1) +
+ 1,
+ staleTime: 0,
+ });
+
+ const flatData = useMemo(
+ () => uniqBy(data?.pages?.filter((p) => p?.results.length).flatMap((p) => p?.results ?? []), "id")?? [],
+ [data]
+ );
+
+ const backdrops = useMemo(
+ () => jellyseerrApi
+ ? flatData.map((r) => jellyseerrApi.imageProxy((r as TvResult | MovieResult).backdropPath, "w1920_and_h800_multi_faces"))
+ : [],
+ [jellyseerrApi, flatData]
+ );
+
+ return (
+ item.id.toString()}
+ onEndReached={() => {
+ if (hasNextPage) {
+ fetchNextPage()
+ }
+ }}
+ logo={
+
+ {name}
+
+ }
+ renderItem={(item, index) =>
+
+ }
+ />
+ );
+}
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/page.tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/page.tsx
index d6aae61a..7796050d 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/page.tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/page.tsx
@@ -1,28 +1,24 @@
-import React, {
- useCallback,
- useEffect,
- useMemo,
- useRef,
- useState,
-} from "react";
-import { useLocalSearchParams, useNavigation } from "expo-router";
-import { MovieResult, TvResult } from "@/utils/jellyseerr/server/models/Search";
-import { Text } from "@/components/common/Text";
-import { ParallaxScrollView } from "@/components/ParallaxPage";
-import { Image } from "expo-image";
-import { TouchableOpacity, View } from "react-native";
-import { Ionicons } from "@expo/vector-icons";
-import { useSafeAreaInsets } from "react-native-safe-area-context";
-import { OverviewText } from "@/components/OverviewText";
-import { GenreTags } from "@/components/GenreTags";
-import {
- MediaRequestStatus,
- MediaStatus,
- MediaType,
-} from "@/utils/jellyseerr/server/constants/media";
-import { useQuery } from "@tanstack/react-query";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
import { Button } from "@/components/Button";
+import { Text } from "@/components/common/Text";
+import { GenreTags } from "@/components/GenreTags";
+import Cast from "@/components/jellyseerr/Cast";
+import DetailFacts from "@/components/jellyseerr/DetailFacts";
+import { OverviewText } from "@/components/OverviewText";
+import { ParallaxScrollView } from "@/components/ParallaxPage";
+import { JellyserrRatings } from "@/components/Ratings";
+import JellyseerrSeasons from "@/components/series/JellyseerrSeasons";
+import { ItemActions } from "@/components/series/SeriesActions";
+import { useJellyseerr } from "@/hooks/useJellyseerr";
+import { useJellyseerrCanRequest } from "@/utils/_jellyseerr/useJellyseerrCanRequest";
+import {
+ IssueType,
+ IssueTypeName,
+} from "@/utils/jellyseerr/server/constants/issue";
+import { MediaType } from "@/utils/jellyseerr/server/constants/media";
+import { MovieResult, TvResult } from "@/utils/jellyseerr/server/models/Search";
+import { TvDetails } from "@/utils/jellyseerr/server/models/Tv";
+import { useTranslation } from "react-i18next";
+import { Ionicons } from "@expo/vector-icons";
import {
BottomSheetBackdrop,
BottomSheetBackdropProps,
@@ -30,23 +26,28 @@ import {
BottomSheetTextInput,
BottomSheetView,
} from "@gorhom/bottom-sheet";
-import {
- IssueType,
- IssueTypeName,
-} from "@/utils/jellyseerr/server/constants/issue";
-import * as DropdownMenu from "@/components/DropdownMenu";
-import { TvDetails } from "@/utils/jellyseerr/server/models/Tv";
-import JellyseerrSeasons from "@/components/series/JellyseerrSeasons";
-import { JellyserrRatings } from "@/components/Ratings";
-import MediaRequest from "@/utils/jellyseerr/server/entity/MediaRequest";
-import DetailFacts from "@/components/jellyseerr/DetailFacts";
-import { ItemActions } from "@/components/series/SeriesActions";
-import Cast from "@/components/jellyseerr/Cast";
-import { useJellyseerrCanRequest } from "@/utils/_jellyseerr/useJellyseerrCanRequest";
+import { useQuery } from "@tanstack/react-query";
+import { Image } from "expo-image";
+import { useLocalSearchParams, useNavigation } from "expo-router";
+import React, {
+ useCallback,
+ useEffect,
+ useMemo,
+ useRef,
+ useState,
+} from "react";
+import { TouchableOpacity, View } from "react-native";
+import { useSafeAreaInsets } from "react-native-safe-area-context";
+import * as DropdownMenu from "zeego/dropdown-menu";
+import RequestModal from "@/components/jellyseerr/RequestModal";
+import { ANIME_KEYWORD_ID } from "@/utils/jellyseerr/server/api/themoviedb/constants";
+import { MediaRequestBody } from "@/utils/jellyseerr/server/interfaces/api/requestInterfaces";
const Page: React.FC = () => {
const insets = useSafeAreaInsets();
const params = useLocalSearchParams();
+ const { t } = useTranslation();
+
const { mediaTitle, releaseYear, posterSrc, ...result } =
params as unknown as {
mediaTitle: string;
@@ -60,6 +61,7 @@ const Page: React.FC = () => {
const [issueType, setIssueType] = useState();
const [issueMessage, setIssueMessage] = useState();
+ const advancedReqModalRef = useRef(null);
const bottomSheetModalRef = useRef(null);
const {
@@ -83,7 +85,8 @@ const Page: React.FC = () => {
},
});
- const canRequest = useJellyseerrCanRequest(details);
+ const [canRequest, hasAdvancedRequestPermission] =
+ useJellyseerrCanRequest(details);
const renderBackdrop = useCallback(
(props: BottomSheetBackdropProps) => (
@@ -109,19 +112,29 @@ const Page: React.FC = () => {
}, [jellyseerrApi, details, result, issueType, issueMessage]);
const request = useCallback(async () => {
- requestMedia(
- mediaTitle,
- {
- mediaId: Number(result.id!!),
- mediaType: result.mediaType!!,
- tvdbId: details?.externalIds?.tvdbId,
- seasons: (details as TvDetails)?.seasons
- ?.filter?.((s) => s.seasonNumber !== 0)
- ?.map?.((s) => s.seasonNumber),
- },
- refetch
- );
- }, [details, result, requestMedia]);
+ const body: MediaRequestBody = {
+ mediaId: Number(result.id!!),
+ mediaType: result.mediaType!!,
+ tvdbId: details?.externalIds?.tvdbId,
+ seasons: (details as TvDetails)?.seasons
+ ?.filter?.((s) => s.seasonNumber !== 0)
+ ?.map?.((s) => s.seasonNumber),
+ };
+
+ if (hasAdvancedRequestPermission) {
+ advancedReqModalRef?.current?.present?.(body);
+ return;
+ }
+
+ requestMedia(mediaTitle, body, refetch);
+ }, [details, result, requestMedia, hasAdvancedRequestPermission]);
+
+ const isAnime = useMemo(
+ () =>
+ (details?.keywords.some((k) => k.id === ANIME_KEYWORD_ID) || false) &&
+ result.mediaType === MediaType.TV,
+ [details]
+ );
useEffect(() => {
if (details) {
@@ -213,7 +226,7 @@ const Page: React.FC = () => {
) : canRequest ? (
) : (
)}
@@ -240,6 +253,10 @@ const Page: React.FC = () => {
result={result as TvResult}
details={details as TvDetails}
refetch={refetch}
+ hasAdvancedRequest={hasAdvancedRequestPermission}
+ onAdvancedRequest={(data) =>
+ advancedReqModalRef?.current?.present(data)
+ }
/>
)}
{
+ {
+ advancedReqModalRef?.current?.close();
+ refetch();
+ }}
+ />
{
- Whats wrong?
+ {t("jellyseerr.whats_wrong")}
@@ -274,13 +302,13 @@ const Page: React.FC = () => {
- Issue Type
+ {t("jellyseerr.issue_type")}
{issueType
? IssueTypeName[issueType]
- : "Select an issue"}
+ : t("jellyseerr.select_an_issue")}
@@ -294,7 +322,9 @@ const Page: React.FC = () => {
collisionPadding={0}
sideOffset={0}
>
- Types
+
+ {t("jellyseerr.types")}
+
{Object.entries(IssueTypeName)
.reverse()
.map(([key, value], idx) => (
@@ -319,7 +349,7 @@ const Page: React.FC = () => {
maxLength={254}
style={{ color: "white" }}
clearButtonMode="always"
- placeholder="(optional) Describe the issue..."
+ placeholder={t("jellyseerr.describe_the_issue")}
placeholderTextColor="#9CA3AF"
// Issue with multiline + Textinput inside a portal
// https://github.com/callstack/react-native-paper/issues/1668
@@ -329,7 +359,7 @@ const Page: React.FC = () => {
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/person/[personId].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/person/[personId].tsx
new file mode 100644
index 00000000..f152563a
--- /dev/null
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/person/[personId].tsx
@@ -0,0 +1,110 @@
+import {
+ useLocalSearchParams,
+ useSegments,
+} from "expo-router";
+import React, { useMemo } from "react";
+import { useQuery } from "@tanstack/react-query";
+import { useJellyseerr } from "@/hooks/useJellyseerr";
+import { Text } from "@/components/common/Text";
+import { Image } from "expo-image";
+import { OverviewText } from "@/components/OverviewText";
+import {orderBy, uniqBy} from "lodash";
+import { PersonCreditCast } from "@/utils/jellyseerr/server/models/Person";
+import ParallaxSlideShow from "@/components/jellyseerr/ParallaxSlideShow";
+import JellyseerrPoster from "@/components/posters/JellyseerrPoster";
+import {MovieResult, TvResult} from "@/utils/jellyseerr/server/models/Search";
+import { useTranslation } from "react-i18next";
+
+export default function page() {
+ const local = useLocalSearchParams();
+ const { t } = useTranslation();
+
+ const { jellyseerrApi, jellyseerrUser } = useJellyseerr();
+
+ const { personId } = local as { personId: string };
+
+ const { data, isLoading, isFetching } = useQuery({
+ queryKey: ["jellyseerr", "person", personId],
+ queryFn: async () => ({
+ details: await jellyseerrApi?.personDetails(personId),
+ combinedCredits: await jellyseerrApi?.personCombinedCredits(personId),
+ }),
+ enabled: !!jellyseerrApi && !!personId,
+ });
+
+ const locale = useMemo(() => {
+ return jellyseerrUser?.settings?.locale || "en";
+ }, [jellyseerrUser]);
+
+ const region = useMemo(
+ () => jellyseerrUser?.settings?.region || "US",
+ [jellyseerrUser]
+ );
+
+ const castedRoles: PersonCreditCast[] = useMemo(
+ () =>
+ uniqBy(orderBy(
+ data?.combinedCredits?.cast,
+ ["voteCount", "voteAverage"],
+ "desc"
+ ), 'id'),
+ [data?.combinedCredits]
+ );
+ const backdrops = useMemo(
+ () => jellyseerrApi
+ ? castedRoles.map((c) => jellyseerrApi.imageProxy(c.backdropPath, "w1920_and_h800_multi_faces"))
+ : [],
+ [jellyseerrApi, data?.combinedCredits]
+ );
+
+ return (
+ item.id.toString()}
+ logo={
+
+ }
+ HeaderContent={() => (
+ <>
+
+ {data?.details?.name}
+
+
+ {t("jellyseerr.born")}{" "}
+ {new Date(data?.details?.birthday!!).toLocaleDateString(
+ `${locale}-${region}`,
+ {
+ year: "numeric",
+ month: "long",
+ day: "numeric",
+ }
+ )}{" "}
+ | {data?.details?.placeOfBirth}
+
+ >
+ )}
+ MainContent={() => (
+
+ )}
+ renderItem={(item, index) => }
+ />
+ );
+}
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/livetv/guide.tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/livetv/guide.tsx
index 01652b5f..398d74b6 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/livetv/guide.tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/livetv/guide.tsx
@@ -17,6 +17,7 @@ import {
View,
} from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
+import { useTranslation } from "react-i18next";
const HOUR_HEIGHT = 30;
const ITEMS_PER_PAGE = 20;
@@ -177,6 +178,7 @@ const PageButtons: React.FC = ({
onNextPage,
isNextDisabled,
}) => {
+ const { t } = useTranslation();
return (
= ({
currentPage === 1 ? "text-gray-500" : "text-white"
}`}
>
- Previous
+ {t("live_tv.previous")}
Page {currentPage}
@@ -206,7 +208,7 @@ const PageButtons: React.FC = ({
- Next
+ {t("live_tv.next")}
{
if (!api) return [] as BaseItemDto[];
const res = await getLiveTvApi(api).getRecommendedPrograms({
@@ -46,7 +49,7 @@ export default function page() {
/>
{
if (!api) return [] as BaseItemDto[];
const res = await getLiveTvApi(api).getLiveTvPrograms({
@@ -68,7 +71,7 @@ export default function page() {
/>
{
if (!api) return [] as BaseItemDto[];
const res = await getLiveTvApi(api).getLiveTvPrograms({
@@ -86,7 +89,7 @@ export default function page() {
/>
{
if (!api) return [] as BaseItemDto[];
const res = await getLiveTvApi(api).getLiveTvPrograms({
@@ -104,7 +107,7 @@ export default function page() {
/>
{
if (!api) return [] as BaseItemDto[];
const res = await getLiveTvApi(api).getLiveTvPrograms({
@@ -122,7 +125,7 @@ export default function page() {
/>
{
if (!api) return [] as BaseItemDto[];
const res = await getLiveTvApi(api).getLiveTvPrograms({
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/livetv/recordings.tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/livetv/recordings.tsx
index 6e3f660e..4068f8a3 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/livetv/recordings.tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/livetv/recordings.tsx
@@ -1,11 +1,13 @@
import { Text } from "@/components/common/Text";
import React from "react";
import { View } from "react-native";
+import { useTranslation } from "react-i18next";
export default function page() {
+ const { t } = useTranslation();
return (
- Coming soon
+ {t("live_tv.coming_soon")}
);
}
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/series/[id].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/series/[id].tsx
index 2758010b..a62405e1 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/series/[id].tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/series/[id].tsx
@@ -16,9 +16,11 @@ import { useLocalSearchParams, useNavigation } from "expo-router";
import { useAtom } from "jotai";
import React, { useEffect, useMemo } from "react";
import { View } from "react-native";
+import { useTranslation } from "react-i18next";
const page: React.FC = () => {
const navigation = useNavigation();
+ const { t } = useTranslation();
const params = useLocalSearchParams();
const { id: seriesId, seasonIndex } = params as {
id: string;
@@ -85,7 +87,7 @@ const page: React.FC = () => {
(
diff --git a/app/(auth)/(tabs)/(libraries)/[libraryId].tsx b/app/(auth)/(tabs)/(libraries)/[libraryId].tsx
index 5252f612..a7b9cc1f 100644
--- a/app/(auth)/(tabs)/(libraries)/[libraryId].tsx
+++ b/app/(auth)/(tabs)/(libraries)/[libraryId].tsx
@@ -41,6 +41,7 @@ import {
} from "@jellyfin/sdk/lib/utils/api";
import { FlashList } from "@shopify/flash-list";
import { useSafeAreaInsets } from "react-native-safe-area-context";
+import { useTranslation } from "react-i18next";
const Page = () => {
const searchParams = useLocalSearchParams();
@@ -62,6 +63,8 @@ const Page = () => {
const { orientation } = useOrientation();
+ const { t } = useTranslation();
+
useEffect(() => {
const sop = getSortOrderPreference(libraryId, sortOrderPreference);
if (sop) {
@@ -150,8 +153,6 @@ const Page = () => {
itemType = "Series";
} else if (library.CollectionType === "boxsets") {
itemType = "BoxSet";
- } else if (library.CollectionType === "music") {
- itemType = "MusicAlbum";
}
const response = await getItemsApi(api).getItems({
@@ -300,7 +301,7 @@ const Page = () => {
}}
set={setSelectedGenres}
values={selectedGenres}
- title="Genres"
+ title={t("library.filters.genres")}
renderItemLabel={(item) => item.toString()}
searchFilter={(item, search) =>
item.toLowerCase().includes(search.toLowerCase())
@@ -327,7 +328,7 @@ const Page = () => {
}}
set={setSelectedYears}
values={selectedYears}
- title="Years"
+ title={t("library.filters.years")}
renderItemLabel={(item) => item.toString()}
searchFilter={(item, search) => item.includes(search)}
/>
@@ -352,7 +353,7 @@ const Page = () => {
}}
set={setSelectedTags}
values={selectedTags}
- title="Tags"
+ title={t("library.filters.tags")}
renderItemLabel={(item) => item.toString()}
searchFilter={(item, search) =>
item.toLowerCase().includes(search.toLowerCase())
@@ -370,7 +371,7 @@ const Page = () => {
queryFn={async () => sortOptions.map((s) => s.key)}
set={setSortBy}
values={sortBy}
- title="Sort By"
+ title={t("library.filters.sort_by")}
renderItemLabel={(item) =>
sortOptions.find((i) => i.key === item)?.value || ""
}
@@ -390,7 +391,7 @@ const Page = () => {
queryFn={async () => sortOrderOptions.map((s) => s.key)}
set={setSortOrder}
values={sortOrder}
- title="Sort Order"
+ title={t("library.filters.sort_order")}
renderItemLabel={(item) =>
sortOrderOptions.find((i) => i.key === item)?.value || ""
}
@@ -436,7 +437,7 @@ const Page = () => {
if (flatData.length === 0)
return (
- No items found
+ {t("library.no_items_found")}
);
@@ -445,7 +446,7 @@ const Page = () => {
key={orientation}
ListEmptyComponent={
- No results
+ {t("library.no_results")}
}
contentInsetAdjustmentBehavior="automatic"
diff --git a/app/(auth)/(tabs)/(libraries)/_layout.tsx b/app/(auth)/(tabs)/(libraries)/_layout.tsx
index 542d8af3..84beca5a 100644
--- a/app/(auth)/(tabs)/(libraries)/_layout.tsx
+++ b/app/(auth)/(tabs)/(libraries)/_layout.tsx
@@ -3,10 +3,13 @@ import { useSettings } from "@/utils/atoms/settings";
import { Ionicons } from "@expo/vector-icons";
import { Stack } from "expo-router";
import { Platform } from "react-native";
-import * as DropdownMenu from "@/components/DropdownMenu";
+const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
+import { useTranslation } from "react-i18next";
export default function IndexLayout() {
- const [settings, updateSettings] = useSettings();
+ const [settings, updateSettings, pluginSettings] = useSettings();
+
+ const { t } = useTranslation();
if (!settings?.libraryOptions) return null;
@@ -17,172 +20,178 @@ export default function IndexLayout() {
options={{
headerShown: true,
headerLargeTitle: true,
- headerTitle: "Library",
+ headerTitle: t("tabs.library"),
headerBlurEffect: "prominent",
headerLargeStyle: {
backgroundColor: "black",
},
headerTransparent: Platform.OS === "ios" ? true : false,
headerShadowVisible: false,
- headerRight: () => (
-
-
-
-
-
- Display
-
-
-
- Display
-
-
+ !pluginSettings?.libraryOptions?.locked &&
+ !Platform.isTV && (
+
+
+
+
+
+
+ {t("library.options.display")}
+
+
+
+
+ {t("library.options.display")}
+
+
+
+ updateSettings({
+ libraryOptions: {
+ ...settings.libraryOptions,
+ display: "row",
+ },
+ })
+ }
+ >
+
+
+ {t("library.options.row")}
+
+
+
+ updateSettings({
+ libraryOptions: {
+ ...settings.libraryOptions,
+ display: "list",
+ },
+ })
+ }
+ >
+
+
+ {t("library.options.list")}
+
+
+
+
+
+
+ {t("library.options.image_style")}
+
+
+
+ updateSettings({
+ libraryOptions: {
+ ...settings.libraryOptions,
+ imageStyle: "poster",
+ },
+ })
+ }
+ >
+
+
+ {t("library.options.poster")}
+
+
+
+ updateSettings({
+ libraryOptions: {
+ ...settings.libraryOptions,
+ imageStyle: "cover",
+ },
+ })
+ }
+ >
+
+
+ {t("library.options.cover")}
+
+
+
+
+
+
+ {
+ if (settings.libraryOptions.imageStyle === "poster")
+ return;
+ updateSettings({
+ libraryOptions: {
+ ...settings.libraryOptions,
+ showTitles: newValue === "on" ? true : false,
+ },
+ });
+ }}
>
-
- updateSettings({
- libraryOptions: {
- ...settings.libraryOptions,
- display: "row",
- },
- })
- }
- >
-
-
- Row
-
-
-
- updateSettings({
- libraryOptions: {
- ...settings.libraryOptions,
- display: "list",
- },
- })
- }
- >
-
-
- List
-
-
-
-
-
-
- Image style
-
-
+
+ {t("library.options.show_titles")}
+
+
+ {
+ updateSettings({
+ libraryOptions: {
+ ...settings.libraryOptions,
+ showStats: newValue === "on" ? true : false,
+ },
+ });
+ }}
>
-
- updateSettings({
- libraryOptions: {
- ...settings.libraryOptions,
- imageStyle: "poster",
- },
- })
- }
- >
-
-
- Poster
-
-
-
- updateSettings({
- libraryOptions: {
- ...settings.libraryOptions,
- imageStyle: "cover",
- },
- })
- }
- >
-
-
- Cover
-
-
-
-
-
-
- {
- if (settings.libraryOptions.imageStyle === "poster")
- return;
- updateSettings({
- libraryOptions: {
- ...settings.libraryOptions,
- showTitles: newValue === "on" ? true : false,
- },
- });
- }}
- >
-
-
- Show titles
-
-
- {
- updateSettings({
- libraryOptions: {
- ...settings.libraryOptions,
- showStats: newValue === "on" ? true : false,
- },
- });
- }}
- >
-
-
- Show stats
-
-
-
+
+
+ {t("library.options.show_stats")}
+
+
+
-
-
-
- ),
+
+
+
+ ),
}}
/>
{
- if (!api || !user?.Id) {
- return null;
- }
-
- const response = await getUserViewsApi(api).getUserViews({
- userId: user.Id,
+ const response = await getUserViewsApi(api!).getUserViews({
+ userId: user?.Id,
});
return response.data.Items || null;
},
- enabled: !!api && !!user?.Id,
- staleTime: 60 * 1000 * 60,
+ staleTime: 60,
});
+ const libraries = useMemo(
+ () =>
+ data
+ ?.filter((l) => !settings?.hiddenLibraries?.includes(l.Id!))
+ .filter((l) => l.CollectionType !== "music")
+ .filter((l) => l.CollectionType !== "books") || [],
+ [data, settings?.hiddenLibraries]
+ );
+
useEffect(() => {
for (const item of data || []) {
queryClient.prefetchQuery({
@@ -63,10 +70,10 @@ export default function index() {
);
- if (!data)
+ if (!libraries)
return (
- No libraries found
+ {t("library.no_libraries_found")}
);
@@ -81,7 +88,7 @@ export default function index() {
paddingLeft: insets.left,
paddingRight: insets.right,
}}
- data={data}
+ data={libraries}
renderItem={({ item }) => }
keyExtractor={(item) => item.Id || ""}
ItemSeparatorComponent={() =>
diff --git a/app/(auth)/(tabs)/(search)/_layout.tsx b/app/(auth)/(tabs)/(search)/_layout.tsx
index 1119e2a4..b031908e 100644
--- a/app/(auth)/(tabs)/(search)/_layout.tsx
+++ b/app/(auth)/(tabs)/(search)/_layout.tsx
@@ -4,8 +4,10 @@ import {
} from "@/components/stacks/NestedTabPageStack";
import { Stack } from "expo-router";
import { Platform } from "react-native";
+import { useTranslation } from "react-i18next";
export default function SearchLayout() {
+ const { t } = useTranslation();
return (
-
+
+
+
);
}
diff --git a/app/(auth)/(tabs)/(search)/index.tsx b/app/(auth)/(tabs)/(search)/index.tsx
index 373a1fbf..ccb90cb6 100644
--- a/app/(auth)/(tabs)/(search)/index.tsx
+++ b/app/(auth)/(tabs)/(search)/index.tsx
@@ -2,14 +2,16 @@ import { Input } from "@/components/common/Input";
import { Text } from "@/components/common/Text";
import { TouchableItemRouter } from "@/components/common/TouchableItemRouter";
import ContinueWatchingPoster from "@/components/ContinueWatchingPoster";
+import { Tag } from "@/components/GenreTags";
import { ItemCardText } from "@/components/ItemCardText";
-import { Loader } from "@/components/Loader";
-import AlbumCover from "@/components/posters/AlbumCover";
+import { JellyserrIndexPage } from "@/components/jellyseerr/JellyseerrIndexPage";
import MoviePoster from "@/components/posters/MoviePoster";
import SeriesPoster from "@/components/posters/SeriesPoster";
+import { LoadingSkeleton } from "@/components/search/LoadingSkeleton";
+import { SearchItemWrapper } from "@/components/search/SearchItemWrapper";
+import { useJellyseerr } from "@/hooks/useJellyseerr";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings";
-import { getUserItemData } from "@/utils/jellyfin/user-library/getUserItemData";
import {
BaseItemDto,
BaseItemKind,
@@ -20,7 +22,6 @@ import axios from "axios";
import { Href, router, useLocalSearchParams, useNavigation } from "expo-router";
import { useAtom } from "jotai";
import React, {
- PropsWithChildren,
useCallback,
useEffect,
useLayoutEffect,
@@ -30,19 +31,7 @@ import React, {
import { Platform, ScrollView, TouchableOpacity, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useDebounce } from "use-debounce";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
-import {
- MovieResult,
- PersonResult,
- TvResult,
-} from "@/utils/jellyseerr/server/models/Search";
-import { MediaType } from "@/utils/jellyseerr/server/constants/media";
-import JellyseerrPoster from "@/components/posters/JellyseerrPoster";
-import { Tag } from "@/components/GenreTags";
-import DiscoverSlide from "@/components/jellyseerr/DiscoverSlide";
-import { sortBy } from "lodash";
-import PersonPoster from "@/components/jellyseerr/PersonPoster";
-import { useReactNavigationQuery } from "@/utils/useReactNavigationQuery";
+import { useTranslation } from "react-i18next";
type SearchType = "Library" | "Discover";
@@ -59,6 +48,8 @@ export default function search() {
const params = useLocalSearchParams();
const insets = useSafeAreaInsets();
+ const { t } = useTranslation();
+
const { q, prev } = params as { q: string; prev: Href };
const [searchType, setSearchType] = useState("Library");
@@ -134,7 +125,7 @@ export default function search() {
if (Platform.OS === "ios")
navigation.setOptions({
headerSearchBarOptions: {
- placeholder: "Search...",
+ placeholder: t("search.search"),
onChangeText: (e: any) => {
router.setParams({ q: "" });
setSearch(e.nativeEvent.text);
@@ -155,57 +146,6 @@ export default function search() {
enabled: searchType === "Library" && debouncedSearch.length > 0,
});
- const { data: jellyseerrResults, isFetching: j1 } = useReactNavigationQuery({
- queryKey: ["search", "jellyseerr", "results", debouncedSearch],
- queryFn: async () => {
- const response = await jellyseerrApi?.search({
- query: new URLSearchParams(debouncedSearch).toString(),
- page: 1, // todo: maybe rework page & page-size if first results are not enough...
- language: "en",
- });
-
- return response?.results;
- },
- enabled:
- !!jellyseerrApi &&
- searchType === "Discover" &&
- debouncedSearch.length > 0,
- });
-
- const { data: jellyseerrDiscoverSettings, isFetching: j2 } =
- useReactNavigationQuery({
- queryKey: ["search", "jellyseerr", "discoverSettings", debouncedSearch],
- queryFn: async () => jellyseerrApi?.discoverSettings(),
- enabled:
- !!jellyseerrApi &&
- searchType === "Discover" &&
- debouncedSearch.length == 0,
- });
-
- const jellyseerrMovieResults: MovieResult[] | undefined = useMemo(
- () =>
- jellyseerrResults?.filter(
- (r) => r.mediaType === MediaType.MOVIE
- ) as MovieResult[],
- [jellyseerrResults]
- );
-
- const jellyseerrTvResults: TvResult[] | undefined = useMemo(
- () =>
- jellyseerrResults?.filter(
- (r) => r.mediaType === MediaType.TV
- ) as TvResult[],
- [jellyseerrResults]
- );
-
- const jellyseerrPersonResults: PersonResult[] | undefined = useMemo(
- () =>
- jellyseerrResults?.filter(
- (r) => r.mediaType === "person"
- ) as PersonResult[],
- [jellyseerrResults]
- );
-
const { data: series, isFetching: l2 } = useQuery({
queryKey: ["search", "series", debouncedSearch],
queryFn: () =>
@@ -246,64 +186,19 @@ export default function search() {
enabled: searchType === "Library" && debouncedSearch.length > 0,
});
- const { data: artists, isFetching: l4 } = useQuery({
- queryKey: ["search", "artists", debouncedSearch],
- queryFn: () =>
- searchFn({
- query: debouncedSearch,
- types: ["MusicArtist"],
- }),
- enabled: searchType === "Library" && debouncedSearch.length > 0,
- });
-
- const { data: albums, isFetching: l5 } = useQuery({
- queryKey: ["search", "albums", debouncedSearch],
- queryFn: () =>
- searchFn({
- query: debouncedSearch,
- types: ["MusicAlbum"],
- }),
- enabled: searchType === "Library" && debouncedSearch.length > 0,
- });
-
- const { data: songs, isFetching: l6 } = useQuery({
- queryKey: ["search", "songs", debouncedSearch],
- queryFn: () =>
- searchFn({
- query: debouncedSearch,
- types: ["Audio"],
- }),
- enabled: searchType === "Library" && debouncedSearch.length > 0,
- });
-
const noResults = useMemo(() => {
return !(
- artists?.length ||
- albums?.length ||
- songs?.length ||
movies?.length ||
episodes?.length ||
series?.length ||
collections?.length ||
- actors?.length ||
- jellyseerrMovieResults?.length ||
- jellyseerrTvResults?.length
+ actors?.length
);
- }, [
- artists,
- episodes,
- albums,
- songs,
- movies,
- series,
- collections,
- actors,
- jellyseerrResults,
- ]);
+ }, [episodes, movies, series, collections, actors]);
const loading = useMemo(() => {
- return l1 || l2 || l3 || l4 || l5 || l6 || l7 || l8 || j1 || j2;
- }, [l1, l2, l3, l4, l5, l6, l7, l8, j1, j2]);
+ return l1 || l2 || l3 || l7 || l8;
+ }, [l1, l2, l3, l7, l8]);
return (
<>
@@ -322,7 +217,7 @@ export default function search() {
autoCorrect={false}
returnKeyType="done"
keyboardType="web-search"
- placeholder="Search here..."
+ placeholder={t("search.search_here")}
value={search}
onChangeText={(text) => setSearch(text)}
/>
@@ -332,7 +227,7 @@ export default function search() {
setSearchType("Library")}>
setSearchType("Discover")}>
)}
- {!!q && (
-
-
- Results for {q}
-
-
- )}
- {searchType === "Library" && (
- <>
+
+
+
+
+
+ {searchType === "Library" ? (
+
m.Id!)}
renderItem={(item: BaseItemDto) => (
m.Id!)}
- header="Series"
+ header={t("search.series")}
renderItem={(item: BaseItemDto) => (
m.Id!)}
- header="Episodes"
+ header={t("search.episodes")}
renderItem={(item: BaseItemDto) => (
m.Id!)}
- header="Collections"
+ header={t("search.collections")}
renderItem={(item: BaseItemDto) => (
m.Id!)}
- header="Actors"
+ header={t("search.actors")}
renderItem={(item: BaseItemDto) => (
)}
/>
- >
- )}
- {searchType === "Discover" && (
- <>
- (
-
- )}
- />
- (
-
- )}
- />
- (
-
- )}
- />
- >
+
+ ) : (
+
)}
- {loading ? (
-
-
-
- ) : noResults && debouncedSearch.length > 0 ? (
-
-
- No results found for
-
-
- "{debouncedSearch}"
-
-
- ) : debouncedSearch.length === 0 && searchType === "Library" ? (
-
- {exampleSearches.map((e) => (
- setSearch(e)}
- key={e}
- className="mb-2"
- >
- {e}
-
- ))}
-
- ) : debouncedSearch.length === 0 && searchType === "Discover" ? (
-
- {sortBy?.(
- jellyseerrDiscoverSettings?.filter((s) => s.enabled),
- "order"
- ).map((slide) => (
-
- ))}
-
- ) : null}
+ {searchType === "Library" && (
+ <>
+ {!loading && noResults && debouncedSearch.length > 0 ? (
+
+
+ {t("search.no_results_found_for")}
+
+
+ "{debouncedSearch}"
+
+
+ ) : debouncedSearch.length === 0 ? (
+
+ {exampleSearches.map((e) => (
+ setSearch(e)}
+ key={e}
+ className="mb-2"
+ >
+ {e}
+
+ ))}
+
+ ) : null}
+ >
+ )}
>
);
}
-
-type Props = {
- ids?: string[] | null;
- items?: T[];
- renderItem: (item: any) => React.ReactNode;
- header?: string;
-};
-
-const SearchItemWrapper = ({
- ids,
- items,
- renderItem,
- header,
-}: PropsWithChildren>) => {
- const [api] = useAtom(apiAtom);
- const [user] = useAtom(userAtom);
-
- const { data, isLoading: l1 } = useQuery({
- queryKey: ["items", ids],
- queryFn: async () => {
- if (!user?.Id || !api || !ids || ids.length === 0) {
- return [];
- }
-
- const itemPromises = ids.map((id) =>
- getUserItemData({
- api,
- userId: user.Id,
- itemId: id,
- })
- );
-
- const results = await Promise.all(itemPromises);
-
- // Filter out null items
- return results.filter(
- (item) => item !== null
- ) as unknown as BaseItemDto[];
- },
- enabled: !!ids && ids.length > 0 && !!api && !!user?.Id,
- staleTime: Infinity,
- });
-
- if (!data && (!items || items.length === 0)) return null;
-
- return (
- <>
- {header}
-
- {data && data?.length > 0
- ? data.map((item) => renderItem(item))
- : items && items?.length > 0
- ? items.map((i) => renderItem(i))
- : undefined}
-
- >
- );
-};
diff --git a/app/(auth)/(tabs)/_layout.tsx b/app/(auth)/(tabs)/_layout.tsx
index 47e5bfaa..ade003ff 100644
--- a/app/(auth)/(tabs)/_layout.tsx
+++ b/app/(auth)/(tabs)/_layout.tsx
@@ -1,7 +1,8 @@
-import React from "react";
+import React, { useCallback, useRef } from "react";
import { Platform } from "react-native";
+import { useTranslation } from "react-i18next";
-import { withLayoutContext } from "expo-router";
+import { useFocusEffect, useRouter, withLayoutContext } from "expo-router";
import {
createNativeBottomTabNavigator,
@@ -13,12 +14,13 @@ const { Navigator } = createNativeBottomTabNavigator();
import { BottomTabNavigationOptions } from "@react-navigation/bottom-tabs";
import { Colors } from "@/constants/Colors";
+import { useSettings } from "@/utils/atoms/settings";
+import { storage } from "@/utils/mmkv";
import type {
ParamListBase,
TabNavigationState,
} from "@react-navigation/native";
import { SystemBars } from "react-native-edge-to-edge";
-import { useSettings } from "@/utils/atoms/settings";
export const NativeTabs = withLayoutContext<
BottomTabNavigationOptions,
@@ -29,11 +31,29 @@ export const NativeTabs = withLayoutContext<
export default function TabLayout() {
const [settings] = useSettings();
+ const { t } = useTranslation();
+ const router = useRouter();
+
+ useFocusEffect(
+ useCallback(() => {
+ const hasShownIntro = storage.getBoolean("hasShownIntro");
+ if (!hasShownIntro) {
+ const timer = setTimeout(() => {
+ router.push("/intro/page");
+ }, 1000);
+
+ return () => {
+ clearTimeout(timer);
+ };
+ }
+ }, [])
+ );
+
return (
<>
@@ -57,7 +77,7 @@ export default function TabLayout() {
@@ -71,7 +91,7 @@ export default function TabLayout() {
@@ -87,7 +107,7 @@ export default function TabLayout() {
@@ -101,7 +121,7 @@ export default function TabLayout() {
-
>
);
diff --git a/app/(auth)/player/direct-player.tsx b/app/(auth)/player/direct-player.tsx
index fa27fac0..03b29cc3 100644
--- a/app/(auth)/player/direct-player.tsx
+++ b/app/(auth)/player/direct-player.tsx
@@ -27,7 +27,7 @@ import {
getUserLibraryApi,
} from "@jellyfin/sdk/lib/utils/api";
import { useQuery } from "@tanstack/react-query";
-import * as Haptics from "@/packages/expo-haptics";
+import { useHaptic } from "@/hooks/useHaptic";
import { useFocusEffect, useGlobalSearchParams } from "expo-router";
import { useAtomValue } from "jotai";
import React, {
@@ -48,11 +48,14 @@ import {
import { useSharedValue } from "react-native-reanimated";
import settings from "../(tabs)/(home)/settings";
import { useSettings } from "@/utils/atoms/settings";
+import { useTranslation } from "react-i18next";
+import { useSafeAreaInsets } from "react-native-safe-area-context";
export default function page() {
const videoRef = useRef(null);
const user = useAtomValue(userAtom);
const api = useAtomValue(apiAtom);
+ const { t } = useTranslation();
const [isPlaybackStopped, setIsPlaybackStopped] = useState(false);
const [showControls, _setShowControls] = useState(true);
@@ -68,9 +71,11 @@ export default function page() {
const { getDownloadedItem } = useDownload();
const revalidateProgressCache = useInvalidatePlaybackProgressCache();
+ const lightHapticFeedback = useHaptic("light");
+
const setShowControls = useCallback((show: boolean) => {
_setShowControls(show);
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
}, []);
const {
@@ -158,7 +163,7 @@ export default function page() {
const { mediaSource, sessionId, url } = res;
if (!sessionId || !mediaSource || !url) {
- Alert.alert("Error", "Failed to get stream url");
+ Alert.alert(t("player.error"), t("player.failed_to_get_stream_url"));
return null;
}
@@ -175,7 +180,7 @@ export default function page() {
const togglePlay = useCallback(async () => {
if (!api) return;
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
if (isPlaying) {
await videoRef.current?.pause();
@@ -411,6 +416,8 @@ export default function page() {
}
}
+ const insets = useSafeAreaInsets();
+
if (!item || isLoadingItem || isLoadingStreamUrl || !stream)
return (
@@ -421,7 +428,7 @@ export default function page() {
if (isErrorItem || isErrorStreamUrl)
return (
- Error
+ {t("player.error")}
);
@@ -435,6 +442,8 @@ export default function page() {
position: "relative",
flexDirection: "column",
justifyContent: "center",
+ paddingLeft: ignoreSafeAreas ? 0 : insets.left,
+ paddingRight: ignoreSafeAreas ? 0 : insets.right,
}}
>
{
console.error("Video Error:", e.nativeEvent);
Alert.alert(
- "Error",
- "An error occurred while playing the video. Check logs in settings."
+ t("player.error"),
+ t("player.an_error_occured_while_playing_the_video")
);
writeToLog("ERROR", "Video Error", e.nativeEvent);
}}
diff --git a/app/(auth)/player/music-player.tsx b/app/(auth)/player/music-player.tsx
deleted file mode 100644
index 5419cafd..00000000
--- a/app/(auth)/player/music-player.tsx
+++ /dev/null
@@ -1,417 +0,0 @@
-import { Text } from "@/components/common/Text";
-import { Loader } from "@/components/Loader";
-import { Controls } from "@/components/video-player/controls/Controls";
-import { useOrientation } from "@/hooks/useOrientation";
-import { useOrientationSettings } from "@/hooks/useOrientationSettings";
-import { useWebSocket } from "@/hooks/useWebsockets";
-import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
-import { useSettings } from "@/utils/atoms/settings";
-import { getBackdropUrl } from "@/utils/jellyfin/image/getBackdropUrl";
-import { getAuthHeaders } from "@/utils/jellyfin/jellyfin";
-import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
-import { secondsToTicks } from "@/utils/secondsToTicks";
-import { Api } from "@jellyfin/sdk";
-import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
-import {
- getPlaystateApi,
- getUserLibraryApi,
-} from "@jellyfin/sdk/lib/utils/api";
-import { useQuery } from "@tanstack/react-query";
-import * as Haptics from "@/packages/expo-haptics";
-import { Image } from "expo-image";
-import { useFocusEffect, useLocalSearchParams } from "expo-router";
-import { useAtomValue } from "jotai";
-import React, { useCallback, useMemo, useRef, useState } from "react";
-import { Pressable, useWindowDimensions, View } from "react-native";
-import { useSharedValue } from "react-native-reanimated";
-import Video, { OnProgressData, VideoRef } from "react-native-video";
-
-export default function page() {
- const api = useAtomValue(apiAtom);
- const user = useAtomValue(userAtom);
- const [settings] = useSettings();
- const videoRef = useRef(null);
- const windowDimensions = useWindowDimensions();
-
- const firstTime = useRef(true);
-
- const [isPlaybackStopped, setIsPlaybackStopped] = useState(false);
- const [showControls, setShowControls] = useState(true);
- const [ignoreSafeAreas, setIgnoreSafeAreas] = useState(false);
- const [isPlaying, setIsPlaying] = useState(false);
- const [isBuffering, setIsBuffering] = useState(true);
-
- const progress = useSharedValue(0);
- const isSeeking = useSharedValue(false);
- const cacheProgress = useSharedValue(0);
-
- const {
- itemId,
- audioIndex: audioIndexStr,
- subtitleIndex: subtitleIndexStr,
- mediaSourceId,
- bitrateValue: bitrateValueStr,
- } = useLocalSearchParams<{
- itemId: string;
- audioIndex: string;
- subtitleIndex: string;
- mediaSourceId: string;
- bitrateValue: string;
- }>();
-
- const audioIndex = audioIndexStr ? parseInt(audioIndexStr, 10) : undefined;
- const subtitleIndex = subtitleIndexStr
- ? parseInt(subtitleIndexStr, 10)
- : undefined;
- const bitrateValue = bitrateValueStr
- ? parseInt(bitrateValueStr, 10)
- : undefined;
-
- const {
- data: item,
- isLoading: isLoadingItem,
- isError: isErrorItem,
- } = useQuery({
- queryKey: ["item", itemId],
- queryFn: async () => {
- if (!api) return;
- const res = await getUserLibraryApi(api).getItem({
- itemId,
- userId: user?.Id,
- });
-
- return res.data;
- },
- enabled: !!itemId && !!api,
- staleTime: 0,
- });
-
- const {
- data: stream,
- isLoading: isLoadingStreamUrl,
- isError: isErrorStreamUrl,
- } = useQuery({
- queryKey: ["stream-url"],
- queryFn: async () => {
- if (!api) return;
- const res = await getStreamUrl({
- api,
- item,
- startTimeTicks: item?.UserData?.PlaybackPositionTicks!,
- userId: user?.Id,
- audioStreamIndex: audioIndex,
- maxStreamingBitrate: bitrateValue,
- mediaSourceId: mediaSourceId,
- subtitleStreamIndex: subtitleIndex,
- });
-
- if (!res) return null;
-
- const { mediaSource, sessionId, url } = res;
-
- if (!sessionId || !mediaSource || !url) return null;
-
- return {
- mediaSource,
- sessionId,
- url,
- };
- },
- });
-
- const poster = usePoster(item, api);
- const videoSource = useVideoSource(item, api, poster, stream?.url);
-
- const togglePlay = useCallback(
- async (ticks: number) => {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
- if (isPlaying) {
- videoRef.current?.pause();
- await getPlaystateApi(api!).onPlaybackProgress({
- itemId: item?.Id!,
- audioStreamIndex: audioIndex ? audioIndex : undefined,
- subtitleStreamIndex: subtitleIndex ? subtitleIndex : undefined,
- mediaSourceId: mediaSourceId,
- positionTicks: Math.floor(ticks),
- isPaused: true,
- playMethod: stream?.url.includes("m3u8")
- ? "Transcode"
- : "DirectStream",
- playSessionId: stream?.sessionId,
- });
- } else {
- videoRef.current?.resume();
- await getPlaystateApi(api!).onPlaybackProgress({
- itemId: item?.Id!,
- audioStreamIndex: audioIndex ? audioIndex : undefined,
- subtitleStreamIndex: subtitleIndex ? subtitleIndex : undefined,
- mediaSourceId: mediaSourceId,
- positionTicks: Math.floor(ticks),
- isPaused: false,
- playMethod: stream?.url.includes("m3u8")
- ? "Transcode"
- : "DirectStream",
- playSessionId: stream?.sessionId,
- });
- }
- },
- [
- isPlaying,
- api,
- item,
- videoRef,
- settings,
- audioIndex,
- subtitleIndex,
- mediaSourceId,
- stream,
- ]
- );
-
- const play = useCallback(() => {
- videoRef.current?.resume();
- reportPlaybackStart();
- }, [videoRef]);
-
- const pause = useCallback(() => {
- videoRef.current?.pause();
- }, [videoRef]);
-
- const stop = useCallback(() => {
- setIsPlaybackStopped(true);
- videoRef.current?.pause();
- reportPlaybackStopped();
- }, [videoRef]);
-
- const seek = useCallback(
- (seconds: number) => {
- videoRef.current?.seek(seconds);
- },
- [videoRef]
- );
-
- const reportPlaybackStopped = async () => {
- if (!item?.Id) return;
- await getPlaystateApi(api!).onPlaybackStopped({
- itemId: item.Id,
- mediaSourceId: mediaSourceId,
- positionTicks: Math.floor(progress.value),
- playSessionId: stream?.sessionId,
- });
- };
-
- const reportPlaybackStart = async () => {
- if (!item?.Id) return;
- await getPlaystateApi(api!).onPlaybackStart({
- itemId: item?.Id,
- audioStreamIndex: audioIndex ? audioIndex : undefined,
- subtitleStreamIndex: subtitleIndex ? subtitleIndex : undefined,
- mediaSourceId: mediaSourceId,
- playMethod: stream?.url.includes("m3u8") ? "Transcode" : "DirectStream",
- playSessionId: stream?.sessionId,
- });
- };
-
- const onProgress = useCallback(
- async (data: OnProgressData) => {
- if (isSeeking.value === true) return;
- if (isPlaybackStopped === true) return;
-
- const ticks = data.currentTime * 10000000;
-
- progress.value = secondsToTicks(data.currentTime);
- cacheProgress.value = secondsToTicks(data.playableDuration);
- setIsBuffering(data.playableDuration === 0);
-
- if (!item?.Id || data.currentTime === 0) return;
-
- await getPlaystateApi(api!).onPlaybackProgress({
- itemId: item.Id!,
- audioStreamIndex: audioIndex ? audioIndex : undefined,
- subtitleStreamIndex: subtitleIndex ? subtitleIndex : undefined,
- mediaSourceId: mediaSourceId,
- positionTicks: Math.round(ticks),
- isPaused: !isPlaying,
- playMethod: stream?.url.includes("m3u8") ? "Transcode" : "DirectStream",
- playSessionId: stream?.sessionId,
- });
- },
- [
- item,
- isPlaying,
- api,
- isPlaybackStopped,
- audioIndex,
- subtitleIndex,
- mediaSourceId,
- stream,
- ]
- );
-
- useFocusEffect(
- useCallback(() => {
- play();
-
- return () => {
- stop();
- };
- }, [play, stop])
- );
-
- useOrientation();
- useOrientationSettings();
-
- useWebSocket({
- isPlaying: isPlaying,
- pauseVideo: pause,
- playVideo: play,
- stopPlayback: stop,
- });
-
- if (isLoadingItem || isLoadingStreamUrl)
- return (
-
-
-
- );
-
- if (isErrorItem || isErrorStreamUrl)
- return (
-
- Error
-
- );
-
- if (!item || !stream)
- return (
-
- Error
-
- );
-
- return (
-
-
-
-
-
- {
- setShowControls(!showControls);
- }}
- className="absolute z-0 h-full w-full opacity-0"
- >
- {videoSource && (
-
-
-
-
- );
-}
-
-export function usePoster(
- item: BaseItemDto | null | undefined,
- api: Api | null
-): string | undefined {
- const poster = useMemo(() => {
- if (!item || !api) return undefined;
- return item.Type === "Audio"
- ? `${api.basePath}/Items/${item.AlbumId}/Images/Primary?tag=${item.AlbumPrimaryImageTag}&quality=90&maxHeight=200&maxWidth=200`
- : getBackdropUrl({
- api,
- item: item,
- quality: 70,
- width: 200,
- });
- }, [item, api]);
-
- return poster ?? undefined;
-}
-
-export function useVideoSource(
- item: BaseItemDto | null | undefined,
- api: Api | null,
- poster: string | undefined,
- url?: string | null
-) {
- const videoSource = useMemo(() => {
- if (!item || !api || !url) {
- return null;
- }
-
- const startPosition = item?.UserData?.PlaybackPositionTicks
- ? Math.round(item.UserData.PlaybackPositionTicks / 10000)
- : 0;
-
- return {
- uri: url,
- isNetwork: true,
- startPosition,
- headers: getAuthHeaders(api),
- metadata: {
- artist: item?.AlbumArtist ?? undefined,
- title: item?.Name || "Unknown",
- description: item?.Overview ?? undefined,
- imageUri: poster,
- subtitle: item?.Album ?? undefined,
- },
- };
- }, [item, api, poster]);
-
- return videoSource;
-}
diff --git a/app/(auth)/player/transcoding-player.tsx b/app/(auth)/player/transcoding-player.tsx
index 06b78722..38a2b2e5 100644
--- a/app/(auth)/player/transcoding-player.tsx
+++ b/app/(auth)/player/transcoding-player.tsx
@@ -20,7 +20,7 @@ import {
getUserLibraryApi,
} from "@jellyfin/sdk/lib/utils/api";
import { useQuery } from "@tanstack/react-query";
-import * as Haptics from "@/packages/expo-haptics";
+import { useHaptic } from "@/hooks/useHaptic";
import { useFocusEffect, useLocalSearchParams } from "expo-router";
import { useAtomValue } from "jotai";
import React, {
@@ -39,15 +39,18 @@ import Video, {
VideoRef,
} from "react-native-video";
import { SubtitleHelper } from "@/utils/SubtitleHelper";
+import { useTranslation } from "react-i18next";
const Player = () => {
const api = useAtomValue(apiAtom);
const user = useAtomValue(userAtom);
const [settings] = useSettings();
const videoRef = useRef(null);
+ const { t } = useTranslation();
const firstTime = useRef(true);
const revalidateProgressCache = useInvalidatePlaybackProgressCache();
+ const lightHapticFeedback = useHaptic("light");
const [isPlaybackStopped, setIsPlaybackStopped] = useState(false);
const [showControls, _setShowControls] = useState(true);
@@ -58,7 +61,7 @@ const Player = () => {
const setShowControls = useCallback((show: boolean) => {
_setShowControls(show);
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
}, []);
const progress = useSharedValue(0);
@@ -167,7 +170,7 @@ const Player = () => {
const videoSource = useVideoSource(item, api, poster, stream?.url);
const togglePlay = useCallback(async () => {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
if (isPlaying) {
videoRef.current?.pause();
await getPlaystateApi(api!).onPlaybackProgress({
@@ -373,7 +376,7 @@ const Player = () => {
if (isErrorItem || isErrorStreamUrl)
return (
- Error
+ {t("player.error")}
);
@@ -413,7 +416,6 @@ const Player = () => {
playWhenInactive={true}
allowsExternalPlayback={true}
playInBackground={true}
- pictureInPicture={true}
showNotificationControls={true}
ignoreSilentSwitch="ignore"
fullscreen={false}
@@ -440,7 +442,7 @@ const Player = () => {
/>
>
) : (
- No video source...
+ {t("player.no_video_source")}
)}
@@ -531,7 +533,6 @@ export function useVideoSource(
startPosition,
headers: getAuthHeaders(api),
metadata: {
- artist: item?.AlbumArtist ?? undefined,
title: item?.Name || "Unknown",
description: item?.Overview ?? undefined,
imageUri: poster,
diff --git a/app/+not-found.tsx b/app/+not-found.tsx
index 41968287..5a8c1964 100644
--- a/app/+not-found.tsx
+++ b/app/+not-found.tsx
@@ -1,13 +1,10 @@
-import { Link, Stack, usePathname } from "expo-router";
+import { Link, Stack } from "expo-router";
import { StyleSheet } from "react-native";
import { ThemedText } from "@/components/ThemedText";
import { ThemedView } from "@/components/ThemedView";
-import { useEffect } from "react";
export default function NotFoundScreen() {
- const pathname = usePathname();
-
return (
<>
diff --git a/app/_layout.tsx b/app/_layout.tsx
index 57b0e1e0..8553f275 100644
--- a/app/_layout.tsx
+++ b/app/_layout.tsx
@@ -1,6 +1,7 @@
import "@/augmentations";
import { Platform } from "react-native";
import { Text } from "@/components/common/Text";
+import i18n from "@/i18n";
import { DownloadProvider } from "@/providers/DownloadProvider";
import {
getOrSetDeviceId,
@@ -9,8 +10,11 @@ import {
} from "@/providers/JellyfinProvider";
import { JobQueueProvider } from "@/providers/JobQueueProvider";
import { PlaySettingsProvider } from "@/providers/PlaySettingsProvider";
+import {
+ SplashScreenProvider,
+ useSplashScreenLoading,
+} from "@/providers/SplashScreenProvider";
import { WebSocketProvider } from "@/providers/WebSocketProvider";
-import { orientationAtom } from "@/utils/atoms/orientation";
import { Settings, useSettings } from "@/utils/atoms/settings";
import { BACKGROUND_FETCH_TASK } from "@/utils/background-tasks";
import { LogProvider, writeToLog } from "@/utils/log";
@@ -19,11 +23,6 @@ import { cancelJobById, getAllJobsByDeviceId } from "@/utils/optimize-server";
import { ActionSheetProvider } from "@expo/react-native-action-sheet";
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
-// import {
-// checkForExistingDownloads,
-// completeHandler,
-// download,
-// } from "@kesha-antonov/react-native-background-downloader";
const BackGroundDownloader = !Platform.isTV
? require("@kesha-antonov/react-native-background-downloader")
: null;
@@ -35,22 +34,20 @@ const BackgroundFetch = !Platform.isTV
import * as FileSystem from "expo-file-system";
import { useFonts } from "expo-font";
import { useKeepAwake } from "expo-keep-awake";
-import * as Linking from "expo-linking";
const Notifications = !Platform.isTV ? require("expo-notifications") : null;
import { router, Stack } from "expo-router";
import * as ScreenOrientation from "@/packages/expo-screen-orientation";
-import * as SplashScreen from "expo-splash-screen";
const TaskManager = !Platform.isTV ? require("expo-task-manager") : null;
-import { Provider as JotaiProvider, useAtom } from "jotai";
+import { getLocales } from "expo-localization";
+import { Provider as JotaiProvider } from "jotai";
import { useEffect, useRef } from "react";
-import { Appearance, AppState, TouchableOpacity } from "react-native";
+import { I18nextProvider, useTranslation } from "react-i18next";
+import { Appearance, AppState } from "react-native";
import { SystemBars } from "react-native-edge-to-edge";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import "react-native-reanimated";
import { Toaster } from "sonner-native";
-SplashScreen.preventAutoHideAsync();
-
if (!Platform.isTV) {
Notifications.setNotificationHandler({
handleNotification: async () => ({
@@ -222,26 +219,20 @@ const checkAndRequestPermissions = async () => {
};
export default function RootLayout() {
- const [loaded] = useFonts({
- SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
- });
-
- useEffect(() => {
- if (loaded) {
- SplashScreen.hideAsync();
- }
- }, [loaded]);
-
Appearance.setColorScheme("dark");
- if (!loaded) {
- return null;
- }
-
return (
-
-
-
+
+
+
+
+
+
+
+
+
+
+
);
}
@@ -258,16 +249,21 @@ const queryClient = new QueryClient({
});
function Layout() {
- const [settings, updateSettings] = useSettings();
- const [orientation, setOrientation] = useAtom(orientationAtom);
-
- useKeepAwake();
-
+ const [settings] = useSettings();
const appState = useRef(AppState.currentState);
+ useEffect(() => {
+ i18n.changeLanguage(
+ settings?.preferedLanguage ?? getLocales()[0].languageCode ?? "en"
+ );
+ }, [settings?.preferedLanguage, i18n]);
+
if (!Platform.isTV) {
+ useKeepAwake();
useNotificationObserver();
+ const { i18n } = useTranslation();
+
useEffect(() => {
checkAndRequestPermissions();
}, []);
@@ -300,95 +296,79 @@ function Layout() {
subscription.remove();
};
}, []);
-
- useEffect(() => {
- const subscription = ScreenOrientation.addOrientationChangeListener(
- (event) => {
- setOrientation(event.orientationInfo.orientation);
- }
- );
-
- ScreenOrientation.getOrientationAsync().then((initialOrientation) => {
- setOrientation(initialOrientation);
- });
-
- return () => {
- ScreenOrientation.removeOrientationChangeListener(subscription);
- };
- }, []);
}
- const url = Linking.useURL();
+ const [loaded] = useFonts({
+ SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
+ });
- if (url) {
- const { hostname, path, queryParams } = Linking.parse(url);
+ useSplashScreenLoading(!loaded);
+
+ if (!loaded) {
+ return null;
}
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- null,
- }}
- />
- null,
- }}
- />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ null,
+ }}
+ />
+ null,
+ }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
diff --git a/app/login.tsx b/app/login.tsx
index 54aa03a8..b55f4b1f 100644
--- a/app/login.tsx
+++ b/app/login.tsx
@@ -1,11 +1,12 @@
import { Button } from "@/components/Button";
import { Input } from "@/components/common/Input";
import { Text } from "@/components/common/Text";
+import JellyfinServerDiscovery from "@/components/JellyfinServerDiscovery";
import { PreviousServersList } from "@/components/PreviousServersList";
+import { Colors } from "@/constants/Colors";
import { apiAtom, useJellyfin } from "@/providers/JellyfinProvider";
-import { Ionicons } from "@expo/vector-icons";
+import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
import { PublicSystemInfo } from "@jellyfin/sdk/lib/generated-client";
-import { getSystemApi } from "@jellyfin/sdk/lib/utils/api";
import { Image } from "expo-image";
import { useLocalSearchParams, useNavigation } from "expo-router";
import { useAtom } from "jotai";
@@ -20,12 +21,11 @@ import {
} from "react-native";
import { z } from "zod";
-
+import { t } from 'i18next';
const CredentialsSchema = z.object({
- username: z.string().min(1, "Username is required"),
-});
+ username: z.string().min(1, t("login.username_required")),});
-const Login: React.FC = () => {
+ const Login: React.FC = () => {
const { setServer, login, removeServer, initiateQuickConnect } =
useJellyfin();
const [api] = useAtom(apiAtom);
@@ -39,7 +39,6 @@ const Login: React.FC = () => {
const [serverURL, setServerURL] = useState(_apiUrl);
const [serverName, setServerName] = useState("");
- const [error, setError] = useState("");
const [credentials, setCredentials] = useState<{
username: string;
password: string;
@@ -77,8 +76,10 @@ const Login: React.FC = () => {
onPress={() => {
removeServer();
}}
+ className="flex flex-row items-center"
>
-
+
+ {t("login.change_server")}
) : null,
});
@@ -95,9 +96,9 @@ const Login: React.FC = () => {
}
} catch (error) {
if (error instanceof Error) {
- setError(error.message);
+ Alert.alert(t("login.connection_failed"), error.message);
} else {
- setError("An unexpected error occurred");
+ Alert.alert(t("login.connection_failed"), t("login.an_unexpected_error_occured"));
}
} finally {
setLoading(false);
@@ -136,6 +137,8 @@ const Login: React.FC = () => {
return url;
}
+ return undefined;
+ } catch {
return undefined;
} finally {
setLoadingServerCheck(false);
@@ -159,14 +162,13 @@ const Login: React.FC = () => {
*
*/
const handleConnect = useCallback(async (url: string) => {
- url = url.trim();
-
+ url = url.trim().replace(/\/$/, "");
const result = await checkUrl(url);
if (result === undefined) {
Alert.alert(
- "Connection failed",
- "Could not connect to the server. Please check the URL and your network connection."
+ t("login.connection_failed"),
+ t("login.could_not_connect_to_server")
);
return;
}
@@ -178,14 +180,14 @@ const Login: React.FC = () => {
try {
const code = await initiateQuickConnect();
if (code) {
- Alert.alert("Quick Connect", `Enter code ${code} to login`, [
+ Alert.alert(t("login.quick_connect"), t("login.enter_code_to_login", {code: code}), [
{
- text: "Got It",
+ text: t("login.got_it"),
},
]);
}
} catch (error) {
- Alert.alert("Error", "Failed to initiate Quick Connect");
+ Alert.alert(t("login.error_title"), t("login.failed_to_initiate_quick_connect"));
}
};
@@ -199,22 +201,21 @@ const Login: React.FC = () => {
-
- Log in
- <>
- {serverName ? (
- <>
- {" to "}
- {serverName}
- >
- ) : null}
- >
-
+
+ <>
+ {serverName ? (
+ <>
+ {t("login.login_to_title") + " "}
+ {serverName}
+ >
+ ) : t("login.login_title")}
+ >
+
{api.basePath}
setCredentials({ ...credentials, username: text })
}
@@ -230,8 +231,7 @@ const Login: React.FC = () => {
/>
setCredentials({ ...credentials, password: text })
}
@@ -244,28 +244,34 @@ const Login: React.FC = () => {
clearButtonMode="while-editing"
maxLength={500}
/>
+
+
+
+
+
+
-
- {error}
-
-
-
-
+
>
) : (
<>
-
+
{
/>
Streamyfin
- Enter the URL to your Jellyfin server
+ {t("server.enter_url_to_jellyfin_server")}
{
textContentType="URL"
maxLength={500}
/>
-
- Make sure to include http or https
-
- {
- handleConnect(s.address);
- }}
- />
-
-
+ {
+ setServerURL(server.address);
+ if (server.serverName) {
+ setServerName(server.serverName);
+ }
+ handleConnect(server.address);
+ }}
+ />
+ {
+ handleConnect(s.address);
+ }}
+ />
>
diff --git a/assets/icons/jellyseerr-logo.svg b/assets/icons/jellyseerr-logo.svg
new file mode 100644
index 00000000..cda2394d
--- /dev/null
+++ b/assets/icons/jellyseerr-logo.svg
@@ -0,0 +1,118 @@
+
+
\ No newline at end of file
diff --git a/assets/images/jellyseerr.PNG b/assets/images/jellyseerr.PNG
new file mode 100644
index 00000000..c72a8da1
Binary files /dev/null and b/assets/images/jellyseerr.PNG differ
diff --git a/augmentations/api.ts b/augmentations/api.ts
new file mode 100644
index 00000000..da5c02a9
--- /dev/null
+++ b/augmentations/api.ts
@@ -0,0 +1,46 @@
+import { Api, AUTHORIZATION_HEADER } from "@jellyfin/sdk";
+import { AxiosRequestConfig, AxiosResponse } from "axios";
+import { StreamyfinPluginConfig } from "@/utils/atoms/settings";
+
+declare module "@jellyfin/sdk" {
+ interface Api {
+ get(
+ url: string,
+ config?: AxiosRequestConfig
+ ): Promise>;
+ post(
+ url: string,
+ data: D,
+ config?: AxiosRequestConfig
+ ): Promise>;
+ getStreamyfinPluginConfig(): Promise>;
+ }
+}
+
+Api.prototype.get = function (
+ url: string,
+ config: AxiosRequestConfig = {}
+): Promise> {
+ return this.axiosInstance.get(`${this.basePath}${url}`, {
+ ...(config ?? {}),
+ headers: { [AUTHORIZATION_HEADER]: this.authorizationHeader },
+ });
+};
+
+Api.prototype.post = function (
+ url: string,
+ data: D,
+ config: AxiosRequestConfig
+): Promise> {
+ return this.axiosInstance.post(`${this.basePath}${url}`, {
+ ...(config || {}),
+ data,
+ headers: { [AUTHORIZATION_HEADER]: this.authorizationHeader },
+ });
+};
+
+Api.prototype.getStreamyfinPluginConfig = function (): Promise<
+ AxiosResponse
+> {
+ return this.get("/Streamyfin/config");
+};
diff --git a/augmentations/index.ts b/augmentations/index.ts
index 22ca2cb0..abec02c9 100644
--- a/augmentations/index.ts
+++ b/augmentations/index.ts
@@ -1,3 +1,4 @@
+export * from "./api";
export * from "./mmkv";
export * from "./number";
export * from "./string";
diff --git a/augmentations/mmkv.ts b/augmentations/mmkv.ts
index 80fbeede..5667502f 100644
--- a/augmentations/mmkv.ts
+++ b/augmentations/mmkv.ts
@@ -13,5 +13,10 @@ MMKV.prototype.get = function (key: string): T | undefined {
}
MMKV.prototype.setAny = function (key: string, value: any | undefined): void {
- this.set(key, JSON.stringify(value));
+ if (value === undefined) {
+ this.delete(key)
+ }
+ else {
+ this.set(key, JSON.stringify(value));
+ }
}
\ No newline at end of file
diff --git a/augmentations/number.ts b/augmentations/number.ts
index c0f53075..15b70507 100644
--- a/augmentations/number.ts
+++ b/augmentations/number.ts
@@ -1,25 +1,23 @@
declare global {
interface Number {
- bytesToReadable(): string;
+ bytesToReadable(decimals?: number): string;
secondsToMilliseconds(): number;
minutesToMilliseconds(): number;
hoursToMilliseconds(): number;
}
}
-Number.prototype.bytesToReadable = function () {
+Number.prototype.bytesToReadable = function (decimals: number = 2) {
const bytes = this.valueOf();
- const gb = bytes / 1e9;
+ if (bytes === 0) return '0 Bytes';
- if (gb >= 1) return `${gb.toFixed(0)} GB`;
+ const k = 1024;
+ const dm = decimals < 0 ? 0 : decimals;
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
- const mb = bytes / 1024.0 / 1024.0;
- if (mb >= 1) return `${mb.toFixed(0)} MB`;
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
- const kb = bytes / 1024.0;
- if (kb >= 1) return `${kb.toFixed(0)} KB`;
-
- return `${bytes.toFixed(2)} B`;
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
};
Number.prototype.secondsToMilliseconds = function () {
diff --git a/bun.lockb b/bun.lockb
index a3b7f578..5d6a7a4a 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/components/AudioTrackSelector.tsx b/components/AudioTrackSelector.tsx
index 11a895fc..d8cba49d 100644
--- a/components/AudioTrackSelector.tsx
+++ b/components/AudioTrackSelector.tsx
@@ -3,6 +3,7 @@ import { useMemo } from "react";
import { TouchableOpacity, View } from "react-native";
import * as DropdownMenu from "@/components/DropdownMenu";
import { Text } from "./common/Text";
+import { useTranslation } from "react-i18next";
interface Props extends React.ComponentProps {
source?: MediaSourceInfo;
@@ -26,6 +27,8 @@ export const AudioTrackSelector: React.FC = ({
[audioStreams, selected]
);
+ const { t } = useTranslation();
+
return (
= ({
- Audio
+ {t("item_card.audio")}
{selectedAudioSteam?.DisplayTitle}
diff --git a/components/BitrateSelector.tsx b/components/BitrateSelector.tsx
index cb284f4b..2fd10b3d 100644
--- a/components/BitrateSelector.tsx
+++ b/components/BitrateSelector.tsx
@@ -2,6 +2,7 @@ import { TouchableOpacity, View } from "react-native";
import * as DropdownMenu from "@/components/DropdownMenu";
import { Text } from "./common/Text";
import { useMemo } from "react";
+import { useTranslation } from "react-i18next";
export type Bitrate = {
key: string;
@@ -27,6 +28,10 @@ export const BITRATES: Bitrate[] = [
key: "2 Mb/s",
value: 2000000,
},
+ {
+ key: "1 Mb/s",
+ value: 1000000,
+ },
{
key: "500 Kb/s",
value: 500000,
@@ -59,6 +64,8 @@ export const BitrateSelector: React.FC = ({
);
}, []);
+ const { t } = useTranslation();
+
return (
= ({
- Quality
+ {t("item_card.quality")}
{BITRATES.find((b) => b.value === selected?.value)?.key}
diff --git a/components/Button.tsx b/components/Button.tsx
index c5c0b746..ca41d06f 100644
--- a/components/Button.tsx
+++ b/components/Button.tsx
@@ -1,4 +1,4 @@
-import * as Haptics from "@/packages/expo-haptics";
+import { useHaptic } from "@/hooks/useHaptic";
import React, { PropsWithChildren, ReactNode, useMemo } from "react";
import { Platform, Text, TouchableOpacity, View } from "react-native";
import { Loader } from "./Loader";
@@ -37,12 +37,14 @@ export const Button: React.FC> = ({
case "red":
return "bg-red-600";
case "black":
- return "bg-neutral-900 border border-neutral-800";
+ return "bg-neutral-900";
case "transparent":
return "bg-transparent";
}
}, [color]);
+ const lightHapticFeedback = useHaptic("light");
+
return (
> = ({
onPress={() => {
if (!loading && !disabled && onPress) {
onPress();
- if (!Platform.isTV) {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
- }
+ lightHapticFeedback();
}
}}
disabled={disabled || loading}
diff --git a/components/Chromecast.tsx b/components/Chromecast.tsx
index 6eb1d2a9..314bc4ee 100644
--- a/components/Chromecast.tsx
+++ b/components/Chromecast.tsx
@@ -1,5 +1,4 @@
import { Feather } from "@expo/vector-icons";
-import { BlurView } from "expo-blur";
import React, { useCallback, useEffect } from "react";
import { Platform, TouchableOpacity, ViewProps } from "react-native";
import GoogleCast, {
@@ -18,12 +17,12 @@ interface Props extends ViewProps {
background?: "blur" | "transparent";
}
-export const Chromecast: React.FC = ({
+export default function Chromecast({
width = 48,
height = 48,
background = "transparent",
...props
-}) => {
+}) {
const client = useRemoteMediaClient();
const castDevice = useCastDevice();
const devices = useDevices();
@@ -83,4 +82,4 @@ export const Chromecast: React.FC = ({
);
-};
+}
diff --git a/components/ContinueWatchingPoster.tsx b/components/ContinueWatchingPoster.tsx
index eb000d45..a011d23e 100644
--- a/components/ContinueWatchingPoster.tsx
+++ b/components/ContinueWatchingPoster.tsx
@@ -49,6 +49,11 @@ const ContinueWatchingPoster: React.FC = ({
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`;
}, [item]);
const progress = useMemo(() => {
diff --git a/components/DownloadItem.tsx b/components/DownloadItem.tsx
index 4618bb4f..dcb14128 100644
--- a/components/DownloadItem.tsx
+++ b/components/DownloadItem.tsx
@@ -2,7 +2,7 @@ import { useRemuxHlsToMp4 } from "@/hooks/useRemuxHlsToMp4";
import { useDownload } from "@/providers/DownloadProvider";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import { queueActions, queueAtom } from "@/utils/atoms/queue";
-import { useSettings } from "@/utils/atoms/settings";
+import {DownloadMethod, useSettings} from "@/utils/atoms/settings";
import { getDefaultPlaySettings } from "@/utils/jellyfin/getDefaultPlaySettings";
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
import { saveDownloadItemInfoToDiskTmp } from "@/utils/optimize-server";
@@ -32,6 +32,7 @@ import { MediaSourceSelector } from "./MediaSourceSelector";
import ProgressCircle from "./ProgressCircle";
import { RoundButton } from "./RoundButton";
import { SubtitleTrackSelector } from "./SubtitleTrackSelector";
+import { t } from "i18next";
interface DownloadProps extends ViewProps {
items: BaseItemDto[];
@@ -55,6 +56,7 @@ export const DownloadItems: React.FC = ({
const [user] = useAtom(userAtom);
const [queue, setQueue] = useAtom(queueAtom);
const [settings] = useSettings();
+
const { processes, startBackgroundDownload, downloadedFiles } = useDownload();
const { startRemuxing } = useRemuxHlsToMp4();
@@ -74,7 +76,7 @@ export const DownloadItems: React.FC = ({
[user]
);
const usingOptimizedServer = useMemo(
- () => settings?.downloadMethod === "optimized",
+ () => settings?.downloadMethod === DownloadMethod.Optimized,
[settings]
);
@@ -160,7 +162,7 @@ export const DownloadItems: React.FC = ({
);
}
} else {
- toast.error("You are not allowed to download files.");
+ toast.error(t("home.downloads.toasts.you_are_not_allowed_to_download_files"));
}
}, [
queue,
@@ -212,8 +214,8 @@ export const DownloadItems: React.FC = ({
if (!res) {
Alert.alert(
- "Something went wrong",
- "Could not get stream url from Jellyfin"
+ t("home.downloads.something_went_wrong"),
+ t("home.downloads.could_not_get_stream_url_from_jellyfin")
);
continue;
}
@@ -330,7 +332,7 @@ export const DownloadItems: React.FC = ({
{title}
- {subtitle || `Download ${itemsNotDownloaded.length} items`}
+ {subtitle || t("item_card.download.download_x_item", {item_count: itemsNotDownloaded.length})}
@@ -368,13 +370,13 @@ export const DownloadItems: React.FC = ({
onPress={acceptDownloadOptions}
color="purple"
>
- Download
+ {t("item_card.download.download_button")}
{usingOptimizedServer
- ? "Using optimized server"
- : "Using default method"}
+ ? t("item_card.download.using_optimized_server")
+ : t("item_card.download.using_default_method")}
@@ -391,7 +393,9 @@ export const DownloadSingleItem: React.FC<{
return (
(
diff --git a/components/ItemContent.tsx b/components/ItemContent.tsx
index c59ccdfb..ef0907ac 100644
--- a/components/ItemContent.tsx
+++ b/components/ItemContent.tsx
@@ -26,10 +26,11 @@ import { Image } from "expo-image";
import { useNavigation } from "expo-router";
import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { useAtom } from "jotai";
-import React, { useEffect, useMemo, useState } from "react";
+import React, { lazy, useEffect, useMemo, useState } from "react";
import { Platform, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
-const Chromecast = !Platform.isTV ? require("./Chromecast") : null;
+// const Chromecast = !Platform.isTV ? require("./Chromecast") : null;
+const Chromecast = lazy(() => import("./Chromecast"));
import { ItemHeader } from "./ItemHeader";
import { ItemTechnicalDetails } from "./ItemTechnicalDetails";
import { MediaSourceSelector } from "./MediaSourceSelector";
@@ -91,7 +92,7 @@ export const ItemContent: React.FC<{ item: BaseItemDto }> = React.memo(
{item.Type !== "Program" && (
-
+
)}
diff --git a/components/ItemTechnicalDetails.tsx b/components/ItemTechnicalDetails.tsx
index 0c472192..6b5852a4 100644
--- a/components/ItemTechnicalDetails.tsx
+++ b/components/ItemTechnicalDetails.tsx
@@ -15,6 +15,7 @@ import {
BottomSheetScrollView,
} from "@gorhom/bottom-sheet";
import { Button } from "./Button";
+import { useTranslation } from "react-i18next";
interface Props {
source?: MediaSourceInfo;
@@ -22,15 +23,16 @@ interface Props {
export const ItemTechnicalDetails: React.FC = ({ source, ...props }) => {
const bottomSheetModalRef = useRef(null);
+ const { t } = useTranslation();
return (
- Video
+ {t("item_card.video")}
bottomSheetModalRef.current?.present()}>
- More details
+ {t("item_card.more_details")}
= ({ source, ...props }) => {
- Video
+ {t("item_card.video")}
- Audio
+ {t("item_card.audio")}
= ({ source, ...props }) => {
- Subtitles
+ {t("item_card.subtitles")}
void;
+}
+
+const JellyfinServerDiscovery: React.FC = ({ onServerSelect }) => {
+ const { servers, isSearching, startDiscovery } = useJellyfinDiscovery();
+ const { t } = useTranslation();
+
+ return (
+
+
+
+ {servers.length ? (
+
+ {servers.map((server) => (
+
+ onServerSelect?.({
+ address: server.address,
+ serverName: server.serverName,
+ })
+ }
+ title={server.address}
+ showArrow
+ />
+ ))}
+
+ ) : null}
+
+ );
+};
+
+export default JellyfinServerDiscovery;
diff --git a/components/MediaSourceSelector.tsx b/components/MediaSourceSelector.tsx
index 4b55a352..27e123cc 100644
--- a/components/MediaSourceSelector.tsx
+++ b/components/MediaSourceSelector.tsx
@@ -1,13 +1,12 @@
-import { tc } from "@/utils/textTools";
import {
BaseItemDto,
MediaSourceInfo,
} from "@jellyfin/sdk/lib/generated-client/models";
-import { useEffect, useMemo } from "react";
+import { useMemo } from "react";
import { TouchableOpacity, View } from "react-native";
import * as DropdownMenu from "@/components/DropdownMenu";
import { Text } from "./common/Text";
-import { convertBitsToMegabitsOrGigabits } from "@/utils/bToMb";
+import { useTranslation } from "react-i18next";
interface Props extends React.ComponentProps {
item: BaseItemDto;
@@ -29,6 +28,29 @@ export const MediaSourceSelector: React.FC = ({
[item, selected]
);
+ const { t } = useTranslation();
+
+ const commonPrefix = useMemo(() => {
+ const mediaSources = item.MediaSources || [];
+ if (!mediaSources.length) return "";
+
+ let commonPrefix = "";
+ for (let i = 0; i < mediaSources[0].Name!.length; i++) {
+ const char = mediaSources[0].Name![i];
+ if (mediaSources.every((source) => source.Name![i] === char)) {
+ commonPrefix += char;
+ } else {
+ commonPrefix = commonPrefix.slice(0, -1);
+ break;
+ }
+ }
+ return commonPrefix;
+ }, [item.MediaSources]);
+
+ const name = (name?: string | null) => {
+ return name?.replace(commonPrefix, "").toLowerCase();
+ };
+
return (
= ({
- Video
+ {t("item_card.video")}
{selectedName}
@@ -63,9 +85,7 @@ export const MediaSourceSelector: React.FC = ({
}}
>
- {`${name(source.Name)} - ${convertBitsToMegabitsOrGigabits(
- source.Size
- )}`}
+ {`${name(source.Name)}`}
))}
@@ -74,9 +94,3 @@ export const MediaSourceSelector: React.FC = ({
);
};
-
-const name = (name?: string | null) => {
- if (name && name.length > 40)
- return name.substring(0, 20) + " [...] " + name.substring(name.length - 20);
- return name;
-};
diff --git a/components/MoreMoviesWithActor.tsx b/components/MoreMoviesWithActor.tsx
index 9a2a044f..9d4bc500 100644
--- a/components/MoreMoviesWithActor.tsx
+++ b/components/MoreMoviesWithActor.tsx
@@ -11,6 +11,7 @@ import { getItemsApi } from "@jellyfin/sdk/lib/utils/api";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { useQuery } from "@tanstack/react-query";
import { getUserItemData } from "@/utils/jellyfin/user-library/getUserItemData";
+import { useTranslation } from "react-i18next";
interface Props extends ViewProps {
actorId: string;
@@ -24,6 +25,7 @@ export const MoreMoviesWithActor: React.FC = ({
}) => {
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
+ const { t } = useTranslation();
const { data: actor } = useQuery({
queryKey: ["actor", actorId],
@@ -76,7 +78,7 @@ export const MoreMoviesWithActor: React.FC = ({
return (
- More with {actor?.Name}
+ {t("item_card.more_with", {name: actor?.Name})}
= ({
...props
}) => {
const [limit, setLimit] = useState(characterLimit);
+ const { t } = useTranslation();
if (!text) return null;
return (
- Overview
+ {t("item_card.overview")}
setLimit((prev) =>
@@ -31,7 +33,7 @@ export const OverviewText: React.FC = ({
{tc(text, limit)}
{text.length > characterLimit && (
- {limit === characterLimit ? "Show more" : "Show less"}
+ {limit === characterLimit ? t("item_card.show_more") : t("item_card.show_less")}
)}
diff --git a/components/ParallaxPage.tsx b/components/ParallaxPage.tsx
index daebca6b..5d7b28e0 100644
--- a/components/ParallaxPage.tsx
+++ b/components/ParallaxPage.tsx
@@ -1,6 +1,6 @@
import { LinearGradient } from "expo-linear-gradient";
import { type PropsWithChildren, type ReactElement } from "react";
-import { View, ViewProps } from "react-native";
+import {NativeScrollEvent, NativeSyntheticEvent, View, ViewProps} from "react-native";
import Animated, {
interpolate,
useAnimatedRef,
@@ -13,6 +13,7 @@ interface Props extends ViewProps {
logo?: ReactElement;
episodePoster?: ReactElement;
headerHeight?: number;
+ onEndReached?: (() => void) | null | undefined;
}
export const ParallaxScrollView: React.FC> = ({
@@ -21,6 +22,7 @@ export const ParallaxScrollView: React.FC> = ({
episodePoster,
headerHeight = 400,
logo,
+ onEndReached,
...props
}: Props) => {
const scrollRef = useAnimatedRef();
@@ -47,6 +49,11 @@ export const ParallaxScrollView: React.FC> = ({
};
});
+
+ function isCloseToBottom({layoutMeasurement, contentOffset, contentSize}: NativeScrollEvent) {
+ return layoutMeasurement.height + contentOffset.y >= contentSize.height - 20;
+ }
+
return (
> = ({
}}
ref={scrollRef}
scrollEventThrottle={16}
+ onScroll={e => {
+ if (isCloseToBottom(e.nativeEvent))
+ onEndReached?.()
+ }}
>
{logo && (
{
item: BaseItemDto;
@@ -53,6 +54,7 @@ export const PlayButton: React.FC = ({
const { showActionSheetWithOptions } = useActionSheet();
const client = useRemoteMediaClient();
const mediaStatus = useMediaStatus();
+ const { t } = useTranslation();
const [colorAtom] = useAtom(itemThemeColorAtom);
const api = useAtomValue(apiAtom);
@@ -67,6 +69,7 @@ export const PlayButton: React.FC = ({
const widthProgress = useSharedValue(0);
const colorChangeProgress = useSharedValue(0);
const [settings] = useSettings();
+ const lightHapticFeedback = useHaptic("light");
const goToPlayer = useCallback(
(q: string, bitrateValue: number | undefined) => {
@@ -82,7 +85,7 @@ export const PlayButton: React.FC = ({
const onPress = useCallback(async () => {
if (!item) return;
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
const queryParams = new URLSearchParams({
itemId: item.Id!,
@@ -134,8 +137,8 @@ export const PlayButton: React.FC = ({
if (!data?.url) {
console.warn("No URL returned from getStreamUrl", data);
Alert.alert(
- "Client error",
- "Could not create stream for Chromecast"
+ t("player.client_error"),
+ t("player.could_not_create_stream_for_chromecast")
);
return;
}
diff --git a/components/PlayedStatus.tsx b/components/PlayedStatus.tsx
index 15890a9f..5d738af4 100644
--- a/components/PlayedStatus.tsx
+++ b/components/PlayedStatus.tsx
@@ -6,16 +6,19 @@ import { View, ViewProps } from "react-native";
import { RoundButton } from "./RoundButton";
interface Props extends ViewProps {
- item: BaseItemDto;
+ items: BaseItemDto[];
+ size?: "default" | "large";
}
-export const PlayedStatus: React.FC = ({ item, ...props }) => {
+export const PlayedStatus: React.FC = ({ items, ...props }) => {
const queryClient = useQueryClient();
const invalidateQueries = () => {
- queryClient.invalidateQueries({
- queryKey: ["item", item.Id],
- });
+ items.forEach((item) => {
+ queryClient.invalidateQueries({
+ queryKey: ["item", item.Id],
+ });
+ })
queryClient.invalidateQueries({
queryKey: ["resumeItems"],
});
@@ -39,15 +42,20 @@ export const PlayedStatus: React.FC = ({ item, ...props }) => {
});
};
- const markAsPlayedStatus = useMarkAsPlayed(item);
+ const allPlayed = items.every((item) => item.UserData?.Played);
+
+ const markAsPlayedStatus = useMarkAsPlayed(items);
return (
markAsPlayedStatus(item.UserData?.Played || false)}
- size="large"
+ fillColor={allPlayed ? "primary" : undefined}
+ icon={allPlayed ? "checkmark" : "checkmark"}
+ onPress={async () => {
+ console.log(allPlayed);
+ await markAsPlayedStatus(!allPlayed)
+ }}
+ size={props.size}
/>
);
diff --git a/components/PreviousServersList.tsx b/components/PreviousServersList.tsx
index 3771961e..437c756d 100644
--- a/components/PreviousServersList.tsx
+++ b/components/PreviousServersList.tsx
@@ -3,6 +3,7 @@ import { View } from "react-native";
import { useMMKVString } from "react-native-mmkv";
import { ListGroup } from "./list/ListGroup";
import { ListItem } from "./list/ListItem";
+import { useTranslation } from "react-i18next";
interface Server {
address: string;
@@ -22,11 +23,13 @@ export const PreviousServersList: React.FC = ({
return JSON.parse(_previousServers || "[]") as Server[];
}, [_previousServers]);
+ const { t } = useTranslation();
+
if (!previousServers.length) return null;
return (
-
+
{previousServers.map((s) => (
= ({
onPress={() => {
setPreviousServers("[]");
}}
- title={"Clear"}
+ title={t("server.clear_button")}
textColor="red"
/>
diff --git a/components/RoundButton.tsx b/components/RoundButton.tsx
index e16613a1..5d2faf73 100644
--- a/components/RoundButton.tsx
+++ b/components/RoundButton.tsx
@@ -6,7 +6,7 @@ import {
TouchableOpacity,
TouchableOpacityProps,
} from "react-native";
-import * as Haptics from "@/packages/expo-haptics";
+import { useHaptic } from "@/hooks/useHaptic";
interface Props extends TouchableOpacityProps {
onPress?: () => void;
@@ -29,10 +29,11 @@ export const RoundButton: React.FC> = ({
}) => {
const buttonSize = size === "large" ? "h-10 w-10" : "h-9 w-9";
const fillColorClass = fillColor === "primary" ? "bg-purple-600" : "";
+ const lightHapticFeedback = useHaptic("light");
const handlePress = () => {
if (hapticFeedback) {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
}
onPress?.();
};
diff --git a/components/SimilarItems.tsx b/components/SimilarItems.tsx
index 46815b6d..45914d9f 100644
--- a/components/SimilarItems.tsx
+++ b/components/SimilarItems.tsx
@@ -12,6 +12,7 @@ import { ItemCardText } from "./ItemCardText";
import { Loader } from "./Loader";
import { HorizontalScroll } from "./common/HorrizontalScroll";
import { TouchableItemRouter } from "./common/TouchableItemRouter";
+import { useTranslation } from "react-i18next";
interface SimilarItemsProps extends ViewProps {
itemId?: string | null;
@@ -23,6 +24,7 @@ export const SimilarItems: React.FC = ({
}) => {
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
+ const { t } = useTranslation();
const { data: similarItems, isLoading } = useQuery({
queryKey: ["similarItems", itemId],
@@ -47,12 +49,12 @@ export const SimilarItems: React.FC = ({
return (
- Similar items
+ {t("item_card.similar_items")}
(
{
source?: MediaSourceInfo;
@@ -37,6 +38,8 @@ export const SubtitleTrackSelector: React.FC = ({
if (subtitleStreams.length === 0) return null;
+ const { t } = useTranslation();
+
return (
= ({
- Subtitle
+ {t("item_card.subtitles")}
{selectedSubtitleSteam
? tc(selectedSubtitleSteam?.DisplayTitle, 7)
- : "None"}
+ : t("item_card.none")}
diff --git a/components/common/Dropdown.tsx b/components/common/Dropdown.tsx
new file mode 100644
index 00000000..fec36d2f
--- /dev/null
+++ b/components/common/Dropdown.tsx
@@ -0,0 +1,108 @@
+import * as DropdownMenu from "zeego/dropdown-menu";
+import {TouchableOpacity, View, ViewProps} from "react-native";
+import {Text} from "@/components/common/Text";
+import React, {PropsWithChildren, ReactNode, useEffect, useState} from "react";
+import DisabledSetting from "@/components/settings/DisabledSetting";
+
+interface Props {
+ data: T[]
+ disabled?: boolean
+ placeholderText?: string,
+ keyExtractor: (item: T) => string
+ titleExtractor: (item: T) => string | undefined
+ title: string | ReactNode,
+ label: string,
+ onSelected: (...item: T[]) => void
+ multi?: boolean
+}
+
+const Dropdown = ({
+ data,
+ disabled,
+ placeholderText,
+ keyExtractor,
+ titleExtractor,
+ title,
+ label,
+ onSelected,
+ multi = false,
+ ...props
+}: PropsWithChildren & ViewProps>) => {
+ const [selected, setSelected] = useState();
+
+ useEffect(() => {
+ if (selected !== undefined) {
+ onSelected(...selected)
+ }
+ }, [selected]);
+
+ return (
+
+
+
+ {typeof title === 'string' ? (
+
+
+ {title}
+
+
+
+ {selected?.length !== undefined ? selected.map(titleExtractor).join(",") : placeholderText}
+
+
+
+ ) : (
+ <>
+ {title}
+ >
+ )}
+
+
+ {label}
+ {data.map((item, idx) => (
+ multi ? (
+ keyExtractor(s) == keyExtractor(item)) ? 'on' : 'off'}
+ key={keyExtractor(item)}
+ onValueChange={(next, previous) =>
+ setSelected((p) => {
+ const prev = p || []
+ if (next == 'on') {
+ return [...prev, item]
+ }
+ return [...prev.filter(p => keyExtractor(p) !== keyExtractor(item))]
+ })
+ }
+ >
+ {titleExtractor(item)}
+
+ )
+ : (
+ setSelected([item])}
+ >
+ {titleExtractor(item)}
+
+ )
+ ))}
+
+
+
+ )
+};
+
+export default Dropdown;
\ No newline at end of file
diff --git a/components/common/InfiniteHorrizontalScroll.tsx b/components/common/InfiniteHorrizontalScroll.tsx
index e8281d0e..f3c504f1 100644
--- a/components/common/InfiniteHorrizontalScroll.tsx
+++ b/components/common/InfiniteHorrizontalScroll.tsx
@@ -15,6 +15,7 @@ import Animated, {
} from "react-native-reanimated";
import { Loader } from "../Loader";
import { Text } from "./Text";
+import { t } from "i18next";
interface HorizontalScrollProps
extends Omit, "renderItem" | "data" | "style"> {
@@ -136,7 +137,7 @@ export function InfiniteHorizontalScroll({
showsHorizontalScrollIndicator={false}
ListEmptyComponent={
- No data available
+ {t("item_card.no_data_available")}
}
{...props}
diff --git a/components/common/Input.tsx b/components/common/Input.tsx
index ba4ab45b..d82a3225 100644
--- a/components/common/Input.tsx
+++ b/components/common/Input.tsx
@@ -7,7 +7,7 @@ export function Input(props: TextInputProps) {
return (
{
- console.log(item.Type, item?.CollectionType);
-
if ("CollectionType" in item && item.CollectionType === "livetv") {
return `/(auth)/(tabs)/${from}/livetv`;
}
@@ -57,10 +55,33 @@ export const TouchableItemRouter: React.FC> = ({
}) => {
const router = useRouter();
const segments = useSegments();
+ const { showActionSheetWithOptions } = useActionSheet();
+ const markAsPlayedStatus = useMarkAsPlayed([item]);
const from = segments[2];
- const markAsPlayedStatus = useMarkAsPlayed(item);
+ const showActionSheet = useCallback(() => {
+ if (!(item.Type === "Movie" || item.Type === "Episode")) return;
+
+ const options = ["Mark as Played", "Mark as Not Played", "Cancel"];
+ const cancelButtonIndex = 2;
+
+ showActionSheetWithOptions(
+ {
+ options,
+ cancelButtonIndex,
+ },
+ async (selectedIndex) => {
+ if (selectedIndex === 0) {
+ await markAsPlayedStatus(true);
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
+ } else if (selectedIndex === 1) {
+ await markAsPlayedStatus(false);
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
+ }
+ }
+ );
+ }, [showActionSheetWithOptions, markAsPlayedStatus]);
if (
from === "(home)" ||
@@ -68,94 +89,17 @@ export const TouchableItemRouter: React.FC> = ({
from === "(libraries)" ||
from === "(favorites)"
)
- if (Platform.isTV) {
- return (
- {
- const url = itemRouter(item, from);
- // @ts-ignore
- router.push(url);
- }}
- {...props}
- >
- {children}
-
- );
- } else {
- return (
-
-
- {
- const url = itemRouter(item, from);
- // @ts-ignore
- router.push(url);
- }}
- {...props}
- >
- {children}
-
-
-
- Actions
- {
- markAsPlayedStatus(true);
- }}
- shouldDismissMenuOnSelect
- >
-
- Mark as watched
-
-
-
- {
- markAsPlayedStatus(false);
- }}
- shouldDismissMenuOnSelect
- destructive
- >
-
- Mark as not watched
-
-
-
-
-
- );
- }
+ return (
+ {
+ const url = itemRouter(item, from);
+ // @ts-expect-error
+ router.push(url);
+ }}
+ {...props}
+ >
+ {children}
+
+ );
};
diff --git a/components/downloads/ActiveDownloads.tsx b/components/downloads/ActiveDownloads.tsx
index 14b7de15..960cc3f2 100644
--- a/components/downloads/ActiveDownloads.tsx
+++ b/components/downloads/ActiveDownloads.tsx
@@ -1,17 +1,14 @@
import { Text } from "@/components/common/Text";
import { useDownload } from "@/providers/DownloadProvider";
-import { apiAtom } from "@/providers/JellyfinProvider";
-import { useSettings } from "@/utils/atoms/settings";
+import {DownloadMethod, useSettings} from "@/utils/atoms/settings";
import { JobStatus } from "@/utils/optimize-server";
import { formatTimeString } from "@/utils/time";
import { Ionicons } from "@expo/vector-icons";
-// import { checkForExistingDownloads } from "@kesha-antonov/react-native-background-downloader";
const BackGroundDownloader = !Platform.isTV
? require("@kesha-antonov/react-native-background-downloader")
: null;
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useRouter } from "expo-router";
-// import { FFmpegKit } from "ffmpeg-kit-react-native";
const FFmpegKit = !Platform.isTV ? require("ffmpeg-kit-react-native") : null;
import { useAtom } from "jotai";
import {
@@ -27,6 +24,7 @@ import { Button } from "../Button";
import { Image } from "expo-image";
import { useMemo } from "react";
import { storage } from "@/utils/mmkv";
+import { t } from "i18next";
interface Props extends ViewProps {}
@@ -35,14 +33,14 @@ export const ActiveDownloads: React.FC = ({ ...props }) => {
if (processes?.length === 0)
return (
- Active download
- No active downloads
+ {t("home.downloads.active_download")}
+ {t("home.downloads.no_active_downloads")}
);
return (
- Active downloads
+ {t("home.downloads.active_downloads")}
{processes?.map((p) => (
@@ -67,7 +65,7 @@ const DownloadCard = ({ process, ...props }: DownloadCardProps) => {
mutationFn: async (id: string) => {
if (!process) throw new Error("No active download");
- if (settings?.downloadMethod === "optimized") {
+ if (settings?.downloadMethod === DownloadMethod.Optimized) {
try {
const tasks = await BackGroundDownloader.checkForExistingDownloads();
for (const task of tasks) {
@@ -87,11 +85,11 @@ const DownloadCard = ({ process, ...props }: DownloadCardProps) => {
}
},
onSuccess: () => {
- toast.success("Download canceled");
+ toast.success(t("home.downloads.toasts.download_cancelled"));
},
onError: (e) => {
console.error(e);
- toast.error("Could not cancel download");
+ toast.error(t("home.downloads.toasts.could_not_cancel_download"));
},
});
@@ -158,7 +156,7 @@ const DownloadCard = ({ process, ...props }: DownloadCardProps) => {
{process.speed?.toFixed(2)}x
)}
{eta(process) && (
- ETA {eta(process)}
+ {t("home.downloads.eta", {eta: eta(process)})}
)}
diff --git a/components/downloads/EpisodeCard.tsx b/components/downloads/EpisodeCard.tsx
index 14b0eefa..53b3ecec 100644
--- a/components/downloads/EpisodeCard.tsx
+++ b/components/downloads/EpisodeCard.tsx
@@ -1,5 +1,5 @@
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
-import * as Haptics from "@/packages/expo-haptics";
+import { useHaptic } from "@/hooks/useHaptic";
import React, { useCallback, useMemo } from "react";
import { TouchableOpacity, TouchableOpacityProps, View } from "react-native";
import {
@@ -26,6 +26,7 @@ export const EpisodeCard: React.FC = ({ item, ...props }) => {
const { deleteFile } = useDownload();
const { openFile } = useDownloadedFileOpener();
const { showActionSheetWithOptions } = useActionSheet();
+ const successHapticFeedback = useHaptic("success");
const base64Image = useMemo(() => {
return storage.getString(item.Id!);
@@ -41,7 +42,7 @@ export const EpisodeCard: React.FC = ({ item, ...props }) => {
const handleDeleteFile = useCallback(() => {
if (item.Id) {
deleteFile(item.Id);
- Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
+ successHapticFeedback();
}
}, [deleteFile, item.Id]);
diff --git a/components/downloads/MovieCard.tsx b/components/downloads/MovieCard.tsx
index 28af9cb1..bb61f3c8 100644
--- a/components/downloads/MovieCard.tsx
+++ b/components/downloads/MovieCard.tsx
@@ -3,7 +3,7 @@ import {
useActionSheet,
} from "@expo/react-native-action-sheet";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
-import * as Haptics from "@/packages/expo-haptics";
+import { useHaptic } from "@/hooks/useHaptic";
import React, { useCallback, useMemo } from "react";
import { TouchableOpacity, View } from "react-native";
@@ -28,6 +28,7 @@ export const MovieCard: React.FC = ({ item }) => {
const { deleteFile } = useDownload();
const { openFile } = useDownloadedFileOpener();
const { showActionSheetWithOptions } = useActionSheet();
+ const successHapticFeedback = useHaptic("success");
const handleOpenFile = useCallback(() => {
openFile(item);
@@ -43,7 +44,7 @@ export const MovieCard: React.FC = ({ item }) => {
const handleDeleteFile = useCallback(() => {
if (item.Id) {
deleteFile(item.Id);
- Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
+ successHapticFeedback();
}
}, [deleteFile, item.Id]);
diff --git a/components/filters/FilterButton.tsx b/components/filters/FilterButton.tsx
index 6d976b26..de8caa2e 100644
--- a/components/filters/FilterButton.tsx
+++ b/components/filters/FilterButton.tsx
@@ -1,7 +1,7 @@
import { Text } from "@/components/common/Text";
import { FontAwesome, Ionicons } from "@expo/vector-icons";
import { useQuery } from "@tanstack/react-query";
-import { useEffect, useState } from "react";
+import { useState } from "react";
import { TouchableOpacity, View, ViewProps } from "react-native";
import { FilterSheet } from "./FilterSheet";
diff --git a/components/filters/FilterSheet.tsx b/components/filters/FilterSheet.tsx
index fe6d9f6a..cc5d4300 100644
--- a/components/filters/FilterSheet.tsx
+++ b/components/filters/FilterSheet.tsx
@@ -19,6 +19,7 @@ import { StyleSheet, TouchableOpacity, View, ViewProps } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { Button } from "../Button";
import { Input } from "../common/Input";
+import { useTranslation } from "react-i18next";
interface Props extends ViewProps {
open: boolean;
@@ -76,6 +77,7 @@ export const FilterSheet = ({
}: Props) => {
const bottomSheetModalRef = useRef(null);
const snapPoints = useMemo(() => ["80%"], []);
+ const { t } = useTranslation();
const [data, setData] = useState([]);
const [offset, setOffset] = useState(0);
@@ -153,10 +155,10 @@ export const FilterSheet = ({
>
{title}
- {_data?.length} items
+ {t("search.items", {count: _data?.length})}
{showSearch && (
{
diff --git a/components/home/Favorites.tsx b/components/home/Favorites.tsx
index 6cf05109..c4ab373e 100644
--- a/components/home/Favorites.tsx
+++ b/components/home/Favorites.tsx
@@ -5,6 +5,7 @@ import { View } from "react-native";
import { ScrollingCollectionList } from "./ScrollingCollectionList";
import { useCallback } from "react";
import { BaseItemKind } from "@jellyfin/sdk/lib/generated-client";
+import { t } from "i18next";
export const Favorites = () => {
const [api] = useAtom(apiAtom);
@@ -54,64 +55,44 @@ export const Favorites = () => {
() => fetchFavoritesByType("Playlist"),
[fetchFavoritesByType]
);
- const fetchFavoriteMusicAlbum = useCallback(
- () => fetchFavoritesByType("MusicAlbum"),
- [fetchFavoritesByType]
- );
- const fetchFavoriteAudio = useCallback(
- () => fetchFavoritesByType("Audio"),
- [fetchFavoritesByType]
- );
return (
-
-
diff --git a/components/home/LargeMovieCarousel.tsx b/components/home/LargeMovieCarousel.tsx
index 7d310c9b..5b228901 100644
--- a/components/home/LargeMovieCarousel.tsx
+++ b/components/home/LargeMovieCarousel.tsx
@@ -1,3 +1,4 @@
+import { useHaptic } from "@/hooks/useHaptic";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings";
import { getBackdropUrl } from "@/utils/jellyfin/image/getBackdropUrl";
@@ -6,9 +7,11 @@ import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { getItemsApi } from "@jellyfin/sdk/lib/utils/api";
import { useQuery } from "@tanstack/react-query";
import { Image } from "expo-image";
+import { useRouter, useSegments } from "expo-router";
import { useAtom } from "jotai";
import React, { useCallback, useMemo } from "react";
-import { Dimensions, TouchableOpacity, View, ViewProps } from "react-native";
+import { Dimensions, View, ViewProps } from "react-native";
+import { Gesture, GestureDetector } from "react-native-gesture-handler";
import Animated, {
runOnJS,
useSharedValue,
@@ -18,11 +21,7 @@ import Carousel, {
ICarouselInstance,
Pagination,
} from "react-native-reanimated-carousel";
-import { itemRouter, TouchableItemRouter } from "../common/TouchableItemRouter";
-import { Loader } from "../Loader";
-import { Gesture, GestureDetector } from "react-native-gesture-handler";
-import { useRouter, useSegments } from "expo-router";
-import * as Haptics from "@/packages/expo-haptics";
+import { itemRouter } from "../common/TouchableItemRouter";
interface Props extends ViewProps {}
@@ -128,6 +127,7 @@ const RenderItem: React.FC<{ item: BaseItemDto }> = ({ item }) => {
const [api] = useAtom(apiAtom);
const router = useRouter();
const screenWidth = Dimensions.get("screen").width;
+ const lightHapticFeedback = useHaptic("light");
const uri = useMemo(() => {
if (!api) return null;
@@ -153,7 +153,7 @@ const RenderItem: React.FC<{ item: BaseItemDto }> = ({ item }) => {
const handleRoute = useCallback(() => {
if (!from) return;
const url = itemRouter(item, from);
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
// @ts-ignore
if (url) router.push(url);
}, [item, from]);
@@ -161,7 +161,7 @@ const RenderItem: React.FC<{ item: BaseItemDto }> = ({ item }) => {
const tap = Gesture.Tap()
.maxDuration(2000)
.onBegin(() => {
- opacity.value = withTiming(0.5, { duration: 100 });
+ opacity.value = withTiming(0.8, { duration: 100 });
})
.onEnd(() => {
runOnJS(handleRoute)();
diff --git a/components/home/ScrollingCollectionList.tsx b/components/home/ScrollingCollectionList.tsx
index 17b4ec77..06f5a057 100644
--- a/components/home/ScrollingCollectionList.tsx
+++ b/components/home/ScrollingCollectionList.tsx
@@ -11,6 +11,7 @@ import ContinueWatchingPoster from "../ContinueWatchingPoster";
import { ItemCardText } from "../ItemCardText";
import { TouchableItemRouter } from "../common/TouchableItemRouter";
import SeriesPoster from "../posters/SeriesPoster";
+import { useTranslation } from "react-i18next";
interface Props extends ViewProps {
title?: string | null;
@@ -39,9 +40,10 @@ export const ScrollingCollectionList: React.FC = ({
refetchOnReconnect: true,
});
- if (disabled || !title) return null;
+ const { t } = useTranslation();
if (hideIfEmpty === true && data?.length === 0) return null;
+ if (disabled || !title) return null;
return (
@@ -50,7 +52,7 @@ export const ScrollingCollectionList: React.FC = ({
{isLoading === false && data?.length === 0 && (
- No items
+ {t("home.no_items")}
)}
{isLoading ? (
@@ -104,7 +106,12 @@ export const ScrollingCollectionList: React.FC = ({
{item.Type === "Movie" && orientation === "vertical" && (
)}
- {item.Type === "Series" && }
+ {item.Type === "Series" && orientation === "vertical" && (
+
+ )}
+ {item.Type === "Series" && orientation === "horizontal" && (
+
+ )}
{item.Type === "Program" && (
)}
diff --git a/components/inputs/Stepper.tsx b/components/inputs/Stepper.tsx
index eb5032cf..86a4ffa9 100644
--- a/components/inputs/Stepper.tsx
+++ b/components/inputs/Stepper.tsx
@@ -1,8 +1,10 @@
import {TouchableOpacity, View} from "react-native";
import {Text} from "@/components/common/Text";
+import DisabledSetting from "@/components/settings/DisabledSetting";
interface StepperProps {
value: number,
+ disabled?: boolean,
step: number,
min: number,
max: number,
@@ -12,6 +14,7 @@ interface StepperProps {
export const Stepper: React.FC = ({
value,
+ disabled,
step,
min,
max,
@@ -19,7 +22,11 @@ export const Stepper: React.FC = ({
appendValue
}) => {
return (
-
+
onUpdate(Math.max(min, value - step))}
className="w-8 h-8 bg-neutral-800 rounded-l-lg flex items-center justify-center"
@@ -39,6 +46,6 @@ export const Stepper: React.FC = ({
>
+
-
+
)
}
\ No newline at end of file
diff --git a/components/jellyseerr/Cast.tsx b/components/jellyseerr/Cast.tsx
index f5474caf..8dcdd785 100644
--- a/components/jellyseerr/Cast.tsx
+++ b/components/jellyseerr/Cast.tsx
@@ -5,15 +5,17 @@ import React from "react";
import { FlashList } from "@shopify/flash-list";
import { Text } from "@/components/common/Text";
import PersonPoster from "@/components/jellyseerr/PersonPoster";
+import { useTranslation } from "react-i18next";
const CastSlide: React.FC<
{ details?: MovieDetails | TvDetails } & ViewProps
> = ({ details, ...props }) => {
+ const { t } = useTranslation();
return (
- details?.credits?.cast?.length &&
+ details?.credits?.cast &&
details?.credits?.cast?.length > 0 && (
- Cast
+ {t("jellyseerr.cast")}
= ({ title, facts, ...props }) =>
facts &&
facts?.length > 0 && (
-
- {title}
+
+ {title}
{facts.map((f, idx) =>
@@ -50,6 +51,7 @@ const DetailFacts: React.FC<
{ details?: MovieDetails | TvDetails } & ViewProps
> = ({ details, className, ...props }) => {
const { jellyseerrUser } = useJellyseerr();
+ const { t } = useTranslation();
const locale = useMemo(() => {
return jellyseerrUser?.settings?.locale || "en";
@@ -144,21 +146,21 @@ const DetailFacts: React.FC<
return (
details && (
- Details
+ {t("jellyseerr.details")}
-
+
{details.keywords.some(
(keyword) => keyword.id === ANIME_KEYWORD_ID
- ) && }
+ ) && }
(
{r.type === 3 ? (
@@ -184,13 +186,13 @@ const DetailFacts: React.FC<
))}
/>
-
-
-
-
-
+
+
+
+
+
(
@@ -199,14 +201,14 @@ const DetailFacts: React.FC<
))}
/>
n.name
)}
/>
- n.name)} />
+ n.name)} />
s.name)}
/>
diff --git a/components/jellyseerr/JellyseerrIndexPage.tsx b/components/jellyseerr/JellyseerrIndexPage.tsx
new file mode 100644
index 00000000..cd093deb
--- /dev/null
+++ b/components/jellyseerr/JellyseerrIndexPage.tsx
@@ -0,0 +1,161 @@
+import Discover from "@/components/jellyseerr/discover/Discover";
+import { useJellyseerr } from "@/hooks/useJellyseerr";
+import { MediaType } from "@/utils/jellyseerr/server/constants/media";
+import {
+ MovieResult,
+ PersonResult,
+ TvResult,
+} from "@/utils/jellyseerr/server/models/Search";
+import { useReactNavigationQuery } from "@/utils/useReactNavigationQuery";
+import React, { useMemo } from "react";
+import { View, ViewProps } from "react-native";
+import {
+ useAnimatedReaction,
+ useAnimatedStyle,
+ useSharedValue,
+ withTiming,
+} from "react-native-reanimated";
+import { Text } from "../common/Text";
+import JellyseerrPoster from "../posters/JellyseerrPoster";
+import { LoadingSkeleton } from "../search/LoadingSkeleton";
+import { SearchItemWrapper } from "../search/SearchItemWrapper";
+import PersonPoster from "./PersonPoster";
+import { useTranslation } from "react-i18next";
+
+interface Props extends ViewProps {
+ searchQuery: string;
+}
+
+export const JellyserrIndexPage: React.FC = ({ searchQuery }) => {
+ const { jellyseerrApi } = useJellyseerr();
+ const opacity = useSharedValue(1);
+ const { t } = useTranslation();
+
+ const {
+ data: jellyseerrDiscoverSettings,
+ isFetching: f1,
+ isLoading: l1,
+ } = useReactNavigationQuery({
+ queryKey: ["search", "jellyseerr", "discoverSettings", searchQuery],
+ queryFn: async () => jellyseerrApi?.discoverSettings(),
+ enabled: !!jellyseerrApi && searchQuery.length == 0,
+ });
+
+ const {
+ data: jellyseerrResults,
+ isFetching: f2,
+ isLoading: l2,
+ } = useReactNavigationQuery({
+ queryKey: ["search", "jellyseerr", "results", searchQuery],
+ queryFn: async () => {
+ const response = await jellyseerrApi?.search({
+ query: new URLSearchParams(searchQuery).toString(),
+ page: 1,
+ language: "en",
+ });
+ return response?.results;
+ },
+ enabled: !!jellyseerrApi && searchQuery.length > 0,
+ });
+
+ const animatedStyle = useAnimatedStyle(() => {
+ return {
+ opacity: opacity.value,
+ };
+ });
+
+ useAnimatedReaction(
+ () => f1 || f2 || l1 || l2,
+ (isLoading) => {
+ if (isLoading) {
+ opacity.value = withTiming(1, { duration: 200 });
+ } else {
+ opacity.value = withTiming(0, { duration: 200 });
+ }
+ }
+ );
+
+ const jellyseerrMovieResults = useMemo(
+ () =>
+ jellyseerrResults?.filter(
+ (r) => r.mediaType === MediaType.MOVIE
+ ) as MovieResult[],
+ [jellyseerrResults]
+ );
+
+ const jellyseerrTvResults = useMemo(
+ () =>
+ jellyseerrResults?.filter(
+ (r) => r.mediaType === MediaType.TV
+ ) as TvResult[],
+ [jellyseerrResults]
+ );
+
+ const jellyseerrPersonResults = useMemo(
+ () =>
+ jellyseerrResults?.filter(
+ (r) => r.mediaType === "person"
+ ) as PersonResult[],
+ [jellyseerrResults]
+ );
+
+ if (!searchQuery.length)
+ return (
+
+
+
+ );
+
+ return (
+
+
+
+ {!jellyseerrMovieResults?.length &&
+ !jellyseerrTvResults?.length &&
+ !jellyseerrPersonResults?.length &&
+ !f1 &&
+ !f2 &&
+ !l1 &&
+ !l2 && (
+
+
+ {t("search.no_results_found_for")}
+
+
+ "{searchQuery}"
+
+
+ )}
+
+
+ (
+
+ )}
+ />
+ (
+
+ )}
+ />
+ (
+
+ )}
+ />
+
+
+ );
+};
diff --git a/components/jellyseerr/ParallaxSlideShow.tsx b/components/jellyseerr/ParallaxSlideShow.tsx
new file mode 100644
index 00000000..6a7fcb7f
--- /dev/null
+++ b/components/jellyseerr/ParallaxSlideShow.tsx
@@ -0,0 +1,160 @@
+import React, {
+ PropsWithChildren,
+ useCallback,
+ useEffect,
+ useRef,
+ useState,
+} from "react";
+import {Dimensions, View, ViewProps} from "react-native";
+import { useSafeAreaInsets } from "react-native-safe-area-context";
+import { ParallaxScrollView } from "@/components/ParallaxPage";
+import { Text } from "@/components/common/Text";
+import { Animated } from "react-native";
+import { FlashList } from "@shopify/flash-list";
+import {useFocusEffect} from "expo-router";
+
+const ANIMATION_ENTER = 250;
+const ANIMATION_EXIT = 250;
+const BACKDROP_DURATION = 5000;
+
+type Render = React.ComponentType
+ | React.ReactElement
+ | null
+ | undefined;
+
+interface Props {
+ data: T[]
+ images: string[];
+ logo?: React.ReactElement;
+ HeaderContent?: () => React.ReactElement;
+ MainContent?: () => React.ReactElement;
+ listHeader: string;
+ renderItem: (item: T, index: number) => Render;
+ keyExtractor: (item: T) => string;
+ onEndReached?: (() => void) | null | undefined;
+}
+
+const ParallaxSlideShow = ({
+ data,
+ images,
+ logo,
+ HeaderContent,
+ MainContent,
+ listHeader,
+ renderItem,
+ keyExtractor,
+ onEndReached,
+ ...props
+}: PropsWithChildren & ViewProps>
+) => {
+ const insets = useSafeAreaInsets();
+
+ const [currentIndex, setCurrentIndex] = useState(0);
+ const fadeAnim = useRef(new Animated.Value(0)).current;
+
+ const enterAnimation = useCallback(
+ () =>
+ Animated.timing(fadeAnim, {
+ toValue: 1,
+ duration: ANIMATION_ENTER,
+ useNativeDriver: true,
+ }),
+ [fadeAnim]
+ );
+
+ const exitAnimation = useCallback(
+ () =>
+ Animated.timing(fadeAnim, {
+ toValue: 0,
+ duration: ANIMATION_EXIT,
+ useNativeDriver: true,
+ }),
+ [fadeAnim]
+ );
+
+ useEffect(() => {
+ if (images?.length) {
+ enterAnimation().start();
+
+ const intervalId = setInterval(() => {
+ Animated.sequence([
+ enterAnimation(),
+ exitAnimation()
+ ]).start(() => {
+ fadeAnim.setValue(0);
+ setCurrentIndex((prevIndex) => (prevIndex + 1) % images?.length);
+ })
+ }, BACKDROP_DURATION);
+
+ return () => {
+ clearInterval(intervalId)
+ };
+ }
+ }, [fadeAnim, images, enterAnimation, exitAnimation, setCurrentIndex, currentIndex]);
+
+ return (
+
+
+ }
+ logo={logo}
+ >
+
+
+
+ {HeaderContent && HeaderContent()}
+
+
+ {MainContent && MainContent()}
+
+
+
+ No results
+
+
+ }
+ contentInsetAdjustmentBehavior="automatic"
+ ListHeaderComponent={
+ {listHeader}
+ }
+ nestedScrollEnabled
+ showsVerticalScrollIndicator={false}
+ //@ts-ignore
+ renderItem={({ item, index}) => renderItem(item, index)}
+ keyExtractor={keyExtractor}
+ numColumns={3}
+ estimatedItemSize={214}
+ ItemSeparatorComponent={() => }
+ />
+
+
+
+
+ );
+}
+
+export default ParallaxSlideShow;
\ No newline at end of file
diff --git a/components/jellyseerr/PersonPoster.tsx b/components/jellyseerr/PersonPoster.tsx
index 57ff9f58..6e7d9aa6 100644
--- a/components/jellyseerr/PersonPoster.tsx
+++ b/components/jellyseerr/PersonPoster.tsx
@@ -26,7 +26,7 @@ const PersonPoster: React.FC = ({
if (from === "(home)" || from === "(search)" || from === "(libraries)")
return (
- router.push(`/(auth)/(tabs)/${from}/jellyseerr/${id}`)}>
+ router.push(`/(auth)/(tabs)/${from}/jellyseerr/person/${id}`)}>
void;
+}
+
+const RequestModal = forwardRef>(({
+ id,
+ title,
+ type,
+ isAnime = false,
+ onRequested,
+ ...props
+}, ref) => {
+ const {jellyseerrApi, jellyseerrUser, requestMedia} = useJellyseerr();
+ const [requestOverrides, setRequestOverrides] =
+ useState({
+ mediaId: Number(id),
+ mediaType: type,
+ userId: jellyseerrUser?.id
+ });
+
+ const { t } = useTranslation();
+
+ const [modalRequestProps, setModalRequestProps] = useState();
+
+ const {data: serviceSettings} = useQuery({
+ queryKey: ["jellyseerr", "request", type, 'service'],
+ queryFn: async () => jellyseerrApi?.service(type == 'movie' ? 'radarr' : 'sonarr'),
+ enabled: !!jellyseerrApi && !!jellyseerrUser,
+ refetchOnMount: 'always'
+ });
+
+ const {data: users} = useQuery({
+ queryKey: ["jellyseerr", "users"],
+ queryFn: async () => jellyseerrApi?.user({take: 1000, sort: 'displayname'}),
+ enabled: !!jellyseerrApi && !!jellyseerrUser,
+ refetchOnMount: 'always'
+ });
+
+ const defaultService = useMemo(
+ () => serviceSettings?.find?.(v => v.isDefault),
+ [serviceSettings]
+ );
+
+ const {data: defaultServiceDetails} = useQuery({
+ queryKey: ["jellyseerr", "request", type, 'service', 'details', defaultService?.id],
+ queryFn: async () => {
+ setRequestOverrides((prev) => ({
+ ...prev,
+ serverId: defaultService?.id
+ }))
+ return jellyseerrApi?.serviceDetails(type === 'movie' ? 'radarr' : 'sonarr', defaultService!!.id)
+ },
+ enabled: !!jellyseerrApi && !!jellyseerrUser && !!defaultService,
+ refetchOnMount: 'always',
+ });
+
+ const defaultProfile: QualityProfile = useMemo(
+ () => defaultServiceDetails?.profiles
+ .find(p =>
+ p.id === (isAnime ? defaultServiceDetails.server?.activeAnimeProfileId : defaultServiceDetails.server?.activeProfileId)
+ ),
+ [defaultServiceDetails]
+ );
+
+ const defaultFolder: RootFolder = useMemo(
+ () => defaultServiceDetails?.rootFolders
+ .find(f =>
+ f.path === (isAnime ? defaultServiceDetails?.server.activeAnimeDirectory : defaultServiceDetails.server?.activeDirectory)
+ ),
+ [defaultServiceDetails]
+ );
+
+ const defaultTags: Tag[] = useMemo(
+ () => {
+ const tags = defaultServiceDetails?.tags
+ .filter(t =>
+ (isAnime
+ ? defaultServiceDetails?.server.activeAnimeTags
+ : defaultServiceDetails?.server.activeTags
+ )?.includes(t.id)
+ ) ?? []
+
+ console.log(tags)
+ return tags
+ },
+ [defaultServiceDetails]
+ );
+
+ const seasonTitle = useMemo(
+ () => modalRequestProps?.seasons?.length ? t("jellyseerr.season_x", {seasons: modalRequestProps?.seasons}) : undefined,
+ [modalRequestProps?.seasons]
+ );
+
+ const request = useCallback(() => {requestMedia(
+ seasonTitle ? `${title}, ${seasonTitle}` : title,
+ {
+ is4k: defaultService?.is4k || defaultServiceDetails?.server.is4k,
+ profileId: defaultProfile.id,
+ rootFolder: defaultFolder.path,
+ tags: defaultTags.map(t => t.id),
+ ...modalRequestProps,
+ ...requestOverrides
+ },
+ onRequested
+ )
+ }, [modalRequestProps, requestOverrides, defaultProfile, defaultFolder, defaultTags]);
+
+ const pathTitleExtractor = (item: RootFolder) => `${item.path} (${item.freeSpace.bytesToReadable()})`;
+
+ return (
+ setModalRequestProps(undefined)}
+ handleIndicatorStyle={{
+ backgroundColor: "white",
+ }}
+ backgroundStyle={{
+ backgroundColor: "#171717",
+ }}
+ backdropComponent={(sheetProps: BottomSheetBackdropProps) =>
+
+ }
+ >
+ {(data) => {
+ setModalRequestProps(data?.data as MediaRequestBody)
+ return
+
+
+ {t("jellyseerr.advanced")}
+ {seasonTitle &&
+ {seasonTitle}
+ }
+
+
+ {(defaultService && defaultServiceDetails && users) && (
+ <>
+ item.name}
+ placeholderText={defaultProfile.name}
+ keyExtractor={(item) => item.id.toString()}
+ label={t("jellyseerr.quality_profile")}
+ onSelected={(item) =>
+ item && setRequestOverrides((prev) => ({
+ ...prev,
+ profileId: item?.id
+ }))
+ }
+ title={t("jellyseerr.quality_profile")}
+ />
+ item.id.toString()}
+ label={t("jellyseerr.root_folder")}
+ onSelected={(item) =>
+ item && setRequestOverrides((prev) => ({
+ ...prev,
+ rootFolder: item.path
+ }))}
+ title={t("jellyseerr.root_folder")}
+ />
+ item.label}
+ placeholderText={defaultTags.map(t => t.label).join(",")}
+ keyExtractor={(item) => item.id.toString()}
+ label={t("jellyseerr.tags")}
+ onSelected={(...item) =>
+ item && setRequestOverrides((prev) => ({
+ ...prev,
+ tags: item.map(i => i.id)
+ }))
+ }
+ title={t("jellyseerr.tags")}
+ />
+ item.displayName}
+ placeholderText={jellyseerrUser!!.displayName}
+ keyExtractor={(item) => item.id.toString() || ""}
+ label={t("jellyseerr.request_as")}
+ onSelected={(item) =>
+ item && setRequestOverrides((prev) => ({
+ ...prev,
+ userId: item?.id
+ }))
+ }
+ title={t("jellyseerr.request_as")}
+ />
+ >
+ )
+ }
+
+
+
+
+ }}
+
+ );
+});
+
+export default RequestModal;
\ No newline at end of file
diff --git a/components/jellyseerr/discover/CompanySlide.tsx b/components/jellyseerr/discover/CompanySlide.tsx
new file mode 100644
index 00000000..abee4a9d
--- /dev/null
+++ b/components/jellyseerr/discover/CompanySlide.tsx
@@ -0,0 +1,51 @@
+import GenericSlideCard from "@/components/jellyseerr/discover/GenericSlideCard";
+import Slide, { SlideProps } from "@/components/jellyseerr/discover/Slide";
+import { useJellyseerr } from "@/hooks/useJellyseerr";
+import {
+ COMPANY_LOGO_IMAGE_FILTER,
+ Network,
+} from "@/utils/jellyseerr/src/components/Discover/NetworkSlider";
+import { Studio } from "@/utils/jellyseerr/src/components/Discover/StudioSlider";
+import { router, useSegments } from "expo-router";
+import React, { useCallback } from "react";
+import { TouchableOpacity, ViewProps } from "react-native";
+
+const CompanySlide: React.FC<
+ { data: Network[] | Studio[] } & SlideProps & ViewProps
+> = ({ slide, data, ...props }) => {
+ const segments = useSegments();
+ const { jellyseerrApi } = useJellyseerr();
+ const from = segments[2];
+
+ const navigate = useCallback(
+ ({ id, image, name }: Network | Studio) =>
+ router.push({
+ pathname: `/(auth)/(tabs)/${from}/jellyseerr/company/${id}`,
+ params: { id, image, name, type: slide.type },
+ }),
+ [slide]
+ );
+
+ return (
+ item.id.toString()}
+ renderItem={(item, index) => (
+ navigate(item)}>
+
+
+ )}
+ />
+ );
+};
+
+export default CompanySlide;
diff --git a/components/jellyseerr/discover/Discover.tsx b/components/jellyseerr/discover/Discover.tsx
new file mode 100644
index 00000000..6270ad2b
--- /dev/null
+++ b/components/jellyseerr/discover/Discover.tsx
@@ -0,0 +1,47 @@
+import React, {useMemo} from "react";
+import DiscoverSlider from "@/utils/jellyseerr/server/entity/DiscoverSlider";
+import {DiscoverSliderType} from "@/utils/jellyseerr/server/constants/discover";
+import {sortBy} from "lodash";
+import MovieTvSlide from "@/components/jellyseerr/discover/MovieTvSlide";
+import CompanySlide from "@/components/jellyseerr/discover/CompanySlide";
+import {View} from "react-native";
+import {networks} from "@/utils/jellyseerr/src/components/Discover/NetworkSlider";
+import {studios} from "@/utils/jellyseerr/src/components/Discover/StudioSlider";
+import GenreSlide from "@/components/jellyseerr/discover/GenreSlide";
+
+interface Props {
+ sliders?: DiscoverSlider[];
+}
+const Discover: React.FC = ({ sliders }) => {
+ if (!sliders)
+ return;
+
+ const sortedSliders = useMemo(
+ () => sortBy(sliders.filter((s) => s.enabled), 'order', 'asc'),
+ [sliders]
+ );
+
+ return (
+
+ {sortedSliders.map(slide => {
+ switch (slide.type) {
+ case DiscoverSliderType.NETWORKS:
+ return
+ case DiscoverSliderType.STUDIOS:
+ return
+ case DiscoverSliderType.MOVIE_GENRES:
+ case DiscoverSliderType.TV_GENRES:
+ return
+ case DiscoverSliderType.TRENDING:
+ case DiscoverSliderType.POPULAR_MOVIES:
+ case DiscoverSliderType.UPCOMING_MOVIES:
+ case DiscoverSliderType.POPULAR_TV:
+ case DiscoverSliderType.UPCOMING_TV:
+ return
+ }
+ })}
+
+ )
+};
+
+export default Discover;
diff --git a/components/jellyseerr/discover/GenericSlideCard.tsx b/components/jellyseerr/discover/GenericSlideCard.tsx
new file mode 100644
index 00000000..776d1424
--- /dev/null
+++ b/components/jellyseerr/discover/GenericSlideCard.tsx
@@ -0,0 +1,59 @@
+import React from "react";
+import {StyleSheet, View, ViewProps} from "react-native";
+import {Image, ImageContentFit} from "expo-image";
+import {Text} from "@/components/common/Text";
+import {LinearGradient} from "expo-linear-gradient";
+
+export const textShadowStyle = StyleSheet.create({
+ shadow: {
+ shadowColor: "#000",
+ shadowOffset: {
+ width: 1,
+ height: 1,
+ },
+ shadowOpacity: 1,
+ shadowRadius: .5,
+
+ elevation: 6,
+ }
+})
+
+const GenericSlideCard: React.FC<{id: string; url?: string, title?: string, colors?: string[], contentFit?: ImageContentFit} & ViewProps> = ({
+ id,
+ url,
+ title,
+ colors = ['#9333ea', 'transparent'],
+ contentFit = "contain",
+ ...props
+}) => (
+ <>
+
+
+
+ {title &&
+
+ {title}
+
+ }
+
+
+ >
+);
+
+export default GenericSlideCard;
\ No newline at end of file
diff --git a/components/jellyseerr/discover/GenreSlide.tsx b/components/jellyseerr/discover/GenreSlide.tsx
new file mode 100644
index 00000000..36623e20
--- /dev/null
+++ b/components/jellyseerr/discover/GenreSlide.tsx
@@ -0,0 +1,67 @@
+import GenericSlideCard from "@/components/jellyseerr/discover/GenericSlideCard";
+import Slide, { SlideProps } from "@/components/jellyseerr/discover/Slide";
+import { Endpoints, useJellyseerr } from "@/hooks/useJellyseerr";
+import { DiscoverSliderType } from "@/utils/jellyseerr/server/constants/discover";
+import { GenreSliderItem } from "@/utils/jellyseerr/server/interfaces/api/discoverInterfaces";
+import { genreColorMap } from "@/utils/jellyseerr/src/components/Discover/constants";
+import { useQuery } from "@tanstack/react-query";
+import { router, useSegments } from "expo-router";
+import React, { useCallback } from "react";
+import { TouchableOpacity, ViewProps } from "react-native";
+
+const GenreSlide: React.FC = ({ slide, ...props }) => {
+ const segments = useSegments();
+ const { jellyseerrApi } = useJellyseerr();
+ const from = segments[2];
+
+ const navigate = useCallback(
+ (genre: GenreSliderItem) =>
+ router.push({
+ pathname: `/(auth)/(tabs)/${from}/jellyseerr/genre/${genre.id}`,
+ params: { type: slide.type, name: genre.name },
+ }),
+ [slide]
+ );
+
+ const { data, isFetching, isLoading } = useQuery({
+ queryKey: ["jellyseerr", "discover", slide.type, slide.id],
+ queryFn: async () => {
+ return jellyseerrApi?.getGenreSliders(
+ slide.type == DiscoverSliderType.MOVIE_GENRES
+ ? Endpoints.MOVIE
+ : Endpoints.TV
+ );
+ },
+ enabled: !!jellyseerrApi,
+ });
+
+ return (
+ data && (
+ item.id.toString()}
+ renderItem={(item, index) => (
+ navigate(item)}>
+
+
+ )}
+ />
+ )
+ );
+};
+
+export default GenreSlide;
diff --git a/components/jellyseerr/DiscoverSlide.tsx b/components/jellyseerr/discover/MovieTvSlide.tsx
similarity index 58%
rename from components/jellyseerr/DiscoverSlide.tsx
rename to components/jellyseerr/discover/MovieTvSlide.tsx
index c7112def..723658c8 100644
--- a/components/jellyseerr/DiscoverSlide.tsx
+++ b/components/jellyseerr/discover/MovieTvSlide.tsx
@@ -1,5 +1,4 @@
-import React, { useMemo } from "react";
-import DiscoverSlider from "@/utils/jellyseerr/server/entity/DiscoverSlider";
+import React, {useMemo} from "react";
import { DiscoverSliderType } from "@/utils/jellyseerr/server/constants/discover";
import {
DiscoverEndpoint,
@@ -9,17 +8,13 @@ import {
import { useInfiniteQuery } from "@tanstack/react-query";
import { MovieResult, TvResult } from "@/utils/jellyseerr/server/models/Search";
import JellyseerrPoster from "@/components/posters/JellyseerrPoster";
-import { Text } from "@/components/common/Text";
-import { FlashList } from "@shopify/flash-list";
-import { View } from "react-native";
+import Slide, {SlideProps} from "@/components/jellyseerr/discover/Slide";
+import {ViewProps} from "react-native";
-interface Props {
- slide: DiscoverSlider;
-}
-const DiscoverSlide: React.FC = ({ slide }) => {
+const MovieTvSlide: React.FC = ({ slide, ...props }) => {
const { jellyseerrApi } = useJellyseerr();
- const { data, isFetching, fetchNextPage, hasNextPage } = useInfiniteQuery({
+ const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
queryKey: ["jellyseerr", "discover", slide.id],
queryFn: async ({ pageParam }) => {
let endpoint: DiscoverEndpoint | undefined = undefined;
@@ -62,42 +57,28 @@ const DiscoverSlide: React.FC = ({ slide }) => {
});
const flatData = useMemo(
- () =>
- data?.pages?.filter((p) => p?.results.length).flatMap((p) => p?.results),
+ () => data?.pages?.filter((p) => p?.results.length).flatMap((p) => p?.results),
[data]
);
return (
flatData &&
flatData?.length > 0 && (
-
-
- {DiscoverSliderType[slide.type].toString().toTitle()}
-
- item!!.id.toString()}
- estimatedItemSize={250}
- data={flatData}
- onEndReachedThreshold={1}
- onEndReached={() => {
- if (hasNextPage) fetchNextPage();
- }}
- renderItem={({ item }) =>
- item ? (
-
- ) : (
- <>>
- )
- }
- />
-
+ item!!.id.toString()}
+ onEndReached={() => {
+ if (hasNextPage)
+ fetchNextPage()
+ }}
+ renderItem={(item) =>
+
+ }
+ />
)
);
};
-export default DiscoverSlide;
+export default MovieTvSlide;
diff --git a/components/jellyseerr/discover/Slide.tsx b/components/jellyseerr/discover/Slide.tsx
new file mode 100644
index 00000000..f110eb15
--- /dev/null
+++ b/components/jellyseerr/discover/Slide.tsx
@@ -0,0 +1,56 @@
+import React, {PropsWithChildren} from "react";
+import DiscoverSlider from "@/utils/jellyseerr/server/entity/DiscoverSlider";
+import { DiscoverSliderType } from "@/utils/jellyseerr/server/constants/discover";
+import { Text } from "@/components/common/Text";
+import { FlashList } from "@shopify/flash-list";
+import {View, ViewProps} from "react-native";
+import { t } from "i18next";
+
+export interface SlideProps {
+ slide: DiscoverSlider;
+}
+
+interface Props extends SlideProps {
+ data: T[]
+ renderItem: (item: T, index: number) =>
+ | React.ComponentType
+ | React.ReactElement
+ | null
+ | undefined;
+ keyExtractor: (item: T) => string;
+ onEndReached?: (() => void) | null | undefined;
+}
+
+const Slide = ({
+ data,
+ slide,
+ renderItem,
+ keyExtractor,
+ onEndReached,
+ ...props
+}: PropsWithChildren & ViewProps>
+) => {
+ return (
+
+
+ {t("search." + DiscoverSliderType[slide.type].toString().toLowerCase())}
+
+ item ? renderItem(item, index) : <>>}
+ />
+
+ );
+};
+
+export default Slide;
diff --git a/components/library/LibraryItemCard.tsx b/components/library/LibraryItemCard.tsx
index 17595db6..a7b78f0a 100644
--- a/components/library/LibraryItemCard.tsx
+++ b/components/library/LibraryItemCard.tsx
@@ -15,6 +15,7 @@ import { useAtom } from "jotai";
import { useMemo } from "react";
import { TouchableOpacityProps, View } from "react-native";
import { TouchableItemRouter } from "../common/TouchableItemRouter";
+import { useTranslation } from "react-i18next";
interface Props extends TouchableOpacityProps {
library: BaseItemDto;
@@ -42,6 +43,8 @@ export const LibraryItemCard: React.FC = ({ library, ...props }) => {
const [user] = useAtom(userAtom);
const [settings] = useSettings();
+ const { t } = useTranslation();
+
const url = useMemo(
() =>
getPrimaryImageUrl({
@@ -60,8 +63,6 @@ export const LibraryItemCard: React.FC = ({ library, ...props }) => {
_itemType = "Series";
} else if (library.CollectionType === "boxsets") {
_itemType = "BoxSet";
- } else if (library.CollectionType === "music") {
- _itemType = "MusicAlbum";
}
return _itemType;
@@ -71,15 +72,13 @@ export const LibraryItemCard: React.FC = ({ library, ...props }) => {
let nameStr: string;
if (library.CollectionType === "movies") {
- nameStr = "movies";
+ nameStr = t("library.item_types.movies");
} else if (library.CollectionType === "tvshows") {
- nameStr = "series";
+ nameStr = t("library.item_types.series");
} else if (library.CollectionType === "boxsets") {
- nameStr = "box sets";
- } else if (library.CollectionType === "music") {
- nameStr = "albums";
+ nameStr = t("library.item_types.boxsets");
} else {
- nameStr = "items";
+ nameStr = t("library.item_types.items");
}
return nameStr;
diff --git a/components/list/ListItem.tsx b/components/list/ListItem.tsx
index 46856b00..403b33dc 100644
--- a/components/list/ListItem.tsx
+++ b/components/list/ListItem.tsx
@@ -1,3 +1,4 @@
+import { Ionicons } from "@expo/vector-icons";
import { PropsWithChildren, ReactNode } from "react";
import {
TouchableOpacity,
@@ -6,7 +7,6 @@ import {
ViewProps,
} from "react-native";
import { Text } from "../common/Text";
-import { Ionicons } from "@expo/vector-icons";
interface Props extends TouchableOpacityProps, ViewProps {
title?: string | null | undefined;
diff --git a/components/music/SongsList.tsx b/components/music/SongsList.tsx
deleted file mode 100644
index 4d576f3c..00000000
--- a/components/music/SongsList.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
-import { useRouter } from "expo-router";
-import { View, ViewProps } from "react-native";
-import { SongsListItem } from "./SongsListItem";
-
-interface Props extends ViewProps {
- songs?: BaseItemDto[] | null;
- collectionId: string;
- artistId: string;
- albumId: string;
-}
-
-export const SongsList: React.FC = ({
- collectionId,
- artistId,
- albumId,
- songs = [],
- ...props
-}) => {
- const router = useRouter();
- return (
-
- {songs?.map((item: BaseItemDto, index: number) => (
-
- ))}
-
- );
-};
diff --git a/components/music/SongsListItem.tsx b/components/music/SongsListItem.tsx
deleted file mode 100644
index 552baa69..00000000
--- a/components/music/SongsListItem.tsx
+++ /dev/null
@@ -1,128 +0,0 @@
-import { Text } from "@/components/common/Text";
-import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
-import { usePlaySettings } from "@/providers/PlaySettingsProvider";
-import { runtimeTicksToSeconds } from "@/utils/time";
-import { useActionSheet } from "@expo/react-native-action-sheet";
-import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
-import { useRouter } from "expo-router";
-import { useAtom } from "jotai";
-import { useCallback } from "react";
-import { TouchableOpacity, TouchableOpacityProps, View } from "react-native";
-import CastContext, {
- PlayServicesState,
- useCastDevice,
- useRemoteMediaClient,
-} from "react-native-google-cast";
-
-interface Props extends TouchableOpacityProps {
- collectionId: string;
- artistId: string;
- albumId: string;
- item: BaseItemDto;
- index: number;
-}
-
-export const SongsListItem: React.FC = ({
- collectionId,
- artistId,
- albumId,
- item,
- index,
- ...props
-}) => {
- const [api] = useAtom(apiAtom);
- const [user] = useAtom(userAtom);
- const castDevice = useCastDevice();
- const router = useRouter();
- const client = useRemoteMediaClient();
- const { showActionSheetWithOptions } = useActionSheet();
-
- const { setPlaySettings } = usePlaySettings();
-
- const openSelect = () => {
- if (!castDevice?.deviceId) {
- play("device");
- return;
- }
-
- const options = ["Chromecast", "Device", "Cancel"];
- const cancelButtonIndex = 2;
-
- showActionSheetWithOptions(
- {
- options,
- cancelButtonIndex,
- },
- (selectedIndex: number | undefined) => {
- switch (selectedIndex) {
- case 0:
- play("cast");
- break;
- case 1:
- play("device");
- break;
- case cancelButtonIndex:
- break;
- }
- }
- );
- };
-
- const play = useCallback(async (type: "device" | "cast") => {
- if (!user?.Id || !api || !item.Id) {
- console.warn("No user, api or item", user, api, item.Id);
- return;
- }
-
- const data = await setPlaySettings({
- item,
- });
-
- if (!data?.url) {
- throw new Error("play-music ~ No stream url");
- }
-
- if (type === "cast" && client) {
- await CastContext.getPlayServicesState().then((state) => {
- if (state && state !== PlayServicesState.SUCCESS)
- CastContext.showPlayServicesErrorDialog(state);
- else {
- client.loadMedia({
- mediaInfo: {
- contentUrl: data.url!,
- contentType: "video/mp4",
- metadata: {
- type: item.Type === "Episode" ? "tvShow" : "movie",
- title: item.Name || "",
- subtitle: item.Overview || "",
- },
- },
- startTime: 0,
- });
- }
- });
- } else {
- console.log("Playing on device", data.url, item.Id);
- router.push("/music-player");
- }
- }, []);
-
- return (
- {
- openSelect();
- }}
- {...props}
- >
-
- {index + 1}
-
- {item.Name}
-
- {runtimeTicksToSeconds(item.RunTimeTicks)}
-
-
-
-
- );
-};
diff --git a/components/posters/AlbumCover.tsx b/components/posters/AlbumCover.tsx
deleted file mode 100644
index 870dce6a..00000000
--- a/components/posters/AlbumCover.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import { apiAtom } from "@/providers/JellyfinProvider";
-import { getPrimaryImageUrl } from "@/utils/jellyfin/image/getPrimaryImageUrl";
-import { getPrimaryImageUrlById } from "@/utils/jellyfin/image/getPrimaryImageUrlById";
-import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
-import { Image } from "expo-image";
-import { useAtom } from "jotai";
-import { useMemo } from "react";
-import { View } from "react-native";
-
-type ArtistPosterProps = {
- item?: BaseItemDto | null;
- id?: string | null;
- showProgress?: boolean;
-};
-
-const AlbumCover: React.FC = ({ item, id }) => {
- const [api] = useAtom(apiAtom);
-
- const url = useMemo(() => {
- const u = getPrimaryImageUrl({
- api,
- item,
- });
- return u;
- }, [item]);
-
- const url2 = useMemo(() => {
- const u = getPrimaryImageUrlById({
- api,
- id,
- quality: 85,
- width: 300,
- });
- return u;
- }, [item]);
-
- if (!item && id)
- return (
-
-
-
- );
-
- if (item)
- return (
-
-
-
- );
-};
-
-export default AlbumCover;
diff --git a/components/posters/ArtistPoster.tsx b/components/posters/ArtistPoster.tsx
deleted file mode 100644
index d64818b6..00000000
--- a/components/posters/ArtistPoster.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import { apiAtom } from "@/providers/JellyfinProvider";
-import { getPrimaryImageUrl } from "@/utils/jellyfin/image/getPrimaryImageUrl";
-import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
-import { Image } from "expo-image";
-import { useAtom } from "jotai";
-import { useMemo } from "react";
-import { View } from "react-native";
-
-type ArtistPosterProps = {
- item: BaseItemDto;
- showProgress?: boolean;
-};
-
-const ArtistPoster: React.FC = ({
- item,
- showProgress = false,
-}) => {
- const [api] = useAtom(apiAtom);
-
- const url = useMemo(
- () =>
- getPrimaryImageUrl({
- api,
- item,
- }),
- [item]
- );
-
- if (!url)
- return (
-
- );
-
- return (
-
-
-
- );
-};
-
-export default ArtistPoster;
diff --git a/components/posters/JellyseerrPoster.tsx b/components/posters/JellyseerrPoster.tsx
index 5f363d42..1c3ce45b 100644
--- a/components/posters/JellyseerrPoster.tsx
+++ b/components/posters/JellyseerrPoster.tsx
@@ -1,36 +1,52 @@
-import { View, ViewProps } from "react-native";
-import { Image } from "expo-image";
-import { Text } from "@/components/common/Text";
-import { useMemo } from "react";
-import { MovieResult, TvResult } from "@/utils/jellyseerr/server/models/Search";
-import {
- MediaStatus,
- MediaType,
-} from "@/utils/jellyseerr/server/constants/media";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
-import {
- hasPermission,
- Permission,
-} from "@/utils/jellyseerr/server/lib/permissions";
import { TouchableJellyseerrRouter } from "@/components/common/JellyseerrItemRouter";
-import JellyseerrStatusIcon from "@/components/jellyseerr/JellyseerrStatusIcon";
+import { Text } from "@/components/common/Text";
import JellyseerrMediaIcon from "@/components/jellyseerr/JellyseerrMediaIcon";
+import JellyseerrStatusIcon from "@/components/jellyseerr/JellyseerrStatusIcon";
+import { useJellyseerr } from "@/hooks/useJellyseerr";
import { useJellyseerrCanRequest } from "@/utils/_jellyseerr/useJellyseerrCanRequest";
+import { MediaType } from "@/utils/jellyseerr/server/constants/media";
+import { MovieResult, TvResult } from "@/utils/jellyseerr/server/models/Search";
+import { Image } from "expo-image";
+import { useMemo } from "react";
+import { View, ViewProps } from "react-native";
+import Animated, {
+ useAnimatedStyle,
+ useSharedValue,
+ withTiming,
+} from "react-native-reanimated";
+
interface Props extends ViewProps {
item: MovieResult | TvResult;
}
const JellyseerrPoster: React.FC = ({ item, ...props }) => {
const { jellyseerrApi } = useJellyseerr();
+ const loadingOpacity = useSharedValue(1);
+ const imageOpacity = useSharedValue(0);
+
+ const loadingAnimatedStyle = useAnimatedStyle(() => ({
+ opacity: loadingOpacity.value,
+ }));
+
+ const imageAnimatedStyle = useAnimatedStyle(() => ({
+ opacity: imageOpacity.value,
+ }));
+
+ const handleImageLoad = () => {
+ loadingOpacity.value = withTiming(0, { duration: 200 });
+ imageOpacity.value = withTiming(1, { duration: 300 });
+ };
const imageSrc = useMemo(
() => jellyseerrApi?.imageProxy(item.posterPath, "w300_and_h450_face"),
[item, jellyseerrApi]
);
+
const title = useMemo(
() => (item.mediaType === MediaType.MOVIE ? item.title : item.name),
[item]
);
+
const releaseYear = useMemo(
() =>
new Date(
@@ -41,7 +57,7 @@ const JellyseerrPoster: React.FC = ({ item, ...props }) => {
[item]
);
- const canRequest = useJellyseerrCanRequest(item);
+ const [canRequest] = useJellyseerrCanRequest(item);
return (
= ({ item, ...props }) => {
>
-
+
+
+
-
= ({ isLoading }) => {
+ const opacity = useSharedValue(1);
+
+ const animatedStyle = useAnimatedStyle(() => {
+ return {
+ opacity: opacity.value,
+ };
+ });
+
+ useAnimatedReaction(
+ () => isLoading,
+ (loading) => {
+ if (loading) {
+ opacity.value = withTiming(1, { duration: 200 });
+ } else {
+ opacity.value = withTiming(0, { duration: 200 });
+ }
+ }
+ );
+
+ return (
+
+ {[1, 2, 3].map((s) => (
+
+
+
+ {[1, 2, 3].map((i) => (
+
+
+
+
+ Nisi mollit voluptate amet.
+
+
+
+
+ Lorem ipsum
+
+
+
+ ))}
+
+
+ ))}
+
+ );
+};
diff --git a/components/search/SearchItemWrapper.tsx b/components/search/SearchItemWrapper.tsx
new file mode 100644
index 00000000..45c3e341
--- /dev/null
+++ b/components/search/SearchItemWrapper.tsx
@@ -0,0 +1,70 @@
+import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
+import { getUserItemData } from "@/utils/jellyfin/user-library/getUserItemData";
+import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
+import { useQuery } from "@tanstack/react-query";
+import { useAtom } from "jotai";
+import { PropsWithChildren } from "react";
+import { ScrollView } from "react-native";
+import { Text } from "../common/Text";
+
+type SearchItemWrapperProps = {
+ ids?: string[] | null;
+ items?: T[];
+ renderItem: (item: any) => React.ReactNode;
+ header?: string;
+};
+
+export const SearchItemWrapper = ({
+ ids,
+ items,
+ renderItem,
+ header,
+}: PropsWithChildren>) => {
+ const [api] = useAtom(apiAtom);
+ const [user] = useAtom(userAtom);
+
+ const { data, isLoading: l1 } = useQuery({
+ queryKey: ["items", ids],
+ queryFn: async () => {
+ if (!user?.Id || !api || !ids || ids.length === 0) {
+ return [];
+ }
+
+ const itemPromises = ids.map((id) =>
+ getUserItemData({
+ api,
+ userId: user.Id,
+ itemId: id,
+ })
+ );
+
+ const results = await Promise.all(itemPromises);
+
+ // Filter out null items
+ return results.filter(
+ (item) => item !== null
+ ) as unknown as BaseItemDto[];
+ },
+ enabled: !!ids && ids.length > 0 && !!api && !!user?.Id,
+ staleTime: Infinity,
+ });
+
+ if (!data && (!items || items.length === 0)) return null;
+
+ return (
+ <>
+ {header}
+
+ {data && data?.length > 0
+ ? data.map((item) => renderItem(item))
+ : items && items?.length > 0
+ ? items.map((i) => renderItem(i))
+ : undefined}
+
+ >
+ );
+};
diff --git a/components/series/CastAndCrew.tsx b/components/series/CastAndCrew.tsx
index 01cd1e84..e774b561 100644
--- a/components/series/CastAndCrew.tsx
+++ b/components/series/CastAndCrew.tsx
@@ -12,6 +12,7 @@ import { HorizontalScroll } from "../common/HorrizontalScroll";
import { Text } from "../common/Text";
import Poster from "../posters/Poster";
import { itemRouter } from "../common/TouchableItemRouter";
+import { useTranslation } from "react-i18next";
interface Props extends ViewProps {
item?: BaseItemDto | null;
@@ -21,6 +22,7 @@ interface Props extends ViewProps {
export const CastAndCrew: React.FC = ({ item, loading, ...props }) => {
const [api] = useAtom(apiAtom);
const segments = useSegments();
+ const { t } = useTranslation();
const from = segments[2];
const destinctPeople = useMemo(() => {
@@ -40,7 +42,7 @@ export const CastAndCrew: React.FC = ({ item, loading, ...props }) => {
return (
- Cast & Crew
+ {t("item_card.cast_and_crew")}
i.Id.toString()}
diff --git a/components/series/CurrentSeries.tsx b/components/series/CurrentSeries.tsx
index 52851533..16536a6d 100644
--- a/components/series/CurrentSeries.tsx
+++ b/components/series/CurrentSeries.tsx
@@ -8,6 +8,7 @@ import Poster from "../posters/Poster";
import { HorizontalScroll } from "../common/HorrizontalScroll";
import { Text } from "../common/Text";
import { getPrimaryImageUrlById } from "@/utils/jellyfin/image/getPrimaryImageUrlById";
+import { useTranslation } from "react-i18next";
interface Props extends ViewProps {
item?: BaseItemDto | null;
@@ -15,10 +16,11 @@ interface Props extends ViewProps {
export const CurrentSeries: React.FC = ({ item, ...props }) => {
const [api] = useAtom(apiAtom);
+ const { t } = useTranslation();
return (
- Series
+ {t("item_card.series")}
void;
refetch: (options?: (RefetchOptions | undefined)) => Promise>;
-}> = ({ isLoading, result, details, refetch }) => {
+}> = ({
+ isLoading,
+ result,
+ details,
+ refetch,
+ hasAdvancedRequest,
+ onAdvancedRequest,
+}) => {
if (!details) return null;
const { jellyseerrApi, requestMedia } = useJellyseerr();
@@ -142,7 +153,7 @@ const JellyseerrSeasons: React.FC<{
const requestAll = useCallback(() => {
if (details && jellyseerrApi) {
- requestMedia(result?.name!!, {
+ const body: MediaRequestBody = {
mediaId: details.id,
mediaType: MediaType.TV,
tvdbId: details.externalIds?.tvdbId,
@@ -151,19 +162,25 @@ const JellyseerrSeasons: React.FC<{
(s) => s.status === MediaStatus.UNKNOWN && s.seasonNumber !== 0
)
.map((s) => s.seasonNumber),
- });
+ }
+
+ if (hasAdvancedRequest) {
+ return onAdvancedRequest?.(body)
+ }
+
+ requestMedia(result?.name!!, body, refetch);
}
- }, [jellyseerrApi, seasons, details]);
+ }, [jellyseerrApi, seasons, details, hasAdvancedRequest, onAdvancedRequest]);
const promptRequestAll = useCallback(
() =>
- Alert.alert("Confirm", "Are you sure you want to request all seasons?", [
+ Alert.alert(t("jellyseerr.confirm"), t("jellyseerr.are_you_sure_you_want_to_request_all_seasons"), [
{
- text: "Cancel",
+ text: t("jellyseerr.cancel"),
style: "cancel",
},
{
- text: "Yes",
+ text: t("jellyseerr.yes"),
onPress: requestAll,
},
]),
@@ -172,24 +189,26 @@ const JellyseerrSeasons: React.FC<{
const requestSeason = useCallback(async (canRequest: Boolean, seasonNumber: number) => {
if (canRequest) {
- requestMedia(
- `${result?.name!!}, Season ${seasonNumber}`,
- {
- mediaId: details.id,
- mediaType: MediaType.TV,
- tvdbId: details.externalIds?.tvdbId,
- seasons: [seasonNumber],
- },
- refetch
- )
+ const body: MediaRequestBody = {
+ mediaId: details.id,
+ mediaType: MediaType.TV,
+ tvdbId: details.externalIds?.tvdbId,
+ seasons: [seasonNumber],
+ }
+
+ if (hasAdvancedRequest) {
+ return onAdvancedRequest?.(body)
+ }
+
+ requestMedia(`${result?.name!!}, Season ${seasonNumber}`, body, refetch);
}
- }, [requestMedia]);
+ }, [requestMedia, hasAdvancedRequest, onAdvancedRequest]);
if (isLoading)
return (
- Seasons
+ {t("item_card.seasons")}
{!allSeasonsAvailable && (
@@ -209,7 +228,7 @@ const JellyseerrSeasons: React.FC<{
)}
ListHeaderComponent={() => (
- Seasons
+ {t("item_card.seasons")}
{!allSeasonsAvailable && (
@@ -237,8 +256,8 @@ const JellyseerrSeasons: React.FC<{
{[0].map(() => {
diff --git a/components/series/NextUp.tsx b/components/series/NextUp.tsx
index 95834b9d..c76a61c6 100644
--- a/components/series/NextUp.tsx
+++ b/components/series/NextUp.tsx
@@ -12,10 +12,12 @@ import ContinueWatchingPoster from "../ContinueWatchingPoster";
import { ItemCardText } from "../ItemCardText";
import { TouchableItemRouter } from "../common/TouchableItemRouter";
import { FlashList } from "@shopify/flash-list";
+import { useTranslation } from "react-i18next";
export const NextUp: React.FC<{ seriesId: string }> = ({ seriesId }) => {
const [user] = useAtom(userAtom);
const [api] = useAtom(apiAtom);
+ const { t } = useTranslation();
const { data: items } = useQuery({
queryKey: ["nextUp", seriesId],
@@ -37,14 +39,14 @@ export const NextUp: React.FC<{ seriesId: string }> = ({ seriesId }) => {
if (!items?.length)
return (
- Next up
- No items to display
+ {t("item_card.next_up")}
+ {t("item_card.no_items_to_display")}
);
return (
- Next up
+ {t("item_card.next_up")}
= ({
- Season {seasonIndex}
+ {t("item_card.season")} {seasonIndex}
@@ -104,7 +105,7 @@ export const SeasonDropdown: React.FC = ({
collisionPadding={8}
sideOffset={8}
>
- Seasons
+ {t("item_card.seasons")}
{seasons?.sort(sortByIndex).map((season: any) => (
= ({ item, initialSeasonIndex }) => {
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
const [seasonIndexState, setSeasonIndexState] = useAtom(seasonIndexAtom);
+ const { t } = useTranslation();
const seasonIndex = useMemo(
() => seasonIndexState[item.Id ?? ""],
@@ -144,17 +147,20 @@ export const SeasonPicker: React.FC = ({ item, initialSeasonIndex }) => {
}}
/>
{episodes?.length || 0 > 0 ? (
- (
-
- )}
- DownloadedIconComponent={() => (
-
- )}
- />
+
+ (
+
+ )}
+ DownloadedIconComponent={() => (
+
+ )}
+ />
+
+
) : null}
@@ -210,7 +216,7 @@ export const SeasonPicker: React.FC = ({ item, initialSeasonIndex }) => {
{(episodes?.length || 0) === 0 ? (
- No episodes for this season
+ {t("item_card.no_episodes_for_this_season")}
) : null}
diff --git a/components/settings/AppLanguageSelector.tsx b/components/settings/AppLanguageSelector.tsx
new file mode 100644
index 00000000..1c296038
--- /dev/null
+++ b/components/settings/AppLanguageSelector.tsx
@@ -0,0 +1,77 @@
+import * as DropdownMenu from "zeego/dropdown-menu";
+import { Platform, TouchableOpacity, View, ViewProps } from "react-native";
+import { Text } from "../common/Text";
+import { useSettings } from "@/utils/atoms/settings";
+import { ListGroup } from "../list/ListGroup";
+import { ListItem } from "../list/ListItem";
+import { useTranslation } from "react-i18next";
+import { APP_LANGUAGES } from "@/i18n";
+
+interface Props extends ViewProps {}
+
+export const AppLanguageSelector: React.FC = ({ ...props }) => {
+ const [settings, updateSettings] = useSettings();
+ const { t } = useTranslation();
+
+ if (!settings) return null;
+
+ // todo: fix
+ if (Platform.isTV) return null;
+
+ return (
+
+
+
+
+
+
+
+ {APP_LANGUAGES.find(
+ (l) => l.value === settings?.preferedLanguage
+ )?.label || t("home.settings.languages.system")}
+
+
+
+
+
+ {t("home.settings.languages.title")}
+
+ {
+ updateSettings({
+ preferedLanguage: undefined,
+ });
+ }}
+ >
+
+ {t("home.settings.languages.system")}
+
+
+ {APP_LANGUAGES?.map((l) => (
+ {
+ updateSettings({
+ preferedLanguage: l.value,
+ });
+ }}
+ >
+ {l.label}
+
+ ))}
+
+
+
+
+
+ );
+};
diff --git a/components/settings/AudioToggles.tsx b/components/settings/AudioToggles.tsx
index 8a185c77..4ce39942 100644
--- a/components/settings/AudioToggles.tsx
+++ b/components/settings/AudioToggles.tsx
@@ -3,43 +3,51 @@ import * as DropdownMenu from "@/components/DropdownMenu";
import { Text } from "../common/Text";
import { useMedia } from "./MediaContext";
import { Switch } from "react-native-gesture-handler";
+import { useTranslation } from "react-i18next";
import { ListGroup } from "../list/ListGroup";
import { ListItem } from "../list/ListItem";
import { Ionicons } from "@expo/vector-icons";
+import {useSettings} from "@/utils/atoms/settings";
interface Props extends ViewProps {}
export const AudioToggles: React.FC = ({ ...props }) => {
const media = useMedia();
+ const [_, __, pluginSettings] = useSettings();
const { settings, updateSettings } = media;
const cultures = media.cultures;
+ const { t } = useTranslation();
if (!settings) return null;
return (
- Choose a default audio language.
+ {t("home.settings.audio.audio_hint")}
}
>
-
+
updateSettings({ rememberAudioSelections: value })
}
/>
-
+
- {settings?.defaultAudioLanguage?.DisplayName || "None"}
+ {settings?.defaultAudioLanguage?.DisplayName || t("home.settings.audio.none")}
= ({ ...props }) => {
collisionPadding={8}
sideOffset={8}
>
- Languages
+ {t("home.settings.audio.language")}
{
@@ -66,7 +74,7 @@ export const AudioToggles: React.FC = ({ ...props }) => {
});
}}
>
- None
+ {t("home.settings.audio.none")}
{cultures?.map((l) => (
= ({
+ disabled = false,
+ showText = true,
+ text,
+ children,
+ ...props
+}) => (
+
+
+ {disabled && showText &&
+ {text ?? "Currently disabled by admin."}
+ }
+ {children}
+
+
+)
+
+export default DisabledSetting;
\ No newline at end of file
diff --git a/components/settings/DownloadSettings.tsx b/components/settings/DownloadSettings.tsx
index fd87c098..7b234929 100644
--- a/components/settings/DownloadSettings.tsx
+++ b/components/settings/DownloadSettings.tsx
@@ -1,35 +1,49 @@
import { Stepper } from "@/components/inputs/Stepper";
import { useDownload } from "@/providers/DownloadProvider";
-import { Settings, useSettings } from "@/utils/atoms/settings";
+import { DownloadMethod, Settings, useSettings } from "@/utils/atoms/settings";
import { Ionicons } from "@expo/vector-icons";
import { useQueryClient } from "@tanstack/react-query";
import { useRouter } from "expo-router";
-import React from "react";
-import { Switch, TouchableOpacity, View } from "react-native";
-import * as DropdownMenu from "@/components/DropdownMenu";
+import React, { useMemo } from "react";
+import { Switch, TouchableOpacity } from "react-native";
+import * as DropdownMenu from "zeego/dropdown-menu";
import { Text } from "../common/Text";
import { ListGroup } from "../list/ListGroup";
import { ListItem } from "../list/ListItem";
+import { useTranslation } from "react-i18next";
+import DisabledSetting from "@/components/settings/DisabledSetting";
-export const DownloadSettings: React.FC = ({ ...props }) => {
- const [settings, updateSettings] = useSettings();
+export default function DownloadSettings({ ...props }) {
+ const [settings, updateSettings, pluginSettings] = useSettings();
const { setProcesses } = useDownload();
const router = useRouter();
const queryClient = useQueryClient();
+ const { t } = useTranslation();
+
+ const allDisabled = useMemo(
+ () =>
+ pluginSettings?.downloadMethod?.locked === true &&
+ pluginSettings?.remuxConcurrentLimit?.locked === true &&
+ pluginSettings?.autoDownload.locked === true,
+ [pluginSettings]
+ );
if (!settings) return null;
return (
-
-
-
+
+
+
- {settings.downloadMethod === "remux"
- ? "Default"
- : "Optimized"}
+ {settings.downloadMethod === DownloadMethod.Remux
+ ? t("home.settings.downloads.default")
+ : t("home.settings.downloads.optimized")}
{
collisionPadding={8}
sideOffset={8}
>
- Methods
+
+ {t("home.settings.downloads.methods")}
+
{
- updateSettings({ downloadMethod: "remux" });
+ updateSettings({ downloadMethod: DownloadMethod.Remux });
setProcesses([]);
}}
>
- Default
+
+ {t("home.settings.downloads.default")}
+
{
- updateSettings({ downloadMethod: "optimized" });
+ updateSettings({ downloadMethod: DownloadMethod.Optimized });
setProcesses([]);
queryClient.invalidateQueries({ queryKey: ["search"] });
}}
>
- Optimized
+
+ {t("home.settings.downloads.optimized")}
+
{
updateSettings({ autoDownload: value })}
/>
router.push("/settings/optimized-server/page")}
showArrow
- title="Optimized Versions Server"
+ title={t("home.settings.downloads.optimized_versions_server")}
>
-
+
);
-};
+}
diff --git a/components/settings/Jellyseerr.tsx b/components/settings/Jellyseerr.tsx
index 148f1823..5f0afdc5 100644
--- a/components/settings/Jellyseerr.tsx
+++ b/components/settings/Jellyseerr.tsx
@@ -2,6 +2,7 @@ import { JellyseerrApi, useJellyseerr } from "@/hooks/useJellyseerr";
import { userAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings";
import { useMutation } from "@tanstack/react-query";
+import { useTranslation } from "react-i18next";
import { useAtom } from "jotai";
import { useState } from "react";
import { View } from "react-native";
@@ -20,8 +21,10 @@ export const JellyseerrSettings = () => {
clearAllJellyseerData,
} = useJellyseerr();
+ const { t } = useTranslation();
+
const [user] = useAtom(userAtom);
- const [settings, updateSettings] = useSettings();
+ const [settings, updateSettings, pluginSettings] = useSettings();
const [promptForJellyseerrPass, setPromptForJellyseerrPass] =
useState(false);
@@ -47,7 +50,7 @@ export const JellyseerrSettings = () => {
updateSettings({ jellyseerrServerUrl });
},
onError: () => {
- toast.error("Failed to login");
+ toast.error(t("jellyseerr.failed_to_login"));
},
onSettled: () => {
setJellyseerrPassword(undefined);
@@ -89,53 +92,50 @@ export const JellyseerrSettings = () => {
<>
>
) : (
- This integration is in its early stages. Expect things to change.
+ {t("home.settings.plugins.jellyseerr.jellyseerr_warning")}
- Server URL
+ {t("home.settings.plugins.jellyseerr.server_url")}
- Example: http(s)://your-host.url
-
-
- (add port if required)
+ {t("home.settings.plugins.jellyseerr.server_url_hint")}
{
marginBottom: 8,
}}
>
- {promptForJellyseerrPass ? "Clear" : "Save"}
+ {promptForJellyseerrPass ? t("home.settings.plugins.jellyseerr.clear_button") : t("home.settings.plugins.jellyseerr.save_button")}
{
opacity: promptForJellyseerrPass ? 1 : 0.5,
}}
>
- Password
+ {t("home.settings.plugins.jellyseerr.password")}
{
className="h-12 mt-2"
onPress={() => loginToJellyseerrMutation.mutate()}
>
- Login
+ {t("home.settings.plugins.jellyseerr.login_button")}
diff --git a/components/settings/MediaToggles.tsx b/components/settings/MediaToggles.tsx
index 7e4c4346..ae431ffb 100644
--- a/components/settings/MediaToggles.tsx
+++ b/components/settings/MediaToggles.tsx
@@ -1,72 +1,64 @@
-import React from "react";
-import { TouchableOpacity, View, ViewProps } from "react-native";
+import React, {useMemo} from "react";
+import { ViewProps } from "react-native";
import { useSettings } from "@/utils/atoms/settings";
import { ListGroup } from "../list/ListGroup";
import { ListItem } from "../list/ListItem";
-import { Text } from "../common/Text";
+import { useTranslation } from "react-i18next";
+import DisabledSetting from "@/components/settings/DisabledSetting";
+import {Stepper} from "@/components/inputs/Stepper";
interface Props extends ViewProps {}
export const MediaToggles: React.FC = ({ ...props }) => {
- const [settings, updateSettings] = useSettings();
+ const { t } = useTranslation();
+
+ const [settings, updateSettings, pluginSettings] = useSettings();
if (!settings) return null;
- const renderSkipControl = (
- value: number,
- onDecrease: () => void,
- onIncrease: () => void
- ) => (
-
-
- -
-
-
- {value}s
-
-
- +
-
-
- );
+ const disabled = useMemo(() => (
+ pluginSettings?.forwardSkipTime?.locked === true &&
+ pluginSettings?.rewindSkipTime?.locked === true
+ ),
+ [pluginSettings]
+ )
return (
-
-
-
- {renderSkipControl(
- settings.forwardSkipTime,
- () =>
- updateSettings({
- forwardSkipTime: Math.max(0, settings.forwardSkipTime - 5),
- }),
- () =>
- updateSettings({
- forwardSkipTime: Math.min(60, settings.forwardSkipTime + 5),
- })
- )}
+
+
+
+ updateSettings({forwardSkipTime})}
+ />
-
- {renderSkipControl(
- settings.rewindSkipTime,
- () =>
- updateSettings({
- rewindSkipTime: Math.max(0, settings.rewindSkipTime - 5),
- }),
- () =>
- updateSettings({
- rewindSkipTime: Math.min(60, settings.rewindSkipTime + 5),
- })
- )}
+
+ updateSettings({rewindSkipTime})}
+ />
-
+
);
};
diff --git a/components/settings/OptimizedServerForm.tsx b/components/settings/OptimizedServerForm.tsx
index 2aa7ebda..35910f04 100644
--- a/components/settings/OptimizedServerForm.tsx
+++ b/components/settings/OptimizedServerForm.tsx
@@ -1,5 +1,6 @@
import { TextInput, View, Linking } from "react-native";
import { Text } from "../common/Text";
+import { useTranslation } from "react-i18next";
interface Props {
value: string;
@@ -14,14 +15,16 @@ export const OptimizedServerForm: React.FC = ({
Linking.openURL("https://github.com/streamyfin/optimized-versions-server");
};
+ const { t } = useTranslation();
+
return (
- URL
+ {t("home.settings.downloads.url")}
= ({
- Enter the URL for the optimize server. The URL should include http or
- https and optionally the port.{" "}
+ {t("home.settings.downloads.optimized_version_hint")}{" "}
- Read more about the optimize server.
+ {t("home.settings.downloads.read_more_about_optimized_server")}
diff --git a/components/settings/OtherSettings.tsx b/components/settings/OtherSettings.tsx
index 5e750e40..e05c14e4 100644
--- a/components/settings/OtherSettings.tsx
+++ b/components/settings/OtherSettings.tsx
@@ -11,18 +11,22 @@ const BackgroundFetch = !Platform.isTV
: null;
import * as ScreenOrientation from "@/packages/expo-screen-orientation";
const TaskManager = !Platform.isTV ? require("expo-task-manager") : null;
-import React, { useEffect } from "react";
-import { Linking, Switch, TouchableOpacity, ViewProps } from "react-native";
+import { useRouter } from "expo-router";
+import React, { useEffect, useMemo } from "react";
+import { Linking, Switch, TouchableOpacity } from "react-native";
import { toast } from "sonner-native";
-import * as DropdownMenu from "@/components/DropdownMenu";
import { Text } from "../common/Text";
import { ListGroup } from "../list/ListGroup";
import { ListItem } from "../list/ListItem";
-
-interface Props extends ViewProps {}
+import { useTranslation } from "react-i18next";
+import DisabledSetting from "@/components/settings/DisabledSetting";
+import Dropdown from "@/components/common/Dropdown";
export const OtherSettings: React.FC = () => {
- const [settings, updateSettings] = useSettings();
+ const router = useRouter();
+ const [settings, updateSettings, pluginSettings] = useSettings();
+
+ const { t } = useTranslation();
/********************
* Background task
@@ -56,133 +60,122 @@ export const OtherSettings: React.FC = () => {
/**********************
*********************/
+ const disabled = useMemo(
+ () =>
+ pluginSettings?.autoRotate?.locked === true &&
+ pluginSettings?.defaultVideoOrientation?.locked === true &&
+ pluginSettings?.safeAreaInControlsEnabled?.locked === true &&
+ pluginSettings?.showCustomMenuLinks?.locked === true &&
+ pluginSettings?.hiddenLibraries?.locked === true &&
+ pluginSettings?.disableHapticFeedback?.locked === true,
+ [pluginSettings]
+ );
+
+ const orientations = [
+ ScreenOrientation.OrientationLock.DEFAULT,
+ ScreenOrientation.OrientationLock.PORTRAIT_UP,
+ ScreenOrientation.OrientationLock.LANDSCAPE_LEFT,
+ ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT,
+ ];
+
if (!settings) return null;
return (
-
-
- updateSettings({ autoRotate: value })}
- />
-
+
+
+
+ updateSettings({ autoRotate: value })}
+ />
+
-
-
-
-
-
- {ScreenOrientationEnum[settings.defaultVideoOrientation]}
-
-
-
-
-
- Orientation
- {
- updateSettings({
- defaultVideoOrientation:
- ScreenOrientation.OrientationLock.DEFAULT,
- });
- }}
- >
-
- {
- ScreenOrientationEnum[
- ScreenOrientation.OrientationLock.DEFAULT
- ]
- }
-
-
- {
- updateSettings({
- defaultVideoOrientation:
- ScreenOrientation.OrientationLock.PORTRAIT_UP,
- });
- }}
- >
-
- {
- ScreenOrientationEnum[
- ScreenOrientation.OrientationLock.PORTRAIT_UP
- ]
- }
-
-
- {
- updateSettings({
- defaultVideoOrientation:
- ScreenOrientation.OrientationLock.LANDSCAPE_LEFT,
- });
- }}
- >
-
- {
- ScreenOrientationEnum[
- ScreenOrientation.OrientationLock.LANDSCAPE_LEFT
- ]
- }
-
-
- {
- updateSettings({
- defaultVideoOrientation:
- ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT,
- });
- }}
- >
-
- {
- ScreenOrientationEnum[
- ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT
- ]
- }
-
-
-
-
-
-
-
-
- updateSettings({ safeAreaInControlsEnabled: value })
+
-
+ >
+ ScreenOrientationEnum[item]}
+ title={
+
+
+ {t(ScreenOrientationEnum[settings.defaultVideoOrientation])}
+
+
+
+ }
+ label={t("home.settings.other.orientation")}
+ onSelected={(defaultVideoOrientation) =>
+ updateSettings({ defaultVideoOrientation })
+ }
+ />
+
-
- Linking.openURL(
- "https://jellyfin.org/docs/general/clients/web-config/#custom-menu-links"
- )
- }
- >
-
- updateSettings({ showCustomMenuLinks: value })
+
+
+ updateSettings({ safeAreaInControlsEnabled: value })
+ }
+ />
+
+
+
+ Linking.openURL(
+ "https://jellyfin.org/docs/general/clients/web-config/#custom-menu-links"
+ )
}
+ >
+
+ updateSettings({ showCustomMenuLinks: value })
+ }
+ />
+
+ router.push("/settings/hide-libraries/page")}
+ title={t("home.settings.other.hide_libraries")}
+ showArrow
/>
-
-
+
+
+ updateSettings({ disableHapticFeedback })
+ }
+ />
+
+
+
);
};
diff --git a/components/settings/PluginSettings.tsx b/components/settings/PluginSettings.tsx
index f611d1a6..caac1e33 100644
--- a/components/settings/PluginSettings.tsx
+++ b/components/settings/PluginSettings.tsx
@@ -4,16 +4,19 @@ import React from "react";
import { View } from "react-native";
import { ListGroup } from "../list/ListGroup";
import { ListItem } from "../list/ListItem";
+import { useTranslation } from "react-i18next";
export const PluginSettings = () => {
const [settings, updateSettings] = useSettings();
const router = useRouter();
+ const { t } = useTranslation();
+
if (!settings) return null;
return (
-
+
router.push("/settings/jellyseerr/page")}
title={"Jellyseerr"}
@@ -24,11 +27,6 @@ export const PluginSettings = () => {
title="Marlin Search"
showArrow
/>
- router.push("/settings/popular-lists/page")}
- title="Popular Lists"
- showArrow
- />
);
diff --git a/components/settings/QuickConnect.tsx b/components/settings/QuickConnect.tsx
index 78fe7d61..834c8268 100644
--- a/components/settings/QuickConnect.tsx
+++ b/components/settings/QuickConnect.tsx
@@ -7,7 +7,8 @@ import {
BottomSheetView,
} from "@gorhom/bottom-sheet";
import { getQuickConnectApi } from "@jellyfin/sdk/lib/utils/api";
-import * as Haptics from "@/packages/expo-haptics";
+import { useTranslation } from "react-i18next";
+import { useHaptic } from "@/hooks/useHaptic";
import { useAtom } from "jotai";
import React, { useCallback, useRef, useState } from "react";
import { Alert, View, ViewProps } from "react-native";
@@ -23,6 +24,10 @@ export const QuickConnect: React.FC = ({ ...props }) => {
const [user] = useAtom(userAtom);
const [quickConnectCode, setQuickConnectCode] = useState();
const bottomSheetModalRef = useRef(null);
+ const successHapticFeedback = useHaptic("success");
+ const errorHapticFeedback = useHaptic("error");
+
+ const { t } = useTranslation();
const renderBackdrop = useCallback(
(props: BottomSheetBackdropProps) => (
@@ -43,27 +48,36 @@ export const QuickConnect: React.FC = ({ ...props }) => {
userId: user?.Id,
});
if (res.status === 200) {
- Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
- Alert.alert("Success", "Quick connect authorized");
+ successHapticFeedback();
+ Alert.alert(
+ t("home.settings.quick_connect.success"),
+ t("home.settings.quick_connect.quick_connect_autorized")
+ );
setQuickConnectCode(undefined);
bottomSheetModalRef?.current?.close();
} else {
- Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
- Alert.alert("Error", "Invalid code");
+ errorHapticFeedback();
+ Alert.alert(
+ t("home.settings.quick_connect.error"),
+ t("home.settings.quick_connect.invalid_code")
+ );
}
} catch (e) {
- Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
- Alert.alert("Error", "Invalid code");
+ errorHapticFeedback();
+ Alert.alert(
+ t("home.settings.quick_connect.error"),
+ t("home.settings.quick_connect.invalid_code")
+ );
}
}
}, [api, user, quickConnectCode]);
return (
-
+
bottomSheetModalRef?.current?.present()}
- title="Authorize Quick Connect"
+ title={t("home.settings.quick_connect.authorize_button")}
textColor="blue"
/>
@@ -83,7 +97,7 @@ export const QuickConnect: React.FC = ({ ...props }) => {
- Quick Connect
+ {t("home.settings.quick_connect.quick_connect_title")}
@@ -91,7 +105,9 @@ export const QuickConnect: React.FC = ({ ...props }) => {
= ({ ...props }) => {
onPress={authorizeQuickConnect}
color="purple"
>
- Authorize
+ {t("home.settings.quick_connect.authorize")}
diff --git a/components/settings/StorageSettings.tsx b/components/settings/StorageSettings.tsx
index 9f682e50..8525afd0 100644
--- a/components/settings/StorageSettings.tsx
+++ b/components/settings/StorageSettings.tsx
@@ -1,18 +1,19 @@
-import { Button } from "@/components/Button";
import { Text } from "@/components/common/Text";
+import { useHaptic } from "@/hooks/useHaptic";
import { useDownload } from "@/providers/DownloadProvider";
-import { clearLogs } from "@/utils/log";
import { useQuery } from "@tanstack/react-query";
import * as FileSystem from "expo-file-system";
-import * as Haptics from "@/packages/expo-haptics";
import { View } from "react-native";
-import * as Progress from "react-native-progress";
import { toast } from "sonner-native";
import { ListGroup } from "../list/ListGroup";
import { ListItem } from "../list/ListItem";
+import { useTranslation } from "react-i18next";
export const StorageSettings = () => {
const { deleteAllFiles, appSizeUsage } = useDownload();
+ const { t } = useTranslation();
+ const successHapticFeedback = useHaptic("success");
+ const errorHapticFeedback = useHaptic("error");
const { data: size, isLoading: appSizeLoading } = useQuery({
queryKey: ["appSize", appSizeUsage],
@@ -29,10 +30,10 @@ export const StorageSettings = () => {
const onDeleteClicked = async () => {
try {
await deleteAllFiles();
- Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
+ successHapticFeedback();
} catch (e) {
- Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
- toast.error("Error deleting files");
+ errorHapticFeedback();
+ toast.error(t("home.settings.toasts.error_deleting_files"));
}
};
@@ -44,11 +45,13 @@ export const StorageSettings = () => {
- Storage
+ {t("home.settings.storage.storage_title")}
{size && (
- {Number(size.total - size.remaining).bytesToReadable()} of{" "}
- {size.total?.bytesToReadable()} used
+ {t("home.settings.storage.size_used", {
+ used: Number(size.total - size.remaining).bytesToReadable(),
+ total: size.total?.bytesToReadable(),
+ })}
)}
@@ -79,18 +82,20 @@ export const StorageSettings = () => {
- App {calculatePercentage(size.app, size.total)}%
+ {t("home.settings.storage.app_usage", {
+ usedSpace: calculatePercentage(size.app, size.total),
+ })}
- Phone{" "}
- {calculatePercentage(
- size.total - size.remaining - size.app,
- size.total
- )}
- %
+ {t("home.settings.storage.device_usage", {
+ availableSpace: calculatePercentage(
+ size.total - size.remaining - size.app,
+ size.total
+ ),
+ })}
>
@@ -101,7 +106,7 @@ export const StorageSettings = () => {
diff --git a/components/settings/SubtitleToggles.tsx b/components/settings/SubtitleToggles.tsx
index 24e3d173..3d2e1117 100644
--- a/components/settings/SubtitleToggles.tsx
+++ b/components/settings/SubtitleToggles.tsx
@@ -7,13 +7,19 @@ import { ListGroup } from "../list/ListGroup";
import { ListItem } from "../list/ListItem";
import { Ionicons } from "@expo/vector-icons";
import { SubtitlePlaybackMode } from "@jellyfin/sdk/lib/generated-client";
+import { useTranslation } from "react-i18next";
+import {useSettings} from "@/utils/atoms/settings";
+import {Stepper} from "@/components/inputs/Stepper";
+import Dropdown from "@/components/common/Dropdown";
interface Props extends ViewProps {}
export const SubtitleToggles: React.FC = ({ ...props }) => {
const media = useMedia();
+ const [_, __, pluginSettings] = useSettings();
const { settings, updateSettings } = media;
const cultures = media.cultures;
+ const { t } = useTranslation();
if (!settings) return null;
@@ -25,22 +31,33 @@ export const SubtitleToggles: React.FC = ({ ...props }) => {
SubtitlePlaybackMode.None,
];
+ const subtitleModeKeys = {
+ [SubtitlePlaybackMode.Default]: "home.settings.subtitles.modes.Default",
+ [SubtitlePlaybackMode.Smart]: "home.settings.subtitles.modes.Smart",
+ [SubtitlePlaybackMode.OnlyForced]: "home.settings.subtitles.modes.OnlyForced",
+ [SubtitlePlaybackMode.Always]: "home.settings.subtitles.modes.Always",
+ [SubtitlePlaybackMode.None]: "home.settings.subtitles.modes.None",
+ };
+
return (
- Configure subtitle preferences.
+ {t("home.settings.subtitles.subtitle_hint")}
}
>
-
-
-
+
+ item?.ThreeLetterISOLanguageName ?? "unknown"}
+ titleExtractor={(item) => item?.DisplayName}
+ title={
- {settings?.defaultSubtitleLanguage?.DisplayName || "None"}
+ {settings?.defaultSubtitleLanguage?.DisplayName || t("home.settings.subtitles.none")}
= ({ ...props }) => {
color="#5A5960"
/>
-
-
- Languages
- {
- updateSettings({
- defaultSubtitleLanguage: null,
- });
- }}
- >
- None
-
- {cultures?.map((l) => (
- {
- updateSettings({
- defaultSubtitleLanguage: l,
- });
- }}
- >
-
- {l.DisplayName}
-
-
- ))}
-
-
+ }
+ label={t("home.settings.subtitles.language")}
+ onSelected={(defaultSubtitleLanguage) =>
+ updateSettings({
+ defaultSubtitleLanguage: defaultSubtitleLanguage.DisplayName === t("home.settings.subtitles.none")
+ ? null
+ : defaultSubtitleLanguage
+ })
+ }
+ />
-
-
-
+
+ t(subtitleModeKeys[item]) || String(item)}
+ title={
- {settings?.subtitleMode || "Loading"}
+ {t(subtitleModeKeys[settings?.subtitleMode]) || t("home.settings.subtitles.loading")}
= ({ ...props }) => {
color="#5A5960"
/>
-
-
- Subtitle Mode
- {subtitleModes?.map((l) => (
- {
- updateSettings({
- subtitleMode: l,
- });
- }}
- >
- {l}
-
- ))}
-
-
+ }
+ label={t("home.settings.subtitles.subtitle_mode")}
+ onSelected={(subtitleMode) =>
+ updateSettings({subtitleMode})
+ }
+ />
-
+
updateSettings({ rememberSubtitleSelections: value })
}
/>
-
-
-
- updateSettings({
- subtitleSize: Math.max(0, settings.subtitleSize - 5),
- })
- }
- className="w-8 h-8 bg-neutral-800 rounded-l-lg flex items-center justify-center"
- >
- -
-
-
- {settings.subtitleSize}
-
-
- updateSettings({
- subtitleSize: Math.min(120, settings.subtitleSize + 5),
- })
- }
- >
- +
-
-
+
+ updateSettings({subtitleSize})}
+ />
diff --git a/components/settings/UserInfo.tsx b/components/settings/UserInfo.tsx
index c42502ce..fdd3db44 100644
--- a/components/settings/UserInfo.tsx
+++ b/components/settings/UserInfo.tsx
@@ -7,12 +7,14 @@ import { useAtom } from "jotai";
import Constants from "expo-constants";
import Application from "expo-application";
import { ListGroup } from "../list/ListGroup";
+import { useTranslation } from "react-i18next";
interface Props extends ViewProps {}
export const UserInfo: React.FC = ({ ...props }) => {
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
+ const { t } = useTranslation();
const version =
Application?.nativeApplicationVersion ||
@@ -21,11 +23,11 @@ export const UserInfo: React.FC = ({ ...props }) => {
return (
-
-
-
-
-
+
+
+
+
+
);
diff --git a/components/video-player/controls/Controls.tsx b/components/video-player/controls/Controls.tsx
index b82455ff..f209a411 100644
--- a/components/video-player/controls/Controls.tsx
+++ b/components/video-player/controls/Controls.tsx
@@ -1,8 +1,8 @@
-import React, { useCallback, useEffect, useRef, useState } from "react";
import { Text } from "@/components/common/Text";
import { Loader } from "@/components/Loader";
import { useAdjacentItems } from "@/hooks/useAdjacentEpisodes";
import { useCreditSkipper } from "@/hooks/useCreditSkipper";
+import { useHaptic } from "@/hooks/useHaptic";
import { useIntroSkipper } from "@/hooks/useIntroSkipper";
import { useTrickplay } from "@/hooks/useTrickplay";
import {
@@ -29,12 +29,13 @@ import {
BaseItemDto,
MediaSourceInfo,
} from "@jellyfin/sdk/lib/generated-client";
-import * as Haptics from "@/packages/expo-haptics";
import { Image } from "expo-image";
import { useLocalSearchParams, useRouter } from "expo-router";
+import * as ScreenOrientation from "expo-screen-orientation";
import { useAtom } from "jotai";
import { debounce } from "lodash";
-import { Dimensions, Pressable, TouchableOpacity, View } from "react-native";
+import React, { useCallback, useEffect, useRef, useState } from "react";
+import { TouchableOpacity, useWindowDimensions, View } from "react-native";
import { Slider } from "react-native-awesome-slider";
import {
runOnJS,
@@ -42,10 +43,7 @@ import {
useAnimatedReaction,
useSharedValue,
} from "react-native-reanimated";
-import {
- SafeAreaView,
- useSafeAreaInsets,
-} from "react-native-safe-area-context";
+import { useSafeAreaInsets } from "react-native-safe-area-context";
import { VideoRef } from "react-native-video";
import AudioSlider from "./AudioSlider";
import BrightnessSlider from "./BrightnessSlider";
@@ -56,6 +54,8 @@ import DropdownViewTranscoding from "./dropdown/DropdownViewTranscoding";
import { EpisodeList } from "./EpisodeList";
import NextEpisodeCountDownButton from "./NextEpisodeCountDownButton";
import SkipButton from "./SkipButton";
+import { useControlsTimeout } from "./useControlsTimeout";
+import { VideoTouchOverlay } from "./VideoTouchOverlay";
interface Props {
item: BaseItemDto;
@@ -86,6 +86,8 @@ interface Props {
isVlc?: boolean;
}
+const CONTROLS_TIMEOUT = 4000;
+
export const Controls: React.FC = ({
item,
seek,
@@ -118,6 +120,13 @@ export const Controls: React.FC = ({
const insets = useSafeAreaInsets();
const [api] = useAtom(apiAtom);
+ const [episodeView, setEpisodeView] = useState(false);
+ const [isSliding, setIsSliding] = useState(false);
+
+ // Used when user changes audio through audio button on device.
+ const [showAudioSlider, setShowAudioSlider] = useState(false);
+
+ const { height: screenHeight, width: screenWidth } = useWindowDimensions();
const { previousItem, nextItem } = useAdjacentItems({ item });
const {
trickPlayUrl,
@@ -135,6 +144,23 @@ export const Controls: React.FC = ({
const wasPlayingRef = useRef(false);
const lastProgressRef = useRef(0);
+ const lightHapticFeedback = useHaptic("light");
+
+ useEffect(() => {
+ prefetchAllTrickplayImages();
+ }, []);
+
+ useEffect(() => {
+ if (item) {
+ progress.value = isVlc
+ ? ticksToMs(item?.UserData?.PlaybackPositionTicks)
+ : item?.UserData?.PlaybackPositionTicks || 0;
+ max.value = isVlc
+ ? ticksToMs(item.RunTimeTicks || 0)
+ : item.RunTimeTicks || 0;
+ }
+ }, [item, isVlc]);
+
const { bitrateValue, subtitleIndex, audioIndex } = useLocalSearchParams<{
bitrateValue: string;
audioIndex: string;
@@ -160,7 +186,7 @@ export const Controls: React.FC = ({
const goToPreviousItem = useCallback(() => {
if (!previousItem || !settings) return;
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
const previousIndexes: previousIndexes = {
subtitleIndex: subtitleIndex ? parseInt(subtitleIndex) : undefined,
@@ -198,7 +224,7 @@ export const Controls: React.FC = ({
const goToNextItem = useCallback(() => {
if (!nextItem || !settings) return;
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
const previousIndexes: previousIndexes = {
subtitleIndex: subtitleIndex ? parseInt(subtitleIndex) : undefined,
@@ -260,20 +286,19 @@ export const Controls: React.FC = ({
[updateTimes]
);
- useEffect(() => {
- if (item) {
- progress.value = isVlc
- ? ticksToMs(item?.UserData?.PlaybackPositionTicks)
- : item?.UserData?.PlaybackPositionTicks || 0;
- max.value = isVlc
- ? ticksToMs(item.RunTimeTicks || 0)
- : item.RunTimeTicks || 0;
- }
- }, [item, isVlc]);
-
- useEffect(() => {
- prefetchAllTrickplayImages();
+ const hideControls = useCallback(() => {
+ setShowControls(false);
+ setShowAudioSlider(false);
}, []);
+
+ const { handleControlsInteraction } = useControlsTimeout({
+ showControls,
+ isSliding,
+ episodeView,
+ onHideControls: hideControls,
+ timeout: CONTROLS_TIMEOUT,
+ });
+
const toggleControls = () => {
if (showControls) {
setShowAudioSlider(false);
@@ -294,16 +319,13 @@ export const Controls: React.FC = ({
isSeeking.value = true;
}, [showControls, isPlaying]);
- const [isSliding, setIsSliding] = useState(false);
const handleSliderComplete = useCallback(
async (value: number) => {
isSeeking.value = false;
progress.value = value;
setIsSliding(false);
- await seek(
- Math.max(0, Math.floor(isVlc ? value : ticksToSeconds(value)))
- );
+ seek(Math.max(0, Math.floor(isVlc ? value : ticksToSeconds(value))));
if (wasPlayingRef.current === true) play();
},
[isVlc]
@@ -326,14 +348,14 @@ export const Controls: React.FC = ({
const handleSkipBackward = useCallback(async () => {
if (!settings?.rewindSkipTime) return;
wasPlayingRef.current = isPlaying;
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
try {
const curr = progress.value;
if (curr !== undefined) {
const newTime = isVlc
? Math.max(0, curr - secondsToMs(settings.rewindSkipTime))
: Math.max(0, ticksToSeconds(curr) - settings.rewindSkipTime);
- await seek(newTime);
+ seek(newTime);
if (wasPlayingRef.current === true) play();
}
} catch (error) {
@@ -344,14 +366,14 @@ export const Controls: React.FC = ({
const handleSkipForward = useCallback(async () => {
if (!settings?.forwardSkipTime) return;
wasPlayingRef.current = isPlaying;
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
try {
const curr = progress.value;
if (curr !== undefined) {
const newTime = isVlc
? curr + secondsToMs(settings.forwardSkipTime)
: ticksToSeconds(curr) + settings.forwardSkipTime;
- await seek(Math.max(0, newTime));
+ seek(Math.max(0, newTime));
if (wasPlayingRef.current === true) play();
}
} catch (error) {
@@ -359,11 +381,62 @@ export const Controls: React.FC = ({
}
}, [settings, isPlaying, isVlc]);
+ const goToItem = useCallback(
+ async (itemId: string) => {
+ try {
+ const gotoItem = await getItemById(api, itemId);
+ if (!settings || !gotoItem) return;
+
+ lightHapticFeedback();
+
+ const previousIndexes: previousIndexes = {
+ subtitleIndex: subtitleIndex ? parseInt(subtitleIndex) : undefined,
+ audioIndex: audioIndex ? parseInt(audioIndex) : undefined,
+ };
+
+ const {
+ mediaSource: newMediaSource,
+ audioIndex: defaultAudioIndex,
+ subtitleIndex: defaultSubtitleIndex,
+ } = getDefaultPlaySettings(
+ gotoItem,
+ settings,
+ previousIndexes,
+ mediaSource ?? undefined
+ );
+
+ const queryParams = new URLSearchParams({
+ itemId: gotoItem.Id ?? "", // Ensure itemId is a string
+ audioIndex: defaultAudioIndex?.toString() ?? "",
+ subtitleIndex: defaultSubtitleIndex?.toString() ?? "",
+ mediaSourceId: newMediaSource?.Id ?? "", // Ensure mediaSourceId is a string
+ bitrateValue: bitrateValue.toString(),
+ }).toString();
+
+ if (!bitrateValue) {
+ // @ts-expect-error
+ router.replace(`player/direct-player?${queryParams}`);
+ return;
+ }
+ // @ts-expect-error
+ router.replace(`player/transcoding-player?${queryParams}`);
+ } catch (error) {
+ console.error("Error in gotoEpisode:", error);
+ }
+ },
+ [settings, subtitleIndex, audioIndex]
+ );
+
const toggleIgnoreSafeAreas = useCallback(() => {
setIgnoreSafeAreas((prev) => !prev);
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
}, []);
+ const switchOnEpisodeMode = useCallback(() => {
+ setEpisodeView(true);
+ if (isPlaying) togglePlay();
+ }, [isPlaying, togglePlay]);
+
const memoizedRenderBubble = useCallback(() => {
if (!trickPlayUrl || !trickplayInfo) {
return null;
@@ -376,12 +449,11 @@ export const Controls: React.FC = ({
= ({
);
}, [trickPlayUrl, trickplayInfo, time]);
- const [EpisodeView, setEpisodeView] = useState(false);
-
- const switchOnEpisodeMode = () => {
- setEpisodeView(true);
- if (isPlaying) togglePlay();
- };
-
- const goToItem = useCallback(
- async (itemId: string) => {
- try {
- const gotoItem = await getItemById(api, itemId);
- if (!settings || !gotoItem) return;
-
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
-
- const previousIndexes: previousIndexes = {
- subtitleIndex: subtitleIndex ? parseInt(subtitleIndex) : undefined,
- audioIndex: audioIndex ? parseInt(audioIndex) : undefined,
- };
-
- const {
- mediaSource: newMediaSource,
- audioIndex: defaultAudioIndex,
- subtitleIndex: defaultSubtitleIndex,
- } = getDefaultPlaySettings(
- gotoItem,
- settings,
- previousIndexes,
- mediaSource ?? undefined
- );
-
- const queryParams = new URLSearchParams({
- itemId: gotoItem.Id ?? "", // Ensure itemId is a string
- audioIndex: defaultAudioIndex?.toString() ?? "",
- subtitleIndex: defaultSubtitleIndex?.toString() ?? "",
- mediaSourceId: newMediaSource?.Id ?? "", // Ensure mediaSourceId is a string
- bitrateValue: bitrateValue.toString(),
- }).toString();
-
- if (!bitrateValue) {
- // @ts-expect-error
- router.replace(`player/direct-player?${queryParams}`);
- return;
- }
- // @ts-expect-error
- router.replace(`player/transcoding-player?${queryParams}`);
- } catch (error) {
- console.error("Error in gotoEpisode:", error);
- }
- },
- [settings, subtitleIndex, audioIndex]
- );
-
- // Used when user changes audio through audio button on device.
- const [showAudioSlider, setShowAudioSlider] = useState(false);
-
return (
- {EpisodeView ? (
+ {episodeView ? (
setEpisodeView(false)}
@@ -497,19 +513,12 @@ export const Controls: React.FC = ({
/>
) : (
<>
- {
- toggleControls();
- }}
- style={{
- position: "absolute",
- width: Dimensions.get("window").width,
- height: Dimensions.get("window").height,
- backgroundColor: "black",
- opacity: showControls ? 0.5 : 0,
- }}
- >
-
+
= ({
top: settings?.safeAreaInControlsEnabled ? insets.top : 0,
right: settings?.safeAreaInControlsEnabled ? insets.right : 0,
width: settings?.safeAreaInControlsEnabled
- ? Dimensions.get("window").width - insets.left - insets.right
- : Dimensions.get("window").width,
+ ? screenWidth - insets.left - insets.right
+ : screenWidth,
opacity: showControls ? 1 : 0,
},
]}
pointerEvents={showControls ? "auto" : "none"}
- className={`flex flex-row w-full p-4 `}
+ className={`flex flex-row w-full pt-2`}
>
= ({
onPress={() => {
switchOnEpisodeMode();
}}
- className="aspect-square flex flex-col bg-neutral-800/90 rounded-xl items-center justify-center p-2"
+ className="aspect-square flex flex-col rounded-xl items-center justify-center p-2"
>
@@ -555,7 +564,7 @@ export const Controls: React.FC = ({
{previousItem && !offline && (
@@ -564,30 +573,33 @@ export const Controls: React.FC = ({
{nextItem && !offline && (
)}
- {mediaSource?.TranscodingUrl && (
-
-
-
- )}
+ {/* {mediaSource?.TranscodingUrl && ( */}
+
+
+
+ {/* )} */}
{
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
+ await ScreenOrientation.lockAsync(
+ ScreenOrientation.OrientationLock.PORTRAIT_UP
+ );
router.back();
}}
- className="aspect-square flex flex-col bg-neutral-800/90 rounded-xl items-center justify-center p-2"
+ className="aspect-square flex flex-col rounded-xl items-center justify-center p-2"
>
@@ -717,10 +729,11 @@ export const Controls: React.FC = ({
bottom: settings?.safeAreaInControlsEnabled ? insets.bottom : 0,
},
]}
- className={`flex flex-col p-4`}
+ className={`flex flex-col px-2`}
+ onTouchStart={handleControlsInteraction}
>
= ({
}}
pointerEvents={showControls ? "box-none" : "none"}
>
- {item?.Name}
{item?.Type === "Episode" && (
- {item.SeriesName}
+
+ {`${item.SeriesName} - ${item.SeasonName} Episode ${item.IndexNumber}`}
+
)}
+ {item?.Name}
{item?.Type === "Movie" && (
{item?.ProductionYear}
@@ -772,7 +787,7 @@ export const Controls: React.FC = ({
= ({
bubbleTextColor: "#666",
heartbeatColor: "#999",
}}
- renderThumb={() => (
-
- )}
+ renderThumb={() => null}
cache={cacheProgress}
onSlidingStart={handleSliderStart}
onSlidingComplete={handleSliderComplete}
@@ -815,7 +818,7 @@ export const Controls: React.FC = ({
minimumValue={min}
maximumValue={max}
/>
-
+
{formatTimeString(currentTime, isVlc ? "ms" : "s")}
diff --git a/components/video-player/controls/EpisodeList.tsx b/components/video-player/controls/EpisodeList.tsx
index db7c5c71..422a2fc3 100644
--- a/components/video-player/controls/EpisodeList.tsx
+++ b/components/video-player/controls/EpisodeList.tsx
@@ -1,26 +1,26 @@
-import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
-import { runtimeTicksToSeconds } from "@/utils/time";
-import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
-import { useQuery, useQueryClient } from "@tanstack/react-query";
-import { atom, useAtom } from "jotai";
-import { useEffect, useMemo, useState, useRef } from "react";
-import { View, TouchableOpacity } from "react-native";
-import { getTvShowsApi } from "@jellyfin/sdk/lib/utils/api";
-import { getUserItemData } from "@/utils/jellyfin/user-library/getUserItemData";
-import { Ionicons } from "@expo/vector-icons";
-import { Loader } from "@/components/Loader";
-import ContinueWatchingPoster from "@/components/ContinueWatchingPoster";
-import { Text } from "@/components/common/Text";
-import { DownloadSingleItem } from "@/components/DownloadItem";
-import { useSafeAreaInsets } from "react-native-safe-area-context";
import {
HorizontalScroll,
HorizontalScrollRef,
} from "@/components/common/HorrizontalScroll";
+import { Text } from "@/components/common/Text";
+import ContinueWatchingPoster from "@/components/ContinueWatchingPoster";
+import { DownloadSingleItem } from "@/components/DownloadItem";
+import { Loader } from "@/components/Loader";
import {
SeasonDropdown,
SeasonIndexState,
} from "@/components/series/SeasonDropdown";
+import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
+import { getUserItemData } from "@/utils/jellyfin/user-library/getUserItemData";
+import { runtimeTicksToSeconds } from "@/utils/time";
+import { Ionicons } from "@expo/vector-icons";
+import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
+import { getTvShowsApi } from "@jellyfin/sdk/lib/utils/api";
+import { useQuery, useQueryClient } from "@tanstack/react-query";
+import { atom, useAtom } from "jotai";
+import { useEffect, useMemo, useRef, useState } from "react";
+import { TouchableOpacity, View } from "react-native";
+import { useSafeAreaInsets } from "react-native-safe-area-context";
type Props = {
item: BaseItemDto;
diff --git a/components/video-player/controls/NextEpisodeCountDownButton.tsx b/components/video-player/controls/NextEpisodeCountDownButton.tsx
index 6f5239e6..73e3f828 100644
--- a/components/video-player/controls/NextEpisodeCountDownButton.tsx
+++ b/components/video-player/controls/NextEpisodeCountDownButton.tsx
@@ -9,6 +9,7 @@ import Animated, {
runOnJS,
} from "react-native-reanimated";
import { Colors } from "@/constants/Colors";
+import { useTranslation } from "react-i18next";
interface NextEpisodeCountDownButtonProps extends TouchableOpacityProps {
onFinish?: () => void;
@@ -59,6 +60,8 @@ const NextEpisodeCountDownButton: React.FC = ({
}
};
+ const { t } = useTranslation();
+
if (!show) {
return null;
}
@@ -71,7 +74,7 @@ const NextEpisodeCountDownButton: React.FC = ({
>
- Next Episode
+ {t("player.next_episode")}
);
diff --git a/components/video-player/controls/VideoTouchOverlay.tsx b/components/video-player/controls/VideoTouchOverlay.tsx
new file mode 100644
index 00000000..85385acf
--- /dev/null
+++ b/components/video-player/controls/VideoTouchOverlay.tsx
@@ -0,0 +1,38 @@
+import { Pressable } from "react-native";
+import { useTapDetection } from "./useTapDetection";
+
+interface Props {
+ screenWidth: number;
+ screenHeight: number;
+ showControls: boolean;
+ onToggleControls: () => void;
+}
+
+export const VideoTouchOverlay = ({
+ screenWidth,
+ screenHeight,
+ showControls,
+ onToggleControls,
+}: Props) => {
+ const { handleTouchStart, handleTouchEnd } = useTapDetection({
+ onValidTap: onToggleControls,
+ });
+
+ return (
+
+ );
+};
diff --git a/components/video-player/controls/dropdown/DropdownViewDirect.tsx b/components/video-player/controls/dropdown/DropdownViewDirect.tsx
index c75104cf..9c853c26 100644
--- a/components/video-player/controls/dropdown/DropdownViewDirect.tsx
+++ b/components/video-player/controls/dropdown/DropdownViewDirect.tsx
@@ -74,7 +74,7 @@ const DropdownViewDirect: React.FC = ({
return (
-
+
diff --git a/components/video-player/controls/dropdown/DropdownViewTranscoding.tsx b/components/video-player/controls/dropdown/DropdownViewTranscoding.tsx
index 09ab8ef2..f42d726a 100644
--- a/components/video-player/controls/dropdown/DropdownViewTranscoding.tsx
+++ b/components/video-player/controls/dropdown/DropdownViewTranscoding.tsx
@@ -121,7 +121,7 @@ const DropdownView: React.FC = ({ showControls }) => {
-
+
diff --git a/components/video-player/controls/useControlsTimeout.ts b/components/video-player/controls/useControlsTimeout.ts
new file mode 100644
index 00000000..ac10fff3
--- /dev/null
+++ b/components/video-player/controls/useControlsTimeout.ts
@@ -0,0 +1,56 @@
+import { useEffect, useRef } from "react";
+
+interface UseControlsTimeoutProps {
+ showControls: boolean;
+ isSliding: boolean;
+ episodeView: boolean;
+ onHideControls: () => void;
+ timeout?: number;
+}
+
+export const useControlsTimeout = ({
+ showControls,
+ isSliding,
+ episodeView,
+ onHideControls,
+ timeout = 4000,
+}: UseControlsTimeoutProps) => {
+ const controlsTimeoutRef = useRef();
+
+ useEffect(() => {
+ const resetControlsTimeout = () => {
+ if (controlsTimeoutRef.current) {
+ clearTimeout(controlsTimeoutRef.current);
+ }
+
+ if (showControls && !isSliding && !episodeView) {
+ controlsTimeoutRef.current = setTimeout(() => {
+ onHideControls();
+ }, timeout);
+ }
+ };
+
+ resetControlsTimeout();
+
+ return () => {
+ if (controlsTimeoutRef.current) {
+ clearTimeout(controlsTimeoutRef.current);
+ }
+ };
+ }, [showControls, isSliding, episodeView, timeout, onHideControls]);
+
+ const handleControlsInteraction = () => {
+ if (showControls) {
+ if (controlsTimeoutRef.current) {
+ clearTimeout(controlsTimeoutRef.current);
+ }
+ controlsTimeoutRef.current = setTimeout(() => {
+ onHideControls();
+ }, timeout);
+ }
+ };
+
+ return {
+ handleControlsInteraction,
+ };
+};
diff --git a/components/video-player/controls/useTapDetection.tsx b/components/video-player/controls/useTapDetection.tsx
new file mode 100644
index 00000000..041e6d39
--- /dev/null
+++ b/components/video-player/controls/useTapDetection.tsx
@@ -0,0 +1,48 @@
+import { useRef } from "react";
+import { GestureResponderEvent } from "react-native";
+
+interface TapDetectionOptions {
+ maxDuration?: number;
+ maxDistance?: number;
+ onValidTap?: () => void;
+}
+
+export const useTapDetection = ({
+ maxDuration = 200,
+ maxDistance = 10,
+ onValidTap,
+}: TapDetectionOptions = {}) => {
+ const touchStartTime = useRef(0);
+ const touchStartPosition = useRef({ x: 0, y: 0 });
+
+ const handleTouchStart = (event: GestureResponderEvent) => {
+ touchStartTime.current = Date.now();
+ touchStartPosition.current = {
+ x: event.nativeEvent.pageX,
+ y: event.nativeEvent.pageY,
+ };
+ };
+
+ const handleTouchEnd = (event: GestureResponderEvent) => {
+ const touchEndTime = Date.now();
+ const touchEndPosition = {
+ x: event.nativeEvent.pageX,
+ y: event.nativeEvent.pageY,
+ };
+
+ const touchDuration = touchEndTime - touchStartTime.current;
+ const touchDistance = Math.sqrt(
+ Math.pow(touchEndPosition.x - touchStartPosition.current.x, 2) +
+ Math.pow(touchEndPosition.y - touchStartPosition.current.y, 2)
+ );
+
+ if (touchDuration < maxDuration && touchDistance < maxDistance) {
+ onValidTap?.();
+ }
+ };
+
+ return {
+ handleTouchStart,
+ handleTouchEnd,
+ };
+};
diff --git a/components/vlc/VideoDebugInfo.tsx b/components/vlc/VideoDebugInfo.tsx
index 5ae04517..8a37659a 100644
--- a/components/vlc/VideoDebugInfo.tsx
+++ b/components/vlc/VideoDebugInfo.tsx
@@ -6,6 +6,7 @@ import React, { useEffect, useState } from "react";
import { TouchableOpacity, View, ViewProps } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { Text } from "../common/Text";
+import { useTranslation } from "react-i18next";
interface Props extends ViewProps {
playerRef: React.RefObject;
@@ -32,6 +33,8 @@ export const VideoDebugInfo: React.FC = ({ playerRef, ...props }) => {
const insets = useSafeAreaInsets();
+ const { t } = useTranslation();
+
return (
= ({ playerRef, ...props }) => {
}}
{...props}
>
- Playback State:
- Audio Tracks:
+ {t("player.playback_state")}
+ {t("player.audio_tracks")}
{audioTracks &&
audioTracks.map((track, index) => (
- {track.name} (Index: {track.index})
+ {track.name} ({t("player.index")} {track.index})
))}
- Subtitle Tracks:
+ {t("player.subtitles_tracks")}
{subtitleTracks &&
subtitleTracks.map((track, index) => (
- {track.name} (Index: {track.index})
+ {track.name} ({t("player.index")} {track.index})
))}
= ({ playerRef, ...props }) => {
}
}}
>
- Refresh Tracks
+ {t("player.refresh_tracks")}
);
diff --git a/eas.json b/eas.json
index 8ce5fc71..9821cceb 100644
--- a/eas.json
+++ b/eas.json
@@ -22,13 +22,13 @@
}
},
"production": {
- "channel": "0.24.0",
+ "channel": "0.25.0",
"android": {
"image": "latest"
}
},
"production-apk": {
- "channel": "0.24.0",
+ "channel": "0.25.0",
"android": {
"buildType": "apk",
"image": "latest"
diff --git a/hooks/useCreditSkipper.ts b/hooks/useCreditSkipper.ts
index 37a82de6..14a77161 100644
--- a/hooks/useCreditSkipper.ts
+++ b/hooks/useCreditSkipper.ts
@@ -5,7 +5,7 @@ import { apiAtom } from "@/providers/JellyfinProvider";
import { getAuthHeaders } from "@/utils/jellyfin/jellyfin";
import { writeToLog } from "@/utils/log";
import { msToSeconds, secondsToMs } from "@/utils/time";
-import * as Haptics from "@/packages/expo-haptics";
+import { useHaptic } from "./useHaptic";
interface CreditTimestamps {
Introduction: {
@@ -29,6 +29,7 @@ export const useCreditSkipper = (
) => {
const [api] = useAtom(apiAtom);
const [showSkipCreditButton, setShowSkipCreditButton] = useState(false);
+ const lightHapticFeedback = useHaptic("light");
if (isVlc) {
currentTime = msToSeconds(currentTime);
@@ -79,7 +80,7 @@ export const useCreditSkipper = (
if (!creditTimestamps) return;
console.log(`Skipping credits to ${creditTimestamps.Credits.End}`);
try {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
wrappedSeek(creditTimestamps.Credits.End);
setTimeout(() => {
play();
diff --git a/hooks/useDefaultPlaySettings.ts b/hooks/useDefaultPlaySettings.ts
index 5c2d9cc6..39009305 100644
--- a/hooks/useDefaultPlaySettings.ts
+++ b/hooks/useDefaultPlaySettings.ts
@@ -6,7 +6,7 @@ import {
} from "@jellyfin/sdk/lib/generated-client";
import { useMemo } from "react";
-// Used only for intial play settings.
+// Used only for initial play settings.
const useDefaultPlaySettings = (
item: BaseItemDto,
settings: Settings | null
diff --git a/hooks/useHaptic.ts b/hooks/useHaptic.ts
new file mode 100644
index 00000000..5e7f7e65
--- /dev/null
+++ b/hooks/useHaptic.ts
@@ -0,0 +1,63 @@
+import { useCallback, useMemo } from "react";
+import { Platform } from "react-native";
+import { useSettings } from "@/utils/atoms/settings";
+const Haptics = !Platform.isTV ? require("expo-haptics") : null;
+
+export type HapticFeedbackType =
+ | "light"
+ | "medium"
+ | "heavy"
+ | "selection"
+ | "success"
+ | "warning"
+ | "error";
+
+export const useHaptic = (feedbackType: HapticFeedbackType = "selection") => {
+ const [settings] = useSettings();
+
+ if (Platform.isTV) {
+ return () => {};
+ }
+
+ const createHapticHandler = useCallback(
+ (type: Haptics.ImpactFeedbackStyle) => {
+ return Platform.OS === "web" || Platform.isTV
+ ? () => {}
+ : () => Haptics.impactAsync(type);
+ },
+ []
+ );
+ const createNotificationFeedback = useCallback(
+ (type: Haptics.NotificationFeedbackType) => {
+ return Platform.OS === "web" || Platform.isTV
+ ? () => {}
+ : () => Haptics.notificationAsync(type);
+ },
+ []
+ );
+
+ const hapticHandlers = useMemo(
+ () => ({
+ light: createHapticHandler(Haptics.ImpactFeedbackStyle.Light),
+ medium: createHapticHandler(Haptics.ImpactFeedbackStyle.Medium),
+ heavy: createHapticHandler(Haptics.ImpactFeedbackStyle.Heavy),
+ selection:
+ Platform.OS === "web" || Platform.isTV
+ ? () => {}
+ : Haptics.selectionAsync,
+ success: createNotificationFeedback(
+ Haptics.NotificationFeedbackType.Success
+ ),
+ warning: createNotificationFeedback(
+ Haptics.NotificationFeedbackType.Warning
+ ),
+ error: createNotificationFeedback(Haptics.NotificationFeedbackType.Error),
+ }),
+ [createHapticHandler, createNotificationFeedback]
+ );
+
+ if (settings?.disableHapticFeedback) {
+ return () => {};
+ }
+ return hapticHandlers[feedbackType];
+};
diff --git a/hooks/useIntroSkipper.ts b/hooks/useIntroSkipper.ts
index 80ea1bf9..b41872dc 100644
--- a/hooks/useIntroSkipper.ts
+++ b/hooks/useIntroSkipper.ts
@@ -5,7 +5,7 @@ import { apiAtom } from "@/providers/JellyfinProvider";
import { getAuthHeaders } from "@/utils/jellyfin/jellyfin";
import { writeToLog } from "@/utils/log";
import { msToSeconds, secondsToMs } from "@/utils/time";
-import * as Haptics from "@/packages/expo-haptics";
+import { useHaptic } from "./useHaptic";
interface IntroTimestamps {
EpisodeId: string;
@@ -33,6 +33,7 @@ export const useIntroSkipper = (
if (isVlc) {
currentTime = msToSeconds(currentTime);
}
+ const lightHapticFeedback = useHaptic("light");
const wrappedSeek = (seconds: number) => {
if (isVlc) {
@@ -78,7 +79,7 @@ export const useIntroSkipper = (
const skipIntro = useCallback(() => {
if (!introTimestamps) return;
try {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
wrappedSeek(introTimestamps.IntroEnd);
setTimeout(() => {
play();
diff --git a/hooks/useJellyfinDiscovery.tsx b/hooks/useJellyfinDiscovery.tsx
new file mode 100644
index 00000000..963dfe81
--- /dev/null
+++ b/hooks/useJellyfinDiscovery.tsx
@@ -0,0 +1,106 @@
+import { useState, useCallback } from "react";
+import dgram from "react-native-udp";
+
+const JELLYFIN_DISCOVERY_PORT = 7359;
+const DISCOVERY_MESSAGE = "Who is JellyfinServer?";
+
+interface ServerInfo {
+ address: string;
+ port: number;
+ serverId?: string;
+ serverName?: string;
+}
+
+export const useJellyfinDiscovery = () => {
+ const [servers, setServers] = useState([]);
+ const [isSearching, setIsSearching] = useState(false);
+
+ const startDiscovery = useCallback(() => {
+ setIsSearching(true);
+ setServers([]);
+
+ const discoveredServers = new Set();
+ let discoveryTimeout: NodeJS.Timeout;
+
+ const socket = dgram.createSocket({
+ type: "udp4",
+ reusePort: true,
+ debug: __DEV__,
+ });
+
+ socket.on("error", (err) => {
+ console.error("Socket error:", err);
+ socket.close();
+ setIsSearching(false);
+ });
+
+ socket.bind(0, () => {
+ console.log("UDP socket bound successfully");
+
+ try {
+ socket.setBroadcast(true);
+ const messageBuffer = new TextEncoder().encode(DISCOVERY_MESSAGE);
+
+ socket.send(
+ messageBuffer,
+ 0,
+ messageBuffer.length,
+ JELLYFIN_DISCOVERY_PORT,
+ "255.255.255.255",
+ (err) => {
+ if (err) {
+ console.error("Failed to send discovery message:", err);
+ return;
+ }
+ console.log("Discovery message sent successfully");
+ }
+ );
+
+ discoveryTimeout = setTimeout(() => {
+ setIsSearching(false);
+ socket.close();
+ }, 5000);
+ } catch (error) {
+ console.error("Error during discovery:", error);
+ setIsSearching(false);
+ }
+ });
+
+ socket.on("message", (msg, rinfo: any) => {
+ if (discoveredServers.has(rinfo.address)) {
+ return;
+ }
+
+ try {
+ const response = new TextDecoder().decode(msg);
+ const serverInfo = JSON.parse(response);
+ discoveredServers.add(rinfo.address);
+
+ const newServer: ServerInfo = {
+ address: `http://${rinfo.address}:${serverInfo.Port || 8096}`,
+ port: serverInfo.Port || 8096,
+ serverId: serverInfo.Id,
+ serverName: serverInfo.Name,
+ };
+
+ setServers((prev) => [...prev, newServer]);
+ } catch (error) {
+ console.error("Error parsing server response:", error);
+ }
+ });
+
+ return () => {
+ clearTimeout(discoveryTimeout);
+ if (isSearching) {
+ setIsSearching(false);
+ }
+ socket.close();
+ };
+ }, []);
+
+ return {
+ servers,
+ isSearching,
+ startDiscovery,
+ };
+};
diff --git a/hooks/useJellyseerr.ts b/hooks/useJellyseerr.ts
index 815510fa..e56ab277 100644
--- a/hooks/useJellyseerr.ts
+++ b/hooks/useJellyseerr.ts
@@ -28,11 +28,18 @@ import Issue from "@/utils/jellyseerr/server/entity/Issue";
import { RTRating } from "@/utils/jellyseerr/server/api/rating/rottentomatoes";
import { writeErrorLog } from "@/utils/log";
import DiscoverSlider from "@/utils/jellyseerr/server/entity/DiscoverSlider";
+import { t } from "i18next";
import {
CombinedCredit,
PersonDetails,
} from "@/utils/jellyseerr/server/models/Person";
import { useQueryClient } from "@tanstack/react-query";
+import {GenreSliderItem} from "@/utils/jellyseerr/server/interfaces/api/discoverInterfaces";
+import {UserResultsResponse} from "@/utils/jellyseerr/server/interfaces/api/userInterfaces";
+import {
+ ServiceCommonServer,
+ ServiceCommonServerWithDetails
+} from "@/utils/jellyseerr/server/interfaces/api/serviceInterfaces";
interface SearchParams {
query: string;
@@ -65,16 +72,24 @@ export enum Endpoints {
MOVIE = "/movie",
RATINGS = "/ratings",
ISSUE = "/issue",
+ USER = "/user",
+ SERVICE = "/service",
TV = "/tv",
SETTINGS = "/settings",
+ NETWORK = "/network",
+ STUDIO = "/studio",
+ GENRE_SLIDER = "/genreslider",
DISCOVER = "/discover",
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,
AUTH_JELLYFIN = "/auth/jellyfin",
}
export type DiscoverEndpoint =
+ | Endpoints.DISCOVER_TV_NETWORK
| Endpoints.DISCOVER_TRENDING
| Endpoints.DISCOVER_MOVIES
| Endpoints.DISCOVER_TV;
@@ -120,7 +135,7 @@ export class JellyseerrApi {
if (inRange(status, 200, 299)) {
if (data.version < "2.0.0") {
const error =
- "Jellyseerr server does not meet minimum version requirements! Please update to at least 2.0.0";
+ t("jellyseerr.toasts.jellyseer_does_not_meet_requirements");
toast.error(error);
throw Error(error);
}
@@ -134,7 +149,7 @@ export class JellyseerrApi {
requiresPass: true,
};
}
- toast.error(`Jellyseerr test failed. Please try again.`);
+ toast.error(t("jellyseerr.toasts.jellyseerr_test_failed"));
writeErrorLog(
`Jellyseerr returned a ${status} for url:\n` +
response.config.url +
@@ -147,7 +162,7 @@ export class JellyseerrApi {
};
})
.catch((e) => {
- const msg = "Failed to test jellyseerr server url";
+ const msg = t("jellyseerr.toasts.failed_to_test_jellyseerr_server_url");
toast.error(msg);
console.error(msg, e);
return {
@@ -181,7 +196,7 @@ export class JellyseerrApi {
}
async discover(
- endpoint: DiscoverEndpoint,
+ endpoint: DiscoverEndpoint | string,
params: any
): Promise {
return this.axios
@@ -189,6 +204,15 @@ export class JellyseerrApi {
.then(({ data }) => data);
}
+ async getGenreSliders(
+ endpoint: Endpoints.TV | Endpoints.MOVIE,
+ params: any = undefined
+ ): Promise {
+ return this.axios
+ ?.get(Endpoints.API_V1 + Endpoints.DISCOVER + Endpoints.GENRE_SLIDER + endpoint, { params })
+ .then(({ data }) => data);
+ }
+
async search(params: SearchParams): Promise {
const response = await this.axios?.get(
Endpoints.API_V1 + Endpoints.SEARCH,
@@ -266,9 +290,15 @@ export class JellyseerrApi {
});
}
+ async user(params: any) {
+ return this.axios
+ ?.get(`${Endpoints.API_V1}${Endpoints.USER}`, { params })
+ .then(({data}) => data.results)
+ }
+
imageProxy(
path?: string,
- tmdbPath: string = "original",
+ filter: string = "original",
width: number = 1920,
quality: number = 75
) {
@@ -276,7 +306,7 @@ export class JellyseerrApi {
? this.axios.defaults.baseURL +
`/_next/image?` +
new URLSearchParams(
- `url=https://image.tmdb.org/t/p/${tmdbPath}/${path}&w=${width}&q=${quality}`
+ `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`;
@@ -293,12 +323,24 @@ export class JellyseerrApi {
const issue = response.data;
if (issue.status === IssueStatus.OPEN) {
- toast.success("Issue submitted!");
+ toast.success(t("jellyseerr.toasts.issue_submitted"));
}
return issue;
});
}
+ async service(type: 'radarr' | 'sonarr') {
+ return this.axios
+ ?.get(Endpoints.API_V1 + Endpoints.SERVICE + `/${type}`)
+ .then(({data}) => data);
+ }
+
+ async serviceDetails(type: 'radarr' | 'sonarr', id: number) {
+ return this.axios
+ ?.get(Endpoints.API_V1 + Endpoints.SERVICE + `/${type}` + `/${id}`)
+ .then(({data}) => data);
+ }
+
private setInterceptors() {
this.axios.interceptors.response.use(
async (response) => {
@@ -381,14 +423,14 @@ export const useJellyseerr = () => {
switch (mediaRequest.status) {
case MediaRequestStatus.PENDING:
case MediaRequestStatus.APPROVED:
- toast.success(`Requested ${title}!`);
- onSuccess?.();
+ toast.success(t("jellyseerr.toasts.requested_item", {item: title}));
+ onSuccess?.()
break;
case MediaRequestStatus.DECLINED:
- toast.error(`You don't have permission to request!`);
+ toast.error(t("jellyseerr.toasts.you_dont_have_permission_to_request"));
break;
case MediaRequestStatus.FAILED:
- toast.error(`Something went wrong requesting media!`);
+ toast.error(t("jellyseerr.toasts.something_went_wrong_requesting_media"));
break;
}
});
diff --git a/hooks/useMarkAsPlayed.ts b/hooks/useMarkAsPlayed.ts
index 01704b74..44731ce8 100644
--- a/hooks/useMarkAsPlayed.ts
+++ b/hooks/useMarkAsPlayed.ts
@@ -3,17 +3,17 @@ import { markAsNotPlayed } from "@/utils/jellyfin/playstate/markAsNotPlayed";
import { markAsPlayed } from "@/utils/jellyfin/playstate/markAsPlayed";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { useQueryClient } from "@tanstack/react-query";
-import * as Haptics from "@/packages/expo-haptics";
+import { useHaptic } from "./useHaptic";
import { useAtom } from "jotai";
-export const useMarkAsPlayed = (item: BaseItemDto) => {
+export const useMarkAsPlayed = (items: BaseItemDto[]) => {
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
const queryClient = useQueryClient();
+ const lightHapticFeedback = useHaptic("light");
const invalidateQueries = () => {
const queriesToInvalidate = [
- ["item", item.Id],
["resumeItems"],
["continueWatching"],
["nextUp-all"],
@@ -23,48 +23,21 @@ export const useMarkAsPlayed = (item: BaseItemDto) => {
["home"],
];
+ items.forEach((item) => {
+ if(!item.Id) return;
+ queriesToInvalidate.push(["item", item.Id]);
+ });
+
queriesToInvalidate.forEach((queryKey) => {
queryClient.invalidateQueries({ queryKey });
});
};
const markAsPlayedStatus = async (played: boolean) => {
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
+ lightHapticFeedback();
- // Optimistic update
- queryClient.setQueryData(
- ["item", item.Id],
- (oldData: BaseItemDto | undefined) => {
- if (oldData) {
- return {
- ...oldData,
- UserData: {
- ...oldData.UserData,
- Played: !played,
- },
- };
- }
- return oldData;
- }
- );
-
- try {
- if (played) {
- await markAsNotPlayed({
- api: api,
- itemId: item?.Id,
- userId: user?.Id,
- });
- } else {
- await markAsPlayed({
- api: api,
- item: item,
- userId: user?.Id,
- });
- }
- invalidateQueries();
- } catch (error) {
- // Revert optimistic update on error
+ items.forEach((item) => {
+ // Optimistic update
queryClient.setQueryData(
["item", item.Id],
(oldData: BaseItemDto | undefined) => {
@@ -80,8 +53,45 @@ export const useMarkAsPlayed = (item: BaseItemDto) => {
return oldData;
}
);
+ })
+
+ try {
+ // Process all items
+ await Promise.all(items.map(item =>
+ played
+ ? markAsPlayed({ api, item, userId: user?.Id })
+ : markAsNotPlayed({ api, itemId: item?.Id, userId: user?.Id })
+ ));
+
+ // Bulk invalidate
+ queryClient.invalidateQueries({
+ queryKey: [
+ "resumeItems",
+ "continueWatching",
+ "nextUp-all",
+ "nextUp",
+ "episodes",
+ "seasons",
+ "home",
+ ...items.map(item => ["item", item.Id])
+ ].flat()
+ });
+ } catch (error) {
+ // Revert all optimistic updates on any failure
+ items.forEach(item => {
+ queryClient.setQueryData(
+ ["item", item.Id],
+ (oldData: BaseItemDto | undefined) =>
+ oldData ? {
+ ...oldData,
+ UserData: { ...oldData.UserData, Played: played }
+ } : oldData
+ );
+ });
console.error("Error updating played status:", error);
}
+
+ invalidateQueries();
};
return markAsPlayedStatus;
diff --git a/hooks/useOrientationSettings.ts b/hooks/useOrientationSettings.ts
index 7bb749a4..7b657d77 100644
--- a/hooks/useOrientationSettings.ts
+++ b/hooks/useOrientationSettings.ts
@@ -10,7 +10,9 @@ export const useOrientationSettings = () => {
useEffect(() => {
if (settings?.autoRotate) {
- // Don't need to do anything
+ ScreenOrientation.lockAsync(
+ ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT
+ );
} else if (settings?.defaultVideoOrientation) {
ScreenOrientation.lockAsync(settings.defaultVideoOrientation);
}
diff --git a/hooks/useRemuxHlsToMp4.ts b/hooks/useRemuxHlsToMp4.ts
index da922e2d..9c03a5ba 100644
--- a/hooks/useRemuxHlsToMp4.ts
+++ b/hooks/useRemuxHlsToMp4.ts
@@ -20,6 +20,7 @@ import { Api } from "@jellyfin/sdk";
import { useSettings } from "@/utils/atoms/settings";
import { JobStatus } from "@/utils/optimize-server";
import { Platform } from "react-native";
+import { useTranslation } from "react-i18next";
const createFFmpegCommand = (url: string, output: string) => [
"-y", // overwrite output files without asking
@@ -51,6 +52,7 @@ export const useRemuxHlsToMp4 = () => {
const api = useAtomValue(apiAtom);
const router = useRouter();
const queryClient = useQueryClient();
+ const { t } = useTranslation();
const [settings] = useSettings();
const { saveImage } = useImageStorage();
@@ -91,7 +93,7 @@ export const useRemuxHlsToMp4 = () => {
queryKey: ["downloadedItems"],
});
saveDownloadedItemInfo(item, stat.getSize());
- toast.success("Download completed");
+ toast.success(t("home.downloads.toasts.download_completed"));
}
setProcesses((prev) => {
@@ -155,7 +157,7 @@ export const useRemuxHlsToMp4 = () => {
// First lets save any important assets we want to present to the user offline
await onSaveAssets(api, item);
- toast.success(`Download started for ${item.Name}`, {
+ toast.success(t("home.downloads.toasts.download_started_for", {item: item.Name}), {
action: {
label: "Go to download",
onClick: () => {
diff --git a/hooks/useWebsockets.ts b/hooks/useWebsockets.ts
index 75199b31..d9e6096a 100644
--- a/hooks/useWebsockets.ts
+++ b/hooks/useWebsockets.ts
@@ -2,6 +2,7 @@ import { useEffect } from "react";
import { Alert } from "react-native";
import { useRouter } from "expo-router";
import { useWebSocketContext } from "@/providers/WebSocketProvider";
+import { useTranslation } from "react-i18next";
interface UseWebSocketProps {
isPlaying: boolean;
@@ -18,6 +19,7 @@ export const useWebSocket = ({
}: UseWebSocketProps) => {
const router = useRouter();
const { ws } = useWebSocketContext();
+ const { t } = useTranslation();
useEffect(() => {
if (!ws) return;
@@ -40,7 +42,7 @@ export const useWebSocket = ({
console.log("Command ~ DisplayMessage");
const title = json?.Data?.Arguments?.Header;
const body = json?.Data?.Arguments?.Text;
- Alert.alert("Message from server: " + title, body);
+ Alert.alert(t("player.message_from_server", {message: title}), body);
}
};
diff --git a/i18n.ts b/i18n.ts
new file mode 100644
index 00000000..4a753152
--- /dev/null
+++ b/i18n.ts
@@ -0,0 +1,36 @@
+import i18n from "i18next";
+import { initReactI18next } from "react-i18next";
+
+import de from "./translations/de.json";
+import en from "./translations/en.json";
+import es from "./translations/es.json";
+import fr from "./translations/fr.json";
+import sv from "./translations/sv.json";
+import { getLocales } from "expo-localization";
+
+export const APP_LANGUAGES = [
+ { label: "Deutsch", value: "de" },
+ { label: "English", value: "en" },
+ { label: "Espaรฑol", value: "es" },
+ { label: "Franรงais", value: "fr" },
+ { label: "Svenska", value: "sv" },
+];
+
+i18n.use(initReactI18next).init({
+ compatibilityJSON: "v4",
+ resources: {
+ de: { translation: de },
+ en: { translation: en },
+ es: { translation: es },
+ fr: { translation: fr },
+ sv: { translation: sv },
+ },
+
+ lng: getLocales()[0].languageCode || "en",
+ fallbackLng: "en",
+ interpolation: {
+ escapeValue: false,
+ },
+});
+
+export default i18n;
diff --git a/package.json b/package.json
index 73b2e503..500bd54c 100644
--- a/package.json
+++ b/package.json
@@ -4,6 +4,7 @@
"version": "1.0.0",
"scripts": {
"submodule-reload": "git submodule update --init --remote --recursive",
+ "clean": "echo y | expo prebuild --clean",
"start": "bun run submodule-reload && expo start",
"ios": "EXPO_TV=0 expo run:ios",
"ios:tv": "EXPO_TV=1 expo run:ios",
@@ -16,21 +17,20 @@
"lint": "expo lint",
"postinstall": "patch-package"
},
- "jest": {
- "preset": "jest-expo"
- },
"dependencies": {
- "@bottom-tabs/react-navigation": "^0.7.1",
+ "@bottom-tabs/react-navigation": "0.8.3",
"@config-plugins/ffmpeg-kit-react-native": "^8.0.0",
+ "@expo/config-plugins": "~8.0.0",
"@expo/react-native-action-sheet": "^4.1.0",
"@expo/vector-icons": "^14.0.4",
"@futurejj/react-native-visibility-sensor": "^1.3.5",
"@gorhom/bottom-sheet": "^4.6.4",
"@jellyfin/sdk": "^0.11.0",
- "@kesha-antonov/react-native-background-downloader": "3.1.2",
+ "@kesha-antonov/react-native-background-downloader": "3.2.6",
"@react-native-async-storage/async-storage": "1.23.1",
"@react-native-community/netinfo": "11.3.1",
"@react-native-menu/menu": "^1.1.6",
+ "@react-navigation/bottom-tabs": "^7.0.0",
"@react-navigation/material-top-tabs": "^6.6.14",
"@react-navigation/native": "^6.1.18",
"@shopify/flash-list": "1.6.4",
@@ -40,13 +40,14 @@
"@types/uuid": "^10.0.0",
"add": "^2.0.6",
"axios": "^1.7.7",
- "expo": "~51.0.39",
+ "expo": "^51",
"expo-asset": "~10.0.10",
"expo-background-fetch": "~12.0.1",
- "expo-blur": "~13.0.2",
+ "expo-blur": "~13.0.3",
"expo-brightness": "~12.0.1",
"expo-build-properties": "~0.12.5",
"expo-constants": "~16.0.2",
+ "expo-crypto": "~13.0.2",
"expo-dev-client": "~4.0.29",
"expo-device": "~6.0.2",
"expo-font": "~12.0.10",
@@ -55,6 +56,7 @@
"expo-keep-awake": "~13.0.2",
"expo-linear-gradient": "~13.0.2",
"expo-linking": "~6.3.1",
+ "expo-localization": "~15.0.3",
"expo-network": "~6.0.1",
"expo-notifications": "~0.28.19",
"expo-router": "~3.5.24",
@@ -62,11 +64,12 @@
"expo-sensors": "~13.0.9",
"expo-splash-screen": "~0.27.7",
"expo-status-bar": "~1.12.1",
- "expo-system-ui": "^3.0.7",
+ "expo-system-ui": "~3.0.7",
"expo-task-manager": "~11.8.2",
- "expo-updates": "~0.25.27",
+ "expo-updates": "~0.25.28",
"expo-web-browser": "~13.0.3",
"ffmpeg-kit-react-native": "^6.0.2",
+ "i18next": "^24.2.2",
"install": "^0.13.0",
"jotai": "^2.10.1",
"lodash": "^4.17.21",
@@ -74,8 +77,9 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "npm:react-native-tvos@~0.74.5-0",
+ "react-i18next": "^15.4.0",
"react-native-awesome-slider": "^2.5.6",
- "react-native-bottom-tabs": "0.7.1",
+ "react-native-bottom-tabs": "0.8.3",
"react-native-circular-progress": "^1.4.1",
"react-native-compressor": "^1.9.0",
"react-native-country-flag": "^2.0.2",
@@ -96,6 +100,7 @@
"react-native-screens": "3.31.1",
"react-native-svg": "15.2.0",
"react-native-tab-view": "^3.5.2",
+ "react-native-udp": "^4.1.7",
"react-native-uitextview": "^1.4.0",
"react-native-url-polyfill": "^2.0.0",
"react-native-uuid": "^2.0.2",
@@ -117,8 +122,6 @@
"@types/jest": "^29.5.14",
"@types/react": "~18.2.79",
"@types/react-test-renderer": "^18.0.7",
- "jest": "^29.2.1",
- "jest-expo": "~51.0.4",
"patch-package": "^8.0.0",
"postinstall-postinstall": "^2.1.0",
"react-test-renderer": "18.2.0",
diff --git a/packages/expo-haptics.ts b/packages/expo-haptics.ts
deleted file mode 100644
index 522187df..00000000
--- a/packages/expo-haptics.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * as Haptics from "expo-haptics";
diff --git a/packages/expo-haptics.tv.ts b/packages/expo-haptics.tv.ts
deleted file mode 100644
index e69de29b..00000000
diff --git a/plugins/network_security_config.xml b/plugins/network_security_config.xml
new file mode 100644
index 00000000..a0e1e57d
--- /dev/null
+++ b/plugins/network_security_config.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+ 192.168.86.64
+
+
\ No newline at end of file
diff --git a/plugins/withGoogleCastActivity.js b/plugins/withGoogleCastActivity.js
new file mode 100644
index 00000000..1a8c0a30
--- /dev/null
+++ b/plugins/withGoogleCastActivity.js
@@ -0,0 +1,34 @@
+const { withAndroidManifest } = require("@expo/config-plugins");
+
+const withGoogleCastActivity = (config) =>
+ withAndroidManifest(config, async (config) => {
+ const mainApplication = config.modResults.manifest.application[0];
+
+ // Initialize activity array if it doesn't exist
+ if (!mainApplication.activity) {
+ mainApplication.activity = [];
+ }
+
+ // Check if the activity already exists
+ const activityExists = mainApplication.activity.some(
+ (activity) =>
+ activity.$?.["android:name"] ===
+ "com.reactnative.googlecast.RNGCExpandedControllerActivity"
+ );
+
+ // Only add the activity if it doesn't already exist
+ if (!activityExists) {
+ mainApplication.activity.push({
+ $: {
+ "android:name":
+ "com.reactnative.googlecast.RNGCExpandedControllerActivity",
+ "android:theme": "@style/Theme.MaterialComponents.NoActionBar",
+ "android:launchMode": "singleTask",
+ },
+ });
+ }
+
+ return config;
+ });
+
+module.exports = withGoogleCastActivity;
diff --git a/plugins/withTrustLocalCerts.js b/plugins/withTrustLocalCerts.js
new file mode 100644
index 00000000..13b326af
--- /dev/null
+++ b/plugins/withTrustLocalCerts.js
@@ -0,0 +1,44 @@
+const { AndroidConfig, withAndroidManifest } = require("@expo/config-plugins");
+const { Paths } = require("@expo/config-plugins/build/android");
+const path = require("path");
+const fs = require("fs");
+const fsPromises = fs.promises;
+
+const { getMainApplicationOrThrow } = AndroidConfig.Manifest;
+
+const withTrustLocalCerts = (config) => {
+ return withAndroidManifest(config, async (config) => {
+ config.modResults = await setCustomConfigAsync(config, config.modResults);
+ return config;
+ });
+};
+
+async function setCustomConfigAsync(config, androidManifest) {
+ const src_file_path = path.join(__dirname, "network_security_config.xml");
+ const res_file_path = path.join(
+ await Paths.getResourceFolderAsync(config.modRequest.projectRoot),
+ "xml",
+ "network_security_config.xml"
+ );
+
+ const res_dir = path.resolve(res_file_path, "..");
+
+ if (!fs.existsSync(res_dir)) {
+ await fsPromises.mkdir(res_dir);
+ }
+
+ try {
+ await fsPromises.copyFile(src_file_path, res_file_path);
+ } catch (e) {
+ throw new Error(
+ `Failed to copy network security config file from ${src_file_path} to ${res_file_path}: ${e.message}`
+ );
+ }
+ const mainApplication = getMainApplicationOrThrow(androidManifest);
+ mainApplication.$["android:networkSecurityConfig"] =
+ "@xml/network_security_config";
+
+ return androidManifest;
+}
+
+module.exports = withTrustLocalCerts;
diff --git a/providers/DownloadProvider.tsx b/providers/DownloadProvider.tsx
index f581dd2e..568ceb76 100644
--- a/providers/DownloadProvider.tsx
+++ b/providers/DownloadProvider.tsx
@@ -1,4 +1,4 @@
-import { useSettings } from "@/utils/atoms/settings";
+import {DownloadMethod, useSettings} from "@/utils/atoms/settings";
import { getOrSetDeviceId } from "@/utils/device";
import { useLog, writeToLog } from "@/utils/log";
import {
@@ -52,8 +52,9 @@ import useImageStorage from "@/hooks/useImageStorage";
import { storage } from "@/utils/mmkv";
import useDownloadHelper from "@/utils/download";
import { FileInfo } from "expo-file-system";
-import * as Haptics from "@/packages/expo-haptics";
+import { useHaptic } from "@/hooks/useHaptic";
import * as Application from "expo-application";
+import { useTranslation } from "react-i18next";
export type DownloadedItem = {
item: Partial;
@@ -73,6 +74,7 @@ const DownloadContext = createContext(processesAtom);
+ const successHapticFeedback = useHaptic("success");
+
const authHeader = useMemo(() => {
return api?.accessToken;
}, [api]);
@@ -109,7 +113,7 @@ function useDownloadProvider() {
const url = settings?.optimizedVersionsServerUrl;
if (
- settings?.downloadMethod !== "optimized" ||
+ settings?.downloadMethod !== DownloadMethod.Optimized ||
!url ||
!deviceId ||
!authHeader
@@ -142,9 +146,9 @@ function useDownloadProvider() {
if (settings.autoDownload) {
startDownload(job);
} else {
- toast.info(`${job.item.Name} is ready to be downloaded`, {
+ toast.info(t("home.downloads.toasts.item_is_ready_to_be_downloaded",{item: job.item.Name}), {
action: {
- label: "Go to downloads",
+ label: t("home.downloads.toasts.go_to_downloads"),
onClick: () => {
router.push("/downloads");
toast.dismiss();
@@ -169,7 +173,7 @@ function useDownloadProvider() {
},
staleTime: 0,
refetchInterval: 2000,
- enabled: settings?.downloadMethod === "optimized",
+ enabled: settings?.downloadMethod === DownloadMethod.Optimized,
});
useEffect(() => {
@@ -227,9 +231,9 @@ function useDownloadProvider() {
},
});
- toast.info(`Download started for ${process.item.Name}`, {
+ toast.info(t("home.downloads.toasts.download_stated_for_item", {item: process.item.Name}), {
action: {
- label: "Go to downloads",
+ label: t("home.downloads.toasts.go_to_downloads"),
onClick: () => {
router.push("/downloads");
toast.dismiss();
@@ -278,10 +282,10 @@ function useDownloadProvider() {
process.item,
doneHandler.bytesDownloaded
);
- toast.success(`Download completed for ${process.item.Name}`, {
+ toast.success(t("home.downloads.toasts.download_completed_for_item", {item: process.item.Name}), {
duration: 3000,
action: {
- label: "Go to downloads",
+ label: t("home.downloads.toasts.go_to_downloads"),
onClick: () => {
router.push("/downloads");
toast.dismiss();
@@ -303,7 +307,7 @@ function useDownloadProvider() {
if (error.errorCode === 404) {
errorMsg = "File not found on server";
}
- toast.error(`Download failed for ${process.item.Name} - ${errorMsg}`);
+ toast.error(t("home.downloads.toasts.download_failed_for_item", {item: process.item.Name, error: errorMsg}));
writeToLog("ERROR", `Download failed for ${process.item.Name}`, {
error,
processDetails: {
@@ -360,9 +364,9 @@ function useDownloadProvider() {
throw new Error("Failed to start optimization job");
}
- toast.success(`Queued ${item.Name} for optimization`, {
+ toast.success(t("home.downloads.toasts.queued_item_for_optimization", {item: item.Name}), {
action: {
- label: "Go to download",
+ label: t("home.downloads.toasts.go_to_downloads"),
onClick: () => {
router.push("/downloads");
toast.dismiss();
@@ -380,21 +384,21 @@ function useDownloadProvider() {
headers: error.response?.headers,
});
toast.error(
- `Failed to start download for ${item.Name}: ${error.message}`
+ t("home.downloads.toasts.failed_to_start_download_for_item", {item: item.Name, message: error.message})
);
if (error.response) {
toast.error(
- `Server responded with status ${error.response.status}`
+ t("home.downloads.toasts.server_responded_with_status", {statusCode: error.response.status})
);
} else if (error.request) {
- toast.error("No response received from server");
+ t("home.downloads.toasts.no_response_received_from_server");
} else {
toast.error("Error setting up the request");
}
} else {
console.error("Non-Axios error:", error);
toast.error(
- `Failed to start download for ${item.Name}: Unexpected error`
+ t("home.downloads.toasts.failed_to_start_download_for_item_unexpected_error", {item: item.Name})
);
}
}
@@ -410,11 +414,11 @@ function useDownloadProvider() {
queryClient.invalidateQueries({ queryKey: ["downloadedItems"] }),
])
.then(() =>
- toast.success("All files, folders, and jobs deleted successfully")
+ toast.success(t("home.downloads.toasts.all_files_folders_and_jobs_deleted_successfully"))
)
.catch((reason) => {
console.error("Failed to delete all files, folders, and jobs:", reason);
- toast.error("An error occurred while deleting files and jobs");
+ toast.error(t("home.downloads.toasts.an_error_occured_while_deleting_files_and_jobs"));
});
};
@@ -537,9 +541,7 @@ function useDownloadProvider() {
if (i.Id) return deleteFile(i.Id);
return;
})
- ).then(() =>
- Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success)
- );
+ ).then(() => successHapticFeedback());
};
const cleanCacheDirectory = async () => {
diff --git a/providers/JellyfinProvider.tsx b/providers/JellyfinProvider.tsx
index 57dd94c6..222417ef 100644
--- a/providers/JellyfinProvider.tsx
+++ b/providers/JellyfinProvider.tsx
@@ -1,3 +1,4 @@
+import "@/augmentations";
import { useInterval } from "@/hooks/useInterval";
import { storage } from "@/utils/mmkv";
import { Api, Jellyfin } from "@jellyfin/sdk";
@@ -19,7 +20,13 @@ import React, {
import { Platform } from "react-native";
import uuid from "react-native-uuid";
import { getDeviceName } from "react-native-device-info";
-import { toast } from "sonner-native";
+import { useTranslation } from "react-i18next";
+import { useSettings } from "@/utils/atoms/settings";
+import { JellyseerrApi, useJellyseerr } from "@/hooks/useJellyseerr";
+import {
+ useSplashScreenLoading,
+ useSplashScreenVisible,
+} from "./SplashScreenProvider";
interface Server {
address: string;
@@ -48,6 +55,8 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
const [jellyfin, setJellyfin] = useState(undefined);
const [deviceId, setDeviceId] = useState(undefined);
+ const { t } = useTranslation();
+
useEffect(() => {
(async () => {
const id = getOrSetDeviceId();
@@ -55,7 +64,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
setJellyfin(
() =>
new Jellyfin({
- clientInfo: { name: "Streamyfin", version: "0.24.0" },
+ clientInfo: { name: "Streamyfin", version: "0.25.0" },
deviceInfo: {
name: deviceName,
id,
@@ -70,6 +79,14 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
const [user, setUser] = useAtom(userAtom);
const [isPolling, setIsPolling] = useState(false);
const [secret, setSecret] = useState(null);
+ const [
+ settings,
+ updateSettings,
+ pluginSettings,
+ setPluginSettings,
+ refreshStreamyfinPluginSettings,
+ ] = useSettings();
+ const { clearAllJellyseerData, setJellyseerrUser } = useJellyseerr();
useQuery({
queryKey: ["user", api],
@@ -92,7 +109,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
return {
authorization: `MediaBrowser Client="Streamyfin", Device=${
Platform.OS === "android" ? "Android" : "iOS"
- }, DeviceId="${deviceId}", Version="0.24.0"`,
+ }, DeviceId="${deviceId}", Version="0.25.0"`,
};
}, [deviceId]);
@@ -164,6 +181,14 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
useInterval(pollQuickConnect, isPolling ? 1000 : null);
+ useEffect(() => {
+ (async () => {
+ await refreshStreamyfinPluginSettings();
+ })();
+ }, []);
+
+ useInterval(refreshStreamyfinPluginSettings, 60 * 5 * 1000); // 5 min
+
const discoverServers = async (url: string): Promise => {
const servers = await jellyfin?.discovery.getRecommendedServerCandidates(
url
@@ -226,27 +251,43 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
storage.set("user", JSON.stringify(auth.data.User));
setApi(jellyfin.createApi(api?.basePath, auth.data?.AccessToken));
storage.set("token", auth.data?.AccessToken);
+
+ const recentPluginSettings = await refreshStreamyfinPluginSettings();
+ if (recentPluginSettings?.jellyseerrServerUrl?.value) {
+ const jellyseerrApi = new JellyseerrApi(
+ recentPluginSettings.jellyseerrServerUrl.value
+ );
+ await jellyseerrApi.test().then((result) => {
+ if (result.isValid && result.requiresPass) {
+ jellyseerrApi.login(username, password).then(setJellyseerrUser);
+ }
+ });
+ }
}
} catch (error) {
if (axios.isAxiosError(error)) {
switch (error.response?.status) {
case 401:
- throw new Error("Invalid username or password");
+ throw new Error(t("login.invalid_username_or_password"));
case 403:
- throw new Error("User does not have permission to log in");
+ throw new Error(
+ t("login.user_does_not_have_permission_to_log_in")
+ );
case 408:
throw new Error(
- "Server is taking too long to respond, try again later"
+ t("login.server_is_taking_too_long_to_respond_try_again_later")
);
case 429:
throw new Error(
- "Server received too many requests, try again later"
+ t("login.server_received_too_many_requests_try_again_later")
);
case 500:
- throw new Error("There is a server error");
+ throw new Error(t("login.there_is_a_server_error"));
default:
throw new Error(
- "An unexpected error occurred. Did you enter the server URL correctly?"
+ t(
+ "login.an_unexpected_error_occured_did_you_enter_the_correct_url"
+ )
);
}
}
@@ -262,6 +303,8 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
mutationFn: async () => {
storage.delete("token");
setUser(null);
+ setPluginSettings(undefined);
+ await clearAllJellyseerData();
},
onError: (error) => {
console.error("Logout failed:", error);
@@ -306,11 +349,17 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
initiateQuickConnect,
};
- useProtectedRoute(user, isLoading || isFetching);
+ let isLoadingOrFetching = isLoading || isFetching;
+ useProtectedRoute(user, isLoadingOrFetching);
+
+ // show splash screen until everything loaded
+ useSplashScreenLoading(isLoadingOrFetching);
+ const splashScreenVisible = useSplashScreenVisible();
return (
- {children}
+ {/* don't render login page when loading and splash screen visible */}
+ {isLoadingOrFetching && splashScreenVisible ? undefined : children}
);
};
diff --git a/providers/PlaySettingsProvider.tsx b/providers/PlaySettingsProvider.tsx
index 50f780cd..ff80bb9e 100644
--- a/providers/PlaySettingsProvider.tsx
+++ b/providers/PlaySettingsProvider.tsx
@@ -38,7 +38,6 @@ type PlaySettingsContextType = {
setPlayUrl: React.Dispatch>;
playSessionId?: string | null;
setOfflineSettings: (data: PlaybackType) => void;
- setMusicPlaySettings: (item: BaseItemDto, url: string) => void;
};
const PlaySettingsContext = createContext(
@@ -61,13 +60,6 @@ export const PlaySettingsProvider: React.FC<{ children: React.ReactNode }> = ({
_setPlaySettings(data);
}, []);
- const setMusicPlaySettings = (item: BaseItemDto, url: string) => {
- setPlaySettings({
- item: item,
- });
- setPlayUrl(url);
- };
-
const setPlaySettings = useCallback(
async (
dataOrUpdater:
@@ -147,7 +139,6 @@ export const PlaySettingsProvider: React.FC<{ children: React.ReactNode }> = ({
setPlaySettings,
playUrl,
setPlayUrl,
- setMusicPlaySettings,
setOfflineSettings,
playSessionId,
mediaSource,
diff --git a/providers/SplashScreenProvider.tsx b/providers/SplashScreenProvider.tsx
new file mode 100644
index 00000000..2265dd00
--- /dev/null
+++ b/providers/SplashScreenProvider.tsx
@@ -0,0 +1,103 @@
+import {
+ createContext,
+ ReactNode,
+ useContext,
+ useEffect,
+ useState,
+ useRef,
+} from "react";
+import * as SplashScreen from "expo-splash-screen";
+
+type SplashScreenContextValue = {
+ registerLoadingComponent: () => () => void;
+ splashScreenVisible: boolean;
+};
+
+const SplashScreenContext = createContext(
+ undefined
+);
+
+// Prevent splash screen from auto-hiding
+void SplashScreen.preventAutoHideAsync();
+
+export const SplashScreenProvider: React.FC<{ children: ReactNode }> = ({
+ children,
+}) => {
+ const [splashScreenVisible, setSplashScreenVisible] = useState(true);
+ const loadingComponentsCount = useRef(0);
+ const isHidingRef = useRef(false);
+
+ const hideScreenIfNoLoadingComponents = async () => {
+ if (loadingComponentsCount.current === 0 && !isHidingRef.current) {
+ try {
+ isHidingRef.current = true;
+ await SplashScreen.hideAsync();
+ setSplashScreenVisible(false);
+ } catch (error) {
+ console.warn("Failed to hide splash screen:", error);
+ } finally {
+ isHidingRef.current = false;
+ }
+ }
+ };
+
+ const registerLoadingComponent = () => {
+ loadingComponentsCount.current += 1;
+
+ return () => {
+ loadingComponentsCount.current -= 1;
+ void hideScreenIfNoLoadingComponents();
+ };
+ };
+
+ const contextValue: SplashScreenContextValue = {
+ registerLoadingComponent,
+ splashScreenVisible,
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+/**
+ * Show the Splash Screen until component is ready to be displayed.
+ *
+ * @param isLoading The loading state of the component
+ *
+ * ## Usage
+ * ```
+ * const isLoading = loadSomething()
+ * useSplashScreenLoading(isLoading) // splash screen visible until isLoading is false
+ * ```
+ */
+export function useSplashScreenLoading(isLoading: boolean) {
+ const context = useContext(SplashScreenContext);
+ if (!context) {
+ throw new Error(
+ "useSplashScreenLoading must be used within a SplashScreenProvider"
+ );
+ }
+
+ useEffect(() => {
+ if (isLoading) {
+ return context.registerLoadingComponent();
+ }
+ }, [isLoading]);
+}
+
+/**
+ * Get the visibility of the Splash Screen.
+ * @returns the visibility of the Splash Screen
+ */
+export function useSplashScreenVisible() {
+ const context = useContext(SplashScreenContext);
+ if (!context) {
+ throw new Error(
+ "useSplashScreenVisible must be used within a SplashScreenProvider"
+ );
+ }
+ return context.splashScreenVisible;
+}
diff --git a/scripts/automerge.sh b/scripts/automerge.sh
new file mode 100755
index 00000000..d66a0941
--- /dev/null
+++ b/scripts/automerge.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+[[ -z $(git status --porcelain) ]] &&
+git checkout master &&
+git pull --ff-only &&
+git checkout develop &&
+git merge master &&
+git push --follow-tags &&
+git checkout master &&
+git merge develop --ff-only &&
+git push &&
+git checkout develop ||
+(echo "Error: Failed to merge" && exit 1)
\ No newline at end of file
diff --git a/translations/de.json b/translations/de.json
new file mode 100644
index 00000000..4d0cd846
--- /dev/null
+++ b/translations/de.json
@@ -0,0 +1,457 @@
+{
+ "login": {
+ "username_required": "Benutzername ist erforderlich",
+ "error_title": "Fehler",
+ "login_title": "Anmelden",
+ "login_to_title": "Anmelden bei",
+ "username_placeholder": "Benutzername",
+ "password_placeholder": "Passwort",
+ "login_button": "Anmelden",
+ "quick_connect": "Schnellverbindung",
+ "enter_code_to_login": "Gib den Code {{code}} ein, um dich anzumelden",
+ "failed_to_initiate_quick_connect": "Fehler beim Initiieren der Schnellverbindung",
+ "got_it": "Verstanden",
+ "connection_failed": "Verbindung fehlgeschlagen",
+ "could_not_connect_to_server": "Verbindung zum Server fehlgeschlagen. Bitte รผberprรผf die URL und deine Netzwerkverbindung.",
+ "an_unexpected_error_occured": "Ein unerwarteter Fehler ist aufgetreten",
+ "change_server": "Server wechseln",
+ "invalid_username_or_password": "Ungรผltiger Benutzername oder Passwort",
+ "user_does_not_have_permission_to_log_in": "Benutzer hat keine Berechtigung, um sich anzumelden",
+ "server_is_taking_too_long_to_respond_try_again_later": "Der Server benรถtigt zu lange, um zu antworten. Bitte versuch es spรคter erneut.",
+ "server_received_too_many_requests_try_again_later": "Der Server hat zu viele Anfragen erhalten. Bitte versuch es spรคter erneut.",
+ "there_is_a_server_error": "Es gibt einen Serverfehler",
+ "an_unexpected_error_occured_did_you_enter_the_correct_url": "Ein unerwarteter Fehler ist aufgetreten. Hast du die Server-URL korrekt eingegeben?"
+ },
+ "server": {
+ "enter_url_to_jellyfin_server": "Gib die URL zu deinem Jellyfin-Server ein",
+ "server_url_placeholder": "http(s)://dein-server.de",
+ "connect_button": "Verbinden",
+ "previous_servers": "Vorherige Server",
+ "clear_button": "Lรถschen",
+ "search_for_local_servers": "Nach lokalen Servern suchen",
+ "searching": "Suche...",
+ "servers": "Server"
+ },
+ "home": {
+ "no_internet": "Kein Internet",
+ "no_items": "Keine Elemente",
+ "no_internet_message": "Keine Sorge, du kannst immer noch heruntergeladene Inhalte ansehen.",
+ "go_to_downloads": "Gehe zu den Downloads",
+ "oops": "Ups!",
+ "error_message": "Etwas ist schiefgelaufen.\nBitte melde dich ab und wieder an.",
+ "continue_watching": "Weiterschauen",
+ "next_up": "Als nรคchstes",
+ "recently_added_in": "Kรผrzlich hinzugefรผgt in {{libraryName}}",
+ "suggested_movies": "Empfohlene Filme",
+ "suggested_episodes": "Empfohlene Episoden",
+ "intro": {
+ "welcome_to_streamyfin": "Willkommen bei Streamyfin",
+ "a_free_and_open_source_client_for_jellyfin": "Ein kostenloser und Open-Source-Client fรผr Jellyfin.",
+ "features_title": "Features",
+ "features_description": "Streamyfin hat viele Features und integriert sich mit einer Vielzahl von Software, die du im Einstellungsmenรผ findest. Dazu gehรถren:",
+ "jellyseerr_feature_description": "Verbinde dich mit deiner Jellyseerr-Instanz und frage Filme direkt in der App an.",
+ "downloads_feature_title": "Downloads",
+ "downloads_feature_description": "Lade Filme und Serien herunter, um sie offline anzusehen. Nutze entweder die Standardmethode oder installiere den optimierten Server, um Dateien im Hintergrund herunterzuladen.",
+ "chromecast_feature_description": "รbertrage Filme und Serien auf deine Chromecast-Gerรคte.",
+ "centralised_settings_plugin_title": "Zentralisiertes Einstellungs-Plugin",
+ "centralised_settings_plugin_description": "Konfiguriere Einstellungen an einem zentralen Ort auf deinem Jellyfin-Server. Alle Client-Einstellungen fรผr alle Benutzer werden automatisch synchronisiert.",
+ "done_button": "Fertig",
+ "go_to_settings_button": "Gehe zu den Einstellungen",
+ "read_more": "Mehr Erfahren"
+ },
+ "settings": {
+ "settings_title": "Einstellungen",
+ "log_out_button": "Abmelden",
+ "user_info": {
+ "user_info_title": "Benutzerinformationen",
+ "user": "Benutzer",
+ "server": "Server",
+ "token": "Token",
+ "app_version": "App-Version"
+ },
+ "quick_connect": {
+ "quick_connect_title": "Schnellverbindung",
+ "authorize_button": "Schnellverbindung autorisieren",
+ "enter_the_quick_connect_code": "Gib den Schnellverbindungscode ein...",
+ "success": "Erfolg",
+ "quick_connect_autorized": "Schnellverbindung autorisiert",
+ "error": "Fehler",
+ "invalid_code": "Ungรผltiger Code",
+ "authorize": "Autorisieren"
+ },
+ "media_controls": {
+ "media_controls_title": "Mediensteuerung",
+ "forward_skip_length": "Vorspulzeit",
+ "rewind_length": "Rรผckspulzeit",
+ "seconds_unit": "s"
+ },
+ "audio": {
+ "audio_title": "Audio",
+ "set_audio_track": "Audiospur aus dem vorherigen Element festlegen",
+ "audio_language": "Audio-Sprache",
+ "audio_hint": "Wรคhl die Standardsprache fรผr Audio aus.",
+ "none": "Keine",
+ "language": "Sprache"
+ },
+ "subtitles": {
+ "subtitle_title": "Untertitel",
+ "subtitle_language": "Untertitel-Sprache",
+ "subtitle_mode": "Untertitel-Modus",
+ "set_subtitle_track": "Untertitel-Spur aus dem vorherigen Element festlegen",
+ "subtitle_size": "Untertitel-Grรถรe",
+ "subtitle_hint": "Konfigurier die Untertitel-Prรคferenzen.",
+ "none": "Keine",
+ "language": "Sprache",
+ "loading": "Lรคdt",
+ "modes": {
+ "Default": "Standard",
+ "Smart": "Smart",
+ "Always": "Immer",
+ "None": "Keine",
+ "OnlyForced": "Nur erzwungen"
+ }
+ },
+ "other": {
+ "other_title": "Sonstiges",
+ "auto_rotate": "Automatische Drehung",
+ "video_orientation": "Videoausrichtung",
+ "orientation": "Ausrichtung",
+ "orientations": {
+ "DEFAULT": "Standard",
+ "ALL": "Alle",
+ "PORTRAIT": "Hochformat",
+ "PORTRAIT_UP": "Hochformat oben",
+ "PORTRAIT_DOWN": "Hochformat unten",
+ "LANDSCAPE": "Querformat",
+ "LANDSCAPE_LEFT": "Querformat links",
+ "LANDSCAPE_RIGHT": "Querformat rechts",
+ "OTHER": "Andere",
+ "UNKNOWN": "Unbekannt"
+ },
+ "safe_area_in_controls": "Sicherer Bereich in den Steuerungen",
+ "show_custom_menu_links": "Benutzerdefinierte Menรผlinks anzeigen",
+ "hide_libraries": "Bibliotheken ausblenden",
+ "select_liraries_you_want_to_hide": "Wรคhl die Bibliotheken aus, die du im Bibliothekstab und auf der Startseite ausblenden mรถchtest.",
+ "disable_haptic_feedback": "Haptisches Feedback deaktivieren"
+ },
+ "downloads": {
+ "downloads_title": "Downloads",
+ "download_method": "Download-Methode",
+ "remux_max_download": "Maximaler Remux-Download",
+ "auto_download": "Automatischer Download",
+ "optimized_versions_server": "Optimierter Versions-Server",
+ "save_button": "Speichern",
+ "optimized_server": "Optimierter Server",
+ "optimized": "Optimiert",
+ "default": "Standard",
+ "optimized_version_hint": "Gib die URL fรผr den optimierten Server ein. Die URL sollte http oder https enthalten und optional den Port.",
+ "read_more_about_optimized_server": "Mehr รผber den optimierten Server lesen.",
+ "url":"URL",
+ "server_url_placeholder": "http(s)://domain.org:port"
+ },
+ "plugins": {
+ "plugins_title": "Plugins",
+ "jellyseerr": {
+ "jellyseerr_warning": "Diese integration ist in einer frรผhen Entwicklungsphase. Erwarte Verรคnderungen.",
+ "server_url": "Server URL",
+ "server_url_hint": "Beispiel: http(s)://your-host.url\n(Portnummer hinzufรผgen, falls erforderlich)",
+ "server_url_placeholder": "Jellyseerr URL...",
+ "password": "Passwort",
+ "password_placeholder": "Passwort fรผr Jellyfin Benutzer {{username}} eingeben",
+ "save_button": "Speichern",
+ "clear_button": "Lรถschen",
+ "login_button": "Anmelden",
+ "total_media_requests": "Gesamtanfragen",
+ "movie_quota_limit": "Film-Anfragelimit",
+ "movie_quota_days": "Film-Anfragetage",
+ "tv_quota_limit": "TV-Anfragelimit",
+ "tv_quota_days": "TV-Anfragetage",
+ "reset_jellyseerr_config_button": "Setze Jellyseerr-Konfiguration zurรผck",
+ "unlimited": "Unlimitiert"
+ },
+ "marlin_search": {
+ "enable_marlin_search": "Aktiviere Marlin Search",
+ "url": "URL",
+ "server_url_placeholder": "http(s)://domain.org:port",
+ "marlin_search_hint": "Gib die URL fรผr den Marlin Server ein. Die URL sollte http oder https enthalten und optional den Port.",
+ "read_more_about_marlin": "Erfahre mehr รผber Marlin.",
+ "save_button": "Speichern",
+ "toasts": {
+ "saved": "Gespeichert"
+ }
+ }
+ },
+ "storage": {
+ "storage_title": "Speicher",
+ "app_usage": "App {{usedSpace}}%",
+ "device_usage": "Gerรคt {{availableSpace}}%",
+ "size_used": "{{used}} von {{total}} benutzt",
+ "delete_all_downloaded_files": "Alle Downloads lรถschen"
+ },
+ "intro": {
+ "show_intro": "Show intro",
+ "reset_intro": "Reset intro"
+ },
+ "logs": {
+ "logs_title": "Logs",
+ "no_logs_available": "Keine Logs verfรผgbar",
+ "delete_all_logs": "Alle Logs lรถschen"
+ },
+ "languages": {
+ "title": "Sprachen",
+ "app_language": "App-Sprache",
+ "app_language_description": "Wรคhle die Sprache fรผr die App aus.",
+ "system": "System"
+ },
+ "toasts":{
+ "error_deleting_files": "Fehler beim Lรถschen von Dateien",
+ "background_downloads_enabled": "Hintergrunddownloads aktiviert",
+ "background_downloads_disabled": "Hintergrunddownloads deaktiviert",
+ "connected": "Verbunden",
+ "could_not_connect": "Konnte keine Verbindung herstellen",
+ "invalid_url": "Ungรผltige URL"
+ }
+ },
+ "downloads": {
+ "downloads_title": "Downloads",
+ "tvseries": "TV-Serien",
+ "movies": "Filme",
+ "queue": "Warteschlange",
+ "queue_hint": "Warteschlange und aktive Downloads gehen verloren bei App-Neustart",
+ "no_items_in_queue": "Keine Elemente in der Warteschlange",
+ "no_downloaded_items": "Keine heruntergeladenen Elemente",
+ "delete_all_movies_button": "Alle Filme lรถschen",
+ "delete_all_tvseries_button": "Alle TV-Serien lรถschen",
+ "delete_all_button": "Alles lรถschen",
+ "active_download": "Aktiver Download",
+ "no_active_downloads": "Keine aktiven Downloads",
+ "active_downloads": "Aktive Downloads",
+ "new_app_version_requires_re_download": "Die neue App-Version erfordert das erneute Herunterladen.",
+ "new_app_version_requires_re_download_description": "Die neue App-Version erfordert das erneute Herunterladen von Filmen und Serien. Bitte lรถsche alle heruntergeladenen Elemente und starte den Download erneut.",
+ "back": "Zurรผck",
+ "delete": "Lรถschen",
+ "something_went_wrong": "Etwas ist schiefgelaufen",
+ "could_not_get_stream_url_from_jellyfin": "Konnte keine Stream-URL von Jellyfin erhalten",
+ "eta": "ETA {{eta}}",
+ "methods": "Methoden",
+ "toasts": {
+ "you_are_not_allowed_to_download_files": "Du hast keine Berechtigung, Dateien herunterzuladen",
+ "deleted_all_movies_successfully": "Alle Filme erfolgreich gelรถscht!",
+ "failed_to_delete_all_movies": "Fehler beim Lรถschen aller Filme",
+ "deleted_all_tvseries_successfully": "Alle TV-Serien erfolgreich gelรถscht!",
+ "failed_to_delete_all_tvseries": "Fehler beim Lรถschen aller TV-Serien",
+ "download_cancelled": "Download abgebrochen",
+ "could_not_cancel_download": "Download konnte nicht abgebrochen werden",
+ "download_completed": "Download abgeschlossen",
+ "download_started_for": "Download fรผr {{item}} gestartet",
+ "item_is_ready_to_be_downloaded": "{{item}} ist bereit zum Herunterladen",
+ "download_stated_for_item": "Download fรผr {{item}} gestartet",
+ "download_failed_for_item": "Download fรผr {{item}} fehlgeschlagen - {{error}}",
+ "download_completed_for_item": "Download fรผr {{item}} ",
+ "queued_item_for_optimization": "{{item}} fรผr Optimierung in die Warteschlange gestellt",
+ "failed_to_start_download_for_item": "Download konnte fรผr {{item}} nicht gestartet werden: {{message}}",
+ "server_responded_with_status_code": "Server hat mit Status {{statusCode}} geantwortet",
+ "no_response_received_from_server": "Keine Antwort vom Server erhalten",
+ "error_setting_up_the_request": "Fehler beim Einrichten der Anfrage",
+ "failed_to_start_download_for_item_unexpected_error": "Fehler beim Starten des Downloads fรผr {{item}}: Unerwarteter Fehler",
+ "all_files_folders_and_jobs_deleted_successfully": "Alle Dateien, Ordner und Jobs erfolgreich gelรถscht",
+ "an_error_occured_while_deleting_files_and_jobs": "Ein Fehler ist beim Lรถschen von Dateien und Jobs aufgetreten",
+ "go_to_downloads": "Gehe zu den Downloads"
+ }
+ }
+ },
+ "search": {
+ "search_here": "Hier Suchen...",
+ "search": "Suche...",
+ "x_items": "{{count}} Elemente",
+ "library": "Bibliothek",
+ "discover": "Entdecken",
+ "no_results": "Keine Ergebnisse",
+ "no_results_found_for": "Keine Ergebnisse gefunden fรผr",
+ "movies": "Filme",
+ "series": "Serien",
+ "episodes": "Episoden",
+ "collections": "Sammlungen",
+ "actors": "Schauspieler",
+ "request_movies": "Film anfragen",
+ "request_series": "Serie anfragen",
+ "recently_added": "Kรผrzlich hinzugefรผgt",
+ "recent_requests": "Kรผrzlich angefragt",
+ "plex_watchlist": "Plex Watchlist",
+ "trending": "In den Trends",
+ "popular_movies": "Beliebte Filme",
+ "movie_genres": "Film-Genres",
+ "upcoming_movies": "Kommende Filme",
+ "studios": "Studios",
+ "popular_tv": "Beliebte TV-Serien",
+ "tv_genres": "TV-Serien-Genres",
+ "upcoming_tv": "Kommende TV-Serien",
+ "networks": "Netzwerke",
+ "tmdb_movie_keyword": "TMDB Film-Schlรผsselwort",
+ "tmdb_movie_genre": "TMDB Film-Genre",
+ "tmdb_tv_keyword": "TMDB TV-Serien-Schlรผsselwort",
+ "tmdb_tv_genre": "TMDB TV-Serien-Genre",
+ "tmdb_search": "TMDB Suche",
+ "tmdb_studio": "TMDB Studio",
+ "tmdb_network": "TMDB Netzwerk",
+ "tmdb_movie_streaming_services": "TMDB Film-Streaming-Dienste",
+ "tmdb_tv_streaming_services": "TMDB TV-Serien-Streaming-Dienste"
+ },
+ "library": {
+ "no_items_found": "Keine Elemente gefunden",
+ "no_results": "Keine Ergebnisse",
+ "no_libraries_found": "Keine Bibliotheken gefunden",
+ "item_types": {
+ "movies": "Filme",
+ "series": "Serien",
+ "boxsets": "Boxsets",
+ "items": "Elemente"
+ },
+ "options": {
+ "display": "Display",
+ "row": "Reihe",
+ "list": "Liste",
+ "image_style": "Bildstil",
+ "poster": "Poster",
+ "cover": "Cover",
+ "show_titles": "Titel anzeigen",
+ "show_stats": "Statistiken anzeigen"
+ },
+ "filters": {
+ "genres": "Genres",
+ "years": "Jahre",
+ "sort_by": "Sortieren nach",
+ "sort_order": "Sortierreihenfolge",
+ "tags": "Tags"
+ }
+ },
+ "favorites": {
+ "series": "Serien",
+ "movies": "Filme",
+ "episodes": "Episoden",
+ "videos": "Videos",
+ "boxsets": "Boxsets",
+ "playlists": "Playlists"
+ },
+ "custom_links": {
+ "no_links": "Keine Links"
+ },
+ "player": {
+ "error": "Fehler",
+ "failed_to_get_stream_url": "Fehler beim Abrufen der Stream-URL",
+ "an_error_occured_while_playing_the_video": "Ein Fehler ist beim Abspielen des Videos aufgetreten. รberprรผf die Logs in den Einstellungen.",
+ "client_error": "Client-Fehler",
+ "could_not_create_stream_for_chromecast": "Konnte keinen Stream fรผr Chromecast erstellen",
+ "message_from_server": "Nachricht vom Server: {{message}}",
+ "video_has_finished_playing": "Video wurde fertig abgespielt!",
+ "no_video_source": "Keine Videoquelle...",
+ "next_episode": "Nรคchste Episode",
+ "refresh_tracks": "Spuren aktualisieren",
+ "subtitle_tracks": "Untertitel-Spuren:",
+ "audio_tracks": "Audiospuren:",
+ "playback_state": "Wiedergabestatus:",
+ "no_data_available": "Keine Daten verfรผgbar",
+ "index": "Index:"
+ },
+ "item_card": {
+ "next_up": "Als nรคchstes",
+ "no_items_to_display": "Keine Elemente zum Anzeigen",
+ "cast_and_crew": "Besetzung und Crew",
+ "series": "Serien",
+ "seasons": "Staffeln",
+ "season": "Staffel",
+ "no_episodes_for_this_season": "Keine Episoden fรผr diese Staffel",
+ "overview": "รberblick",
+ "more_with": "Mehr mit {{name}}",
+ "similar_items": "รhnliche Elemente",
+ "no_similar_items_found": "Keine รคhnlichen Elemente gefunden",
+ "video": "Video",
+ "more_details": "Mehr Details",
+ "quality": "Qualitรคt",
+ "audio": "Audio",
+ "subtitles": "Untertitel",
+ "show_more": "Mehr anzeigen",
+ "show_less": "Weniger anzeigen",
+ "appeared_in": "Erschienen in",
+ "could_not_load_item": "Konnte Element nicht laden",
+ "none": "Keine",
+ "download": {
+ "download_season": "Staffel herunterladen",
+ "download_series": "Serie herunterladen",
+ "download_episode": "Episode herunterladen",
+ "download_movie": "Film herunterladen",
+ "download_x_item": "{{item_count}} Elemente herunterladen",
+ "download_button": "Herunterladen",
+ "using_optimized_server": "Verwende optimierten Server",
+ "using_default_method": "Verwende Standardmethode"
+ }
+ },
+ "live_tv": {
+ "next": "Nรคchster",
+ "previous": "Vorheriger",
+ "live_tv": "Live TV",
+ "coming_soon": "Demnรคchst",
+ "on_now": "Jetzt",
+ "shows": "Shows",
+ "movies": "Filme",
+ "sports": "Sport",
+ "for_kids": "Fรผr Kinder",
+ "news": "Nachrichten"
+ },
+ "jellyseerr":{
+ "confirm": "Bestรคtigen",
+ "cancel": "Abbrechen",
+ "yes": "Ja",
+ "whats_wrong": "Hast du Probleme?",
+ "issue_type": "Fehlerart",
+ "select_an_issue": "Wรคhle einen Fehlerart aus",
+ "types": "Arten",
+ "describe_the_issue": "(optional) Beschreibe das Problem",
+ "submit_button": "Absenden",
+ "report_issue_button": "Fehler melden",
+ "request_button": "Anfragen",
+ "are_you_sure_you_want_to_request_all_seasons": "Bist du sicher, dass du alle Staffeln anfragen mรถchtest?",
+ "failed_to_login": "Fehler beim Anmelden",
+ "cast": "Besetzung",
+ "details": "Details",
+ "status": "Status",
+ "original_title": "Original Titel",
+ "series_type": "Serien Typ",
+ "release_dates": "Verรถffentlichungsdaten",
+ "first_air_date": "Erstausstrahlungsdatum",
+ "next_air_date": "Nรคchstes Ausstrahlungsdatum",
+ "revenue": "Einnahmen",
+ "budget": "Budget",
+ "original_language": "Originalsprache",
+ "production_country": "Produktionsland",
+ "studios": "Studios",
+ "network": "Netzwerk",
+ "currently_streaming_on": "Derzeit im Streaming auf",
+ "advanced": "Erweitert",
+ "request_as": "Anfragen als",
+ "tags": "Tags",
+ "quality_profile": "Qualitรคtsprofil",
+ "root_folder": "Root-Ordner",
+ "season_x": "Staffel {{seasons}}",
+ "season_number": "Staffel {{season_number}}",
+ "number_episodes": "{{episode_number}} Episodes",
+ "born": "Geboren",
+ "appearances": "Auftritte",
+ "toasts": {
+ "jellyseer_does_not_meet_requirements": "Jellyseerr Server erfรผllt nicht die Anforderungsversion. Bitte aktualisiere deinen Jellyseerr Server auf mindestens 2.0.0",
+ "jellyseerr_test_failed": "Jellyseerr-Test fehlgeschlagen. Bitte versuche es erneut.",
+ "failed_to_test_jellyseerr_server_url": "Fehler beim Testen der Jellyseerr-Server-URL",
+ "issue_submitted": "Problem eingereicht!",
+ "requested_item": "{{item}} angefragt!",
+ "you_dont_have_permission_to_request": "Du hast keine Berechtigung Anfragen zu stellen",
+ "something_went_wrong_requesting_media": "Etwas ist schiefgelaufen beim Anfragen von Medien"
+ }
+ },
+ "tabs": {
+ "home": "Startseite",
+ "search": "Suche",
+ "library": "Bibliothek",
+ "custom_links": "Benutzerdefinierte Links",
+ "favorites": "Favoriten"
+ }
+}
diff --git a/translations/en.json b/translations/en.json
new file mode 100644
index 00000000..83caf7ae
--- /dev/null
+++ b/translations/en.json
@@ -0,0 +1,457 @@
+{
+ "login": {
+ "username_required": "Username is required",
+ "error_title": "Error",
+ "login_title": "Log in",
+ "login_to_title": "Log in to",
+ "username_placeholder": "Username",
+ "password_placeholder": "Password",
+ "login_button": "Log in",
+ "quick_connect": "Quick Connect",
+ "enter_code_to_login": "Enter code {{code}} to login",
+ "failed_to_initiate_quick_connect": "Failed to initiate Quick Connect",
+ "got_it": "Got it",
+ "connection_failed": "Connection failed",
+ "could_not_connect_to_server": "Could not connect to the server. Please check the URL and your network connection.",
+ "an_unexpected_error_occured": "An unexpected error occurred",
+ "change_server": "Change server",
+ "invalid_username_or_password": "Invalid username or password",
+ "user_does_not_have_permission_to_log_in": "User does not have permission to log in",
+ "server_is_taking_too_long_to_respond_try_again_later": "Server is taking too long to respond, try again later",
+ "server_received_too_many_requests_try_again_later": "Server received too many requests, try again later.",
+ "there_is_a_server_error": "There is a server error",
+ "an_unexpected_error_occured_did_you_enter_the_correct_url": "An unexpected error occurred. Did you enter the server URL correctly?"
+ },
+ "server": {
+ "enter_url_to_jellyfin_server": "Enter the URL to your Jellyfin server",
+ "server_url_placeholder": "http(s)://your-server.com",
+ "connect_button": "Connect",
+ "previous_servers": "previous servers",
+ "clear_button": "Clear",
+ "search_for_local_servers": "Search for local servers",
+ "searching": "Searching...",
+ "servers": "Servers"
+ },
+ "home": {
+ "no_internet": "No Internet",
+ "no_items": "No items",
+ "no_internet_message": "No worries, you can still watch\ndownloaded content.",
+ "go_to_downloads": "Go to downloads",
+ "oops": "Oops!",
+ "error_message": "Something went wrong.\nPlease log out and in again.",
+ "continue_watching": "Continue Watching",
+ "next_up": "Next Up",
+ "recently_added_in": "Recently Added in {{libraryName}}",
+ "suggested_movies": "Suggested Movies",
+ "suggested_episodes": "Suggested Episodes",
+ "intro": {
+ "welcome_to_streamyfin": "Welcome to Streamyfin",
+ "a_free_and_open_source_client_for_jellyfin": "A free and open-source client for Jellyfin.",
+ "features_title": "Features",
+ "features_description": "Streamyfin has a bunch of features and integrates with a wide array of software which you can find in the settings menu, these include:",
+ "jellyseerr_feature_description": "Connect to your Jellyseerr instance and request movies directly in the app.",
+ "downloads_feature_title": "Downloads",
+ "downloads_feature_description": "Download movies and tv-shows to view offline. Use either the default method or install the optimize server to download files in the background.",
+ "chromecast_feature_description": "Cast movies and tv-shows to your Chromecast devices.",
+ "centralised_settings_plugin_title": "Centralised Settings Plugin",
+ "centralised_settings_plugin_description": "Configure settings from a centralised location on your Jellyfin server. All client settings for all users will be synced automatically.",
+ "done_button": "Done",
+ "go_to_settings_button": "Go to settings",
+ "read_more": "Read more"
+ },
+ "settings": {
+ "settings_title": "Settings",
+ "log_out_button": "Log out",
+ "user_info": {
+ "user_info_title": "User Info",
+ "user": "User",
+ "server": "Server",
+ "token": "Token",
+ "app_version": "App Version"
+ },
+ "quick_connect": {
+ "quick_connect_title": "Quick Connect",
+ "authorize_button": "Authorize Quick Connect",
+ "enter_the_quick_connect_code": "Enter the quick connect code...",
+ "success": "Success",
+ "quick_connect_autorized": "Quick Connect authorized",
+ "error": "Error",
+ "invalid_code": "Invalid code",
+ "authorize": "Authorize"
+ },
+ "media_controls": {
+ "media_controls_title": "Media Controls",
+ "forward_skip_length": "Forward skip length",
+ "rewind_length": "Rewind length",
+ "seconds_unit": "s"
+ },
+ "audio": {
+ "audio_title": "Audio",
+ "set_audio_track": "Set Audio Track From Previous Item",
+ "audio_language": "Audio language",
+ "audio_hint": "Choose a default audio language.",
+ "none": "None",
+ "language": "Language"
+ },
+ "subtitles": {
+ "subtitle_title": "Subtitles",
+ "subtitle_language": "Subtitle language",
+ "subtitle_mode": "Subtitle Mode",
+ "set_subtitle_track": "Set Subtitle Track From Previous Item",
+ "subtitle_size": "Subtitle Size",
+ "subtitle_hint": "Configure subtitle preference.",
+ "none": "None",
+ "language": "Language",
+ "loading": "Loading",
+ "modes": {
+ "Default": "Default",
+ "Smart": "Smart",
+ "Always": "Always",
+ "None": "None",
+ "OnlyForced": "OnlyForced"
+ }
+ },
+ "other": {
+ "other_title": "Other",
+ "auto_rotate": "Auto rotate",
+ "video_orientation": "Video orientation",
+ "orientation": "Orientation",
+ "orientations": {
+ "DEFAULT": "Default",
+ "ALL": "All",
+ "PORTRAIT": "Portrait",
+ "PORTRAIT_UP": "Portrait Up",
+ "PORTRAIT_DOWN": "Portrait Down",
+ "LANDSCAPE": "Landscape",
+ "LANDSCAPE_LEFT": "Landscape Left",
+ "LANDSCAPE_RIGHT": "Landscape Right",
+ "OTHER": "Other",
+ "UNKNOWN": "Unknown"
+ },
+ "safe_area_in_controls": "Safe area in controls",
+ "show_custom_menu_links": "Show Custom Menu Links",
+ "hide_libraries": "Hide Libraries",
+ "select_liraries_you_want_to_hide": "Select the libraries you want to hide from the Library tab and home page sections.",
+ "disable_haptic_feedback": "Disable Haptic Feedback"
+ },
+ "downloads": {
+ "downloads_title": "Downloads",
+ "download_method": "Download method",
+ "remux_max_download": "Remux max download",
+ "auto_download": "Auto download",
+ "optimized_versions_server": "Optimized versions server",
+ "save_button": "Save",
+ "optimized_server": "Optimized Server",
+ "optimized": "Optimized",
+ "default": "Default",
+ "optimized_version_hint": "Enter the URL for the optimize server. The URL should include http or https and optionally the port.",
+ "read_more_about_optimized_server": "Read more about the optimize server.",
+ "url":"URL",
+ "server_url_placeholder": "http(s)://domain.org:port"
+ },
+ "plugins": {
+ "plugins_title": "Plugins",
+ "jellyseerr": {
+ "jellyseerr_warning": "This integration is in its early stages. Expect things to change.",
+ "server_url": "Server URL",
+ "server_url_hint": "Example: http(s)://your-host.url\n(add port if required)",
+ "server_url_placeholder": "Jellyseerr URL...",
+ "password": "Password",
+ "password_placeholder": "Enter password for Jellyfin user {{username}}",
+ "save_button": "Save",
+ "clear_button": "Clear",
+ "login_button": "Login",
+ "total_media_requests": "Total media requests",
+ "movie_quota_limit": "Movie quota limit",
+ "movie_quota_days": "Movie quota days",
+ "tv_quota_limit": "TV quota limit",
+ "tv_quota_days": "TV quota days",
+ "reset_jellyseerr_config_button": "Reset Jellyseerr config",
+ "unlimited": "Unlimited"
+ },
+ "marlin_search": {
+ "enable_marlin_search": "Enable Marlin Search ",
+ "url": "URL",
+ "server_url_placeholder": "http(s)://domain.org:port",
+ "marlin_search_hint": "Enter the URL for the Marlin server. The URL should include http or https and optionally the port.",
+ "read_more_about_marlin": "Read more about Marlin.",
+ "save_button": "Save",
+ "toasts": {
+ "saved": "Saved"
+ }
+ }
+ },
+ "storage": {
+ "storage_title": "Storage",
+ "app_usage": "App {{usedSpace}}%",
+ "device_usage": "Device {{availableSpace}}%",
+ "size_used": "{{used}} of {{total}} used",
+ "delete_all_downloaded_files": "Delete All Downloaded Files"
+ },
+ "intro": {
+ "show_intro": "Show intro",
+ "reset_intro": "Reset intro"
+ },
+ "logs": {
+ "logs_title": "Logs",
+ "no_logs_available": "No logs available",
+ "delete_all_logs": "Delete all logs"
+ },
+ "languages": {
+ "title": "Languages",
+ "app_language": "App language",
+ "app_language_description": "Select the language for the app.",
+ "system": "System"
+ },
+ "toasts":{
+ "error_deleting_files": "Error deleting files",
+ "background_downloads_enabled": "Background downloads enabled",
+ "background_downloads_disabled": "Background downloads disabled",
+ "connected": "Connected",
+ "could_not_connect": "Could not connect",
+ "invalid_url": "Invalid URL"
+ }
+ },
+ "downloads": {
+ "downloads_title": "Downloads",
+ "tvseries": "TV-Series",
+ "movies": "Movies",
+ "queue": "Queue",
+ "queue_hint": "Queue and downloads will be lost on app restart",
+ "no_items_in_queue": "No items in queue",
+ "no_downloaded_items": "No downloaded items",
+ "delete_all_movies_button": "Delete all Movies",
+ "delete_all_tvseries_button": "Delete all TV-Series",
+ "delete_all_button": "Delete all",
+ "active_download": "Active download",
+ "no_active_downloads": "No active downloads",
+ "active_downloads": "Active downloads",
+ "new_app_version_requires_re_download": "New app version requires re-download",
+ "new_app_version_requires_re_download_description": "The new update requires content to be downloaded again. Please remove all downloaded content and try again.",
+ "back": "Back",
+ "delete": "Delete",
+ "something_went_wrong": "Something went wrong",
+ "could_not_get_stream_url_from_jellyfin": "Could not get the stream URL from Jellyfin",
+ "eta": "ETA {{eta}}",
+ "methods": "Methods",
+ "toasts": {
+ "you_are_not_allowed_to_download_files": "You are not allowed to download files.",
+ "deleted_all_movies_successfully": "Deleted all movies successfully!",
+ "failed_to_delete_all_movies": "Failed to delete all movies",
+ "deleted_all_tvseries_successfully": "Deleted all TV-Series successfully!",
+ "failed_to_delete_all_tvseries": "Failed to delete all TV-Series",
+ "download_cancelled": "Download cancelled",
+ "could_not_cancel_download": "Could not cancel download",
+ "download_completed": "Download completed",
+ "download_started_for": "Download started for {{item}}",
+ "item_is_ready_to_be_downloaded": "{{item}} is ready to be downloaded",
+ "download_stated_for_item": "Download started for {{item}}",
+ "download_failed_for_item": "Download failed for {{item}} - {{error}}",
+ "download_completed_for_item": "Download completed for {{item}}",
+ "queued_item_for_optimization": "Queued {{item}} for optimization",
+ "failed_to_start_download_for_item": "Failed to start downloading for {{item}}: {{message}}",
+ "server_responded_with_status_code": "Server responded with status {{statusCode}}",
+ "no_response_received_from_server": "No response received from the server",
+ "error_setting_up_the_request": "Error setting up the request",
+ "failed_to_start_download_for_item_unexpected_error": "Failed to start downloading for {{item}}: Unexpected error",
+ "all_files_folders_and_jobs_deleted_successfully": "All files, folders, and jobs deleted successfully",
+ "an_error_occured_while_deleting_files_and_jobs": "An error occurred while deleting files and jobs",
+ "go_to_downloads": "Go to downloads"
+ }
+ }
+ },
+ "search": {
+ "search_here": "Search here...",
+ "search": "Search...",
+ "x_items": "{{count}} items",
+ "library": "Library",
+ "discover": "Discover",
+ "no_results": "No results",
+ "no_results_found_for": "No results found for",
+ "movies": "Movies",
+ "series": "Series",
+ "episodes": "Episodes",
+ "collections": "Collections",
+ "actors": "Actors",
+ "request_movies": "Request Movies",
+ "request_series": "Request Series",
+ "recently_added": "Recently Added",
+ "recent_requests": "Recent Requests",
+ "plex_watchlist": "Plex Watchlist",
+ "trending": "Trending",
+ "popular_movies": "Popular Movies",
+ "movie_genres": "Movie Genres",
+ "upcoming_movies": "Upcoming Movies",
+ "studios": "Studios",
+ "popular_tv": "Popular TV",
+ "tv_genres": "TV Genres",
+ "upcoming_tv": "Upcoming TV",
+ "networks": "Networks",
+ "tmdb_movie_keyword": "TMDB Movie Keyword",
+ "tmdb_movie_genre": "TMDB Movie Genre",
+ "tmdb_tv_keyword": "TMDB TV Keyword",
+ "tmdb_tv_genre": "TMDB TV Genre",
+ "tmdb_search": "TMDB Search",
+ "tmdb_studio": "TMDB Studio",
+ "tmdb_network": "TMDB Network",
+ "tmdb_movie_streaming_services": "TMDB Movie Streaming Services",
+ "tmdb_tv_streaming_services": "TMDB TV Streaming Services"
+ },
+ "library": {
+ "no_items_found": "No items found",
+ "no_results": "No results",
+ "no_libraries_found": "No libraries found",
+ "item_types": {
+ "movies": "movies",
+ "series": "series",
+ "boxsets": "box sets",
+ "items": "items"
+ },
+ "options": {
+ "display": "Display",
+ "row": "Row",
+ "list": "List",
+ "image_style": "Image style",
+ "poster": "Poster",
+ "cover": "Cover",
+ "show_titles": "Show titles",
+ "show_stats": "Show stats"
+ },
+ "filters": {
+ "genres": "Genres",
+ "years": "Years",
+ "sort_by": "Sort By",
+ "sort_order": "Sort Order",
+ "tags": "Tags"
+ }
+ },
+ "favorites": {
+ "series": "Series",
+ "movies": "Movies",
+ "episodes": "Episodes",
+ "videos": "Videos",
+ "boxsets": "Boxsets",
+ "playlists": "Playlists"
+ },
+ "custom_links": {
+ "no_links": "No links"
+ },
+ "player": {
+ "error": "Error",
+ "failed_to_get_stream_url": "Failed to get the stream URL",
+ "an_error_occured_while_playing_the_video": "An error occurred while playing the video. Check logs in settings.",
+ "client_error": "Client error",
+ "could_not_create_stream_for_chromecast": "Could not create a stream for Chromecast",
+ "message_from_server": "Message from server: {{message}}",
+ "video_has_finished_playing": "Video has finished playing!",
+ "no_video_source": "No video source...",
+ "next_episode": "Next Episode",
+ "refresh_tracks": "Refresh Tracks",
+ "subtitle_tracks": "Subtitle Tracks:",
+ "audio_tracks": "Audio Tracks:",
+ "playback_state": "Playback State:",
+ "no_data_available": "No data available",
+ "index": "Index:"
+ },
+ "item_card": {
+ "next_up": "Next up",
+ "no_items_to_display": "No items to display",
+ "cast_and_crew": "Cast & Crew",
+ "series": "Series",
+ "seasons": "Seasons",
+ "season": "Season",
+ "no_episodes_for_this_season": "No episodes for this season",
+ "overview": "Overview",
+ "more_with": "More with {{name}}",
+ "similar_items": "Similar items",
+ "no_similar_items_found": "No similar items found",
+ "video": "Video",
+ "more_details": "More details",
+ "quality": "Quality",
+ "audio": "Audio",
+ "subtitles": "Subtitle",
+ "show_more": "Show more",
+ "show_less": "Show less",
+ "appeared_in": "Appeared in",
+ "could_not_load_item": "Could not load item",
+ "none": "None",
+ "download": {
+ "download_season": "Download Season",
+ "download_series": "Download Series",
+ "download_episode": "Download Episode",
+ "download_movie": "Download Movie",
+ "download_x_item": "Download {{item_count}} items",
+ "download_button": "Download",
+ "using_optimized_server": "Using optimized server",
+ "using_default_method": "Using default method"
+ }
+ },
+ "live_tv": {
+ "next": "Next",
+ "previous": "Previous",
+ "live_tv": "Live TV",
+ "coming_soon": "Coming soon",
+ "on_now": "On now",
+ "shows": "Shows",
+ "movies": "Movies",
+ "sports": "Sports",
+ "for_kids": "For Kids",
+ "news": "News"
+ },
+ "jellyseerr":{
+ "confirm": "Confirm",
+ "cancel": "Cancel",
+ "yes": "Yes",
+ "whats_wrong": "What's wrong?",
+ "issue_type": "Issue type",
+ "select_an_issue": "Select an issue",
+ "types": "Types",
+ "describe_the_issue": "(optional) Describe the issue...",
+ "submit_button": "Submit",
+ "report_issue_button": "Report issue",
+ "request_button": "Request",
+ "are_you_sure_you_want_to_request_all_seasons": "Are you sure you want to request all seasons?",
+ "failed_to_login": "Failed to login",
+ "cast": "Cast",
+ "details": "Details",
+ "status": "Status",
+ "original_title": "Original Title",
+ "series_type": "Series Type",
+ "release_dates": "Release Dates",
+ "first_air_date": "First Air Date",
+ "next_air_date": "Next Air Date",
+ "revenue": "Revenue",
+ "budget": "Budget",
+ "original_language": "Original Language",
+ "production_country": "Production Country",
+ "studios": "Studios",
+ "network": "Network",
+ "currently_streaming_on": "Currently Streaming on",
+ "advanced": "Advanced",
+ "request_as": "Request As",
+ "tags": "Tags",
+ "quality_profile": "Quality Profile",
+ "root_folder": "Root Folder",
+ "season_x": "Season {{seasons}}",
+ "season_number": "Season {{season_number}}",
+ "number_episodes": "{{episode_number}} Episodes",
+ "born": "Born",
+ "appearances": "Appearances",
+ "toasts": {
+ "jellyseer_does_not_meet_requirements": "Jellyseerr server does not meet minimum version requirements! Please update to at least 2.0.0",
+ "jellyseerr_test_failed": "Jellyseerr test failed. Please try again.",
+ "failed_to_test_jellyseerr_server_url": "Failed to test jellyseerr server url",
+ "issue_submitted": "Issue submitted!",
+ "requested_item": "Requested {{item}}!",
+ "you_dont_have_permission_to_request": "You don't have permission to request!",
+ "something_went_wrong_requesting_media": "Something went wrong requesting media!"
+ }
+ },
+ "tabs": {
+ "home": "Home",
+ "search": "Search",
+ "library": "Library",
+ "custom_links": "Custom Links",
+ "favorites": "Favorites"
+ }
+}
diff --git a/translations/es.json b/translations/es.json
new file mode 100644
index 00000000..55890beb
--- /dev/null
+++ b/translations/es.json
@@ -0,0 +1,457 @@
+{
+ "login": {
+ "username_required": "Se requiere un nombre de usuario",
+ "error_title": "Error",
+ "login_title": "Iniciar sesiรณn",
+ "login_to_title": "Iniciar sesiรณn en",
+ "username_placeholder": "Nombre de usuario",
+ "password_placeholder": "Contraseรฑa",
+ "login_button": "Iniciar sesiรณn",
+ "quick_connect": "Conexiรณn rรกpida",
+ "enter_code_to_login": "Introduce el cรณdigo {{code}} para iniciar sesiรณn",
+ "failed_to_initiate_quick_connect": "Error al iniciar la conexiรณn rรกpida",
+ "got_it": "Entendido",
+ "connection_failed": "Conexiรณn fallida",
+ "could_not_connect_to_server": "No se pudo conectar al servidor. Por favor comprueba la URL y tu conexiรณn de red.",
+ "an_unexpected_error_occured": "Ha ocurrido un error inesperado",
+ "change_server": "Cambiar servidor",
+ "invalid_username_or_password": "Usuario o contraseรฑa invรกlidos",
+ "user_does_not_have_permission_to_log_in": "El usuario no tiene permiso para iniciar sesiรณn",
+ "server_is_taking_too_long_to_respond_try_again_later": "El servidor estรก tardando mucho en responder, intรฉntalo de nuevo mรกs tarde.",
+ "server_received_too_many_requests_try_again_later": "El servidor estรก recibiendo muchas peticiones, intรฉntalo de nuevo mรกs tarde.",
+ "there_is_a_server_error": "Hay un error en el servidor",
+ "an_unexpected_error_occured_did_you_enter_the_correct_url": "Ha ocurrido un error inesperado. ยฟHas introducido la URL correcta?"
+ },
+ "server": {
+ "enter_url_to_jellyfin_server": "Introduce la URL de tu servidor Jellyfin",
+ "server_url_placeholder": "http(s)://tu-servidor.com",
+ "connect_button": "Conectar",
+ "previous_servers": "Servidores previos",
+ "clear_button": "Limpiar",
+ "search_for_local_servers": "Buscar servidores locales",
+ "searching": "Buscando...",
+ "servers": "Servidores"
+ },
+ "home": {
+ "no_internet": "Sin internet",
+ "no_items": "No hay รญtems",
+ "no_internet_message": "No te preocupes, todavรญa puedes\nver el contenido descargado.",
+ "go_to_downloads": "Ir a descargas",
+ "oops": "ยกVaya!",
+ "error_message": "Algo ha salido mal.\nPor favor, cierra la sesiรณn y vuelve a iniciar.",
+ "continue_watching": "Seguir viendo",
+ "next_up": "A continuaciรณn",
+ "recently_added_in": "Recientemente aรฑadido en {{libraryName}}",
+ "suggested_movies": "Pelรญculas sugeridas",
+ "suggested_episodes": "Episodios sugeridos",
+ "intro": {
+ "welcome_to_streamyfin": "Bienvenido a Streamyfin",
+ "a_free_and_open_source_client_for_jellyfin": "Un cliente gratuito y de cรณdigo abierto para Jellyfin.",
+ "features_title": "Caracterรญsticas",
+ "features_description": "Streamyfin tiene una amplia gama de caracterรญsticas y se integra con una variedad de software que puedes encontrar en el menรบ de configuraciรณn, esto incluye:",
+ "jellyseerr_feature_description": "Conรฉctate a tu servidor de Jellyseer y pide pelรญculas directamente desde la app.",
+ "downloads_feature_title": "Descargas",
+ "downloads_feature_description": "Descarga pelรญculas y series para ver sin conexiรณn. Usa el mรฉtodo por defecto o el servidor optimizado para descargar archivos en segundo plano.",
+ "chromecast_feature_description": "Envรญa pelรญcuas y series a tus dispositivos Chromecast.",
+ "centralised_settings_plugin_title": "Plugin de configuraciรณn centralizada",
+ "centralised_settings_plugin_description": "Crea configuraciones desde una ubicaciรณn centralizada en tu servidor de Jellyfin. Todas las configuraciones para todos los usuarios se sincronizarรกn automรกticamente.",
+ "done_button": "Hecho",
+ "go_to_settings_button": "Ir a la configuraciรณn",
+ "read_more": "Leer mรกs"
+ },
+ "settings": {
+ "settings_title": "Configuraciรณn",
+ "log_out_button": "Cerrar sesiรณn",
+ "user_info": {
+ "user_info_title": "Informaciรณn de usuario",
+ "user": "Usuario",
+ "server": "Servidor",
+ "token": "Token",
+ "app_version": "Versiรณn de la app"
+ },
+ "quick_connect": {
+ "quick_connect_title": "Conexiรณn rรกpida",
+ "authorize_button": "Autorizar conexiรณn rรกpida",
+ "enter_the_quick_connect_code": "Introduce el cรณdigo de conexiรณn rรกpida...",
+ "success": "Hecho",
+ "quick_connect_autorized": "Conexiรณn rรกpida autorizada",
+ "error": "Error",
+ "invalid_code": "Cรณdigo invรกlido",
+ "authorize": "Autorizar"
+ },
+ "media_controls": {
+ "media_controls_title": "Controles de reproducciรณn",
+ "forward_skip_length": "Longitud de avance",
+ "rewind_length": "Longitud de retroceso",
+ "seconds_unit": "s"
+ },
+ "audio": {
+ "audio_title": "Audio",
+ "set_audio_track": "Establecer pista de audio del elemento anterior",
+ "audio_language": "Idioma de audio",
+ "audio_hint": "Elige un idioma de audio por defecto.",
+ "none": "Ninguno",
+ "language": "Idioma"
+ },
+ "subtitles": {
+ "subtitle_title": "Subtรญtulos",
+ "subtitle_language": "Idioma de subtรญtulos",
+ "subtitle_mode": "Modo de subtรญtulos",
+ "set_subtitle_track": "Establecer pista de subtรญtulos del elemento anterior",
+ "subtitle_size": "Tamaรฑo de subtรญtulos",
+ "subtitle_hint": "Configurar preferencias de subtรญtulos.",
+ "none": "Ninguno",
+ "language": "Idioma",
+ "loading": "Cargando",
+ "modes": {
+ "Default": "Por defecto",
+ "Smart": "Inteligente",
+ "Always": "Siempre",
+ "None": "Nada",
+ "OnlyForced": "Solo forzados"
+ }
+ },
+ "other": {
+ "other_title": "Otros",
+ "auto_rotate": "Rotaciรณn automรกtica",
+ "video_orientation": "Orientaciรณn de vรญdeo",
+ "orientation": "Orientaciรณn",
+ "orientations": {
+ "DEFAULT": "Por defecto",
+ "ALL": "Todas",
+ "PORTRAIT": "Vertical",
+ "PORTRAIT_UP": "Vertical arriba",
+ "PORTRAIT_DOWN": "Vertical abajo",
+ "LANDSCAPE": "Horizontal",
+ "LANDSCAPE_LEFT": "Horizontal izquierda",
+ "LANDSCAPE_RIGHT": "Horizontal derecha",
+ "OTHER": "Otra",
+ "UNKNOWN": "Desconocida"
+ },
+ "safe_area_in_controls": "รrea segura en controles",
+ "show_custom_menu_links": "Mostrar enlaces de menรบ personalizados",
+ "hide_libraries": "Ocultar bibliotecas",
+ "select_liraries_you_want_to_hide": "Selecciona las bibliotecas que quieres ocultar de la pestaรฑa Bibliotecas y de Inicio.",
+ "disable_haptic_feedback": "Desactivar feedback hรกptico"
+ },
+ "downloads": {
+ "downloads_title": "Descargas",
+ "download_method": "Mรฉtodo de descarga",
+ "remux_max_download": "Remux mรกx. descarga",
+ "auto_download": "Descarga automรกtica",
+ "optimized_versions_server": "Servidor de versiones optimizadas",
+ "save_button": "Guardar",
+ "optimized_server": "Servidor optimizado",
+ "optimized": "Optimizado",
+ "default": "Por defecto",
+ "optimized_version_hint": "Introduce la URL del servidor de versiones optimizadas. La URL debe incluir http o https y opcionalmente el puerto.",
+ "read_more_about_optimized_server": "Leer mรกs sobre el servidor de versiones optimizadas.",
+ "url": "URL",
+ "server_url_placeholder": "http(s)://dominio.org:puerto"
+ },
+ "plugins": {
+ "plugins_title": "Plugins",
+ "jellyseerr": {
+ "jellyseerr_warning": "Esta integraciรณn estรก en sus primeras etapas. Cuenta con posibles cambios.",
+ "server_url": "URL del servidor",
+ "server_url_hint": "Ejemplo: http(s)://tu-dominio.url\n(aรฑade el puerto si es necesario)",
+ "server_url_placeholder": "URL de Jellyseerr...",
+ "password": "Contrasรฑea",
+ "password_placeholder": "Introduce la contraseรฑa de Jellyfin de {{username}}",
+ "save_button": "Guardar",
+ "clear_button": "Limpiar",
+ "login_button": "Iniciar sesiรณn",
+ "total_media_requests": "Peticiones totales de medios",
+ "movie_quota_limit": "Lรญmite de cuota de pelรญculas",
+ "movie_quota_days": "Dรญas de cuota de pelรญculas",
+ "tv_quota_limit": "Lรญmite de cuota de series",
+ "tv_quota_days": "Dรญas de cuota de series",
+ "reset_jellyseerr_config_button": "Restablecer configuraciรณn de Jellyseerr",
+ "unlimited": "Ilimitado"
+ },
+ "marlin_search": {
+ "enable_marlin_search": "Habilitar bรบsqueda de Marlin",
+ "url": "URL",
+ "server_url_placeholder": "http(s)://dominio.org:puerto",
+ "marlin_search_hint": "Introduce la URL del servidor de Marlin. La URL debe incluir http o https y opcionalmente el puerto.",
+ "read_more_about_marlin": "Leer mรกs sobre Marlin.",
+ "save_button": "Guardar",
+ "toasts": {
+ "saved": "Guardado"
+ }
+ }
+ },
+ "storage": {
+ "storage_title": "Almacenamiento",
+ "app_usage": "App {{usedSpace}}%",
+ "phone_usage": "Dispositivo {{availableSpace}}%",
+ "size_used": "{{used}} de {{total}} usado",
+ "delete_all_downloaded_files": "Eliminar todos los archivos descargados"
+ },
+ "intro": {
+ "show_intro": "Mostrar intro",
+ "reset_intro": "Restablecer intro"
+ },
+ "logs": {
+ "logs_title": "Registros",
+ "no_logs_available": "No hay registros disponibles",
+ "delete_all_logs": "Eliminar todos los registros"
+ },
+ "languages": {
+ "title": "Idiomas",
+ "app_language": "Idioma de la app",
+ "app_language_description": "Selecciona el idioma de la app.",
+ "system": "Sistema"
+ },
+ "toasts":{
+ "error_deleting_files": "Error al eliminar archivos",
+ "background_downloads_enabled": "Descargas en segundo plano habilitadas",
+ "background_downloads_disabled": "Descargas en segundo plano deshabilitadas",
+ "connected": "Conectado",
+ "could_not_connect": "No se pudo conectar",
+ "invalid_url": "URL invรกlida"
+ }
+ },
+ "downloads": {
+ "downloads_title": "Descargas",
+ "tvseries": "Series",
+ "movies": "Pelรญculas",
+ "queue": "Cola",
+ "queue_hint": "La cola de series y pelรญculas se perderรก al reiniciar la app",
+ "no_items_in_queue": "No hay รญtems en la cola",
+ "no_downloaded_items": "No hay รญtems descargados",
+ "delete_all_movies_button": "Eliminar todas las pelรญculas",
+ "delete_all_tvseries_button": "Eliminar todas las series",
+ "delete_all_button": "Eliminar todo",
+ "active_download": "Descarga activa",
+ "no_active_downloads": "No hay descargas activas",
+ "active_downloads": "Descargas activas",
+ "new_app_version_requires_re_download": "La nueva actualizaciรณn requiere volver a descargar",
+ "new_app_version_requires_re_download_description": "La nueva actualizaciรณn requiere volver a descargar el contenido. Por favor, elimina todo el cรณdigo descargado y vuรฉlvelo a intentar.",
+ "back": "Atrรกs",
+ "delete": "Borrar",
+ "something_went_wrong": "Algo ha salido mal",
+ "could_not_get_stream_url_from_jellyfin": "No se pudo obtener la URL del stream de Jellyfin",
+ "eta": "{{eta}} restante",
+ "methods": "Mรฉtodos",
+ "toasts": {
+ "you_are_not_allowed_to_download_files": "No tienes permiso para descargar archivos.",
+ "deleted_all_movies_successfully": "ยกTodas las pelรญculas eliminadas con รฉxito!",
+ "failed_to_delete_all_movies": "Error al eliminar todas las pelรญculas",
+ "deleted_all_tvseries_successfully": "ยกTodas las series eliminadas con รฉxito!",
+ "failed_to_delete_all_tvseries": "Error al eliminar todas las series",
+ "download_cancelled": "Descarga cancelada",
+ "could_not_cancel_download": "No se pudo cancelar la descarga",
+ "download_completed": "Descarga completada",
+ "download_started_for": "Descarga iniciada para {{item}}",
+ "item_is_ready_to_be_downloaded": "{{item}} estรก listo para ser descargado",
+ "download_stated_for_item": "Descarga iniciada para {{item}}",
+ "download_failed_for_item": "Descarga fallida para {{item}} - {{error}}",
+ "download_completed_for_item": "Descarga completada para {{item}}",
+ "queued_item_for_optimization": "{{item}} en cola para optimizaciรณn",
+ "failed_to_start_download_for_item": "Error al iniciar la descarga para {{item}}: {{message}}",
+ "server_responded_with_status_code": "El servidor ha respondido con el estado {{statusCode}}",
+ "no_response_received_from_server": "No se ha recibido respuesta del servidor",
+ "error_setting_up_the_request": "Error al configurar la peticiรณn",
+ "failed_to_start_download_for_item_unexpected_error": "Error al iniciar la descarga para {{item}}: Error inesperado",
+ "all_files_folders_and_jobs_deleted_successfully": "Todos los archivos, carpetas y trabajos eliminados con รฉxito",
+ "an_error_occured_while_deleting_files_and_jobs": "Ha ocurrido un error al eliminar archivos y trabajos",
+ "go_to_downloads": "Ir a descargas"
+ }
+ }
+ },
+ "search": {
+ "search_here": "Buscar aquรญ...",
+ "search": "Buscar...",
+ "x_items": "{{count}} รญtems",
+ "library": "Biblioteca",
+ "discover": "Descubrir",
+ "no_results": "Sin resultados",
+ "no_results_found_for": "No se han encontrado resultados para",
+ "movies": "Pelรญculas",
+ "series": "Series",
+ "episodes": "Episodios",
+ "collections": "Colecciones",
+ "actors": "Actores",
+ "request_movies": "Solicitar pelรญculas",
+ "request_series": "Solicitar series",
+ "recently_added": "Recientemente aรฑadido",
+ "recent_requests": "Solicitudes recientes",
+ "plex_watchlist": "Lista de seguimiento de Plex",
+ "trending": "Trending",
+ "popular_movies": "Pelรญculas populares",
+ "movie_genres": "Gรฉneros de pelรญculas",
+ "upcoming_movies": "Prรณximas pelรญculas",
+ "studios": "Estudios",
+ "popular_tv": "Series populares",
+ "tv_genres": "Gรฉneros de series",
+ "upcoming_tv": "Prรณximas series",
+ "networks": "Cadenas",
+ "tmdb_movie_keyword": "Palabra clave de pelรญcula de TMDB",
+ "tmdb_movie_genre": "Gรฉnero de pelรญcula de TMDB",
+ "tmdb_tv_keyword": "Palabra clave de serie de TMDB",
+ "tmdb_tv_genre": "Gรฉnero de serie de TMDB",
+ "tmdb_search": "Bรบsqueda de TMDB",
+ "tmdb_studio": "Estudio de TMDB",
+ "tmdb_network": "Cadena de TMDB",
+ "tmdb_movie_streaming_services": "Servicios de streaming de pelรญculas de TMDB",
+ "tmdb_tv_streaming_services": "Servicios de streaming de series de TMDB"
+ },
+ "library": {
+ "no_items_found": "No se han encontrado รญtems",
+ "no_results": "Sin resultados",
+ "no_libraries_found": "No se han encontrado bibliotecas",
+ "item_types": {
+ "movies": "pelรญculas",
+ "series": "series",
+ "boxsets": "colecciones",
+ "items": "รญtems"
+ },
+ "options": {
+ "display": "Mostrar",
+ "row": "Fila",
+ "list": "Lista",
+ "image_style": "Estilo de imagen",
+ "poster": "Poster",
+ "cover": "Portada",
+ "show_titles": "Mostrar tรญtulos",
+ "show_stats": "Mostrar estadรญsticas"
+ },
+ "filters": {
+ "genres": "Gรฉneros",
+ "years": "Aรฑos",
+ "sort_by": "Ordenar por",
+ "sort_order": "Ordenar",
+ "tags": "Etiquetas"
+ }
+ },
+ "favorites": {
+ "series": "Series",
+ "movies": "Pelรญculas",
+ "episodes": "Episodios",
+ "videos": "Vรญdeos",
+ "boxsets": "Colecciones",
+ "playlists": "Playlists"
+ },
+ "custom_links": {
+ "no_links": "Sin enlaces"
+ },
+ "player": {
+ "error": "Error",
+ "failed_to_get_stream_url": "Error al obtener la URL del stream",
+ "an_error_occured_while_playing_the_video": "Ha ocurrido un error al reproducir el vรญdeo. Comprueba los registros en la configuraciรณn.",
+ "client_error": "Error del cliente",
+ "could_not_create_stream_for_chromecast": "No se pudo crear el stream para Chromecast",
+ "message_from_server": "Mensaje del servidor: {{message}}",
+ "video_has_finished_playing": "El vรญdeo ha terminado de reproducirse",
+ "no_video_source": "No hay fuente de vรญdeo...",
+ "next_episode": "Siguiente episodio",
+ "refresh_tracks": "Refrescar pistas",
+ "subtitle_tracks": "Pistas de subtรญtulos:",
+ "audio_tracks": "Pistas de audio:",
+ "playback_state": "Estado de la reproducciรณn:",
+ "no_data_available": "No hay datos disponibles",
+ "index": "รndice:"
+ },
+ "item_card": {
+ "next_up": "A continuaciรณn",
+ "no_items_to_display": "No hay รญtems para mostrar",
+ "cast_and_crew": "Reparto y equipo",
+ "series": "Series",
+ "seasons": "Temporadas",
+ "season": "Temporada",
+ "no_episodes_for_this_season": "No hay episodios para esta temporada",
+ "overview": "Resumen",
+ "more_with": "Mรกs con {{name}}",
+ "similar_items": "รtems similares",
+ "no_similar_items_found": "No se han encontrado รญtems similares",
+ "video": "Vรญdeo",
+ "more_details": "Mรกs detalles",
+ "quality": "Calidad",
+ "audio": "Audio",
+ "subtitles": "Subtรญtulos",
+ "show_more": "Mostrar mรกs",
+ "show_less": "Mostrar menos",
+ "appeared_in": "Apareciรณ en",
+ "could_not_load_item": "No se pudo cargar el รญtem",
+ "none": "Ninguno",
+ "download": {
+ "download_season": "Descargar temporada",
+ "download_series": "Descargar serie",
+ "download_episode": "Descargar episodio",
+ "download_movie": "Descargar pelรญcula",
+ "download_x_item": "Descargar {{item_count}} รญtems",
+ "download_button": "Descargar",
+ "using_optimized_server": "Usando servidor optimizado",
+ "using_default_method": "Usando mรฉtodo por defecto"
+ }
+ },
+ "live_tv": {
+ "next": "Siguiente",
+ "previous": "Anterior",
+ "live_tv": "TV en directo",
+ "coming_soon": "Prรณximamente",
+ "on_now": "En directo",
+ "shows": "Programas",
+ "movies": "Pelรญculas",
+ "sports": "Deportes",
+ "for_kids": "Para niรฑos",
+ "news": "Noticias"
+ },
+ "jellyseerr":{
+ "confirm": "Confirmar",
+ "cancel": "Cancelar",
+ "yes": "Sรญ",
+ "whats_wrong": "ยฟQuรฉ pasa?",
+ "issue_type": "Tipo de problema",
+ "select_an_issue": "Selecciona un problema",
+ "types": "Tipos",
+ "describe_the_issue": "(opcional) Describe el problema...",
+ "submit_button": "Enviar",
+ "report_issue_button": "Reportar problema",
+ "request_button": "Solicitar",
+ "are_you_sure_you_want_to_request_all_seasons": "ยฟEstรกs seguro de que quieres solicitar todas las temporadas?",
+ "failed_to_login": "Error al iniciar sesiรณn",
+ "cast": "Reparto",
+ "details": "Detalles",
+ "status": "Estado",
+ "original_title": "Tรญtulo original",
+ "series_type": "Tipo de serie",
+ "release_dates": "Fechas de estreno",
+ "first_air_date": "Primera fecha de emisiรณn",
+ "next_air_date": "Prรณxima fecha de emisiรณn",
+ "revenue": "Ingresos",
+ "budget": "Presupuesto",
+ "original_language": "Idioma original",
+ "production_country": "Paรญs de producciรณn",
+ "studios": "Estudios",
+ "network": "Cadena",
+ "currently_streaming_on": "Actualmente en streaming en",
+ "advanced": "Avanzado",
+ "request_as": "Solicitar como",
+ "tags": "Etiquetas",
+ "quality_profile": "Perfil de calidad",
+ "root_folder": "Carpeta raรญz",
+ "season_x": "Temporada {{seasons}}",
+ "season_number": "Temporada {{season_number}}",
+ "number_episodes": "{{episode_number}} episodios",
+ "born": "Nacido",
+ "appearances": "Apariciones",
+ "toasts": {
+ "jellyseer_does_not_meet_requirements": "ยกJellyseer no cumple con los requisitos! Por favor, actualรญzalo al menos a la versiรณn 2.0.0.",
+ "jellyseerr_test_failed": "La prueba de Jellyseerr ha fallado. Por favor intรฉntalo de nuevo.",
+ "failed_to_test_jellyseerr_server_url": "Error al probar la URL del servidor de Jellyseerr",
+ "issue_submitted": "ยกProblema enviado!",
+ "requested_item": "ยก{{item}} solicitado!",
+ "you_dont_have_permission_to_request": "ยกNo tienes permiso para solicitar!",
+ "something_went_wrong_requesting_media": "ยกAlgo ha salido mal solicitando los medios!"
+ }
+ },
+ "tabs": {
+ "home": "Inicio",
+ "search": "Buscar",
+ "library": "Bibliotecas",
+ "custom_links": "Enlaces personalizados",
+ "favorites": "Favoritos"
+ }
+}
diff --git a/translations/fr.json b/translations/fr.json
new file mode 100644
index 00000000..e9fdbbf6
--- /dev/null
+++ b/translations/fr.json
@@ -0,0 +1,457 @@
+{
+ "login": {
+ "username_required": "Nom d'utilisateur requis",
+ "error_title": "Erreur",
+ "login_title": "Se connecter",
+ "login_to_title": "Se connecter ร ",
+ "username_placeholder": "Nom d'utilisateur",
+ "password_placeholder": "Mot de passe",
+ "login_button": "Se connecter",
+ "quick_connect": "Connexion Rapide",
+ "enter_code_to_login": "Entrez le code {{code}} pour vous connecter",
+ "failed_to_initiate_quick_connect": "รchec de l'initialisation de Connexion Rapide",
+ "got_it": "D'accord",
+ "connection_failed": "La connexion a รฉchouรฉ",
+ "could_not_connect_to_server": "Impossible de se connecter au serveur. Veuillez vรฉrifier l'URL et votre connection rรฉseau.",
+ "an_unexpected_error_occured": "Une erreur inattendue s'est produite",
+ "change_server": "Changer de serveur",
+ "invalid_username_or_password": "Nom d'utilisateur ou mot de passe invalide",
+ "user_does_not_have_permission_to_log_in": "L'utilisateur n'a pas la permission de se connecter",
+ "server_is_taking_too_long_to_respond_try_again_later": "Le serveur prend trop de temps ร rรฉpondre, rรฉessayez plus tard",
+ "server_received_too_many_requests_try_again_later": "Le serveur a reรงu trop de demandes, rรฉessayez plus tard",
+ "there_is_a_server_error": "Il y a une erreur de serveur",
+ "an_unexpected_error_occured_did_you_enter_the_correct_url": "Une erreur inattendue s'est produite. Avez-vous entrรฉ la bonne URL?"
+ },
+ "server": {
+ "enter_url_to_jellyfin_server": "Entrez l'URL du serveur Jellyfin",
+ "server_url_placeholder": "http(s)://votre-serveur.com",
+ "connect_button": "Connexion",
+ "previous_servers": "Serveurs prรฉcรฉdents",
+ "clear_button": "Effacer",
+ "search_for_local_servers": "Rechercher des serveurs locaux",
+ "searching": "Recherche...",
+ "servers": "Serveurs"
+ },
+ "home": {
+ "no_internet": "Pas d'Internet",
+ "no_items": "Aucun mรฉdia",
+ "no_internet_message": "Aucun problรจme, vous pouvez toujours regarder\nle contenu tรฉlรฉchargรฉ.",
+ "go_to_downloads": "Aller aux tรฉlรฉchargements",
+ "oops": "Oups!",
+ "error_message": "Quelque chose s'est mal passรฉ.\nVeuillez vous reconnecter ร nouveau.",
+ "continue_watching": "Continuer ร regarder",
+ "next_up": "ร suivre",
+ "recently_added_in": "Ajoutรฉs rรฉcemment dans {{libraryName}}",
+ "suggested_movies": "Films suggรฉrรฉs",
+ "suggested_episodes": "รpisodes suggรฉrรฉs",
+ "intro": {
+ "welcome_to_streamyfin": "Bienvenue sur Streamyfin",
+ "a_free_and_open_source_client_for_jellyfin": "Un client gratuit et open source pour Jellyfin",
+ "features_title": "Fonctionnalitรฉs",
+ "features_description": "Streamyfin possรจde de nombreuses fonctionnalitรฉs et s'intรจgre ร un large รฉventail de logiciels que vous pouvez trouver dans le menu des paramรจtres, notamment:",
+ "jellyseerr_feature_description": "Connectez-vous ร votre instance Jellyseerr et demandez des films directement dans l'application.",
+ "downloads_feature_title": "Tรฉlรฉchargements",
+ "downloads_feature_description": "Tรฉlรฉchargez des films et des รฉmissions de tรฉlรฉvision pour les regarder hors ligne. Utilisez la mรฉthode par dรฉfaut ou installez le serveur d'optimisation pour tรฉlรฉcharger les fichiers en arriรจre-plan.",
+ "chromecast_feature_description": "Diffusez des films et des รฉmissions de tรฉlรฉvision sur vos appareils Chromecast.",
+ "centralised_settings_plugin_title": "Plugin de paramรจtres centralisรฉs",
+ "centralised_settings_plugin_description": "Configuration des paramรจtres d'un emplacement centralisรฉ sur votre serveur Jellyfin. Tous les paramรจtres clients pour tous les utilisateurs seront synchronisรฉs automatiquement.",
+ "done_button": "Terminรฉ",
+ "go_to_settings_button": "Allez dans les paramรจtres",
+ "read_more": "Lisez-en plus"
+ },
+ "settings": {
+ "settings_title": "Paramรจtres",
+ "log_out_button": "Dรฉconnexion",
+ "user_info": {
+ "user_info_title": "Informations utilisateur",
+ "user": "Utilisateur",
+ "server": "Serveur",
+ "token": "Jeton",
+ "app_version": "Version de l'application"
+ },
+ "quick_connect": {
+ "quick_connect_title": "Connexion Rapide",
+ "authorize_button": "Autoriser Connexion Rapide",
+ "enter_the_quick_connect_code": "Entrez le code Connexion Rapide...",
+ "success": "Succรจs",
+ "quick_connect_autorized": "Connexion Rapide autorisรฉ",
+ "error": "Erreur",
+ "invalid_code": "Code invalide",
+ "authorize": "Autoriser"
+ },
+ "media_controls": {
+ "media_controls_title": "Contrรดles Mรฉdia",
+ "forward_skip_length": "Durรฉe de saut en avant",
+ "rewind_length": "Durรฉe de retour en arriรจre",
+ "seconds_unit": "s"
+ },
+ "audio": {
+ "audio_title": "Audio",
+ "set_audio_track": "Piste audio de l'รฉlรฉment prรฉcรฉdent",
+ "audio_language": "Langue audio",
+ "audio_hint": "Choisissez une langue audio par dรฉfaut.",
+ "none": "Aucune",
+ "language": "Langage"
+ },
+ "subtitles": {
+ "subtitle_title": "Sous-titres",
+ "subtitle_language": "Langue des sous-titres",
+ "subtitle_mode": "Mode des sous-titres",
+ "set_subtitle_track": "Piste de sous-titres de l'รฉlรฉment prรฉcรฉdent",
+ "subtitle_size": "Taille des sous-titres",
+ "subtitle_hint": "Configurez les prรฉfรฉrences des sous-titres.",
+ "none": "Aucune",
+ "language": "Langage",
+ "loading": "Chargement",
+ "modes": {
+ "Default": "Par dรฉfaut",
+ "Smart": "Intelligent",
+ "Always": "Toujours",
+ "None": "Aucun",
+ "OnlyForced": "Forcรฉs seulement"
+ }
+ },
+ "other": {
+ "other_title": "Autres",
+ "auto_rotate": "Rotation automatique",
+ "video_orientation": "Orientation vidรฉo",
+ "orientation": "Orientation",
+ "orientations": {
+ "DEFAULT": "Par dรฉfaut",
+ "ALL": "Toutes",
+ "PORTRAIT": "Portrait",
+ "PORTRAIT_UP": "Portrait Haut",
+ "PORTRAIT_DOWN": "Portrait Bas",
+ "LANDSCAPE": "Paysage",
+ "LANDSCAPE_LEFT": "Paysage Gauche",
+ "LANDSCAPE_RIGHT": "Paysage Droite",
+ "OTHER": "Autre",
+ "UNKNOWN": "Inconnu"
+ },
+ "safe_area_in_controls": "Zone de sรฉcuritรฉ dans les contrรดles",
+ "show_custom_menu_links": "Afficher les liens personnalisรฉs",
+ "hide_libraries": "Cacher des bibliothรจques",
+ "select_liraries_you_want_to_hide": "Sรฉlectionnez les bibliothรจques que vous souhaitez masquer dans lโonglet Bibliothรจque et les sections de la page dโaccueil.",
+ "disable_haptic_feedback": "Dรฉsactiver le retour haptique"
+ },
+ "downloads": {
+ "downloads_title": "Tรฉlรฉchargements",
+ "download_method": "Mรฉthode de tรฉlรฉchargement",
+ "remux_max_download": "Tรฉlรฉchargement max remux",
+ "auto_download": "Tรฉlรฉchargement automatique",
+ "optimized_versions_server": "Serveur de versions optimisรฉes",
+ "save_button": "Enregistrer",
+ "optimized_server": "Serveur optimisรฉ",
+ "optimized": "Optimisรฉ",
+ "default": "Par dรฉfaut",
+ "optimized_version_hint": "Entrez l'URL du serveur de versions optimisรฉes. L'URL devrait inclure http ou https et optionnellement le port.",
+ "read_more_about_optimized_server": "Lisez-en plus sur le serveur de versions optimisรฉes.",
+ "url": "URL",
+ "server_url_placeholder": "http(s)://domaine.org:port"
+ },
+ "plugins": {
+ "plugins_title": "Plugins",
+ "jellyseerr": {
+ "jellyseerr_warning": "Cette intรฉgration est dans ses dรฉbuts. Attendez-vous ร ce que des choses changent.",
+ "server_url": "URL du serveur",
+ "server_url_hint": "Exemple: http(s)://votre-domaine.url\n(ajouter le port si nรฉcessaire)",
+ "server_url_placeholder": "URL de Jellyseerr...",
+ "password": "Mot de passe",
+ "password_placeholder": "Entrez le mot de passe pour l'utilisateur Jellyfin {{username}}",
+ "save_button": "Enregistrer",
+ "clear_button": "Effacer",
+ "login_button": "Connexion",
+ "total_media_requests": "Total de demandes de mรฉdias",
+ "movie_quota_limit": "Limite de quota de film",
+ "movie_quota_days": "Jours de quota de film",
+ "tv_quota_limit": "Limite de quota TV",
+ "tv_quota_days": "Jours de quota TV",
+ "reset_jellyseerr_config_button": "Rรฉinitialiser la configuration Jellyseerr",
+ "unlimited": "Illimitรฉ"
+ },
+ "marlin_search": {
+ "enable_marlin_search": "Activer Marlin Search ",
+ "url": "URL",
+ "server_url_placeholder": "http(s)://domaine.org:port",
+ "marlin_search_hint": "Entrez l'URL du serveur Marlin. L'URL devrait inclure http ou https et optionnellement le port.",
+ "read_more_about_marlin": "Lisez-en plus sur Marlin.",
+ "save_button": "Enregistrer",
+ "toasts": {
+ "saved": "Enregistrรฉ"
+ }
+ }
+ },
+ "storage": {
+ "storage_title": "Stockage",
+ "app_usage": "App {{usedSpace}}%",
+ "device_usage": "Appareil {{availableSpace}}%",
+ "size_used": "{{used}} de {{total}} utilisรฉs",
+ "delete_all_downloaded_files": "Supprimer tous les fichiers tรฉlรฉchargรฉs"
+ },
+ "intro": {
+ "show_intro": "Afficher l'intro",
+ "reset_intro": "Rรฉinitialiser l'intro"
+ },
+ "logs": {
+ "logs_title": "Journaux",
+ "no_logs_available": "Aucun journal disponible",
+ "delete_all_logs": "Supprimer tous les journaux"
+ },
+ "languages": {
+ "title": "Langues",
+ "app_language": "Langue de l'application",
+ "app_language_description": "Sรฉlectionnez la langue de l'application",
+ "system": "Systรจme"
+ },
+ "toasts":{
+ "error_deleting_files": "Erreur lors de la suppression des fichiers",
+ "background_downloads_enabled": "Tรฉlรฉchargements en arriรจre-plan activรฉs",
+ "background_downloads_disabled": "Tรฉlรฉchargements en arriรจre-plan dรฉsactivรฉs",
+ "connected": "Connectรฉ",
+ "could_not_connect": "Impossible de se connecter",
+ "invalid_url": "URL invalide"
+ }
+ },
+ "downloads": {
+ "downloads_title": "Tรฉlรฉchargements",
+ "tvseries": "Sรฉries TV",
+ "movies": "Films",
+ "queue": "File d'attente",
+ "queue_hint": "La file d'attente et les tรฉlรฉchargements seront perdus au redรฉmarrage de l'application",
+ "no_items_in_queue": "Aucun tรฉlรฉchargement de mรฉdia dans la file d'attente",
+ "no_downloaded_items": "Aucun mรฉdia tรฉlรฉchargรฉ",
+ "delete_all_movies_button": "Supprimer tous les films",
+ "delete_all_tvseries_button": "Supprimer toutes les sรฉries",
+ "delete_all_button": "Supprimer tout les mรฉdias",
+ "active_download": "Tรฉlรฉchargement actif",
+ "no_active_downloads": "Aucun tรฉlรฉchargements actifs",
+ "active_downloads": "Tรฉlรฉchargements actifs",
+ "new_app_version_requires_re_download": "La nouvelle version de l'application nรฉcessite un nouveau tรฉlรฉchargement",
+ "new_app_version_requires_re_download_description": "Une nouvelle version de l'application est disponible. Veuillez supprimer tous les tรฉlรฉchargements et redรฉmarrer l'application pour tรฉlรฉcharger ร nouveau",
+ "back": "Retour",
+ "delete": "Supprimer",
+ "something_went_wrong": "Quelque chose s'est mal passรฉ",
+ "could_not_get_stream_url_from_jellyfin": "Impossible d'obtenir l'URL du flux depuis Jellyfin",
+ "eta": "ETA {{eta}}",
+ "methods": "Mรฉthodes",
+ "toasts": {
+ "you_are_not_allowed_to_download_files": "Vous n'รชtes pas autorisรฉ ร tรฉlรฉcharger des fichiers",
+ "deleted_all_movies_successfully": "Tous les films ont รฉtรฉ supprimรฉs avec succรจs!",
+ "failed_to_delete_all_movies": "รchec de la suppression de tous les films",
+ "deleted_all_tvseries_successfully": "Toutes les sรฉries ont รฉtรฉ supprimรฉes avec succรจs!",
+ "failed_to_delete_all_tvseries": "รchec de la suppression de toutes les sรฉries",
+ "download_cancelled": "Tรฉlรฉchargement annulรฉ",
+ "could_not_cancel_download": "Impossible d'annuler le tรฉlรฉchargement",
+ "download_completed": "Tรฉlรฉchargement terminรฉ",
+ "download_started_for": "Tรฉlรฉchargement dรฉmarrรฉ pour {{item}}",
+ "item_is_ready_to_be_downloaded": "{{item}} est prรชt ร รชtre tรฉlรฉchargรฉ",
+ "download_stated_for_item": "Tรฉlรฉchargement dรฉmarrรฉ pour {{item}}",
+ "download_failed_for_item": "รchec du tรฉlรฉchargement pour {{item}} - {{error}}",
+ "download_completed_for_item": "Tรฉlรฉchargement terminรฉ pour {{item}}",
+ "queued_item_for_optimization": "{{item}} mis en file d'attente pour l'optimisation",
+ "failed_to_start_download_for_item": "รchec du dรฉmarrage du tรฉlรฉchargement pour {{item}}: {{message}}",
+ "server_responded_with_status_code": "Le serveur a rรฉpondu avec le code de statut {{statusCode}}",
+ "no_response_received_from_server": "Aucune rรฉponse reรงue du serveur",
+ "error_setting_up_the_request": "Erreur lors de la configuration de la demande",
+ "failed_to_start_download_for_item_unexpected_error": "รchec du dรฉmarrage du tรฉlรฉchargement pour {{item}}: Erreur inattendue",
+ "all_files_folders_and_jobs_deleted_successfully": "Tous les fichiers, dossiers et tรขches ont รฉtรฉ supprimรฉs avec succรจs",
+ "an_error_occured_while_deleting_files_and_jobs": "Une erreur s'est produite lors de la suppression des fichiers et des tรขches",
+ "go_to_downloads": "Aller aux tรฉlรฉchargements"
+ }
+ }
+ },
+ "search": {
+ "search_here": "Rechercher ici...",
+ "search": "Rechercher...",
+ "x_items": "{{count}} mรฉdias",
+ "library": "Bibliothรจque",
+ "discover": "Dรฉcouvrir",
+ "no_results": "Aucun rรฉsultat",
+ "no_results_found_for": "Aucun rรฉsultat trouvรฉ pour",
+ "movies": "Films",
+ "series": "Sรฉries",
+ "episodes": "รpisodes",
+ "collections": "Collections",
+ "actors": "Acteurs",
+ "request_movies": "Demander un film",
+ "request_series": "Demander une sรฉrie",
+ "recently_added": "Ajoutรฉs rรฉcemment",
+ "recent_requests": "Demandes rรฉcentes",
+ "plex_watchlist": "Liste de lecture Plex",
+ "trending": "Tendance",
+ "popular_movies": "Films populaires",
+ "movie_genres": "Genres de films",
+ "upcoming_movies": "Films ร venir",
+ "studios": "Studios",
+ "popular_tv": "TV populaire",
+ "tv_genres": "Genres TV",
+ "upcoming_tv": "TV ร venir",
+ "networks": "Rรฉseaux",
+ "tmdb_movie_keyword": "Mot(s)-clรฉ(s) Films TMDB",
+ "tmdb_movie_genre": "Genre de film TMDB",
+ "tmdb_tv_keyword": "Mot(s)-clรฉ(s) TV TMDB",
+ "tmdb_tv_genre": "Genre TV TMDB",
+ "tmdb_search": "Recherche TMDB",
+ "tmdb_studio": "Studio TMDB",
+ "tmdb_network": "Rรฉseau TMDB",
+ "tmdb_movie_streaming_services": "Services de streaming de films TMDB",
+ "tmdb_tv_streaming_services": "Services de streaming TV TMDB"
+ },
+ "library": {
+ "no_items_found": "Aucun mรฉdia trouvรฉ",
+ "no_results": "Aucun rรฉsultat",
+ "no_libraries_found": "Aucune bibliothรจque trouvรฉe",
+ "item_types": {
+ "movies": "films",
+ "series": "sรฉries",
+ "boxsets": "coffrets",
+ "items": "mรฉdias"
+ },
+ "options": {
+ "display": "Affichage",
+ "row": "Rangรฉe",
+ "list": "Liste",
+ "image_style": "Style d'image",
+ "poster": "Affiche",
+ "cover": "Couverture",
+ "show_titles": "Afficher les titres",
+ "show_stats": "Afficher les statistiques"
+ },
+ "filters": {
+ "genres": "Genres",
+ "years": "Annรฉes",
+ "sort_by": "Trier par",
+ "sort_order": "Ordre de tri",
+ "tags": "Tags"
+ }
+ },
+ "favorites": {
+ "series": "Sรฉries",
+ "movies": "Films",
+ "episodes": "รpisodes",
+ "videos": "Vidรฉos",
+ "boxsets": "Coffrets",
+ "playlists": "Listes de lecture"
+ },
+ "custom_links": {
+ "no_links": "Aucuns liens"
+ },
+ "player": {
+ "error": "Erreur",
+ "failed_to_get_stream_url": "รchec de l'obtention de l'URL du flux",
+ "an_error_occured_while_playing_the_video": "Une erreur s'est produite lors de la lecture de la vidรฉo",
+ "client_error": "Erreur client",
+ "could_not_create_stream_for_chromecast": "Impossible de crรฉer un flux sur la Chromecast",
+ "message_from_server": "Message du serveur: {{message}}",
+ "video_has_finished_playing": "La vidรฉo a fini de jouer!",
+ "no_video_source": "Aucune source vidรฉo...",
+ "next_episode": "รpisode suivant",
+ "refresh_tracks": "Rafraรฎchir les pistes",
+ "subtitle_tracks": "Pistes de sous-titres:",
+ "audio_tracks": "Pistes audio:",
+ "playback_state": "รtat de lecture:",
+ "no_data_available": "Aucune donnรฉe disponible",
+ "index": "Index:"
+ },
+ "item_card": {
+ "next_up": "ร suivre",
+ "no_items_to_display": "Aucun mรฉdias ร afficher",
+ "cast_and_crew": "Distribution et รฉquipe",
+ "series": "Sรฉries",
+ "seasons": "Saisons",
+ "season": "Saison",
+ "no_episodes_for_this_season": "Aucun รฉpisode pour cette saison",
+ "overview": "Aperรงu",
+ "more_with": "Plus avec {{name}}",
+ "similar_items": "Mรฉdias similaires",
+ "no_similar_items_found": "Aucun mรฉdia similaire trouvรฉ",
+ "video": "Vidรฉo",
+ "more_details": "Plus de dรฉtails",
+ "quality": "Qualitรฉ",
+ "audio": "Audio",
+ "subtitles": "Sous-titres",
+ "show_more": "Afficher plus",
+ "show_less": "Afficher moins",
+ "appeared_in": "Apparu dans",
+ "could_not_load_item": "Impossible de charger le mรฉdia",
+ "none": "Aucun",
+ "download": {
+ "download_season": "Tรฉlรฉcharger la saison",
+ "download_series": "Tรฉlรฉcharger la sรฉrie",
+ "download_episode": "Tรฉlรฉcharger l'รฉpisode",
+ "download_movie": "Tรฉlรฉcharger le film",
+ "download_x_item": "Tรฉlรฉcharger {{item_count}} mรฉdias",
+ "download_button": "Tรฉlรฉcharger",
+ "using_optimized_server": "Avec le serveur optimisรฉes",
+ "using_default_method": "Avec la mรฉthode par dรฉfaut"
+ }
+ },
+ "live_tv": {
+ "next": "Suivant",
+ "previous": "Prรฉcรฉdent",
+ "live_tv": "TV en direct",
+ "coming_soon": "Bientรดt",
+ "on_now": "En ce moment",
+ "shows": "รmissions",
+ "movies": "Films",
+ "sports": "Sports",
+ "for_kids": "Pour enfants",
+ "news": "Actualitรฉs"
+ },
+ "jellyseerr":{
+ "confirm": "Confirmer",
+ "cancel": "Annuler",
+ "yes": "Oui",
+ "whats_wrong": "Quel est le problรจme?",
+ "issue_type": "Type de problรจme",
+ "select_an_issue": "Sรฉlectionnez un problรจme",
+ "types": "Types",
+ "describe_the_issue": "(optionnel) Dรฉcrivez le problรจme...",
+ "submit_button": "Soumettre",
+ "report_issue_button": "Signaler un problรจme",
+ "request_button": "Demander",
+ "are_you_sure_you_want_to_request_all_seasons": "รtes-vous sรปr de vouloir demander toutes les saisons?",
+ "failed_to_login": "รchec de la connexion",
+ "cast": "Distribution",
+ "details": "Dรฉtails",
+ "status": "Statut",
+ "original_title": "Titre original",
+ "series_type": "Type de sรฉrie",
+ "release_dates": "Dates de sortie",
+ "first_air_date": "Date de premiรจre diffusion",
+ "next_air_date": "Date de prochaine diffusion",
+ "revenue": "Revenu",
+ "budget": "Budget",
+ "original_language": "Langue originale",
+ "production_country": "Pays de production",
+ "studios": "Studios",
+ "network": "Rรฉseaux",
+ "currently_streaming_on": "En streaming sur",
+ "advanced": "Avancรฉ",
+ "request_as": "Demander en tant que",
+ "tags": "Tags",
+ "quality_profile": "Profil de qualitรฉ",
+ "root_folder": "Dossier racine",
+ "season_x": "Saison {{seasons}}",
+ "season_number": "Saison {{season_number}}",
+ "number_episodes": "{{episode_number}} รฉpisodes",
+ "born": "Nรฉ(e) le",
+ "appearances": "Apparences",
+ "toasts": {
+ "jellyseer_does_not_meet_requirements": "Jellyseer ne rรฉpond pas aux exigences! Veuillez mettre ร jour au moins vers la version 2.0.0.",
+ "jellyseerr_test_failed": "รchec du test de Jellyseerr",
+ "failed_to_test_jellyseerr_server_url": "รchec du test de l'URL du serveur Jellyseerr",
+ "issue_submitted": "Problรจme soumis!",
+ "requested_item": "{{item}}} demandรฉ!",
+ "you_dont_have_permission_to_request": "Vous n'avez pas la permission de demander {{item}}",
+ "something_went_wrong_requesting_media": "Quelque chose s'est mal passรฉ en demandant le mรฉdia!"
+ }
+ },
+ "tabs": {
+ "home": "Accueil",
+ "search": "Recherche",
+ "library": "Bibliothรจque",
+ "custom_links": "Liens personnalisรฉs",
+ "favorites": "Favoris"
+ }
+}
diff --git a/translations/sv.json b/translations/sv.json
new file mode 100644
index 00000000..d35f6c82
--- /dev/null
+++ b/translations/sv.json
@@ -0,0 +1,30 @@
+{
+ "login": {
+ "username_required": "Anvรคndarnamn krรคvs",
+ "error_title": "Fel",
+ "login_title": "Logga in",
+ "username_placeholder": "Anvรคndarnamn",
+ "password_placeholder": "Lรถsenord",
+ "login_button": "Logga in"
+ },
+ "server": {
+ "server_url_placeholder": "Server URL",
+ "connect_button": "Anslut"
+ },
+ "home": {
+ "home": "Hem",
+ "no_internet": "Ingen Internet",
+ "no_internet_message": "Ingen fara, du kan fortfarande titta\npรฅ nedladdat innehรฅll.",
+ "go_to_downloads": "Gรฅ till nedladdningar",
+ "oops": "Hoppsan!",
+ "error_message": "Nรฅgot gick fel.\nLogga ut och in igen.",
+ "continue_watching": "Fortsรคtt titta",
+ "next_up": "Nรคsta upp",
+ "recently_added_in": "Nyligen tillagt i {{libraryName}}"
+ },
+ "tabs": {
+ "home": "Hem",
+ "search": "Sรถk",
+ "library": "Bibliotek"
+ }
+}
diff --git a/utils/_jellyseerr/useJellyseerrCanRequest.ts b/utils/_jellyseerr/useJellyseerrCanRequest.ts
index ba692df3..c58a8928 100644
--- a/utils/_jellyseerr/useJellyseerrCanRequest.ts
+++ b/utils/_jellyseerr/useJellyseerrCanRequest.ts
@@ -48,5 +48,20 @@ export const useJellyseerrCanRequest = (
return userHasPermission && !canNotRequest;
}, [item, jellyseerrUser]);
- return canRequest;
+ const hasAdvancedRequestPermission = useMemo(() => {
+ if (!jellyseerrUser) return false;
+
+ return hasPermission(
+ [
+ Permission.REQUEST_ADVANCED,
+ Permission.MANAGE_REQUESTS
+ ],
+ jellyseerrUser.permissions,
+ {type: 'or'}
+ )
+ },
+ [jellyseerrUser]
+ );
+
+ return [canRequest, hasAdvancedRequestPermission];
};
diff --git a/utils/atoms/settings.ts b/utils/atoms/settings.ts
index fd669530..3beff72a 100644
--- a/utils/atoms/settings.ts
+++ b/utils/atoms/settings.ts
@@ -1,12 +1,21 @@
import { atom, useAtom } from "jotai";
-import { useEffect } from "react";
-import * as ScreenOrientation from "@/packages/expo-screen-orientation";
+import { useCallback, useEffect, useMemo } from "react";
+import * as ScreenOrientation from "expo-screen-orientation";
import { storage } from "../mmkv";
import { Platform } from "react-native";
import {
CultureDto,
SubtitlePlaybackMode,
+ ItemSortBy,
+ SortOrder,
+ BaseItemKind,
+ ItemFilter,
} from "@jellyfin/sdk/lib/generated-client";
+import { apiAtom } from "@/providers/JellyfinProvider";
+import { writeInfoLog } from "@/utils/log";
+
+const STREAMYFIN_PLUGIN_ID = "1e9e5d386e6746158719e98a5c34f004";
+const STREAMYFIN_PLUGIN_SETTINGS = "STREAMYFIN_PLUGIN_SETTINGS";
export type DownloadQuality = "original" | "high" | "low";
@@ -19,16 +28,26 @@ export const ScreenOrientationEnum: Record<
ScreenOrientation.OrientationLock,
string
> = {
- [ScreenOrientation.OrientationLock.DEFAULT]: "Default",
- [ScreenOrientation.OrientationLock.ALL]: "All",
- [ScreenOrientation.OrientationLock.PORTRAIT]: "Portrait",
- [ScreenOrientation.OrientationLock.PORTRAIT_UP]: "Portrait Up",
- [ScreenOrientation.OrientationLock.PORTRAIT_DOWN]: "Portrait Down",
- [ScreenOrientation.OrientationLock.LANDSCAPE]: "Landscape",
- [ScreenOrientation.OrientationLock.LANDSCAPE_LEFT]: "Landscape Left",
- [ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT]: "Landscape Right",
- [ScreenOrientation.OrientationLock.OTHER]: "Other",
- [ScreenOrientation.OrientationLock.UNKNOWN]: "Unknown",
+ [ScreenOrientation.OrientationLock.DEFAULT]:
+ "home.settings.other.orientations.DEFAULT",
+ [ScreenOrientation.OrientationLock.ALL]:
+ "home.settings.other.orientations.ALL",
+ [ScreenOrientation.OrientationLock.PORTRAIT]:
+ "home.settings.other.orientations.PORTRAIT",
+ [ScreenOrientation.OrientationLock.PORTRAIT_UP]:
+ "home.settings.other.orientations.PORTRAIT_UP",
+ [ScreenOrientation.OrientationLock.PORTRAIT_DOWN]:
+ "home.settings.other.orientations.PORTRAIT_DOWN",
+ [ScreenOrientation.OrientationLock.LANDSCAPE]:
+ "home.settings.other.orientations.LANDSCAPE",
+ [ScreenOrientation.OrientationLock.LANDSCAPE_LEFT]:
+ "home.settings.other.orientations.LANDSCAPE_LEFT",
+ [ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT]:
+ "home.settings.other.orientations.LANDSCAPE_RIGHT",
+ [ScreenOrientation.OrientationLock.OTHER]:
+ "home.settings.other.orientations.OTHER",
+ [ScreenOrientation.OrientationLock.UNKNOWN]:
+ "home.settings.other.orientations.UNKNOWN",
};
export const DownloadOptions: DownloadOption[] = [
@@ -59,12 +78,46 @@ export type DefaultLanguageOption = {
label: string;
};
+export enum DownloadMethod {
+ Remux = "remux",
+ Optimized = "optimized",
+}
+
+export type Home = {
+ sections: Array;
+};
+
+export type HomeSection = {
+ orientation?: "horizontal" | "vertical";
+ items?: HomeSectionItemResolver;
+ nextUp?: HomeSectionNextUpResolver;
+};
+
+export type HomeSectionItemResolver = {
+ title?: string;
+ sortBy?: Array;
+ sortOrder?: Array;
+ includeItemTypes?: Array;
+ genres?: Array;
+ parentId?: string;
+ limit?: number;
+ filters?: Array;
+};
+
+export type HomeSectionNextUpResolver = {
+ parentId?: string;
+ limit?: number;
+ enableResumable?: boolean;
+ enableRewatching?: boolean;
+};
+
export type Settings = {
+ home?: Home | null;
autoRotate?: boolean;
forceLandscapeInVideoPlayer?: boolean;
- usePopularPlugin?: boolean;
deviceProfile?: "Expo" | "Native" | "Old";
mediaListCollectionIds?: string[];
+ preferedLanguage?: string;
searchEngine: "Marlin" | "Jellyfin";
marlinServerUrl?: string;
openInVLC?: boolean;
@@ -81,22 +134,37 @@ export type Settings = {
forwardSkipTime: number;
rewindSkipTime: number;
optimizedVersionsServerUrl?: string | null;
- downloadMethod: "optimized" | "remux";
+ downloadMethod: DownloadMethod;
autoDownload: boolean;
showCustomMenuLinks: boolean;
+ disableHapticFeedback: boolean;
subtitleSize: number;
remuxConcurrentLimit: 1 | 2 | 3 | 4;
safeAreaInControlsEnabled: boolean;
jellyseerrServerUrl?: string;
+ hiddenLibraries?: string[];
+};
+
+export interface Lockable {
+ locked: boolean;
+ value: T;
+}
+
+export type PluginLockableSettings = {
+ [K in keyof Settings]: Lockable;
+};
+export type StreamyfinPluginConfig = {
+ settings: PluginLockableSettings;
};
const loadSettings = (): Settings => {
const defaultValues: Settings = {
+ home: null,
autoRotate: true,
forceLandscapeInVideoPlayer: false,
- usePopularPlugin: false,
deviceProfile: "Expo",
mediaListCollectionIds: [],
+ preferedLanguage: undefined,
searchEngine: "Jellyfin",
marlinServerUrl: "",
openInVLC: false,
@@ -119,13 +187,15 @@ const loadSettings = (): Settings => {
forwardSkipTime: 30,
rewindSkipTime: 10,
optimizedVersionsServerUrl: null,
- downloadMethod: "remux",
+ downloadMethod: DownloadMethod.Remux,
autoDownload: false,
showCustomMenuLinks: false,
+ disableHapticFeedback: false,
subtitleSize: Platform.OS === "ios" ? 60 : 100,
remuxConcurrentLimit: 1,
safeAreaInControlsEnabled: true,
jellyseerrServerUrl: undefined,
+ hiddenLibraries: [],
};
try {
@@ -140,22 +210,55 @@ const loadSettings = (): Settings => {
}
};
+const EXCLUDE_FROM_SAVE = ["home"];
+
const saveSettings = (settings: Settings) => {
+ Object.keys(settings).forEach((key) => {
+ if (EXCLUDE_FROM_SAVE.includes(key)) {
+ delete settings[key as keyof Settings];
+ }
+ });
const jsonValue = JSON.stringify(settings);
storage.set("settings", jsonValue);
};
export const settingsAtom = atom(null);
+export const pluginSettingsAtom = atom(
+ storage.get(STREAMYFIN_PLUGIN_SETTINGS)
+);
export const useSettings = () => {
- const [settings, setSettings] = useAtom(settingsAtom);
+ const [api] = useAtom(apiAtom);
+ const [_settings, setSettings] = useAtom(settingsAtom);
+ const [pluginSettings, _setPluginSettings] = useAtom(pluginSettingsAtom);
useEffect(() => {
- if (settings === null) {
+ if (_settings === null) {
const loadedSettings = loadSettings();
setSettings(loadedSettings);
}
- }, [settings, setSettings]);
+ }, [_settings, setSettings]);
+
+ const setPluginSettings = useCallback(
+ (settings: PluginLockableSettings | undefined) => {
+ storage.setAny(STREAMYFIN_PLUGIN_SETTINGS, settings);
+ _setPluginSettings(settings);
+ },
+ [_setPluginSettings]
+ );
+
+ const refreshStreamyfinPluginSettings = useCallback(async () => {
+ if (!api) return;
+ const settings = await api.getStreamyfinPluginConfig().then(
+ ({ data }) => {
+ writeInfoLog(`Got remote settings: ${data?.settings}`);
+ return data?.settings;
+ },
+ (err) => undefined
+ );
+ setPluginSettings(settings);
+ return settings;
+ }, [api]);
const updateSettings = (update: Partial) => {
if (settings) {
@@ -166,5 +269,53 @@ export const useSettings = () => {
}
};
- return [settings, updateSettings] as const;
+ // We do not want to save over users pre-existing settings in case admin ever removes/unlocks a setting.
+ // If admin sets locked to false but provides a value,
+ // use user settings first and fallback on admin setting if required.
+ const settings: Settings = useMemo(() => {
+ let unlockedPluginDefaults = {} as Settings;
+ const overrideSettings = Object.entries(pluginSettings || {}).reduce(
+ (acc, [key, setting]) => {
+ if (setting) {
+ const { value, locked } = setting;
+
+ // Make sure we override default settings with plugin settings when they are not locked.
+ // Admin decided what users defaults should be and grants them the ability to change them too.
+ if (
+ locked === false &&
+ value &&
+ _settings?.[key as keyof Settings] !== value
+ ) {
+ unlockedPluginDefaults = Object.assign(unlockedPluginDefaults, {
+ [key as keyof Settings]: value,
+ });
+ }
+
+ acc = Object.assign(acc, {
+ [key]: locked ? value : _settings?.[key as keyof Settings] ?? value,
+ });
+ }
+ return acc;
+ },
+ {} as Settings
+ );
+
+ // Update settings with plugin defined defaults
+ if (Object.keys(unlockedPluginDefaults).length > 0) {
+ updateSettings(unlockedPluginDefaults);
+ }
+
+ return {
+ ..._settings,
+ ...overrideSettings,
+ };
+ }, [_settings, pluginSettings]);
+
+ return [
+ settings,
+ updateSettings,
+ pluginSettings,
+ setPluginSettings,
+ refreshStreamyfinPluginSettings,
+ ] as const;
};
diff --git a/utils/collectionTypeToItemType.ts b/utils/collectionTypeToItemType.ts
index 64c23ff0..f37fe5f4 100644
--- a/utils/collectionTypeToItemType.ts
+++ b/utils/collectionTypeToItemType.ts
@@ -10,8 +10,6 @@ import {
* readonly Unknown: "unknown";
readonly Movies: "movies";
readonly Tvshows: "tvshows";
- readonly Music: "music";
- readonly Musicvideos: "musicvideos";
readonly Trailers: "trailers";
readonly Homevideos: "homevideos";
readonly Boxsets: "boxsets";
@@ -33,8 +31,6 @@ export const colletionTypeToItemType = (
return BaseItemKind.Series;
case CollectionType.Homevideos:
return BaseItemKind.Video;
- case CollectionType.Musicvideos:
- return BaseItemKind.MusicVideo;
case CollectionType.Books:
return BaseItemKind.Book;
case CollectionType.Playlists:
diff --git a/utils/log.tsx b/utils/log.tsx
index 7c432406..45999062 100644
--- a/utils/log.tsx
+++ b/utils/log.tsx
@@ -1,7 +1,7 @@
import { atomWithStorage, createJSONStorage } from "jotai/utils";
import { storage } from "./mmkv";
-import {useQuery} from "@tanstack/react-query";
-import React, {createContext, useContext} from "react";
+import { useQuery } from "@tanstack/react-query";
+import React, { createContext, useContext } from "react";
type LogLevel = "INFO" | "WARN" | "ERROR";
@@ -19,10 +19,12 @@ const mmkvStorage = createJSONStorage(() => ({
}));
const logsAtom = atomWithStorage("logs", [], mmkvStorage);
-const LogContext = createContext | null>(null);
-const DownloadContext = createContext | null>(null);
+const LogContext = createContext | null>(
+ null
+);
+const DownloadContext = createContext | null>(
+ null
+);
function useLogProvider() {
const { data: logs } = useQuery({
@@ -32,11 +34,10 @@ function useLogProvider() {
});
return {
- logs
- }
+ logs,
+ };
}
-
export const writeToLog = (level: LogLevel, message: string, data?: any) => {
const newEntry: LogEntry = {
timestamp: new Date().toISOString(),
@@ -53,10 +54,13 @@ export const writeToLog = (level: LogLevel, message: string, data?: any) => {
const recentLogs = logs.slice(Math.max(logs.length - maxLogs, 0));
storage.set("logs", JSON.stringify(recentLogs));
+ console.log(message);
};
-export const writeInfoLog = (message: string, data?: any) => writeToLog("INFO", message, data);
-export const writeErrorLog = (message: string, data?: any) => writeToLog("ERROR", message, data);
+export const writeInfoLog = (message: string, data?: any) =>
+ writeToLog("INFO", message, data);
+export const writeErrorLog = (message: string, data?: any) =>
+ writeToLog("ERROR", message, data);
export const readFromLog = (): LogEntry[] => {
const logs = storage.getString("logs");
@@ -75,14 +79,10 @@ export function useLog() {
return context;
}
-export function LogProvider({children}: { children: React.ReactNode }) {
+export function LogProvider({ children }: { children: React.ReactNode }) {
const provider = useLogProvider();
- return (
-
- {children}
-
- )
+ return {children};
}
export default logsAtom;
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 00000000..b2bdf609
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,9412 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@0no-co/graphql.web@^1.0.5":
+ version "1.0.13"
+ resolved "https://registry.yarnpkg.com/@0no-co/graphql.web/-/graphql.web-1.0.13.tgz#978f4d3a869240f2d487fa1c1009028b34bc33b5"
+ integrity sha512-jqYxOevheVTU1S36ZdzAkJIdvRp2m3OYIG5SEoKDw5NI8eVwkoI0D/Q3DYNGmXCxkA6CQuoa7zvMiDPTLqUNuw==
+
+"@alloc/quick-lru@^5.2.0":
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30"
+ integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==
+
+"@ampproject/remapping@^2.2.0":
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4"
+ integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.5"
+ "@jridgewell/trace-mapping" "^0.3.24"
+
+"@babel/code-frame@7.10.4", "@babel/code-frame@~7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
+ integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==
+ dependencies:
+ "@babel/highlight" "^7.10.4"
+
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.2":
+ version "7.26.2"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85"
+ integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.25.9"
+ js-tokens "^4.0.0"
+ picocolors "^1.0.0"
+
+"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.5":
+ version "7.26.5"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.5.tgz#df93ac37f4417854130e21d72c66ff3d4b897fc7"
+ integrity sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==
+
+"@babel/core@^7.13.16", "@babel/core@^7.20.0", "@babel/core@^7.26.0":
+ version "7.26.7"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.7.tgz#0439347a183b97534d52811144d763a17f9d2b24"
+ integrity sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==
+ dependencies:
+ "@ampproject/remapping" "^2.2.0"
+ "@babel/code-frame" "^7.26.2"
+ "@babel/generator" "^7.26.5"
+ "@babel/helper-compilation-targets" "^7.26.5"
+ "@babel/helper-module-transforms" "^7.26.0"
+ "@babel/helpers" "^7.26.7"
+ "@babel/parser" "^7.26.7"
+ "@babel/template" "^7.25.9"
+ "@babel/traverse" "^7.26.7"
+ "@babel/types" "^7.26.7"
+ convert-source-map "^2.0.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.2.3"
+ semver "^6.3.1"
+
+"@babel/generator@7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.2.0.tgz#eaf3821fa0301d9d4aef88e63d4bcc19b73ba16c"
+ integrity sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==
+ dependencies:
+ "@babel/types" "^7.2.0"
+ jsesc "^2.5.1"
+ lodash "^4.17.10"
+ source-map "^0.5.0"
+ trim-right "^1.0.1"
+
+"@babel/generator@^7.18.7", "@babel/generator@^7.20.0", "@babel/generator@^7.20.5", "@babel/generator@^7.26.5":
+ version "7.26.5"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.5.tgz#e44d4ab3176bbcaf78a5725da5f1dc28802a9458"
+ integrity sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==
+ dependencies:
+ "@babel/parser" "^7.26.5"
+ "@babel/types" "^7.26.5"
+ "@jridgewell/gen-mapping" "^0.3.5"
+ "@jridgewell/trace-mapping" "^0.3.25"
+ jsesc "^3.0.2"
+
+"@babel/helper-annotate-as-pure@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4"
+ integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==
+ dependencies:
+ "@babel/types" "^7.25.9"
+
+"@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.25.9", "@babel/helper-compilation-targets@^7.26.5":
+ version "7.26.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz#75d92bb8d8d51301c0d49e52a65c9a7fe94514d8"
+ integrity sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==
+ dependencies:
+ "@babel/compat-data" "^7.26.5"
+ "@babel/helper-validator-option" "^7.25.9"
+ browserslist "^4.24.0"
+ lru-cache "^5.1.1"
+ semver "^6.3.1"
+
+"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz#7644147706bb90ff613297d49ed5266bde729f83"
+ integrity sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.25.9"
+ "@babel/helper-member-expression-to-functions" "^7.25.9"
+ "@babel/helper-optimise-call-expression" "^7.25.9"
+ "@babel/helper-replace-supers" "^7.25.9"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9"
+ "@babel/traverse" "^7.25.9"
+ semver "^6.3.1"
+
+"@babel/helper-create-regexp-features-plugin@^7.25.9":
+ version "7.26.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz#5169756ecbe1d95f7866b90bb555b022595302a0"
+ integrity sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.25.9"
+ regexpu-core "^6.2.0"
+ semver "^6.3.1"
+
+"@babel/helper-define-polyfill-provider@^0.6.2", "@babel/helper-define-polyfill-provider@^0.6.3":
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz#f4f2792fae2ef382074bc2d713522cf24e6ddb21"
+ integrity sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==
+ dependencies:
+ "@babel/helper-compilation-targets" "^7.22.6"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ debug "^4.1.1"
+ lodash.debounce "^4.0.8"
+ resolve "^1.14.2"
+
+"@babel/helper-environment-visitor@^7.18.9":
+ version "7.24.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9"
+ integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==
+ dependencies:
+ "@babel/types" "^7.24.7"
+
+"@babel/helper-member-expression-to-functions@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz#9dfffe46f727005a5ea29051ac835fb735e4c1a3"
+ integrity sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==
+ dependencies:
+ "@babel/traverse" "^7.25.9"
+ "@babel/types" "^7.25.9"
+
+"@babel/helper-module-imports@7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e"
+ integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==
+ dependencies:
+ "@babel/types" "^7.18.6"
+
+"@babel/helper-module-imports@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715"
+ integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==
+ dependencies:
+ "@babel/traverse" "^7.25.9"
+ "@babel/types" "^7.25.9"
+
+"@babel/helper-module-transforms@^7.26.0":
+ version "7.26.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae"
+ integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==
+ dependencies:
+ "@babel/helper-module-imports" "^7.25.9"
+ "@babel/helper-validator-identifier" "^7.25.9"
+ "@babel/traverse" "^7.25.9"
+
+"@babel/helper-optimise-call-expression@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e"
+ integrity sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==
+ dependencies:
+ "@babel/types" "^7.25.9"
+
+"@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.8.0":
+ version "7.26.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35"
+ integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==
+
+"@babel/helper-remap-async-to-generator@^7.18.9", "@babel/helper-remap-async-to-generator@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz#e53956ab3d5b9fb88be04b3e2f31b523afd34b92"
+ integrity sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.25.9"
+ "@babel/helper-wrap-function" "^7.25.9"
+ "@babel/traverse" "^7.25.9"
+
+"@babel/helper-replace-supers@^7.25.9":
+ version "7.26.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz#6cb04e82ae291dae8e72335dfe438b0725f14c8d"
+ integrity sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==
+ dependencies:
+ "@babel/helper-member-expression-to-functions" "^7.25.9"
+ "@babel/helper-optimise-call-expression" "^7.25.9"
+ "@babel/traverse" "^7.26.5"
+
+"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9"
+ integrity sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==
+ dependencies:
+ "@babel/traverse" "^7.25.9"
+ "@babel/types" "^7.25.9"
+
+"@babel/helper-string-parser@^7.18.10", "@babel/helper-string-parser@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c"
+ integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==
+
+"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7"
+ integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==
+
+"@babel/helper-validator-option@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72"
+ integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==
+
+"@babel/helper-wrap-function@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz#d99dfd595312e6c894bd7d237470025c85eea9d0"
+ integrity sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==
+ dependencies:
+ "@babel/template" "^7.25.9"
+ "@babel/traverse" "^7.25.9"
+ "@babel/types" "^7.25.9"
+
+"@babel/helpers@^7.26.7":
+ version "7.26.7"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.7.tgz#fd1d2a7c431b6e39290277aacfd8367857c576a4"
+ integrity sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==
+ dependencies:
+ "@babel/template" "^7.25.9"
+ "@babel/types" "^7.26.7"
+
+"@babel/highlight@^7.10.4":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.25.9.tgz#8141ce68fc73757946f983b343f1231f4691acc6"
+ integrity sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.25.9"
+ chalk "^2.4.2"
+ js-tokens "^4.0.0"
+ picocolors "^1.0.0"
+
+"@babel/parser@^7.13.16", "@babel/parser@^7.20.0", "@babel/parser@^7.25.9", "@babel/parser@^7.26.5", "@babel/parser@^7.26.7":
+ version "7.26.7"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.7.tgz#e114cd099e5f7d17b05368678da0fb9f69b3385c"
+ integrity sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==
+ dependencies:
+ "@babel/types" "^7.26.7"
+
+"@babel/plugin-proposal-async-generator-functions@^7.0.0":
+ version "7.20.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz#bfb7276d2d573cb67ba379984a2334e262ba5326"
+ integrity sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.20.2"
+ "@babel/helper-remap-async-to-generator" "^7.18.9"
+ "@babel/plugin-syntax-async-generators" "^7.8.4"
+
+"@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.18.0":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3"
+ integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-proposal-decorators@^7.12.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.9.tgz#8680707f943d1a3da2cd66b948179920f097e254"
+ integrity sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.25.9"
+ "@babel/helper-plugin-utils" "^7.25.9"
+ "@babel/plugin-syntax-decorators" "^7.25.9"
+
+"@babel/plugin-proposal-export-default-from@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz#52702be6ef8367fc8f18b8438278332beeb8f87c"
+ integrity sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-proposal-logical-assignment-operators@^7.18.0":
+ version "7.20.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz#dfbcaa8f7b4d37b51e8bfb46d94a5aea2bb89d83"
+ integrity sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.20.2"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
+
+"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8", "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.0":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1"
+ integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+
+"@babel/plugin-proposal-numeric-separator@^7.0.0":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75"
+ integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/plugin-syntax-numeric-separator" "^7.10.4"
+
+"@babel/plugin-proposal-object-rest-spread@^7.20.0":
+ version "7.20.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a"
+ integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==
+ dependencies:
+ "@babel/compat-data" "^7.20.5"
+ "@babel/helper-compilation-targets" "^7.20.7"
+ "@babel/helper-plugin-utils" "^7.20.2"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+ "@babel/plugin-transform-parameters" "^7.20.7"
+
+"@babel/plugin-proposal-optional-catch-binding@^7.0.0":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb"
+ integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+
+"@babel/plugin-proposal-optional-chaining@^7.13.12", "@babel/plugin-proposal-optional-chaining@^7.20.0":
+ version "7.21.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea"
+ integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.20.2"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+
+"@babel/plugin-syntax-async-generators@^7.8.4":
+ version "7.8.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
+ integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-decorators@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz#986b4ca8b7b5df3f67cee889cedeffc2e2bf14b3"
+ integrity sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-syntax-dynamic-import@^7.8.0":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
+ integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-export-default-from@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.25.9.tgz#86614767a9ff140366f0c3766ef218beb32a730a"
+ integrity sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-syntax-flow@^7.12.1", "@babel/plugin-syntax-flow@^7.18.0", "@babel/plugin-syntax-flow@^7.26.0":
+ version "7.26.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz#96507595c21b45fccfc2bc758d5c45452e6164fa"
+ integrity sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-syntax-jsx@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz#a34313a178ea56f1951599b929c1ceacee719290"
+ integrity sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-syntax-logical-assignment-operators@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
+ integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+"@babel/plugin-syntax-nullish-coalescing-operator@^7.0.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9"
+ integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-numeric-separator@^7.10.4":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97"
+ integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+"@babel/plugin-syntax-object-rest-spread@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871"
+ integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-optional-catch-binding@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1"
+ integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-optional-chaining@^7.0.0", "@babel/plugin-syntax-optional-chaining@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a"
+ integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-typescript@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz#67dda2b74da43727cf21d46cf9afef23f4365399"
+ integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-arrow-functions@^7.0.0", "@babel/plugin-transform-arrow-functions@^7.0.0-0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz#7821d4410bee5daaadbb4cdd9a6649704e176845"
+ integrity sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-async-to-generator@^7.20.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz#c80008dacae51482793e5a9c08b39a5be7e12d71"
+ integrity sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==
+ dependencies:
+ "@babel/helper-module-imports" "^7.25.9"
+ "@babel/helper-plugin-utils" "^7.25.9"
+ "@babel/helper-remap-async-to-generator" "^7.25.9"
+
+"@babel/plugin-transform-block-scoping@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz#c33665e46b06759c93687ca0f84395b80c0473a1"
+ integrity sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-classes@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz#7152457f7880b593a63ade8a861e6e26a4469f52"
+ integrity sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.25.9"
+ "@babel/helper-compilation-targets" "^7.25.9"
+ "@babel/helper-plugin-utils" "^7.25.9"
+ "@babel/helper-replace-supers" "^7.25.9"
+ "@babel/traverse" "^7.25.9"
+ globals "^11.1.0"
+
+"@babel/plugin-transform-computed-properties@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz#db36492c78460e534b8852b1d5befe3c923ef10b"
+ integrity sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+ "@babel/template" "^7.25.9"
+
+"@babel/plugin-transform-destructuring@^7.20.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz#966ea2595c498224340883602d3cfd7a0c79cea1"
+ integrity sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-export-namespace-from@^7.22.11":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz#90745fe55053394f554e40584cda81f2c8a402a2"
+ integrity sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-flow-strip-types@^7.20.0", "@babel/plugin-transform-flow-strip-types@^7.25.9":
+ version "7.26.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz#2904c85a814e7abb1f4850b8baf4f07d0a2389d4"
+ integrity sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.26.5"
+ "@babel/plugin-syntax-flow" "^7.26.0"
+
+"@babel/plugin-transform-function-name@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz#939d956e68a606661005bfd550c4fc2ef95f7b97"
+ integrity sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==
+ dependencies:
+ "@babel/helper-compilation-targets" "^7.25.9"
+ "@babel/helper-plugin-utils" "^7.25.9"
+ "@babel/traverse" "^7.25.9"
+
+"@babel/plugin-transform-literals@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz#1a1c6b4d4aa59bc4cad5b6b3a223a0abd685c9de"
+ integrity sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.25.9":
+ version "7.26.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz#8f011d44b20d02c3de44d8850d971d8497f981fb"
+ integrity sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.26.0"
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-named-capturing-groups-regex@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz#454990ae6cc22fd2a0fa60b3a2c6f63a38064e6a"
+ integrity sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.25.9"
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-nullish-coalescing-operator@^7.0.0-0":
+ version "7.26.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz#fbf6b3c92cb509e7b319ee46e3da89c5bedd31fe"
+ integrity sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.26.5"
+
+"@babel/plugin-transform-object-rest-spread@^7.12.13":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz#0203725025074164808bcf1a2cfa90c652c99f18"
+ integrity sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==
+ dependencies:
+ "@babel/helper-compilation-targets" "^7.25.9"
+ "@babel/helper-plugin-utils" "^7.25.9"
+ "@babel/plugin-transform-parameters" "^7.25.9"
+
+"@babel/plugin-transform-optional-chaining@^7.0.0-0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz#e142eb899d26ef715435f201ab6e139541eee7dd"
+ integrity sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9"
+
+"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.20.7", "@babel/plugin-transform-parameters@^7.22.15", "@babel/plugin-transform-parameters@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz#b856842205b3e77e18b7a7a1b94958069c7ba257"
+ integrity sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-private-methods@^7.22.5":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz#847f4139263577526455d7d3223cd8bda51e3b57"
+ integrity sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.25.9"
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-private-property-in-object@^7.22.11":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz#9c8b73e64e6cc3cbb2743633885a7dd2c385fe33"
+ integrity sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.25.9"
+ "@babel/helper-create-class-features-plugin" "^7.25.9"
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-react-display-name@^7.0.0", "@babel/plugin-transform-react-display-name@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz#4b79746b59efa1f38c8695065a92a9f5afb24f7d"
+ integrity sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-react-jsx-development@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz#8fd220a77dd139c07e25225a903b8be8c829e0d7"
+ integrity sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==
+ dependencies:
+ "@babel/plugin-transform-react-jsx" "^7.25.9"
+
+"@babel/plugin-transform-react-jsx-self@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz#c0b6cae9c1b73967f7f9eb2fca9536ba2fad2858"
+ integrity sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-react-jsx-source@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz#4c6b8daa520b5f155b5fb55547d7c9fa91417503"
+ integrity sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-react-jsx@^7.0.0", "@babel/plugin-transform-react-jsx@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz#06367940d8325b36edff5e2b9cbe782947ca4166"
+ integrity sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.25.9"
+ "@babel/helper-module-imports" "^7.25.9"
+ "@babel/helper-plugin-utils" "^7.25.9"
+ "@babel/plugin-syntax-jsx" "^7.25.9"
+ "@babel/types" "^7.25.9"
+
+"@babel/plugin-transform-react-pure-annotations@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz#ea1c11b2f9dbb8e2d97025f43a3b5bc47e18ae62"
+ integrity sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.25.9"
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-runtime@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz#62723ea3f5b31ffbe676da9d6dae17138ae580ea"
+ integrity sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==
+ dependencies:
+ "@babel/helper-module-imports" "^7.25.9"
+ "@babel/helper-plugin-utils" "^7.25.9"
+ babel-plugin-polyfill-corejs2 "^0.4.10"
+ babel-plugin-polyfill-corejs3 "^0.10.6"
+ babel-plugin-polyfill-regenerator "^0.6.1"
+ semver "^6.3.1"
+
+"@babel/plugin-transform-shorthand-properties@^7.0.0", "@babel/plugin-transform-shorthand-properties@^7.0.0-0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz#bb785e6091f99f826a95f9894fc16fde61c163f2"
+ integrity sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-spread@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz#24a35153931b4ba3d13cec4a7748c21ab5514ef9"
+ integrity sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9"
+
+"@babel/plugin-transform-sticky-regex@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz#c7f02b944e986a417817b20ba2c504dfc1453d32"
+ integrity sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-template-literals@^7.0.0-0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz#6dbd4a24e8fad024df76d1fac6a03cf413f60fe1"
+ integrity sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/plugin-transform-typescript@^7.25.9", "@babel/plugin-transform-typescript@^7.5.0":
+ version "7.26.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.7.tgz#64339515ea3eff610160f62499c3ef437d0ac83d"
+ integrity sha512-5cJurntg+AT+cgelGP9Bt788DKiAw9gIMSMU2NJrLAilnj0m8WZWUNZPSLOmadYsujHutpgElO+50foX+ib/Wg==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.25.9"
+ "@babel/helper-create-class-features-plugin" "^7.25.9"
+ "@babel/helper-plugin-utils" "^7.26.5"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9"
+ "@babel/plugin-syntax-typescript" "^7.25.9"
+
+"@babel/plugin-transform-unicode-regex@^7.0.0":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz#5eae747fe39eacf13a8bd006a4fb0b5d1fa5e9b1"
+ integrity sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.25.9"
+ "@babel/helper-plugin-utils" "^7.25.9"
+
+"@babel/preset-flow@^7.13.13":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.25.9.tgz#ef8b5e7e3f24a42b3711e77fb14919b87dffed0a"
+ integrity sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+ "@babel/helper-validator-option" "^7.25.9"
+ "@babel/plugin-transform-flow-strip-types" "^7.25.9"
+
+"@babel/preset-react@^7.22.15":
+ version "7.26.3"
+ resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.26.3.tgz#7c5e028d623b4683c1f83a0bd4713b9100560caa"
+ integrity sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+ "@babel/helper-validator-option" "^7.25.9"
+ "@babel/plugin-transform-react-display-name" "^7.25.9"
+ "@babel/plugin-transform-react-jsx" "^7.25.9"
+ "@babel/plugin-transform-react-jsx-development" "^7.25.9"
+ "@babel/plugin-transform-react-pure-annotations" "^7.25.9"
+
+"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.16.7", "@babel/preset-typescript@^7.23.0":
+ version "7.26.0"
+ resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz#4a570f1b8d104a242d923957ffa1eaff142a106d"
+ integrity sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.25.9"
+ "@babel/helper-validator-option" "^7.25.9"
+ "@babel/plugin-syntax-jsx" "^7.25.9"
+ "@babel/plugin-transform-modules-commonjs" "^7.25.9"
+ "@babel/plugin-transform-typescript" "^7.25.9"
+
+"@babel/register@^7.13.16":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.25.9.tgz#1c465acf7dc983d70ccc318eb5b887ecb04f021b"
+ integrity sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA==
+ dependencies:
+ clone-deep "^4.0.1"
+ find-cache-dir "^2.0.0"
+ make-dir "^2.1.0"
+ pirates "^4.0.6"
+ source-map-support "^0.5.16"
+
+"@babel/runtime@^7.13.10", "@babel/runtime@^7.18.6", "@babel/runtime@^7.20.0", "@babel/runtime@^7.23.2", "@babel/runtime@^7.25.0", "@babel/runtime@^7.7.2":
+ version "7.26.7"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.7.tgz#f4e7fe527cd710f8dc0618610b61b4b060c3c341"
+ integrity sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==
+ dependencies:
+ regenerator-runtime "^0.14.0"
+
+"@babel/template@^7.0.0", "@babel/template@^7.25.9":
+ version "7.25.9"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016"
+ integrity sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==
+ dependencies:
+ "@babel/code-frame" "^7.25.9"
+ "@babel/parser" "^7.25.9"
+ "@babel/types" "^7.25.9"
+
+"@babel/traverse@^7.20.0", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.7":
+ version "7.26.7"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.7.tgz#99a0a136f6a75e7fb8b0a1ace421e0b25994b8bb"
+ integrity sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==
+ dependencies:
+ "@babel/code-frame" "^7.26.2"
+ "@babel/generator" "^7.26.5"
+ "@babel/parser" "^7.26.7"
+ "@babel/template" "^7.25.9"
+ "@babel/types" "^7.26.7"
+ debug "^4.3.1"
+ globals "^11.1.0"
+
+"@babel/types@7.19.0":
+ version "7.19.0"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.0.tgz#75f21d73d73dc0351f3368d28db73465f4814600"
+ integrity sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==
+ dependencies:
+ "@babel/helper-string-parser" "^7.18.10"
+ "@babel/helper-validator-identifier" "^7.18.6"
+ to-fast-properties "^2.0.0"
+
+"@babel/types@^7.18.6", "@babel/types@^7.19.0", "@babel/types@^7.2.0", "@babel/types@^7.20.0", "@babel/types@^7.24.7", "@babel/types@^7.25.9", "@babel/types@^7.26.5", "@babel/types@^7.26.7":
+ version "7.26.7"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.7.tgz#5e2b89c0768e874d4d061961f3a5a153d71dc17a"
+ integrity sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==
+ dependencies:
+ "@babel/helper-string-parser" "^7.25.9"
+ "@babel/helper-validator-identifier" "^7.25.9"
+
+"@bottom-tabs/react-navigation@0.8.3":
+ version "0.8.3"
+ resolved "https://registry.yarnpkg.com/@bottom-tabs/react-navigation/-/react-navigation-0.8.3.tgz#558eb5310f13757bf2b97e6068ee398c69274b72"
+ integrity sha512-UargM8/RPBk4hAS9l8laGk5cF6oQxHxx5S5oDuAG/z31yPa2E8WGab2tlN3sQTeGx8OxmxtDhY7vNDxzBJHJQA==
+ dependencies:
+ color "^4.2.3"
+
+"@config-plugins/ffmpeg-kit-react-native@^8.0.0":
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/@config-plugins/ffmpeg-kit-react-native/-/ffmpeg-kit-react-native-8.0.0.tgz#86d6f236bcab5b1d3faa768cea0e7508c25be544"
+ integrity sha512-PUQHUBfRaGMBwPM8KnfHNVcWH0WvWO9QgIJYkb55/WGSmIdezsgJo/zlcXFexe7kkSTBqG/Pxnp5DGTYFBYBuQ==
+ dependencies:
+ semver "^7.3.5"
+
+"@dominicstop/ts-event-emitter@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@dominicstop/ts-event-emitter/-/ts-event-emitter-1.1.0.tgz#1f3d3fa878a1ccab686931280757954719cf88e4"
+ integrity sha512-CcxmJIvUb1vsFheuGGVSQf4KdPZC44XolpUT34+vlal+LyQoBUOn31pjFET5M9ctOxEpt8xa0M3/2M7uUiAoJw==
+
+"@egjs/hammerjs@^2.0.17":
+ version "2.0.17"
+ resolved "https://registry.yarnpkg.com/@egjs/hammerjs/-/hammerjs-2.0.17.tgz#5dc02af75a6a06e4c2db0202cae38c9263895124"
+ integrity sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==
+ dependencies:
+ "@types/hammerjs" "^2.0.36"
+
+"@expo/bunyan@^4.0.0":
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/@expo/bunyan/-/bunyan-4.0.1.tgz#ab9e17e36c71c704a0ce72168378a487368da736"
+ integrity sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==
+ dependencies:
+ uuid "^8.0.0"
+
+"@expo/cli@0.18.31":
+ version "0.18.31"
+ resolved "https://registry.yarnpkg.com/@expo/cli/-/cli-0.18.31.tgz#d07b7f1b2d10d146ec8b732ce1353b90912c56bd"
+ integrity sha512-v9llw9fT3Uv+TCM6Xllo54t672CuYtinEQZ2LPJ2EJsCwuTc4Cd2gXQaouuIVD21VoeGQnr5JtJuWbF97sBKzQ==
+ dependencies:
+ "@babel/runtime" "^7.20.0"
+ "@expo/code-signing-certificates" "0.0.5"
+ "@expo/config" "~9.0.0-beta.0"
+ "@expo/config-plugins" "~8.0.8"
+ "@expo/devcert" "^1.0.0"
+ "@expo/env" "~0.3.0"
+ "@expo/image-utils" "^0.5.0"
+ "@expo/json-file" "^8.3.0"
+ "@expo/metro-config" "0.18.11"
+ "@expo/osascript" "^2.0.31"
+ "@expo/package-manager" "^1.5.0"
+ "@expo/plist" "^0.1.0"
+ "@expo/prebuild-config" "7.0.9"
+ "@expo/rudder-sdk-node" "1.1.1"
+ "@expo/spawn-async" "^1.7.2"
+ "@expo/xcpretty" "^4.3.0"
+ "@react-native/dev-middleware" "0.74.85"
+ "@urql/core" "2.3.6"
+ "@urql/exchange-retry" "0.3.0"
+ accepts "^1.3.8"
+ arg "5.0.2"
+ better-opn "~3.0.2"
+ bplist-creator "0.0.7"
+ bplist-parser "^0.3.1"
+ cacache "^18.0.2"
+ chalk "^4.0.0"
+ ci-info "^3.3.0"
+ connect "^3.7.0"
+ debug "^4.3.4"
+ env-editor "^0.4.1"
+ fast-glob "^3.3.2"
+ find-yarn-workspace-root "~2.0.0"
+ form-data "^3.0.1"
+ freeport-async "2.0.0"
+ fs-extra "~8.1.0"
+ getenv "^1.0.0"
+ glob "^7.1.7"
+ graphql "15.8.0"
+ graphql-tag "^2.10.1"
+ https-proxy-agent "^5.0.1"
+ internal-ip "4.3.0"
+ is-docker "^2.0.0"
+ is-wsl "^2.1.1"
+ js-yaml "^3.13.1"
+ json-schema-deref-sync "^0.13.0"
+ lodash.debounce "^4.0.8"
+ md5hex "^1.0.0"
+ minimatch "^3.0.4"
+ node-fetch "^2.6.7"
+ node-forge "^1.3.1"
+ npm-package-arg "^7.0.0"
+ open "^8.3.0"
+ ora "3.4.0"
+ picomatch "^3.0.1"
+ pretty-bytes "5.6.0"
+ progress "2.0.3"
+ prompts "^2.3.2"
+ qrcode-terminal "0.11.0"
+ require-from-string "^2.0.2"
+ requireg "^0.2.2"
+ resolve "^1.22.2"
+ resolve-from "^5.0.0"
+ resolve.exports "^2.0.2"
+ semver "^7.6.0"
+ send "^0.18.0"
+ slugify "^1.3.4"
+ source-map-support "~0.5.21"
+ stacktrace-parser "^0.1.10"
+ structured-headers "^0.4.1"
+ tar "^6.0.5"
+ temp-dir "^2.0.0"
+ tempy "^0.7.1"
+ terminal-link "^2.1.1"
+ text-table "^0.2.0"
+ url-join "4.0.0"
+ wrap-ansi "^7.0.0"
+ ws "^8.12.1"
+
+"@expo/code-signing-certificates@0.0.5":
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/@expo/code-signing-certificates/-/code-signing-certificates-0.0.5.tgz#a693ff684fb20c4725dade4b88a6a9f96b02496c"
+ integrity sha512-BNhXkY1bblxKZpltzAx98G2Egj9g1Q+JRcvR7E99DOj862FTCX+ZPsAUtPTr7aHxwtrL7+fL3r0JSmM9kBm+Bw==
+ dependencies:
+ node-forge "^1.2.1"
+ nullthrows "^1.1.1"
+
+"@expo/config-plugins@8.0.11", "@expo/config-plugins@~8.0.0", "@expo/config-plugins@~8.0.8":
+ version "8.0.11"
+ resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-8.0.11.tgz#b814395a910f4c8b7cc95d9719dccb6ca53ea4c5"
+ integrity sha512-oALE1HwnLFthrobAcC9ocnR9KXLzfWEjgIe4CPe+rDsfC6GDs8dGYCXfRFoCEzoLN4TGYs9RdZ8r0KoCcNrm2A==
+ dependencies:
+ "@expo/config-types" "^51.0.3"
+ "@expo/json-file" "~8.3.0"
+ "@expo/plist" "^0.1.0"
+ "@expo/sdk-runtime-versions" "^1.0.0"
+ chalk "^4.1.2"
+ debug "^4.3.1"
+ find-up "~5.0.0"
+ getenv "^1.0.0"
+ glob "7.1.6"
+ resolve-from "^5.0.0"
+ semver "^7.5.4"
+ slash "^3.0.0"
+ slugify "^1.6.6"
+ xcode "^3.0.1"
+ xml2js "0.6.0"
+
+"@expo/config-types@^51.0.3":
+ version "51.0.3"
+ resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-51.0.3.tgz#520bdce5fd75f9d234fd81bd0347443086419450"
+ integrity sha512-hMfuq++b8VySb+m9uNNrlpbvGxYc8OcFCUX9yTmi9tlx6A4k8SDabWFBgmnr4ao3wEArvWrtUQIfQCVtPRdpKA==
+
+"@expo/config@9.0.4", "@expo/config@~9.0.0", "@expo/config@~9.0.0-beta.0":
+ version "9.0.4"
+ resolved "https://registry.yarnpkg.com/@expo/config/-/config-9.0.4.tgz#52f0a94edd0e2c36dfb5e284cc1a6d99d9d2af97"
+ integrity sha512-g5ns5u1JSKudHYhjo1zaSfkJ/iZIcWmUmIQptMJZ6ag1C0ShL2sj8qdfU8MmAMuKLOgcIfSaiWlQnm4X3VJVkg==
+ dependencies:
+ "@babel/code-frame" "~7.10.4"
+ "@expo/config-plugins" "~8.0.8"
+ "@expo/config-types" "^51.0.3"
+ "@expo/json-file" "^8.3.0"
+ getenv "^1.0.0"
+ glob "7.1.6"
+ require-from-string "^2.0.2"
+ resolve-from "^5.0.0"
+ semver "^7.6.0"
+ slugify "^1.3.4"
+ sucrase "3.34.0"
+
+"@expo/devcert@^1.0.0":
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/@expo/devcert/-/devcert-1.1.4.tgz#d98807802a541847cc42791a606bfdc26e641277"
+ integrity sha512-fqBODr8c72+gBSX5Ty3SIzaY4bXainlpab78+vEYEKL3fXmsOswMLf0+KE36mUEAa36BYabX7K3EiXOXX5OPMw==
+ dependencies:
+ application-config-path "^0.1.0"
+ command-exists "^1.2.4"
+ debug "^3.1.0"
+ eol "^0.9.1"
+ get-port "^3.2.0"
+ glob "^10.4.2"
+ lodash "^4.17.21"
+ mkdirp "^0.5.1"
+ password-prompt "^1.0.4"
+ sudo-prompt "^8.2.0"
+ tmp "^0.0.33"
+ tslib "^2.4.0"
+
+"@expo/env@~0.3.0":
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/@expo/env/-/env-0.3.0.tgz#a66064e5656e0e48197525f47f3398034fdf579e"
+ integrity sha512-OtB9XVHWaXidLbHvrVDeeXa09yvTl3+IQN884sO6PhIi2/StXfgSH/9zC7IvzrDB8kW3EBJ1PPLuCUJ2hxAT7Q==
+ dependencies:
+ chalk "^4.0.0"
+ debug "^4.3.4"
+ dotenv "~16.4.5"
+ dotenv-expand "~11.0.6"
+ getenv "^1.0.0"
+
+"@expo/fingerprint@^0.10.2":
+ version "0.10.3"
+ resolved "https://registry.yarnpkg.com/@expo/fingerprint/-/fingerprint-0.10.3.tgz#87c2811fe7773ec7d00cae86ab041d578f9041b5"
+ integrity sha512-h/BnnyloJyMSrzeXonKLE6HfiMpRg3e9m8CAv+eUaAozG9heKMG9ftHW4cfm2StDYj/rWjFc5YK6MSIX6qd+xg==
+ dependencies:
+ "@expo/spawn-async" "^1.7.2"
+ chalk "^4.1.2"
+ debug "^4.3.4"
+ find-up "^5.0.0"
+ minimatch "^3.0.4"
+ p-limit "^3.1.0"
+ resolve-from "^5.0.0"
+ semver "^7.6.0"
+
+"@expo/image-utils@^0.5.0":
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/@expo/image-utils/-/image-utils-0.5.1.tgz#06fade141facebcd8431355923d30f3839309942"
+ integrity sha512-U/GsFfFox88lXULmFJ9Shfl2aQGcwoKPF7fawSCLixIKtMCpsI+1r0h+5i0nQnmt9tHuzXZDL8+Dg1z6OhkI9A==
+ dependencies:
+ "@expo/spawn-async" "^1.7.2"
+ chalk "^4.0.0"
+ fs-extra "9.0.0"
+ getenv "^1.0.0"
+ jimp-compact "0.16.1"
+ node-fetch "^2.6.0"
+ parse-png "^2.1.0"
+ resolve-from "^5.0.0"
+ semver "^7.6.0"
+ tempy "0.3.0"
+
+"@expo/json-file@^8.3.0", "@expo/json-file@~8.3.0":
+ version "8.3.3"
+ resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.3.3.tgz#7926e3592f76030ce63d6b1308ac8f5d4d9341f4"
+ integrity sha512-eZ5dld9AD0PrVRiIWpRkm5aIoWBw3kAyd8VkuWEy92sEthBKDDDHAnK2a0dw0Eil6j7rK7lS/Qaq/Zzngv2h5A==
+ dependencies:
+ "@babel/code-frame" "~7.10.4"
+ json5 "^2.2.2"
+ write-file-atomic "^2.3.0"
+
+"@expo/json-file@^9.0.1":
+ version "9.0.1"
+ resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-9.0.1.tgz#ff60654caf1fa3c33f9b17dcd1e9691eb854a318"
+ integrity sha512-ZVPhbbEBEwafPCJ0+kI25O2Iivt3XKHEKAADCml1q2cmOIbQnKgLyn8DpOJXqWEyRQr/VWS+hflBh8DU2YFSqg==
+ dependencies:
+ "@babel/code-frame" "~7.10.4"
+ json5 "^2.2.3"
+ write-file-atomic "^2.3.0"
+
+"@expo/metro-config@0.18.11":
+ version "0.18.11"
+ resolved "https://registry.yarnpkg.com/@expo/metro-config/-/metro-config-0.18.11.tgz#22e82d92fb9d94ac760cc8b3bff48e6f32b4f032"
+ integrity sha512-/uOq55VbSf9yMbUO1BudkUM2SsGW1c5hr9BnhIqYqcsFv0Jp5D3DtJ4rljDKaUeNLbwr6m7pqIrkSMq5NrYf4Q==
+ dependencies:
+ "@babel/core" "^7.20.0"
+ "@babel/generator" "^7.20.5"
+ "@babel/parser" "^7.20.0"
+ "@babel/types" "^7.20.0"
+ "@expo/config" "~9.0.0-beta.0"
+ "@expo/env" "~0.3.0"
+ "@expo/json-file" "~8.3.0"
+ "@expo/spawn-async" "^1.7.2"
+ chalk "^4.1.0"
+ debug "^4.3.2"
+ find-yarn-workspace-root "~2.0.0"
+ fs-extra "^9.1.0"
+ getenv "^1.0.0"
+ glob "^7.2.3"
+ jsc-safe-url "^0.2.4"
+ lightningcss "~1.19.0"
+ postcss "~8.4.32"
+ resolve-from "^5.0.0"
+
+"@expo/metro-runtime@3.2.3":
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/@expo/metro-runtime/-/metro-runtime-3.2.3.tgz#e074c28084f30725f8d0d0eeee4fcd6074797d2d"
+ integrity sha512-v5ji+fAGi7B9YavrxvekuF8gXEV/5fz0+PhaED5AaFDnbGB4IJIbpaiqK9nqZV1axjGZNQSw6Q8TsnFetCR3bQ==
+
+"@expo/osascript@^2.0.31":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@expo/osascript/-/osascript-2.1.5.tgz#655c3913e592efbb5db41273b76920911c60809e"
+ integrity sha512-Cp7YF7msGiTAIbFdzNovwHBfecdMLVL5XzSqq4xQz72ALFCQ3uSIUXRph1QV2r61ugH7Yem0gY8yi7RcDlI4qg==
+ dependencies:
+ "@expo/spawn-async" "^1.7.2"
+ exec-async "^2.2.0"
+
+"@expo/package-manager@^1.5.0":
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/@expo/package-manager/-/package-manager-1.7.1.tgz#13eb686bc949a395d992fb2575f8a1930a6aebf3"
+ integrity sha512-DKbELrTOdl7U3KT0C07Aka9P+sUP3LL+1UTKf1KmLx2x2gPH1IC+c68N7iQlwNt+yA37qIw6/vKoqyTGu5EL9g==
+ dependencies:
+ "@expo/json-file" "^9.0.1"
+ "@expo/spawn-async" "^1.7.2"
+ ansi-regex "^5.0.0"
+ chalk "^4.0.0"
+ find-up "^5.0.0"
+ js-yaml "^3.13.1"
+ micromatch "^4.0.8"
+ npm-package-arg "^11.0.0"
+ ora "^3.4.0"
+ resolve-workspace-root "^2.0.0"
+ split "^1.0.1"
+ sudo-prompt "9.1.1"
+
+"@expo/plist@^0.1.0":
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.1.3.tgz#b4fbee2c4f7a88512a4853d85319f4d95713c529"
+ integrity sha512-GW/7hVlAylYg1tUrEASclw1MMk9FP4ZwyFAY/SUTJIhPDQHtfOlXREyWV3hhrHdX/K+pS73GNgdfT6E/e+kBbg==
+ dependencies:
+ "@xmldom/xmldom" "~0.7.7"
+ base64-js "^1.2.3"
+ xmlbuilder "^14.0.0"
+
+"@expo/prebuild-config@7.0.9":
+ version "7.0.9"
+ resolved "https://registry.yarnpkg.com/@expo/prebuild-config/-/prebuild-config-7.0.9.tgz#7abd489e18ed6514a0c9cd214eb34c0d5efda799"
+ integrity sha512-9i6Cg7jInpnGEHN0jxnW0P+0BexnePiBzmbUvzSbRXpdXihYUX2AKMu73jgzxn5P1hXOSkzNS7umaY+BZ+aBag==
+ dependencies:
+ "@expo/config" "~9.0.0-beta.0"
+ "@expo/config-plugins" "~8.0.8"
+ "@expo/config-types" "^51.0.3"
+ "@expo/image-utils" "^0.5.0"
+ "@expo/json-file" "^8.3.0"
+ "@react-native/normalize-colors" "0.74.85"
+ debug "^4.3.1"
+ fs-extra "^9.0.0"
+ resolve-from "^5.0.0"
+ semver "^7.6.0"
+ xml2js "0.6.0"
+
+"@expo/react-native-action-sheet@^4.1.0":
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/@expo/react-native-action-sheet/-/react-native-action-sheet-4.1.0.tgz#d10da29f487a4e0fa8c688b560cc354d5212d9d3"
+ integrity sha512-RILoWhREgjMdr1NUSmZa/cHg8onV2YPDAMOy0iIP1c3H7nT9QQZf5dQNHK8ehcLM82sarVxriBJyYSSHAx7j6w==
+ dependencies:
+ "@types/hoist-non-react-statics" "^3.3.1"
+ hoist-non-react-statics "^3.3.0"
+
+"@expo/rudder-sdk-node@1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@expo/rudder-sdk-node/-/rudder-sdk-node-1.1.1.tgz#6aa575f346833eb6290282118766d4919c808c6a"
+ integrity sha512-uy/hS/awclDJ1S88w9UGpc6Nm9XnNUjzOAAib1A3PVAnGQIwebg8DpFqOthFBTlZxeuV/BKbZ5jmTbtNZkp1WQ==
+ dependencies:
+ "@expo/bunyan" "^4.0.0"
+ "@segment/loosely-validate-event" "^2.0.0"
+ fetch-retry "^4.1.1"
+ md5 "^2.2.1"
+ node-fetch "^2.6.1"
+ remove-trailing-slash "^0.1.0"
+ uuid "^8.3.2"
+
+"@expo/sdk-runtime-versions@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz#d7ebd21b19f1c6b0395e50d78da4416941c57f7c"
+ integrity sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ==
+
+"@expo/server@^0.4.0":
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/@expo/server/-/server-0.4.4.tgz#f89a8e57ef93b35e9635632e217a8868f762f358"
+ integrity sha512-q9ADBzMN5rZ/fgQ2mz5YIJuZ8gelQlhG2CQqToD+UvBLZvbaHCNxTTSs2KI1LzJvAaW5CWgWMatGvGF6iUQ0LA==
+ dependencies:
+ "@remix-run/node" "^2.7.2"
+ abort-controller "^3.0.0"
+ debug "^4.3.4"
+ source-map-support "~0.5.21"
+
+"@expo/spawn-async@^1.7.2":
+ version "1.7.2"
+ resolved "https://registry.yarnpkg.com/@expo/spawn-async/-/spawn-async-1.7.2.tgz#fcfe66c3e387245e72154b1a7eae8cada6a47f58"
+ integrity sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew==
+ dependencies:
+ cross-spawn "^7.0.3"
+
+"@expo/vector-icons@^14.0.3", "@expo/vector-icons@^14.0.4":
+ version "14.0.4"
+ resolved "https://registry.yarnpkg.com/@expo/vector-icons/-/vector-icons-14.0.4.tgz#fa9d4351877312badf91a806598b2f0bab16039a"
+ integrity sha512-+yKshcbpDfbV4zoXOgHxCwh7lkE9VVTT5T03OUlBsqfze1PLy6Hi4jp1vSb1GVbY6eskvMIivGVc9SKzIv0oEQ==
+ dependencies:
+ prop-types "^15.8.1"
+
+"@expo/xcpretty@^4.3.0":
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/@expo/xcpretty/-/xcpretty-4.3.2.tgz#12dba1295167a9c8dde4be783d74f7e81648ca5d"
+ integrity sha512-ReZxZ8pdnoI3tP/dNnJdnmAk7uLT4FjsKDGW7YeDdvdOMz2XCQSmSCM9IWlrXuWtMF9zeSB6WJtEhCQ41gQOfw==
+ dependencies:
+ "@babel/code-frame" "7.10.4"
+ chalk "^4.1.0"
+ find-up "^5.0.0"
+ js-yaml "^4.1.0"
+
+"@floating-ui/core@^1.6.0":
+ version "1.6.9"
+ resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.9.tgz#64d1da251433019dafa091de9b2886ff35ec14e6"
+ integrity sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==
+ dependencies:
+ "@floating-ui/utils" "^0.2.9"
+
+"@floating-ui/dom@^1.0.0":
+ version "1.6.13"
+ resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.13.tgz#a8a938532aea27a95121ec16e667a7cbe8c59e34"
+ integrity sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==
+ dependencies:
+ "@floating-ui/core" "^1.6.0"
+ "@floating-ui/utils" "^0.2.9"
+
+"@floating-ui/react-dom@^2.0.0":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31"
+ integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==
+ dependencies:
+ "@floating-ui/dom" "^1.0.0"
+
+"@floating-ui/utils@^0.2.9":
+ version "0.2.9"
+ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429"
+ integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==
+
+"@futurejj/react-native-visibility-sensor@^1.3.5":
+ version "1.3.9"
+ resolved "https://registry.yarnpkg.com/@futurejj/react-native-visibility-sensor/-/react-native-visibility-sensor-1.3.9.tgz#b00f5cbf8224862d51eddc60537364b38a68b5d2"
+ integrity sha512-3V6Cx8CZo4zJqcfapYs5e0dkkpA2PZTIB2UezKM0USO6qYm0G3fET7V3XMZGZVXYjAhG0yXtXunlgMhsFSSUBQ==
+
+"@gorhom/bottom-sheet@^4.6.4":
+ version "4.6.4"
+ resolved "https://registry.yarnpkg.com/@gorhom/bottom-sheet/-/bottom-sheet-4.6.4.tgz#387d0f0f21e3470eb8575498cb81ce96f5108e79"
+ integrity sha512-0itLMblLBvepE065w3a60S030c2rNUsGshPC7wbWDm31VyqoaU2xjzh/ojH62YIJOcobBr5QoC30IxBBKDGovQ==
+ dependencies:
+ "@gorhom/portal" "1.0.14"
+ invariant "^2.2.4"
+
+"@gorhom/portal@1.0.14":
+ version "1.0.14"
+ resolved "https://registry.yarnpkg.com/@gorhom/portal/-/portal-1.0.14.tgz#1953edb76aaba80fb24021dc774550194a18e111"
+ integrity sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A==
+ dependencies:
+ nanoid "^3.3.1"
+
+"@graphql-typed-document-node/core@^3.1.0":
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861"
+ integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==
+
+"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0":
+ version "9.3.0"
+ resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
+ integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
+
+"@hapi/topo@^5.1.0":
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
+ integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
+ dependencies:
+ "@hapi/hoek" "^9.0.0"
+
+"@ide/backoff@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@ide/backoff/-/backoff-1.0.0.tgz#466842c25bd4a4833e0642fab41ccff064010176"
+ integrity sha512-F0YfUDjvT+Mtt/R4xdl2X0EYCHMMiJqNLdxHD++jDT5ydEFIyqbCHh51Qx2E211dgZprPKhV7sHmnXKpLuvc5g==
+
+"@isaacs/cliui@^8.0.2":
+ version "8.0.2"
+ resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
+ integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
+ dependencies:
+ string-width "^5.1.2"
+ string-width-cjs "npm:string-width@^4.2.0"
+ strip-ansi "^7.0.1"
+ strip-ansi-cjs "npm:strip-ansi@^6.0.1"
+ wrap-ansi "^8.1.0"
+ wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
+
+"@isaacs/ttlcache@^1.4.1":
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz#21fb23db34e9b6220c6ba023a0118a2dd3461ea2"
+ integrity sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==
+
+"@jellyfin/sdk@^0.11.0":
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/@jellyfin/sdk/-/sdk-0.11.0.tgz#74c7d81f306c7b64c3d27dd35199a089d84097c1"
+ integrity sha512-WmM4as9ptqH+CvC2YsUefNWQDmu2aWIamwAoj7h2BFR6l019pcRFG5FT22egwbdizR6DfdpmsoAWB4x9QCzcEQ==
+
+"@jest/create-cache-key-function@^29.6.3":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz#793be38148fab78e65f40ae30c36785f4ad859f0"
+ integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==
+ dependencies:
+ "@jest/types" "^29.6.3"
+
+"@jest/environment@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7"
+ integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==
+ dependencies:
+ "@jest/fake-timers" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ jest-mock "^29.7.0"
+
+"@jest/expect-utils@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6"
+ integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==
+ dependencies:
+ jest-get-type "^29.6.3"
+
+"@jest/fake-timers@^29.7.0":
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565"
+ integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@sinonjs/fake-timers" "^10.0.2"
+ "@types/node" "*"
+ jest-message-util "^29.7.0"
+ jest-mock "^29.7.0"
+ jest-util "^29.7.0"
+
+"@jest/schemas@^29.6.3":
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03"
+ integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==
+ dependencies:
+ "@sinclair/typebox" "^0.27.8"
+
+"@jest/types@^24.9.0":
+ version "24.9.0"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59"
+ integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==
+ dependencies:
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^1.1.1"
+ "@types/yargs" "^13.0.0"
+
+"@jest/types@^26.6.2":
+ version "26.6.2"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e"
+ integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==
+ dependencies:
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^15.0.0"
+ chalk "^4.0.0"
+
+"@jest/types@^29.6.3":
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59"
+ integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==
+ dependencies:
+ "@jest/schemas" "^29.6.3"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^17.0.8"
+ chalk "^4.0.0"
+
+"@jimp/bmp@^0.16.13":
+ version "0.16.13"
+ resolved "https://registry.yarnpkg.com/@jimp/bmp/-/bmp-0.16.13.tgz#57ffa5b17417b5a181f6f184bdabc8218e8448ef"
+ integrity sha512-9edAxu7N2FX7vzkdl5Jo1BbACfycUtBQX+XBMcHA2bk62P8R0otgkHg798frgAk/WxQIzwxqOH6wMiCwrlAzdQ==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ "@jimp/utils" "^0.16.13"
+ bmp-js "^0.1.0"
+
+"@jimp/core@^0.16.13":
+ version "0.16.13"
+ resolved "https://registry.yarnpkg.com/@jimp/core/-/core-0.16.13.tgz#7171745a912b5b847f8bf53e70b0672c5ca92744"
+ integrity sha512-qXpA1tzTnlkTku9yqtuRtS/wVntvE6f3m3GNxdTdtmc+O+Wcg9Xo2ABPMh7Nc0AHbMKzwvwgB2JnjZmlmJEObg==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ "@jimp/utils" "^0.16.13"
+ any-base "^1.1.0"
+ buffer "^5.2.0"
+ exif-parser "^0.1.12"
+ file-type "^16.5.4"
+ load-bmfont "^1.3.1"
+ mkdirp "^0.5.1"
+ phin "^2.9.1"
+ pixelmatch "^4.0.2"
+ tinycolor2 "^1.4.1"
+
+"@jimp/custom@^0.16.1":
+ version "0.16.13"
+ resolved "https://registry.yarnpkg.com/@jimp/custom/-/custom-0.16.13.tgz#2e4ed447b7410b81fe9103682b4166af904daf84"
+ integrity sha512-LTATglVUPGkPf15zX1wTMlZ0+AU7cGEGF6ekVF1crA8eHUWsGjrYTB+Ht4E3HTrCok8weQG+K01rJndCp/l4XA==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ "@jimp/core" "^0.16.13"
+
+"@jimp/gif@^0.16.13":
+ version "0.16.13"
+ resolved "https://registry.yarnpkg.com/@jimp/gif/-/gif-0.16.13.tgz#fa72f35d8ad67d6ce3a3d7ef6c8d04a462afaaf9"
+ integrity sha512-yFAMZGv3o+YcjXilMWWwS/bv1iSqykFahFMSO169uVMtfQVfa90kt4/kDwrXNR6Q9i6VHpFiGZMlF2UnHClBvg==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ "@jimp/utils" "^0.16.13"
+ gifwrap "^0.9.2"
+ omggif "^1.0.9"
+
+"@jimp/jpeg@^0.16.13":
+ version "0.16.13"
+ resolved "https://registry.yarnpkg.com/@jimp/jpeg/-/jpeg-0.16.13.tgz#e1c128a591bd7f8a26c8731fd0bc65d32d4ba32a"
+ integrity sha512-BJHlDxzTlCqP2ThqP8J0eDrbBfod7npWCbJAcfkKqdQuFk0zBPaZ6KKaQKyKxmWJ87Z6ohANZoMKEbtvrwz1AA==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ "@jimp/utils" "^0.16.13"
+ jpeg-js "^0.4.2"
+
+"@jimp/plugin-resize@^0.16.1":
+ version "0.16.13"
+ resolved "https://registry.yarnpkg.com/@jimp/plugin-resize/-/plugin-resize-0.16.13.tgz#6267087f724d47e7bb8824c5b842d9315f50b8e7"
+ integrity sha512-qoqtN8LDknm3fJm9nuPygJv30O3vGhSBD2TxrsCnhtOsxKAqVPJtFVdGd/qVuZ8nqQANQmTlfqTiK9mVWQ7MiQ==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ "@jimp/utils" "^0.16.13"
+
+"@jimp/png@^0.16.13":
+ version "0.16.13"
+ resolved "https://registry.yarnpkg.com/@jimp/png/-/png-0.16.13.tgz#8b130cc5e1e754c074c42fa3fe2609897cefdf7c"
+ integrity sha512-8cGqINvbWJf1G0Her9zbq9I80roEX0A+U45xFby3tDWfzn+Zz8XKDF1Nv9VUwVx0N3zpcG1RPs9hfheG4Cq2kg==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ "@jimp/utils" "^0.16.13"
+ pngjs "^3.3.3"
+
+"@jimp/tiff@^0.16.13":
+ version "0.16.13"
+ resolved "https://registry.yarnpkg.com/@jimp/tiff/-/tiff-0.16.13.tgz#9cf8d19f2b0b0c46758e81acfc7d656835ee6da1"
+ integrity sha512-oJY8d9u95SwW00VPHuCNxPap6Q1+E/xM5QThb9Hu+P6EGuu6lIeLaNBMmFZyblwFbwrH+WBOZlvIzDhi4Dm/6Q==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ utif "^2.0.1"
+
+"@jimp/types@^0.16.1":
+ version "0.16.13"
+ resolved "https://registry.yarnpkg.com/@jimp/types/-/types-0.16.13.tgz#39be1886cbfa4fb5e77e17441a046a1f961d3046"
+ integrity sha512-mC0yVNUobFDjoYLg4hoUwzMKgNlxynzwt3cDXzumGvRJ7Kb8qQGOWJQjQFo5OxmGExqzPphkirdbBF88RVLBCg==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ "@jimp/bmp" "^0.16.13"
+ "@jimp/gif" "^0.16.13"
+ "@jimp/jpeg" "^0.16.13"
+ "@jimp/png" "^0.16.13"
+ "@jimp/tiff" "^0.16.13"
+ timm "^1.6.1"
+
+"@jimp/utils@^0.16.13":
+ version "0.16.13"
+ resolved "https://registry.yarnpkg.com/@jimp/utils/-/utils-0.16.13.tgz#afde41b9c6cdadfb45d83cb5e16deb65f369bf99"
+ integrity sha512-VyCpkZzFTHXtKgVO35iKN0sYR10psGpV6SkcSeV4oF7eSYlR8Bl6aQLCzVeFjvESF7mxTmIiI3/XrMobVrtxDA==
+ dependencies:
+ "@babel/runtime" "^7.7.2"
+ regenerator-runtime "^0.13.3"
+
+"@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5":
+ version "0.3.8"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142"
+ integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==
+ dependencies:
+ "@jridgewell/set-array" "^1.2.1"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+ "@jridgewell/trace-mapping" "^0.3.24"
+
+"@jridgewell/resolve-uri@^3.1.0":
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
+ integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
+
+"@jridgewell/set-array@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280"
+ integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
+
+"@jridgewell/source-map@^0.3.3":
+ version "0.3.6"
+ resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a"
+ integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.5"
+ "@jridgewell/trace-mapping" "^0.3.25"
+
+"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14":
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
+ integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
+
+"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25":
+ version "0.3.25"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
+ integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.1.0"
+ "@jridgewell/sourcemap-codec" "^1.4.14"
+
+"@kesha-antonov/react-native-background-downloader@3.2.6":
+ version "3.2.6"
+ resolved "https://registry.yarnpkg.com/@kesha-antonov/react-native-background-downloader/-/react-native-background-downloader-3.2.6.tgz#87656a9c6e31f9b7b915cd64b6a89e18896e79e8"
+ integrity sha512-J87PHzBh4knWTQNkCNM4LTMZ85RpMW/QSV+0LGdTxz4JmfLXoeg8R6ratbFU0DP/l8K1eL7r4S1Rc8bmqNJ3Ug==
+
+"@nodelib/fs.scandir@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.5"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.walk@^1.2.3":
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
+"@npmcli/fs@^3.1.0":
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.1.tgz#59cdaa5adca95d135fc00f2bb53f5771575ce726"
+ integrity sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==
+ dependencies:
+ semver "^7.3.5"
+
+"@pkgjs/parseargs@^0.11.0":
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
+ integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
+
+"@radix-ui/primitive@1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.1.tgz#fc169732d755c7fbad33ba8d0cd7fd10c90dc8e3"
+ integrity sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==
+
+"@radix-ui/react-arrow@1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz#2103721933a8bfc6e53bbfbdc1aaad5fc8ba0dd7"
+ integrity sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w==
+ dependencies:
+ "@radix-ui/react-primitive" "2.0.1"
+
+"@radix-ui/react-collection@1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.1.tgz#be2c7e01d3508e6d4b6d838f492e7d182f17d3b0"
+ integrity sha512-LwT3pSho9Dljg+wY2KN2mrrh6y3qELfftINERIzBUO9e0N+t0oMTyn3k9iv+ZqgrwGkRnLpNJrsMv9BZlt2yuA==
+ dependencies:
+ "@radix-ui/react-compose-refs" "1.1.1"
+ "@radix-ui/react-context" "1.1.1"
+ "@radix-ui/react-primitive" "2.0.1"
+ "@radix-ui/react-slot" "1.1.1"
+
+"@radix-ui/react-compose-refs@1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz#37595b1f16ec7f228d698590e78eeed18ff218ae"
+ integrity sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+
+"@radix-ui/react-compose-refs@1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz#6f766faa975f8738269ebb8a23bad4f5a8d2faec"
+ integrity sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==
+
+"@radix-ui/react-context-menu@^2.0.1":
+ version "2.2.5"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-context-menu/-/react-context-menu-2.2.5.tgz#56eec9d96c6b27fb37a5e08f62caf2e263e29d4b"
+ integrity sha512-MY5PFCwo/ICaaQtpQBQ0g19AyjzI0mhz+a2GUWA2pJf4XFkvglAdcgDV2Iqm+lLbXn8hb+6rbLgcmRtc6ImPvg==
+ dependencies:
+ "@radix-ui/primitive" "1.1.1"
+ "@radix-ui/react-context" "1.1.1"
+ "@radix-ui/react-menu" "2.1.5"
+ "@radix-ui/react-primitive" "2.0.1"
+ "@radix-ui/react-use-callback-ref" "1.1.0"
+ "@radix-ui/react-use-controllable-state" "1.1.0"
+
+"@radix-ui/react-context@1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a"
+ integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==
+
+"@radix-ui/react-direction@1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc"
+ integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==
+
+"@radix-ui/react-dismissable-layer@1.1.4":
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.4.tgz#6e31ad92e7d9e77548001fd8c04f8561300c02a9"
+ integrity sha512-XDUI0IVYVSwjMXxM6P4Dfti7AH+Y4oS/TB+sglZ/EXc7cqLwGAmp1NlMrcUjj7ks6R5WTZuWKv44FBbLpwU3sA==
+ dependencies:
+ "@radix-ui/primitive" "1.1.1"
+ "@radix-ui/react-compose-refs" "1.1.1"
+ "@radix-ui/react-primitive" "2.0.1"
+ "@radix-ui/react-use-callback-ref" "1.1.0"
+ "@radix-ui/react-use-escape-keydown" "1.1.0"
+
+"@radix-ui/react-dropdown-menu@^2.0.1":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.5.tgz#82293e6a7572f77c18f3aebb943676019a7872da"
+ integrity sha512-50ZmEFL1kOuLalPKHrLWvPFMons2fGx9TqQCWlPwDVpbAnaUJ1g4XNcKqFNMQymYU0kKWR4MDDi+9vUQBGFgcQ==
+ dependencies:
+ "@radix-ui/primitive" "1.1.1"
+ "@radix-ui/react-compose-refs" "1.1.1"
+ "@radix-ui/react-context" "1.1.1"
+ "@radix-ui/react-id" "1.1.0"
+ "@radix-ui/react-menu" "2.1.5"
+ "@radix-ui/react-primitive" "2.0.1"
+ "@radix-ui/react-use-controllable-state" "1.1.0"
+
+"@radix-ui/react-focus-guards@1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe"
+ integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==
+
+"@radix-ui/react-focus-scope@1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.1.tgz#5c602115d1db1c4fcfa0fae4c3b09bb8919853cb"
+ integrity sha512-01omzJAYRxXdG2/he/+xy+c8a8gCydoQ1yOxnWNcRhrrBW5W+RQJ22EK1SaO8tb3WoUsuEw7mJjBozPzihDFjA==
+ dependencies:
+ "@radix-ui/react-compose-refs" "1.1.1"
+ "@radix-ui/react-primitive" "2.0.1"
+ "@radix-ui/react-use-callback-ref" "1.1.0"
+
+"@radix-ui/react-id@1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed"
+ integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==
+ dependencies:
+ "@radix-ui/react-use-layout-effect" "1.1.0"
+
+"@radix-ui/react-menu@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.1.5.tgz#0c2e7a368771b6061e7f3692f18240917547ef7f"
+ integrity sha512-uH+3w5heoMJtqVCgYOtYVMECk1TOrkUn0OG0p5MqXC0W2ppcuVeESbou8PTHoqAjbdTEK19AGXBWcEtR5WpEQg==
+ dependencies:
+ "@radix-ui/primitive" "1.1.1"
+ "@radix-ui/react-collection" "1.1.1"
+ "@radix-ui/react-compose-refs" "1.1.1"
+ "@radix-ui/react-context" "1.1.1"
+ "@radix-ui/react-direction" "1.1.0"
+ "@radix-ui/react-dismissable-layer" "1.1.4"
+ "@radix-ui/react-focus-guards" "1.1.1"
+ "@radix-ui/react-focus-scope" "1.1.1"
+ "@radix-ui/react-id" "1.1.0"
+ "@radix-ui/react-popper" "1.2.1"
+ "@radix-ui/react-portal" "1.1.3"
+ "@radix-ui/react-presence" "1.1.2"
+ "@radix-ui/react-primitive" "2.0.1"
+ "@radix-ui/react-roving-focus" "1.1.1"
+ "@radix-ui/react-slot" "1.1.1"
+ "@radix-ui/react-use-callback-ref" "1.1.0"
+ aria-hidden "^1.2.4"
+ react-remove-scroll "^2.6.2"
+
+"@radix-ui/react-popper@1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.1.tgz#2fc66cfc34f95f00d858924e3bee54beae2dff0a"
+ integrity sha512-3kn5Me69L+jv82EKRuQCXdYyf1DqHwD2U/sxoNgBGCB7K9TRc3bQamQ+5EPM9EvyPdli0W41sROd+ZU1dTCztw==
+ dependencies:
+ "@floating-ui/react-dom" "^2.0.0"
+ "@radix-ui/react-arrow" "1.1.1"
+ "@radix-ui/react-compose-refs" "1.1.1"
+ "@radix-ui/react-context" "1.1.1"
+ "@radix-ui/react-primitive" "2.0.1"
+ "@radix-ui/react-use-callback-ref" "1.1.0"
+ "@radix-ui/react-use-layout-effect" "1.1.0"
+ "@radix-ui/react-use-rect" "1.1.0"
+ "@radix-ui/react-use-size" "1.1.0"
+ "@radix-ui/rect" "1.1.0"
+
+"@radix-ui/react-portal@1.1.3":
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.3.tgz#b0ea5141103a1671b715481b13440763d2ac4440"
+ integrity sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==
+ dependencies:
+ "@radix-ui/react-primitive" "2.0.1"
+ "@radix-ui/react-use-layout-effect" "1.1.0"
+
+"@radix-ui/react-presence@1.1.2":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.2.tgz#bb764ed8a9118b7ec4512da5ece306ded8703cdc"
+ integrity sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==
+ dependencies:
+ "@radix-ui/react-compose-refs" "1.1.1"
+ "@radix-ui/react-use-layout-effect" "1.1.0"
+
+"@radix-ui/react-primitive@2.0.1":
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz#6d9efc550f7520135366f333d1e820cf225fad9e"
+ integrity sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==
+ dependencies:
+ "@radix-ui/react-slot" "1.1.1"
+
+"@radix-ui/react-roving-focus@1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.1.tgz#3b3abb1e03646937f28d9ab25e96343667ca6520"
+ integrity sha512-QE1RoxPGJ/Nm8Qmk0PxP8ojmoaS67i0s7hVssS7KuI2FQoc/uzVlZsqKfQvxPE6D8hICCPHJ4D88zNhT3OOmkw==
+ dependencies:
+ "@radix-ui/primitive" "1.1.1"
+ "@radix-ui/react-collection" "1.1.1"
+ "@radix-ui/react-compose-refs" "1.1.1"
+ "@radix-ui/react-context" "1.1.1"
+ "@radix-ui/react-direction" "1.1.0"
+ "@radix-ui/react-id" "1.1.0"
+ "@radix-ui/react-primitive" "2.0.1"
+ "@radix-ui/react-use-callback-ref" "1.1.0"
+ "@radix-ui/react-use-controllable-state" "1.1.0"
+
+"@radix-ui/react-slot@1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.1.tgz#e7868c669c974d649070e9ecbec0b367ee0b4d81"
+ integrity sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw==
+ dependencies:
+ "@babel/runtime" "^7.13.10"
+ "@radix-ui/react-compose-refs" "1.0.0"
+
+"@radix-ui/react-slot@1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.1.tgz#ab9a0ffae4027db7dc2af503c223c978706affc3"
+ integrity sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==
+ dependencies:
+ "@radix-ui/react-compose-refs" "1.1.1"
+
+"@radix-ui/react-use-callback-ref@1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1"
+ integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==
+
+"@radix-ui/react-use-controllable-state@1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0"
+ integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==
+ dependencies:
+ "@radix-ui/react-use-callback-ref" "1.1.0"
+
+"@radix-ui/react-use-escape-keydown@1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754"
+ integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==
+ dependencies:
+ "@radix-ui/react-use-callback-ref" "1.1.0"
+
+"@radix-ui/react-use-layout-effect@1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27"
+ integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==
+
+"@radix-ui/react-use-rect@1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88"
+ integrity sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==
+ dependencies:
+ "@radix-ui/rect" "1.1.0"
+
+"@radix-ui/react-use-size@1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b"
+ integrity sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==
+ dependencies:
+ "@radix-ui/react-use-layout-effect" "1.1.0"
+
+"@radix-ui/rect@1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438"
+ integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==
+
+"@react-native-async-storage/async-storage@1.23.1":
+ version "1.23.1"
+ resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.23.1.tgz#cad3cd4fab7dacfe9838dce6ecb352f79150c883"
+ integrity sha512-Qd2kQ3yi6Y3+AcUlrHxSLlnBvpdCEMVGFlVBneVOjaFaPU61g1huc38g339ysXspwY1QZA2aNhrk/KlHGO+ewA==
+ dependencies:
+ merge-options "^3.0.4"
+
+"@react-native-community/cli-clean@13.6.9":
+ version "13.6.9"
+ resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-13.6.9.tgz#b6754f39c2b877c9d730feb848945150e1d52209"
+ integrity sha512-7Dj5+4p9JggxuVNOjPbduZBAP1SUgNhLKVw5noBUzT/3ZpUZkDM+RCSwyoyg8xKWoE4OrdUAXwAFlMcFDPKykA==
+ dependencies:
+ "@react-native-community/cli-tools" "13.6.9"
+ chalk "^4.1.2"
+ execa "^5.0.0"
+ fast-glob "^3.3.2"
+
+"@react-native-community/cli-config@13.6.9":
+ version "13.6.9"
+ resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-13.6.9.tgz#d609a64d40a173c89bd7d24e31807bb7dcba69f9"
+ integrity sha512-rFfVBcNojcMm+KKHE/xqpqXg8HoKl4EC7bFHUrahMJ+y/tZll55+oX/PGG37rzB8QzP2UbMQ19DYQKC1G7kXeg==
+ dependencies:
+ "@react-native-community/cli-tools" "13.6.9"
+ chalk "^4.1.2"
+ cosmiconfig "^5.1.0"
+ deepmerge "^4.3.0"
+ fast-glob "^3.3.2"
+ joi "^17.2.1"
+
+"@react-native-community/cli-debugger-ui@13.6.9":
+ version "13.6.9"
+ resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-13.6.9.tgz#bc5727c51964206a00d417e5148b46331a81d5a5"
+ integrity sha512-TkN7IdFmGPPvTpAo3nCAH9uwGCPxWBEAwpqEZDrq0NWllI7Tdie8vDpGdrcuCcKalmhq6OYnkXzeBah7O1Ztpw==
+ dependencies:
+ serve-static "^1.13.1"
+
+"@react-native-community/cli-doctor@13.6.9":
+ version "13.6.9"
+ resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-13.6.9.tgz#f1d4eeff427ddc8a9d19851042621c10939c35cb"
+ integrity sha512-5quFaLdWFQB+677GXh5dGU9I5eg2z6Vg4jOX9vKnc9IffwyIFAyJfCZHrxLSRPDGNXD7biDQUdoezXYGwb6P/A==
+ dependencies:
+ "@react-native-community/cli-config" "13.6.9"
+ "@react-native-community/cli-platform-android" "13.6.9"
+ "@react-native-community/cli-platform-apple" "13.6.9"
+ "@react-native-community/cli-platform-ios" "13.6.9"
+ "@react-native-community/cli-tools" "13.6.9"
+ chalk "^4.1.2"
+ command-exists "^1.2.8"
+ deepmerge "^4.3.0"
+ envinfo "^7.10.0"
+ execa "^5.0.0"
+ hermes-profile-transformer "^0.0.6"
+ node-stream-zip "^1.9.1"
+ ora "^5.4.1"
+ semver "^7.5.2"
+ strip-ansi "^5.2.0"
+ wcwidth "^1.0.1"
+ yaml "^2.2.1"
+
+"@react-native-community/cli-hermes@13.6.9":
+ version "13.6.9"
+ resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-13.6.9.tgz#88c8dfe936a0d4272efc54429eda9ccc3fca3ad8"
+ integrity sha512-GvwiwgvFw4Ws+krg2+gYj8sR3g05evmNjAHkKIKMkDTJjZ8EdyxbkifRUs1ZCq3TMZy2oeblZBXCJVOH4W7ZbA==
+ dependencies:
+ "@react-native-community/cli-platform-android" "13.6.9"
+ "@react-native-community/cli-tools" "13.6.9"
+ chalk "^4.1.2"
+ hermes-profile-transformer "^0.0.6"
+
+"@react-native-community/cli-platform-android@13.6.9":
+ version "13.6.9"
+ resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-13.6.9.tgz#b175b9b11334fc90da3f395432678bd53c30fae4"
+ integrity sha512-9KsYGdr08QhdvT3Ht7e8phQB3gDX9Fs427NJe0xnoBh+PDPTI2BD5ks5ttsH8CzEw8/P6H8tJCHq6hf2nxd9cw==
+ dependencies:
+ "@react-native-community/cli-tools" "13.6.9"
+ chalk "^4.1.2"
+ execa "^5.0.0"
+ fast-glob "^3.3.2"
+ fast-xml-parser "^4.2.4"
+ logkitty "^0.7.1"
+
+"@react-native-community/cli-platform-apple@13.6.9":
+ version "13.6.9"
+ resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-13.6.9.tgz#02fb5dc47d62acd85f4d7a852e93216927a772fa"
+ integrity sha512-KoeIHfhxMhKXZPXmhQdl6EE+jGKWwoO9jUVWgBvibpVmsNjo7woaG/tfJMEWfWF3najX1EkQAoJWpCDBMYWtlA==
+ dependencies:
+ "@react-native-community/cli-tools" "13.6.9"
+ chalk "^4.1.2"
+ execa "^5.0.0"
+ fast-glob "^3.3.2"
+ fast-xml-parser "^4.0.12"
+ ora "^5.4.1"
+
+"@react-native-community/cli-platform-ios@13.6.9":
+ version "13.6.9"
+ resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-13.6.9.tgz#f37ceab41c2302e8f0d4bcbd3bf58b3353db4306"
+ integrity sha512-CiUcHlGs8vE0CAB4oi1f+dzniqfGuhWPNrDvae2nm8dewlahTBwIcK5CawyGezjcJoeQhjBflh9vloska+nlnw==
+ dependencies:
+ "@react-native-community/cli-platform-apple" "13.6.9"
+
+"@react-native-community/cli-server-api@13.6.9":
+ version "13.6.9"
+ resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-13.6.9.tgz#269e666bc26e9d0b2f42c7f6099559b5f9259e9d"
+ integrity sha512-W8FSlCPWymO+tlQfM3E0JmM8Oei5HZsIk5S0COOl0MRi8h0NmHI4WSTF2GCfbFZkcr2VI/fRsocoN8Au4EZAug==
+ dependencies:
+ "@react-native-community/cli-debugger-ui" "13.6.9"
+ "@react-native-community/cli-tools" "13.6.9"
+ compression "^1.7.1"
+ connect "^3.6.5"
+ errorhandler "^1.5.1"
+ nocache "^3.0.1"
+ pretty-format "^26.6.2"
+ serve-static "^1.13.1"
+ ws "^6.2.2"
+
+"@react-native-community/cli-tools@13.6.9":
+ version "13.6.9"
+ resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-13.6.9.tgz#2baee279358ba1a863e737b2fa9f45659ad91929"
+ integrity sha512-OXaSjoN0mZVw3nrAwcY1PC0uMfyTd9fz7Cy06dh+EJc+h0wikABsVRzV8cIOPrVV+PPEEXE0DBrH20T2puZzgQ==
+ dependencies:
+ appdirsjs "^1.2.4"
+ chalk "^4.1.2"
+ execa "^5.0.0"
+ find-up "^5.0.0"
+ mime "^2.4.1"
+ node-fetch "^2.6.0"
+ open "^6.2.0"
+ ora "^5.4.1"
+ semver "^7.5.2"
+ shell-quote "^1.7.3"
+ sudo-prompt "^9.0.0"
+
+"@react-native-community/cli-types@13.6.9":
+ version "13.6.9"
+ resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-13.6.9.tgz#08bfb796eacf0daeb31e2de516e81e78a36a1a55"
+ integrity sha512-RLxDppvRxXfs3hxceW/mShi+6o5yS+kFPnPqZTaMKKR5aSg7LwDpLQW4K2D22irEG8e6RKDkZUeH9aL3vO2O0w==
+ dependencies:
+ joi "^17.2.1"
+
+"@react-native-community/cli@13.6.9":
+ version "13.6.9"
+ resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-13.6.9.tgz#ba6360b94e0aba9c4001bda256cf7e57e2ecb02c"
+ integrity sha512-hFJL4cgLPxncJJd/epQ4dHnMg5Jy/7Q56jFvA3MHViuKpzzfTCJCB+pGY54maZbtym53UJON9WTGpM3S81UfjQ==
+ dependencies:
+ "@react-native-community/cli-clean" "13.6.9"
+ "@react-native-community/cli-config" "13.6.9"
+ "@react-native-community/cli-debugger-ui" "13.6.9"
+ "@react-native-community/cli-doctor" "13.6.9"
+ "@react-native-community/cli-hermes" "13.6.9"
+ "@react-native-community/cli-server-api" "13.6.9"
+ "@react-native-community/cli-tools" "13.6.9"
+ "@react-native-community/cli-types" "13.6.9"
+ chalk "^4.1.2"
+ commander "^9.4.1"
+ deepmerge "^4.3.0"
+ execa "^5.0.0"
+ find-up "^4.1.0"
+ fs-extra "^8.1.0"
+ graceful-fs "^4.1.3"
+ prompts "^2.4.2"
+ semver "^7.5.2"
+
+"@react-native-community/netinfo@11.3.1":
+ version "11.3.1"
+ resolved "https://registry.yarnpkg.com/@react-native-community/netinfo/-/netinfo-11.3.1.tgz#4539371a2f4bd402d932031be82c2449ed63a1a5"
+ integrity sha512-UBnJxyV0b7i9Moa97Av+HKho1ByzX0DtbJXzUQS5E3xhQs6P2D/Os0iw3ouy7joY1TVd6uIhplPbr7l1SJNaNQ==
+
+"@react-native-menu/menu@^1.1.6":
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/@react-native-menu/menu/-/menu-1.2.2.tgz#550d158f1496ae27cb68424d540d74ee08f6c181"
+ integrity sha512-Uk65PAhwNkCVBAqJu5t2H9biV+m0JLwJc7m3v2X2A/W8SFJmUqYabBsLH4fOWKI3a7kkR9QDT6HruliIKSfM8w==
+
+"@react-native/assets-registry@0.74.87":
+ version "0.74.87"
+ resolved "https://registry.yarnpkg.com/@react-native/assets-registry/-/assets-registry-0.74.87.tgz#7dda64e48db14597e19e15f679e31abbb1c1fb4d"
+ integrity sha512-1XmRhqQchN+pXPKEKYdpJlwESxVomJOxtEnIkbo7GAlaN2sym84fHEGDXAjLilih5GVPpcpSmFzTy8jx3LtaFg==
+
+"@react-native/babel-plugin-codegen@0.74.87":
+ version "0.74.87"
+ resolved "https://registry.yarnpkg.com/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.74.87.tgz#44457f4de69911f37a6ac308a7783203a757574a"
+ integrity sha512-+vJYpMnENFrwtgvDfUj+CtVJRJuUnzAUYT0/Pb68Sq9RfcZ5xdcCuUgyf7JO+akW2VTBoJY427wkcxU30qrWWw==
+ dependencies:
+ "@react-native/codegen" "0.74.87"
+
+"@react-native/babel-preset@0.74.87":
+ version "0.74.87"
+ resolved "https://registry.yarnpkg.com/@react-native/babel-preset/-/babel-preset-0.74.87.tgz#3d74517d2ea8898f83b5106027033607d5bda50d"
+ integrity sha512-hyKpfqzN2nxZmYYJ0tQIHG99FQO0OWXp/gVggAfEUgiT+yNKas1C60LuofUsK7cd+2o9jrpqgqW4WzEDZoBlTg==
+ dependencies:
+ "@babel/core" "^7.20.0"
+ "@babel/plugin-proposal-async-generator-functions" "^7.0.0"
+ "@babel/plugin-proposal-class-properties" "^7.18.0"
+ "@babel/plugin-proposal-export-default-from" "^7.0.0"
+ "@babel/plugin-proposal-logical-assignment-operators" "^7.18.0"
+ "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0"
+ "@babel/plugin-proposal-numeric-separator" "^7.0.0"
+ "@babel/plugin-proposal-object-rest-spread" "^7.20.0"
+ "@babel/plugin-proposal-optional-catch-binding" "^7.0.0"
+ "@babel/plugin-proposal-optional-chaining" "^7.20.0"
+ "@babel/plugin-syntax-dynamic-import" "^7.8.0"
+ "@babel/plugin-syntax-export-default-from" "^7.0.0"
+ "@babel/plugin-syntax-flow" "^7.18.0"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0"
+ "@babel/plugin-syntax-optional-chaining" "^7.0.0"
+ "@babel/plugin-transform-arrow-functions" "^7.0.0"
+ "@babel/plugin-transform-async-to-generator" "^7.20.0"
+ "@babel/plugin-transform-block-scoping" "^7.0.0"
+ "@babel/plugin-transform-classes" "^7.0.0"
+ "@babel/plugin-transform-computed-properties" "^7.0.0"
+ "@babel/plugin-transform-destructuring" "^7.20.0"
+ "@babel/plugin-transform-flow-strip-types" "^7.20.0"
+ "@babel/plugin-transform-function-name" "^7.0.0"
+ "@babel/plugin-transform-literals" "^7.0.0"
+ "@babel/plugin-transform-modules-commonjs" "^7.0.0"
+ "@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0"
+ "@babel/plugin-transform-parameters" "^7.0.0"
+ "@babel/plugin-transform-private-methods" "^7.22.5"
+ "@babel/plugin-transform-private-property-in-object" "^7.22.11"
+ "@babel/plugin-transform-react-display-name" "^7.0.0"
+ "@babel/plugin-transform-react-jsx" "^7.0.0"
+ "@babel/plugin-transform-react-jsx-self" "^7.0.0"
+ "@babel/plugin-transform-react-jsx-source" "^7.0.0"
+ "@babel/plugin-transform-runtime" "^7.0.0"
+ "@babel/plugin-transform-shorthand-properties" "^7.0.0"
+ "@babel/plugin-transform-spread" "^7.0.0"
+ "@babel/plugin-transform-sticky-regex" "^7.0.0"
+ "@babel/plugin-transform-typescript" "^7.5.0"
+ "@babel/plugin-transform-unicode-regex" "^7.0.0"
+ "@babel/template" "^7.0.0"
+ "@react-native/babel-plugin-codegen" "0.74.87"
+ babel-plugin-transform-flow-enums "^0.0.2"
+ react-refresh "^0.14.0"
+
+"@react-native/codegen@0.74.87":
+ version "0.74.87"
+ resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.74.87.tgz#47f07a627d0294c8270a03aee098991ed91f8ae9"
+ integrity sha512-GMSYDiD+86zLKgMMgz9z0k6FxmRn+z6cimYZKkucW4soGbxWsbjUAZoZ56sJwt2FJ3XVRgXCrnOCgXoH/Bkhcg==
+ dependencies:
+ "@babel/parser" "^7.20.0"
+ glob "^7.1.1"
+ hermes-parser "0.19.1"
+ invariant "^2.2.4"
+ jscodeshift "^0.14.0"
+ mkdirp "^0.5.1"
+ nullthrows "^1.1.1"
+
+"@react-native/community-cli-plugin@0.74.87":
+ version "0.74.87"
+ resolved "https://registry.yarnpkg.com/@react-native/community-cli-plugin/-/community-cli-plugin-0.74.87.tgz#4d9798d51381912f3771acded9b6b2804987e952"
+ integrity sha512-EgJG9lSr8x3X67dHQKQvU6EkO+3ksVlJHYIVv6U/AmW9dN80BEFxgYbSJ7icXS4wri7m4kHdgeq2PQ7/3vvrTQ==
+ dependencies:
+ "@react-native-community/cli-server-api" "13.6.9"
+ "@react-native-community/cli-tools" "13.6.9"
+ "@react-native/dev-middleware" "0.74.87"
+ "@react-native/metro-babel-transformer" "0.74.87"
+ chalk "^4.0.0"
+ execa "^5.1.1"
+ metro "^0.80.3"
+ metro-config "^0.80.3"
+ metro-core "^0.80.3"
+ node-fetch "^2.2.0"
+ querystring "^0.2.1"
+ readline "^1.3.0"
+
+"@react-native/debugger-frontend@0.74.85":
+ version "0.74.85"
+ resolved "https://registry.yarnpkg.com/@react-native/debugger-frontend/-/debugger-frontend-0.74.85.tgz#a7af94a7b81cb59f241fd1771d1b083445329700"
+ integrity sha512-gUIhhpsYLUTYWlWw4vGztyHaX/kNlgVspSvKe2XaPA7o3jYKUoNLc3Ov7u70u/MBWfKdcEffWq44eSe3j3s5JQ==
+
+"@react-native/debugger-frontend@0.74.87":
+ version "0.74.87"
+ resolved "https://registry.yarnpkg.com/@react-native/debugger-frontend/-/debugger-frontend-0.74.87.tgz#0bb4f4f54365d04fc975349d5f635cb575f6a5d8"
+ integrity sha512-MN95DJLYTv4EqJc+9JajA3AJZSBYJz2QEJ3uWlHrOky2vKrbbRVaW1ityTmaZa2OXIvNc6CZwSRSE7xCoHbXhQ==
+
+"@react-native/dev-middleware@0.74.85":
+ version "0.74.85"
+ resolved "https://registry.yarnpkg.com/@react-native/dev-middleware/-/dev-middleware-0.74.85.tgz#eca35aceb882b1111385f7c20f1aad7a33a2734e"
+ integrity sha512-BRmgCK5vnMmHaKRO+h8PKJmHHH3E6JFuerrcfE3wG2eZ1bcSr+QTu8DAlpxsDWvJvHpCi8tRJGauxd+Ssj/c7w==
+ dependencies:
+ "@isaacs/ttlcache" "^1.4.1"
+ "@react-native/debugger-frontend" "0.74.85"
+ "@rnx-kit/chromium-edge-launcher" "^1.0.0"
+ chrome-launcher "^0.15.2"
+ connect "^3.6.5"
+ debug "^2.2.0"
+ node-fetch "^2.2.0"
+ nullthrows "^1.1.1"
+ open "^7.0.3"
+ selfsigned "^2.4.1"
+ serve-static "^1.13.1"
+ temp-dir "^2.0.0"
+ ws "^6.2.2"
+
+"@react-native/dev-middleware@0.74.87":
+ version "0.74.87"
+ resolved "https://registry.yarnpkg.com/@react-native/dev-middleware/-/dev-middleware-0.74.87.tgz#254807b579a3015ced659a14c374dbf029a9c04e"
+ integrity sha512-7TmZ3hTHwooYgIHqc/z87BMe1ryrIqAUi+AF7vsD+EHCGxHFdMjSpf1BZ2SUPXuLnF2cTiTfV2RwhbPzx0tYIA==
+ dependencies:
+ "@isaacs/ttlcache" "^1.4.1"
+ "@react-native/debugger-frontend" "0.74.87"
+ "@rnx-kit/chromium-edge-launcher" "^1.0.0"
+ chrome-launcher "^0.15.2"
+ connect "^3.6.5"
+ debug "^2.2.0"
+ node-fetch "^2.2.0"
+ nullthrows "^1.1.1"
+ open "^7.0.3"
+ selfsigned "^2.4.1"
+ serve-static "^1.13.1"
+ temp-dir "^2.0.0"
+ ws "^6.2.2"
+
+"@react-native/gradle-plugin@0.74.87":
+ version "0.74.87"
+ resolved "https://registry.yarnpkg.com/@react-native/gradle-plugin/-/gradle-plugin-0.74.87.tgz#a66c01fda7a938a116dc27447f0ccce285796b2a"
+ integrity sha512-T+VX0N1qP+U9V4oAtn7FTX7pfsoVkd1ocyw9swYXgJqU2fK7hC9famW7b3s3ZiufPGPr1VPJe2TVGtSopBjL6A==
+
+"@react-native/js-polyfills@0.74.87":
+ version "0.74.87"
+ resolved "https://registry.yarnpkg.com/@react-native/js-polyfills/-/js-polyfills-0.74.87.tgz#d28090a4dae417a2e9ad14e065fcf8cf52cc482c"
+ integrity sha512-M5Evdn76CuVEF0GsaXiGi95CBZ4IWubHqwXxV9vG9CC9kq0PSkoM2Pn7Lx7dgyp4vT7ccJ8a3IwHbe+5KJRnpw==
+
+"@react-native/metro-babel-transformer@0.74.87":
+ version "0.74.87"
+ resolved "https://registry.yarnpkg.com/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.74.87.tgz#f60958f5e7eb39008a2c01dc5248ab60240bdc01"
+ integrity sha512-UsJCO24sNax2NSPBmV1zLEVVNkS88kcgAiYrZHtYSwSjpl4WZ656tIeedBfiySdJ94Hr3kQmBYLipV5zk0NI1A==
+ dependencies:
+ "@babel/core" "^7.20.0"
+ "@react-native/babel-preset" "0.74.87"
+ hermes-parser "0.19.1"
+ nullthrows "^1.1.1"
+
+"@react-native/normalize-colors@0.74.85":
+ version "0.74.85"
+ resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.74.85.tgz#62bcb9ab1b10b822ca0278fdfdf23d3b18e125da"
+ integrity sha512-pcE4i0X7y3hsAE0SpIl7t6dUc0B0NZLd1yv7ssm4FrLhWG+CGyIq4eFDXpmPU1XHmL5PPySxTAjEMiwv6tAmOw==
+
+"@react-native/normalize-colors@0.74.87":
+ version "0.74.87"
+ resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.74.87.tgz#a814169d0ce4ce13ffebcda0a3a5a3f780ccd772"
+ integrity sha512-Xh7Nyk/MPefkb0Itl5Z+3oOobeG9lfLb7ZOY2DKpFnoCE1TzBmib9vMNdFaLdSxLIP+Ec6icgKtdzYg8QUPYzA==
+
+"@react-native/normalize-colors@^0.74.1":
+ version "0.74.89"
+ resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.74.89.tgz#b8ac17d1bbccd3ef9a1f921665d04d42cff85976"
+ integrity sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg==
+
+"@react-native/virtualized-lists@0.74.87":
+ version "0.74.87"
+ resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.74.87.tgz#31bc44d62617df7d893df22c4c57094f576677a0"
+ integrity sha512-lsGxoFMb0lyK/MiplNKJpD+A1EoEUumkLrCjH4Ht+ZlG8S0BfCxmskLZ6qXn3BiDSkLjfjI/qyZ3pnxNBvkXpQ==
+ dependencies:
+ invariant "^2.2.4"
+ nullthrows "^1.1.1"
+
+"@react-navigation/bottom-tabs@^7.0.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-7.2.0.tgz#5b336b823226647a263b4fe743655462796b6aaf"
+ integrity sha512-1LxjgnbPyFINyf9Qr5d1YE0pYhuJayg5TCIIFQmbcX4PRhX7FKUXV7cX8OzrKXEdZi/UE/VNXugtozPAR9zgvA==
+ dependencies:
+ "@react-navigation/elements" "^2.2.5"
+ color "^4.2.3"
+
+"@react-navigation/bottom-tabs@~6.5.7":
+ version "6.5.20"
+ resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.20.tgz#5335e75b02c527ef0569bd97d4f9185d65616e49"
+ integrity sha512-ow6Z06iS4VqBO8d7FP+HsGjJLWt2xTWIvuWjpoCvsM/uQXzCRDIjBv9HaKcXbF0yTW7IMir0oDAbU5PFzEDdgA==
+ dependencies:
+ "@react-navigation/elements" "^1.3.30"
+ color "^4.2.3"
+ warn-once "^0.1.0"
+
+"@react-navigation/core@^6.4.17":
+ version "6.4.17"
+ resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.4.17.tgz#f277a196b578c8a456efcc563d1c9bd87eb4ab04"
+ integrity sha512-Nd76EpomzChWAosGqWOYE3ItayhDzIEzzZsT7PfGcRFDgW5miHV2t4MZcq9YIK4tzxZjVVpYbIynOOQQd1e0Cg==
+ dependencies:
+ "@react-navigation/routers" "^6.1.9"
+ escape-string-regexp "^4.0.0"
+ nanoid "^3.1.23"
+ query-string "^7.1.3"
+ react-is "^16.13.0"
+ use-latest-callback "^0.2.1"
+
+"@react-navigation/elements@^1.3.30":
+ version "1.3.31"
+ resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.31.tgz#28dd802a0787bb03fc0e5be296daf1804dbebbcf"
+ integrity sha512-bUzP4Awlljx5RKEExw8WYtif8EuQni2glDaieYROKTnaxsu9kEIA515sXQgUDZU4Ob12VoL7+z70uO3qrlfXcQ==
+
+"@react-navigation/elements@^2.2.5":
+ version "2.2.5"
+ resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-2.2.5.tgz#0e2ca76e2003e96b417a3d7c2829bf1afd69193f"
+ integrity sha512-sDhE+W14P7MNWLMxXg1MEVXwkLUpMZJGflE6nQNzLmolJQIHgcia0Mrm8uRa3bQovhxYu1UzEojLZ+caoZt7Fg==
+ dependencies:
+ color "^4.2.3"
+
+"@react-navigation/material-top-tabs@^6.6.14":
+ version "6.6.14"
+ resolved "https://registry.yarnpkg.com/@react-navigation/material-top-tabs/-/material-top-tabs-6.6.14.tgz#48877ba5e1038d089439fede39ac5aab99c13c28"
+ integrity sha512-kfNQt3BInQusEc8A+PDWaKmRQNaCrSqngcOQwUe1uNizJdZJEFdfaInivtBFW2LcQqtzgIHK/am2TgK0Pos6og==
+ dependencies:
+ color "^4.2.3"
+ warn-once "^0.1.0"
+
+"@react-navigation/native-stack@~6.9.12":
+ version "6.9.26"
+ resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.26.tgz#90facf7783c9927f094bc9f01c613af75b6c241e"
+ integrity sha512-++dueQ+FDj2XkZ902DVrK79ub1vp19nSdAZWxKRgd6+Bc0Niiesua6rMCqymYOVaYh+dagwkA9r00bpt/U5WLw==
+ dependencies:
+ "@react-navigation/elements" "^1.3.30"
+ warn-once "^0.1.0"
+
+"@react-navigation/native@^6.1.18", "@react-navigation/native@~6.1.6":
+ version "6.1.18"
+ resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.18.tgz#338fa9afa2c89feec1d3eac41c963840d8d6f106"
+ integrity sha512-mIT9MiL/vMm4eirLcmw2h6h/Nm5FICtnYSdohq4vTLA2FF/6PNhByM7s8ffqoVfE5L0uAa6Xda1B7oddolUiGg==
+ dependencies:
+ "@react-navigation/core" "^6.4.17"
+ escape-string-regexp "^4.0.0"
+ fast-deep-equal "^3.1.3"
+ nanoid "^3.1.23"
+
+"@react-navigation/routers@^6.1.9":
+ version "6.1.9"
+ resolved "https://registry.yarnpkg.com/@react-navigation/routers/-/routers-6.1.9.tgz#73f5481a15a38e36592a0afa13c3c064b9f90bed"
+ integrity sha512-lTM8gSFHSfkJvQkxacGM6VJtBt61ip2XO54aNfswD+KMw6eeZ4oehl7m0me3CR9hnDE4+60iAZR8sAhvCiI3NA==
+ dependencies:
+ nanoid "^3.1.23"
+
+"@remix-run/node@^2.7.2":
+ version "2.15.3"
+ resolved "https://registry.yarnpkg.com/@remix-run/node/-/node-2.15.3.tgz#c400b21ef50e94b0ae3b4631b0110f3c9094eae9"
+ integrity sha512-TYfS6BPhbABBpSRZ6WBA4qIWSwWvJhRVQGXCHUtgOwkuW863rcFmjh9g2Xj/IHyTmbOYPdcjHsIgZ9el4CHOKQ==
+ dependencies:
+ "@remix-run/server-runtime" "2.15.3"
+ "@remix-run/web-fetch" "^4.4.2"
+ "@web3-storage/multipart-parser" "^1.0.0"
+ cookie-signature "^1.1.0"
+ source-map-support "^0.5.21"
+ stream-slice "^0.1.2"
+ undici "^6.11.1"
+
+"@remix-run/router@1.22.0":
+ version "1.22.0"
+ resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.22.0.tgz#dd8096cb055c475a4de6b35322b8d3b118c17b43"
+ integrity sha512-MBOl8MeOzpK0HQQQshKB7pABXbmyHizdTpqnrIseTbsv0nAepwC2ENZa1aaBExNQcpLoXmWthhak8SABLzvGPw==
+
+"@remix-run/server-runtime@2.15.3":
+ version "2.15.3"
+ resolved "https://registry.yarnpkg.com/@remix-run/server-runtime/-/server-runtime-2.15.3.tgz#a5031a6c406423adec94f1a49952137df5b00a2d"
+ integrity sha512-taHBe1DEqxZNjjj6OfkSYbup+sZPjbTgUhykaI+nHqrC2NDQuTiisBXhLwtx60GctONR/x0lWhF7R9ZGC5WsHw==
+ dependencies:
+ "@remix-run/router" "1.22.0"
+ "@types/cookie" "^0.6.0"
+ "@web3-storage/multipart-parser" "^1.0.0"
+ cookie "^0.6.0"
+ set-cookie-parser "^2.4.8"
+ source-map "^0.7.3"
+ turbo-stream "2.4.0"
+
+"@remix-run/web-blob@^3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@remix-run/web-blob/-/web-blob-3.1.0.tgz#e0c669934c1eb6028960047e57a13ed38bbfb434"
+ integrity sha512-owGzFLbqPH9PlKb8KvpNJ0NO74HWE2euAn61eEiyCXX/oteoVzTVSN8mpLgDjaxBf2btj5/nUllSUgpyd6IH6g==
+ dependencies:
+ "@remix-run/web-stream" "^1.1.0"
+ web-encoding "1.1.5"
+
+"@remix-run/web-fetch@^4.4.2":
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/@remix-run/web-fetch/-/web-fetch-4.4.2.tgz#ce7aedef72cc26e15060e8cf84674029f92809b6"
+ integrity sha512-jgKfzA713/4kAW/oZ4bC3MoLWyjModOVDjFPNseVqcJKSafgIscrYL9G50SurEYLswPuoU3HzSbO0jQCMYWHhA==
+ dependencies:
+ "@remix-run/web-blob" "^3.1.0"
+ "@remix-run/web-file" "^3.1.0"
+ "@remix-run/web-form-data" "^3.1.0"
+ "@remix-run/web-stream" "^1.1.0"
+ "@web3-storage/multipart-parser" "^1.0.0"
+ abort-controller "^3.0.0"
+ data-uri-to-buffer "^3.0.1"
+ mrmime "^1.0.0"
+
+"@remix-run/web-file@^3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@remix-run/web-file/-/web-file-3.1.0.tgz#07219021a2910e90231bc30ca1ce693d0e9d3825"
+ integrity sha512-dW2MNGwoiEYhlspOAXFBasmLeYshyAyhIdrlXBi06Duex5tDr3ut2LFKVj7tyHLmn8nnNwFf1BjNbkQpygC2aQ==
+ dependencies:
+ "@remix-run/web-blob" "^3.1.0"
+
+"@remix-run/web-form-data@^3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@remix-run/web-form-data/-/web-form-data-3.1.0.tgz#47f9ad8ce8bf1c39ed83eab31e53967fe8e3df6a"
+ integrity sha512-NdeohLMdrb+pHxMQ/Geuzdp0eqPbea+Ieo8M8Jx2lGC6TBHsgHzYcBvr0LyPdPVycNRDEpWpiDdCOdCryo3f9A==
+ dependencies:
+ web-encoding "1.1.5"
+
+"@remix-run/web-stream@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@remix-run/web-stream/-/web-stream-1.1.0.tgz#b93a8f806c2c22204930837c44d81fdedfde079f"
+ integrity sha512-KRJtwrjRV5Bb+pM7zxcTJkhIqWWSy+MYsIxHK+0m5atcznsf15YwUBWHWulZerV2+vvHH1Lp1DD7pw6qKW8SgA==
+ dependencies:
+ web-streams-polyfill "^3.1.1"
+
+"@rnx-kit/chromium-edge-launcher@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@rnx-kit/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz#c0df8ea00a902c7a417cd9655aab06de398b939c"
+ integrity sha512-lzD84av1ZQhYUS+jsGqJiCMaJO2dn9u+RTT9n9q6D3SaKVwWqv+7AoRKqBu19bkwyE+iFRl1ymr40QS90jVFYg==
+ dependencies:
+ "@types/node" "^18.0.0"
+ escape-string-regexp "^4.0.0"
+ is-wsl "^2.2.0"
+ lighthouse-logger "^1.0.0"
+ mkdirp "^1.0.4"
+ rimraf "^3.0.2"
+
+"@segment/loosely-validate-event@^2.0.0":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz#87dfc979e5b4e7b82c5f1d8b722dfd5d77644681"
+ integrity sha512-ZMCSfztDBqwotkl848ODgVcAmN4OItEWDCkshcKz0/W6gGSQayuuCtWV/MlodFivAZD793d6UgANd6wCXUfrIw==
+ dependencies:
+ component-type "^1.2.1"
+ join-component "^1.1.0"
+
+"@shopify/flash-list@1.6.4":
+ version "1.6.4"
+ resolved "https://registry.yarnpkg.com/@shopify/flash-list/-/flash-list-1.6.4.tgz#2844ae7334f314c06c62b649bc9c5de2480800b4"
+ integrity sha512-M2momcnY7swsvmpHIFDVbdOaFw4aQocJXA/lFP0Gpz+alQjFylqVKvszxl4atYO2SNbjxlb2L6hEP9WEcAknGQ==
+ dependencies:
+ recyclerlistview "4.2.0"
+ tslib "2.4.0"
+
+"@sideway/address@^4.1.5":
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5"
+ integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==
+ dependencies:
+ "@hapi/hoek" "^9.0.0"
+
+"@sideway/formula@^3.0.1":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
+ integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==
+
+"@sideway/pinpoint@^2.0.0":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
+ integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
+
+"@sinclair/typebox@^0.27.8":
+ version "0.27.8"
+ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e"
+ integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==
+
+"@sinonjs/commons@^3.0.0":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd"
+ integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==
+ dependencies:
+ type-detect "4.0.8"
+
+"@sinonjs/fake-timers@^10.0.2":
+ version "10.3.0"
+ resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66"
+ integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==
+ dependencies:
+ "@sinonjs/commons" "^3.0.0"
+
+"@tanstack/query-core@5.66.0":
+ version "5.66.0"
+ resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.66.0.tgz#163f670b3b4e3b3cdbff6698ad44b2edfcaed185"
+ integrity sha512-J+JeBtthiKxrpzUu7rfIPDzhscXF2p5zE/hVdrqkACBP8Yu0M96mwJ5m/8cPPYQE9aRNvXztXHlNwIh4FEeMZw==
+
+"@tanstack/react-query@^5.59.20":
+ version "5.66.0"
+ resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.66.0.tgz#9f7aa1b3e844ea6a0ad2ee61fccaed76e614b865"
+ integrity sha512-z3sYixFQJe8hndFnXgWu7C79ctL+pI0KAelYyW+khaNJ1m22lWrhJU2QrsTcRKMuVPtoZvfBYrTStIdKo+x0Xw==
+ dependencies:
+ "@tanstack/query-core" "5.66.0"
+
+"@tokenizer/token@^0.3.0":
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276"
+ integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==
+
+"@types/cookie@^0.6.0":
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5"
+ integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==
+
+"@types/hammerjs@^2.0.36":
+ version "2.0.46"
+ resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.46.tgz#381daaca1360ff8a7c8dff63f32e69745b9fb1e1"
+ integrity sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==
+
+"@types/hoist-non-react-statics@^3.3.1":
+ version "3.3.6"
+ resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz#6bba74383cdab98e8db4e20ce5b4a6b98caed010"
+ integrity sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==
+ dependencies:
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+
+"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7"
+ integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==
+
+"@types/istanbul-lib-report@*":
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf"
+ integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==
+ dependencies:
+ "@types/istanbul-lib-coverage" "*"
+
+"@types/istanbul-reports@^1.1.1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz#e875cc689e47bce549ec81f3df5e6f6f11cfaeb2"
+ integrity sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==
+ dependencies:
+ "@types/istanbul-lib-coverage" "*"
+ "@types/istanbul-lib-report" "*"
+
+"@types/istanbul-reports@^3.0.0":
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54"
+ integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==
+ dependencies:
+ "@types/istanbul-lib-report" "*"
+
+"@types/jest@^29.5.14":
+ version "29.5.14"
+ resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.14.tgz#2b910912fa1d6856cadcd0c1f95af7df1d6049e5"
+ integrity sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==
+ dependencies:
+ expect "^29.0.0"
+ pretty-format "^29.0.0"
+
+"@types/json-schema@^7.0.9":
+ version "7.0.15"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
+ integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
+
+"@types/lodash@^4.14.53", "@types/lodash@^4.17.13":
+ version "4.17.15"
+ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.15.tgz#12d4af0ed17cc7600ce1f9980cec48fc17ad1e89"
+ integrity sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==
+
+"@types/node-forge@^1.3.0":
+ version "1.3.11"
+ resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da"
+ integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==
+ dependencies:
+ "@types/node" "*"
+
+"@types/node@*":
+ version "22.13.0"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.0.tgz#d376dd9a0ee2f9382d86c2d5d7beb4d198b4ea8c"
+ integrity sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==
+ dependencies:
+ undici-types "~6.20.0"
+
+"@types/node@16.9.1":
+ version "16.9.1"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.1.tgz#0611b37db4246c937feef529ddcc018cf8e35708"
+ integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==
+
+"@types/node@^10.11.7":
+ version "10.17.60"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b"
+ integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==
+
+"@types/node@^18.0.0":
+ version "18.19.74"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.74.tgz#4d093acd2a558ebbc5f0efa4e20ce63791b0cc58"
+ integrity sha512-HMwEkkifei3L605gFdV+/UwtpxP6JSzM+xFk2Ia6DNFSwSVBRh9qp5Tgf4lNFOMfPVuU0WnkcWpXZpgn5ufO4A==
+ dependencies:
+ undici-types "~5.26.4"
+
+"@types/prop-types@*":
+ version "15.7.14"
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.14.tgz#1433419d73b2a7ebfc6918dcefd2ec0d5cd698f2"
+ integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==
+
+"@types/react-native-vector-icons@^6.4.18":
+ version "6.4.18"
+ resolved "https://registry.yarnpkg.com/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.18.tgz#18671c617b9d0958747bc959903470dde91a8c79"
+ integrity sha512-YGlNWb+k5laTBHd7+uZowB9DpIK3SXUneZqAiKQaj1jnJCZM0x71GDim5JCTMi4IFkhc9m8H/Gm28T5BjyivUw==
+ dependencies:
+ "@types/react" "*"
+ "@types/react-native" "^0.70"
+
+"@types/react-native@^0.70":
+ version "0.70.19"
+ resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.70.19.tgz#b4e651dcf7f49c69ff3a4c3072584cad93155582"
+ integrity sha512-c6WbyCgWTBgKKMESj/8b4w+zWcZSsCforson7UdXtXMecG3MxCinYi6ihhrHVPyUrVzORsvEzK8zg32z4pK6Sg==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react-test-renderer@^18.0.7":
+ version "18.3.1"
+ resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-18.3.1.tgz#225bfe8d4ad7ee3b04c2fa27642bb74274a5961d"
+ integrity sha512-vAhnk0tG2eGa37lkU9+s5SoroCsRI08xnsWFiAXOuPH2jqzMbcXvKExXViPi1P5fIklDeCvXqyrdmipFaSkZrA==
+ dependencies:
+ "@types/react" "^18"
+
+"@types/react@*":
+ version "19.0.8"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-19.0.8.tgz#7098e6159f2a61e4f4cef2c1223c044a9bec590e"
+ integrity sha512-9P/o1IGdfmQxrujGbIMDyYaaCykhLKc0NGCtYcECNUr9UAaDe4gwvV9bR6tvd5Br1SG0j+PBpbKr2UYY8CwqSw==
+ dependencies:
+ csstype "^3.0.2"
+
+"@types/react@^18":
+ version "18.3.18"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.18.tgz#9b382c4cd32e13e463f97df07c2ee3bbcd26904b"
+ integrity sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==
+ dependencies:
+ "@types/prop-types" "*"
+ csstype "^3.0.2"
+
+"@types/react@~18.2.79":
+ version "18.2.79"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.79.tgz#c40efb4f255711f554d47b449f796d1c7756d865"
+ integrity sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==
+ dependencies:
+ "@types/prop-types" "*"
+ csstype "^3.0.2"
+
+"@types/stack-utils@^2.0.0":
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8"
+ integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==
+
+"@types/uuid@^10.0.0":
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-10.0.0.tgz#e9c07fe50da0f53dc24970cca94d619ff03f6f6d"
+ integrity sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==
+
+"@types/yargs-parser@*":
+ version "21.0.3"
+ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15"
+ integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==
+
+"@types/yargs@^13.0.0":
+ version "13.0.12"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.12.tgz#d895a88c703b78af0465a9de88aa92c61430b092"
+ integrity sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==
+ dependencies:
+ "@types/yargs-parser" "*"
+
+"@types/yargs@^15.0.0":
+ version "15.0.19"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.19.tgz#328fb89e46109ecbdb70c295d96ff2f46dfd01b9"
+ integrity sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==
+ dependencies:
+ "@types/yargs-parser" "*"
+
+"@types/yargs@^17.0.8":
+ version "17.0.33"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.33.tgz#8c32303da83eec050a84b3c7ae7b9f922d13e32d"
+ integrity sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==
+ dependencies:
+ "@types/yargs-parser" "*"
+
+"@urql/core@2.3.6":
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/@urql/core/-/core-2.3.6.tgz#ee0a6f8fde02251e9560c5f17dce5cd90f948552"
+ integrity sha512-PUxhtBh7/8167HJK6WqBv6Z0piuiaZHQGYbhwpNL9aIQmLROPEdaUYkY4wh45wPQXcTpnd11l0q3Pw+TI11pdw==
+ dependencies:
+ "@graphql-typed-document-node/core" "^3.1.0"
+ wonka "^4.0.14"
+
+"@urql/core@>=2.3.1":
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/@urql/core/-/core-5.1.0.tgz#7f4b81f1aba1ca34ae6354763abeb87ff9af84ff"
+ integrity sha512-yC3sw8yqjbX45GbXxfiBY8GLYCiyW/hLBbQF9l3TJrv4ro00Y0ChkKaD9I2KntRxAVm9IYBqh0awX8fwWAe/Yw==
+ dependencies:
+ "@0no-co/graphql.web" "^1.0.5"
+ wonka "^6.3.2"
+
+"@urql/exchange-retry@0.3.0":
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/@urql/exchange-retry/-/exchange-retry-0.3.0.tgz#13252108b5a111aab45f9982f4db18d1a286e423"
+ integrity sha512-hHqer2mcdVC0eYnVNbWyi28AlGOPb2vjH3lP3/Bc8Lc8BjhMsDwFMm7WhoP5C1+cfbr/QJ6Er3H/L08wznXxfg==
+ dependencies:
+ "@urql/core" ">=2.3.1"
+ wonka "^4.0.14"
+
+"@web3-storage/multipart-parser@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@web3-storage/multipart-parser/-/multipart-parser-1.0.0.tgz#6b69dc2a32a5b207ba43e556c25cc136a56659c4"
+ integrity sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==
+
+"@xmldom/xmldom@^0.8.8":
+ version "0.8.10"
+ resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99"
+ integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==
+
+"@xmldom/xmldom@~0.7.7":
+ version "0.7.13"
+ resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.13.tgz#ff34942667a4e19a9f4a0996a76814daac364cf3"
+ integrity sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==
+
+"@yarnpkg/lockfile@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31"
+ integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==
+
+"@zxing/text-encoding@0.9.0":
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz#fb50ffabc6c7c66a0c96b4c03e3d9be74864b70b"
+ integrity sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==
+
+abort-controller@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
+ integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
+ dependencies:
+ event-target-shim "^5.0.0"
+
+accepts@^1.3.7, accepts@^1.3.8, accepts@~1.3.7:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
+ integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
+ dependencies:
+ mime-types "~2.1.34"
+ negotiator "0.6.3"
+
+acorn@^8.8.2:
+ version "8.14.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0"
+ integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==
+
+add@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/add/-/add-2.0.6.tgz#248f0a9f6e5a528ef2295dbeec30532130ae2235"
+ integrity sha512-j5QzrmsokwWWp6kUcJQySpbG+xfOBqqKnup3OIk1pz+kB/80SLorZ9V8zHFLO92Lcd+hbvq8bT+zOGoPkmBV0Q==
+
+agent-base@6:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
+ integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
+ dependencies:
+ debug "4"
+
+aggregate-error@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
+ integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==
+ dependencies:
+ clean-stack "^2.0.0"
+ indent-string "^4.0.0"
+
+ajv-formats@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
+ integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==
+ dependencies:
+ ajv "^8.0.0"
+
+ajv-keywords@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16"
+ integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==
+ dependencies:
+ fast-deep-equal "^3.1.3"
+
+ajv@8.11.0:
+ version "8.11.0"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f"
+ integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ json-schema-traverse "^1.0.0"
+ require-from-string "^2.0.2"
+ uri-js "^4.2.2"
+
+ajv@^8.0.0, ajv@^8.11.0, ajv@^8.9.0:
+ version "8.17.1"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6"
+ integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==
+ dependencies:
+ fast-deep-equal "^3.1.3"
+ fast-uri "^3.0.1"
+ json-schema-traverse "^1.0.0"
+ require-from-string "^2.0.2"
+
+anser@^1.4.9:
+ version "1.4.10"
+ resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.10.tgz#befa3eddf282684bd03b63dcda3927aef8c2e35b"
+ integrity sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==
+
+ansi-escapes@^4.2.1, ansi-escapes@^4.3.2:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
+ integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
+ dependencies:
+ type-fest "^0.21.3"
+
+ansi-fragments@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-fragments/-/ansi-fragments-0.2.1.tgz#24409c56c4cc37817c3d7caa99d8969e2de5a05e"
+ integrity sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==
+ dependencies:
+ colorette "^1.0.7"
+ slice-ansi "^2.0.0"
+ strip-ansi "^5.0.0"
+
+ansi-regex@^4.0.0, ansi-regex@^4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed"
+ integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==
+
+ansi-regex@^5.0.0, ansi-regex@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
+ integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+
+ansi-regex@^6.0.1:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654"
+ integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==
+
+ansi-styles@^3.2.0, ansi-styles@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+ dependencies:
+ color-convert "^1.9.0"
+
+ansi-styles@^4.0.0, ansi-styles@^4.1.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+ dependencies:
+ color-convert "^2.0.1"
+
+ansi-styles@^5.0.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
+ integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
+
+ansi-styles@^6.1.0:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
+ integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
+
+any-base@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/any-base/-/any-base-1.1.0.tgz#ae101a62bc08a597b4c9ab5b7089d456630549fe"
+ integrity sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==
+
+any-promise@^1.0.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
+ integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==
+
+anymatch@^3.0.3, anymatch@~3.1.2:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+ integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+appdirsjs@^1.2.4:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/appdirsjs/-/appdirsjs-1.2.7.tgz#50b4b7948a26ba6090d4aede2ae2dc2b051be3b3"
+ integrity sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==
+
+application-config-path@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/application-config-path/-/application-config-path-0.1.1.tgz#8b5ac64ff6afdd9bd70ce69f6f64b6998f5f756e"
+ integrity sha512-zy9cHePtMP0YhwG+CfHm0bgwdnga2X3gZexpdCwEj//dpb+TKajtiC8REEUJUSq6Ab4f9cgNy2l8ObXzCXFkEw==
+
+arg@4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.0.tgz#583c518199419e0037abb74062c37f8519e575f0"
+ integrity sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==
+
+arg@5.0.2, arg@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
+ integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
+
+argparse@^1.0.7:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+ integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
+ dependencies:
+ sprintf-js "~1.0.2"
+
+argparse@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
+ integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+
+aria-hidden@^1.2.4:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522"
+ integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==
+ dependencies:
+ tslib "^2.0.0"
+
+array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz#384d12a37295aec3769ab022ad323a18a51ccf8b"
+ integrity sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==
+ dependencies:
+ call-bound "^1.0.3"
+ is-array-buffer "^3.0.5"
+
+array-union@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
+arraybuffer.prototype.slice@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c"
+ integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==
+ dependencies:
+ array-buffer-byte-length "^1.0.1"
+ call-bind "^1.0.8"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.5"
+ es-errors "^1.3.0"
+ get-intrinsic "^1.2.6"
+ is-array-buffer "^3.0.4"
+
+asap@~2.0.3, asap@~2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
+ integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==
+
+assert@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd"
+ integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==
+ dependencies:
+ call-bind "^1.0.2"
+ is-nan "^1.3.2"
+ object-is "^1.1.5"
+ object.assign "^4.1.4"
+ util "^0.12.5"
+
+ast-types@0.15.2:
+ version "0.15.2"
+ resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.15.2.tgz#39ae4809393c4b16df751ee563411423e85fb49d"
+ integrity sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==
+ dependencies:
+ tslib "^2.0.1"
+
+astral-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
+ integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
+
+async-function@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b"
+ integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==
+
+async-limiter@~1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
+ integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
+at-least-node@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
+ integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
+
+available-typed-arrays@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846"
+ integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==
+ dependencies:
+ possible-typed-array-names "^1.0.0"
+
+axios@^1.7.7:
+ version "1.7.9"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a"
+ integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==
+ dependencies:
+ follow-redirects "^1.15.6"
+ form-data "^4.0.0"
+ proxy-from-env "^1.1.0"
+
+babel-core@^7.0.0-bridge.0:
+ version "7.0.0-bridge.0"
+ resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece"
+ integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==
+
+babel-plugin-polyfill-corejs2@^0.4.10:
+ version "0.4.12"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz#ca55bbec8ab0edeeef3d7b8ffd75322e210879a9"
+ integrity sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==
+ dependencies:
+ "@babel/compat-data" "^7.22.6"
+ "@babel/helper-define-polyfill-provider" "^0.6.3"
+ semver "^6.3.1"
+
+babel-plugin-polyfill-corejs3@^0.10.6:
+ version "0.10.6"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz#2deda57caef50f59c525aeb4964d3b2f867710c7"
+ integrity sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==
+ dependencies:
+ "@babel/helper-define-polyfill-provider" "^0.6.2"
+ core-js-compat "^3.38.0"
+
+babel-plugin-polyfill-regenerator@^0.6.1:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz#abeb1f3f1c762eace37587f42548b08b57789bc8"
+ integrity sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==
+ dependencies:
+ "@babel/helper-define-polyfill-provider" "^0.6.3"
+
+babel-plugin-react-compiler@0.0.0-experimental-592953e-20240517:
+ version "0.0.0-experimental-592953e-20240517"
+ resolved "https://registry.yarnpkg.com/babel-plugin-react-compiler/-/babel-plugin-react-compiler-0.0.0-experimental-592953e-20240517.tgz#e800fa1550d03573cd5637218dc711f12f642249"
+ integrity sha512-OjG1SVaeQZaJrqkMFJatg8W/MTow8Ak5rx2SI0ETQBO1XvOk/XZGMbltNCPdFJLKghBYoBjC+Y3Ap/Xr7B01mA==
+ dependencies:
+ "@babel/generator" "7.2.0"
+ "@babel/types" "^7.19.0"
+ chalk "4"
+ invariant "^2.2.4"
+ pretty-format "^24"
+ zod "^3.22.4"
+ zod-validation-error "^2.1.0"
+
+babel-plugin-react-native-web@~0.19.10:
+ version "0.19.13"
+ resolved "https://registry.yarnpkg.com/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.19.13.tgz#bf919bd6f18c4689dd1a528a82bda507363b953d"
+ integrity sha512-4hHoto6xaN23LCyZgL9LJZc3olmAxd7b6jDzlZnKXAh4rRAbZRKNBJoOOdp46OBqgy+K0t0guTj5/mhA8inymQ==
+
+babel-plugin-transform-flow-enums@^0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz#d1d0cc9bdc799c850ca110d0ddc9f21b9ec3ef25"
+ integrity sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==
+ dependencies:
+ "@babel/plugin-syntax-flow" "^7.12.1"
+
+babel-preset-expo@~11.0.15:
+ version "11.0.15"
+ resolved "https://registry.yarnpkg.com/babel-preset-expo/-/babel-preset-expo-11.0.15.tgz#f29b1ac1f59f8739f63c80515906186586c24d3c"
+ integrity sha512-rgiMTYwqIPULaO7iZdqyL7aAff9QLOX6OWUtLZBlOrOTreGY1yHah/5+l8MvI6NVc/8Zj5LY4Y5uMSnJIuzTLw==
+ dependencies:
+ "@babel/plugin-proposal-decorators" "^7.12.9"
+ "@babel/plugin-transform-export-namespace-from" "^7.22.11"
+ "@babel/plugin-transform-object-rest-spread" "^7.12.13"
+ "@babel/plugin-transform-parameters" "^7.22.15"
+ "@babel/preset-react" "^7.22.15"
+ "@babel/preset-typescript" "^7.23.0"
+ "@react-native/babel-preset" "0.74.87"
+ babel-plugin-react-compiler "0.0.0-experimental-592953e-20240517"
+ babel-plugin-react-native-web "~0.19.10"
+ react-refresh "^0.14.2"
+
+badgin@^1.1.5:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/badgin/-/badgin-1.2.3.tgz#994b5f519827d7d5422224825b2c8faea2bc43ad"
+ integrity sha512-NQGA7LcfCpSzIbGRbkgjgdWkjy7HI+Th5VLxTJfW5EeaAf3fnS+xWQaQOCYiny+q6QSvxqoSO04vCx+4u++EJw==
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+base64-js@^1.2.3, base64-js@^1.3.0, base64-js@^1.3.1, base64-js@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
+ integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
+
+better-opn@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/better-opn/-/better-opn-3.0.2.tgz#f96f35deaaf8f34144a4102651babcf00d1d8817"
+ integrity sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==
+ dependencies:
+ open "^8.0.4"
+
+big-integer@1.6.x:
+ version "1.6.52"
+ resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85"
+ integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==
+
+binary-extensions@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"
+ integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
+
+bl@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
+ integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
+ dependencies:
+ buffer "^5.5.0"
+ inherits "^2.0.4"
+ readable-stream "^3.4.0"
+
+bmp-js@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.1.0.tgz#e05a63f796a6c1ff25f4771ec7adadc148c07233"
+ integrity sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==
+
+boolbase@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+ integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
+
+bplist-creator@0.0.7:
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/bplist-creator/-/bplist-creator-0.0.7.tgz#37df1536092824b87c42f957b01344117372ae45"
+ integrity sha512-xp/tcaV3T5PCiaY04mXga7o/TE+t95gqeLmADeBI1CvZtdWTbgBt3uLpvh4UWtenKeBhCV6oVxGk38yZr2uYEA==
+ dependencies:
+ stream-buffers "~2.2.0"
+
+bplist-creator@0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/bplist-creator/-/bplist-creator-0.1.0.tgz#018a2d1b587f769e379ef5519103730f8963ba1e"
+ integrity sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==
+ dependencies:
+ stream-buffers "2.2.x"
+
+bplist-parser@0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.1.tgz#e1c90b2ca2a9f9474cc72f6862bbf3fee8341fd1"
+ integrity sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==
+ dependencies:
+ big-integer "1.6.x"
+
+bplist-parser@^0.3.1:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.2.tgz#3ac79d67ec52c4c107893e0237eb787cbacbced7"
+ integrity sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==
+ dependencies:
+ big-integer "1.6.x"
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+brace-expansion@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
+ integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
+ dependencies:
+ balanced-match "^1.0.0"
+
+braces@^3.0.3, braces@~3.0.2:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
+ integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
+ dependencies:
+ fill-range "^7.1.1"
+
+browserslist@^4.24.0, browserslist@^4.24.3:
+ version "4.24.4"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b"
+ integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==
+ dependencies:
+ caniuse-lite "^1.0.30001688"
+ electron-to-chromium "^1.5.73"
+ node-releases "^2.0.19"
+ update-browserslist-db "^1.1.1"
+
+bser@2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
+ integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==
+ dependencies:
+ node-int64 "^0.4.0"
+
+buffer-alloc-unsafe@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
+ integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
+
+buffer-alloc@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
+ integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
+ dependencies:
+ buffer-alloc-unsafe "^1.1.0"
+ buffer-fill "^1.0.0"
+
+buffer-equal@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b"
+ integrity sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==
+
+buffer-fill@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
+ integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==
+
+buffer-from@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
+ integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
+
+buffer@^5.2.0, buffer@^5.4.3, buffer@^5.5.0, buffer@^5.6.0:
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
+ integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
+ dependencies:
+ base64-js "^1.3.1"
+ ieee754 "^1.1.13"
+
+builtins@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88"
+ integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==
+
+bytes@3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
+ integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
+
+cacache@^18.0.2:
+ version "18.0.4"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.4.tgz#4601d7578dadb59c66044e157d02a3314682d6a5"
+ integrity sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==
+ dependencies:
+ "@npmcli/fs" "^3.1.0"
+ fs-minipass "^3.0.0"
+ glob "^10.2.2"
+ lru-cache "^10.0.1"
+ minipass "^7.0.3"
+ minipass-collect "^2.0.1"
+ minipass-flush "^1.0.5"
+ minipass-pipeline "^1.2.4"
+ p-map "^4.0.0"
+ ssri "^10.0.0"
+ tar "^6.1.11"
+ unique-filename "^3.0.0"
+
+call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz#32e5892e6361b29b0b545ba6f7763378daca2840"
+ integrity sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==
+ dependencies:
+ es-errors "^1.3.0"
+ function-bind "^1.1.2"
+
+call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.7, call-bind@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c"
+ integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==
+ dependencies:
+ call-bind-apply-helpers "^1.0.0"
+ es-define-property "^1.0.0"
+ get-intrinsic "^1.2.4"
+ set-function-length "^1.2.2"
+
+call-bound@^1.0.2, call-bound@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.3.tgz#41cfd032b593e39176a71533ab4f384aa04fd681"
+ integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==
+ dependencies:
+ call-bind-apply-helpers "^1.0.1"
+ get-intrinsic "^1.2.6"
+
+caller-callsite@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134"
+ integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==
+ dependencies:
+ callsites "^2.0.0"
+
+caller-path@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4"
+ integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==
+ dependencies:
+ caller-callsite "^2.0.0"
+
+callsites@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
+ integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==
+
+camelcase-css@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
+ integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
+
+camelcase@^5.0.0:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+ integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
+camelcase@^6.2.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
+ integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
+
+camelize@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3"
+ integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==
+
+caniuse-lite@^1.0.30001688:
+ version "1.0.30001696"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001696.tgz#00c30a2fc11e3c98c25e5125418752af3ae2f49f"
+ integrity sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==
+
+centra@^2.7.0:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/centra/-/centra-2.7.0.tgz#4c8312a58436e8a718302011561db7e6a2b0ec18"
+ integrity sha512-PbFMgMSrmgx6uxCdm57RUos9Tc3fclMvhLSATYN39XsDV29B89zZ3KA89jmY0vwSGazyU+uerqwa6t+KaodPcg==
+ dependencies:
+ follow-redirects "^1.15.6"
+
+chalk@4, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+chalk@^2.0.1, chalk@^2.4.2:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
+charenc@0.0.2, charenc@~0.0.1:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
+ integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==
+
+chokidar@^3.5.3:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
+ integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
+ dependencies:
+ anymatch "~3.1.2"
+ braces "~3.0.2"
+ glob-parent "~5.1.2"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.6.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+chownr@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
+ integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
+
+chrome-launcher@^0.15.2:
+ version "0.15.2"
+ resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.15.2.tgz#4e6404e32200095fdce7f6a1e1004f9bd36fa5da"
+ integrity sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==
+ dependencies:
+ "@types/node" "*"
+ escape-string-regexp "^4.0.0"
+ is-wsl "^2.2.0"
+ lighthouse-logger "^1.0.0"
+
+ci-info@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
+ integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
+
+ci-info@^3.2.0, ci-info@^3.3.0, ci-info@^3.7.0:
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4"
+ integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==
+
+clean-stack@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
+ integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
+
+cli-cursor@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
+ integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==
+ dependencies:
+ restore-cursor "^2.0.0"
+
+cli-cursor@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
+ integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
+ dependencies:
+ restore-cursor "^3.1.0"
+
+cli-spinners@^2.0.0, cli-spinners@^2.5.0:
+ version "2.9.2"
+ resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41"
+ integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==
+
+cliui@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
+ integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.0"
+ wrap-ansi "^6.2.0"
+
+cliui@^8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
+ integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.1"
+ wrap-ansi "^7.0.0"
+
+clone-deep@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
+ integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
+ dependencies:
+ is-plain-object "^2.0.4"
+ kind-of "^6.0.2"
+ shallow-clone "^3.0.0"
+
+clone@^1.0.2:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
+ integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
+
+clone@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
+ integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==
+
+color-convert@^1.9.0:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+ dependencies:
+ color-name "1.1.3"
+
+color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
+color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+ integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
+
+color-name@^1.0.0, color-name@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+color-string@^1.9.0:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4"
+ integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
+ dependencies:
+ color-name "^1.0.0"
+ simple-swizzle "^0.2.2"
+
+color@^4.2.3:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a"
+ integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==
+ dependencies:
+ color-convert "^2.0.1"
+ color-string "^1.9.0"
+
+colorette@^1.0.7:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40"
+ integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==
+
+combined-stream@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
+command-exists@^1.2.4, command-exists@^1.2.8:
+ version "1.2.9"
+ resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69"
+ integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==
+
+commander@^2.20.0:
+ version "2.20.3"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+commander@^4.0.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
+ integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
+
+commander@^7.2.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
+ integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
+
+commander@^9.4.1:
+ version "9.5.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30"
+ integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==
+
+commondir@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+ integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==
+
+component-type@^1.2.1:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/component-type/-/component-type-1.2.2.tgz#4458ecc0c1871efc6288bfaff0cbdab08141d079"
+ integrity sha512-99VUHREHiN5cLeHm3YLq312p6v+HUEcwtLCAtelvUDI6+SH5g5Cr85oNR2S1o6ywzL0ykMbuwLzM2ANocjEOIA==
+
+compressible@~2.0.18:
+ version "2.0.18"
+ resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
+ integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
+ dependencies:
+ mime-db ">= 1.43.0 < 2"
+
+compression@^1.7.1:
+ version "1.7.5"
+ resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.5.tgz#fdd256c0a642e39e314c478f6c2cd654edd74c93"
+ integrity sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==
+ dependencies:
+ bytes "3.1.2"
+ compressible "~2.0.18"
+ debug "2.6.9"
+ negotiator "~0.6.4"
+ on-headers "~1.0.2"
+ safe-buffer "5.2.1"
+ vary "~1.1.2"
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
+connect@^3.6.5, connect@^3.7.0:
+ version "3.7.0"
+ resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8"
+ integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==
+ dependencies:
+ debug "2.6.9"
+ finalhandler "1.1.2"
+ parseurl "~1.3.3"
+ utils-merge "1.0.1"
+
+convert-source-map@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
+ integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
+
+cookie-signature@^1.1.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.2.tgz#57c7fc3cc293acab9fec54d73e15690ebe4a1793"
+ integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==
+
+cookie@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
+ integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
+
+core-js-compat@^3.38.0:
+ version "3.40.0"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.40.0.tgz#7485912a5a4a4315c2fdb2cbdc623e6881c88b38"
+ integrity sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ==
+ dependencies:
+ browserslist "^4.24.3"
+
+core-util-is@~1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
+ integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
+
+cosmiconfig@^5.0.5, cosmiconfig@^5.1.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
+ integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
+ dependencies:
+ import-fresh "^2.0.0"
+ is-directory "^0.3.1"
+ js-yaml "^3.13.1"
+ parse-json "^4.0.0"
+
+cross-fetch@^3.1.5:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.2.0.tgz#34e9192f53bc757d6614304d9e5e6fb4edb782e3"
+ integrity sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==
+ dependencies:
+ node-fetch "^2.7.0"
+
+cross-spawn@^6.0.0:
+ version "6.0.6"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.6.tgz#30d0efa0712ddb7eb5a76e1e8721bffafa6b5d57"
+ integrity sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==
+ dependencies:
+ nice-try "^1.0.4"
+ path-key "^2.0.1"
+ semver "^5.5.0"
+ shebang-command "^1.2.0"
+ which "^1.2.9"
+
+cross-spawn@^7.0.0, cross-spawn@^7.0.3:
+ version "7.0.6"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
+ integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+crypt@0.0.2, crypt@~0.0.1:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
+ integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==
+
+crypto-random-string@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
+ integrity sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg==
+
+crypto-random-string@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
+ integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
+
+css-color-keywords@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
+ integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==
+
+css-in-js-utils@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz#640ae6a33646d401fc720c54fc61c42cd76ae2bb"
+ integrity sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==
+ dependencies:
+ hyphenate-style-name "^1.0.3"
+
+css-mediaquery@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/css-mediaquery/-/css-mediaquery-0.1.2.tgz#6a2c37344928618631c54bd33cedd301da18bea0"
+ integrity sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q==
+
+css-select@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6"
+ integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==
+ dependencies:
+ boolbase "^1.0.0"
+ css-what "^6.1.0"
+ domhandler "^5.0.2"
+ domutils "^3.0.1"
+ nth-check "^2.0.1"
+
+css-to-react-native@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.2.0.tgz#cdd8099f71024e149e4f6fe17a7d46ecd55f1e32"
+ integrity sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==
+ dependencies:
+ camelize "^1.0.0"
+ css-color-keywords "^1.0.0"
+ postcss-value-parser "^4.0.2"
+
+css-tree@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d"
+ integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==
+ dependencies:
+ mdn-data "2.0.14"
+ source-map "^0.6.1"
+
+css-what@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4"
+ integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
+
+cssesc@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
+ integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
+
+csstype@^3.0.2:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
+ integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
+
+dag-map@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/dag-map/-/dag-map-1.0.2.tgz#e8379f041000ed561fc515475c1ed2c85eece8d7"
+ integrity sha512-+LSAiGFwQ9dRnRdOeaj7g47ZFJcOUPukAP8J3A3fuZ1g9Y44BG+P1sgApjLXTQPOzC4+7S9Wr8kXsfpINM4jpw==
+
+data-uri-to-buffer@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636"
+ integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==
+
+data-view-buffer@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570"
+ integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==
+ dependencies:
+ call-bound "^1.0.3"
+ es-errors "^1.3.0"
+ is-data-view "^1.0.2"
+
+data-view-byte-length@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz#9e80f7ca52453ce3e93d25a35318767ea7704735"
+ integrity sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==
+ dependencies:
+ call-bound "^1.0.3"
+ es-errors "^1.3.0"
+ is-data-view "^1.0.2"
+
+data-view-byte-offset@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz#068307f9b71ab76dbbe10291389e020856606191"
+ integrity sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==
+ dependencies:
+ call-bound "^1.0.2"
+ es-errors "^1.3.0"
+ is-data-view "^1.0.1"
+
+dayjs@^1.8.15:
+ version "1.11.13"
+ resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c"
+ integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
+
+debug@2.6.9, debug@^2.2.0, debug@^2.6.9:
+ version "2.6.9"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+ dependencies:
+ ms "2.0.0"
+
+debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a"
+ integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
+ dependencies:
+ ms "^2.1.3"
+
+debug@^3.1.0:
+ version "3.2.7"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
+ integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
+ dependencies:
+ ms "^2.1.1"
+
+decamelize@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+ integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
+
+decode-uri-component@^0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9"
+ integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==
+
+deep-extend@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
+ integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
+
+deepmerge@^4.3.0:
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
+ integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
+
+default-gateway@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b"
+ integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==
+ dependencies:
+ execa "^1.0.0"
+ ip-regex "^2.1.0"
+
+defaults@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a"
+ integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==
+ dependencies:
+ clone "^1.0.2"
+
+define-data-property@^1.0.1, define-data-property@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
+ integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
+ dependencies:
+ es-define-property "^1.0.0"
+ es-errors "^1.3.0"
+ gopd "^1.0.1"
+
+define-lazy-prop@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
+ integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
+
+define-properties@^1.1.3, define-properties@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c"
+ integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==
+ dependencies:
+ define-data-property "^1.0.1"
+ has-property-descriptors "^1.0.0"
+ object-keys "^1.1.1"
+
+del@^6.0.0:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a"
+ integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==
+ dependencies:
+ globby "^11.0.1"
+ graceful-fs "^4.2.4"
+ is-glob "^4.0.1"
+ is-path-cwd "^2.2.0"
+ is-path-inside "^3.0.2"
+ p-map "^4.0.0"
+ rimraf "^3.0.2"
+ slash "^3.0.0"
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
+denodeify@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631"
+ integrity sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==
+
+depd@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
+ integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
+
+destroy@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
+ integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
+
+detect-libc@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
+ integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
+
+detect-node-es@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493"
+ integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==
+
+didyoumean@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
+ integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
+
+diff-sequences@^29.6.3:
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921"
+ integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==
+
+dir-glob@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+ dependencies:
+ path-type "^4.0.0"
+
+dlv@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
+ integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
+
+dom-serializer@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53"
+ integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==
+ dependencies:
+ domelementtype "^2.3.0"
+ domhandler "^5.0.2"
+ entities "^4.2.0"
+
+dom-walk@^0.1.0:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84"
+ integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==
+
+domelementtype@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
+ integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
+
+domhandler@^5.0.2, domhandler@^5.0.3:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31"
+ integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
+ dependencies:
+ domelementtype "^2.3.0"
+
+domutils@^3.0.1:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78"
+ integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==
+ dependencies:
+ dom-serializer "^2.0.0"
+ domelementtype "^2.3.0"
+ domhandler "^5.0.3"
+
+dotenv-expand@~11.0.6:
+ version "11.0.7"
+ resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-11.0.7.tgz#af695aea007d6fdc84c86cd8d0ad7beb40a0bd08"
+ integrity sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==
+ dependencies:
+ dotenv "^16.4.5"
+
+dotenv@^16.4.5, dotenv@~16.4.5:
+ version "16.4.7"
+ resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26"
+ integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==
+
+dunder-proto@^1.0.0, dunder-proto@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
+ integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==
+ dependencies:
+ call-bind-apply-helpers "^1.0.1"
+ es-errors "^1.3.0"
+ gopd "^1.2.0"
+
+eastasianwidth@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
+ integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
+
+ee-first@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+ integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
+
+electron-to-chromium@^1.5.73:
+ version "1.5.90"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.90.tgz#4717e5a5413f95bbb12d0af14c35057e9c65e0b6"
+ integrity sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug==
+
+emoji-regex@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
+ integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+
+emoji-regex@^9.2.2:
+ version "9.2.2"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
+ integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
+
+encodeurl@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+ integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
+
+encodeurl@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
+ integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
+
+end-of-stream@^1.1.0:
+ version "1.4.4"
+ resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
+ integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
+ dependencies:
+ once "^1.4.0"
+
+entities@^4.2.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
+ integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
+
+env-editor@^0.4.1:
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/env-editor/-/env-editor-0.4.2.tgz#4e76568d0bd8f5c2b6d314a9412c8fe9aa3ae861"
+ integrity sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA==
+
+envinfo@^7.10.0:
+ version "7.14.0"
+ resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.14.0.tgz#26dac5db54418f2a4c1159153a0b2ae980838aae"
+ integrity sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==
+
+eol@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd"
+ integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==
+
+error-ex@^1.3.1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
+ integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
+ dependencies:
+ is-arrayish "^0.2.1"
+
+error-stack-parser@^2.0.6:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286"
+ integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==
+ dependencies:
+ stackframe "^1.3.4"
+
+errorhandler@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/errorhandler/-/errorhandler-1.5.1.tgz#b9ba5d17cf90744cd1e851357a6e75bf806a9a91"
+ integrity sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==
+ dependencies:
+ accepts "~1.3.7"
+ escape-html "~1.0.3"
+
+es-abstract@^1.23.5, es-abstract@^1.23.9:
+ version "1.23.9"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.9.tgz#5b45994b7de78dada5c1bebf1379646b32b9d606"
+ integrity sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==
+ dependencies:
+ array-buffer-byte-length "^1.0.2"
+ arraybuffer.prototype.slice "^1.0.4"
+ available-typed-arrays "^1.0.7"
+ call-bind "^1.0.8"
+ call-bound "^1.0.3"
+ data-view-buffer "^1.0.2"
+ data-view-byte-length "^1.0.2"
+ data-view-byte-offset "^1.0.1"
+ es-define-property "^1.0.1"
+ es-errors "^1.3.0"
+ es-object-atoms "^1.0.0"
+ es-set-tostringtag "^2.1.0"
+ es-to-primitive "^1.3.0"
+ function.prototype.name "^1.1.8"
+ get-intrinsic "^1.2.7"
+ get-proto "^1.0.0"
+ get-symbol-description "^1.1.0"
+ globalthis "^1.0.4"
+ gopd "^1.2.0"
+ has-property-descriptors "^1.0.2"
+ has-proto "^1.2.0"
+ has-symbols "^1.1.0"
+ hasown "^2.0.2"
+ internal-slot "^1.1.0"
+ is-array-buffer "^3.0.5"
+ is-callable "^1.2.7"
+ is-data-view "^1.0.2"
+ is-regex "^1.2.1"
+ is-shared-array-buffer "^1.0.4"
+ is-string "^1.1.1"
+ is-typed-array "^1.1.15"
+ is-weakref "^1.1.0"
+ math-intrinsics "^1.1.0"
+ object-inspect "^1.13.3"
+ object-keys "^1.1.1"
+ object.assign "^4.1.7"
+ own-keys "^1.0.1"
+ regexp.prototype.flags "^1.5.3"
+ safe-array-concat "^1.1.3"
+ safe-push-apply "^1.0.0"
+ safe-regex-test "^1.1.0"
+ set-proto "^1.0.0"
+ string.prototype.trim "^1.2.10"
+ string.prototype.trimend "^1.0.9"
+ string.prototype.trimstart "^1.0.8"
+ typed-array-buffer "^1.0.3"
+ typed-array-byte-length "^1.0.3"
+ typed-array-byte-offset "^1.0.4"
+ typed-array-length "^1.0.7"
+ unbox-primitive "^1.1.0"
+ which-typed-array "^1.1.18"
+
+es-define-property@^1.0.0, es-define-property@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa"
+ integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==
+
+es-errors@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
+ integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
+
+es-object-atoms@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1"
+ integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==
+ dependencies:
+ es-errors "^1.3.0"
+
+es-set-tostringtag@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d"
+ integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==
+ dependencies:
+ es-errors "^1.3.0"
+ get-intrinsic "^1.2.6"
+ has-tostringtag "^1.0.2"
+ hasown "^2.0.2"
+
+es-to-primitive@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18"
+ integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==
+ dependencies:
+ is-callable "^1.2.7"
+ is-date-object "^1.0.5"
+ is-symbol "^1.0.4"
+
+escalade@^3.1.1, escalade@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
+ integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
+
+escape-html@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+ integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
+
+escape-string-regexp@2.0.0, escape-string-regexp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
+ integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
+
+escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+ integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
+
+escape-string-regexp@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
+ integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+
+esprima@^4.0.0, esprima@~4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+ integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
+
+etag@~1.8.1:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+ integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
+
+event-target-shim@^5.0.0, event-target-shim@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
+ integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
+
+events@^3.1.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
+ integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+
+exec-async@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/exec-async/-/exec-async-2.2.0.tgz#c7c5ad2eef3478d38390c6dd3acfe8af0efc8301"
+ integrity sha512-87OpwcEiMia/DeiKFzaQNBNFeN3XkkpYIh9FyOqq5mS2oKv3CBE67PXoEKcr6nodWdXNogTiQ0jE2NGuoffXPw==
+
+execa@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
+ integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
+ 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"
+
+execa@^5.0.0, execa@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
+ integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
+ dependencies:
+ cross-spawn "^7.0.3"
+ get-stream "^6.0.0"
+ human-signals "^2.1.0"
+ is-stream "^2.0.0"
+ merge-stream "^2.0.0"
+ npm-run-path "^4.0.1"
+ onetime "^5.1.2"
+ signal-exit "^3.0.3"
+ strip-final-newline "^2.0.0"
+
+exif-parser@^0.1.12:
+ version "0.1.12"
+ resolved "https://registry.yarnpkg.com/exif-parser/-/exif-parser-0.1.12.tgz#58a9d2d72c02c1f6f02a0ef4a9166272b7760922"
+ integrity sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==
+
+expect@^29.0.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc"
+ integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==
+ dependencies:
+ "@jest/expect-utils" "^29.7.0"
+ jest-get-type "^29.6.3"
+ jest-matcher-utils "^29.7.0"
+ jest-message-util "^29.7.0"
+ jest-util "^29.7.0"
+
+expo-application@~5.9.0:
+ version "5.9.1"
+ resolved "https://registry.yarnpkg.com/expo-application/-/expo-application-5.9.1.tgz#a12e0cf2741b6f084cc49cd0121ad0a70c770459"
+ integrity sha512-uAfLBNZNahnDZLRU41ZFmNSKtetHUT9Ua557/q189ua0AWV7pQjoVAx49E4953feuvqc9swtU3ScZ/hN1XO/FQ==
+
+expo-asset@~10.0.10:
+ version "10.0.10"
+ resolved "https://registry.yarnpkg.com/expo-asset/-/expo-asset-10.0.10.tgz#9e6e02c1a6ec3d19b50d5e615e4dd8e5cc30e857"
+ integrity sha512-0qoTIihB79k+wGus9wy0JMKq7DdenziVx3iUkGvMAy2azscSgWH6bd2gJ9CGnhC6JRd3qTMFBL0ou/fx7WZl7A==
+ dependencies:
+ expo-constants "~16.0.0"
+ invariant "^2.2.4"
+ md5-file "^3.2.3"
+
+expo-background-fetch@~12.0.1:
+ version "12.0.1"
+ resolved "https://registry.yarnpkg.com/expo-background-fetch/-/expo-background-fetch-12.0.1.tgz#0ec95d18e956e186b86c459fbebce06f17ecc4ec"
+ integrity sha512-8915rCoRKWBwCkhSSowv2+kH+QV6YYR7ES8r+yWAUPQ0vq+26NojeWAZtR0vCyTW+QLsQrYVV5Eh0brpZIMS7w==
+ dependencies:
+ expo-task-manager "~11.8.0"
+
+expo-blur@~13.0.3:
+ version "13.0.3"
+ resolved "https://registry.yarnpkg.com/expo-blur/-/expo-blur-13.0.3.tgz#f150f396ce8d0aac95587bc84806abf63ba2e2ba"
+ integrity sha512-z5W9ZGlG6ZiRLuoJZG1AHRvjK8j+2+nc/mtvEtyAa8T/8iTNpUnX4eC8xXDoTL/H4y2pc3cHvytDjCXJG26pcQ==
+
+expo-brightness@~12.0.1:
+ version "12.0.1"
+ resolved "https://registry.yarnpkg.com/expo-brightness/-/expo-brightness-12.0.1.tgz#24505912a19a909ab73814574ddf145430230d53"
+ integrity sha512-Jdi8+9YeixWdg0Z2A/f3YnQ86+iMLuGyqcTi8UTipGotTHZBG8UuV1Gab/2tttOhUK2cfv4Hc2zDbkKFP6F1JQ==
+
+expo-build-properties@~0.12.5:
+ version "0.12.5"
+ resolved "https://registry.yarnpkg.com/expo-build-properties/-/expo-build-properties-0.12.5.tgz#4d6232389f00c846ba37ca5df2c0b5527c2d94ca"
+ integrity sha512-donC1le0PYfLKCPKRMGQoixuWuwDWCngzXSoQXUPsgHTDHQUKr8aw+lcWkTwZcItgNovcnk784I0dyfYDcxybA==
+ dependencies:
+ ajv "^8.11.0"
+ semver "^7.6.0"
+
+expo-constants@~16.0.0, expo-constants@~16.0.2:
+ version "16.0.2"
+ resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-16.0.2.tgz#eb5a1bddb7308fd8cadac8fc44decaf4784cac5e"
+ integrity sha512-9tNY3OVO0jfiMzl7ngb6IOyR5VFzNoN5OOazUWoeGfmMqVB5kltTemRvKraK9JRbBKIw+SOYLEmF0sEqgFZ6OQ==
+ dependencies:
+ "@expo/config" "~9.0.0"
+ "@expo/env" "~0.3.0"
+
+expo-crypto@~13.0.2:
+ version "13.0.2"
+ resolved "https://registry.yarnpkg.com/expo-crypto/-/expo-crypto-13.0.2.tgz#e892874f571967f588b1f1e2e4924cafaf4f6823"
+ integrity sha512-7f/IMPYJZkBM21LNEMXGrNo/0uXSVfZTwufUdpNKedJR0fm5fH4DCSN79ZddlV26nF90PuXjK2inIbI6lb0qRA==
+ dependencies:
+ base64-js "^1.3.0"
+
+expo-dev-client@~4.0.29:
+ version "4.0.29"
+ resolved "https://registry.yarnpkg.com/expo-dev-client/-/expo-dev-client-4.0.29.tgz#86683c584db6b787828b10e2a049f810a246441d"
+ integrity sha512-aANlw9dC4PJEPaRNpe+X5xwyYI+aCIcbZklAAsFlkv2/05gLrsvAFgmQpRtowAzF+VggHWde1eKUOeUccAYIEg==
+ dependencies:
+ expo-dev-launcher "4.0.29"
+ expo-dev-menu "5.0.23"
+ expo-dev-menu-interface "1.8.4"
+ expo-manifests "~0.14.0"
+ expo-updates-interface "~0.16.2"
+
+expo-dev-launcher@4.0.29:
+ version "4.0.29"
+ resolved "https://registry.yarnpkg.com/expo-dev-launcher/-/expo-dev-launcher-4.0.29.tgz#c655d842802f696ad6a5e446c60d20c1e453d175"
+ integrity sha512-0a0SL8mc4FrqPeGxJHe9kf0kG+Di+38Gd+HP5DEL9dcOa8m2qffKnk22UcyujCT6+Qk0OUK1s53nnfqFB26uVw==
+ dependencies:
+ ajv "8.11.0"
+ expo-dev-menu "5.0.23"
+ expo-manifests "~0.14.0"
+ resolve-from "^5.0.0"
+ semver "^7.6.0"
+
+expo-dev-menu-interface@1.8.4:
+ version "1.8.4"
+ resolved "https://registry.yarnpkg.com/expo-dev-menu-interface/-/expo-dev-menu-interface-1.8.4.tgz#fa23bf3228ea51cf412599fcb715c27259ffdd84"
+ integrity sha512-FpYI57EUu9qTSOOi+FZJ58xkCGJK7QD0mTiXK/y1I8lRdZGjCmdBqVvC4dAx2GcbIT78EPxaVf4/90tK/KRK6A==
+
+expo-dev-menu@5.0.23:
+ version "5.0.23"
+ resolved "https://registry.yarnpkg.com/expo-dev-menu/-/expo-dev-menu-5.0.23.tgz#7e6d6fd93c54ca955e8a69601a0b1991b64389b3"
+ integrity sha512-ztDvrSdFGkRbMoQlGLyKMS6CslMGylonVW4kQHUrBQApCL0c2NtRwLlr2bA1SXF0S7qYdPPg/ayLnj7DDR5X2w==
+ dependencies:
+ expo-dev-menu-interface "1.8.4"
+ semver "^7.5.4"
+
+expo-device@~6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/expo-device/-/expo-device-6.0.2.tgz#9bc3eccd16509c2819c225cc2ca8f7c3e3bdd11e"
+ integrity sha512-sCt91CuTmAuMXX4SlFOn4lIos2UIr8vb0jDstDDZXys6kErcj0uynC7bQAMreU5uRUTKMAl4MAMpKt9ufCXPBw==
+ dependencies:
+ ua-parser-js "^0.7.33"
+
+expo-eas-client@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/expo-eas-client/-/expo-eas-client-0.12.0.tgz#e8b6f7d33873e6f630f37f7bfc41646ae7b0b2a9"
+ integrity sha512-Jkww9Cwpv0z7DdLYiRX0r4fqBEcI9cKqTn7cHx63S09JaZ2rcwEE4zYHgrXwjahO+tU2VW8zqH+AJl6RhhW4zA==
+
+expo-file-system@~17.0.1:
+ version "17.0.1"
+ resolved "https://registry.yarnpkg.com/expo-file-system/-/expo-file-system-17.0.1.tgz#b9f8af8c1c06ec71d96fd7a0d2567fa9e1c88f15"
+ integrity sha512-dYpnZJqTGj6HCYJyXAgpFkQWsiCH3HY1ek2cFZVHFoEc5tLz9gmdEgTF6nFHurvmvfmXqxi7a5CXyVm0aFYJBw==
+
+expo-font@~12.0.10:
+ version "12.0.10"
+ resolved "https://registry.yarnpkg.com/expo-font/-/expo-font-12.0.10.tgz#62deaf1f46159d7839f01305f44079268781b1db"
+ integrity sha512-Q1i2NuYri3jy32zdnBaHHCya1wH1yMAsI+3CCmj9zlQzlhsS9Bdwcj2W3c5eU5FvH2hsNQy4O+O1NnM6o/pDaQ==
+ dependencies:
+ fontfaceobserver "^2.1.0"
+
+expo-haptics@~13.0.1:
+ version "13.0.1"
+ resolved "https://registry.yarnpkg.com/expo-haptics/-/expo-haptics-13.0.1.tgz#35679c7fde4ae1c21ae3bc2d2cb34c266049dc2c"
+ integrity sha512-qG0EOLDE4bROVT3DtUSyV9g3iB3YFu9j3711X7SNNEnBDXc+2/p3wGDPTnJvPW0ao6HG3/McAOrBQA5hVSdWng==
+
+expo-image@~1.13.0:
+ version "1.13.0"
+ resolved "https://registry.yarnpkg.com/expo-image/-/expo-image-1.13.0.tgz#f0ad585ecf57f6df2d8524f5e9275cb12b349836"
+ integrity sha512-0NLDcFmEn4Nh1sXeRvNzDHT+Fl6FXtTol6ki6kYYH0/iDeSFWyIy/Fek6kzDDYAmhipSMR7buPf7VVoHseTbAA==
+
+expo-json-utils@~0.13.0:
+ version "0.13.1"
+ resolved "https://registry.yarnpkg.com/expo-json-utils/-/expo-json-utils-0.13.1.tgz#e49b697198e11c573d346f08ab91c467095934a9"
+ integrity sha512-mlfaSArGVb+oJmUcR22jEONlgPp0wj4iNIHfQ2je9Q8WTOqMc0Ws9tUciz3JdJnhffdHqo/k8fpvf0IRmN5HPA==
+
+expo-keep-awake@~13.0.2:
+ version "13.0.2"
+ resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-13.0.2.tgz#5ef31311a339671eec9921b934fdd90ab9652b0e"
+ integrity sha512-kKiwkVg/bY0AJ5q1Pxnm/GvpeB6hbNJhcFsoOWDh2NlpibhCLaHL826KHUM+WsnJRbVRxJ+K9vbPRHEMvFpVyw==
+
+expo-linear-gradient@~13.0.2:
+ version "13.0.2"
+ resolved "https://registry.yarnpkg.com/expo-linear-gradient/-/expo-linear-gradient-13.0.2.tgz#21bd7bc7c71ef4f7c089521daa16db729d2aec5f"
+ integrity sha512-EDcILUjRKu4P1rtWcwciN6CSyGtH7Bq4ll3oTRV7h3h8oSzSilH1g6z7kTAMlacPBKvMnkkWOGzW6KtgMKEiTg==
+
+expo-linking@~6.3.1:
+ version "6.3.1"
+ resolved "https://registry.yarnpkg.com/expo-linking/-/expo-linking-6.3.1.tgz#05aef8a42bd310391d0b00644be40d80ece038d9"
+ integrity sha512-xuZCntSBGWCD/95iZ+mTUGTwHdy8Sx+immCqbUBxdvZ2TN61P02kKg7SaLS8A4a/hLrSCwrg5tMMwu5wfKr35g==
+ dependencies:
+ expo-constants "~16.0.0"
+ invariant "^2.2.4"
+
+expo-localization@~15.0.3:
+ version "15.0.3"
+ resolved "https://registry.yarnpkg.com/expo-localization/-/expo-localization-15.0.3.tgz#772c89b3ab9c925b7eca6911a11ca33980c2b674"
+ integrity sha512-IfcmlKuKRlowR9qIzL0e+nGHBeNoF7l2GQaOJstc7HZiPjNJ4J1R4D53ZNf483dt7JSkTRJBihdTadOtOEjRdg==
+ dependencies:
+ rtl-detect "^1.0.2"
+
+expo-manifests@~0.14.0:
+ version "0.14.3"
+ resolved "https://registry.yarnpkg.com/expo-manifests/-/expo-manifests-0.14.3.tgz#17854c45c8c9ced4a07031ae0838c38ac3115fbc"
+ integrity sha512-L3b5/qocBPiQjbW0cpOHfnqdKZbTJS7sA3mgeDJT+mWga/xYsdpma1EfNmsuvrOzjLGjStr1k1fceM9Bl49aqQ==
+ dependencies:
+ "@expo/config" "~9.0.0"
+ expo-json-utils "~0.13.0"
+
+expo-modules-autolinking@1.11.3:
+ version "1.11.3"
+ resolved "https://registry.yarnpkg.com/expo-modules-autolinking/-/expo-modules-autolinking-1.11.3.tgz#bc64d278c04015014bb5802e3cfcd942d7c07168"
+ integrity sha512-oYh8EZEvYF5TYppxEKUTTJmbr8j7eRRnrIxzZtMvxLTXoujThVPMFS/cbnSnf2bFm1lq50TdDNABhmEi7z0ngQ==
+ dependencies:
+ chalk "^4.1.0"
+ commander "^7.2.0"
+ fast-glob "^3.2.5"
+ find-up "^5.0.0"
+ fs-extra "^9.1.0"
+ require-from-string "^2.0.2"
+ resolve-from "^5.0.0"
+
+expo-modules-core@1.12.26:
+ version "1.12.26"
+ resolved "https://registry.yarnpkg.com/expo-modules-core/-/expo-modules-core-1.12.26.tgz#86c4087dc6246abfc4d7f5e61097dc8cc4b22262"
+ integrity sha512-y8yDWjOi+rQRdO+HY+LnUlz8qzHerUaw/LUjKPU/mX8PRXP4UUPEEp5fjAwBU44xjNmYSHWZDwet4IBBE+yQUA==
+ dependencies:
+ invariant "^2.2.4"
+
+expo-network@~6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/expo-network/-/expo-network-6.0.1.tgz#0e1f8e2476d8094ae7eada651a58219eda2ec4e8"
+ integrity sha512-WXXvkt1H75ojHVa263Jq+qjIyMzCfaoRzHKzOBMuSyDDcma9WpvKJpR1YpEQZH/zDhSfkKvh7Q3wRGOJr1J+dQ==
+
+expo-notifications@~0.28.19:
+ version "0.28.19"
+ resolved "https://registry.yarnpkg.com/expo-notifications/-/expo-notifications-0.28.19.tgz#d8f858b887aacfc8ac5e0a59b00a9c88ded54469"
+ integrity sha512-rKKTnVQQ9XNQyTNwKmI9OlchhVu0XOZfRpImMqPFCJg6IwECM1izdas2SLCbE/GApg2Tw3U5R2fd26OnCtUU/w==
+ dependencies:
+ "@expo/image-utils" "^0.5.0"
+ "@ide/backoff" "^1.0.0"
+ abort-controller "^3.0.0"
+ assert "^2.0.0"
+ badgin "^1.1.5"
+ expo-application "~5.9.0"
+ expo-constants "~16.0.0"
+ fs-extra "^9.1.0"
+
+expo-router@~3.5.24:
+ version "3.5.24"
+ resolved "https://registry.yarnpkg.com/expo-router/-/expo-router-3.5.24.tgz#ac834b66c023151a3f919c456805cdd7377a677f"
+ integrity sha512-wFi+PIUrOntF5cgg0PgBMlkxEZlWedIv5dWnPFEzN6Tr3A3bpsqdDLgOEIwvwd+pxn5DLzykTmg9EkQ1pPGspw==
+ dependencies:
+ "@expo/metro-runtime" "3.2.3"
+ "@expo/server" "^0.4.0"
+ "@radix-ui/react-slot" "1.0.1"
+ "@react-navigation/bottom-tabs" "~6.5.7"
+ "@react-navigation/native" "~6.1.6"
+ "@react-navigation/native-stack" "~6.9.12"
+ expo-splash-screen "0.27.7"
+ react-native-helmet-async "2.0.4"
+ schema-utils "^4.0.1"
+
+expo-screen-orientation@~7.0.5:
+ version "7.0.5"
+ resolved "https://registry.yarnpkg.com/expo-screen-orientation/-/expo-screen-orientation-7.0.5.tgz#0a517982151c6519fa4b10ce27047de39c1f92cf"
+ integrity sha512-1j0MzVzYpjKQo4BWowQ3ZYwC3OnddX/8k06C8VYTAxMyd8ou1k+rG4tm+GIV2n2RSzc3g7cfPlQwSYr3/SGmbg==
+
+expo-sensors@~13.0.9:
+ version "13.0.9"
+ resolved "https://registry.yarnpkg.com/expo-sensors/-/expo-sensors-13.0.9.tgz#7c937925df131f6ea3abd247d60464f80987eb42"
+ integrity sha512-yi/TERUP8dpsJWWRgjT+UuQ7PI604PMndwXh9iBnfNO7q+dtoKZKsVSNJw61IKLNflbtCAyJxgmzPoe/JDT04Q==
+ dependencies:
+ invariant "^2.2.4"
+
+expo-splash-screen@0.27.7, expo-splash-screen@~0.27.7:
+ version "0.27.7"
+ resolved "https://registry.yarnpkg.com/expo-splash-screen/-/expo-splash-screen-0.27.7.tgz#52171be54d8c008880d928e802819d767fbd3c12"
+ integrity sha512-s+eGcG185878nixlrjhhLD6UDYrvoqBUaBkIEozBVWFg3pkdsKpONPiUAco4XR3h7I/9ODq4quN28RJLFO+s0Q==
+ dependencies:
+ "@expo/prebuild-config" "7.0.9"
+
+expo-status-bar@~1.12.1:
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/expo-status-bar/-/expo-status-bar-1.12.1.tgz#52ce594aab5064a0511d14375364d718ab78aa66"
+ integrity sha512-/t3xdbS8KB0prj5KG5w7z+wZPFlPtkgs95BsmrP/E7Q0xHXTcDcQ6Cu2FkFuRM+PKTb17cJDnLkawyS5vDLxMA==
+
+expo-structured-headers@~3.8.0:
+ version "3.8.0"
+ resolved "https://registry.yarnpkg.com/expo-structured-headers/-/expo-structured-headers-3.8.0.tgz#11797a4c3a7a6770b21126cecffcda148030e361"
+ integrity sha512-R+gFGn0x5CWl4OVlk2j1bJTJIz4KO8mPoCHpRHmfqMjmrMvrOM0qQSY3V5NHXwp1yT/L2v8aUmFQsBRIdvi1XA==
+
+expo-system-ui@~3.0.7:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/expo-system-ui/-/expo-system-ui-3.0.7.tgz#73fee2a61db435e5d66cbf6407e0987f39c25b4e"
+ integrity sha512-KAs72F5JKhdIfPR9ZNVlRubTPK9uUuevPy5oYEp12xNEzSQcjZKvypH5NpwJuNWkXzrp3n3vZ+3pXsudA7J3KA==
+ dependencies:
+ "@react-native/normalize-colors" "0.74.85"
+ debug "^4.3.2"
+
+expo-task-manager@~11.8.0, expo-task-manager@~11.8.2:
+ version "11.8.2"
+ resolved "https://registry.yarnpkg.com/expo-task-manager/-/expo-task-manager-11.8.2.tgz#1090a445565ca65ed99991166ddda38575b3dc8c"
+ integrity sha512-Uhy3ol5gYeZOyeRFddYjLI1B2DGRH1gjp/YC8Hpn5p5MVENviySoKNF+wd98rRvOAokzrzElyDBHSTfX+C3tpg==
+ dependencies:
+ unimodules-app-loader "~4.6.0"
+
+expo-updates-interface@~0.16.2:
+ version "0.16.2"
+ resolved "https://registry.yarnpkg.com/expo-updates-interface/-/expo-updates-interface-0.16.2.tgz#ad1ac2ca8ee5a8cc84052ea3c18a11da64da569b"
+ integrity sha512-929XBU70q5ELxkKADj1xL0UIm3HvhYhNAOZv5DSk7rrKvLo7QDdPyl+JVnwZm9LrkNbH4wuE2rLoKu1KMgZ+9A==
+
+expo-updates@~0.25.28:
+ version "0.25.28"
+ resolved "https://registry.yarnpkg.com/expo-updates/-/expo-updates-0.25.28.tgz#37ab65f67798c7080e724a2ad91e763f1941d2ae"
+ integrity sha512-NTI1r7wvXel36qCzKwCjCJ9HExBo6GX9wkA9WzaNsysmg+eEd5BCmcaxvQGZUQkfDocEfI78N5vRBSuMi0iS1w==
+ dependencies:
+ "@expo/code-signing-certificates" "0.0.5"
+ "@expo/config" "~9.0.0-beta.0"
+ "@expo/config-plugins" "~8.0.8"
+ "@expo/fingerprint" "^0.10.2"
+ "@expo/spawn-async" "^1.7.2"
+ arg "4.1.0"
+ chalk "^4.1.2"
+ expo-eas-client "~0.12.0"
+ expo-manifests "~0.14.0"
+ expo-structured-headers "~3.8.0"
+ expo-updates-interface "~0.16.2"
+ fast-glob "^3.3.2"
+ fbemitter "^3.0.0"
+ ignore "^5.3.1"
+ resolve-from "^5.0.0"
+
+expo-web-browser@~13.0.3:
+ version "13.0.3"
+ resolved "https://registry.yarnpkg.com/expo-web-browser/-/expo-web-browser-13.0.3.tgz#dceb05dbc187b498ca937b02adf385b0232a4e92"
+ integrity sha512-HXb7y82ApVJtqk8tManyudtTrCtx8xcUnVzmJECeHCB0SsWSQ+penVLZxJkcyATWoJOsFMnfVSVdrTcpKKGszQ==
+
+expo@^51:
+ version "51.0.39"
+ resolved "https://registry.yarnpkg.com/expo/-/expo-51.0.39.tgz#d9efab081a91a0d3e925b0e4648722b13a8fceae"
+ integrity sha512-Cs/9xopyzJrpXWbyVUZnr37rprdFJorRgfSp6cdBfvbjxZeKnw2MEu7wJwV/s626i5lZTPGjZPHUF9uQvt51cg==
+ dependencies:
+ "@babel/runtime" "^7.20.0"
+ "@expo/cli" "0.18.31"
+ "@expo/config" "9.0.4"
+ "@expo/config-plugins" "8.0.11"
+ "@expo/metro-config" "0.18.11"
+ "@expo/vector-icons" "^14.0.3"
+ babel-preset-expo "~11.0.15"
+ expo-asset "~10.0.10"
+ expo-file-system "~17.0.1"
+ expo-font "~12.0.10"
+ expo-keep-awake "~13.0.2"
+ expo-modules-autolinking "1.11.3"
+ expo-modules-core "1.12.26"
+ fbemitter "^3.0.0"
+ whatwg-url-without-unicode "8.0.0-3"
+
+exponential-backoff@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6"
+ integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==
+
+extend@^3.0.1:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
+ integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
+
+fast-base64-decode@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz#b434a0dd7d92b12b43f26819300d2dafb83ee418"
+ integrity sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==
+
+fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-glob@^3.2.12, fast-glob@^3.2.5, fast-glob@^3.2.9, fast-glob@^3.3.2:
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818"
+ integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.8"
+
+fast-loops@^1.1.3:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/fast-loops/-/fast-loops-1.1.4.tgz#61bc77d518c0af5073a638c6d9d5c7683f069ce2"
+ integrity sha512-8dbd3XWoKCTms18ize6JmQF1SFnnfj5s0B7rRry22EofgMu7B6LKHVh+XfFqFGsqnbH54xgeO83PzpKI+ODhlg==
+
+fast-uri@^3.0.1:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748"
+ integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==
+
+fast-xml-parser@^4.0.12, fast-xml-parser@^4.2.4:
+ version "4.5.1"
+ resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.5.1.tgz#a7e665ff79b7919100a5202f23984b6150f9b31e"
+ integrity sha512-y655CeyUQ+jj7KBbYMc4FG01V8ZQqjN+gDYGJ50RtfsUB8iG9AmwmwoAgeKLJdmueKKMrH1RJ7yXHTSoczdv5w==
+ dependencies:
+ strnum "^1.0.5"
+
+fastq@^1.6.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.0.tgz#a82c6b7c2bb4e44766d865f07997785fecfdcb89"
+ integrity sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==
+ dependencies:
+ reusify "^1.0.4"
+
+fb-watchman@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c"
+ integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==
+ dependencies:
+ bser "2.1.1"
+
+fbemitter@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-3.0.0.tgz#00b2a1af5411254aab416cd75f9e6289bee4bff3"
+ integrity sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw==
+ dependencies:
+ fbjs "^3.0.0"
+
+fbjs-css-vars@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8"
+ integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==
+
+fbjs@^3.0.0, fbjs@^3.0.4:
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.5.tgz#aa0edb7d5caa6340011790bd9249dbef8a81128d"
+ integrity sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==
+ dependencies:
+ cross-fetch "^3.1.5"
+ fbjs-css-vars "^1.0.0"
+ loose-envify "^1.0.0"
+ object-assign "^4.1.0"
+ promise "^7.1.1"
+ setimmediate "^1.0.5"
+ ua-parser-js "^1.0.35"
+
+fetch-retry@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/fetch-retry/-/fetch-retry-4.1.1.tgz#fafe0bb22b54f4d0a9c788dff6dd7f8673ca63f3"
+ integrity sha512-e6eB7zN6UBSwGVwrbWVH+gdLnkW9WwHhmq2YDK1Sh30pzx1onRVGBvogTlUeWxwTa+L86NYdo4hFkh7O8ZjSnA==
+
+ffmpeg-kit-react-native@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/ffmpeg-kit-react-native/-/ffmpeg-kit-react-native-6.0.2.tgz#9eeac96ad89367c99480bd90431391405d4eb73e"
+ integrity sha512-r9uSmahq8TeyIb7fXf3ft+uUXyoeWRFa99+khjo0TAzWO9y0z9wU7eGnab9JLw1MmCB9v64o4yojNluJhVm9nQ==
+
+file-type@^16.5.4:
+ version "16.5.4"
+ resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.5.4.tgz#474fb4f704bee427681f98dd390058a172a6c2fd"
+ integrity sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==
+ dependencies:
+ readable-web-to-node-stream "^3.0.0"
+ strtok3 "^6.2.4"
+ token-types "^4.1.1"
+
+fill-range@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
+ integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+filter-obj@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b"
+ integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==
+
+finalhandler@1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
+ integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
+ dependencies:
+ debug "2.6.9"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ on-finished "~2.3.0"
+ parseurl "~1.3.3"
+ statuses "~1.5.0"
+ unpipe "~1.0.0"
+
+find-cache-dir@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7"
+ integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==
+ dependencies:
+ commondir "^1.0.1"
+ make-dir "^2.0.0"
+ pkg-dir "^3.0.0"
+
+find-up@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
+ integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+ dependencies:
+ locate-path "^3.0.0"
+
+find-up@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+ dependencies:
+ locate-path "^5.0.0"
+ path-exists "^4.0.0"
+
+find-up@^5.0.0, find-up@~5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+ integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+ dependencies:
+ locate-path "^6.0.0"
+ path-exists "^4.0.0"
+
+find-yarn-workspace-root@^2.0.0, find-yarn-workspace-root@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd"
+ integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==
+ dependencies:
+ micromatch "^4.0.2"
+
+flow-enums-runtime@^0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz#5bb0cd1b0a3e471330f4d109039b7eba5cb3e787"
+ integrity sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==
+
+flow-parser@0.*:
+ version "0.259.1"
+ resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.259.1.tgz#2ab828be197bb87f47af299e5b734eab139bd269"
+ integrity sha512-xiXLmMH2Z7OmdE9Q+MjljUMr/rbemFqZIRxaeZieVScG4HzQrKKhNcCYZbWTGpoN7ZPi7z8ClQbeVPq6t5AszQ==
+
+follow-redirects@^1.15.6:
+ version "1.15.9"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1"
+ integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==
+
+fontfaceobserver@^2.1.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz#5fb392116e75d5024b7ec8e4f2ce92106d1488c8"
+ integrity sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==
+
+for-each@^0.3.3:
+ version "0.3.4"
+ resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.4.tgz#814517ffc303d1399b2564d8165318e735d0341c"
+ integrity sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw==
+ dependencies:
+ is-callable "^1.2.7"
+
+foreground-child@^3.1.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77"
+ integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==
+ dependencies:
+ cross-spawn "^7.0.0"
+ signal-exit "^4.0.1"
+
+form-data@^3.0.1:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.2.tgz#83ad9ced7c03feaad97e293d6f6091011e1659c8"
+ integrity sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
+form-data@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48"
+ integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
+freeport-async@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/freeport-async/-/freeport-async-2.0.0.tgz#6adf2ec0c629d11abff92836acd04b399135bab4"
+ integrity sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ==
+
+fresh@0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+ integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
+
+fs-extra@9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.0.tgz#b6afc31036e247b2466dc99c29ae797d5d4580a3"
+ integrity sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==
+ dependencies:
+ at-least-node "^1.0.0"
+ graceful-fs "^4.2.0"
+ jsonfile "^6.0.1"
+ universalify "^1.0.0"
+
+fs-extra@^8.1.0, fs-extra@~8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
+ integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
+ dependencies:
+ graceful-fs "^4.2.0"
+ jsonfile "^4.0.0"
+ universalify "^0.1.0"
+
+fs-extra@^9.0.0, fs-extra@^9.1.0:
+ version "9.1.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
+ integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==
+ dependencies:
+ at-least-node "^1.0.0"
+ graceful-fs "^4.2.0"
+ jsonfile "^6.0.1"
+ universalify "^2.0.0"
+
+fs-minipass@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
+ integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
+ dependencies:
+ minipass "^3.0.0"
+
+fs-minipass@^3.0.0:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54"
+ integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==
+ dependencies:
+ minipass "^7.0.3"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+
+fsevents@^2.3.2, fsevents@~2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
+ integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
+
+function-bind@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
+ integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
+
+function.prototype.name@^1.1.6, function.prototype.name@^1.1.8:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78"
+ integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==
+ dependencies:
+ call-bind "^1.0.8"
+ call-bound "^1.0.3"
+ define-properties "^1.2.1"
+ functions-have-names "^1.2.3"
+ hasown "^2.0.2"
+ is-callable "^1.2.7"
+
+functions-have-names@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
+ integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
+
+gensync@^1.0.0-beta.2:
+ version "1.0.0-beta.2"
+ resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
+ integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
+
+get-caller-file@^2.0.1, get-caller-file@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
+ integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+
+get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.7.tgz#dcfcb33d3272e15f445d15124bc0a216189b9044"
+ integrity sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==
+ 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"
+
+get-nonce@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3"
+ integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==
+
+get-port@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc"
+ integrity sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==
+
+get-proto@^1.0.0, get-proto@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
+ integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==
+ dependencies:
+ dunder-proto "^1.0.1"
+ es-object-atoms "^1.0.0"
+
+get-stream@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
+ integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
+ dependencies:
+ pump "^3.0.0"
+
+get-stream@^6.0.0:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
+ integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
+
+get-symbol-description@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee"
+ integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==
+ dependencies:
+ call-bound "^1.0.3"
+ es-errors "^1.3.0"
+ get-intrinsic "^1.2.6"
+
+getenv@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/getenv/-/getenv-1.0.0.tgz#874f2e7544fbca53c7a4738f37de8605c3fcfc31"
+ integrity sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg==
+
+gifwrap@^0.9.2:
+ version "0.9.4"
+ resolved "https://registry.yarnpkg.com/gifwrap/-/gifwrap-0.9.4.tgz#f4eb6169ba027d61df64aafbdcb1f8ae58ccc0c5"
+ integrity sha512-MDMwbhASQuVeD4JKd1fKgNgCRL3fGqMM4WaqpNhWO0JiMOAjbQdumbs4BbBZEy9/M00EHEjKN3HieVhCUlwjeQ==
+ dependencies:
+ image-q "^4.0.0"
+ omggif "^1.0.10"
+
+glob-parent@^5.1.2, glob-parent@~5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+glob-parent@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
+ integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
+ dependencies:
+ is-glob "^4.0.3"
+
+glob@7.1.6:
+ version "7.1.6"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
+ integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+glob@^10.2.2, glob@^10.3.10, glob@^10.4.2:
+ version "10.4.5"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956"
+ integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==
+ dependencies:
+ foreground-child "^3.1.0"
+ jackspeak "^3.1.2"
+ minimatch "^9.0.4"
+ minipass "^7.1.2"
+ package-json-from-dist "^1.0.0"
+ path-scurry "^1.11.1"
+
+glob@^7.1.1, glob@^7.1.3, glob@^7.1.7, glob@^7.2.3:
+ version "7.2.3"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
+ integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
+ 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"
+
+global@~4.4.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406"
+ integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==
+ dependencies:
+ min-document "^2.19.0"
+ process "^0.11.10"
+
+globals@^11.1.0:
+ version "11.12.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
+ integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+
+globalthis@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236"
+ integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==
+ dependencies:
+ define-properties "^1.2.1"
+ gopd "^1.0.1"
+
+globby@^11.0.1:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
+ integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+ dependencies:
+ array-union "^2.1.0"
+ dir-glob "^3.0.1"
+ fast-glob "^3.2.9"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
+ slash "^3.0.0"
+
+gopd@^1.0.1, gopd@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1"
+ integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
+
+graceful-fs@^4.1.11, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9:
+ version "4.2.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+ integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+graphql-tag@^2.10.1:
+ version "2.12.6"
+ resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1"
+ integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==
+ dependencies:
+ tslib "^2.1.0"
+
+graphql@15.8.0:
+ version "15.8.0"
+ resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38"
+ integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==
+
+has-bigints@^1.0.2:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe"
+ integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==
+
+has-flag@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+ integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
+
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
+ integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
+ dependencies:
+ es-define-property "^1.0.0"
+
+has-proto@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5"
+ integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==
+ dependencies:
+ dunder-proto "^1.0.0"
+
+has-symbols@^1.0.3, has-symbols@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
+ integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==
+
+has-tostringtag@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc"
+ integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==
+ dependencies:
+ has-symbols "^1.0.3"
+
+hasown@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
+ integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
+ dependencies:
+ function-bind "^1.1.2"
+
+hermes-estree@0.19.1:
+ version "0.19.1"
+ resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.19.1.tgz#d5924f5fac2bf0532547ae9f506d6db8f3c96392"
+ integrity sha512-daLGV3Q2MKk8w4evNMKwS8zBE/rcpA800nu1Q5kM08IKijoSnPe9Uo1iIxzPKRkn95IxxsgBMPeYHt3VG4ej2g==
+
+hermes-estree@0.23.1:
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.23.1.tgz#d0bac369a030188120ee7024926aabe5a9f84fdb"
+ integrity sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==
+
+hermes-parser@0.19.1:
+ version "0.19.1"
+ resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.19.1.tgz#1044348097165b7c93dc198a80b04ed5130d6b1a"
+ integrity sha512-Vp+bXzxYJWrpEuJ/vXxUsLnt0+y4q9zyi4zUlkLqD8FKv4LjIfOvP69R/9Lty3dCyKh0E2BU7Eypqr63/rKT/A==
+ dependencies:
+ hermes-estree "0.19.1"
+
+hermes-parser@0.23.1:
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.23.1.tgz#e5de648e664f3b3d84d01b48fc7ab164f4b68205"
+ integrity sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==
+ dependencies:
+ hermes-estree "0.23.1"
+
+hermes-profile-transformer@^0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz#bd0f5ecceda80dd0ddaae443469ab26fb38fc27b"
+ integrity sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ==
+ dependencies:
+ source-map "^0.7.3"
+
+hoist-non-react-statics@^3.3.0:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
+ integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
+ dependencies:
+ react-is "^16.7.0"
+
+hosted-git-info@^3.0.2:
+ version "3.0.8"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.8.tgz#6e35d4cc87af2c5f816e4cb9ce350ba87a3f370d"
+ integrity sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==
+ dependencies:
+ lru-cache "^6.0.0"
+
+hosted-git-info@^7.0.0:
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-7.0.2.tgz#9b751acac097757667f30114607ef7b661ff4f17"
+ integrity sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==
+ dependencies:
+ lru-cache "^10.0.1"
+
+html-parse-stringify@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2"
+ integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==
+ dependencies:
+ void-elements "3.1.0"
+
+http-errors@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
+ integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
+ dependencies:
+ depd "2.0.0"
+ inherits "2.0.4"
+ setprototypeof "1.2.0"
+ statuses "2.0.1"
+ toidentifier "1.0.1"
+
+https-proxy-agent@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
+ integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
+ dependencies:
+ agent-base "6"
+ debug "4"
+
+human-signals@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
+ integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
+
+hyphenate-style-name@^1.0.3:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz#1797bf50369588b47b72ca6d5e65374607cf4436"
+ integrity sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==
+
+i18next@^24.2.2:
+ version "24.2.2"
+ resolved "https://registry.yarnpkg.com/i18next/-/i18next-24.2.2.tgz#3ba3d213302068d569142737f03f30929de696de"
+ integrity sha512-NE6i86lBCKRYZa5TaUDkU5S4HFgLIEJRLr3Whf2psgaxBleQ2LC1YW1Vc+SCgkAW7VEzndT6al6+CzegSUHcTQ==
+ dependencies:
+ "@babel/runtime" "^7.23.2"
+
+ieee754@^1.1.13, ieee754@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
+ integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
+
+ignore@^5.2.0, ignore@^5.3.1:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
+ integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
+
+image-q@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/image-q/-/image-q-4.0.0.tgz#31e075be7bae3c1f42a85c469b4732c358981776"
+ integrity sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==
+ dependencies:
+ "@types/node" "16.9.1"
+
+image-size@^1.0.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.2.0.tgz#312af27a2ff4ff58595ad00b9344dd684c910df6"
+ integrity sha512-4S8fwbO6w3GeCVN6OPtA9I5IGKkcDMPcKndtUlpJuCwu7JLjtj7JZpwqLuyY2nrmQT3AWsCJLSKPsc2mPBSl3w==
+ dependencies:
+ queue "6.0.2"
+
+import-fresh@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
+ integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==
+ dependencies:
+ caller-path "^2.0.0"
+ resolve-from "^3.0.0"
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+ integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
+
+indent-string@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
+ integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+ini@~1.3.0:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
+ integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
+
+inline-style-prefixer@^6.0.1:
+ version "6.0.4"
+ resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-6.0.4.tgz#4290ed453ab0e4441583284ad86e41ad88384f44"
+ integrity sha512-FwXmZC2zbeeS7NzGjJ6pAiqRhXR0ugUShSNb6GApMl6da0/XGc4MOJsoWAywia52EEWbXNSy0pzkwz/+Y+swSg==
+ dependencies:
+ css-in-js-utils "^3.1.0"
+ fast-loops "^1.1.3"
+
+install@^0.13.0:
+ version "0.13.0"
+ resolved "https://registry.yarnpkg.com/install/-/install-0.13.0.tgz#6af6e9da9dd0987de2ab420f78e60d9c17260776"
+ integrity sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==
+
+internal-ip@4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907"
+ integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==
+ dependencies:
+ default-gateway "^4.2.0"
+ ipaddr.js "^1.9.0"
+
+internal-slot@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961"
+ integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==
+ dependencies:
+ es-errors "^1.3.0"
+ hasown "^2.0.2"
+ side-channel "^1.1.0"
+
+invariant@2.2.4, invariant@^2.2.4:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
+ integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
+ dependencies:
+ loose-envify "^1.0.0"
+
+ip-regex@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
+ integrity sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==
+
+ipaddr.js@^1.9.0:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
+ integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
+
+is-arguments@^1.0.4:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.2.0.tgz#ad58c6aecf563b78ef2bf04df540da8f5d7d8e1b"
+ integrity sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==
+ dependencies:
+ call-bound "^1.0.2"
+ has-tostringtag "^1.0.2"
+
+is-array-buffer@^3.0.4, is-array-buffer@^3.0.5:
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280"
+ integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==
+ dependencies:
+ call-bind "^1.0.8"
+ call-bound "^1.0.3"
+ get-intrinsic "^1.2.6"
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+ integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
+
+is-arrayish@^0.3.1:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
+ integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
+
+is-async-function@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.1.1.tgz#3e69018c8e04e73b738793d020bfe884b9fd3523"
+ integrity sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==
+ dependencies:
+ async-function "^1.0.0"
+ call-bound "^1.0.3"
+ get-proto "^1.0.1"
+ has-tostringtag "^1.0.2"
+ safe-regex-test "^1.1.0"
+
+is-bigint@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672"
+ integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==
+ dependencies:
+ has-bigints "^1.0.2"
+
+is-binary-path@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+ integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+ dependencies:
+ binary-extensions "^2.0.0"
+
+is-boolean-object@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.1.tgz#c20d0c654be05da4fbc23c562635c019e93daf89"
+ integrity sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==
+ dependencies:
+ call-bound "^1.0.2"
+ has-tostringtag "^1.0.2"
+
+is-buffer@~1.1.1, is-buffer@~1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
+ integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
+
+is-callable@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
+ integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
+
+is-core-module@^2.16.0:
+ version "2.16.1"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4"
+ integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==
+ dependencies:
+ hasown "^2.0.2"
+
+is-data-view@^1.0.1, is-data-view@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e"
+ integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==
+ dependencies:
+ call-bound "^1.0.2"
+ get-intrinsic "^1.2.6"
+ is-typed-array "^1.1.13"
+
+is-date-object@^1.0.5, is-date-object@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7"
+ integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==
+ dependencies:
+ call-bound "^1.0.2"
+ has-tostringtag "^1.0.2"
+
+is-directory@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
+ integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==
+
+is-docker@^2.0.0, is-docker@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
+ integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
+
+is-extglob@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
+ integrity sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-finalizationregistry@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz#eefdcdc6c94ddd0674d9c85887bf93f944a97c90"
+ integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==
+ dependencies:
+ call-bound "^1.0.3"
+
+is-fullwidth-code-point@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+ integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==
+
+is-fullwidth-code-point@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
+ integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
+is-function@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08"
+ integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==
+
+is-generator-function@^1.0.10, is-generator-function@^1.0.7:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca"
+ integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==
+ dependencies:
+ call-bound "^1.0.3"
+ get-proto "^1.0.0"
+ has-tostringtag "^1.0.2"
+ safe-regex-test "^1.1.0"
+
+is-glob@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
+ integrity sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==
+ dependencies:
+ is-extglob "^1.0.0"
+
+is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-interactive@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
+ integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
+
+is-invalid-path@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/is-invalid-path/-/is-invalid-path-0.1.0.tgz#307a855b3cf1a938b44ea70d2c61106053714f34"
+ integrity sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ==
+ dependencies:
+ is-glob "^2.0.0"
+
+is-map@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e"
+ integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==
+
+is-nan@^1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d"
+ integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==
+ dependencies:
+ call-bind "^1.0.0"
+ define-properties "^1.1.3"
+
+is-number-object@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541"
+ integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==
+ dependencies:
+ call-bound "^1.0.3"
+ has-tostringtag "^1.0.2"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-path-cwd@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb"
+ integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==
+
+is-path-inside@^3.0.2:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
+ integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
+
+is-plain-obj@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
+ integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
+
+is-plain-object@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
+ integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
+ dependencies:
+ isobject "^3.0.1"
+
+is-regex@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22"
+ integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==
+ dependencies:
+ call-bound "^1.0.2"
+ gopd "^1.2.0"
+ has-tostringtag "^1.0.2"
+ hasown "^2.0.2"
+
+is-set@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d"
+ integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==
+
+is-shared-array-buffer@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz#9b67844bd9b7f246ba0708c3a93e34269c774f6f"
+ integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==
+ dependencies:
+ call-bound "^1.0.3"
+
+is-stream@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+ integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==
+
+is-stream@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
+ integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
+
+is-string@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9"
+ integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==
+ dependencies:
+ call-bound "^1.0.3"
+ has-tostringtag "^1.0.2"
+
+is-symbol@^1.0.4, is-symbol@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634"
+ integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==
+ dependencies:
+ call-bound "^1.0.2"
+ has-symbols "^1.1.0"
+ safe-regex-test "^1.1.0"
+
+is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15, is-typed-array@^1.1.3:
+ version "1.1.15"
+ resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b"
+ integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==
+ dependencies:
+ which-typed-array "^1.1.16"
+
+is-unicode-supported@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
+ integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
+
+is-valid-path@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/is-valid-path/-/is-valid-path-0.1.1.tgz#110f9ff74c37f663e1ec7915eb451f2db93ac9df"
+ integrity sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A==
+ dependencies:
+ is-invalid-path "^0.1.0"
+
+is-weakmap@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd"
+ integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==
+
+is-weakref@^1.0.2, is-weakref@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.0.tgz#47e3472ae95a63fa9cf25660bcf0c181c39770ef"
+ integrity sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==
+ dependencies:
+ call-bound "^1.0.2"
+
+is-weakset@^2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.4.tgz#c9f5deb0bc1906c6d6f1027f284ddf459249daca"
+ integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==
+ dependencies:
+ call-bound "^1.0.3"
+ get-intrinsic "^1.2.6"
+
+is-wsl@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
+ integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==
+
+is-wsl@^2.1.1, is-wsl@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
+ integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
+ dependencies:
+ is-docker "^2.0.0"
+
+isarray@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
+ integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
+
+isarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+ integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+isobject@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
+ integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
+
+jackspeak@^3.1.2:
+ version "3.4.3"
+ resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a"
+ integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==
+ dependencies:
+ "@isaacs/cliui" "^8.0.2"
+ optionalDependencies:
+ "@pkgjs/parseargs" "^0.11.0"
+
+jest-diff@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a"
+ integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==
+ dependencies:
+ chalk "^4.0.0"
+ diff-sequences "^29.6.3"
+ jest-get-type "^29.6.3"
+ pretty-format "^29.7.0"
+
+jest-environment-node@^29.6.3:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376"
+ integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==
+ dependencies:
+ "@jest/environment" "^29.7.0"
+ "@jest/fake-timers" "^29.7.0"
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ jest-mock "^29.7.0"
+ jest-util "^29.7.0"
+
+jest-get-type@^29.6.3:
+ version "29.6.3"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1"
+ integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==
+
+jest-matcher-utils@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12"
+ integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==
+ dependencies:
+ chalk "^4.0.0"
+ jest-diff "^29.7.0"
+ jest-get-type "^29.6.3"
+ pretty-format "^29.7.0"
+
+jest-message-util@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3"
+ integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==
+ dependencies:
+ "@babel/code-frame" "^7.12.13"
+ "@jest/types" "^29.6.3"
+ "@types/stack-utils" "^2.0.0"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ micromatch "^4.0.4"
+ pretty-format "^29.7.0"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+
+jest-mock@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347"
+ integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ jest-util "^29.7.0"
+
+jest-util@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc"
+ integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ graceful-fs "^4.2.9"
+ picomatch "^2.2.3"
+
+jest-validate@^29.6.3:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c"
+ integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==
+ dependencies:
+ "@jest/types" "^29.6.3"
+ camelcase "^6.2.0"
+ chalk "^4.0.0"
+ jest-get-type "^29.6.3"
+ leven "^3.1.0"
+ pretty-format "^29.7.0"
+
+jest-worker@^29.6.3:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a"
+ integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==
+ dependencies:
+ "@types/node" "*"
+ jest-util "^29.7.0"
+ merge-stream "^2.0.0"
+ supports-color "^8.0.0"
+
+jimp-compact@0.16.1:
+ version "0.16.1"
+ resolved "https://registry.yarnpkg.com/jimp-compact/-/jimp-compact-0.16.1.tgz#9582aea06548a2c1e04dd148d7c3ab92075aefa3"
+ integrity sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==
+
+jiti@^1.18.2:
+ version "1.21.7"
+ resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.7.tgz#9dd81043424a3d28458b193d965f0d18a2300ba9"
+ integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==
+
+joi@^17.2.1:
+ version "17.13.3"
+ resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec"
+ integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==
+ dependencies:
+ "@hapi/hoek" "^9.3.0"
+ "@hapi/topo" "^5.1.0"
+ "@sideway/address" "^4.1.5"
+ "@sideway/formula" "^3.0.1"
+ "@sideway/pinpoint" "^2.0.0"
+
+join-component@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/join-component/-/join-component-1.1.0.tgz#b8417b750661a392bee2c2537c68b2a9d4977cd5"
+ integrity sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==
+
+jotai@^2.10.1:
+ version "2.11.3"
+ resolved "https://registry.yarnpkg.com/jotai/-/jotai-2.11.3.tgz#7d95086ac7aebf363cb607404356b8427d3c1547"
+ integrity sha512-B/PsewAQ0UOS5e2+TTWegUPQ3SCLPCjPY24LYUjfn2EorGlluTA2dFjVLgF1+xHLjK9Jit3y5mKHyMG3Xq/GZg==
+
+jpeg-js@^0.4.2:
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa"
+ integrity sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==
+
+"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+js-yaml@^3.13.1:
+ version "3.14.1"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
+ integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^4.0.0"
+
+js-yaml@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
+ integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
+ dependencies:
+ argparse "^2.0.1"
+
+jsc-android@^250231.0.0:
+ version "250231.0.0"
+ resolved "https://registry.yarnpkg.com/jsc-android/-/jsc-android-250231.0.0.tgz#91720f8df382a108872fa4b3f558f33ba5e95262"
+ integrity sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==
+
+jsc-safe-url@^0.2.2, jsc-safe-url@^0.2.4:
+ version "0.2.4"
+ resolved "https://registry.yarnpkg.com/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz#141c14fbb43791e88d5dc64e85a374575a83477a"
+ integrity sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==
+
+jscodeshift@^0.14.0:
+ version "0.14.0"
+ resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.14.0.tgz#7542e6715d6d2e8bde0b4e883f0ccea358b46881"
+ integrity sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==
+ dependencies:
+ "@babel/core" "^7.13.16"
+ "@babel/parser" "^7.13.16"
+ "@babel/plugin-proposal-class-properties" "^7.13.0"
+ "@babel/plugin-proposal-nullish-coalescing-operator" "^7.13.8"
+ "@babel/plugin-proposal-optional-chaining" "^7.13.12"
+ "@babel/plugin-transform-modules-commonjs" "^7.13.8"
+ "@babel/preset-flow" "^7.13.13"
+ "@babel/preset-typescript" "^7.13.0"
+ "@babel/register" "^7.13.16"
+ babel-core "^7.0.0-bridge.0"
+ chalk "^4.1.2"
+ flow-parser "0.*"
+ graceful-fs "^4.2.4"
+ micromatch "^4.0.4"
+ neo-async "^2.5.0"
+ node-dir "^0.1.17"
+ recast "^0.21.0"
+ temp "^0.8.4"
+ write-file-atomic "^2.3.0"
+
+jsesc@^2.5.1:
+ version "2.5.2"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
+ integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+
+jsesc@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d"
+ integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==
+
+jsesc@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e"
+ integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==
+
+json-parse-better-errors@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
+ integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
+
+json-schema-deref-sync@^0.13.0:
+ version "0.13.0"
+ resolved "https://registry.yarnpkg.com/json-schema-deref-sync/-/json-schema-deref-sync-0.13.0.tgz#cb08b4ff435a48b5a149652d7750fdd071009823"
+ integrity sha512-YBOEogm5w9Op337yb6pAT6ZXDqlxAsQCanM3grid8lMWNxRJO/zWEJi3ZzqDL8boWfwhTFym5EFrNgWwpqcBRg==
+ dependencies:
+ clone "^2.1.2"
+ dag-map "~1.0.0"
+ is-valid-path "^0.1.1"
+ lodash "^4.17.13"
+ md5 "~2.2.0"
+ memory-cache "~0.2.0"
+ traverse "~0.6.6"
+ valid-url "~1.0.9"
+
+json-schema-traverse@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
+ integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+
+json-stable-stringify@^1.0.2:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.2.1.tgz#addb683c2b78014d0b78d704c2fcbdf0695a60e2"
+ integrity sha512-Lp6HbbBgosLmJbjx0pBLbgvx68FaFU1sdkmBuckmhhJ88kL13OA51CDtR2yJB50eCNMH9wRqtQNNiAqQH4YXnA==
+ dependencies:
+ call-bind "^1.0.8"
+ call-bound "^1.0.3"
+ isarray "^2.0.5"
+ jsonify "^0.0.1"
+ object-keys "^1.1.1"
+
+json5@^2.2.2, json5@^2.2.3:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
+ integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
+
+jsonfile@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+ integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
+jsonfile@^6.0.1:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
+ integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
+ dependencies:
+ universalify "^2.0.0"
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
+jsonify@^0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978"
+ integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==
+
+kind-of@^6.0.2:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
+ integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+
+klaw-sync@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c"
+ integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==
+ dependencies:
+ graceful-fs "^4.1.11"
+
+kleur@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
+ integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
+
+leven@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
+ integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
+
+lighthouse-logger@^1.0.0:
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz#aef90f9e97cd81db367c7634292ee22079280aaa"
+ integrity sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==
+ dependencies:
+ debug "^2.6.9"
+ marky "^1.2.2"
+
+lightningcss-darwin-arm64@1.19.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.19.0.tgz#56ab071e932f845dbb7667f44f5b78441175a343"
+ integrity sha512-wIJmFtYX0rXHsXHSr4+sC5clwblEMji7HHQ4Ub1/CznVRxtCFha6JIt5JZaNf8vQrfdZnBxLLC6R8pC818jXqg==
+
+lightningcss-darwin-x64@1.19.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.19.0.tgz#c867308b88859ba61a2c46c82b1ca52ff73a1bd0"
+ integrity sha512-Lif1wD6P4poaw9c/4Uh2z+gmrWhw/HtXFoeZ3bEsv6Ia4tt8rOJBdkfVaUJ6VXmpKHALve+iTyP2+50xY1wKPw==
+
+lightningcss-linux-arm-gnueabihf@1.19.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.19.0.tgz#0f921dc45f2e5c3aea70fab98844ac0e5f2f81be"
+ integrity sha512-P15VXY5682mTXaiDtbnLYQflc8BYb774j2R84FgDLJTN6Qp0ZjWEFyN1SPqyfTj2B2TFjRHRUvQSSZ7qN4Weig==
+
+lightningcss-linux-arm64-gnu@1.19.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.19.0.tgz#027f9df9c7f4ffa127c37a71726245a5794d7ba2"
+ integrity sha512-zwXRjWqpev8wqO0sv0M1aM1PpjHz6RVIsBcxKszIG83Befuh4yNysjgHVplF9RTU7eozGe3Ts7r6we1+Qkqsww==
+
+lightningcss-linux-arm64-musl@1.19.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.19.0.tgz#85ea987da868524eac6db94f8e1eaa23d0b688a3"
+ integrity sha512-vSCKO7SDnZaFN9zEloKSZM5/kC5gbzUjoJQ43BvUpyTFUX7ACs/mDfl2Eq6fdz2+uWhUh7vf92c4EaaP4udEtA==
+
+lightningcss-linux-x64-gnu@1.19.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.19.0.tgz#02bec89579ab4153dccc0def755d1fd9e3ee7f3c"
+ integrity sha512-0AFQKvVzXf9byrXUq9z0anMGLdZJS+XSDqidyijI5njIwj6MdbvX2UZK/c4FfNmeRa2N/8ngTffoIuOUit5eIQ==
+
+lightningcss-linux-x64-musl@1.19.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.19.0.tgz#e36a5df8193ae961d22974635e4c100a1823bb8c"
+ integrity sha512-SJoM8CLPt6ECCgSuWe+g0qo8dqQYVcPiW2s19dxkmSI5+Uu1GIRzyKA0b7QqmEXolA+oSJhQqCmJpzjY4CuZAg==
+
+lightningcss-win32-x64-msvc@1.19.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.19.0.tgz#0854dbd153035eca1396e2227c708ad43655a61c"
+ integrity sha512-C+VuUTeSUOAaBZZOPT7Etn/agx/MatzJzGRkeV+zEABmPuntv1zihncsi+AyGmjkkzq3wVedEy7h0/4S84mUtg==
+
+lightningcss@~1.19.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.19.0.tgz#fbbad0975de66252e38d96b5bdd2a62f2dd0ffbf"
+ integrity sha512-yV5UR7og+Og7lQC+70DA7a8ta1uiOPnWPJfxa0wnxylev5qfo4P+4iMpzWAdYWOca4jdNQZii+bDL/l+4hUXIA==
+ dependencies:
+ detect-libc "^1.0.3"
+ optionalDependencies:
+ lightningcss-darwin-arm64 "1.19.0"
+ lightningcss-darwin-x64 "1.19.0"
+ lightningcss-linux-arm-gnueabihf "1.19.0"
+ lightningcss-linux-arm64-gnu "1.19.0"
+ lightningcss-linux-arm64-musl "1.19.0"
+ lightningcss-linux-x64-gnu "1.19.0"
+ lightningcss-linux-x64-musl "1.19.0"
+ lightningcss-win32-x64-msvc "1.19.0"
+
+lilconfig@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
+ integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==
+
+lilconfig@^3.0.0:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4"
+ integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==
+
+lines-and-columns@^1.1.6:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
+ integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+
+load-bmfont@^1.3.1:
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.2.tgz#e0f4516064fa5be8439f9c3696c01423a64e8717"
+ integrity sha512-qElWkmjW9Oq1F9EI5Gt7aD9zcdHb9spJCW1L/dmPf7KzCCEJxq8nhHz5eCgI9aMf7vrG/wyaCqdsI+Iy9ZTlog==
+ 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"
+
+locate-path@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
+ integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+ dependencies:
+ p-locate "^3.0.0"
+ path-exists "^3.0.0"
+
+locate-path@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+ dependencies:
+ p-locate "^4.1.0"
+
+locate-path@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
+ integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+ dependencies:
+ p-locate "^5.0.0"
+
+lodash.debounce@4.0.8, lodash.debounce@^4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
+ integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
+
+lodash.throttle@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
+ integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==
+
+lodash@^4.17.10, lodash@^4.17.13, lodash@^4.17.20, lodash@^4.17.21:
+ version "4.17.21"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+ integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+
+log-symbols@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
+ integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
+ dependencies:
+ chalk "^2.0.1"
+
+log-symbols@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
+ integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
+ dependencies:
+ chalk "^4.1.0"
+ is-unicode-supported "^0.1.0"
+
+logkitty@^0.7.1:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/logkitty/-/logkitty-0.7.1.tgz#8e8d62f4085a826e8d38987722570234e33c6aa7"
+ integrity sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==
+ dependencies:
+ ansi-fragments "^0.2.1"
+ dayjs "^1.8.15"
+ yargs "^15.1.0"
+
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
+ integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
+ dependencies:
+ js-tokens "^3.0.0 || ^4.0.0"
+
+lru-cache@^10.0.1, lru-cache@^10.2.0:
+ version "10.4.3"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
+ integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
+
+lru-cache@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
+ integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
+ dependencies:
+ yallist "^3.0.2"
+
+lru-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ dependencies:
+ yallist "^4.0.0"
+
+make-dir@^2.0.0, make-dir@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
+ integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
+ dependencies:
+ pify "^4.0.1"
+ semver "^5.6.0"
+
+makeerror@1.0.12:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a"
+ integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==
+ dependencies:
+ tmpl "1.0.5"
+
+marky@^1.2.2:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.5.tgz#55796b688cbd72390d2d399eaaf1832c9413e3c0"
+ integrity sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==
+
+math-intrinsics@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
+ integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
+
+md5-file@^3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/md5-file/-/md5-file-3.2.3.tgz#f9bceb941eca2214a4c0727f5e700314e770f06f"
+ integrity sha512-3Tkp1piAHaworfcCgH0jKbTvj1jWWFgbvh2cXaNCgHwyTCBxxvD1Y04rmfpvdPm1P4oXMOpm6+2H7sr7v9v8Fw==
+ dependencies:
+ buffer-alloc "^1.1.0"
+
+md5@^2.2.1:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f"
+ integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==
+ dependencies:
+ charenc "0.0.2"
+ crypt "0.0.2"
+ is-buffer "~1.1.6"
+
+md5@~2.2.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9"
+ integrity sha512-PlGG4z5mBANDGCKsYQe0CaUYHdZYZt8ZPZLmEt+Urf0W4GlpTX4HescwHU+dc9+Z/G/vZKYZYFrwgm9VxK6QOQ==
+ dependencies:
+ charenc "~0.0.1"
+ crypt "~0.0.1"
+ is-buffer "~1.1.1"
+
+md5hex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/md5hex/-/md5hex-1.0.0.tgz#ed74b477a2ee9369f75efee2f08d5915e52a42e8"
+ integrity sha512-c2YOUbp33+6thdCUi34xIyOU/a7bvGKj/3DB1iaPMTuPHf/Q2d5s4sn1FaCOO43XkXggnb08y5W2PU8UNYNLKQ==
+
+mdn-data@2.0.14:
+ version "2.0.14"
+ resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
+ integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==
+
+memoize-one@^5.0.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
+ integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
+
+memoize-one@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045"
+ integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==
+
+memory-cache@~0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/memory-cache/-/memory-cache-0.2.0.tgz#7890b01d52c00c8ebc9d533e1f8eb17e3034871a"
+ integrity sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==
+
+merge-options@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-3.0.4.tgz#84709c2aa2a4b24c1981f66c179fe5565cc6dbb7"
+ integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==
+ dependencies:
+ is-plain-obj "^2.1.0"
+
+merge-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
+ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+
+merge2@^1.3.0, merge2@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+metro-babel-transformer@0.80.12:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.80.12.tgz#ad02ade921dd4ced27b26b18ff31eb60608e3f56"
+ integrity sha512-YZziRs0MgA3pzCkkvOoQRXjIoVjvrpi/yRlJnObyIvMP6lFdtyG4nUGIwGY9VXnBvxmXD6mPY2e+NSw6JAyiRg==
+ dependencies:
+ "@babel/core" "^7.20.0"
+ flow-enums-runtime "^0.0.6"
+ hermes-parser "0.23.1"
+ nullthrows "^1.1.1"
+
+metro-cache-key@0.80.12:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.80.12.tgz#52f5de698b85866503ace45d0ad76f75aaec92a4"
+ integrity sha512-o4BspKnugg/pE45ei0LGHVuBJXwRgruW7oSFAeSZvBKA/sGr0UhOGY3uycOgWInnS3v5yTTfiBA9lHlNRhsvGA==
+ dependencies:
+ flow-enums-runtime "^0.0.6"
+
+metro-cache@0.80.12:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.80.12.tgz#bd81af02c4f17b5aeab19bb030566b14147cee8b"
+ integrity sha512-p5kNHh2KJ0pbQI/H7ZBPCEwkyNcSz7OUkslzsiIWBMPQGFJ/xArMwkV7I+GJcWh+b4m6zbLxE5fk6fqbVK1xGA==
+ dependencies:
+ exponential-backoff "^3.1.1"
+ flow-enums-runtime "^0.0.6"
+ metro-core "0.80.12"
+
+metro-config@0.80.12, metro-config@^0.80.3:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.80.12.tgz#1543009f37f7ad26352ffc493fc6305d38bdf1c0"
+ integrity sha512-4rwOWwrhm62LjB12ytiuR5NgK1ZBNr24/He8mqCsC+HXZ+ATbrewLNztzbAZHtFsrxP4D4GLTGgh96pCpYLSAQ==
+ dependencies:
+ connect "^3.6.5"
+ cosmiconfig "^5.0.5"
+ flow-enums-runtime "^0.0.6"
+ jest-validate "^29.6.3"
+ metro "0.80.12"
+ metro-cache "0.80.12"
+ metro-core "0.80.12"
+ metro-runtime "0.80.12"
+
+metro-core@0.80.12, metro-core@^0.80.3:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.80.12.tgz#5ae337923ab19ff524077efa1aeacdf4480cfa28"
+ integrity sha512-QqdJ/yAK+IpPs2HU/h5v2pKEdANBagSsc6DRSjnwSyJsCoHlmyJKCaCJ7KhWGx+N4OHxh37hoA8fc2CuZbx0Fw==
+ dependencies:
+ flow-enums-runtime "^0.0.6"
+ lodash.throttle "^4.1.1"
+ metro-resolver "0.80.12"
+
+metro-file-map@0.80.12:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.80.12.tgz#b03240166a68aa16c5a168c26e190d9da547eefb"
+ integrity sha512-sYdemWSlk66bWzW2wp79kcPMzwuG32x1ZF3otI0QZTmrnTaaTiGyhE66P1z6KR4n2Eu5QXiABa6EWbAQv0r8bw==
+ dependencies:
+ anymatch "^3.0.3"
+ debug "^2.2.0"
+ fb-watchman "^2.0.0"
+ flow-enums-runtime "^0.0.6"
+ graceful-fs "^4.2.4"
+ invariant "^2.2.4"
+ jest-worker "^29.6.3"
+ micromatch "^4.0.4"
+ node-abort-controller "^3.1.1"
+ nullthrows "^1.1.1"
+ walker "^1.0.7"
+ optionalDependencies:
+ fsevents "^2.3.2"
+
+metro-minify-terser@0.80.12:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.80.12.tgz#9951030e3bc52d7f3ac8664ce5862401c673e3c6"
+ integrity sha512-muWzUw3y5k+9083ZoX9VaJLWEV2Jcgi+Oan0Mmb/fBNMPqP9xVDuy4pOMn/HOiGndgfh/MK7s4bsjkyLJKMnXQ==
+ dependencies:
+ flow-enums-runtime "^0.0.6"
+ terser "^5.15.0"
+
+metro-resolver@0.80.12:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.80.12.tgz#e3815914c21315b04db200032c3243a4cc22dfb6"
+ integrity sha512-PR24gYRZnYHM3xT9pg6BdbrGbM/Cu1TcyIFBVlAk7qDAuHkUNQ1nMzWumWs+kwSvtd9eZGzHoucGJpTUEeLZAw==
+ dependencies:
+ flow-enums-runtime "^0.0.6"
+
+metro-runtime@0.80.12, metro-runtime@^0.80.3:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.80.12.tgz#a68af3a2a013f5372d3b8cee234fdd467455550b"
+ integrity sha512-LIx7+92p5rpI0i6iB4S4GBvvLxStNt6fF0oPMaUd1Weku7jZdfkCZzmrtDD9CSQ6EPb0T9NUZoyXIxlBa3wOCw==
+ dependencies:
+ "@babel/runtime" "^7.25.0"
+ flow-enums-runtime "^0.0.6"
+
+metro-source-map@0.80.12, metro-source-map@^0.80.3:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.80.12.tgz#36a2768c880f8c459d6d758e2d0975e36479f49c"
+ integrity sha512-o+AXmE7hpvM8r8MKsx7TI21/eerYYy2DCDkWfoBkv+jNkl61khvDHlQn0cXZa6lrcNZiZkl9oHSMcwLLIrFmpw==
+ dependencies:
+ "@babel/traverse" "^7.20.0"
+ "@babel/types" "^7.20.0"
+ flow-enums-runtime "^0.0.6"
+ invariant "^2.2.4"
+ metro-symbolicate "0.80.12"
+ nullthrows "^1.1.1"
+ ob1 "0.80.12"
+ source-map "^0.5.6"
+ vlq "^1.0.0"
+
+metro-symbolicate@0.80.12:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.80.12.tgz#3a6aa783c6e494e2879342d88d5379fab69d1ed2"
+ integrity sha512-/dIpNdHksXkGHZXARZpL7doUzHqSNxgQ8+kQGxwpJuHnDhGkENxB5PS2QBaTDdEcmyTMjS53CN1rl9n1gR6fmw==
+ dependencies:
+ flow-enums-runtime "^0.0.6"
+ invariant "^2.2.4"
+ metro-source-map "0.80.12"
+ nullthrows "^1.1.1"
+ source-map "^0.5.6"
+ through2 "^2.0.1"
+ vlq "^1.0.0"
+
+metro-transform-plugins@0.80.12:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.80.12.tgz#4a3853630ad0f36cc2bffd53bae659ee171a389c"
+ integrity sha512-WQWp00AcZvXuQdbjQbx1LzFR31IInlkCDYJNRs6gtEtAyhwpMMlL2KcHmdY+wjDO9RPcliZ+Xl1riOuBecVlPA==
+ dependencies:
+ "@babel/core" "^7.20.0"
+ "@babel/generator" "^7.20.0"
+ "@babel/template" "^7.0.0"
+ "@babel/traverse" "^7.20.0"
+ flow-enums-runtime "^0.0.6"
+ nullthrows "^1.1.1"
+
+metro-transform-worker@0.80.12:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.80.12.tgz#80be8a185b7deb93402b682f58a1dd6724317ad1"
+ integrity sha512-KAPFN1y3eVqEbKLx1I8WOarHPqDMUa8WelWxaJCNKO/yHCP26zELeqTJvhsQup+8uwB6EYi/sp0b6TGoh6lOEA==
+ dependencies:
+ "@babel/core" "^7.20.0"
+ "@babel/generator" "^7.20.0"
+ "@babel/parser" "^7.20.0"
+ "@babel/types" "^7.20.0"
+ flow-enums-runtime "^0.0.6"
+ metro "0.80.12"
+ metro-babel-transformer "0.80.12"
+ metro-cache "0.80.12"
+ metro-cache-key "0.80.12"
+ metro-minify-terser "0.80.12"
+ metro-source-map "0.80.12"
+ metro-transform-plugins "0.80.12"
+ nullthrows "^1.1.1"
+
+metro@0.80.12, metro@^0.80.3:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/metro/-/metro-0.80.12.tgz#29a61fb83581a71e50c4d8d5d8458270edfe34cc"
+ integrity sha512-1UsH5FzJd9quUsD1qY+zUG4JY3jo3YEMxbMYH9jT6NK3j4iORhlwTK8fYTfAUBhDKjgLfKjAh7aoazNE23oIRA==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ "@babel/core" "^7.20.0"
+ "@babel/generator" "^7.20.0"
+ "@babel/parser" "^7.20.0"
+ "@babel/template" "^7.0.0"
+ "@babel/traverse" "^7.20.0"
+ "@babel/types" "^7.20.0"
+ accepts "^1.3.7"
+ chalk "^4.0.0"
+ ci-info "^2.0.0"
+ connect "^3.6.5"
+ debug "^2.2.0"
+ denodeify "^1.2.1"
+ error-stack-parser "^2.0.6"
+ flow-enums-runtime "^0.0.6"
+ graceful-fs "^4.2.4"
+ hermes-parser "0.23.1"
+ image-size "^1.0.2"
+ invariant "^2.2.4"
+ jest-worker "^29.6.3"
+ jsc-safe-url "^0.2.2"
+ lodash.throttle "^4.1.1"
+ metro-babel-transformer "0.80.12"
+ metro-cache "0.80.12"
+ metro-cache-key "0.80.12"
+ metro-config "0.80.12"
+ metro-core "0.80.12"
+ metro-file-map "0.80.12"
+ metro-resolver "0.80.12"
+ metro-runtime "0.80.12"
+ metro-source-map "0.80.12"
+ metro-symbolicate "0.80.12"
+ metro-transform-plugins "0.80.12"
+ metro-transform-worker "0.80.12"
+ mime-types "^2.1.27"
+ nullthrows "^1.1.1"
+ serialize-error "^2.1.0"
+ source-map "^0.5.6"
+ strip-ansi "^6.0.0"
+ throat "^5.0.0"
+ ws "^7.5.10"
+ yargs "^17.6.2"
+
+micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5, micromatch@^4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
+ integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
+ dependencies:
+ braces "^3.0.3"
+ picomatch "^2.3.1"
+
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+"mime-db@>= 1.43.0 < 2":
+ version "1.53.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447"
+ integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==
+
+mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.34:
+ version "2.1.35"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
+mime@1.6.0, mime@^1.3.4:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+ integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+
+mime@^2.4.1:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367"
+ integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==
+
+mimic-fn@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
+ integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
+
+mimic-fn@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+ integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+
+min-document@^2.19.0:
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
+ integrity sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==
+ dependencies:
+ dom-walk "^0.1.0"
+
+minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimatch@^9.0.4:
+ version "9.0.5"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5"
+ integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==
+ dependencies:
+ brace-expansion "^2.0.1"
+
+minimist@^1.2.0, minimist@^1.2.6:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+ integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
+minipass-collect@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-2.0.1.tgz#1621bc77e12258a12c60d34e2276ec5c20680863"
+ integrity sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==
+ dependencies:
+ minipass "^7.0.3"
+
+minipass-flush@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373"
+ integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==
+ dependencies:
+ minipass "^3.0.0"
+
+minipass-pipeline@^1.2.4:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c"
+ integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==
+ dependencies:
+ minipass "^3.0.0"
+
+minipass@^3.0.0:
+ version "3.3.6"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a"
+ integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==
+ dependencies:
+ yallist "^4.0.0"
+
+minipass@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d"
+ integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==
+
+"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.3, minipass@^7.1.2:
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707"
+ integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
+
+minizlib@^2.1.1:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
+ integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
+ dependencies:
+ minipass "^3.0.0"
+ yallist "^4.0.0"
+
+mkdirp@^0.5.1:
+ version "0.5.6"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
+ integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
+ dependencies:
+ minimist "^1.2.6"
+
+mkdirp@^1.0.3, mkdirp@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
+ integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
+
+mrmime@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27"
+ integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==
+
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+ integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
+
+ms@2.1.3, ms@^2.1.1, ms@^2.1.3:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+ integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+
+mz@^2.7.0:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
+ integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
+ dependencies:
+ any-promise "^1.0.0"
+ object-assign "^4.0.1"
+ thenify-all "^1.0.0"
+
+nanoid@^3.1.23, nanoid@^3.3.1, nanoid@^3.3.7, nanoid@^3.3.8:
+ version "3.3.8"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf"
+ integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==
+
+nativewind@^2.0.11:
+ version "2.0.11"
+ resolved "https://registry.yarnpkg.com/nativewind/-/nativewind-2.0.11.tgz#aaa80a65b663a49856b26bd4f3153161f70299d7"
+ integrity sha512-qCEXUwKW21RYJ33KRAJl3zXq2bCq82WoI564fI21D/TiqhfmstZOqPN53RF8qK1NDK6PGl56b2xaTxgObEePEg==
+ dependencies:
+ "@babel/generator" "^7.18.7"
+ "@babel/helper-module-imports" "7.18.6"
+ "@babel/types" "7.19.0"
+ css-mediaquery "^0.1.2"
+ css-to-react-native "^3.0.0"
+ micromatch "^4.0.5"
+ postcss "^8.4.12"
+ postcss-calc "^8.2.4"
+ postcss-color-functional-notation "^4.2.2"
+ postcss-css-variables "^0.18.0"
+ postcss-nested "^5.0.6"
+ react-is "^18.1.0"
+ use-sync-external-store "^1.1.0"
+
+negotiator@0.6.3:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
+ integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
+
+negotiator@~0.6.4:
+ version "0.6.4"
+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7"
+ integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==
+
+neo-async@^2.5.0:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
+ integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+
+nested-error-stacks@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz#d2cc9fc5235ddb371fc44d506234339c8e4b0a4b"
+ integrity sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A==
+
+nice-try@^1.0.4:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
+ integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+
+nocache@^3.0.1:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/nocache/-/nocache-3.0.4.tgz#5b37a56ec6e09fc7d401dceaed2eab40c8bfdf79"
+ integrity sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==
+
+node-abort-controller@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548"
+ integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==
+
+node-dir@^0.1.17:
+ version "0.1.17"
+ resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5"
+ integrity sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==
+ dependencies:
+ minimatch "^3.0.2"
+
+node-fetch@^2.2.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.7.0:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
+ integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
+ dependencies:
+ whatwg-url "^5.0.0"
+
+node-forge@^1, node-forge@^1.2.1, node-forge@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
+ integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
+
+node-int64@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
+ integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==
+
+node-releases@^2.0.19:
+ version "2.0.19"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314"
+ integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==
+
+node-stream-zip@^1.9.1:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.15.0.tgz#158adb88ed8004c6c49a396b50a6a5de3bca33ea"
+ integrity sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==
+
+node-vibrant@3.1.6:
+ version "3.1.6"
+ resolved "https://registry.yarnpkg.com/node-vibrant/-/node-vibrant-3.1.6.tgz#8554c3108903232cbe1e722f928469ee4379aa18"
+ integrity sha512-Wlc/hQmBMOu6xon12ZJHS2N3M+I6J8DhrD3Yo6m5175v8sFkVIN+UjhKVRcO+fqvre89ASTpmiFEP3nPO13SwA==
+ dependencies:
+ "@jimp/custom" "^0.16.1"
+ "@jimp/plugin-resize" "^0.16.1"
+ "@jimp/types" "^0.16.1"
+ "@types/lodash" "^4.14.53"
+ "@types/node" "^10.11.7"
+ lodash "^4.17.20"
+ url "^0.11.0"
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+npm-package-arg@^11.0.0:
+ version "11.0.3"
+ resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-11.0.3.tgz#dae0c21199a99feca39ee4bfb074df3adac87e2d"
+ integrity sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==
+ dependencies:
+ hosted-git-info "^7.0.0"
+ proc-log "^4.0.0"
+ semver "^7.3.5"
+ validate-npm-package-name "^5.0.0"
+
+npm-package-arg@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-7.0.0.tgz#52cdf08b491c0c59df687c4c925a89102ef794a5"
+ integrity sha512-xXxr8y5U0kl8dVkz2oK7yZjPBvqM2fwaO5l3Yg13p03v8+E3qQcD0JNhHzjL1vyGgxcKkD0cco+NLR72iuPk3g==
+ dependencies:
+ hosted-git-info "^3.0.2"
+ osenv "^0.1.5"
+ semver "^5.6.0"
+ validate-npm-package-name "^3.0.0"
+
+npm-run-path@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
+ integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==
+ dependencies:
+ path-key "^2.0.0"
+
+npm-run-path@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
+ integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
+ dependencies:
+ path-key "^3.0.0"
+
+nth-check@^2.0.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
+ integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==
+ dependencies:
+ boolbase "^1.0.0"
+
+nullthrows@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1"
+ integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==
+
+ob1@0.80.12:
+ version "0.80.12"
+ resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.80.12.tgz#0451944ba6e5be225cc9751d8cd0d7309d2d1537"
+ integrity sha512-VMArClVT6LkhUGpnuEoBuyjG9rzUyEzg4PDkav6wK1cLhOK02gPCYFxoiB4mqVnrMhDpIzJcrGNAMVi9P+hXrw==
+ dependencies:
+ flow-enums-runtime "^0.0.6"
+
+object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+ integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
+
+object-hash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
+ integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
+
+object-inspect@^1.13.3:
+ version "1.13.3"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a"
+ integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==
+
+object-is@^1.1.5:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07"
+ integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+
+object-keys@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
+ integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
+
+object.assign@^4.1.4, object.assign@^4.1.7:
+ version "4.1.7"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d"
+ integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==
+ dependencies:
+ call-bind "^1.0.8"
+ call-bound "^1.0.3"
+ define-properties "^1.2.1"
+ es-object-atoms "^1.0.0"
+ has-symbols "^1.1.0"
+ object-keys "^1.1.1"
+
+omggif@^1.0.10, omggif@^1.0.9:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19"
+ integrity sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==
+
+on-finished@2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
+ integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
+ dependencies:
+ ee-first "1.1.1"
+
+on-finished@~2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
+ integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==
+ dependencies:
+ ee-first "1.1.1"
+
+on-headers@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
+ integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
+
+once@^1.3.0, once@^1.3.1, once@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+ dependencies:
+ wrappy "1"
+
+onetime@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
+ integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==
+ dependencies:
+ mimic-fn "^1.0.0"
+
+onetime@^5.1.0, onetime@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
+ integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
+ dependencies:
+ mimic-fn "^2.1.0"
+
+open@^6.2.0:
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9"
+ integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==
+ dependencies:
+ is-wsl "^1.1.0"
+
+open@^7.0.3, open@^7.4.2:
+ version "7.4.2"
+ resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321"
+ integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==
+ dependencies:
+ is-docker "^2.0.0"
+ is-wsl "^2.1.1"
+
+open@^8.0.4, open@^8.3.0:
+ version "8.4.2"
+ resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9"
+ integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==
+ dependencies:
+ define-lazy-prop "^2.0.0"
+ is-docker "^2.1.1"
+ is-wsl "^2.2.0"
+
+ora@3.4.0, ora@^3.4.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318"
+ integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==
+ 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"
+
+ora@^5.4.1:
+ version "5.4.1"
+ resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18"
+ integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==
+ 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"
+
+os-homedir@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+ integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==
+
+os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+ integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
+
+osenv@^0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
+ integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
+ dependencies:
+ os-homedir "^1.0.0"
+ os-tmpdir "^1.0.0"
+
+own-keys@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358"
+ integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==
+ dependencies:
+ get-intrinsic "^1.2.6"
+ object-keys "^1.1.1"
+ safe-push-apply "^1.0.0"
+
+p-finally@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
+ integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==
+
+p-limit@^2.0.0, p-limit@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+ dependencies:
+ p-try "^2.0.0"
+
+p-limit@^3.0.2, p-limit@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+ integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+ dependencies:
+ yocto-queue "^0.1.0"
+
+p-locate@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
+ integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+ dependencies:
+ p-limit "^2.0.0"
+
+p-locate@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+ dependencies:
+ p-limit "^2.2.0"
+
+p-locate@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
+ integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+ dependencies:
+ p-limit "^3.0.2"
+
+p-map@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
+ integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
+ dependencies:
+ aggregate-error "^3.0.0"
+
+p-try@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+package-json-from-dist@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505"
+ integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==
+
+pako@^1.0.5:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
+ integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
+
+parse-bmfont-ascii@^1.0.3:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz#11ac3c3ff58f7c2020ab22769079108d4dfa0285"
+ integrity sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==
+
+parse-bmfont-binary@^1.0.5:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz#d038b476d3e9dd9db1e11a0b0e53a22792b69006"
+ integrity sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==
+
+parse-bmfont-xml@^1.1.4:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz#016b655da7aebe6da38c906aca16bf0415773767"
+ integrity sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==
+ dependencies:
+ xml-parse-from-string "^1.0.0"
+ xml2js "^0.5.0"
+
+parse-headers@^2.0.0:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9"
+ integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==
+
+parse-json@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
+ integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==
+ dependencies:
+ error-ex "^1.3.1"
+ json-parse-better-errors "^1.0.1"
+
+parse-png@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/parse-png/-/parse-png-2.1.0.tgz#2a42ad719fedf90f81c59ebee7ae59b280d6b338"
+ integrity sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==
+ dependencies:
+ pngjs "^3.3.0"
+
+parseurl@~1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
+ integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
+
+password-prompt@^1.0.4:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/password-prompt/-/password-prompt-1.1.3.tgz#05e539f4e7ca4d6c865d479313f10eb9db63ee5f"
+ integrity sha512-HkrjG2aJlvF0t2BMH0e2LB/EHf3Lcq3fNMzy4GYHcQblAvOl+QQji1Lx7WRBMqpVK8p+KR7bCg7oqAMXtdgqyw==
+ dependencies:
+ ansi-escapes "^4.3.2"
+ cross-spawn "^7.0.3"
+
+patch-package@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-8.0.0.tgz#d191e2f1b6e06a4624a0116bcb88edd6714ede61"
+ integrity sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==
+ 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"
+
+path-exists@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+ integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==
+
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
+
+path-key@^2.0.0, path-key@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
+ integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==
+
+path-key@^3.0.0, path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+path-parse@^1.0.5, path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+path-scurry@^1.11.1:
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2"
+ integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==
+ dependencies:
+ lru-cache "^10.2.0"
+ minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
+
+path-type@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
+peek-readable@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-4.1.0.tgz#4ece1111bf5c2ad8867c314c81356847e8a62e72"
+ integrity sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==
+
+phin@^2.9.1:
+ version "2.9.3"
+ resolved "https://registry.yarnpkg.com/phin/-/phin-2.9.3.tgz#f9b6ac10a035636fb65dfc576aaaa17b8743125c"
+ integrity sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==
+
+phin@^3.7.1:
+ version "3.7.1"
+ resolved "https://registry.yarnpkg.com/phin/-/phin-3.7.1.tgz#bf841da75ee91286691b10e41522a662aa628fd6"
+ integrity sha512-GEazpTWwTZaEQ9RhL7Nyz0WwqilbqgLahDM3D0hxWwmVDI52nXEybHqiN6/elwpkJBhcuj+WbBu+QfT0uhPGfQ==
+ dependencies:
+ centra "^2.7.0"
+
+picocolors@^1.0.0, picocolors@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
+ integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
+
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+picomatch@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-3.0.1.tgz#817033161def55ec9638567a2f3bbc876b3e7516"
+ integrity sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==
+
+pify@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+ integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
+
+pify@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
+ integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
+
+pirates@^4.0.1, pirates@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
+ integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==
+
+pixelmatch@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-4.0.2.tgz#8f47dcec5011b477b67db03c243bc1f3085e8854"
+ integrity sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==
+ dependencies:
+ pngjs "^3.0.0"
+
+pkg-dir@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
+ integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==
+ dependencies:
+ find-up "^3.0.0"
+
+plist@^3.0.5:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/plist/-/plist-3.1.0.tgz#797a516a93e62f5bde55e0b9cc9c967f860893c9"
+ integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==
+ dependencies:
+ "@xmldom/xmldom" "^0.8.8"
+ base64-js "^1.5.1"
+ xmlbuilder "^15.1.1"
+
+pngjs@^3.0.0, pngjs@^3.3.0, pngjs@^3.3.3:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
+ integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==
+
+possible-typed-array-names@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f"
+ integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==
+
+postcss-calc@^8.2.4:
+ version "8.2.4"
+ resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5"
+ integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==
+ dependencies:
+ postcss-selector-parser "^6.0.9"
+ postcss-value-parser "^4.2.0"
+
+postcss-color-functional-notation@^4.2.2:
+ version "4.2.4"
+ resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz#21a909e8d7454d3612d1659e471ce4696f28caec"
+ integrity sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-css-variables@^0.18.0:
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/postcss-css-variables/-/postcss-css-variables-0.18.0.tgz#d97b6da19e86245eb817006e11117382f997bb93"
+ integrity sha512-lYS802gHbzn1GI+lXvy9MYIYDuGnl1WB4FTKoqMQqJ3Mab09A7a/1wZvGTkCEZJTM8mSbIyb1mJYn8f0aPye0Q==
+ dependencies:
+ balanced-match "^1.0.0"
+ escape-string-regexp "^1.0.3"
+ extend "^3.0.1"
+
+postcss-import@^15.1.0:
+ version "15.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70"
+ integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==
+ dependencies:
+ postcss-value-parser "^4.0.0"
+ read-cache "^1.0.0"
+ resolve "^1.1.7"
+
+postcss-js@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2"
+ integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==
+ dependencies:
+ camelcase-css "^2.0.1"
+
+postcss-load-config@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3"
+ integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==
+ dependencies:
+ lilconfig "^3.0.0"
+ yaml "^2.3.4"
+
+postcss-nested@^5.0.6:
+ version "5.0.6"
+ resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-5.0.6.tgz#466343f7fc8d3d46af3e7dba3fcd47d052a945bc"
+ integrity sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==
+ dependencies:
+ postcss-selector-parser "^6.0.6"
+
+postcss-nested@^6.0.1:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.2.0.tgz#4c2d22ab5f20b9cb61e2c5c5915950784d068131"
+ integrity sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==
+ dependencies:
+ postcss-selector-parser "^6.1.1"
+
+postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9, postcss-selector-parser@^6.1.1:
+ version "6.1.2"
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz#27ecb41fb0e3b6ba7a1ec84fff347f734c7929de"
+ integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==
+ dependencies:
+ cssesc "^3.0.0"
+ util-deprecate "^1.0.2"
+
+postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
+ integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
+
+postcss@^8.4.12, postcss@^8.4.23:
+ version "8.5.1"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.1.tgz#e2272a1f8a807fafa413218245630b5db10a3214"
+ integrity sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==
+ dependencies:
+ nanoid "^3.3.8"
+ picocolors "^1.1.1"
+ source-map-js "^1.2.1"
+
+postcss@~8.4.32:
+ version "8.4.49"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.49.tgz#4ea479048ab059ab3ae61d082190fabfd994fe19"
+ integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==
+ dependencies:
+ nanoid "^3.3.7"
+ picocolors "^1.1.1"
+ source-map-js "^1.2.1"
+
+postinstall-postinstall@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3"
+ integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ==
+
+pretty-bytes@5.6.0:
+ version "5.6.0"
+ resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
+ integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==
+
+pretty-format@^24:
+ version "24.9.0"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9"
+ integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==
+ dependencies:
+ "@jest/types" "^24.9.0"
+ ansi-regex "^4.0.0"
+ ansi-styles "^3.2.0"
+ react-is "^16.8.4"
+
+pretty-format@^26.5.2, pretty-format@^26.6.2:
+ version "26.6.2"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93"
+ integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==
+ dependencies:
+ "@jest/types" "^26.6.2"
+ ansi-regex "^5.0.0"
+ ansi-styles "^4.0.0"
+ react-is "^17.0.1"
+
+pretty-format@^29.0.0, pretty-format@^29.7.0:
+ version "29.7.0"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812"
+ integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==
+ dependencies:
+ "@jest/schemas" "^29.6.3"
+ ansi-styles "^5.0.0"
+ react-is "^18.0.0"
+
+proc-log@^4.0.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-4.2.0.tgz#b6f461e4026e75fdfe228b265e9f7a00779d7034"
+ integrity sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==
+
+process-nextick-args@~2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
+ integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
+
+process@^0.11.10:
+ version "0.11.10"
+ resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
+ integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
+
+progress@2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
+ integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
+
+promise@^7.1.1:
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
+ integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
+ dependencies:
+ asap "~2.0.3"
+
+promise@^8.3.0:
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a"
+ integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==
+ dependencies:
+ asap "~2.0.6"
+
+prompts@^2.3.2, prompts@^2.4.2:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
+ integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
+ dependencies:
+ kleur "^3.0.3"
+ sisteransi "^1.0.5"
+
+prop-types@15.8.1, prop-types@^15.7.2, prop-types@^15.8.1:
+ version "15.8.1"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
+ integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
+ dependencies:
+ loose-envify "^1.4.0"
+ object-assign "^4.1.1"
+ react-is "^16.13.1"
+
+proxy-from-env@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
+ integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
+
+pump@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.2.tgz#836f3edd6bc2ee599256c924ffe0d88573ddcbf8"
+ integrity sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==
+ dependencies:
+ end-of-stream "^1.1.0"
+ once "^1.3.1"
+
+punycode@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+ integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==
+
+punycode@^2.1.0, punycode@^2.1.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
+ integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
+
+qrcode-terminal@0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz#ffc6c28a2fc0bfb47052b47e23f4f446a5fbdb9e"
+ integrity sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==
+
+qs@^6.12.3:
+ version "6.14.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930"
+ integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==
+ dependencies:
+ side-channel "^1.1.0"
+
+query-string@^7.1.3:
+ version "7.1.3"
+ resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328"
+ integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==
+ dependencies:
+ decode-uri-component "^0.2.2"
+ filter-obj "^1.1.0"
+ split-on-first "^1.0.0"
+ strict-uri-encode "^2.0.0"
+
+querystring@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd"
+ integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==
+
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+queue@6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65"
+ integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==
+ dependencies:
+ inherits "~2.0.3"
+
+range-parser@~1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
+ integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
+
+rc@~1.2.7:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
+ integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
+ dependencies:
+ deep-extend "^0.6.0"
+ ini "~1.3.0"
+ minimist "^1.2.0"
+ strip-json-comments "~2.0.1"
+
+react-devtools-core@^5.0.0:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-5.3.2.tgz#d5df92f8ef2a587986d094ef2c47d84cf4ae46ec"
+ integrity sha512-crr9HkVrDiJ0A4zot89oS0Cgv0Oa4OG1Em4jit3P3ZxZSKPMYyMjfwMqgcJna9o625g8oN87rBm8SWWrSTBZxg==
+ dependencies:
+ shell-quote "^1.6.1"
+ ws "^7"
+
+react-dom@18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
+ integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
+ dependencies:
+ loose-envify "^1.1.0"
+ scheduler "^0.23.0"
+
+react-fast-compare@^3.2.2:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49"
+ integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==
+
+react-freeze@^1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/react-freeze/-/react-freeze-1.0.4.tgz#cbbea2762b0368b05cbe407ddc9d518c57c6f3ad"
+ integrity sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA==
+
+react-i18next@^15.4.0:
+ version "15.4.0"
+ resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.4.0.tgz#87c755fb6d7a567eec134e4759b022a0baacb19e"
+ integrity sha512-Py6UkX3zV08RTvL6ZANRoBh9sL/ne6rQq79XlkHEdd82cZr2H9usbWpUNVadJntIZP2pu3M2rL1CN+5rQYfYFw==
+ dependencies:
+ "@babel/runtime" "^7.25.0"
+ html-parse-stringify "^3.0.1"
+
+"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.1.0, react-is@^18.2.0:
+ version "18.3.1"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
+ integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
+
+react-is@^16.13.0, react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.4:
+ version "16.13.1"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
+ integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+
+react-is@^17.0.1:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
+ integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
+
+react-native-awesome-slider@^2.5.6:
+ version "2.9.0"
+ resolved "https://registry.yarnpkg.com/react-native-awesome-slider/-/react-native-awesome-slider-2.9.0.tgz#7d5013a0e0e15ed84d59b4fa4c26a8b7ab9b2454"
+ integrity sha512-sc5qgX4YtM6IxjtosjgQLdsal120MvU+YWs0F2MdgQWijps22AXLDCUoBnZZ8vxVhVyJ2WnnIPrmtVBvVJjSuQ==
+
+react-native-bottom-tabs@0.8.3:
+ version "0.8.3"
+ resolved "https://registry.yarnpkg.com/react-native-bottom-tabs/-/react-native-bottom-tabs-0.8.3.tgz#4712bf0c740d1fe65a79c598c22255f248ec2b90"
+ integrity sha512-00+2Ehiblhb9/+bZ7P2bN9I5JN9TqemTU1ANbD+EG0LCes2O98aMGQAWuO7jZ/wg7MZAc+/UVHvLWe4LoX7ntw==
+ dependencies:
+ sf-symbols-typescript "^2.0.0"
+ use-latest-callback "^0.2.1"
+
+react-native-circular-progress@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/react-native-circular-progress/-/react-native-circular-progress-1.4.1.tgz#46d94e73e5973bb415937b912ba56ce1947f66b7"
+ integrity sha512-HEzvI0WPuWvsCgWE3Ff2HBTMgAEQB2GvTFw0KHyD/t1STAlDDRiolu0mEGhVvihKR3jJu3v3V4qzvSklY/7XzQ==
+ dependencies:
+ prop-types "^15.8.1"
+
+react-native-compressor@^1.9.0:
+ version "1.10.3"
+ resolved "https://registry.yarnpkg.com/react-native-compressor/-/react-native-compressor-1.10.3.tgz#4e44fa8395de17fd6dc63c074e5a8c2ef06b80a1"
+ integrity sha512-i51DfTwfLcKorWbTXtnPOcQC4SQDuC+DqKkSl9wF9qAUmNS9PtipYZCXOvWShYFnX0mmcWw5vwEp2b2V73PaDQ==
+
+react-native-country-flag@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/react-native-country-flag/-/react-native-country-flag-2.0.2.tgz#ef22a6017f3118aaeae23c0409663c18e49241bd"
+ integrity sha512-5LMWxS79ZQ0Q9ntYgDYzWp794+HcQGXQmzzZNBR1AT7z5HcJHtX7rlk8RHi7RVzfp5gW6plWSZ4dKjRpu/OafQ==
+
+react-native-device-info@^14.0.1:
+ version "14.0.2"
+ resolved "https://registry.yarnpkg.com/react-native-device-info/-/react-native-device-info-14.0.2.tgz#cb583e283eba4e54f56c9c548dae89a96ccf39ab"
+ integrity sha512-W1oqu4dC4uLKT/Z4uimRP6birJprWjhMP/AwV9hxGSZ5K3wJ/yb34aQ22sd6HmegQHfT2PmkFs3mj+4uXLE1YQ==
+
+react-native-edge-to-edge@^1.1.3:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/react-native-edge-to-edge/-/react-native-edge-to-edge-1.4.3.tgz#755c77f9bee94392166a7bdf46618886b54e0c77"
+ integrity sha512-fYchwiQ2D/8NzcvJK1sD9Cm25GFQfsLgYmGpohoSpRxwBwR5UCL0wUf4scoQgYncRh9Hmc2t8ml/sikTwMM3ng==
+
+react-native-gesture-handler@~2.16.1:
+ version "2.16.2"
+ resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-2.16.2.tgz#032bd2a07334292d7f6cff1dc9d1ec928f72e26d"
+ integrity sha512-vGFlrDKlmyI+BT+FemqVxmvO7nqxU33cgXVsn6IKAFishvlG3oV2Ds67D5nPkHMea8T+s1IcuMm0bF8ntZtAyg==
+ dependencies:
+ "@egjs/hammerjs" "^2.0.17"
+ hoist-non-react-statics "^3.3.0"
+ invariant "^2.2.4"
+ lodash "^4.17.21"
+ prop-types "^15.7.2"
+
+react-native-get-random-values@^1.11.0:
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/react-native-get-random-values/-/react-native-get-random-values-1.11.0.tgz#1ca70d1271f4b08af92958803b89dccbda78728d"
+ integrity sha512-4BTbDbRmS7iPdhYLRcz3PGFIpFJBwNZg9g42iwa2P6FOv9vZj/xJc678RZXnLNZzd0qd7Q3CCF6Yd+CU2eoXKQ==
+ dependencies:
+ fast-base64-decode "^1.0.0"
+
+react-native-google-cast@^4.8.3:
+ version "4.8.3"
+ resolved "https://registry.yarnpkg.com/react-native-google-cast/-/react-native-google-cast-4.8.3.tgz#b7572972add806f44f44267a5079e343472766bf"
+ integrity sha512-2s/dBr+YYSXYTo7Btx9Az9yOPjnr2GQ8GWU+qDXMsHijrYDafe9uIj7RWFFmx7cL/4RSICx1RwC3vUkHSqaWEA==
+
+react-native-helmet-async@2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/react-native-helmet-async/-/react-native-helmet-async-2.0.4.tgz#93f53a1ff22d6898039688a541653a2d6b6866bb"
+ integrity sha512-m3CkXWss6B1dd6mCMleLpzDCJJGGaHOLQsUzZv8kAASJmMfmVT4d2fx375iXKTRWT25ThBfae3dECuX5cq/8hg==
+ dependencies:
+ invariant "^2.2.4"
+ react-fast-compare "^3.2.2"
+ shallowequal "^1.1.0"
+
+react-native-image-colors@^2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/react-native-image-colors/-/react-native-image-colors-2.4.0.tgz#6af1d5fe0e994331de789c1fa33788971f755aec"
+ integrity sha512-qlC31+UNVthByNLVuYSEQeZghOXn3uy1GLF6lHKlvT1HM1GGFH/LXNhU8iXAoQvUyzNa1bEAOTo09Hwinvp/rA==
+ dependencies:
+ node-vibrant "3.1.6"
+
+react-native-ios-context-menu@^2.5.2:
+ version "2.5.3"
+ resolved "https://registry.yarnpkg.com/react-native-ios-context-menu/-/react-native-ios-context-menu-2.5.3.tgz#3e65a6cee50e95a71766ad3ebc3920015eb02318"
+ integrity sha512-RMztfU71XiLuxnmf/eE4/ez6FT4dzFAzrsHEA0+QmMfaQMHjpyEHTfLJvvM++9gygBvLZmHuc/rQgzQzH7ETug==
+ dependencies:
+ "@dominicstop/ts-event-emitter" "^1.1.0"
+
+react-native-ios-utilities@4.5.3:
+ version "4.5.3"
+ resolved "https://registry.yarnpkg.com/react-native-ios-utilities/-/react-native-ios-utilities-4.5.3.tgz#5af77955147b60f2a3a519fcd36d9e28493d84b9"
+ integrity sha512-bw+bIGMC9tA2GRrQYFyQedV4PWYwgfcX8Lw0puILEeO9uExTbtftYEaj78tgMRpYxwiztjtOlR+rC1Lo93CstA==
+
+react-native-mmkv@^2.12.2:
+ version "2.12.2"
+ resolved "https://registry.yarnpkg.com/react-native-mmkv/-/react-native-mmkv-2.12.2.tgz#4bba0f5f04e2cf222494cce3a9794ba6a4894dee"
+ integrity sha512-6058Aq0p57chPrUutLGe9fYoiDVDNMU2PKV+lLFUJ3GhoHvUrLdsS1PDSCLr00yqzL4WJQ7TTzH+V8cpyrNcfg==
+
+react-native-pager-view@6.3.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-6.3.0.tgz#7e734e84b1692f877591335373f6fd92f0d67aa6"
+ integrity sha512-ufJOoVa9pFL1J/yb4hpsCqp8n1qTlcF5VvwqvCacHX//D7hSeRscsiIXg1u1pXNWwllvACb+mqxec/3Uj2mxrA==
+
+react-native-progress@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/react-native-progress/-/react-native-progress-5.0.1.tgz#4e15258b5661c49bad74554352326ca540bb7c58"
+ integrity sha512-TYfJ4auAe5vubDma2yfFvt7ktSI+UCfysqJnkdHEcLXqAitRFOozgF/cLgN5VNi/iLdaf3ga1ETi2RF4jVZ/+g==
+ dependencies:
+ prop-types "^15.7.2"
+
+react-native-reanimated-carousel@4.0.0-canary.22:
+ version "4.0.0-canary.22"
+ resolved "https://registry.yarnpkg.com/react-native-reanimated-carousel/-/react-native-reanimated-carousel-4.0.0-canary.22.tgz#4fa530548bf330184b252eabd2d95dc02eb31f28"
+ integrity sha512-GOTSXVuoV08ZUxGPuzQ1Kl1YOOOrKWb18uRlPsa759bFyiqFWpjjLrCUdfgBgF9ZqUHUbb1jj+UffFf2eGDz+A==
+
+react-native-reanimated@~3.10.1:
+ version "3.10.1"
+ resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz#3c37d1100bbba0065df39c96aab0c1ff1b50c0fa"
+ integrity sha512-sfxg6vYphrDc/g4jf/7iJ7NRi+26z2+BszPmvmk0Vnrz6FL7HYljJqTf531F1x6tFmsf+FEAmuCtTUIXFLVo9w==
+ dependencies:
+ "@babel/plugin-transform-arrow-functions" "^7.0.0-0"
+ "@babel/plugin-transform-nullish-coalescing-operator" "^7.0.0-0"
+ "@babel/plugin-transform-optional-chaining" "^7.0.0-0"
+ "@babel/plugin-transform-shorthand-properties" "^7.0.0-0"
+ "@babel/plugin-transform-template-literals" "^7.0.0-0"
+ "@babel/preset-typescript" "^7.16.7"
+ convert-source-map "^2.0.0"
+ invariant "^2.2.4"
+
+react-native-safe-area-context@4.10.5:
+ version "4.10.5"
+ resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.10.5.tgz#a9c677a48bd273afa6876772062ce08e8af1f18d"
+ integrity sha512-Wyb0Nqw2XJ6oZxW/cK8k5q7/UAhg/wbEG6UVf89rQqecDZTDA5ic//P9J6VvJRVZerzGmxWQpVuM7f+PRYUM4g==
+
+react-native-screens@3.31.1:
+ version "3.31.1"
+ resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-3.31.1.tgz#909a890f669e32b0fb1b1410278b71ad2f8238f6"
+ integrity sha512-8fRW362pfZ9y4rS8KY5P3DFScrmwo/vu1RrRMMx0PNHbeC9TLq0Kw1ubD83591yz64gLNHFLTVkTJmWeWCXKtQ==
+ dependencies:
+ react-freeze "^1.0.0"
+ warn-once "^0.1.0"
+
+react-native-svg@15.2.0:
+ version "15.2.0"
+ resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-15.2.0.tgz#9561a6b3bd6b44689f437ba13182afee33bd5557"
+ integrity sha512-R0E6IhcJfVLsL0lRmnUSm72QO+mTqcAOM5Jb8FVGxJqX3NfJMlMP0YyvcajZiaRR8CqQUpEoqrY25eyZb006kw==
+ dependencies:
+ css-select "^5.1.0"
+ css-tree "^1.1.3"
+
+react-native-tab-view@^3.5.2:
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-3.5.2.tgz#2789b8af6148b16835869566bf13dc3b0e6c1b46"
+ integrity sha512-nE5WqjbeEPsWQx4mtz81QGVvgHRhujTNIIZiMCx3Bj6CBFDafbk7XZp9ocmtzXUQaZ4bhtVS43R4FIiR4LboJw==
+ dependencies:
+ use-latest-callback "^0.1.5"
+
+react-native-udp@^4.1.7:
+ version "4.1.7"
+ resolved "https://registry.yarnpkg.com/react-native-udp/-/react-native-udp-4.1.7.tgz#9fa90b772b44c991605e8191444dd2ca3259cb58"
+ integrity sha512-NUE3zewu61NCdSsLlj+l0ad6qojcVEZPT4hVG/x6DU9U4iCzwtfZSASh9vm7teAcVzLkdD+cO3411LHshAi/wA==
+ dependencies:
+ buffer "^5.6.0"
+ events "^3.1.0"
+
+react-native-uitextview@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/react-native-uitextview/-/react-native-uitextview-1.4.0.tgz#d1b583cc173cec00f4fdd03744cca76c54a12fbb"
+ integrity sha512-itm/frzkn/ma3+lwmKn2CkBOXPNo4bL8iVwQwjlzix5gVO59T2+axdfoj/Wi+Ra6F76KzNKxSah+7Y8dYmCHbQ==
+
+react-native-url-polyfill@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/react-native-url-polyfill/-/react-native-url-polyfill-2.0.0.tgz#db714520a2985cff1d50ab2e66279b9f91ffd589"
+ integrity sha512-My330Do7/DvKnEvwQc0WdcBnFPploYKp9CYlefDXzIdEaA+PAhDYllkvGeEroEzvc4Kzzj2O4yVdz8v6fjRvhA==
+ dependencies:
+ whatwg-url-without-unicode "8.0.0-3"
+
+react-native-uuid@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/react-native-uuid/-/react-native-uuid-2.0.3.tgz#f85f8a8d68e52e3f1c18ba0f02ec7776f9d4a0da"
+ integrity sha512-f/YfIS2f5UB+gut7t/9BKGSCYbRA9/74A5R1MDp+FLYsuS+OSWoiM/D8Jko6OJB6Jcu3v6ONuddvZKHdIGpeiw==
+
+react-native-video@^6.7.0:
+ version "6.10.0"
+ resolved "https://registry.yarnpkg.com/react-native-video/-/react-native-video-6.10.0.tgz#35ac89761c2ffde9234ca65456db9f62342ca930"
+ integrity sha512-NyDnpSBRJkj7TxMku2dEys54qKynW/l9kSPCVvayyqXWrc24cxHhLvAaxORdJDb6tS4FhUbR8tFIoOY65/XKZg==
+
+react-native-volume-manager@^1.10.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/react-native-volume-manager/-/react-native-volume-manager-1.10.0.tgz#4e73d284b31cf3b9b41df7c8ce9115454ad3e0af"
+ integrity sha512-MJbUyXCEz5q2GDJoOImvVZ+aC39mdxqvD6ZYVXPBuhbdhoThOIDZoaVAf+vC7H8ahGToLtNWVfcbgds8zzgHAg==
+
+react-native-web@~0.19.13:
+ version "0.19.13"
+ resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.19.13.tgz#2d84849bf0251ec0e3a8072fda7f9a7c29375331"
+ integrity sha512-etv3bN8rJglrRCp/uL4p7l8QvUNUC++QwDbdZ8CB7BvZiMvsxfFIRM1j04vxNldG3uo2puRd6OSWR3ibtmc29A==
+ dependencies:
+ "@babel/runtime" "^7.18.6"
+ "@react-native/normalize-colors" "^0.74.1"
+ fbjs "^3.0.4"
+ inline-style-prefixer "^6.0.1"
+ memoize-one "^6.0.0"
+ nullthrows "^1.1.1"
+ postcss-value-parser "^4.2.0"
+ styleq "^0.1.3"
+
+react-native-webview@13.8.6:
+ version "13.8.6"
+ resolved "https://registry.yarnpkg.com/react-native-webview/-/react-native-webview-13.8.6.tgz#5d4a62cb311d5ef8d910a8e112b3f1f2807bcd18"
+ integrity sha512-jtZ9OgB2AN6rhDwto6dNL3PtOtl/SI4VN93pZEPbMLvRjqHfxiUrilGllL5fKAXq5Ry5FJyfUi82A4Ii8olZ7A==
+ dependencies:
+ escape-string-regexp "2.0.0"
+ invariant "2.2.4"
+
+react-native@0.74.5:
+ version "0.74.5"
+ resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.74.5.tgz#80e556690fc2583d46714d5618ecd30d93c24e81"
+ integrity sha512-Bgg2WvxaGODukJMTZFTZBNMKVaROHLwSb8VAGEdrlvKwfb1hHg/3aXTUICYk7dwgAnb+INbGMwnF8yeAgIUmqw==
+ dependencies:
+ "@jest/create-cache-key-function" "^29.6.3"
+ "@react-native-community/cli" "13.6.9"
+ "@react-native-community/cli-platform-android" "13.6.9"
+ "@react-native-community/cli-platform-ios" "13.6.9"
+ "@react-native/assets-registry" "0.74.87"
+ "@react-native/codegen" "0.74.87"
+ "@react-native/community-cli-plugin" "0.74.87"
+ "@react-native/gradle-plugin" "0.74.87"
+ "@react-native/js-polyfills" "0.74.87"
+ "@react-native/normalize-colors" "0.74.87"
+ "@react-native/virtualized-lists" "0.74.87"
+ abort-controller "^3.0.0"
+ anser "^1.4.9"
+ ansi-regex "^5.0.0"
+ base64-js "^1.5.1"
+ chalk "^4.0.0"
+ event-target-shim "^5.0.1"
+ flow-enums-runtime "^0.0.6"
+ invariant "^2.2.4"
+ jest-environment-node "^29.6.3"
+ jsc-android "^250231.0.0"
+ memoize-one "^5.0.0"
+ metro-runtime "^0.80.3"
+ metro-source-map "^0.80.3"
+ mkdirp "^0.5.1"
+ nullthrows "^1.1.1"
+ pretty-format "^26.5.2"
+ promise "^8.3.0"
+ react-devtools-core "^5.0.0"
+ react-refresh "^0.14.0"
+ react-shallow-renderer "^16.15.0"
+ regenerator-runtime "^0.13.2"
+ scheduler "0.24.0-canary-efb381bbf-20230505"
+ stacktrace-parser "^0.1.10"
+ whatwg-fetch "^3.0.0"
+ ws "^6.2.2"
+ yargs "^17.6.2"
+
+react-refresh@^0.14.0, react-refresh@^0.14.2:
+ version "0.14.2"
+ resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9"
+ integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==
+
+react-remove-scroll-bar@^2.3.7:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223"
+ integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==
+ dependencies:
+ react-style-singleton "^2.2.2"
+ tslib "^2.0.0"
+
+react-remove-scroll@^2.6.2:
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz#df02cde56d5f2731e058531f8ffd7f9adec91ac2"
+ integrity sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==
+ dependencies:
+ react-remove-scroll-bar "^2.3.7"
+ react-style-singleton "^2.2.3"
+ tslib "^2.1.0"
+ use-callback-ref "^1.3.3"
+ use-sidecar "^1.1.3"
+
+react-shallow-renderer@^16.15.0:
+ version "16.15.0"
+ resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz#48fb2cf9b23d23cde96708fe5273a7d3446f4457"
+ integrity sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==
+ dependencies:
+ object-assign "^4.1.1"
+ react-is "^16.12.0 || ^17.0.0 || ^18.0.0"
+
+react-style-singleton@^2.2.2, react-style-singleton@^2.2.3:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388"
+ integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==
+ dependencies:
+ get-nonce "^1.0.0"
+ tslib "^2.0.0"
+
+react-test-renderer@18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-18.2.0.tgz#1dd912bd908ff26da5b9fca4fd1c489b9523d37e"
+ integrity sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==
+ dependencies:
+ react-is "^18.2.0"
+ react-shallow-renderer "^16.15.0"
+ scheduler "^0.23.0"
+
+react@18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
+ integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
+ dependencies:
+ loose-envify "^1.1.0"
+
+read-cache@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
+ integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==
+ dependencies:
+ pify "^2.3.0"
+
+readable-stream@^3.4.0, readable-stream@^3.6.0:
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
+ integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
+ dependencies:
+ inherits "^2.0.3"
+ string_decoder "^1.1.1"
+ util-deprecate "^1.0.1"
+
+readable-stream@~2.3.6:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
+ integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~2.0.0"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.1.1"
+ util-deprecate "~1.0.1"
+
+readable-web-to-node-stream@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz#5d52bb5df7b54861fd48d015e93a2cb87b3ee0bb"
+ integrity sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==
+ dependencies:
+ readable-stream "^3.6.0"
+
+readdirp@~3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+ integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+ dependencies:
+ picomatch "^2.2.1"
+
+readline@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c"
+ integrity sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==
+
+recast@^0.21.0:
+ version "0.21.5"
+ resolved "https://registry.yarnpkg.com/recast/-/recast-0.21.5.tgz#e8cd22bb51bcd6130e54f87955d33a2b2e57b495"
+ integrity sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==
+ dependencies:
+ ast-types "0.15.2"
+ esprima "~4.0.0"
+ source-map "~0.6.1"
+ tslib "^2.0.1"
+
+recyclerlistview@4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/recyclerlistview/-/recyclerlistview-4.2.0.tgz#a140149aaa470c9787a1426452651934240d69ef"
+ integrity sha512-uuBCi0c+ggqHKwrzPX4Z/mJOzsBbjZEAwGGmlwpD/sD7raXixdAbdJ6BTcAmuWG50Cg4ru9p12M94Njwhr/27A==
+ dependencies:
+ lodash.debounce "4.0.8"
+ prop-types "15.8.1"
+ ts-object-utils "0.0.5"
+
+reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9"
+ integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==
+ dependencies:
+ call-bind "^1.0.8"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.9"
+ es-errors "^1.3.0"
+ es-object-atoms "^1.0.0"
+ get-intrinsic "^1.2.7"
+ get-proto "^1.0.1"
+ which-builtin-type "^1.2.1"
+
+regenerate-unicode-properties@^10.2.0:
+ version "10.2.0"
+ resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz#626e39df8c372338ea9b8028d1f99dc3fd9c3db0"
+ integrity sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==
+ dependencies:
+ regenerate "^1.4.2"
+
+regenerate@^1.4.2:
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
+ integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
+
+regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.3:
+ version "0.13.11"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
+ integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
+
+regenerator-runtime@^0.14.0:
+ version "0.14.1"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
+ integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
+
+regexp.prototype.flags@^1.5.3:
+ version "1.5.4"
+ resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz#1ad6c62d44a259007e55b3970e00f746efbcaa19"
+ integrity sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==
+ dependencies:
+ call-bind "^1.0.8"
+ define-properties "^1.2.1"
+ es-errors "^1.3.0"
+ get-proto "^1.0.1"
+ gopd "^1.2.0"
+ set-function-name "^2.0.2"
+
+regexpu-core@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.2.0.tgz#0e5190d79e542bf294955dccabae04d3c7d53826"
+ integrity sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==
+ dependencies:
+ regenerate "^1.4.2"
+ regenerate-unicode-properties "^10.2.0"
+ regjsgen "^0.8.0"
+ regjsparser "^0.12.0"
+ unicode-match-property-ecmascript "^2.0.0"
+ unicode-match-property-value-ecmascript "^2.1.0"
+
+regjsgen@^0.8.0:
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.8.0.tgz#df23ff26e0c5b300a6470cad160a9d090c3a37ab"
+ integrity sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==
+
+regjsparser@^0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.12.0.tgz#0e846df6c6530586429377de56e0475583b088dc"
+ integrity sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==
+ dependencies:
+ jsesc "~3.0.2"
+
+remove-trailing-slash@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/remove-trailing-slash/-/remove-trailing-slash-0.1.1.tgz#be2285a59f39c74d1bce4f825950061915e3780d"
+ integrity sha512-o4S4Qh6L2jpnCy83ysZDau+VORNvnFw07CKSAymkd6ICNVEPisMyzlc00KlvvicsxKck94SEwhDnMNdICzO+tA==
+
+require-directory@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+ integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
+
+require-from-string@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
+ integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+
+require-main-filename@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
+ integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+
+requireg@^0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/requireg/-/requireg-0.2.2.tgz#437e77a5316a54c9bcdbbf5d1f755fe093089830"
+ integrity sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg==
+ dependencies:
+ nested-error-stacks "~2.0.1"
+ rc "~1.2.7"
+ resolve "~1.7.1"
+
+resolve-from@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
+ integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==
+
+resolve-from@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
+ integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+
+resolve-workspace-root@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-workspace-root/-/resolve-workspace-root-2.0.0.tgz#a0098daa0067cd0efa6eb525c57c8fb4a61e78f8"
+ integrity sha512-IsaBUZETJD5WsI11Wt8PKHwaIe45or6pwNc8yflvLJ4DWtImK9kuLoH5kUva/2Mmx/RdIyr4aONNSa2v9LTJsw==
+
+resolve.exports@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.3.tgz#41955e6f1b4013b7586f873749a635dea07ebe3f"
+ integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==
+
+resolve@^1.1.7, resolve@^1.14.2, resolve@^1.22.2:
+ version "1.22.10"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39"
+ integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==
+ dependencies:
+ is-core-module "^2.16.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+resolve@~1.7.1:
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3"
+ integrity sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==
+ dependencies:
+ path-parse "^1.0.5"
+
+restore-cursor@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
+ integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==
+ dependencies:
+ onetime "^2.0.0"
+ signal-exit "^3.0.2"
+
+restore-cursor@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
+ integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
+ dependencies:
+ onetime "^5.1.0"
+ signal-exit "^3.0.2"
+
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+rimraf@^2.6.3:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
+ integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
+ dependencies:
+ glob "^7.1.3"
+
+rimraf@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
+ integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
+ dependencies:
+ glob "^7.1.3"
+
+rimraf@~2.6.2:
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
+ integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
+ dependencies:
+ glob "^7.1.3"
+
+rtl-detect@^1.0.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.1.2.tgz#ca7f0330af5c6bb626c15675c642ba85ad6273c6"
+ integrity sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==
+
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
+safe-array-concat@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3"
+ integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==
+ dependencies:
+ call-bind "^1.0.8"
+ call-bound "^1.0.2"
+ get-intrinsic "^1.2.6"
+ has-symbols "^1.1.0"
+ isarray "^2.0.5"
+
+safe-buffer@5.2.1, safe-buffer@~5.2.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+ integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+safe-push-apply@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5"
+ integrity sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==
+ dependencies:
+ es-errors "^1.3.0"
+ isarray "^2.0.5"
+
+safe-regex-test@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1"
+ integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==
+ dependencies:
+ call-bound "^1.0.2"
+ es-errors "^1.3.0"
+ is-regex "^1.2.1"
+
+sax@>=0.6.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f"
+ integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==
+
+scheduler@0.24.0-canary-efb381bbf-20230505:
+ version "0.24.0-canary-efb381bbf-20230505"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz#5dddc60e29f91cd7f8b983d7ce4a99c2202d178f"
+ integrity sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==
+ dependencies:
+ loose-envify "^1.1.0"
+
+scheduler@^0.23.0:
+ version "0.23.2"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3"
+ integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==
+ dependencies:
+ loose-envify "^1.1.0"
+
+schema-utils@^4.0.1:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.0.tgz#3b669f04f71ff2dfb5aba7ce2d5a9d79b35622c0"
+ integrity sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==
+ dependencies:
+ "@types/json-schema" "^7.0.9"
+ ajv "^8.9.0"
+ ajv-formats "^2.1.1"
+ ajv-keywords "^5.1.0"
+
+selfsigned@^2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0"
+ integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==
+ dependencies:
+ "@types/node-forge" "^1.3.0"
+ node-forge "^1"
+
+semver@^5.5.0, semver@^5.6.0:
+ version "5.7.2"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
+ integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
+
+semver@^6.3.1:
+ version "6.3.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
+ integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
+
+semver@^7.3.5, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0:
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.0.tgz#9c6fe61d0c6f9fa9e26575162ee5a9180361b09c"
+ integrity sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==
+
+send@0.19.0:
+ version "0.19.0"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8"
+ integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==
+ dependencies:
+ debug "2.6.9"
+ depd "2.0.0"
+ destroy "1.2.0"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ mime "1.6.0"
+ ms "2.1.3"
+ on-finished "2.4.1"
+ range-parser "~1.2.1"
+ statuses "2.0.1"
+
+send@^0.18.0:
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
+ integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
+ dependencies:
+ debug "2.6.9"
+ depd "2.0.0"
+ destroy "1.2.0"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ mime "1.6.0"
+ ms "2.1.3"
+ on-finished "2.4.1"
+ range-parser "~1.2.1"
+ statuses "2.0.1"
+
+serialize-error@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a"
+ integrity sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==
+
+serve-static@^1.13.1:
+ version "1.16.2"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296"
+ integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==
+ dependencies:
+ encodeurl "~2.0.0"
+ escape-html "~1.0.3"
+ parseurl "~1.3.3"
+ send "0.19.0"
+
+set-blocking@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+ integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==
+
+set-cookie-parser@^2.4.8:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943"
+ integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==
+
+set-function-length@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
+ integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==
+ dependencies:
+ define-data-property "^1.1.4"
+ es-errors "^1.3.0"
+ function-bind "^1.1.2"
+ get-intrinsic "^1.2.4"
+ gopd "^1.0.1"
+ has-property-descriptors "^1.0.2"
+
+set-function-name@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985"
+ integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==
+ dependencies:
+ define-data-property "^1.1.4"
+ es-errors "^1.3.0"
+ functions-have-names "^1.2.3"
+ has-property-descriptors "^1.0.2"
+
+set-proto@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/set-proto/-/set-proto-1.0.0.tgz#0760dbcff30b2d7e801fd6e19983e56da337565e"
+ integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==
+ dependencies:
+ dunder-proto "^1.0.1"
+ es-errors "^1.3.0"
+ es-object-atoms "^1.0.0"
+
+setimmediate@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
+ integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==
+
+setprototypeof@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
+ integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
+
+sf-symbols-typescript@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/sf-symbols-typescript/-/sf-symbols-typescript-2.1.0.tgz#50a2d7b36edd6809606f0b0a36322fc1fdd7cfde"
+ integrity sha512-ezT7gu/SHTPIOEEoG6TF+O0m5eewl0ZDAO4AtdBi5HjsrUI6JdCG17+Q8+aKp0heM06wZKApRCn5olNbs0Wb/A==
+
+shallow-clone@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
+ integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
+ dependencies:
+ kind-of "^6.0.2"
+
+shallowequal@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
+ integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
+
+shebang-command@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+ integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==
+ dependencies:
+ shebang-regex "^1.0.0"
+
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
+shebang-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
+ integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==
+
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+shell-quote@^1.6.1, shell-quote@^1.7.3:
+ version "1.8.2"
+ resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.2.tgz#d2d83e057959d53ec261311e9e9b8f51dcb2934a"
+ integrity sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==
+
+side-channel-list@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad"
+ integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==
+ dependencies:
+ es-errors "^1.3.0"
+ object-inspect "^1.13.3"
+
+side-channel-map@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42"
+ integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==
+ dependencies:
+ call-bound "^1.0.2"
+ es-errors "^1.3.0"
+ get-intrinsic "^1.2.5"
+ object-inspect "^1.13.3"
+
+side-channel-weakmap@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea"
+ integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==
+ dependencies:
+ call-bound "^1.0.2"
+ es-errors "^1.3.0"
+ get-intrinsic "^1.2.5"
+ object-inspect "^1.13.3"
+ side-channel-map "^1.0.1"
+
+side-channel@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9"
+ integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==
+ dependencies:
+ es-errors "^1.3.0"
+ object-inspect "^1.13.3"
+ side-channel-list "^1.0.0"
+ side-channel-map "^1.0.1"
+ side-channel-weakmap "^1.0.2"
+
+signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
+ integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
+
+signal-exit@^4.0.1:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
+ integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
+
+simple-plist@^1.1.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-1.3.1.tgz#16e1d8f62c6c9b691b8383127663d834112fb017"
+ integrity sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==
+ dependencies:
+ bplist-creator "0.1.0"
+ bplist-parser "0.3.1"
+ plist "^3.0.5"
+
+simple-swizzle@^0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
+ integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==
+ dependencies:
+ is-arrayish "^0.3.1"
+
+sisteransi@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
+ integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
+
+slash@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
+ integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
+
+slash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+slice-ansi@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"
+ integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==
+ dependencies:
+ ansi-styles "^3.2.0"
+ astral-regex "^1.0.0"
+ is-fullwidth-code-point "^2.0.0"
+
+slugify@^1.3.4, slugify@^1.6.6:
+ version "1.6.6"
+ resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.6.6.tgz#2d4ac0eacb47add6af9e04d3be79319cbcc7924b"
+ integrity sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==
+
+sonner-native@^0.14.2:
+ version "0.14.2"
+ resolved "https://registry.yarnpkg.com/sonner-native/-/sonner-native-0.14.2.tgz#f13ba9c9c98580be374a8dba1f1556250627b65d"
+ integrity sha512-4zcHBGLQIV/2u6I7zcEHXpBoyCkpRax1BuHlFvcCEc3qPc+qTZykAOlsCijoOGQ2chUsmXFhB6Ux3M3CaCRZew==
+
+source-map-js@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
+ integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
+
+source-map-support@^0.5.16, source-map-support@^0.5.21, source-map-support@~0.5.20, source-map-support@~0.5.21:
+ version "0.5.21"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
+ integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
+ dependencies:
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
+
+source-map@^0.5.0, source-map@^0.5.6:
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+ integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
+
+source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+source-map@^0.7.3:
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656"
+ integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==
+
+split-on-first@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
+ integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
+
+split@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
+ integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==
+ dependencies:
+ through "2"
+
+sprintf-js@~1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+ integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==
+
+ssri@^10.0.0:
+ version "10.0.6"
+ resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.6.tgz#a8aade2de60ba2bce8688e3fa349bad05c7dc1e5"
+ integrity sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==
+ dependencies:
+ minipass "^7.0.3"
+
+stack-utils@^2.0.3:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f"
+ integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==
+ dependencies:
+ escape-string-regexp "^2.0.0"
+
+stackframe@^1.3.4:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310"
+ integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==
+
+stacktrace-parser@^0.1.10:
+ version "0.1.10"
+ resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a"
+ integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==
+ dependencies:
+ type-fest "^0.7.1"
+
+statuses@2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
+ integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
+
+statuses@~1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
+ integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
+
+stream-buffers@2.2.x, stream-buffers@~2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4"
+ integrity sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==
+
+stream-slice@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/stream-slice/-/stream-slice-0.1.2.tgz#2dc4f4e1b936fb13f3eb39a2def1932798d07a4b"
+ integrity sha512-QzQxpoacatkreL6jsxnVb7X5R/pGw9OUv2qWTYWnmLpg4NdN31snPy/f3TdQE1ZUXaThRvj1Zw4/OGg0ZkaLMA==
+
+strict-uri-encode@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
+ integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==
+
+"string-width-cjs@npm:string-width@^4.2.0":
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+string-width@^5.0.1, string-width@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
+ integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
+ dependencies:
+ eastasianwidth "^0.2.0"
+ emoji-regex "^9.2.2"
+ strip-ansi "^7.0.1"
+
+string.prototype.trim@^1.2.10:
+ version "1.2.10"
+ resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81"
+ integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==
+ dependencies:
+ call-bind "^1.0.8"
+ call-bound "^1.0.2"
+ define-data-property "^1.1.4"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.5"
+ es-object-atoms "^1.0.0"
+ has-property-descriptors "^1.0.2"
+
+string.prototype.trimend@^1.0.9:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942"
+ integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==
+ dependencies:
+ call-bind "^1.0.8"
+ call-bound "^1.0.2"
+ define-properties "^1.2.1"
+ es-object-atoms "^1.0.0"
+
+string.prototype.trimstart@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde"
+ integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-object-atoms "^1.0.0"
+
+string_decoder@^1.1.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
+ integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
+ dependencies:
+ safe-buffer "~5.2.0"
+
+string_decoder@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+ integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+ dependencies:
+ safe-buffer "~5.1.0"
+
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+strip-ansi@^5.0.0, strip-ansi@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
+ integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
+ dependencies:
+ ansi-regex "^4.1.0"
+
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+strip-ansi@^7.0.1:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
+ integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
+ dependencies:
+ ansi-regex "^6.0.1"
+
+strip-eof@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
+ integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==
+
+strip-final-newline@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
+ integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
+
+strip-json-comments@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+ integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==
+
+strnum@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db"
+ integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==
+
+strtok3@^6.2.4:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-6.3.0.tgz#358b80ffe6d5d5620e19a073aa78ce947a90f9a0"
+ integrity sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==
+ dependencies:
+ "@tokenizer/token" "^0.3.0"
+ peek-readable "^4.1.0"
+
+structured-headers@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/structured-headers/-/structured-headers-0.4.1.tgz#77abd9410622c6926261c09b9d16cf10592694d1"
+ integrity sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==
+
+styleq@^0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/styleq/-/styleq-0.1.3.tgz#8efb2892debd51ce7b31dc09c227ad920decab71"
+ integrity sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA==
+
+sucrase@3.34.0:
+ version "3.34.0"
+ resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.34.0.tgz#1e0e2d8fcf07f8b9c3569067d92fbd8690fb576f"
+ integrity sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.2"
+ commander "^4.0.0"
+ glob "7.1.6"
+ lines-and-columns "^1.1.6"
+ mz "^2.7.0"
+ pirates "^4.0.1"
+ ts-interface-checker "^0.1.9"
+
+sucrase@^3.32.0:
+ version "3.35.0"
+ resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263"
+ integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.2"
+ commander "^4.0.0"
+ glob "^10.3.10"
+ lines-and-columns "^1.1.6"
+ mz "^2.7.0"
+ pirates "^4.0.1"
+ ts-interface-checker "^0.1.9"
+
+sudo-prompt@9.1.1:
+ version "9.1.1"
+ resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.1.1.tgz#73853d729770392caec029e2470db9c221754db0"
+ integrity sha512-es33J1g2HjMpyAhz8lOR+ICmXXAqTuKbuXuUWLhOLew20oN9oUCgCJx615U/v7aioZg7IX5lIh9x34vwneu4pA==
+
+sudo-prompt@^8.2.0:
+ version "8.2.5"
+ resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-8.2.5.tgz#cc5ef3769a134bb94b24a631cc09628d4d53603e"
+ integrity sha512-rlBo3HU/1zAJUrkY6jNxDOC9eVYliG6nS4JA8u8KAshITd07tafMc/Br7xQwCSseXwJ2iCcHCE8SNWX3q8Z+kw==
+
+sudo-prompt@^9.0.0:
+ version "9.2.1"
+ resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.2.1.tgz#77efb84309c9ca489527a4e749f287e6bdd52afd"
+ integrity sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==
+
+supports-color@^5.3.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+ integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+ dependencies:
+ has-flag "^3.0.0"
+
+supports-color@^7.0.0, supports-color@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-color@^8.0.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
+ integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-hyperlinks@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624"
+ integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==
+ dependencies:
+ has-flag "^4.0.0"
+ supports-color "^7.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+tailwindcss@3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.2.tgz#2f9e35d715fdf0bbf674d90147a0684d7054a2d3"
+ integrity sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==
+ dependencies:
+ "@alloc/quick-lru" "^5.2.0"
+ arg "^5.0.2"
+ chokidar "^3.5.3"
+ didyoumean "^1.2.2"
+ dlv "^1.1.3"
+ fast-glob "^3.2.12"
+ glob-parent "^6.0.2"
+ is-glob "^4.0.3"
+ jiti "^1.18.2"
+ lilconfig "^2.1.0"
+ micromatch "^4.0.5"
+ normalize-path "^3.0.0"
+ object-hash "^3.0.0"
+ picocolors "^1.0.0"
+ postcss "^8.4.23"
+ postcss-import "^15.1.0"
+ postcss-js "^4.0.1"
+ postcss-load-config "^4.0.1"
+ postcss-nested "^6.0.1"
+ postcss-selector-parser "^6.0.11"
+ postcss-value-parser "^4.2.0"
+ resolve "^1.22.2"
+ sucrase "^3.32.0"
+
+tar@^6.0.5, tar@^6.1.11:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a"
+ integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==
+ dependencies:
+ chownr "^2.0.0"
+ fs-minipass "^2.0.0"
+ minipass "^5.0.0"
+ minizlib "^2.1.1"
+ mkdirp "^1.0.3"
+ yallist "^4.0.0"
+
+temp-dir@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d"
+ integrity sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==
+
+temp-dir@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e"
+ integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==
+
+temp@^0.8.4:
+ version "0.8.4"
+ resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.4.tgz#8c97a33a4770072e0a05f919396c7665a7dd59f2"
+ integrity sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==
+ dependencies:
+ rimraf "~2.6.2"
+
+tempy@0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.3.0.tgz#6f6c5b295695a16130996ad5ab01a8bd726e8bf8"
+ integrity sha512-WrH/pui8YCwmeiAoxV+lpRH9HpRtgBhSR2ViBPgpGb/wnYDzp21R4MN45fsCGvLROvY67o3byhJRYRONJyImVQ==
+ dependencies:
+ temp-dir "^1.0.0"
+ type-fest "^0.3.1"
+ unique-string "^1.0.0"
+
+tempy@^0.7.1:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.7.1.tgz#5a654e6dbd1747cdd561efb112350b55cd9c1d46"
+ integrity sha512-vXPxwOyaNVi9nyczO16mxmHGpl6ASC5/TVhRRHpqeYHvKQm58EaWNvZXxAhR0lYYnBOQFjXjhzeLsaXdjxLjRg==
+ dependencies:
+ del "^6.0.0"
+ is-stream "^2.0.0"
+ temp-dir "^2.0.0"
+ type-fest "^0.16.0"
+ unique-string "^2.0.0"
+
+terminal-link@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994"
+ integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==
+ dependencies:
+ ansi-escapes "^4.2.1"
+ supports-hyperlinks "^2.0.0"
+
+terser@^5.15.0:
+ version "5.37.0"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-5.37.0.tgz#38aa66d1cfc43d0638fab54e43ff8a4f72a21ba3"
+ integrity sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==
+ dependencies:
+ "@jridgewell/source-map" "^0.3.3"
+ acorn "^8.8.2"
+ commander "^2.20.0"
+ source-map-support "~0.5.20"
+
+text-table@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+ integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
+
+thenify-all@^1.0.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
+ integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==
+ dependencies:
+ thenify ">= 3.1.0 < 4"
+
+"thenify@>= 3.1.0 < 4":
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f"
+ integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
+ dependencies:
+ any-promise "^1.0.0"
+
+throat@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b"
+ integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==
+
+through2@^2.0.1:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
+ integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
+ dependencies:
+ readable-stream "~2.3.6"
+ xtend "~4.0.1"
+
+through@2:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+ integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
+
+timm@^1.6.1:
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/timm/-/timm-1.7.1.tgz#96bab60c7d45b5a10a8a4d0f0117c6b7e5aff76f"
+ integrity sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==
+
+tinycolor2@^1.4.1:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e"
+ integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==
+
+tmp@^0.0.33:
+ version "0.0.33"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+ integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
+ dependencies:
+ os-tmpdir "~1.0.2"
+
+tmpl@1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
+ integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
+
+to-fast-properties@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+ integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+toidentifier@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
+ integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
+
+token-types@^4.1.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/token-types/-/token-types-4.2.1.tgz#0f897f03665846982806e138977dbe72d44df753"
+ integrity sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==
+ dependencies:
+ "@tokenizer/token" "^0.3.0"
+ ieee754 "^1.2.1"
+
+tr46@~0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
+ integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
+
+traverse@~0.6.6:
+ version "0.6.11"
+ resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.11.tgz#e8daa071b101ae66767fffa6f177aa6f7110068e"
+ integrity sha512-vxXDZg8/+p3gblxB6BhhG5yWVn1kGRlaL8O78UDXc3wRnPizB5g83dcvWV1jpDMIPnjZjOFuxlMmE82XJ4407w==
+ dependencies:
+ gopd "^1.2.0"
+ typedarray.prototype.slice "^1.0.5"
+ which-typed-array "^1.1.18"
+
+trim-right@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
+ integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==
+
+ts-interface-checker@^0.1.9:
+ version "0.1.13"
+ resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
+ integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
+
+ts-object-utils@0.0.5:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/ts-object-utils/-/ts-object-utils-0.0.5.tgz#95361cdecd7e52167cfc5e634c76345e90a26077"
+ integrity sha512-iV0GvHqOmilbIKJsfyfJY9/dNHCs969z3so90dQWsO1eMMozvTpnB1MEaUbb3FYtZTGjv5sIy/xmslEz0Rg2TA==
+
+tslib@2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
+ integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
+
+tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0:
+ version "2.8.1"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
+ integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
+
+turbo-stream@2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/turbo-stream/-/turbo-stream-2.4.0.tgz#1e4fca6725e90fa14ac4adb782f2d3759a5695f0"
+ integrity sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==
+
+type-detect@4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
+ integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
+
+type-fest@^0.16.0:
+ version "0.16.0"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.16.0.tgz#3240b891a78b0deae910dbeb86553e552a148860"
+ integrity sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==
+
+type-fest@^0.21.3:
+ version "0.21.3"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
+ integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
+
+type-fest@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1"
+ integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==
+
+type-fest@^0.7.1:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48"
+ integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==
+
+typed-array-buffer@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536"
+ integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==
+ dependencies:
+ call-bound "^1.0.3"
+ es-errors "^1.3.0"
+ is-typed-array "^1.1.14"
+
+typed-array-byte-length@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz#8407a04f7d78684f3d252aa1a143d2b77b4160ce"
+ integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==
+ dependencies:
+ call-bind "^1.0.8"
+ for-each "^0.3.3"
+ gopd "^1.2.0"
+ has-proto "^1.2.0"
+ is-typed-array "^1.1.14"
+
+typed-array-byte-offset@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz#ae3698b8ec91a8ab945016108aef00d5bff12355"
+ integrity sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==
+ dependencies:
+ available-typed-arrays "^1.0.7"
+ call-bind "^1.0.8"
+ for-each "^0.3.3"
+ gopd "^1.2.0"
+ has-proto "^1.2.0"
+ is-typed-array "^1.1.15"
+ reflect.getprototypeof "^1.0.9"
+
+typed-array-length@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d"
+ integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==
+ dependencies:
+ call-bind "^1.0.7"
+ for-each "^0.3.3"
+ gopd "^1.0.1"
+ is-typed-array "^1.1.13"
+ possible-typed-array-names "^1.0.0"
+ reflect.getprototypeof "^1.0.6"
+
+typedarray.prototype.slice@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/typedarray.prototype.slice/-/typedarray.prototype.slice-1.0.5.tgz#a40f896968573b33cbb466a61622d3ee615a0728"
+ integrity sha512-q7QNVDGTdl702bVFiI5eY4l/HkgCM6at9KhcFbgUAzezHFbOVy4+0O/lCjsABEQwbZPravVfBIiBVGo89yzHFg==
+ dependencies:
+ call-bind "^1.0.8"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.9"
+ es-errors "^1.3.0"
+ get-proto "^1.0.1"
+ math-intrinsics "^1.1.0"
+ typed-array-buffer "^1.0.3"
+ typed-array-byte-offset "^1.0.4"
+
+typescript@~5.3.3:
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
+ integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
+
+ua-parser-js@^0.7.33:
+ version "0.7.40"
+ resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.40.tgz#c87d83b7bb25822ecfa6397a0da5903934ea1562"
+ integrity sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ==
+
+ua-parser-js@^1.0.35:
+ version "1.0.40"
+ resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.40.tgz#ac6aff4fd8ea3e794a6aa743ec9c2fc29e75b675"
+ integrity sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==
+
+unbox-primitive@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2"
+ integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==
+ dependencies:
+ call-bound "^1.0.3"
+ has-bigints "^1.0.2"
+ has-symbols "^1.1.0"
+ which-boxed-primitive "^1.1.1"
+
+undici-types@~5.26.4:
+ version "5.26.5"
+ resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
+ integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
+
+undici-types@~6.20.0:
+ version "6.20.0"
+ resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"
+ integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==
+
+undici@^6.11.1:
+ version "6.21.1"
+ resolved "https://registry.yarnpkg.com/undici/-/undici-6.21.1.tgz#336025a14162e6837e44ad7b819b35b6c6af0e05"
+ integrity sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==
+
+unicode-canonical-property-names-ecmascript@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz#cb3173fe47ca743e228216e4a3ddc4c84d628cc2"
+ integrity sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==
+
+unicode-match-property-ecmascript@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3"
+ integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==
+ dependencies:
+ unicode-canonical-property-names-ecmascript "^2.0.0"
+ unicode-property-aliases-ecmascript "^2.0.0"
+
+unicode-match-property-value-ecmascript@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz#a0401aee72714598f739b68b104e4fe3a0cb3c71"
+ integrity sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==
+
+unicode-property-aliases-ecmascript@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd"
+ integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==
+
+unimodules-app-loader@~4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/unimodules-app-loader/-/unimodules-app-loader-4.6.0.tgz#8836040b3acbf605fc4c2c6f6feb6dd9084ea0d4"
+ integrity sha512-FRNIlx7sLBDVPG117JnEBhnzZkTIgZTEwYW2rzrY9HdvLBTpRN+k0dxY50U/CAhFHW3zMD0OP5JAlnSQRhx5HA==
+
+unique-filename@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea"
+ integrity sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==
+ dependencies:
+ unique-slug "^4.0.0"
+
+unique-slug@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-4.0.0.tgz#6bae6bb16be91351badd24cdce741f892a6532e3"
+ integrity sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==
+ dependencies:
+ imurmurhash "^0.1.4"
+
+unique-string@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a"
+ integrity sha512-ODgiYu03y5g76A1I9Gt0/chLCzQjvzDy7DsZGsLOE/1MrF6wriEskSncj1+/C58Xk/kPZDppSctDybCwOSaGAg==
+ dependencies:
+ crypto-random-string "^1.0.0"
+
+unique-string@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d"
+ integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==
+ dependencies:
+ crypto-random-string "^2.0.0"
+
+universalify@^0.1.0:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+ integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+
+universalify@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
+ integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
+
+universalify@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d"
+ integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==
+
+unpipe@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+ integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
+
+update-browserslist-db@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz#97e9c96ab0ae7bcac08e9ae5151d26e6bc6b5580"
+ integrity sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==
+ dependencies:
+ escalade "^3.2.0"
+ picocolors "^1.1.1"
+
+uri-js@^4.2.2:
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+ integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+ dependencies:
+ punycode "^2.1.0"
+
+url-join@4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.0.tgz#4d3340e807d3773bda9991f8305acdcc2a665d2a"
+ integrity sha512-EGXjXJZhIHiQMK2pQukuFcL303nskqIRzWvPvV5O8miOfwoUb9G+a/Cld60kUyeaybEI94wvVClT10DtfeAExA==
+
+url@^0.11.0:
+ version "0.11.4"
+ resolved "https://registry.yarnpkg.com/url/-/url-0.11.4.tgz#adca77b3562d56b72746e76b330b7f27b6721f3c"
+ integrity sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==
+ dependencies:
+ punycode "^1.4.1"
+ qs "^6.12.3"
+
+use-callback-ref@^1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf"
+ integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==
+ dependencies:
+ tslib "^2.0.0"
+
+use-debounce@^10.0.4:
+ version "10.0.4"
+ resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-10.0.4.tgz#2135be498ad855416c4495cfd8e0e130bd33bb24"
+ integrity sha512-6Cf7Yr7Wk7Kdv77nnJMf6de4HuDE4dTxKij+RqE9rufDsI6zsbjyAxcH5y2ueJCQAnfgKbzXbZHYlkFwmBlWkw==
+
+use-latest-callback@^0.1.5:
+ version "0.1.11"
+ resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.1.11.tgz#e073fcbba792cc95ac661d96bc13b6041956cfe1"
+ integrity sha512-8nhb73STSD/z3GTHklvNjL8F9wMOo0bj0AFnulpIYuFTm6aQlT3ZcNbXF2YurKImIY8+kpSFSDHZZyQmurGrhw==
+
+use-latest-callback@^0.2.1:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.2.3.tgz#2d644d3063040b9bc2d4c55bb525a13ae3de9e16"
+ integrity sha512-7vI3fBuyRcP91pazVboc4qu+6ZqM8izPWX9k7cRnT8hbD5svslcknsh3S9BUhaK11OmgTV4oWZZVSeQAiV53SQ==
+
+use-sidecar@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb"
+ integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==
+ dependencies:
+ detect-node-es "^1.1.0"
+ tslib "^2.0.0"
+
+use-sync-external-store@^1.1.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc"
+ integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==
+
+utif@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/utif/-/utif-2.0.1.tgz#9e1582d9bbd20011a6588548ed3266298e711759"
+ integrity sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==
+ dependencies:
+ pako "^1.0.5"
+
+util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+ integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
+
+util@^0.12.3, util@^0.12.5:
+ version "0.12.5"
+ resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc"
+ integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==
+ dependencies:
+ inherits "^2.0.3"
+ is-arguments "^1.0.4"
+ is-generator-function "^1.0.7"
+ is-typed-array "^1.1.3"
+ which-typed-array "^1.1.2"
+
+utils-merge@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+ integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
+
+uuid@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294"
+ integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==
+
+uuid@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b"
+ integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==
+
+uuid@^8.0.0, uuid@^8.3.2:
+ version "8.3.2"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
+ integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
+
+valid-url@~1.0.9:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200"
+ integrity sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==
+
+validate-npm-package-name@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e"
+ integrity sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==
+ dependencies:
+ builtins "^1.0.3"
+
+validate-npm-package-name@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz#a316573e9b49f3ccd90dbb6eb52b3f06c6d604e8"
+ integrity sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==
+
+vary@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+ integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
+
+vlq@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468"
+ integrity sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==
+
+void-elements@3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09"
+ integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==
+
+walker@^1.0.7:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f"
+ integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==
+ dependencies:
+ makeerror "1.0.12"
+
+warn-once@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/warn-once/-/warn-once-0.1.1.tgz#952088f4fb56896e73fd4e6a3767272a3fccce43"
+ integrity sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==
+
+wcwidth@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
+ integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==
+ dependencies:
+ defaults "^1.0.3"
+
+web-encoding@1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/web-encoding/-/web-encoding-1.1.5.tgz#fc810cf7667364a6335c939913f5051d3e0c4864"
+ integrity sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==
+ dependencies:
+ util "^0.12.3"
+ optionalDependencies:
+ "@zxing/text-encoding" "0.9.0"
+
+web-streams-polyfill@^3.1.1:
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b"
+ integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==
+
+webidl-conversions@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
+ integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
+
+webidl-conversions@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
+ integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==
+
+whatwg-fetch@^3.0.0:
+ version "3.6.20"
+ resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70"
+ integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==
+
+whatwg-url-without-unicode@8.0.0-3:
+ version "8.0.0-3"
+ resolved "https://registry.yarnpkg.com/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz#ab6df4bf6caaa6c85a59f6e82c026151d4bb376b"
+ integrity sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==
+ dependencies:
+ buffer "^5.4.3"
+ punycode "^2.1.1"
+ webidl-conversions "^5.0.0"
+
+whatwg-url@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
+ integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
+ dependencies:
+ tr46 "~0.0.3"
+ webidl-conversions "^3.0.0"
+
+which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e"
+ integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==
+ dependencies:
+ is-bigint "^1.1.0"
+ is-boolean-object "^1.2.1"
+ is-number-object "^1.1.1"
+ is-string "^1.1.1"
+ is-symbol "^1.1.1"
+
+which-builtin-type@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e"
+ integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==
+ dependencies:
+ call-bound "^1.0.2"
+ function.prototype.name "^1.1.6"
+ has-tostringtag "^1.0.2"
+ is-async-function "^2.0.0"
+ is-date-object "^1.1.0"
+ is-finalizationregistry "^1.1.0"
+ is-generator-function "^1.0.10"
+ is-regex "^1.2.1"
+ is-weakref "^1.0.2"
+ isarray "^2.0.5"
+ which-boxed-primitive "^1.1.0"
+ which-collection "^1.0.2"
+ which-typed-array "^1.1.16"
+
+which-collection@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0"
+ integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==
+ dependencies:
+ is-map "^2.0.3"
+ is-set "^2.0.3"
+ is-weakmap "^2.0.2"
+ is-weakset "^2.0.3"
+
+which-module@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409"
+ integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==
+
+which-typed-array@^1.1.16, which-typed-array@^1.1.18, which-typed-array@^1.1.2:
+ version "1.1.18"
+ resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.18.tgz#df2389ebf3fbb246a71390e90730a9edb6ce17ad"
+ integrity sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==
+ dependencies:
+ available-typed-arrays "^1.0.7"
+ call-bind "^1.0.8"
+ call-bound "^1.0.3"
+ for-each "^0.3.3"
+ gopd "^1.2.0"
+ has-tostringtag "^1.0.2"
+
+which@^1.2.9:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+ integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
+ dependencies:
+ isexe "^2.0.0"
+
+which@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
+wonka@^4.0.14:
+ version "4.0.15"
+ resolved "https://registry.yarnpkg.com/wonka/-/wonka-4.0.15.tgz#9aa42046efa424565ab8f8f451fcca955bf80b89"
+ integrity sha512-U0IUQHKXXn6PFo9nqsHphVCE5m3IntqZNB9Jjn7EB1lrR7YTDY3YWgFvEvwniTzXSvOH/XMzAZaIfJF/LvHYXg==
+
+wonka@^6.3.2:
+ version "6.3.4"
+ resolved "https://registry.yarnpkg.com/wonka/-/wonka-6.3.4.tgz#76eb9316e3d67d7febf4945202b5bdb2db534594"
+ integrity sha512-CjpbqNtBGNAeyNS/9W6q3kSkKE52+FjIj7AkFlLr11s/VWGUu6a2CdYSdGxocIhIVjaW/zchesBQUKPVU69Cqg==
+
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
+wrap-ansi@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
+ integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
+wrap-ansi@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
+ integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
+ dependencies:
+ ansi-styles "^6.1.0"
+ string-width "^5.0.1"
+ strip-ansi "^7.0.1"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+
+write-file-atomic@^2.3.0:
+ version "2.4.3"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
+ integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
+ dependencies:
+ graceful-fs "^4.1.11"
+ imurmurhash "^0.1.4"
+ signal-exit "^3.0.2"
+
+ws@^6.2.2:
+ version "6.2.3"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.3.tgz#ccc96e4add5fd6fedbc491903075c85c5a11d9ee"
+ integrity sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==
+ dependencies:
+ async-limiter "~1.0.0"
+
+ws@^7, ws@^7.5.10:
+ version "7.5.10"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9"
+ integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==
+
+ws@^8.12.1:
+ version "8.18.0"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
+ integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==
+
+xcode@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/xcode/-/xcode-3.0.1.tgz#3efb62aac641ab2c702458f9a0302696146aa53c"
+ integrity sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==
+ dependencies:
+ simple-plist "^1.1.0"
+ uuid "^7.0.3"
+
+xhr@^2.0.1:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d"
+ integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==
+ dependencies:
+ global "~4.4.0"
+ is-function "^1.0.1"
+ parse-headers "^2.0.0"
+ xtend "^4.0.0"
+
+xml-parse-from-string@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28"
+ integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==
+
+xml2js@0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.0.tgz#07afc447a97d2bd6507a1f76eeadddb09f7a8282"
+ integrity sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==
+ dependencies:
+ sax ">=0.6.0"
+ xmlbuilder "~11.0.0"
+
+xml2js@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7"
+ integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==
+ dependencies:
+ sax ">=0.6.0"
+ xmlbuilder "~11.0.0"
+
+xmlbuilder@^14.0.0:
+ version "14.0.0"
+ resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-14.0.0.tgz#876b5aec4f05ffd5feb97b0a871c855d16fbeb8c"
+ integrity sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg==
+
+xmlbuilder@^15.1.1:
+ version "15.1.1"
+ resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5"
+ integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==
+
+xmlbuilder@~11.0.0:
+ version "11.0.1"
+ resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
+ integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
+
+xtend@^4.0.0, xtend@~4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
+ integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
+
+y18n@^4.0.0:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
+ integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
+
+y18n@^5.0.5:
+ version "5.0.8"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
+ integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
+
+yallist@^3.0.2:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
+ integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
+
+yallist@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
+yaml@^2.2.1, yaml@^2.2.2, yaml@^2.3.4:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.0.tgz#aef9bb617a64c937a9a748803786ad8d3ffe1e98"
+ integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==
+
+yargs-parser@^18.1.2:
+ version "18.1.3"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
+ integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
+ dependencies:
+ camelcase "^5.0.0"
+ decamelize "^1.2.0"
+
+yargs-parser@^21.1.1:
+ version "21.1.1"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
+ integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
+
+yargs@^15.1.0:
+ version "15.4.1"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
+ integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
+ 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"
+
+yargs@^17.6.2:
+ version "17.7.2"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
+ integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
+ dependencies:
+ cliui "^8.0.1"
+ escalade "^3.1.1"
+ get-caller-file "^2.0.5"
+ require-directory "^2.1.1"
+ string-width "^4.2.3"
+ y18n "^5.0.5"
+ yargs-parser "^21.1.1"
+
+yocto-queue@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+ integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
+
+zeego@^1.10.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/zeego/-/zeego-1.10.0.tgz#4f787e269f3d85b4eb2fdfe58e6765d7e0e8dcf2"
+ integrity sha512-HrPv7DfyAubkp/NOy+Uwcb1rcS3DtkZEtNQFiSDduBoZt2EDf89+1N+aweACj1UnmGOOu+kk56WYiV9sliMpng==
+ dependencies:
+ "@radix-ui/react-context-menu" "^2.0.1"
+ "@radix-ui/react-dropdown-menu" "^2.0.1"
+ sf-symbols-typescript "^2.0.0"
+
+zod-validation-error@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-2.1.0.tgz#208eac75237dfed47c0018d2fe8fd03501bfc9ac"
+ integrity sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==
+
+zod@^3.22.4, zod@^3.23.8:
+ version "3.24.1"
+ resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.1.tgz#27445c912738c8ad1e9de1bea0359fa44d9d35ee"
+ integrity sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==