mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Create menu (bottom sheet or side sheet)
This commit is contained in:
parent
b0eb8c3b42
commit
1139a726c9
@ -28,6 +28,7 @@ import { createQueryClient } from "@kyoo/models";
|
||||
import i18next from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import { getLocales } from "expo-localization";
|
||||
import { PortalProvider } from "@gorhom/portal";
|
||||
import "intl-pluralrules";
|
||||
|
||||
// TODO: use a backend to load jsons.
|
||||
@ -72,7 +73,9 @@ export default function Root() {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<ThemeSelector>
|
||||
<ThemedStack />
|
||||
<PortalProvider>
|
||||
<ThemedStack />
|
||||
</PortalProvider>
|
||||
</ThemeSelector>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
|
@ -9,6 +9,7 @@
|
||||
"web": "expo start --web"
|
||||
},
|
||||
"dependencies": {
|
||||
"@gorhom/portal": "^1.0.14",
|
||||
"@kyoo/ui": "workspace:^",
|
||||
"@material-symbols/svg-400": "^0.4.2",
|
||||
"@shopify/flash-list": "1.3.1",
|
||||
|
@ -13,6 +13,7 @@
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.9.3",
|
||||
"@emotion/styled": "^11.9.3",
|
||||
"@gorhom/portal": "^1.0.14",
|
||||
"@kyoo/models": "workspace:^",
|
||||
"@kyoo/primitives": "workspace:^",
|
||||
"@kyoo/ui": "workspace:^",
|
||||
|
@ -20,10 +20,11 @@
|
||||
|
||||
import "../polyfill";
|
||||
|
||||
import { ReactNode, useState } from "react";
|
||||
import NextApp, { AppContext, type AppProps } from "next/app";
|
||||
import { PortalProvider } from "@gorhom/portal";
|
||||
import { createTheme, ThemeProvider as MTheme } from "@mui/material";
|
||||
import { Hydrate, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { ReactNode, useState } from "react";
|
||||
import NextApp, { AppContext, type AppProps } from "next/app";
|
||||
import {
|
||||
HiddenIfNoJs,
|
||||
SkeletonCss,
|
||||
@ -32,7 +33,6 @@ import {
|
||||
} from "@kyoo/primitives";
|
||||
import { createQueryClient, fetchQuery, QueryIdentifier, QueryPage } from "@kyoo/models";
|
||||
import { useTheme, useMobileHover } from "yoshiki/web";
|
||||
import { useYoshiki } from "yoshiki/native";
|
||||
import superjson from "superjson";
|
||||
import Head from "next/head";
|
||||
import { withTranslations } from "../i18n";
|
||||
@ -105,7 +105,9 @@ const App = ({ Component, pageProps }: AppProps) => {
|
||||
<Hydrate state={queryState}>
|
||||
<ThemeSelector>
|
||||
<GlobalCssTheme />
|
||||
<Layout page={<Component {...props} />} />
|
||||
<PortalProvider>
|
||||
<Layout page={<Component {...props} />} />
|
||||
</PortalProvider>
|
||||
</ThemeSelector>
|
||||
</Hydrate>
|
||||
</QueryClientProvider>
|
||||
|
@ -8,6 +8,7 @@
|
||||
"typescript": "^4.9.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@gorhom/portal": "*",
|
||||
"@material-symbols/svg-400": "*",
|
||||
"expo-linear-gradient": "*",
|
||||
"moti": "*",
|
||||
|
@ -31,6 +31,7 @@ export * from "./container";
|
||||
export * from "./divider";
|
||||
export * from "./progress";
|
||||
export * from "./slider";
|
||||
export * from "./menu";
|
||||
|
||||
export * from "./animated";
|
||||
export * from "./utils";
|
||||
|
@ -18,18 +18,20 @@
|
||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ComponentType, Fragment, ReactNode } from "react";
|
||||
import { ComponentProps, ComponentType, Fragment, ReactNode } from "react";
|
||||
import {
|
||||
Platform,
|
||||
Pressable,
|
||||
TextProps,
|
||||
TouchableOpacity,
|
||||
TouchableNativeFeedback,
|
||||
View,
|
||||
ViewProps,
|
||||
StyleSheet,
|
||||
PressableProps,
|
||||
} from "react-native";
|
||||
import { LinkCore, TextLink } from "solito/link";
|
||||
import { useYoshiki, Pressable } from "yoshiki/native";
|
||||
import { useYoshiki } from "yoshiki/native";
|
||||
|
||||
export const A = ({
|
||||
href,
|
||||
@ -58,19 +60,20 @@ export const A = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const Link = ({
|
||||
href,
|
||||
export const PressableFeedback = ({
|
||||
children,
|
||||
WebComponent,
|
||||
...props
|
||||
}: ViewProps & {
|
||||
href: string;
|
||||
onFocus?: () => void;
|
||||
onBlur?: () => void;
|
||||
onPressIn?: () => void;
|
||||
onPressOut?: () => void;
|
||||
onFocus?: PressableProps["onFocus"];
|
||||
onBlur?: PressableProps["onBlur"];
|
||||
onPressIn?: PressableProps["onPressIn"];
|
||||
onPressOut?: PressableProps["onPressOut"];
|
||||
onPress?: PressableProps["onPress"];
|
||||
WebComponent?: ComponentType;
|
||||
}) => {
|
||||
const { onBlur, onFocus, onPressIn, onPressOut, ...noFocusProps } = props;
|
||||
const focusProps = { onBlur, onFocus, onPressIn, onPressOut };
|
||||
const { onBlur, onFocus, onPressIn, onPressOut, onPress, ...noPressProps } = props;
|
||||
const pressProps = { onBlur, onFocus, onPressIn, onPressOut, onPress };
|
||||
const radiusStyle = Platform.select<ViewProps>({
|
||||
android: {
|
||||
style: { borderRadius: StyleSheet.flatten(props?.style)?.borderRadius, overflow: "hidden" },
|
||||
@ -78,28 +81,43 @@ export const Link = ({
|
||||
default: {},
|
||||
});
|
||||
const Wrapper = radiusStyle.style ? View : Fragment;
|
||||
const InnerPressable = Platform.select<ComponentType<{ children?: any }>>({
|
||||
web: WebComponent ?? Pressable,
|
||||
android: TouchableNativeFeedback,
|
||||
ios: TouchableOpacity,
|
||||
default: Pressable,
|
||||
});
|
||||
|
||||
return (
|
||||
<Wrapper {...radiusStyle}>
|
||||
<LinkCore
|
||||
href={href}
|
||||
Component={Platform.select<ComponentType>({
|
||||
web: View,
|
||||
android: TouchableNativeFeedback,
|
||||
ios: TouchableOpacity,
|
||||
default: Pressable,
|
||||
})}
|
||||
componentProps={Platform.select<object>({
|
||||
android: { useForeground: true, ...focusProps },
|
||||
<InnerPressable
|
||||
{...Platform.select<object>({
|
||||
android: { useForeground: true, ...pressProps },
|
||||
default: props,
|
||||
})}
|
||||
>
|
||||
{Platform.select<ReactNode>({
|
||||
android: <View {...noFocusProps}>{children}</View>,
|
||||
ios: <View {...noFocusProps}>{children}</View>,
|
||||
android: <View {...noPressProps}>{children}</View>,
|
||||
ios: <View {...noPressProps}>{children}</View>,
|
||||
default: children,
|
||||
})}
|
||||
</LinkCore>
|
||||
</InnerPressable>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const Link = ({
|
||||
href,
|
||||
children,
|
||||
...props
|
||||
}: { href: string } & Omit<ComponentProps<typeof PressableFeedback>, "WebComponent">) => {
|
||||
return (
|
||||
<LinkCore
|
||||
href={href}
|
||||
Component={PressableFeedback}
|
||||
componentProps={{ WebComponent: View, ...props }}
|
||||
>
|
||||
{children}
|
||||
</LinkCore>
|
||||
);
|
||||
};
|
||||
|
145
front/packages/primitives/src/menu.tsx
Normal file
145
front/packages/primitives/src/menu.tsx
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Kyoo - A portable and vast media library solution.
|
||||
* Copyright (c) Kyoo.
|
||||
*
|
||||
* See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
*
|
||||
* Kyoo is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* Kyoo is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Portal } from "@gorhom/portal";
|
||||
import { ScrollView } from "moti";
|
||||
import { ComponentType, createContext, ReactNode, useContext, useEffect, useState } from "react";
|
||||
import { PressableProps, StyleSheet, Pressable } from "react-native";
|
||||
import { percent, px, sm, useYoshiki, xl } from "yoshiki/native";
|
||||
import Close from "@material-symbols/svg-400/rounded/close-fill.svg";
|
||||
import { IconButton } from "./icons";
|
||||
import { PressableFeedback } from "./links";
|
||||
import { P } from "./text";
|
||||
import { ContrastArea } from "./themes";
|
||||
import { ts } from "./utils";
|
||||
|
||||
const MenuContext = createContext<((open: boolean) => void) | undefined>(undefined);
|
||||
|
||||
const Menu = <AsProps extends { onPress: PressableProps["onPress"] }>({
|
||||
Triger,
|
||||
onMenuOpen,
|
||||
onMenuClose,
|
||||
children,
|
||||
...props
|
||||
}: {
|
||||
Triger: ComponentType<AsProps>;
|
||||
children: ReactNode | ReactNode[] | null;
|
||||
onMenuOpen: () => void;
|
||||
onMenuClose: () => void;
|
||||
} & Omit<AsProps, "onPress">) => {
|
||||
const [isOpen, setOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) onMenuOpen?.call(null);
|
||||
else onMenuClose?.call(null);
|
||||
}, [isOpen, onMenuClose, onMenuOpen]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* @ts-ignore */}
|
||||
<Triger onPress={() => setOpen(true)} {...props} />
|
||||
{isOpen && (
|
||||
<Portal>
|
||||
<ContrastArea mode="user">
|
||||
{({ css, theme }) => (
|
||||
<MenuContext.Provider value={setOpen}>
|
||||
<Pressable
|
||||
onPress={() => setOpen(false)}
|
||||
focusable={false}
|
||||
{...css({ ...StyleSheet.absoluteFillObject, flexGrow: 1, bg: "transparent" })}
|
||||
/>
|
||||
<ScrollView
|
||||
{...css([
|
||||
{
|
||||
bg: (theme) => theme.background,
|
||||
position: "absolute",
|
||||
bottom: 0,
|
||||
width: percent(100),
|
||||
alignSelf: "center",
|
||||
borderTopLeftRadius: px(26),
|
||||
borderTopRightRadius: { xs: px(26), xl: 0 },
|
||||
paddingTop: { xs: px(26), xl: 0 },
|
||||
marginTop: { xs: px(72), xl: 0 },
|
||||
},
|
||||
sm({
|
||||
maxWidth: px(640),
|
||||
marginHorizontal: px(56),
|
||||
}),
|
||||
xl({
|
||||
top: 0,
|
||||
right: 0,
|
||||
marginRight: 0,
|
||||
borderBottomLeftRadius: px(26),
|
||||
}),
|
||||
])}
|
||||
>
|
||||
<IconButton
|
||||
icon={Close}
|
||||
color={theme.colors.black}
|
||||
onPress={() => setOpen(false)}
|
||||
{...css({ alignSelf: "flex-end", display: { xs: "none", xl: "flex" } })}
|
||||
/>
|
||||
{children}
|
||||
</ScrollView>
|
||||
</MenuContext.Provider>
|
||||
)}
|
||||
</ContrastArea>
|
||||
</Portal>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const MenuItem = <AsProps extends PressableProps>({
|
||||
label,
|
||||
icon,
|
||||
selected,
|
||||
as,
|
||||
onPress,
|
||||
...props
|
||||
}: {
|
||||
label: string;
|
||||
icon?: JSX.Element;
|
||||
selected?: boolean;
|
||||
as?: ComponentType<AsProps>;
|
||||
} & AsProps) => {
|
||||
const { css } = useYoshiki();
|
||||
const setOpen = useContext(MenuContext);
|
||||
|
||||
const As: ComponentType<any> = as ?? PressableFeedback;
|
||||
return (
|
||||
<As
|
||||
onPress={(e: any) => {
|
||||
setOpen?.call(null, false);
|
||||
onPress?.call(null, e);
|
||||
}}
|
||||
{...css(
|
||||
{ paddingHorizontal: ts(2), width: percent(100), height: ts(5), justifyContent: "center" },
|
||||
props as any,
|
||||
)}
|
||||
>
|
||||
{icon ?? null}
|
||||
<P>{label}</P>
|
||||
</As>
|
||||
);
|
||||
};
|
||||
Menu.Item = MenuItem;
|
||||
|
||||
export { Menu };
|
@ -135,7 +135,7 @@ export const ContrastArea = ({
|
||||
contrastText,
|
||||
}: {
|
||||
children: ReactNode | YoshikiFunc<ReactNode>;
|
||||
mode?: "light" | "dark";
|
||||
mode?: "light" | "dark" | "user";
|
||||
contrastText?: boolean;
|
||||
}) => {
|
||||
const oldTheme = useTheme();
|
||||
|
@ -25,10 +25,5 @@
|
||||
"react-native-reanimated": "*",
|
||||
"react-native-svg": "*",
|
||||
"yoshiki": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react-native": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,64 +19,75 @@
|
||||
*/
|
||||
|
||||
import { Font, Track } from "@kyoo/models";
|
||||
import { IconButton, tooltip } from "@kyoo/primitives";
|
||||
import { IconButton, tooltip, Menu, ts, A } from "@kyoo/primitives";
|
||||
import { useAtom } from "jotai";
|
||||
import { useRouter } from "solito/router";
|
||||
import { useState } from "react";
|
||||
import { Platform, View } from "react-native";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ClosedCaption from "@material-symbols/svg-400/rounded/closed_caption-fill.svg";
|
||||
import Fullscreen from "@material-symbols/svg-400/rounded/fullscreen-fill.svg";
|
||||
import FullscreenExit from "@material-symbols/svg-400/rounded/fullscreen_exit-fill.svg";
|
||||
import { Stylable, useYoshiki } from "yoshiki/native";
|
||||
import { createParam } from "solito";
|
||||
import { fullscreenAtom, subtitleAtom } from "../state";
|
||||
|
||||
const { useParam } = createParam<{ subtitle?: string }>();
|
||||
|
||||
export const RightButtons = ({
|
||||
subtitles,
|
||||
fonts,
|
||||
onMenuOpen,
|
||||
onMenuClose,
|
||||
...props
|
||||
}: {
|
||||
subtitles?: Track[];
|
||||
fonts?: Font[];
|
||||
onMenuOpen: () => void;
|
||||
onMenuClose: () => void;
|
||||
}) => {
|
||||
} & Stylable) => {
|
||||
const { css } = useYoshiki();
|
||||
const { t } = useTranslation();
|
||||
const [subtitleAnchor, setSubtitleAnchor] = useState<HTMLButtonElement | null>(null);
|
||||
const [isFullscreen, setFullscreen] = useAtom(fullscreenAtom);
|
||||
const [selectedSubtitle, setSubtitle] = useParam("subtitle");
|
||||
|
||||
const spacing = css({ marginHorizontal: ts(1) });
|
||||
|
||||
subtitles = [{ id: 1, slug: "oto", displayName: "toto" }];
|
||||
|
||||
return (
|
||||
<View
|
||||
// sx={{
|
||||
// display: "flex",
|
||||
// "> *": {
|
||||
// m: { xs: "4px !important", sm: "8px !important" },
|
||||
// p: { xs: "4px !important", sm: "8px !important" },
|
||||
// },
|
||||
// }}
|
||||
>
|
||||
{/* {subtitles && ( */}
|
||||
{/* <Tooltip title={t("subtitles")}> */}
|
||||
{/* <IconButton */}
|
||||
{/* id="sortby" */}
|
||||
{/* aria-label={t("subtitles")} */}
|
||||
{/* aria-controls={subtitleAnchor ? "subtitle-menu" : undefined} */}
|
||||
{/* aria-haspopup="true" */}
|
||||
{/* aria-expanded={subtitleAnchor ? "true" : undefined} */}
|
||||
{/* onClick={(event) => { */}
|
||||
{/* setSubtitleAnchor(event.currentTarget); */}
|
||||
{/* onMenuOpen(); */}
|
||||
{/* }} */}
|
||||
{/* sx={{ color: "white" }} */}
|
||||
{/* > */}
|
||||
{/* <ClosedCaption /> */}
|
||||
{/* </IconButton> */}
|
||||
{/* </Tooltip> */}
|
||||
{/* )} */}
|
||||
<View {...css({ flexDirection: "row" }, props)}>
|
||||
{subtitles && (
|
||||
<Menu
|
||||
Triger={IconButton}
|
||||
icon={ClosedCaption}
|
||||
{...tooltip(t("player.subtitles"), true)}
|
||||
{...spacing}
|
||||
// id="sortby"
|
||||
// aria-controls={subtitleAnchor ? "subtitle-menu" : undefined}
|
||||
// aria-haspopup="true"
|
||||
// aria-expanded={subtitleAnchor ? "true" : undefined}
|
||||
>
|
||||
<Menu.Item
|
||||
label={t("player.subtitle-none")}
|
||||
selected={!selectedSubtitle}
|
||||
onPress={() => setSubtitle(undefined)}
|
||||
/>
|
||||
{subtitles.map((x) => (
|
||||
<Menu.Item
|
||||
key={x.id}
|
||||
label={x.displayName}
|
||||
selected={selectedSubtitle === x.slug}
|
||||
onPress={() => setSubtitle(x.slug)}
|
||||
/>
|
||||
))}
|
||||
</Menu>
|
||||
)}
|
||||
{Platform.OS === "web" && (
|
||||
<IconButton
|
||||
icon={isFullscreen ? FullscreenExit : Fullscreen}
|
||||
onPress={() => setFullscreen(!isFullscreen)}
|
||||
{...tooltip(t("player.fullscreen"), true)}
|
||||
{...spacing}
|
||||
/>
|
||||
)}
|
||||
{/* {subtitleAnchor && ( */}
|
||||
|
@ -31,6 +31,7 @@ import {
|
||||
subtitleAtom,
|
||||
volumeAtom,
|
||||
} from "./state";
|
||||
import { Platform } from "react-native";
|
||||
|
||||
type Action =
|
||||
| { type: "play" }
|
||||
@ -93,6 +94,7 @@ export const useVideoKeyboard = (
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
if (Platform.OS !== "web") return;
|
||||
const handler = (event: KeyboardEvent) => {
|
||||
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
|
||||
|
||||
|
@ -26,6 +26,7 @@ import { ResizeMode, Video as NativeVideo, VideoProps } from "expo-av";
|
||||
import SubtitleOctopus from "libass-wasm";
|
||||
import Hls from "hls.js";
|
||||
import { bakedAtom } from "../jotai-utils";
|
||||
import { Platform } from "react-native";
|
||||
|
||||
enum PlayMode {
|
||||
Direct,
|
||||
@ -100,6 +101,7 @@ export const Video = ({
|
||||
|
||||
const setFullscreen = useSetAtom(privateFullscreen);
|
||||
useEffect(() => {
|
||||
if (Platform.OS !== "web") return;
|
||||
const handler = () => {
|
||||
setFullscreen(document.fullscreenElement != null);
|
||||
};
|
||||
|
@ -2142,6 +2142,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@gorhom/portal@npm:^1.0.14":
|
||||
version: 1.0.14
|
||||
resolution: "@gorhom/portal@npm:1.0.14"
|
||||
dependencies:
|
||||
nanoid: ^3.3.1
|
||||
peerDependencies:
|
||||
react: "*"
|
||||
react-native: "*"
|
||||
checksum: 227bb96a2db854ab29bb9da8d4f3823c7f7448358de459709dd1b78522110da564c9a8734c6bc7d7153ed7c99320e0fb5d60b420c2ebb75ecaf2f0d757f410f9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-typed-document-node/core@npm:^3.1.0":
|
||||
version: 3.1.1
|
||||
resolution: "@graphql-typed-document-node/core@npm:3.1.1"
|
||||
@ -2339,6 +2351,7 @@ __metadata:
|
||||
solito: ^2.0.5
|
||||
typescript: ^4.9.3
|
||||
peerDependencies:
|
||||
"@gorhom/portal": "*"
|
||||
"@material-symbols/svg-400": "*"
|
||||
expo-linear-gradient: "*"
|
||||
moti: "*"
|
||||
@ -2375,9 +2388,6 @@ __metadata:
|
||||
react-native-reanimated: "*"
|
||||
react-native-svg: "*"
|
||||
yoshiki: "*"
|
||||
peerDependenciesMeta:
|
||||
react-native:
|
||||
optional: true
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@ -6545,19 +6555,19 @@ __metadata:
|
||||
|
||||
"expo-av@file:///home/anonymus-raccoon/projects/expo/packages/expo-av/::locator=mobile%40workspace%3Aapps%2Fmobile":
|
||||
version: 13.0.1
|
||||
resolution: "expo-av@file:///home/anonymus-raccoon/projects/expo/packages/expo-av/#///home/anonymus-raccoon/projects/expo/packages/expo-av/::hash=5981bc&locator=mobile%40workspace%3Aapps%2Fmobile"
|
||||
resolution: "expo-av@file:///home/anonymus-raccoon/projects/expo/packages/expo-av/#///home/anonymus-raccoon/projects/expo/packages/expo-av/::hash=6acf81&locator=mobile%40workspace%3Aapps%2Fmobile"
|
||||
peerDependencies:
|
||||
expo: "*"
|
||||
checksum: 3313e891f708f423f29c417372701fa6ddd5bd30028a1ebcd9634d61e5ed0475dbbcc51384fc88e82b4c0dd482dc6af38f9b1d4d103fb1a81ea05d2a4c967586
|
||||
checksum: 89c23346fcf8cc3ed50b523969dad76c14e9bb3f526c7cc0032783fca9aeacc1c14a1aca86b84cb5ebd51d4ee2142f7fb507ed47d7430e12b71733858a70acc9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"expo-av@file:///home/anonymus-raccoon/projects/expo/packages/expo-av/::locator=web%40workspace%3Aapps%2Fweb":
|
||||
version: 13.0.1
|
||||
resolution: "expo-av@file:///home/anonymus-raccoon/projects/expo/packages/expo-av/#///home/anonymus-raccoon/projects/expo/packages/expo-av/::hash=5981bc&locator=web%40workspace%3Aapps%2Fweb"
|
||||
resolution: "expo-av@file:///home/anonymus-raccoon/projects/expo/packages/expo-av/#///home/anonymus-raccoon/projects/expo/packages/expo-av/::hash=6acf81&locator=web%40workspace%3Aapps%2Fweb"
|
||||
peerDependencies:
|
||||
expo: "*"
|
||||
checksum: 3313e891f708f423f29c417372701fa6ddd5bd30028a1ebcd9634d61e5ed0475dbbcc51384fc88e82b4c0dd482dc6af38f9b1d4d103fb1a81ea05d2a4c967586
|
||||
checksum: 89c23346fcf8cc3ed50b523969dad76c14e9bb3f526c7cc0032783fca9aeacc1c14a1aca86b84cb5ebd51d4ee2142f7fb507ed47d7430e12b71733858a70acc9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -9962,6 +9972,7 @@ __metadata:
|
||||
resolution: "mobile@workspace:apps/mobile"
|
||||
dependencies:
|
||||
"@babel/core": ^7.19.3
|
||||
"@gorhom/portal": ^1.0.14
|
||||
"@kyoo/ui": "workspace:^"
|
||||
"@material-symbols/svg-400": ^0.4.2
|
||||
"@shopify/flash-list": 1.3.1
|
||||
@ -10057,7 +10068,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"nanoid@npm:^3.1.23, nanoid@npm:^3.3.4":
|
||||
"nanoid@npm:^3.1.23, nanoid@npm:^3.3.1, nanoid@npm:^3.3.4":
|
||||
version: 3.3.4
|
||||
resolution: "nanoid@npm:3.3.4"
|
||||
bin:
|
||||
@ -13639,6 +13650,7 @@ __metadata:
|
||||
dependencies:
|
||||
"@emotion/react": ^11.9.3
|
||||
"@emotion/styled": ^11.9.3
|
||||
"@gorhom/portal": ^1.0.14
|
||||
"@kyoo/models": "workspace:^"
|
||||
"@kyoo/primitives": "workspace:^"
|
||||
"@kyoo/ui": "workspace:^"
|
||||
|
Loading…
x
Reference in New Issue
Block a user