New UI Connect Page

This commit is contained in:
KoalaSat 2023-01-13 12:51:30 +01:00
parent 269253ebf0
commit 52beb0c63f
No known key found for this signature in database
GPG Key ID: 2F7F61C6146AB157
24 changed files with 881 additions and 508 deletions

View File

@ -2,6 +2,7 @@ import App from './frontend'
import { Buffer as SafeBuffer } from 'safe-buffer'
import { randomBytes } from '@noble/hashes/utils'
import 'text-encoding-polyfill'
import 'react-native-gesture-handler'
global.Buffer = SafeBuffer
global.randomBytes = randomBytes

View File

@ -1,5 +1,7 @@
package com.nostros;
import android.os.Bundle;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
@ -30,6 +32,11 @@ public class MainActivity extends ReactActivity {
super(activity, mainComponentName);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
}
@Override
protected ReactRootView createRootView() {
ReactRootView reactRootView = new ReactRootView(getContext());

View File

@ -1,3 +1,6 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
'react-native-reanimated/plugin',
],
}

View File

@ -0,0 +1,49 @@
import * as React from 'react'
import { StyleSheet, View } from 'react-native'
import { Text } from 'react-native-paper'
import { nostrosLogoSvg } from '../../Constants/Theme'
import { SvgXml } from 'react-native-svg'
interface LogoProps {
onlyIcon?: boolean
size?: 'large' | 'small'
}
export const Logo: React.FC<LogoProps> = ({onlyIcon = false, size = 'small' }) => {
return (
<View style={styles.container}>
<SvgXml xml={nostrosLogoSvg} style={size === 'small' ? styles.logoSmall : styles.logoLarge} />
{!onlyIcon && (
<Text style={styles.text} variant={size === 'small' ? 'headlineSmall' : 'displayMedium'}>
NOSTROS
</Text>
)}
</View>
)
}
const styles = StyleSheet.create({
logoSmall: {
maxHeight: 120,
flex: 1,
height: 40
},
logoLarge: {
maxHeight: 120,
flex: 1,
height: 60,
},
container: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center'
},
text: {
fontFamily: 'SpaceGrotesk-Bold',
flex: 2,
height: 60,
textAlignVertical: 'center',
},
})
export default Logo

View File

@ -0,0 +1,147 @@
import * as React from 'react'
import { StyleSheet } from 'react-native'
import { DrawerContentScrollView } from '@react-navigation/drawer'
import { Button, Drawer, Text, useTheme } from 'react-native-paper'
import Logo from '../Logo'
import { useTranslation } from 'react-i18next'
import SInfo from 'react-native-sensitive-info'
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
import { dropTables } from '../../Functions/DatabaseFunctions'
import { AppContext } from '../../Contexts/AppContext'
import { DrawerNavigationHelpers } from '@react-navigation/drawer/lib/typescript/src/types'
interface ItemList {
label: string
icon: string
key: number
right?: () => JSX.Element
}
interface MenuItemsProps {
navigation: DrawerNavigationHelpers;
}
export const MenuItems: React.FC<MenuItemsProps> = ({ navigation }) => {
const [drawerItemIndex, setDrawerItemIndex] = React.useState<number>(-1)
const { goToPage, database, init } = React.useContext(AppContext)
const { setPrivateKey, setPublicKey, relayPool, publicKey } = React.useContext(RelayPoolContext)
const { t } = useTranslation('common')
const theme = useTheme()
const onPressLogout: () => void = () => {
if (database) {
relayPool?.unsubscribeAll()
setPrivateKey(undefined)
setPublicKey(undefined)
dropTables(database).then(() => {
SInfo.deleteItem('privateKey', {}).then(() => {
SInfo.deleteItem('publicKey', {}).then(() => {
init()
goToPage('landing', true)
})
})
})
}
}
const onPressItem: (index:number) => void = (index) => {
setDrawerItemIndex(index)
navigation.navigate('About')
}
const relaysRightButton: () => JSX.Element = () => {
if (!relayPool || relayPool?.relays.length < 1) {
return <Text style={{color: theme.colors.error}}>{t('menuItems.notConnected')}</Text>
}
return <Text style={{color: theme.colors.inversePrimary}}>{t('menuItems.connectedRelays', { number: relayPool?.relays.length.toString()})}</Text>
}
const DrawerItemsData = React.useMemo(
() => {
if (!publicKey) return []
const defaultList: ItemList[] = [
{ label: t('menuItems.relays'), icon: 'message-question-outline', key: 0, right: relaysRightButton},
{ label: t('menuItems.configuration'), icon: 'cog-outline', key: 1 }
]
return defaultList
},
[publicKey],
)
const DrawerBottomItemsData = React.useMemo(
() => [{ label: t('menuItems.about'), icon: 'message-question-outline', key: 2 }],
[],
)
return (
<>
<DrawerContentScrollView
alwaysBounceVertical={false}
style={[
styles.drawerContent,
{
backgroundColor: theme.colors.background,
},
]}
>
<Drawer.Section showDivider={false}>
<Logo />
</Drawer.Section>
<Drawer.Section showDivider={publicKey !== undefined}>
{DrawerItemsData.map((props, index) => (
<Drawer.Item
label={props.label}
icon={props.icon}
key={props.key}
active={drawerItemIndex === index}
onPress={() => onPressItem(index)}
onTouchEnd={() => setDrawerItemIndex(-1)}
right={props.right}
/>
))}
</Drawer.Section>
<Drawer.Section showDivider={false}>
{DrawerBottomItemsData.map((props, index) => (
<Drawer.Item
label={props.label}
icon={props.icon}
key={props.key}
active={drawerItemIndex === DrawerItemsData.length + index}
onPress={() => onPressItem(DrawerItemsData.length + index)}
onTouchEnd={() => setDrawerItemIndex(-1)}
/>
))}
</Drawer.Section>
</DrawerContentScrollView>
{publicKey && (
<Drawer.Section
style={[
styles.bottomSection,
{
backgroundColor: theme.colors.background,
},
]}
showDivider={false}
>
<Button mode='outlined' onPress={onPressLogout}>
{t('menuItems.logout')}
</Button>
</Drawer.Section>
)}
</>
)
}
const styles = StyleSheet.create({
drawerContent: {
flex: 1,
borderBottomRightRadius: 28,
borderTopRightRadius: 28
},
bottomSection: {
padding: 24,
},
})
export default MenuItems

View File

@ -0,0 +1,106 @@
import * as React from 'react'
import { Platform, View } from 'react-native'
import type { DrawerNavigationProp } from '@react-navigation/drawer'
import { CardStyleInterpolators, createStackNavigator, StackNavigationProp } from '@react-navigation/stack'
import { Appbar, Snackbar, Text, useTheme } from 'react-native-paper'
import ProfileConnectPage from '../../Pages/ProfileConnectPage'
import ProfileLoadPage from '../../Pages/ProfileLoadPage'
import RBSheet from "react-native-raw-bottom-sheet"
import AboutPage from '../../Pages/AboutPage'
import { ParamListBase } from '@react-navigation/native'
import { useTranslation } from 'react-i18next'
export const RootNavigator: React.FC = () => {
const theme = useTheme()
const { t } = useTranslation('common')
const bottomSheetRef = React.useRef<RBSheet>(null)
const Stack = React.useMemo(() => createStackNavigator(), [])
const cardStyleInterpolator = React.useMemo(
() =>
Platform.OS === 'android'
? CardStyleInterpolators.forFadeFromBottomAndroid
: CardStyleInterpolators.forHorizontalIOS,
[],
)
const onPressQuestion: () => void = () => {
bottomSheetRef.current?.open()
}
const rightAction: (routeName: string, navigation: StackNavigationProp<ParamListBase, string, undefined>) => JSX.Element = (routeName, navigation) => {
if (['Logger', 'Loader'].includes(routeName)) {
return <Appbar.Action icon='help-circle-outline' isLeading onPress={onPressQuestion} />
} else if (['About'].includes(routeName)) {
return <></>
} else {
return <Appbar.Action icon='cog-outline' isLeading onPress={onPressQuestion} />
}
}
return (
<>
<Stack.Navigator
screenOptions={({ navigation }) => {
return {
detachPreviousScreen: !navigation.isFocused(),
cardStyleInterpolator,
header: ({ navigation, route, options, back }) => {
return (
<Appbar.Header>
{back ? (
<Appbar.BackAction onPress={() => navigation.goBack()} />
) : (navigation as any).openDrawer ? (
<Appbar.Action
icon='menu'
isLeading
onPress={() => (navigation as any as DrawerNavigationProp<{}>).openDrawer()}
/>
) : null}
<Appbar.Content title={t(`loggerPage.${route.name}`)} />
{rightAction(route.name, navigation)}
</Appbar.Header>
)
},
}
}}
>
<Stack.Group>
<Stack.Screen name='Logger' component={ProfileConnectPage} />
<Stack.Screen name='Loader' component={ProfileLoadPage} />
</Stack.Group>
<Stack.Group>
<Stack.Screen name='About' component={AboutPage} />
</Stack.Group>
</Stack.Navigator>
<RBSheet
ref={bottomSheetRef}
closeOnDragDown={true}
height={380}
customStyles={{
container: {
backgroundColor: theme.colors.background,
padding: 16,
},
draggableIcon: {
backgroundColor: "#000"
}
}}
>
<View>
<Text variant="headlineSmall">¿Qué son las claves?</Text>
<Text variant="bodyMedium">En nostr tienes dos claves: tu clave pública y tu clave privada.</Text>
<Text variant="titleMedium">Clave pública</Text>
<Text variant="bodyMedium">Piensa en la clave pública como tu nombre de usuario (como tu @handle en Twitter). Compártela con otras personas para que te añadan a su red.</Text>
<Text variant="titleMedium">Clave privada</Text>
<Text variant="bodyMedium">Piensa en tu clave privada como tu contraseña.</Text>
<Snackbar visible onDismiss={() => {}}>
Muy importante.
Guarda tu clave privada en un lugar seguro, si la pierdes no podrás volver a acceder con ella ni recuperar tu cuenta.
</Snackbar>
</View>
</RBSheet>
</>
)
}
export default RootNavigator

View File

@ -1,32 +1,2 @@
import React from 'react'
import { Animated, Easing } from 'react-native'
import { SvgXml } from 'react-native-svg'
interface LoadingProps {
style?: object
}
export const Loading: React.FC<LoadingProps> = ({ style = {} }) => {
const logo =
export const nostrosLogoSvg =
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs" viewBox="0 0 800 800"><g stroke="hsl(0, 0%, 100%)" fill="none" stroke-linecap="round" style="--darkreader-inline-stroke: #e8e6e3;" data-darkreader-inline-stroke=""><circle r="256" cx="400" cy="400" stroke-width="24" stroke-dasharray="68 51" stroke-dashoffset="25" transform="rotate(309, 400, 400)" opacity="1.00"></circle><circle r="224" cx="400" cy="400" stroke-width="23" stroke-dasharray="76 63" stroke-dashoffset="25" transform="rotate(258, 400, 400)" opacity="0.86"></circle><circle r="192" cx="400" cy="400" stroke-width="22" stroke-dasharray="63 31" stroke-dashoffset="25" transform="rotate(74, 400, 400)" opacity="0.73"></circle><circle r="160" cx="400" cy="400" stroke-width="21" stroke-dasharray="75 71" stroke-dashoffset="25" transform="rotate(62, 400, 400)" opacity="0.59"></circle><circle r="128" cx="400" cy="400" stroke-width="21" stroke-dasharray="43 37" stroke-dashoffset="25" transform="rotate(333, 400, 400)" opacity="0.46"></circle><circle r="96" cx="400" cy="400" stroke-width="20" stroke-dasharray="65 73" stroke-dashoffset="25" transform="rotate(17, 400, 400)" opacity="0.32"></circle><circle r="64" cx="400" cy="400" stroke-width="19" stroke-dasharray="33 58" stroke-dashoffset="25" transform="rotate(269, 400, 400)" opacity="0.19"></circle><circle r="32" cx="400" cy="400" stroke-width="18" stroke-dasharray="66 52" stroke-dashoffset="25" transform="rotate(281, 400, 400)" opacity="0.05"></circle></g></svg>'
const spinValue = new Animated.Value(0)
Animated.timing(spinValue, {
toValue: 1,
duration: 200000,
easing: Easing.linear, // Easing is an additional import from react-native
useNativeDriver: true, // To make use of native driver for performance
}).start()
const spin = spinValue.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '4032deg'],
})
return (
<Animated.View style={{ ...style, ...{ transform: [{ rotate: spin }] } }}>
<SvgXml xml={logo} />
</Animated.View>
)
}
export default Loading

View File

@ -0,0 +1,43 @@
{
"colors": {
"primary": "#B5C4FF",
"onPrimary": "#042978",
"primaryContainer": "#264190",
"onPrimaryContainer": "#DCE1FF",
"secondary": "#A1C9FF",
"onSecondary": "#00325A",
"secondaryContainer": "#00487F",
"onSecondaryContainer": "#D2E4FF",
"tertiary": "#FFAFD2",
"onTertiary": "#62023F",
"tertiaryContainer": "#7F2056",
"onTertiaryContainer": "#FFD8E7",
"error": "#FFB4AB",
"onError": "#690005",
"errorContainer": "#93000A",
"onErrorContainer": "#FFDAD6",
"background": "#001B3D",
"onBackground": "#D6E3FF",
"surface": "#001B3D",
"onSurface": "#D6E3FF",
"surfaceVariant": "#45464F",
"onSurfaceVariant": "#C6C6D0",
"outline": "#8F909A",
"outlineVariant": "#45464F",
"shadow": "#000000",
"scrim": "#000000",
"inverseSurface": "#D6E3FF",
"inverseOnSurface": "#001B3D",
"inversePrimary": "#405AA9",
"elevation": {
"level0": "transparent",
"level1": "#092541",
"level2": "#0E2A47",
"level3": "#142F4D",
"level4": "#16304F",
"level5": "#193353"
},
"warning": "#D69242",
"success": "#369734"
}
}

View File

@ -1,7 +1,6 @@
import React, { useEffect, useState } from 'react'
import { QuickSQLiteConnection } from 'react-native-quick-sqlite'
import { initDatabase } from '../Functions/DatabaseFunctions'
import FlashMessage from 'react-native-flash-message'
import SInfo from 'react-native-sensitive-info'
import { BackHandler } from 'react-native'
@ -84,7 +83,6 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): JSX.E
}}
>
{children}
<FlashMessage position='top' />
</AppContext.Provider>
)
}

View File

@ -54,7 +54,6 @@ export const RelayPoolContextProvider = ({
setLastEventId(event.eventId)
}
const changeConfirmationIdHandler: (event: WebsocketEvent) => void = (event) => {
console.log('changeConfirmationIdHandler', event)
setLastConfirmationId(event.eventId)
}

View File

@ -1,117 +1,12 @@
{
"common": {
"landing": {
"connect": "Connect",
"connecting": "Connecting",
"loadingContacts": "Loading contacts",
"loadingEvents": "Loading events",
"ready": "Ready",
"privateKey": "Private key",
"publicKey": "Public key"
"loggerPage": {
"Logger": ""
},
"navigationBar": {
"home": "Home",
"profile": "Profile"
},
"homePage": {
"search": "Search",
"send": "Send",
"noContacts": "You have no contacts yet",
"addContacts": "Add contacts"
},
"logger": {
"randomKeyGenerator": {
"message": "Your private key is on your clipboard",
"description": "Store it on a safe place to recover your user"
}
},
"lnPayment": {
"monto": "Amount",
"comment": "Comment (optional)",
"copy": "Copy",
"openApp": "Open App"
},
"profilePage": {
"search": "Search",
"send": "Send",
"profileNotCreated": "Profile not published",
"createProfile": "Go to configuration"
},
"relaysPage": {
"title": "Relays",
"addRelay": {
"placeholder": "Relay URL",
"invalidFormat": "Invalid Format",
"add": "Add relay"
}
},
"loader": {
"searchingProfile": "Searching your profile",
"profileFound": "Profile found",
"searchingContacts": "Searching contacts:",
"help1": "Problems loading your data?",
"help2": "Try connecting to other relays.",
"menuItems": {
"relays": "Relays",
"home": "Go to Home"
},
"notePage": {
"reply": "Reply"
},
"configPage": {
"title": "Configuration",
"logout": "Delete keys",
"relays": "Relays",
"publicKey": "Public key",
"privateKey": "Private key",
"username": "Username",
"picture": "Picture URL",
"lnurl": "LNURL / Lightning address",
"nip05": "NIP05",
"about": "About",
"publish": "Publish"
},
"direcMessagesPage": {
"sendMessage": {
"placeholder": "Public key",
"send": "Open conversation",
"contacts": "Contacts"
}
},
"contactsPage": {
"following": "Following",
"followers": "Followers",
"add": "Add user",
"addContact": {
"placeholder": "Public key",
"add": "Add user"
}
},
"mentionsPage": {
"noMentions": "No mentions found yet."
},
"sendPage": {
"title": "Send a note",
"placeholder": "Say something to the world...",
"send": "Send",
"reply": "Send a reply",
"contentWarning": "Sensitive content"
},
"alerts": {
"relayAdded": "Relay added",
"relayRemoved": "Relay removed",
"profilePublished": "Profile published",
"profilePublishError": "There was an error while publishing the profile",
"invoiceCopied": "Invoice copied",
"invoiceError": "There was an error while trying to obtain the invoice",
"sendNoteSuccess": "Note sent",
"sendNoteError": "There was an error while sending the note",
"sendGetNotesError": "There was an internal error retrieving notes",
"contactAddError": "There was an error while adding the contact",
"privateMessageEncryptError": "There was an error while encrypting the DM",
"privateMessageSendError": "There was an error while sending the DM"
},
"note": {
"contentWarning": "Sensitive content. Tap to show."
"notConnected": "Not connected",
"connectedRelays": "{{number}} connected"
}
}
}

View File

@ -0,0 +1,61 @@
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { FlatList, Linking, ListRenderItem, StyleSheet } from 'react-native'
import { Divider, List } from 'react-native-paper'
interface ItemList {
key: number
title: string
left?: () => JSX.Element
onPress: () => void
}
export const AboutPage: React.FC = () => {
const { t } = useTranslation('common')
const items = React.useMemo(
() => [
{
key: 1,
title: t('aboutPage.gitHub'),
left: () => <List.Icon icon='chart-tree' />,
onPress: async () => await Linking.openURL('https://github.com/KoalaSat/nostros'),
},
{
key: 2,
title: t('aboutPage.nostr'),
left: () => <List.Icon icon='chart-tree' />,
onPress: async () => await Linking.openURL('https://usenostr.org'),
},
{
key: 3,
title: t('aboutPage.nips'),
left: () => <List.Icon icon='chart-tree' />,
onPress: async () => await Linking.openURL('https://github.com/nostr-protocol/nips'),
},
],
[],
)
const renderItem: ListRenderItem<ItemList> = ({ item }) => {
return <List.Item key={item.key} title={item.title} onPress={item.onPress} left={item.left} />
}
return (
<FlatList
style={styles.container}
showsVerticalScrollIndicator={false}
ItemSeparatorComponent={Divider}
data={items}
renderItem={renderItem}
/>
)
}
const styles = StyleSheet.create({
container: {
padding: 16,
},
})
export default AboutPage

View File

@ -1,128 +0,0 @@
import React, { useContext, useState } from 'react'
import { Button, Input, Layout, useTheme } from '@ui-kitten/components'
import { Clipboard, StyleSheet } from 'react-native'
import { RelayPoolContext } from '../../../Contexts/RelayPoolContext'
import { useTranslation } from 'react-i18next'
import Icon from 'react-native-vector-icons/FontAwesome5'
import { generateRandomKey } from '../../../lib/nostr/Bip'
import { showMessage } from 'react-native-flash-message'
import { getNip19Key, isPrivateKey, isPublicKey } from '../../../lib/nostr/Nip19'
export const Logger: React.FC = () => {
const { publicKey, setPrivateKey, setPublicKey } = useContext(RelayPoolContext)
const { t } = useTranslation('common')
const theme = useTheme()
const [isPrivate, setIsPrivate] = useState<boolean>(true)
const [inputValue, setInputValue] = useState<string>('')
const onPress: () => void = () => {
if (inputValue && inputValue !== '') {
const isBenchPrivate = isPrivateKey(inputValue)
const isBenchPublic = isPublicKey(inputValue)
if (isBenchPrivate) setIsPrivate(true)
if (isBenchPublic) setIsPrivate(false)
const key = getNip19Key(inputValue)
if ((isPrivate && !isBenchPublic) || isBenchPrivate) {
setPrivateKey(key)
} else {
setPublicKey(key)
}
}
}
const randomKeyGenerator: () => JSX.Element = () => {
if (!isPrivate) return <></>
const storeRandomPrivateKey: () => void = () => {
generateRandomKey().then((string) => {
setInputValue(string)
Clipboard.setString(string)
showMessage({
message: t('logger.randomKeyGenerator.message'),
description: t('logger.randomKeyGenerator.description'),
duration: 8000,
type: 'info',
})
})
}
return (
<Icon
name={'dice'}
size={16}
color={theme['text-basic-color']}
solid
onPress={storeRandomPrivateKey}
/>
)
}
const styles = StyleSheet.create({
inputsContainer: {
flexDirection: 'row',
marginVertical: 10,
padding: 32,
},
buttonssContainer: {
flexDirection: 'row',
paddingLeft: 32,
paddingRight: 32,
},
input: {
flex: 4,
},
buttonLeft: {
flex: 3,
paddingRight: 16,
},
buttonRight: {
flex: 3,
paddingLeft: 16,
},
})
const keyButton = (
<Icon name={isPrivate ? 'lock' : 'eye'} size={16} color={theme['text-basic-color']} solid />
)
const label: string = isPrivate ? t('landing.privateKey') : t('landing.publicKey')
return (
<>
<Layout style={styles.inputsContainer}>
<Layout style={styles.input}>
<Input
size='medium'
label={label}
onChangeText={setInputValue}
value={inputValue}
disabled={publicKey !== undefined}
accessoryRight={randomKeyGenerator}
/>
</Layout>
</Layout>
<Layout style={styles.buttonssContainer}>
<Layout style={styles.buttonLeft}>
<Button
onPress={() => {
setIsPrivate(!isPrivate)
setInputValue('')
}}
disabled={publicKey !== undefined}
accessoryLeft={keyButton}
status={isPrivate ? 'warning' : 'default'}
/>
</Layout>
<Layout style={styles.buttonRight}>
<Button onPress={onPress} disabled={publicKey !== undefined}>
{t('landing.connect')}
</Button>
</Layout>
</Layout>
</>
)
}
export default Logger

View File

@ -1,73 +0,0 @@
import React, { useContext } from 'react'
import { Layout, Text, useTheme } from '@ui-kitten/components'
import { Linking, StyleSheet, TouchableOpacity } from 'react-native'
import Loading from '../../Components/Loading'
import Logger from './Logger'
import Loader from './Loader'
import Icon from 'react-native-vector-icons/FontAwesome5'
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
export const LandingPage: React.FC = () => {
const { publicKey } = useContext(RelayPoolContext)
const theme = useTheme()
const onPressQuestion: () => void = () => {
Linking.openURL('https://usenostr.org')
}
const styles = StyleSheet.create({
tab: {
height: '100%',
alignItems: 'center',
justifyContent: 'center',
},
info: {
alignItems: 'flex-end',
flexDirection: 'row',
padding: 24,
paddingBottom: -12,
},
svg: {
height: 340,
width: 340,
},
icon: {
marginRight: 24,
},
title: {
marginTop: -40,
marginBottom: -20,
fontFamily: 'SpaceGrotesk-Bold',
fontSize: 45,
},
action: {
backgroundColor: 'transparent',
marginTop: 30,
},
})
return (
<>
<Layout style={styles.info}>
<TouchableOpacity onPress={onPressQuestion}>
<Icon name='question' style={styles.icon} size={24} color={theme['text-basic-color']} />
</TouchableOpacity>
</Layout>
<Layout style={styles.tab}>
<Layout style={styles.svg}>
<Loading />
</Layout>
{!publicKey ? (
<>
<Text style={styles.title}>NOSTROS</Text>
<Logger />
</>
) : (
<Loader />
)}
</Layout>
</>
)
}
export default LandingPage

View File

@ -1,55 +1,42 @@
import React, { useContext } from 'react'
import { Layout } from '@ui-kitten/components'
import { StyleSheet } from 'react-native'
import { AppContext } from '../../Contexts/AppContext'
import HomePage from '../HomePage'
import ProfilePage from '../ProfilePage'
import NavigationBar from '../../Components/NavigationBar'
import SendPage from '../SendPage'
import ContactsPage from '../ContactsPage'
import NotePage from '../NotePage'
import LandingPage from '../LandingPage'
import ConfigPage from '../ConfigPage'
import RelaysPage from '../RelaysPage'
import DirectMessagesPage from '../DirectMessagesPage'
import ConversationPage from '../ConversationPage'
import Loading from '../../Components/Loading'
import MentionsPage from '../MentionsPage'
import { createDrawerNavigator } from '@react-navigation/drawer';
import { Appbar } from 'react-native-paper'
export const MainLayout: React.FC = () => {
const { page } = useContext(AppContext)
const styles = StyleSheet.create({
container: {
flex: 1,
},
})
const pagination: Record<string, JSX.Element> = {
'': <Loading />,
mentions: <MentionsPage />,
landing: <LandingPage />,
home: <HomePage />,
send: <SendPage />,
profile: <ProfilePage />,
contacts: <ContactsPage />,
note: <NotePage />,
config: <ConfigPage />,
relays: <RelaysPage />,
messages: <DirectMessagesPage />,
conversation: <ConversationPage />,
}
// const pagination: Record<string, JSX.Element> = {
// '': <Loading />,
// mentions: <MentionsPage />,
// landing: <LandingPage />,
// home: <HomePage />,
// send: <SendPage />,
// profile: <ProfilePage />,
// contacts: <ContactsPage />,
// note: <NotePage />,
// config: <ConfigPage />,
// relays: <RelaysPage />,
// messages: <DirectMessagesPage />,
// conversation: <ConversationPage />,
// }
const breadcrump: string[] = page.split('%')
const pageToDisplay: string = breadcrump[breadcrump.length - 1].split('#')[0]
const DrawerNavigator = createDrawerNavigator<{ Home: undefined }>();
return (
<>
<Layout style={styles.container} level='4'>
{pagination[pageToDisplay]}
</Layout>
{pageToDisplay === 'landing' ? <></> : <NavigationBar />}
</>
// <>
// {pagination[pageToDisplay]}
// {pageToDisplay === 'landing' ? <></> : <NavigationBar />}
// </>
<Appbar.Header>
<Appbar.BackAction onPress={() => {}} />
<Appbar.Content title="Title" />
<Appbar.Action icon="calendar" onPress={() => {}} />
<Appbar.Action icon="magnify" onPress={() => {}} />
</Appbar.Header>
)
}

View File

@ -0,0 +1,98 @@
import React, { useContext, useState } from 'react'
import { Clipboard, StyleSheet, View } from 'react-native'
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
import { useTranslation } from 'react-i18next'
import { getNip19Key, isPrivateKey, isPublicKey } from '../../lib/nostr/Nip19'
import { Button, Switch, Text, TextInput } from 'react-native-paper'
import Logo from '../../Components/Logo'
export const ProfileConnectPage: React.FC = () => {
const { setPrivateKey, setPublicKey } = useContext(RelayPoolContext)
const { t } = useTranslation('common')
const [isPublic, setIsPublic] = useState<boolean>(false)
const [inputValue, setInputValue] = useState<string>('')
const onPress: () => void = () => {
if (inputValue && inputValue !== '') {
const isBenchPrivate = isPrivateKey(inputValue)
const isBenchPublic = isPublicKey(inputValue)
if (isBenchPrivate) setIsPublic(true)
if (isBenchPublic) setIsPublic(false)
const key = getNip19Key(inputValue)
if ((!isPublic && !isBenchPublic) || isBenchPrivate) {
setPrivateKey(key)
} else {
setPublicKey(key)
}
}
}
const pasteContent: () => void = () => {
Clipboard.getString().then((value) => {
setInputValue(value ?? '')
})
}
const label: string = React.useMemo(() => isPublic ? t('loggerPage.publicKey') : t('loggerPage.privateKey'), [isPublic])
return (
<>
<View style={styles.container}>
<Logo size='large'/>
<View>
<TextInput
mode='outlined'
label={label}
placeholder={t('loggerPage.placeholder') ?? ''}
onChangeText={setInputValue}
value={inputValue}
secureTextEntry={!isPublic}
right={
<TextInput.Icon
icon={inputValue ? 'close-circle-outline' : 'content-paste'}
onPress={() =>
inputValue ? setInputValue('') : pasteContent()
}
forceTextInputFocus={false}
/>
}
/>
<Button mode='contained' onPress={onPress}>
{t('loggerPage.accessButton')}
</Button>
</View>
<View>
<View style={styles.row}>
<Text>{t('loggerPage.isPublic')}</Text>
<Switch
value={isPublic}
onValueChange={() => setIsPublic(!isPublic)}
/>
</View>
<View style={styles.row}>
<Text>{t('loggerPage.notKeys')}</Text>
<Button mode='text' onPress={() => console.log('Pressed')}>
{t('loggerPage.createButton')}
</Button>
</View>
</View>
</View>
</>
)
}
const styles = StyleSheet.create({
container: {
padding: 16,
},
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
})
export default ProfileConnectPage

View File

@ -0,0 +1,46 @@
import React, { useState } from 'react'
import { generateRandomKey } from '../../lib/nostr/Bip'
import { Clipboard } from 'react-native'
export const ProfileCreatePage: React.FC = () => {
const [inputValue, setInputValue] = useState<string>('')
const randomKeyGenerator: () => JSX.Element = () => {
generateRandomKey().then((string) => {
setInputValue(string)
Clipboard.setString(string)
})
}
return (
<>
{/* <Layout style={styles.text}>
<Text>{profileFound ? t('loader.profileFound') : t('loader.searchingProfile')}</Text>
<Text>{`${t('loader.searchingContacts')} ${contactsCount}`}</Text>
</Layout>
<Layout>
<Text>{t('loader.help1')}</Text>
<Text>{t('loader.help2')}</Text>
</Layout>
<Layout style={styles.action}>
<Button
onPress={() => goToPage('relays')}
status='warning'
accessoryLeft={<Icon name='server' size={16} color={theme['text-basic-color']} solid />}
>
{t('loader.relays')}
</Button>
</Layout>
<Layout style={styles.action}>
<Button
onPress={() => goToPage('home')}
accessoryLeft={<Icon name='home' size={16} color={theme['text-basic-color']} solid />}
>
{t('loader.home')}
</Button>
</Layout> */}
</>
)
}
export default ProfileCreatePage

View File

@ -1,18 +1,14 @@
import React, { useContext, useEffect, useState } from 'react'
import { Button, Layout, Text, useTheme } from '@ui-kitten/components'
import { StyleSheet } from 'react-native'
import { RelayPoolContext } from '../../../Contexts/RelayPoolContext'
import { EventKind } from '../../../lib/nostr/Events'
import { AppContext } from '../../../Contexts/AppContext'
import { getUser, getUsers, User } from '../../../Functions/DatabaseFunctions/Users'
import Icon from 'react-native-vector-icons/FontAwesome5'
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
import { EventKind } from '../../lib/nostr/Events'
import { AppContext } from '../../Contexts/AppContext'
import { getUser, getUsers, User } from '../../Functions/DatabaseFunctions/Users'
import { useTranslation } from 'react-i18next'
import moment from 'moment'
export const Loader: React.FC = () => {
export const ProfileLoadPage: React.FC = () => {
const { goToPage, loadingDb, database } = useContext(AppContext)
const { publicKey, relayPool, lastEventId, loadingRelayPool } = useContext(RelayPoolContext)
const theme = useTheme()
const { t } = useTranslation('common')
const [profileFound, setProfileFound] = useState<boolean>(false)
const [contactsCount, setContactsCount] = useState<number>()
@ -61,25 +57,9 @@ export const Loader: React.FC = () => {
}
}
const styles = StyleSheet.create({
container: {
padding: 32,
},
text: {
marginVertical: 10,
padding: 32,
alignItems: 'center',
justifyContent: 'center',
},
action: {
backgroundColor: 'transparent',
marginTop: 12,
},
})
return (
<>
<Layout style={styles.text}>
{/* <Layout style={styles.text}>
<Text>{profileFound ? t('loader.profileFound') : t('loader.searchingProfile')}</Text>
<Text>{`${t('loader.searchingContacts')} ${contactsCount}`}</Text>
</Layout>
@ -103,9 +83,9 @@ export const Loader: React.FC = () => {
>
{t('loader.home')}
</Button>
</Layout>
</Layout> */}
</>
)
}
export default Loader
export default ProfileLoadPage

View File

@ -15,7 +15,7 @@ import Icon from 'react-native-vector-icons/FontAwesome5'
import { useTranslation } from 'react-i18next'
import { RelayPoolContext } from '../../Contexts/RelayPoolContext'
import { getRelays, Relay } from '../../Functions/DatabaseFunctions/Relays'
import { defaultRelays, REGEX_SOCKET_LINK } from '../../Constants/RelayConstants'
import { defaultRelays, REGEX_SOCKET_LINK } from '../../Constants/Relay'
import { showMessage } from 'react-native-flash-message'
export const RelaysPage: React.FC = () => {

View File

@ -1,35 +1,76 @@
import React from 'react'
import { ApplicationProvider, IconRegistry } from '@ui-kitten/components'
import theme from './theme.json'
import { EvaIconsPack } from '@ui-kitten/eva-icons'
import * as eva from '@eva-design/eva'
import { AppContextProvider } from './Contexts/AppContext'
import MainLayout from './Pages/MainLayout'
import {
InitialState,
NavigationContainer,
DefaultTheme as NavigationDefaultTheme,
DarkTheme as NavigationDarkTheme,
} from '@react-navigation/native'
import { createDrawerNavigator } from '@react-navigation/drawer'
import { RelayPoolContextProvider } from './Contexts/RelayPoolContext'
import { I18nextProvider } from 'react-i18next'
import { adaptNavigationTheme, Provider as PaperProvider } from 'react-native-paper'
import { SafeAreaProvider, SafeAreaInsetsContext } from 'react-native-safe-area-context'
import i18n from './i18n.config'
import nostrosDarkTheme from './Constants/Theme/theme-dark.json'
import RootNavigator from './Components/RootNavigator'
import MenuItems from './Components/MenuItems'
export const Frontend: React.FC = (props) => {
const mapping = {
strict: {
'text-font-family': 'OpenSans-Regular',
},
components: {},
}
const DrawerNavigator = createDrawerNavigator()
export const Frontend: React.FC = () => {
const [initialState, setInitialState] = React.useState<InitialState | undefined>()
const { LightTheme, DarkTheme } = adaptNavigationTheme({
reactNavigationLight: NavigationDefaultTheme,
reactNavigationDark: NavigationDarkTheme,
})
const CombinedDefaultTheme = React.useMemo(() => {
return {
...DarkTheme,
...nostrosDarkTheme,
colors: {
...DarkTheme.colors,
...nostrosDarkTheme.colors,
},
}
}, [])
return (
<>
<IconRegistry icons={EvaIconsPack} />
<ApplicationProvider {...eva} theme={{ ...eva.dark, ...theme }} customMapping={mapping}>
<PaperProvider theme={nostrosDarkTheme}>
<SafeAreaProvider>
<I18nextProvider i18n={i18n}>
<AppContextProvider>
<RelayPoolContextProvider>
<MainLayout />
<React.Fragment>
<NavigationContainer theme={CombinedDefaultTheme} initialState={initialState}>
<SafeAreaInsetsContext.Consumer>
{() => {
return (
<DrawerNavigator.Navigator
drawerContent={({navigation}) => <MenuItems navigation={navigation}/>}
screenOptions={{
drawerStyle: {
borderRadius: 28
},
}}
>
<DrawerNavigator.Screen
name='Home'
component={RootNavigator}
options={{ headerShown: false }}
/>
</DrawerNavigator.Navigator>
)
}}
</SafeAreaInsetsContext.Consumer>
</NavigationContainer>
</React.Fragment>
</RelayPoolContextProvider>
</AppContextProvider>
</I18nextProvider>
</ApplicationProvider>
</>
</SafeAreaProvider>
</PaperProvider>
)
}

View File

@ -21,15 +21,17 @@ export interface RelayMessage {
class RelayPool {
constructor(relaysUrls: string[], privateKey?: string) {
this.privateKey = privateKey
this.relays = relaysUrls
this.subscriptions = {}
relaysUrls.forEach((relayUrl) => {
this.relays.forEach((relayUrl) => {
this.add(relayUrl)
})
}
private readonly privateKey?: string
private subscriptions: Record<string, string[]>
public relays: string[]
private readonly send: (message: object) => void = async (message) => {
const tosend = JSON.stringify(message)
@ -46,6 +48,7 @@ class RelayPool {
callback = () => {},
) => {
RelayPoolModule.add(relayUrl, callback)
this.relays.push(relayUrl)
}
public readonly remove: (relayUrl: string, callback?: () => void) => void = async (
@ -53,6 +56,7 @@ class RelayPool {
callback = () => {},
) => {
RelayPoolModule.remove(relayUrl, callback)
this.relays = this.relays.filter((relay) => relay === relayUrl)
}
public readonly sendEvent: (event: Event) => Promise<Event | null> = async (event) => {

View File

@ -13,10 +13,10 @@
"dependencies": {
"@eva-design/eva": "^2.1.0",
"@flyerhq/react-native-link-preview": "^1.6.0",
"@react-navigation/drawer": "^6.5.7",
"@react-navigation/native": "^6.1.2",
"@react-navigation/stack": "^6.3.11",
"@scure/base": "^1.1.1",
"@ui-kitten/components": "5.1.2",
"@ui-kitten/eva-icons": "5.1.2",
"@ui-kitten/metro-config": "5.1.2",
"assert": "^2.0.0",
"bip-schnorr": "^0.6.6",
"buffer": "^6.0.3",
@ -35,11 +35,15 @@
"react-native": "0.70.6",
"react-native-action-button": "^2.8.5",
"react-native-bidirectional-infinite-scroll": "^0.3.3",
"react-native-flash-message": "^0.3.1",
"react-native-gesture-handler": "^2.8.0",
"react-native-multithreading": "^1.1.1",
"react-native-paper": "^5.1.3",
"react-native-parsed-text": "^0.0.22",
"react-native-quick-sqlite": "^6.1.1",
"react-native-reanimated": "^2.13.0",
"react-native-raw-bottom-sheet": "^2.2.0",
"react-native-reanimated": "^2.14.0",
"react-native-safe-area-context": "^4.4.1",
"react-native-screens": "^3.18.2",
"react-native-securerandom": "^1.0.1",
"react-native-sensitive-info": "^5.5.8",
"react-native-svg": "^13.5.0",

273
yarn.lock
View File

@ -1010,6 +1010,21 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@callstack/react-theme-provider@^3.0.8":
version "3.0.8"
resolved "https://registry.yarnpkg.com/@callstack/react-theme-provider/-/react-theme-provider-3.0.8.tgz#d0d7ac71e422133c5f7b78f4c4aa1bc57f156f50"
integrity sha512-5U231sYY2sqQOaELX0WBCn+iluV8bFaXIS7em03k4W5Xz0AhGvKlnpLIhDGFP8im/SvNW7/2XoR0BsClhn9t6Q==
dependencies:
deepmerge "^3.2.0"
hoist-non-react-statics "^3.3.0"
"@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"
"@eslint/eslintrc@^1.4.1":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e"
@ -1025,21 +1040,11 @@
minimatch "^3.1.2"
strip-json-comments "^3.1.1"
"@eva-design/dss@^2.0.0":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@eva-design/dss/-/dss-2.1.1.tgz#bd8da793e13a0dcac91d852b91ebf05e6fbdc0ee"
integrity sha512-Z6rZSodsQHWW1yDuiop1glJU8xKJSdKTPoWWCBsQWXYMNwTAEPgcZV69HNlnerB+T++jwj2jeoBzO24CTc0PmQ==
"@eva-design/eva@^2.1.0":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@eva-design/eva/-/eva-2.1.1.tgz#ad237ae76d63e7c474b3a0755c697490bbe5a4bc"
integrity sha512-WS1ykETXyq0Kxa0aFlPMBeftEtBeTDv9qEUeQ4VvbTETMc7hsZPSkPr2HudtQhFihiM72GFfwAK6GIAlF6GXdQ==
"@eva-design/processor@^2.0.0":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@eva-design/processor/-/processor-2.1.1.tgz#33a59efa52ee2d206ac4d912dae801d12f9275a8"
integrity sha512-lbxZLm5ARhuk/wxWkaiWhw5XeZ+Xcp1JGCjcZl+S5rUbLppfp4U47jfq861EY27BP1dpQ5PyTVFCbl5eHlRFdg==
"@flyerhq/react-native-link-preview@^1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@flyerhq/react-native-link-preview/-/react-native-link-preview-1.6.0.tgz#c7285ab93a133328edc5d69b011822581bb4414b"
@ -1629,6 +1634,58 @@
resolved "https://registry.yarnpkg.com/@react-native/polyfills/-/polyfills-2.0.0.tgz#4c40b74655c83982c8cf47530ee7dc13d957b6aa"
integrity sha512-K0aGNn1TjalKj+65D7ycc1//H9roAQ51GJVk5ZJQFb2teECGmzd86bYDC0aYdbRf7gtovescq4Zt6FR0tgXiHQ==
"@react-navigation/core@^6.4.6":
version "6.4.6"
resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.4.6.tgz#b0738667dec5927b01c4c496c2f4c73ef8a5e4dd"
integrity sha512-6zaAgUT5k4vhJlddUk2l52RZyMkMelHdrRv1cL57ALi2RZzERdgmbiMKhJerxFLn9S8E3PUe8vwxHzjHOZKG4w==
dependencies:
"@react-navigation/routers" "^6.1.6"
escape-string-regexp "^4.0.0"
nanoid "^3.1.23"
query-string "^7.1.3"
react-is "^16.13.0"
use-latest-callback "^0.1.5"
"@react-navigation/drawer@^6.5.7":
version "6.5.7"
resolved "https://registry.yarnpkg.com/@react-navigation/drawer/-/drawer-6.5.7.tgz#a687dd909d9f4ae92e07f3cc295986761d19e340"
integrity sha512-k8l+G05WrP+Il8USxEcaBtZ2Jv/JFn9dS8O1IlqIoddZITrFjsyDhk3zxeE3RWDcc9u0o7HgHfgKHPXxcT8QRQ==
dependencies:
"@react-navigation/elements" "^1.3.13"
color "^4.2.3"
warn-once "^0.1.0"
"@react-navigation/elements@^1.3.13":
version "1.3.13"
resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.13.tgz#5105fa26df8d32810cd9f14d6ec5a3d2c2bb26d2"
integrity sha512-LqqK5s2ZfYHn2cQ376jC5V9dQztLH5ixkkJj9WR7JY2g4SghDd39WJhL3Jillw1Mu3F3b9sZwvAK+QkXhnDeAA==
"@react-navigation/native@^6.1.2":
version "6.1.2"
resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.2.tgz#6fffbf4787c233687fff8fe9ce7364ffce696d38"
integrity sha512-qLUe0asHofr5EhxKjvUBJ9DrPPmR4535IEwmW3oU4DRb3cLbNysjajJKHL8kcYtqPvn9Bx9QZG2x0PMb2vN23A==
dependencies:
"@react-navigation/core" "^6.4.6"
escape-string-regexp "^4.0.0"
fast-deep-equal "^3.1.3"
nanoid "^3.1.23"
"@react-navigation/routers@^6.1.6":
version "6.1.6"
resolved "https://registry.yarnpkg.com/@react-navigation/routers/-/routers-6.1.6.tgz#f57f2a73855d329255aa225fdad75ae8e7700c6d"
integrity sha512-Z5DeCW3pUvMafbU9Cjy1qJYC2Bvl8iy3+PfsB0DsAwQ6zZ3WAXW5FTMX4Gb9H+Jg6qHWGbMFFwlYpS3UJ3tlVQ==
dependencies:
nanoid "^3.1.23"
"@react-navigation/stack@^6.3.11":
version "6.3.11"
resolved "https://registry.yarnpkg.com/@react-navigation/stack/-/stack-6.3.11.tgz#5f5e93a34e4492d7baa3f29bddf822489724ec4e"
integrity sha512-GWOAyJfPEsjVwDWec1ERwWL5LvManJucCRUZetJqCBs4/mV7HXEt2x6l3SMitHxH1+K+9XuYXI+wBTbK1WDYOA==
dependencies:
"@react-navigation/elements" "^1.3.13"
color "^4.2.3"
warn-once "^0.1.0"
"@scure/base@^1.1.1", "@scure/base@~1.1.0":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938"
@ -1741,10 +1798,10 @@
dependencies:
"@types/node" "*"
"@types/invariant@^2.2.35":
version "2.2.35"
resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.35.tgz#cd3ebf581a6557452735688d8daba6cf0bd5a3be"
integrity sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg==
"@types/hammerjs@^2.0.36":
version "2.0.41"
resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.41.tgz#f6ecf57d1b12d2befcce00e928a6a097c22980aa"
integrity sha512-ewXv/ceBaJprikMcxCmWU1FKyMAQ2X7a9Gtmzw8fcg2kIePI1crERDM818W+XYrxqdBBOdlf2rm137bU+BltCA==
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
version "2.0.4"
@ -2102,29 +2159,6 @@
"@typescript-eslint/types" "5.43.0"
eslint-visitor-keys "^3.3.0"
"@ui-kitten/components@5.1.2":
version "5.1.2"
resolved "https://registry.yarnpkg.com/@ui-kitten/components/-/components-5.1.2.tgz#18b6aba8ed67b0b893f0ec3f40daf5e698676811"
integrity sha512-J1Gd53+2qngktLSKot9aT+LGhUt05uGE3ouEiY6FsxUZdexlzcQVhp5rRasExUSAYNcN5J7/XSNEPNB9qX0v1g==
dependencies:
"@eva-design/dss" "^2.0.0"
"@eva-design/processor" "^2.0.0"
fecha "3.0.3"
hoist-non-react-statics "^3.2.1"
lodash.merge "^4.6.1"
"@ui-kitten/eva-icons@5.1.2":
version "5.1.2"
resolved "https://registry.yarnpkg.com/@ui-kitten/eva-icons/-/eva-icons-5.1.2.tgz#f128c4baf95d84a13067f02f0bdcb8df61178a9f"
integrity sha512-cUU6P469TgZ/vF9BrpBXFyTHttfXu/pHZiITfGw96BbaPn5GtBFSnorRtaOyqU4k2+pyzOA7rohqlbRY3jgAdA==
dependencies:
react-native-eva-icons "^1.3.1"
"@ui-kitten/metro-config@5.1.2":
version "5.1.2"
resolved "https://registry.yarnpkg.com/@ui-kitten/metro-config/-/metro-config-5.1.2.tgz#c678d11230ec93756859a7359a00086fd50ab43d"
integrity sha512-PV+S23ocybRqDrD7kjEqBfvnfE5h+53zFivoI7m/Zln+cTZPqxDaWZZvadW1IlyHEQe5oPA/QdWyuP8ccH1kaA==
abort-controller@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
@ -3009,7 +3043,7 @@ collection-visit@^1.0.0:
map-visit "^1.0.0"
object-visit "^1.0.0"
color-convert@^1.9.0:
color-convert@^1.9.0, color-convert@^1.9.3:
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==
@ -3028,11 +3062,35 @@ color-name@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.1.4:
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.6.0, 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@^3.1.2:
version "3.2.1"
resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164"
integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==
dependencies:
color-convert "^1.9.3"
color-string "^1.6.0"
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"
@ -3275,7 +3333,7 @@ decamelize@^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.0:
decode-uri-component@^0.2.0, 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==
@ -4137,11 +4195,6 @@ fb-watchman@^2.0.0:
dependencies:
bser "2.1.1"
fecha@3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/fecha/-/fecha-3.0.3.tgz#fabbd416497649a42c24d34bfa726b579203a1e2"
integrity sha512-6LQK/1jud/FZnfEEZJ7y81vw7ge81DNd/XEsX0hgMUjhS+QMljkb1C0czBaP7dMNRVrd5mw/J2J7qI2Nw+TWZw==
file-entry-cache@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
@ -4166,6 +4219,11 @@ fill-range@^7.0.1:
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"
@ -4579,7 +4637,7 @@ hmac-drbg@^1.0.1:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.2.1:
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==
@ -4736,6 +4794,11 @@ is-arrayish@^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-bigint@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
@ -5761,7 +5824,7 @@ lodash.isequal@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
lodash.merge@^4.6.1, lodash.merge@^4.6.2:
lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
@ -6310,6 +6373,11 @@ ms@2.1.3, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
nanoid@^3.1.23:
version "3.3.4"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@ -6945,6 +7013,16 @@ punycode@^2.1.0:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
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.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
@ -6983,6 +7061,11 @@ react-devtools-core@4.24.0:
shell-quote "^1.6.1"
ws "^7"
react-freeze@^1.0.0:
version "1.0.3"
resolved "https://registry.yarnpkg.com/react-freeze/-/react-freeze-1.0.3.tgz#5e3ca90e682fed1d73a7cb50c2c7402b3e85618d"
integrity sha512-ZnXwLQnGzrDpHBHiC56TXFXvmolPeMjTn1UOm610M4EXGzbEDR7oOIyS2ZiItgbs6eZc4oU/a0hpk8PrcKvv5g==
react-i18next@^12.0.0:
version "12.0.0"
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-12.0.0.tgz#634015a2c035779c5736ae4c2e5c34c1659753b1"
@ -6996,7 +7079,7 @@ react-i18next@^12.0.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
react-is@^16.13.1, react-is@^16.7.0:
react-is@^16.13.0, react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@ -7028,34 +7111,36 @@ react-native-codegen@^0.70.6:
jscodeshift "^0.13.1"
nullthrows "^1.1.1"
react-native-eva-icons@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/react-native-eva-icons/-/react-native-eva-icons-1.3.1.tgz#1e6e019b0fd3cb1669db50bd6bbdaa6d89327593"
integrity sha512-emd/aYXuOacuDVTx0SJoLi+xsOdCNdljQB3PTNCM9AQ3m/smG0X1TN0+ihelPO7MqoHzaH0h6lbANtwxGUy8Fw==
react-native-flash-message@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/react-native-flash-message/-/react-native-flash-message-0.3.1.tgz#e88073dffa826385c92aebf9244438940fbcffec"
integrity sha512-PswNvDdHBOavmIM7G4loLuEwML3oB8E8wVCuOPQ0Q6hRbExwTaF6gsTJvo5fQkyUsCi27ainSkL/F0ZijIkVig==
react-native-gesture-handler@^2.8.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-2.8.0.tgz#ef9857871c10663c95a51546225b6e00cd4740cf"
integrity sha512-poOSfz/w0IyD6Qwq7aaIRRfEaVTl1ecQFoyiIbpOpfNTjm2B1niY2FLrdVQIOtIOe+K9nH55Qal04nr4jGkHdQ==
dependencies:
prop-types "^15.8.1"
react-native-iphone-x-helper "^1.3.1"
"@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-gradle-plugin@^0.70.3:
version "0.70.3"
resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.70.3.tgz#cbcf0619cbfbddaa9128701aa2d7b4145f9c4fc8"
integrity sha512-oOanj84fJEXUg9FoEAQomA8ISG+DVIrTZ3qF7m69VQUJyOGYyDZmPqKcjvRku4KXlEH6hWO9i4ACLzNBh8gC0A==
react-native-iphone-x-helper@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.3.1.tgz#20c603e9a0e765fd6f97396638bdeb0e5a60b010"
integrity sha512-HOf0jzRnq2/aFUcdCJ9w9JGzN3gdEg0zFE4FyYlp4jtidqU03D5X7ZegGKfT1EWteR0gPBGp9ye5T5FvSWi9Yg==
react-native-multithreading@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/react-native-multithreading/-/react-native-multithreading-1.1.1.tgz#e1522ecd56115993d444a69c21bca49ca123bf4e"
integrity sha512-ceJQRZAPjH5LfrDjb5svF4F18Ne7QR7QLQUFO0huAe+9w0hd2C3PR12ATxljo+590GXCzWRt2ruR9pY3EstFAQ==
react-native-paper@^5.1.3:
version "5.1.3"
resolved "https://registry.yarnpkg.com/react-native-paper/-/react-native-paper-5.1.3.tgz#31b9c52633c1ee0e5842ca0f61179de0750b48ee"
integrity sha512-s3uDfhLFDUdMIgYOx93GoZ+rn0oRwRadzW3/zeUj8h7DeZl8Eb8+F0JW5HcKWfBBgBvAPYRzzY6K5SN+Fm4pVA==
dependencies:
"@callstack/react-theme-provider" "^3.0.8"
color "^3.1.2"
use-event-callback "^0.1.0"
react-native-parsed-text@^0.0.22:
version "0.0.22"
resolved "https://registry.yarnpkg.com/react-native-parsed-text/-/react-native-parsed-text-0.0.22.tgz#a23c756eaa5d6724296814755085127f9072e5f5"
@ -7068,19 +7153,37 @@ react-native-quick-sqlite@^6.1.1:
resolved "https://registry.yarnpkg.com/react-native-quick-sqlite/-/react-native-quick-sqlite-6.1.1.tgz#ba35d0a4a919a5a0962306c3fee4dc46983b0839"
integrity sha512-bVV7+mWAhWH/0iPjQmDlLHqTIkYm+j+k5pFiy+3jW91DnkH44C0tR4DSeRa6ERLz1fG/lDB1KwcBU3fOL9vFCA==
react-native-reanimated@^2.13.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.13.0.tgz#d64c1386626822d4dc22094b4efe028ff2c49cc9"
integrity sha512-yUHyYVIegWWIza4+nVyS3CSmI/Mc8kLFVHw2c6gnSHaYhYA4LeEjH/jBkoMzHk9Xd0Ra3cwtjYKAMG8OTp6JVg==
react-native-raw-bottom-sheet@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/react-native-raw-bottom-sheet/-/react-native-raw-bottom-sheet-2.2.0.tgz#d11dabb86aadb014273767ef7b554924b13633c5"
integrity sha512-qL4JKIqvbcVxbkKzeh51hjV7suoJN3ouxzvLmOg0FBUV1yiJAfEbacjQdtRCI6+OU5pyGFBIifLsTXcFDwHggg==
react-native-reanimated@^2.14.0:
version "2.14.0"
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.14.0.tgz#acc20d62ac4668afffb5bc749cf0a095e6c44239"
integrity sha512-WicflLAyXGveVLZCHLqxH4axkb1QoTLejsdb5WbjkMN0mEDHWQQly7BeKR7Ek0zzZnmcrChnNfMLGGW+X3uDkg==
dependencies:
"@babel/plugin-transform-object-assign" "^7.16.7"
"@babel/preset-typescript" "^7.16.7"
"@types/invariant" "^2.2.35"
convert-source-map "^1.7.0"
invariant "^2.2.4"
lodash.isequal "^4.5.0"
setimmediate "^1.0.5"
string-hash-64 "^1.0.3"
react-native-safe-area-context@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.4.1.tgz#239c60b8a9a80eac70a38a822b04c0f1d15ffc01"
integrity sha512-N9XTjiuD73ZpVlejHrUWIFZc+6Z14co1K/p1IFMkImU7+avD69F3y+lhkqA2hN/+vljdZrBSiOwXPkuo43nFQA==
react-native-screens@^3.18.2:
version "3.18.2"
resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-3.18.2.tgz#d7ab2d145258d3db9fa630fa5379dc4474117866"
integrity sha512-ANUEuvMUlsYJ1QKukEhzhfrvOUO9BVH9Nzg+6eWxpn3cfD/O83yPBOF8Mx6x5H/2+sMy+VS5x/chWOOo/U7QJw==
dependencies:
react-freeze "^1.0.0"
warn-once "^0.1.0"
react-native-securerandom@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/react-native-securerandom/-/react-native-securerandom-1.0.1.tgz#dc983cce980c80d1af62406e2ef2917ed0ada55f"
@ -7611,6 +7714,13 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
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"
@ -7712,6 +7822,11 @@ source-map@^0.7.3:
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-string@^3.0.1, split-string@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
@ -7791,6 +7906,11 @@ stream@^0.0.2:
dependencies:
emitter-component "^1.1.1"
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-hash-64@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/string-hash-64/-/string-hash-64-1.0.3.tgz#0deb56df58678640db5c479ccbbb597aaa0de322"
@ -8252,6 +8372,16 @@ url@^0.11.0:
punycode "1.3.2"
querystring "0.2.0"
use-event-callback@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/use-event-callback/-/use-event-callback-0.1.0.tgz#29d7ce996802935c5387e7d3b606cf316da3457f"
integrity sha512-5fTzY5UEXHMK5UR0NRkUz6TPfWmmX9fO8Tx3SnHrfMPdrQ7Rna0gDBy0r56SP68TwsP9DgwSBzeysCu3A/Z2NA==
use-latest-callback@^0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.1.5.tgz#a4a836c08fa72f6608730b5b8f4bbd9c57c04f51"
integrity sha512-HtHatS2U4/h32NlkhupDsPlrbiD27gSH5swBdtXbCAlc6pfOFzaj0FehW/FO12rx8j2Vy4/lJScCiJyM01E+bQ==
use-sync-external-store@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
@ -8326,6 +8456,11 @@ walker@^1.0.7, walker@^1.0.8:
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"