-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Native Share follow ups #59239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Native Share follow ups #59239
Changes from 7 commits
4e5ce39
87bbb83
f5081df
0f346ae
947647b
e3a41e9
f7367ff
4e25e67
4cc13ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
import type {StackScreenProps} from '@react-navigation/stack'; | ||
import React, {useMemo, useState} from 'react'; | ||
import React, {useEffect, useMemo, useState} from 'react'; | ||
import {SafeAreaView, View} from 'react-native'; | ||
import {useOnyx} from 'react-native-onyx'; | ||
import type {OnyxEntry} from 'react-native-onyx'; | ||
|
@@ -11,7 +11,6 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; | |
import {FallbackAvatar} from '@components/Icon/Expensicons'; | ||
import {PressableWithoutFeedback} from '@components/Pressable'; | ||
import ScreenWrapper from '@components/ScreenWrapper'; | ||
import ScrollView from '@components/ScrollView'; | ||
import Text from '@components/Text'; | ||
import TextInput from '@components/TextInput'; | ||
import useLocalize from '@hooks/useLocalize'; | ||
|
@@ -24,13 +23,16 @@ import type {ShareNavigatorParamList} from '@libs/Navigation/types'; | |
import {getReportDisplayOption} from '@libs/OptionsListUtils'; | ||
import {getReportOrDraftReport, isDraftReport} from '@libs/ReportUtils'; | ||
import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; | ||
import variables from '@styles/variables'; | ||
import UserListItem from '@src/components/SelectionList/UserListItem'; | ||
import CONST from '@src/CONST'; | ||
import ONYXKEYS from '@src/ONYXKEYS'; | ||
import ROUTES from '@src/ROUTES'; | ||
import type SCREENS from '@src/SCREENS'; | ||
import type {Report as ReportType} from '@src/types/onyx'; | ||
import {isEmptyObject} from '@src/types/utils/EmptyObject'; | ||
import KeyboardUtils from '@src/utils/keyboard'; | ||
import getFileSize from './getFileSize'; | ||
import {showErrorAlert} from './ShareRootPage'; | ||
|
||
type ShareDetailsPageProps = StackScreenProps<ShareNavigatorParamList, typeof SCREENS.SHARE.SHARE_DETAILS>; | ||
|
@@ -46,10 +48,37 @@ function ShareDetailsPage({ | |
const [currentAttachment] = useOnyx(ONYXKEYS.SHARE_TEMP_FILE); | ||
const isTextShared = currentAttachment?.mimeType === 'txt'; | ||
const [message, setMessage] = useState(isTextShared ? currentAttachment?.content ?? '' : ''); | ||
const [errorTitle, setErrorTitle] = useState<string | undefined>(undefined); | ||
const [errorMessage, setErrorMessage] = useState<string | undefined>(undefined); | ||
|
||
const report: OnyxEntry<ReportType> = getReportOrDraftReport(reportOrAccountID); | ||
const displayReport = useMemo(() => getReportDisplayOption(report, unknownUserDetails), [report, unknownUserDetails]); | ||
|
||
useEffect(() => { | ||
if (!currentAttachment?.content || errorTitle) { | ||
return; | ||
} | ||
getFileSize(currentAttachment?.content).then((size) => { | ||
if (size > CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE) { | ||
setErrorTitle(translate('attachmentPicker.attachmentTooLarge')); | ||
setErrorMessage(translate('attachmentPicker.sizeExceeded')); | ||
} | ||
|
||
if (size < CONST.API_ATTACHMENT_VALIDATIONS.MIN_SIZE) { | ||
setErrorTitle(translate('attachmentPicker.attachmentTooSmall')); | ||
setErrorMessage(translate('attachmentPicker.sizeNotMet')); | ||
} | ||
}); | ||
}, [currentAttachment, errorTitle, translate]); | ||
|
||
useEffect(() => { | ||
if (!errorTitle || !errorMessage) { | ||
return; | ||
} | ||
|
||
showErrorAlert(errorTitle, errorMessage); | ||
}, [errorTitle, errorMessage]); | ||
|
||
if (isEmptyObject(report)) { | ||
return <NotFoundPage />; | ||
} | ||
|
@@ -68,7 +97,7 @@ function ShareDetailsPage({ | |
if (isTextShared) { | ||
addComment(report.reportID, message); | ||
const routeToNavigate = ROUTES.REPORT_WITH_ID.getRoute(reportOrAccountID); | ||
Navigation.navigate(routeToNavigate); | ||
Navigation.navigate(routeToNavigate, {forceReplace: true}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what does this change do? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I forgot to comment on this line. It fixes the problem with navigation I've fixed before but I forgot about the sharing plain text case. This way when we share (text or file) and click back button we wont end up in the share flow again. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you! |
||
return; | ||
} | ||
|
||
|
@@ -100,20 +129,20 @@ function ShareDetailsPage({ | |
}; | ||
|
||
return ( | ||
<PressableWithoutFeedback | ||
onPress={() => { | ||
KeyboardUtils.dismiss(); | ||
}} | ||
accessible={false} | ||
<ScreenWrapper | ||
includeSafeAreaPaddingBottom | ||
shouldEnableKeyboardAvoidingView={false} | ||
keyboardAvoidingViewBehavior="padding" | ||
shouldEnableMinHeight={canUseTouchScreen()} | ||
testID={ShareDetailsPage.displayName} | ||
> | ||
<ScreenWrapper | ||
includeSafeAreaPaddingBottom | ||
shouldEnableKeyboardAvoidingView={false} | ||
keyboardAvoidingViewBehavior="padding" | ||
shouldEnableMinHeight={canUseTouchScreen()} | ||
testID={ShareDetailsPage.displayName} | ||
> | ||
<View style={[styles.flex1, styles.flexColumn, styles.h100, styles.appBG]}> | ||
<View style={[styles.flex1, styles.flexColumn, styles.h100, styles.appBG]}> | ||
<PressableWithoutFeedback | ||
onPress={() => { | ||
KeyboardUtils.dismiss(); | ||
}} | ||
accessible={false} | ||
> | ||
<HeaderWithBackButton | ||
title={translate('share.shareToExpensify')} | ||
shouldShowBackButton | ||
|
@@ -136,20 +165,27 @@ function ShareDetailsPage({ | |
/> | ||
</View> | ||
)} | ||
|
||
<View style={[styles.ph5, styles.flex1, styles.flexColumn]}> | ||
<View style={styles.pv5}> | ||
<ScrollView> | ||
<TextInput | ||
autoFocus={false} | ||
value={message} | ||
multiline | ||
onChangeText={setMessage} | ||
accessibilityLabel={translate('share.messageInputLabel')} | ||
label={translate('share.messageInputLabel')} | ||
/> | ||
</ScrollView> | ||
</View> | ||
</PressableWithoutFeedback> | ||
<View style={[styles.ph5, styles.flex1, styles.flexColumn, styles.overflowHidden]}> | ||
<View style={styles.pv3}> | ||
<TextInput | ||
autoFocus={false} | ||
value={message} | ||
multiline | ||
scrollEnabled | ||
autoGrowHeight | ||
maxAutoGrowHeight={variables.textInputAutoGrowMaxHeight} | ||
onChangeText={setMessage} | ||
accessibilityLabel={translate('share.messageInputLabel')} | ||
label={translate('share.messageInputLabel')} | ||
/> | ||
</View> | ||
<PressableWithoutFeedback | ||
onPress={() => { | ||
KeyboardUtils.dismiss(); | ||
}} | ||
accessible={false} | ||
> | ||
{shouldShowAttachment && ( | ||
<> | ||
<View style={[styles.pt6, styles.pb2]}> | ||
|
@@ -176,19 +212,19 @@ function ShareDetailsPage({ | |
</SafeAreaView> | ||
</> | ||
)} | ||
</View> | ||
</PressableWithoutFeedback> | ||
</View> | ||
<FixedFooter style={[styles.appBG, styles.pt2, styles.pb2]}> | ||
<FixedFooter style={[styles.pt4]}> | ||
<Button | ||
success | ||
large | ||
text={translate('common.share')} | ||
style={[styles.w100]} | ||
style={styles.w100} | ||
onPress={handleShare} | ||
/> | ||
</FixedFooter> | ||
</ScreenWrapper> | ||
</PressableWithoutFeedback> | ||
</View> | ||
</ScreenWrapper> | ||
); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import RNFS from 'react-native-fs'; | ||
import type GetFileSizeType from './types'; | ||
|
||
const getFileSize: GetFileSizeType = (uri: string) => { | ||
return RNFS.stat(uri).then((fileStat) => { | ||
return fileStat.size; | ||
}); | ||
}; | ||
|
||
export default getFileSize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added the

fitPolicy={1}
because I thought it looked nicer. Let me know if I should change that back.fitPolicy={1}
fitPolicy={0}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I thought fitPolicy was a boolean, nvm! 😁