[MOB-37, MOB-38, MOB-39] Preview for PDF, Text and Media files (#2098)

* version & microphonePermission text & eslint

* remove polyfill as hermes supports intl now

* why do we have solid on mobile?

* cleanup

* add solid back =_=

* pnpm lock

* we hate relative paths here

* android config

* open file logic

* visual tweaks

---------

Co-authored-by: ameer2468 <33054370+ameer2468@users.noreply.github.com>
This commit is contained in:
Utku 2024-02-21 08:26:05 -05:00 committed by GitHub
parent c533d12df0
commit b638fc2177
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 241 additions and 193 deletions

View file

@ -3,7 +3,7 @@
"name": "Spacedrive",
"slug": "spacedrive",
"owner": "spacedrive",
"version": "0.0.1",
"version": "0.1.0",
"orientation": "portrait",
"jsEngine": "hermes",
"scheme": "spacedrive",
@ -58,7 +58,14 @@
}
}
],
["./withRiveAssets.js"]
[
"expo-av",
{
"microphonePermission": "Allow Spacedrive to access your microphone."
}
],
["./scripts/withRiveAssets.js"],
["./scripts/withAndroidIntent.js"]
]
}
}

View file

@ -4,7 +4,7 @@ apply plugin: 'maven-publish'
group = 'com.spacedrive.core'
version = '0.0.1'
version = '0.1.0'
buildscript {
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@ -72,7 +72,7 @@ android {
minSdkVersion safeExtGet("minSdkVersion", 28)
targetSdkVersion safeExtGet("targetSdkVersion", 34)
versionCode 1
versionName "0.2.0"
versionName "0.1.0"
}
lintOptions {
abortOnError false

View file

@ -1,83 +1,84 @@
{
"name": "@sd/mobile",
"version": "1.0.0",
"main": "index.js",
"license": "GPL-3.0-only",
"private": true,
"scripts": {
"start": "expo start --dev-client",
"android": "expo run:android",
"ios": "expo run:ios",
"prebuild": "expo prebuild",
"xcode": "open ios/Spacedrive.xcworkspace",
"android-studio": "open -a '/Applications/Android Studio.app' ./android",
"lint": "eslint src --cache",
"test": "cd ../.. && ./apps/mobile/scripts/run-maestro-tests ios",
"export": "expo export",
"typecheck": "tsc -b"
},
"dependencies": {
"@gorhom/bottom-sheet": "^4.4.7",
"@hookform/resolvers": "^3.1.0",
"@oscartbeaumont-sd/rspc-client": "=0.0.0-main-dc31e5b2",
"@oscartbeaumont-sd/rspc-react": "=0.0.0-main-dc31e5b2",
"@react-native-async-storage/async-storage": "~1.21.0",
"@react-native-masked-view/masked-view": "^0.3.0",
"@react-navigation/bottom-tabs": "^6.5.8",
"@react-navigation/drawer": "^6.6.3",
"@react-navigation/native": "^6.1.7",
"@react-navigation/stack": "^6.3.17",
"@sd/assets": "workspace:*",
"@sd/client": "workspace:*",
"@shopify/flash-list": "1.6.3",
"@tanstack/react-query": "^4.36.1",
"babel-preset-solid": "^1.8.9",
"class-variance-authority": "^0.7.0",
"dayjs": "^1.11.10",
"event-target-polyfill": "^0.0.3",
"expo": "~50.0.6",
"expo-av": "^13.10.5",
"expo-blur": "^12.9.1",
"expo-build-properties": "~0.11.1",
"expo-linking": "~6.2.2",
"expo-media-library": "~15.9.1",
"expo-splash-screen": "~0.26.4",
"expo-status-bar": "~1.11.1",
"intl": "^1.2.5",
"lottie-react-native": "6.5.1",
"metro-react-native-babel-transformer": "^0.77.0",
"moti": "^0.26.0",
"phosphor-react-native": "^2.0.0",
"react": "^18.2.0",
"react-hook-form": "^7.47.0",
"react-native": "0.73.4",
"react-native-circular-progress": "^1.3.9",
"react-native-document-picker": "^9.0.1",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "~2.14.1",
"react-native-linear-gradient": "^2.8.3",
"react-native-popup-menu": "^0.16.1",
"react-native-reanimated": "~3.6.2",
"react-native-safe-area-context": "4.8.2",
"react-native-screens": "~3.29.0",
"react-native-svg": "14.1.0",
"react-native-wheel-color-picker": "^1.2.0",
"rive-react-native": "^6.2.3",
"solid-js": "^1.8.8",
"twrnc": "^3.6.4",
"use-count-up": "^3.0.1",
"use-debounce": "^9.0.4",
"valtio": "^1.11.2",
"zod": "~3.22.4"
},
"devDependencies": {
"@babel/core": "^7.23.2",
"@rnx-kit/metro-config": "^1.3.12",
"@sd/config": "workspace:*",
"@types/react": "^18.2.52",
"babel-plugin-module-resolver": "^5.0.0",
"eslint-plugin-react-native": "^4.1.0",
"react-native-svg-transformer": "^1.1.0",
"typescript": "^5.3.3"
}
"name": "@sd/mobile",
"version": "1.0.0",
"main": "index.js",
"license": "GPL-3.0-only",
"private": true,
"scripts": {
"start": "expo start --dev-client",
"android": "expo run:android",
"ios": "expo run:ios",
"prebuild": "expo prebuild",
"xcode": "open ios/Spacedrive.xcworkspace",
"android-studio": "open -a '/Applications/Android Studio.app' ./android",
"lint": "eslint src --cache",
"test": "cd ../.. && ./apps/mobile/scripts/run-maestro-tests ios",
"export": "expo export",
"typecheck": "tsc -b",
"format": "prettier --write ."
},
"dependencies": {
"@gorhom/bottom-sheet": "^4.4.7",
"@hookform/resolvers": "^3.1.0",
"@oscartbeaumont-sd/rspc-client": "=0.0.0-main-dc31e5b2",
"@oscartbeaumont-sd/rspc-react": "=0.0.0-main-dc31e5b2",
"@react-native-async-storage/async-storage": "~1.21.0",
"@react-native-masked-view/masked-view": "^0.3.0",
"@react-navigation/bottom-tabs": "^6.5.8",
"@react-navigation/drawer": "^6.6.3",
"@react-navigation/native": "^6.1.7",
"@react-navigation/stack": "^6.3.17",
"@sd/assets": "workspace:*",
"@sd/client": "workspace:*",
"@shopify/flash-list": "1.6.3",
"@tanstack/react-query": "^4.36.1",
"babel-preset-solid": "^1.8.9",
"class-variance-authority": "^0.7.0",
"dayjs": "^1.11.10",
"event-target-polyfill": "^0.0.3",
"expo": "~50.0.6",
"expo-av": "^13.10.5",
"expo-blur": "^12.9.1",
"expo-build-properties": "~0.11.1",
"expo-linking": "~6.2.2",
"expo-media-library": "~15.9.1",
"expo-splash-screen": "~0.26.4",
"expo-status-bar": "~1.11.1",
"lottie-react-native": "6.5.1",
"metro-react-native-babel-transformer": "^0.77.0",
"moti": "^0.26.0",
"phosphor-react-native": "^2.0.0",
"react": "^18.2.0",
"react-hook-form": "^7.47.0",
"react-native": "0.73.4",
"react-native-circular-progress": "^1.3.9",
"react-native-document-picker": "^9.0.1",
"react-native-file-viewer": "^2.1.5",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "~2.14.1",
"react-native-linear-gradient": "^2.8.3",
"react-native-popup-menu": "^0.16.1",
"react-native-reanimated": "~3.6.2",
"react-native-safe-area-context": "4.8.2",
"react-native-screens": "~3.29.0",
"react-native-svg": "14.1.0",
"react-native-wheel-color-picker": "^1.2.0",
"rive-react-native": "^6.2.3",
"solid-js": "^1.8.8",
"twrnc": "^3.6.4",
"use-count-up": "^3.0.1",
"use-debounce": "^9.0.4",
"valtio": "^1.11.2",
"zod": "~3.22.4"
},
"devDependencies": {
"@babel/core": "^7.23.2",
"@rnx-kit/metro-config": "^1.3.12",
"@sd/config": "workspace:*",
"@types/react": "^18.2.52",
"babel-plugin-module-resolver": "^5.0.0",
"eslint-plugin-react-native": "^4.1.0",
"react-native-svg-transformer": "^1.1.0",
"typescript": "^5.3.3"
}
}

View file

@ -0,0 +1,26 @@
const { withAndroidManifest } = require('@expo/config-plugins');
// NOTE: Can be extended if needed (https://forums.expo.dev/t/how-to-edit-android-manifest-was-build/65663/4)
function modifyAndroidManifest(androidManifest) {
const { manifest } = androidManifest;
const intent = manifest['queries'][0]['intent'][0];
if (intent) {
// Adds <data android:mimeType="*/*" /> to the intents
intent['data'].push({
$: {
'android:mimeType': '*/*'
}
});
}
return androidManifest;
}
module.exports = function withAndroidIntent(config) {
return withAndroidManifest(config, (config) => {
config.modResults = modifyAndroidManifest(config.modResults);
return config;
});
};

View file

@ -68,11 +68,7 @@ function AppNavigation() {
useEffect(() => {
const interval = setInterval(() => {
plausibleEvent({
event: {
type: 'ping'
}
});
plausibleEvent({ event: { type: 'ping' } });
}, 270 * 1000);
return () => clearInterval(interval);

View file

@ -13,6 +13,7 @@ import { useActionsModalStore } from '~/stores/modalStore';
import FileItem from './FileItem';
import FileRow from './FileRow';
import ScreenContainer from '../layout/ScreenContainer';
type ExplorerProps = {
items?: ExplorerItem[];
@ -44,7 +45,7 @@ const Explorer = ({ items }: ExplorerProps) => {
}
return (
<View style={tw`flex-1 bg-mobile-screen`}>
<ScreenContainer style={'gap-0 py-0'} scrollview={false}>
{/* Header */}
<View style={tw`flex flex-row items-center justify-between`}>
{/* Sort By */}
@ -99,6 +100,7 @@ const Explorer = ({ items }: ExplorerProps) => {
)}
</Pressable>
)}
contentContainerStyle={tw`p-2`}
extraData={layoutMode}
estimatedItemSize={
layoutMode === 'grid'
@ -107,7 +109,7 @@ const Explorer = ({ items }: ExplorerProps) => {
}
/>
)}
</View>
</ScreenContainer>
);
};

View file

@ -2,7 +2,8 @@ import { useNavigation } from '@react-navigation/native';
import { StackHeaderProps } from '@react-navigation/stack';
import { ArrowLeft, DotsThreeOutline, MagnifyingGlass } from 'phosphor-react-native';
import { lazy } from 'react';
import { Platform, Pressable, Text, View } from 'react-native';
import { Pressable, Text, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { tw, twStyle } from '~/lib/tailwind';
import { getExplorerStore, useExplorerStore } from '~/stores/explorerStore';
@ -44,16 +45,18 @@ export default function Header({
const explorerStore = useExplorerStore();
const routeParams = route?.route.params as any;
const headerHeight = useSafeAreaInsets().top;
return (
<View
style={twStyle(
'relative h-auto w-full border-b border-app-line/50 bg-mobile-header',
Platform.OS === 'android' ? 'pt-5' : 'pt-10'
{ paddingTop: headerHeight }
)}
>
<View style={tw`mx-auto mt-5 h-auto w-full justify-center px-7 pb-5`}>
<View style={tw`mx-auto h-auto w-full justify-center px-7 pb-5`}>
<View style={tw`w-full flex-row items-center justify-between`}>
<View style={tw`flex-row items-center gap-5`}>
<View style={tw`flex-row items-center gap-3`}>
{navBack && (
<Pressable
onPress={() => {
@ -67,7 +70,7 @@ export default function Header({
<HeaderIconKind headerKind={headerKind} routeParams={routeParams} />
<Text
numberOfLines={1}
style={tw`max-w-[190px] text-[22px] font-bold text-white`}
style={tw`max-w-[200px] text-xl font-bold text-white`}
>
{title || (routeTitle && route?.options.title)}
</Text>
@ -128,11 +131,11 @@ interface HeaderIconKindProps {
const HeaderIconKind = ({ headerKind, routeParams }: HeaderIconKindProps) => {
switch (headerKind) {
case 'location':
return <Icon size={32} name="Folder" />;
return <Icon size={30} name="Folder" />;
case 'tag':
return (
<View
style={twStyle('h-6 w-6 rounded-full', {
style={twStyle('h-[30px] w-[30px] rounded-full', {
backgroundColor: routeParams.color
})}
/>

View file

@ -12,7 +12,14 @@ import {
} from 'phosphor-react-native';
import { PropsWithChildren, useRef } from 'react';
import { Pressable, Text, View, ViewStyle } from 'react-native';
import { byteSize, getItemFilePath, getItemObject } from '@sd/client';
import FileViewer from 'react-native-file-viewer';
import {
byteSize,
getIndexedItemFilePath,
getItemObject,
useLibraryMutation,
useLibraryQuery
} from '@sd/client';
import FileThumb from '~/components/explorer/FileThumb';
import FavoriteButton from '~/components/explorer/sections/FavoriteButton';
import InfoTagPills from '~/components/explorer/sections/InfoTagPills';
@ -32,7 +39,7 @@ const ActionsContainer = ({ children, style }: ActionsContainerProps) => (
type ActionsItemProps = {
title: string;
icon: Icon;
icon?: Icon;
onPress?: () => void;
isDanger?: boolean;
};
@ -49,7 +56,7 @@ const ActionsItem = ({ icon, onPress, title, isDanger = false }: ActionsItemProp
>
{title}
</Text>
<Icon color={isDanger ? 'red' : 'white'} size={22} />
{Icon && <Icon color={isDanger ? 'red' : 'white'} size={22} />}
</Pressable>
);
};
@ -62,7 +69,31 @@ export const ActionsModal = () => {
const { modalRef, data } = useActionsModalStore();
const objectData = data && getItemObject(data);
const filePath = data && getItemFilePath(data);
const filePath = data && getIndexedItemFilePath(data);
// Open
const updateAccessTime = useLibraryMutation('files.updateAccessTime');
const queriedFullPath = useLibraryQuery(['files.getPath', filePath?.id ?? -1], {
enabled: filePath != null
});
async function handleOpen() {
const absolutePath = queriedFullPath.data;
if (!absolutePath) return;
try {
await FileViewer.open(absolutePath, {
// Android only
showAppsSuggestions: false, // If there is not an installed app that can open the file, open the Play Store with suggested apps
showOpenWithDialog: true // if there is more than one app that can open the file, show an Open With dialogue box
});
filePath &&
filePath.object_id &&
updateAccessTime.mutateAsync([filePath.object_id]).catch(console.error);
} catch (error) {
// TODO: Handle Error & toast message
}
}
return (
<>
@ -99,6 +130,8 @@ export const ActionsModal = () => {
<View style={tw`my-3`} />
{/* Actions */}
<ActionsContainer>
<ActionsItem title="Open" onPress={handleOpen} />
<ActionDivider />
<ActionsItem
icon={Info}
title="Show Info"

View file

@ -7,26 +7,19 @@ import OverviewSection from './OverviewSection';
const Cloud = () => {
return (
<View>
<OverviewSection title="Cloud Drives" count={0}>
<View style={tw`px-7`}>
<NewCard
icons={[
'DriveAmazonS3',
'DriveDropbox',
'DriveGoogleDrive',
'DriveOneDrive'
]}
text="Connect your cloud accounts to Spacedrive."
button={() => (
<Button variant="transparent">
<Text style={tw`font-bold text-ink-dull`}>Coming soon</Text>
</Button>
)}
/>
</View>
</OverviewSection>
</View>
<OverviewSection title="Cloud Drives" count={0}>
<View style={tw`px-7`}>
<NewCard
icons={['DriveAmazonS3', 'DriveDropbox', 'DriveGoogleDrive', 'DriveOneDrive']}
text="Connect your cloud accounts to Spacedrive."
button={() => (
<Button variant="transparent">
<Text style={tw`font-bold text-ink-dull`}>Coming soon</Text>
</Button>
)}
/>
</View>
</OverviewSection>
);
};

View file

@ -23,7 +23,7 @@ const Locations = ({ locations }: Props) => {
const modalRef = useRef<ModalRef>(null);
return (
<View>
<>
<OverviewSection title="Locations" count={locations?.length}>
<View style={tw`flex-row items-center`}>
<Fade height={'100%'} width={30} color="mobile-screen">
@ -80,7 +80,7 @@ const Locations = ({ locations }: Props) => {
</View>
</OverviewSection>
<ImportModal ref={modalRef} />
</View>
</>
);
};

View file

@ -94,20 +94,6 @@ window.screen = {
height
};
/*
https://github.com/facebook/hermes/issues/23
We are using "Hermes" on Android & IOS, which for the current version (0.11),
IOS does not support the Intl fully so we need polyfill it.
NOTE: We can be picky about what we "polyfill" to optimize but for now this works.
*/
if (Platform.OS === 'ios') {
require('intl'); // import intl object
require('intl/locale-data/jsonp/en');
}
// This is insane. We load all data from `AsyncStorage` into the `_localStorage` global and then once complete we import the app.
// This way the polyfilled `localStorage` implementation has its data populated before the global stores within `@sd/client` are initialized (as they are initialized on import).
const App = lazy(async () => {

View file

@ -1,4 +1,4 @@
import React, { useEffect, useMemo } from 'react';
import { useEffect, useMemo } from 'react';
import { useCache, useLibraryQuery, useNodes } from '@sd/client';
import Explorer from '~/components/explorer/Explorer';
import { BrowseStackScreenProps } from '~/navigation/tabs/BrowseStack';
@ -11,21 +11,23 @@ export default function LocationScreen({ navigation, route }: BrowseStackScreenP
useNodes(location.data?.nodes);
const locationData = useCache(location.data?.item);
const { data } = useLibraryQuery([
const paths = useLibraryQuery([
'search.paths',
{
filters: [
{
filePath: {
locations: { in: [id] },
path: { path: path ?? '', location_id: id, include_descendants: false }
locations: { in: [id] }
// path: {location_id: id, path: path ?? '', include_descendants: true} // FIXME: This is the correct query, but it doesn't work and then provides a deserialization error.
}
}
],
take: 100
}
]);
const pathsItemsReferences = useMemo(() => data?.items ?? [], [data]);
const pathsItemsReferences = useMemo(() => paths.data?.items ?? [], [paths.data]);
useNodes(paths.data?.nodes);
const pathsItems = useCache(pathsItemsReferences);
useEffect(() => {

View file

@ -2,10 +2,13 @@ import { proxy, useSnapshot } from 'valtio';
import { proxySet } from 'valtio/utils';
import { resetStore } from '@sd/client';
// TODO: Add "media"
export type ExplorerLayoutMode = 'list' | 'grid' | 'media';
export type ExplorerKind = 'Location' | 'Tag' | 'Space';
export enum ExplorerKind {
Location,
Tag,
Space
}
const state = {
locationId: null as number | null,

View file

@ -251,9 +251,7 @@ function Options({
<Tooltip label={t('pause')}>
<Button
className="cursor-pointer"
onClick={() => {
pauseJob.mutate(group.id);
}}
onClick={() => pauseJob.mutate(group.id)}
size="icon"
variant="outline"
>

View file

@ -1,7 +1,7 @@
import { byteSize } from '.';
import { getItemFilePath, getItemLocation, getItemObject, type ObjectKindKey } from '..';
import type { ExplorerItem } from '../core';
import { ObjectKind } from './objectKind';
import { getItemFilePath, getItemLocation, getItemObject } from '../utils';
import { byteSize } from './byte-size';
import { ObjectKind, ObjectKindKey } from './objectKind';
// ItemData is a single data structure understood by the Explorer, we map all ExplorerItems to this structure in this file
// we use `null` instead of `?` optional values intentionally

View file

@ -397,9 +397,6 @@ importers:
expo-status-bar:
specifier: ~1.11.1
version: 1.11.1
intl:
specifier: ^1.2.5
version: 1.2.5
lottie-react-native:
specifier: 6.5.1
version: 6.5.1(react-native@0.73.4)(react@18.2.0)
@ -427,6 +424,9 @@ importers:
react-native-document-picker:
specifier: ^9.0.1
version: 9.0.1(react-native@0.73.4)(react@18.2.0)
react-native-file-viewer:
specifier: ^2.1.5
version: 2.1.5(react-native@0.73.4)
react-native-fs:
specifier: ^2.20.0
version: 2.20.0(react-native@0.73.4)
@ -6565,7 +6565,7 @@ packages:
magic-string: 0.27.0
react-docgen-typescript: 2.2.2(typescript@5.3.3)
typescript: 5.3.3
vite: 5.0.10(less@4.2.0)
vite: 5.0.10(@types/node@18.17.19)
/@jridgewell/gen-mapping@0.3.3:
resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
@ -10043,7 +10043,7 @@ packages:
magic-string: 0.30.5
rollup: 3.29.4
typescript: 5.3.3
vite: 5.0.10(less@4.2.0)
vite: 5.0.10(@types/node@18.17.19)
transitivePeerDependencies:
- encoding
- supports-color
@ -10396,7 +10396,7 @@ packages:
react: 18.2.0
react-docgen: 6.0.4
react-dom: 18.2.0(react@18.2.0)
vite: 5.0.10(less@4.2.0)
vite: 5.0.10(@types/node@18.17.19)
transitivePeerDependencies:
- '@preact/preset-vite'
- encoding
@ -10636,7 +10636,7 @@ packages:
dependencies:
'@babel/core': 7.23.2
'@svgr/babel-preset': 8.1.0(@babel/core@7.23.2)
'@svgr/core': 8.1.0(typescript@5.2.2)
'@svgr/core': 8.1.0(typescript@5.3.3)
'@svgr/hast-util-to-babel-ast': 8.0.0
svg-parser: 2.0.4
transitivePeerDependencies:
@ -11841,7 +11841,7 @@ packages:
'@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.23.7)
magic-string: 0.27.0
react-refresh: 0.14.0
vite: 5.0.10(less@4.2.0)
vite: 5.0.10(@types/node@18.17.19)
transitivePeerDependencies:
- supports-color
@ -12489,21 +12489,8 @@ packages:
- supports-color
dev: false
/babel-plugin-jsx-dom-expressions@0.37.11(@babel/core@7.23.7):
resolution: {integrity: sha512-0NaWy4sFsE0AWlucvL/myEiZ851BgjeLwhtctOFmyVCK6fPXqQHQUBB5SrrrmvOiw/BZCmMe8dOy7JL3FSyTtQ==}
peerDependencies:
'@babel/core': ^7.20.12
dependencies:
'@babel/core': 7.23.7
'@babel/helper-module-imports': 7.18.6
'@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.7)
'@babel/types': 7.23.6
html-entities: 2.3.3
validate-html-nesting: 1.2.2
dev: true
/babel-plugin-jsx-dom-expressions@0.37.13(@babel/core@7.23.2):
resolution: {integrity: sha512-oAEMMIgU0h1DmHn4ZDaBBFc08nsVJciLq9pF7g0ZdpeIDKfY4zXjXr8+/oBjKhXG8nyomhnTodPjeG+/ZXcWXQ==}
/babel-plugin-jsx-dom-expressions@0.37.17(@babel/core@7.23.2):
resolution: {integrity: sha512-1bv8rOTzs6TR3DVyVZ7ElxyPEhnS556FMWRIsB3gBPfkn/cSKaLvXLGk+X1lvI+SzcUo4G+UcmJrn3vr1ig8mQ==}
peerDependencies:
'@babel/core': ^7.20.12
dependencies:
@ -12515,6 +12502,19 @@ packages:
validate-html-nesting: 1.2.2
dev: false
/babel-plugin-jsx-dom-expressions@0.37.17(@babel/core@7.23.7):
resolution: {integrity: sha512-1bv8rOTzs6TR3DVyVZ7ElxyPEhnS556FMWRIsB3gBPfkn/cSKaLvXLGk+X1lvI+SzcUo4G+UcmJrn3vr1ig8mQ==}
peerDependencies:
'@babel/core': ^7.20.12
dependencies:
'@babel/core': 7.23.7
'@babel/helper-module-imports': 7.18.6
'@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.7)
'@babel/types': 7.23.6
html-entities: 2.3.3
validate-html-nesting: 1.2.2
dev: true
/babel-plugin-module-resolver@5.0.0:
resolution: {integrity: sha512-g0u+/ChLSJ5+PzYwLwP8Rp8Rcfowz58TJNCe+L/ui4rpzE/mg//JVX0EWBUYoxaextqnwuGHzfGp2hh0PPV25Q==}
engines: {node: '>= 16'}
@ -12730,13 +12730,13 @@ packages:
babel-plugin-syntax-trailing-function-commas: 7.0.0-beta.0
dev: false
/babel-preset-solid@1.8.8(@babel/core@7.23.7):
resolution: {integrity: sha512-m+sFxzriUgMiyUPz/oWxU+N6PwY2bVsZVlc4Jxx+5XhDt5lGE/meg+ZL/kLgSAZ75YuU9AJZr444Un1bO0vhJQ==}
/babel-preset-solid@1.8.15(@babel/core@7.23.7):
resolution: {integrity: sha512-P2yOQbB7Hn/m4YvpXV6ExHIMcgNWXWXcvY4kJzG3yqAB3hKS58OZRsvJ7RObsZWqXRvZTITBIwnpK0BMGu+ZIQ==}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/core': 7.23.7
babel-plugin-jsx-dom-expressions: 0.37.11(@babel/core@7.23.7)
babel-plugin-jsx-dom-expressions: 0.37.17(@babel/core@7.23.7)
dev: true
/babel-preset-solid@1.8.9(@babel/core@7.23.2):
@ -12745,7 +12745,7 @@ packages:
'@babel/core': ^7.0.0
dependencies:
'@babel/core': 7.23.2
babel-plugin-jsx-dom-expressions: 0.37.13(@babel/core@7.23.2)
babel-plugin-jsx-dom-expressions: 0.37.17(@babel/core@7.23.2)
dev: false
/bail@2.0.2:
@ -16953,10 +16953,6 @@ packages:
hasown: 2.0.0
side-channel: 1.0.4
/intl@1.2.5:
resolution: {integrity: sha512-rK0KcPHeBFBcqsErKSpvZnrOmWOj+EmDkyJ57e90YWaQNqbcivcqmKDlHEeNprDWOsKzPsh1BfSpPQdDvclHVw==}
dev: false
/invariant@2.2.4:
resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
dependencies:
@ -21190,6 +21186,14 @@ packages:
resolution: {integrity: sha512-BWIKcEYtzjRV6GpkX0Km5/w2E7fgIcywiQOT7JZTc5NSbv/YI9kpFinB9lRFsOoRVGmiqq/O3VfP/oH2clIiBA==}
dev: false
/react-native-file-viewer@2.1.5(react-native@0.73.4):
resolution: {integrity: sha512-MGC6sx9jsqHdefhVQ6o0akdsPGpkXgiIbpygb2Sg4g4bh7v6K1cardLV1NwGB9A6u1yICOSDT/MOC//9Ez6EUg==}
peerDependencies:
react-native: '>=0.47'
dependencies:
react-native: 0.73.4(@babel/core@7.23.2)(@babel/preset-env@7.23.8)(react@18.2.0)
dev: false
/react-native-fs@2.20.0(react-native@0.73.4):
resolution: {integrity: sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ==}
peerDependencies:
@ -22371,15 +22375,9 @@ packages:
seroval: 1.0.4
dev: true
/seroval@1.0.3:
resolution: {integrity: sha512-v5Psun3O2OdehTS/BpTC9EezHxyQRM4lqtvOdbngEq8qOZUECqG5XaoFNZgBQrJKXZFgcyZtMH6Dv7G96pKSSQ==}
engines: {node: '>=10'}
dev: false
/seroval@1.0.4:
resolution: {integrity: sha512-qQs/N+KfJu83rmszFQaTxcoJoPn6KNUruX4KmnmyD0oZkUoiNvJ1rpdYKDf4YHM05k+HOgCxa3yvf15QbVijGg==}
engines: {node: '>=10'}
dev: true
/serve-static@1.15.0:
resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==}
@ -22582,8 +22580,8 @@ packages:
/solid-js@1.8.8:
resolution: {integrity: sha512-9CtL5xWTYX1WWjQKqht3Tl0AJzgz4YWVQk8hoscO9TzRCgzlpAauEOexXa6bPG30W+fWLnFVE7XUiAzQFNeUKw==}
dependencies:
csstype: 3.1.2
seroval: 1.0.3
csstype: 3.1.3
seroval: 1.0.4
dev: false
/solid-refresh@0.5.3(solid-js@1.8.11):
@ -24701,7 +24699,7 @@ packages:
'@babel/core': 7.23.7
'@babel/preset-typescript': 7.23.3(@babel/core@7.23.7)
'@types/babel__core': 7.20.5
babel-preset-solid: 1.8.8(@babel/core@7.23.7)
babel-preset-solid: 1.8.15(@babel/core@7.23.7)
merge-anything: 5.1.7
solid-js: 1.8.11
solid-refresh: 0.5.3(solid-js@1.8.11)
@ -24827,7 +24825,6 @@ packages:
rollup: 4.9.2
optionalDependencies:
fsevents: 2.3.3
dev: true
/vite@5.0.10(less@4.2.0):
resolution: {integrity: sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==}
@ -24863,6 +24860,7 @@ packages:
rollup: 4.9.2
optionalDependencies:
fsevents: 2.3.3
dev: true
/vite@5.0.10(sass@1.69.5):
resolution: {integrity: sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==}