mirror of
https://github.com/standardnotes/mobile.git
synced 2026-04-19 13:49:03 -04:00
feature: refactor ActionSheet & use new SIdeMenu
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
"postinstall": "patch-package"
|
||||
},
|
||||
"dependencies": {
|
||||
"@expo/react-native-action-sheet": "^3.8.0",
|
||||
"@react-native-community/async-storage": "1.11.0",
|
||||
"@react-native-community/masked-view": "^0.1.10",
|
||||
"@react-navigation/native": "^5.5.1",
|
||||
@@ -33,7 +34,6 @@
|
||||
"moment": "^2.27.0",
|
||||
"react": "16.11.0",
|
||||
"react-native": "0.62.2",
|
||||
"react-native-actionsheet": "standardnotes/react-native-actionsheet#9cb323f",
|
||||
"react-native-aes-crypto": "standardnotes/react-native-aes#d156762",
|
||||
"react-native-alternate-icons": "standardnotes/react-native-alternate-icons#1d335d",
|
||||
"react-native-fab": "standardnotes/react-native-fab#cb60e00",
|
||||
|
||||
69
src/App.tsx
69
src/App.tsx
@@ -1,29 +1,9 @@
|
||||
import { Client } from 'bugsnag-react-native';
|
||||
import React, { useState, useEffect, useCallback, useContext } from 'react';
|
||||
import { Platform, Dimensions, ScaledSize } from 'react-native';
|
||||
import { NavigationContainer } from '@react-navigation/native';
|
||||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
import { ThemeProvider, ThemeContext } from 'styled-components/native';
|
||||
// import { createDrawerNavigator, DrawerActions } from 'react-navigation-drawer';
|
||||
// import Authenticate from '@Screens/Authentication/Authenticate';
|
||||
// import Compose from '@Screens/Compose';
|
||||
// import {
|
||||
// SCREEN_AUTHENTICATE,
|
||||
// SCREEN_HOME,
|
||||
// SCREEN_NOTES,
|
||||
// SCREEN_COMPOSE,
|
||||
// SCREEN_INPUT_MODAL,
|
||||
// SCREEN_SETTINGS,
|
||||
// SCREEN_MANAGE_PRIVILEGES,
|
||||
// SCREEN_KEY_RECOVERY,
|
||||
// } from '@Screens/screens';
|
||||
// import InputModal from '@Screens/InputModal';
|
||||
// import KeyRecovery from '@Screens/KeyRecovery';
|
||||
// import MainSideMenu from '@Screens/SideMenu/MainSideMenu';
|
||||
// import ManagePrivileges from '@Screens/ManagePrivileges';
|
||||
// import NoteSideMenu from '@Screens/SideMenu/NoteSideMenu';
|
||||
// import Root from '@Screens/Root';
|
||||
// import Settings from '@Screens/Settings/Settings';
|
||||
// import SideMenuManager from '@Screens/SideMenu/SideMenuManager';
|
||||
import { CurrentApplication, ContextProvider } from './ApplicationContext';
|
||||
import { Root } from '@Screens/Root';
|
||||
import {
|
||||
@@ -41,8 +21,12 @@ import {
|
||||
import { ICON_MENU } from '@Style/icons';
|
||||
import { StyleKit } from '@Style/StyleKit';
|
||||
import Icon from 'react-native-vector-icons/Ionicons';
|
||||
import { enableScreens } from 'react-native-screens';
|
||||
import DrawerLayout from 'react-native-gesture-handler/DrawerLayout';
|
||||
import { View, Text } from 'react-native';
|
||||
import { ActionSheetProvider } from '@expo/react-native-action-sheet';
|
||||
import { MainSideMenu } from '@Screens/SideMenu/MainSideMenu';
|
||||
|
||||
enableScreens();
|
||||
|
||||
if (__DEV__ === false) {
|
||||
// bugsnag
|
||||
@@ -146,22 +130,43 @@ type AppStackNavigatorParamList = {
|
||||
[SCREEN_COMPOSE]: undefined;
|
||||
};
|
||||
|
||||
const getDefaultDrawerWidth = ({ height, width }: ScaledSize) => {
|
||||
/*
|
||||
* Default drawer width is screen width - header height
|
||||
* with a max width of 280 on mobile and 320 on tablet
|
||||
* https://material.io/guidelines/patterns/navigation-drawer.html
|
||||
*/
|
||||
const smallerAxisSize = Math.min(height, width);
|
||||
const isLandscape = width > height;
|
||||
const isTablet = smallerAxisSize >= 600;
|
||||
const appBarHeight = Platform.OS === 'ios' ? (isLandscape ? 32 : 44) : 56;
|
||||
const maxWidth = isTablet ? 320 : 280;
|
||||
|
||||
return Math.min(smallerAxisSize - appBarHeight, maxWidth);
|
||||
};
|
||||
|
||||
const AppStack = createStackNavigator<AppStackNavigatorParamList>();
|
||||
|
||||
const AppStackComponent = () => {
|
||||
const theme = useContext(ThemeContext);
|
||||
const drawerRef = React.createRef<DrawerLayout>();
|
||||
const renderDrawer = () => {
|
||||
return (
|
||||
<View>
|
||||
<Text>I am in the drawer!</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
const [dimensions, setDimensions] = React.useState(() =>
|
||||
Dimensions.get('window')
|
||||
);
|
||||
React.useEffect(() => {
|
||||
const updateDimensions = ({ window }: { window: ScaledSize }) => {
|
||||
setDimensions(window);
|
||||
};
|
||||
|
||||
Dimensions.addEventListener('change', updateDimensions);
|
||||
|
||||
return () => Dimensions.removeEventListener('change', updateDimensions);
|
||||
}, []);
|
||||
const renderDrawer = () => <MainSideMenu />;
|
||||
return (
|
||||
<DrawerLayout
|
||||
ref={drawerRef}
|
||||
drawerWidth={200}
|
||||
drawerWidth={getDefaultDrawerWidth(dimensions)}
|
||||
drawerPosition={'left'}
|
||||
drawerType="slide"
|
||||
drawerBackgroundColor="#ddd"
|
||||
@@ -301,7 +306,9 @@ export const App: React.FC = () => {
|
||||
<NavigationContainer>
|
||||
<ThemeProvider theme={CurrentApplication!.getThemeService().theme!}>
|
||||
<ContextProvider>
|
||||
<AppStackComponent />
|
||||
<ActionSheetProvider>
|
||||
<AppStackComponent />
|
||||
</ActionSheetProvider>
|
||||
</ContextProvider>
|
||||
</ThemeProvider>
|
||||
</NavigationContainer>
|
||||
|
||||
19
src/screens/SideMenu/MainSideMenu.styled.ts
Normal file
19
src/screens/SideMenu/MainSideMenu.styled.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import styled from 'styled-components/native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
|
||||
// We want top color to be different from bottom color of safe area.
|
||||
// See https://stackoverflow.com/questions/47725607/react-native-safeareaview-background-color-how-to-assign-two-different-backgro
|
||||
export const FirstSafeAreaView = styled(SafeAreaView)`
|
||||
flex: 0;
|
||||
background-color: ${({ theme }) => theme.stylekitContrastBackgroundColor};
|
||||
`;
|
||||
export const MainSafeAreaView = styled(SafeAreaView)`
|
||||
flex: 1;
|
||||
background-color: ${({ theme }) => theme.stylekitBackgroundColor};
|
||||
color: ${({ theme }) => theme.stylekitForegroundColor};
|
||||
`;
|
||||
export const SideMenuSectionContainer = styled.ScrollView`
|
||||
padding: 15px;
|
||||
flex: 1;
|
||||
background-color: ${({ theme }) => theme.stylekitBackgroundColor};
|
||||
`;
|
||||
96
src/screens/SideMenu/MainSideMenu.tsx
Normal file
96
src/screens/SideMenu/MainSideMenu.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import React, { Fragment, useContext, useState, useEffect } from 'react';
|
||||
import { Platform } from 'react-native';
|
||||
import FAB from 'react-native-fab';
|
||||
import { ThemeContext } from 'styled-components/native';
|
||||
import { ContentType } from 'snjs';
|
||||
import {
|
||||
MainSafeAreaView,
|
||||
FirstSafeAreaView,
|
||||
SideMenuSectionContainer,
|
||||
} from './MainSideMenu.styled';
|
||||
import { SideMenuHero } from './SideMenuHero';
|
||||
import Icon from 'react-native-vector-icons/Ionicons';
|
||||
import { StyleKit } from '@Style/StyleKit';
|
||||
import { ICON_SETTINGS } from '@Style/icons';
|
||||
import { SideMenuSection } from './SideMenuSection';
|
||||
import { ApplicationContext } from '@Root/ApplicationContext';
|
||||
import { useCustomActionSheet } from '@Style/ActionSheetWrapper';
|
||||
|
||||
export const MainSideMenu = (): JSX.Element => {
|
||||
const theme = useContext(ThemeContext);
|
||||
const application = useContext(ApplicationContext);
|
||||
const { showActionSheet } = useCustomActionSheet();
|
||||
const [outOfSync, setOutOfSync] = useState(false);
|
||||
useEffect(() => {
|
||||
const performSyncResolution = async () => {
|
||||
const isOutofSync = await application!.isOutOfSync();
|
||||
setOutOfSync(isOutofSync);
|
||||
};
|
||||
performSyncResolution();
|
||||
}, [application]);
|
||||
const outOfSyncPressed = () => {
|
||||
application!.alertService!.confirm(
|
||||
"We've detected that the data in the current application session may not match the data on the server. This can happen due to poor network conditions, or if a large note fails to download on your device. To resolve this issue, we recommend first creating a backup of your data in the Settings screen, the signing out of your account and signing back in.",
|
||||
'Potentially Out of Sync',
|
||||
'Open Settings',
|
||||
undefined,
|
||||
() => {} // TODO: nav open settings
|
||||
);
|
||||
};
|
||||
return (
|
||||
<Fragment>
|
||||
<FirstSafeAreaView />
|
||||
<MainSafeAreaView edges={['bottom', 'left']}>
|
||||
<SideMenuHero
|
||||
outOfSync={outOfSync}
|
||||
testID="settingsButton"
|
||||
onPress={() => {}} // TODO: nav open settings
|
||||
onOutOfSyncPress={outOfSyncPressed}
|
||||
/>
|
||||
|
||||
{/* <SideMenuSectionContainer>
|
||||
<SideMenuSection
|
||||
title="Themes"
|
||||
key="themes-section"
|
||||
options={themeOptions}
|
||||
collapsed={true}
|
||||
/>
|
||||
|
||||
<SideMenuSection title="Views" key="views-section">
|
||||
<TagSelectionList
|
||||
key="views-section-list"
|
||||
contentType={ContentType.SmartTag}
|
||||
onTagSelect={this.onTagSelect}
|
||||
selectedTags={selectedTags}
|
||||
/>
|
||||
</SideMenuSection>
|
||||
|
||||
<SideMenuSection title="Tags" key="tags-section">
|
||||
<TagSelectionList
|
||||
key="tags-section-list"
|
||||
hasBottomPadding={Platform.OS === 'android'}
|
||||
emptyPlaceholder={'No tags. Create one from the note composer.'}
|
||||
contentType={ContentType.Tag}
|
||||
onTagSelect={this.onTagSelect}
|
||||
selectedTags={selectedTags}
|
||||
/>
|
||||
</SideMenuSection>
|
||||
</SideMenuSectionContainer> */}
|
||||
|
||||
<FAB
|
||||
buttonColor={theme.stylekitInfoColor}
|
||||
iconTextColor={theme.stylekitInfoContrastColor}
|
||||
onClickAction={() => {}} // TODO: nav open settings
|
||||
visible={true}
|
||||
size={29}
|
||||
paddingTop={Platform.OS ? 2 : 0}
|
||||
iconTextComponent={
|
||||
<Icon name={StyleKit.nameForIcon(ICON_SETTINGS)} />
|
||||
}
|
||||
/>
|
||||
|
||||
{/* {this.state.actionSheet && this.state.actionSheet} */}
|
||||
</MainSafeAreaView>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
38
src/screens/SideMenu/SideMenuHero.styled.ts
Normal file
38
src/screens/SideMenu/SideMenuHero.styled.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import styled from 'styled-components/native';
|
||||
|
||||
export const Cell = styled.View`
|
||||
background-color: ${({ theme }) => theme.stylekitContrastBackgroundColor};
|
||||
border-bottom-color: ${({ theme }) => theme.stylekitContrastBorderColor};
|
||||
border-bottom-width: 1px;
|
||||
padding: 15px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 12px;
|
||||
padding-right: 25px;
|
||||
`;
|
||||
export const Touchable = styled.TouchableOpacity``;
|
||||
export const Title = styled.Text`
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
color: ${({ theme }) => theme.stylekitContrastForegroundColor};
|
||||
margin-bottom: 3px;
|
||||
`;
|
||||
export const SubTitle = styled.Text`
|
||||
font-size: 13px;
|
||||
color: ${({ theme }) => theme.stylekitContrastForegroundColor};
|
||||
opacity: 0.6;
|
||||
`;
|
||||
export const OutOfSyncContainer = styled.TouchableOpacity`
|
||||
flex: 0px;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
`;
|
||||
export const IconCircle = styled.View`
|
||||
margin-top: 10px;
|
||||
width: 15px;
|
||||
`;
|
||||
export const OutOfSyncLabel = styled.Text`
|
||||
margin-top: 10px;
|
||||
font-size: 13px;
|
||||
color: ${({ theme }) => theme.stylekitWarningColor};
|
||||
font-weight: bold;
|
||||
`;
|
||||
72
src/screens/SideMenu/SideMenuHero.tsx
Normal file
72
src/screens/SideMenu/SideMenuHero.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import React, { useContext, useCallback } from 'react';
|
||||
import { ApplicationContext } from '@Root/ApplicationContext';
|
||||
import { ContentType } from 'snjs';
|
||||
import {
|
||||
Cell,
|
||||
Touchable,
|
||||
Title,
|
||||
SubTitle,
|
||||
OutOfSyncContainer,
|
||||
IconCircle,
|
||||
OutOfSyncLabel,
|
||||
} from './SideMenuHero.styled';
|
||||
import { ViewProps } from 'react-native';
|
||||
import { Circle } from '@Components/Circle';
|
||||
import { ThemeContext } from 'styled-components/native';
|
||||
|
||||
type Props = {
|
||||
onPress: () => void;
|
||||
outOfSync: boolean;
|
||||
onOutOfSyncPress: () => void;
|
||||
testID: ViewProps['testID'];
|
||||
};
|
||||
|
||||
export const SideMenuHero: React.FC<Props> = props => {
|
||||
const application = useContext(ApplicationContext);
|
||||
const theme = useContext(ThemeContext);
|
||||
const getText = useCallback(() => {
|
||||
const noAccount = application?.noAccount();
|
||||
const hasEncryption = !noAccount; // TODO: check this
|
||||
if (noAccount) {
|
||||
return {
|
||||
title: 'Data Not Backed Up',
|
||||
text: hasEncryption
|
||||
? 'Sign in or register to enable sync to your other devices.'
|
||||
: 'Sign in or register to add encryption and enable sync to your other devices.',
|
||||
};
|
||||
} else {
|
||||
const user = application?.getUser();
|
||||
const email = user?.email;
|
||||
const items = application!.getItems([ContentType.Note, ContentType.Tag]);
|
||||
const itemsStatus =
|
||||
items.length + '/' + items.length + ' notes and tags encrypted';
|
||||
return {
|
||||
title: email,
|
||||
text: itemsStatus,
|
||||
};
|
||||
}
|
||||
}, []);
|
||||
const textData = getText();
|
||||
return (
|
||||
<Cell>
|
||||
<Touchable testID={props.testID} onPress={props.onPress}>
|
||||
<Title>{textData.title}</Title>
|
||||
</Touchable>
|
||||
<Touchable onPress={props.onPress}>
|
||||
<SubTitle>{textData.text}</SubTitle>
|
||||
</Touchable>
|
||||
{props.outOfSync && (
|
||||
<OutOfSyncContainer onPress={props.onOutOfSyncPress}>
|
||||
<IconCircle>
|
||||
<Circle
|
||||
size={10}
|
||||
backgroundColor={theme.stylekitWarningColor}
|
||||
borderColor={theme.stylekitWarningColor}
|
||||
/>
|
||||
</IconCircle>
|
||||
<OutOfSyncLabel>Potentially Out of Sync</OutOfSyncLabel>
|
||||
</OutOfSyncContainer>
|
||||
)}
|
||||
</Cell>
|
||||
);
|
||||
};
|
||||
@@ -1,100 +0,0 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, Platform } from 'react-native';
|
||||
import ActionSheet from 'react-native-actionsheet';
|
||||
|
||||
type Option =
|
||||
| {
|
||||
text: string;
|
||||
key?: string;
|
||||
callback: () => void;
|
||||
destructive?: boolean;
|
||||
}
|
||||
| {
|
||||
text: string;
|
||||
key?: string;
|
||||
callback: (option: Option) => void;
|
||||
destructive?: boolean;
|
||||
};
|
||||
|
||||
export default class ActionSheetWrapper {
|
||||
options: Option[];
|
||||
destructiveIndex?: number;
|
||||
cancelIndex: number;
|
||||
title: string;
|
||||
actionSheet = React.createRef<ActionSheet>();
|
||||
static BuildOption({ text, key, callback, destructive }: Option) {
|
||||
return {
|
||||
text,
|
||||
key,
|
||||
callback,
|
||||
destructive,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props: {
|
||||
title: string;
|
||||
options: Option[];
|
||||
onCancel: () => void;
|
||||
}) {
|
||||
const cancelOption: Option[] = [
|
||||
{
|
||||
text: 'Cancel',
|
||||
callback: props.onCancel,
|
||||
key: 'CancelItem',
|
||||
destructive: false,
|
||||
},
|
||||
];
|
||||
this.options = props.options.concat(cancelOption);
|
||||
|
||||
this.destructiveIndex = this.options.findIndex(item => item.destructive);
|
||||
this.cancelIndex = this.options.length - 1;
|
||||
this.title = props.title;
|
||||
}
|
||||
|
||||
show() {
|
||||
this.actionSheet.current?.show();
|
||||
}
|
||||
|
||||
handleActionSheetPress = (index: number) => {
|
||||
let option = this.options[index];
|
||||
option.callback && option.callback(option);
|
||||
};
|
||||
|
||||
actionSheetElement() {
|
||||
return (
|
||||
<ActionSheet
|
||||
ref={this.actionSheet}
|
||||
title={this.title}
|
||||
options={this.options.map(option => {
|
||||
return option.text;
|
||||
})}
|
||||
cancelButtonIndex={this.cancelIndex}
|
||||
destructiveButtonIndex={this.destructiveIndex}
|
||||
onPress={this.handleActionSheetPress}
|
||||
{...ActionSheetWrapper.actionSheetStyles()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
static actionSheetStyles() {
|
||||
return {
|
||||
wrapperStyle: StyleKit.styles.actionSheetWrapper,
|
||||
overlayStyle: StyleKit.styles.actionSheetOverlay,
|
||||
bodyStyle: StyleKit.styles.actionSheetBody,
|
||||
|
||||
buttonWrapperStyle: StyleKit.styles.actionSheetButtonWrapper,
|
||||
buttonTitleStyle: StyleKit.styles.actionSheetButtonTitle,
|
||||
|
||||
titleWrapperStyle: StyleKit.styles.actionSheetTitleWrapper,
|
||||
titleTextStyle: StyleKit.styles.actionSheetTitleText,
|
||||
tintColor:
|
||||
Platform.OS == 'ios' ? undefined : StyleKit.variables.stylekitInfoColor,
|
||||
|
||||
buttonUnderlayColor: StyleKit.variables.stylekitBorderColor,
|
||||
|
||||
cancelButtonWrapperStyle: StyleKit.styles.actionSheetCancelButtonWrapper,
|
||||
cancelButtonTitleStyle: StyleKit.styles.actionSheetCancelButtonTitle,
|
||||
cancelMargin: StyleSheet.hairlineWidth,
|
||||
};
|
||||
}
|
||||
}
|
||||
66
src/style/useCustomActionSheet.ts
Normal file
66
src/style/useCustomActionSheet.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { useContext } from 'react';
|
||||
import { useActionSheet } from '@expo/react-native-action-sheet';
|
||||
import { ThemeContext } from 'styled-components/native';
|
||||
|
||||
type Option =
|
||||
| {
|
||||
text: string;
|
||||
key?: string;
|
||||
callback?: () => void;
|
||||
destructive?: boolean;
|
||||
}
|
||||
| {
|
||||
text: string;
|
||||
key?: string;
|
||||
callback?: (option: Option) => void;
|
||||
destructive?: boolean;
|
||||
};
|
||||
|
||||
export const createActionSheetOptions = () => {};
|
||||
|
||||
export const useCustomActionSheet = () => {
|
||||
const { showActionSheetWithOptions } = useActionSheet();
|
||||
const theme = useContext(ThemeContext);
|
||||
|
||||
const showActionSheet = (
|
||||
title: string,
|
||||
options: Option[],
|
||||
onCancel?: () => void
|
||||
) => {
|
||||
const cancelOption: Option[] = [
|
||||
{
|
||||
text: 'Cancel',
|
||||
callback: onCancel || (() => {}),
|
||||
key: 'CancelItem',
|
||||
destructive: false,
|
||||
},
|
||||
];
|
||||
const tempOptions = options.concat(cancelOption);
|
||||
const destructiveIndex = tempOptions.findIndex(item => item.destructive);
|
||||
const cancelIndex = tempOptions.length - 1;
|
||||
|
||||
showActionSheetWithOptions(
|
||||
{
|
||||
options: tempOptions.map(option => option.text),
|
||||
destructiveButtonIndex: destructiveIndex,
|
||||
cancelButtonIndex: cancelIndex,
|
||||
title,
|
||||
containerStyle: {
|
||||
backgroundColor: theme.stylekitBorderColor,
|
||||
},
|
||||
textStyle: {
|
||||
color: theme.stylekitForegroundColor,
|
||||
},
|
||||
titleTextStyle: {
|
||||
color: theme.stylekitForegroundColor,
|
||||
},
|
||||
},
|
||||
buttonIndex => {
|
||||
let option = tempOptions[buttonIndex];
|
||||
option.callback && option.callback(option);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return { showActionSheet };
|
||||
};
|
||||
14
yarn.lock
14
yarn.lock
@@ -766,6 +766,14 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed"
|
||||
integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
|
||||
|
||||
"@expo/react-native-action-sheet@^3.8.0":
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@expo/react-native-action-sheet/-/react-native-action-sheet-3.8.0.tgz#0db8b70ea8550ceb2983abda8584efa3a61d7389"
|
||||
integrity sha512-tCfwysuqy0sfaN+aA98IKUrwCLKsbDHSYLcnHrx9wNbawOHNez8rSeFtieAS48/HyrPI75yg/ZGvxe6UsJRS8Q==
|
||||
dependencies:
|
||||
"@types/hoist-non-react-statics" "^3.3.1"
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
|
||||
"@hapi/address@2.x.x":
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5"
|
||||
@@ -1291,7 +1299,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.36.tgz#17ce0a235e9ffbcdcdf5095646b374c2bf615a4c"
|
||||
integrity sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ==
|
||||
|
||||
"@types/hoist-non-react-statics@*":
|
||||
"@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.1":
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
|
||||
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
|
||||
@@ -6197,10 +6205,6 @@ react-is@^16.12.0, react-is@^16.13.0, react-is@^16.7.0, react-is@^16.8.1, react-
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
||||
react-native-actionsheet@standardnotes/react-native-actionsheet#9cb323f:
|
||||
version "2.4.2"
|
||||
resolved "https://codeload.github.com/standardnotes/react-native-actionsheet/tar.gz/9cb323f2fd5ca9687395354b88c5ae3c1a92c43e"
|
||||
|
||||
react-native-aes-crypto@standardnotes/react-native-aes#d156762:
|
||||
version "1.3.9"
|
||||
resolved "https://codeload.github.com/standardnotes/react-native-aes/tar.gz/d156762424897aaf1e020462edecbe52c492c056"
|
||||
|
||||
Reference in New Issue
Block a user