mattermost-mobile/app/screens/invite/summary.tsx
Elias Nahum b8c088cc70
Upgrade RN as well as update or replace other dependencies (#8011)
* start upgrade to RN 74

* migrate react-native-fs to expo-file-system

* exclude expo-asset module

* fix database manager remove directory

* fix: android network helper

* include expo on android

* temporarily disable android dep lock

* replace react-native-create-thumbnail with expo-video-thumnails

* update patches file version

* fix android build on 74

* create local library to replace MattermostManaged, Notifications and SplitView modules with new arch support

* migrate app to use new mattermost-rnutils library

* remove unused flipper class for android unsigned

* fix mattermost-rnutils android foldedObserver lifecycle

* use mattermost-rnutils on Android

* use mattermost-rnutils on iOS

* path react-native-navigation to not crash when activity is not NavigationActivity

* create local library for android share extension with new arch support

* Replace ShareModule with @mattermost/rnshare library

* remove ShareModule from android native code

* update react-intl

* update nodejs to 20.x.x npm to 10.x.x and dev deps

* update @gorhom/bottom-sheet

* use MattermostShare conditionally based on the platform

* update @react-native-camera-roll/camera-roll

* remove unused react-native-calendars

* fix metro config

* fix terminate session race condition

* remove unused analytics

* replace react-native-device-info with expo-application and expo-device

* update @react-native-clipboard/clipboard

* update @react-native-community/datetimepicker

* update @react-native-community/netinfo

* update @sentry/react-native

* update react-native-document-picker

* update react-native-gesture-handler

* update react-native-share

* update react-native-svg and react-native-svg-transformer

* update react-native-vector-icons

* update babel

* update react-native-shadow-2

* update semver

* remove react-native-svg-transformer and convert svg files to svg components

* fix @mattermost/rnshare new-arch build on android

* remove react-native-create-thumbnail resolution in build.gradle

* create @mattermost/hardware-keyboard library to replace hw-keyboard-events

* fix hardware-keyboard library

* fix rnutils library

* create @mattermost/keyboard-tracker library

* replace react-native-keyboard-tracking-view with @mattermost/keyboard-tracker

* fix: rnutils to not crash on lateinit context

* fix: rnutils delete database

* revert changes to session_manager

* Removed react-native-webview and added expo-web-browser instead

With expo-web-browser we no longer need the webview for SSO login
the SSO login is now done by using "custom Chrome tabs" on Android
and ASWebAuthenticationSession on iOS

* remove patch for react-native-keyboard-tracking-view

* replace react-native-linear-gradient with expo-linear-gradient

* replace react-native-in-app-review with expo-store-review

* fix: shared group database directory on ios

* replace react-native-fast-image with expo-image

* remove unusued type def for react-native-keyboard-tracking-view

* replace react-native-elements and react-native-button with @rneui

* node version

* update sizzling methods

* fix tests using jest-expo

* replace jail-monkey with expo-device

* update babel deps

* update typescript eslint

* update rn and expo

* react-native-document-picker @react-native-camera-roll/camera-roll @react-native-community/datetimepicker react-native-reanimated react-native-safe-area-context

* update patches

* update @sentry/react-native

* upgrade react-native-navigation

* update expo & expo-image

* upgrade to working version of @sentry/react-native

* update node, cocoapods, bundler, fastlane versions

* @testing-library/react-native and eslint-plugin-jest

* fix: FloatingTextInput causing a crash with reanimated

* update sentry, localize, @types/lodash and uuid

* fix floating text input label

* update react-native-video

* fix: cannot calculate shadow efficiently on some components

* fix: reduce motion warning for bottomSheet

* fix: shadow on YouTube component

* update react-native-webrtc expo and @typescript-eslint

* audit fix

* fix swizzling bad merge

* temp use of github dependency for @mattermost libraries

* feedback review

* feedback review

* npm audit fix

* update bundle deps

* update @mattermost/react-native-turbo-log

* update deps
2024-06-19 09:33:45 +08:00

302 lines
9.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Button} from '@rneui/base';
import React, {useCallback, useMemo} from 'react';
import {useIntl} from 'react-intl';
import {View, Text, ScrollView} from 'react-native';
import CompassIcon from '@components/compass_icon';
import FormattedText from '@components/formatted_text';
import AlertSvg from '@components/illustrations/alert';
import ErrorSvg from '@components/illustrations/error';
import SuccessSvg from '@components/illustrations/success';
import {useTheme} from '@context/theme';
import {t} from '@i18n';
import {buttonBackgroundStyle, buttonTextStyle} from '@utils/buttonStyles';
import {makeStyleSheetFromTheme, changeOpacity} from '@utils/theme';
import {typography} from '@utils/typography';
import SummaryReport, {SummaryReportType} from './summary_report';
import type {SearchResult, Result} from './invite';
const MAX_WIDTH_CONTENT = 480;
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
return {
container: {
display: 'flex',
flex: 1,
},
summary: {
display: 'flex',
flex: 1,
},
summaryContainer: {
display: 'flex',
flexGrow: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'stretch',
marginTop: 20,
marginHorizontal: 20,
paddingBottom: 20,
},
summaryContent: {
flexGrow: 1,
flexDirection: 'column',
justifyContent: 'center',
maxWidth: MAX_WIDTH_CONTENT,
},
summarySvg: {
marginBottom: 20,
alignSelf: 'center',
},
summaryMessageText: {
color: theme.centerChannelColor,
...typography('Heading', 700, 'SemiBold'),
textAlign: 'center',
marginHorizontal: 32,
marginBottom: 24,
},
summaryErrorText: {
color: changeOpacity(theme.centerChannelColor, 0.72),
...typography('Body', 200, 'Regular'),
textAlign: 'center',
},
footer: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
borderTopWidth: 1,
borderTopColor: changeOpacity(theme.centerChannelColor, 0.16),
padding: 20,
},
summaryButtonContainer: {
flexGrow: 1,
flexDirection: 'row',
justifyContent: 'center',
},
summaryButtonTextContainer: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
height: 24,
},
summaryButtonIcon: {
marginRight: 7,
color: theme.buttonColor,
},
summaryButtonContainerStyle: {flexGrow: 1},
};
});
enum SummaryButtonType {
DONE = 'done',
RETRY = 'retry',
BACK = 'back',
}
type SummaryProps = {
result: Result;
selectedIds: {[id: string]: SearchResult};
error?: string;
testID: string;
onClose: () => void;
onRetry: () => void;
onBack: () => void;
}
export default function Summary({
result,
selectedIds,
error,
testID,
onClose,
onRetry,
onBack,
}: SummaryProps) {
const {formatMessage, locale} = useIntl();
const theme = useTheme();
const styles = getStyleSheet(theme);
const {sent, notSent} = result;
const sentCount = sent.length;
const notSentCount = notSent.length;
const styleSummaryMessageText = useMemo(() => {
const style = [];
style.push(styles.summaryMessageText);
if (error) {
style.push({marginBottom: 8});
}
return style;
}, [error, styles]);
let svg = <></>;
let message = '';
if (error) {
svg = <ErrorSvg/>;
message = formatMessage(
{
id: 'invite.summary.error',
defaultMessage: '{invitationsCount, plural, one {Invitation} other {Invitations}} could not be sent successfully',
},
{invitationsCount: sentCount + notSentCount},
);
} else if (!sentCount && notSentCount) {
svg = <ErrorSvg/>;
message = formatMessage(
{
id: 'invite.summary.not_sent',
defaultMessage: '{notSentCount, plural, one {Invitation wasnt} other {Invitations werent}} sent',
},
{notSentCount},
);
} else if (sentCount && !notSentCount) {
svg = <SuccessSvg/>;
message = formatMessage(
{
id: 'invite.summary.sent',
defaultMessage: 'Your {sentCount, plural, one {invitation has} other {invitations have}} been sent',
},
{sentCount},
);
} else if (sentCount && notSentCount) {
svg = <AlertSvg/>;
message = formatMessage(
{
id: 'invite.summary.some_not_sent',
defaultMessage: '{notSentCount, plural, one {An invitation was} other {Some invitations were}} not sent',
},
{notSentCount},
);
}
const renderButton = useCallback((type: SummaryButtonType) => {
let onPress;
let iconName = '';
let text;
let styleButtonText = buttonTextStyle(theme, 'lg', 'primary');
let styleButtonBackground = buttonBackgroundStyle(theme, 'lg', 'primary');
const styleButtonIcon = [];
styleButtonIcon.push(styles.summaryButtonIcon);
switch (type) {
case SummaryButtonType.BACK:
onPress = onBack;
iconName = 'chevron-left';
text = {
id: t('invite.summary.back'),
defaultMessage: 'Go back',
};
styleButtonText = buttonTextStyle(theme, 'lg', 'tertiary');
styleButtonBackground = [buttonBackgroundStyle(theme, 'lg', 'tertiary'), {marginRight: 8}];
styleButtonIcon.push({color: theme.buttonBg});
break;
case SummaryButtonType.RETRY:
onPress = onRetry;
iconName = 'refresh';
text = {
id: t('invite.summary.try_again'),
defaultMessage: 'Try again',
};
break;
case SummaryButtonType.DONE:
default:
onPress = onClose;
text = {
id: t('invite.summary.done'),
defaultMessage: 'Done',
};
break;
}
return (
<Button
containerStyle={styles.summaryButtonContainerStyle}
buttonStyle={styleButtonBackground}
onPress={onPress}
testID={`invite.summary_button.${SummaryButtonType.RETRY}`}
>
<View style={styles.summaryButtonTextContainer}>
{iconName && (
<CompassIcon
name={iconName}
size={24}
style={styleButtonIcon}
/>
)}
<FormattedText
{...text}
style={styleButtonText}
/>
</View>
</Button>
);
}, [theme, locale, onClose, onRetry, onBack]);
return (
<View
style={styles.container}
testID={testID}
>
<ScrollView
style={styles.summary}
contentContainerStyle={styles.summaryContainer}
testID='invite.summary'
>
<View style={styles.summaryContent}>
<View style={styles.summarySvg}>
{svg}
</View>
<Text style={styleSummaryMessageText}>
{message}
</Text>
{error ? (
<Text style={styles.summaryErrorText}>
{error}
</Text>
) : (
<>
{notSent.length > 0 && (
<SummaryReport
type={SummaryReportType.NOT_SENT}
invites={notSent}
selectedIds={selectedIds}
testID='invite.summary_report'
/>
)}
{sent.length > 0 && (
<SummaryReport
type={SummaryReportType.SENT}
invites={sent}
selectedIds={selectedIds}
testID='invite.summary_report'
/>
)}
</>
)}
</View>
</ScrollView>
<View style={styles.footer}>
<View style={styles.summaryButtonContainer}>
{error ? (
<>
{renderButton(SummaryButtonType.BACK)}
{renderButton(SummaryButtonType.RETRY)}
</>
) : (
renderButton(SummaryButtonType.DONE)
)}
</View>
</View>
</View>
);
}