[IMPROVEMENT] Reusable toast (#1065)

This commit is contained in:
pranavpandey1998official 2019-07-23 19:32:57 +05:30 committed by Diego Mello
parent 266ae3bac7
commit aac6da34af
8 changed files with 77 additions and 49 deletions

View File

@ -21,6 +21,8 @@ import I18n from '../i18n';
import log from '../utils/log'; import log from '../utils/log';
import Navigation from '../lib/Navigation'; import Navigation from '../lib/Navigation';
import { getMessageTranslation } from './message/utils'; import { getMessageTranslation } from './message/utils';
import { LISTENER } from './Toast';
import EventEmitter from '../utils/events';
@connect( @connect(
state => ({ state => ({
@ -48,7 +50,6 @@ export default class MessageActions extends React.Component {
actionsHide: PropTypes.func.isRequired, actionsHide: PropTypes.func.isRequired,
room: PropTypes.object.isRequired, room: PropTypes.object.isRequired,
actionMessage: PropTypes.object, actionMessage: PropTypes.object,
toast: PropTypes.element,
user: PropTypes.object, user: PropTypes.object,
deleteRequest: PropTypes.func.isRequired, deleteRequest: PropTypes.func.isRequired,
editInit: PropTypes.func.isRequired, editInit: PropTypes.func.isRequired,
@ -275,9 +276,9 @@ export default class MessageActions extends React.Component {
} }
handleCopy = async() => { handleCopy = async() => {
const { actionMessage, toast } = this.props; const { actionMessage } = this.props;
await Clipboard.setString(actionMessage.msg); await Clipboard.setString(actionMessage.msg);
toast.show(I18n.t('Copied_to_clipboard')); EventEmitter.emit(LISTENER, { message: I18n.t('Copied_to_clipboard') });
} }
handleShare = async() => { handleShare = async() => {
@ -294,10 +295,10 @@ export default class MessageActions extends React.Component {
} }
handlePermalink = async() => { handlePermalink = async() => {
const { actionMessage, toast } = this.props; const { actionMessage } = this.props;
const permalink = await this.getPermalink(actionMessage); const permalink = await this.getPermalink(actionMessage);
Clipboard.setString(permalink); Clipboard.setString(permalink);
toast.show(I18n.t('Permalink_copied_to_clipboard')); EventEmitter.emit(LISTENER, { message: I18n.t('Permalink_copied_to_clipboard') });
} }
handlePin = () => { handlePin = () => {

53
app/containers/Toast.js Normal file
View File

@ -0,0 +1,53 @@
import React from 'react';
import { StyleSheet } from 'react-native';
import EasyToast from 'react-native-easy-toast';
import { COLOR_TOAST, COLOR_WHITE } from '../constants/colors';
import sharedStyles from '../views/Styles';
import EventEmitter from '../utils/events';
const styles = StyleSheet.create({
toast: {
backgroundColor: COLOR_TOAST,
maxWidth: 300,
padding: 10
},
text: {
...sharedStyles.textRegular,
color: COLOR_WHITE,
fontSize: 14,
textAlign: 'center'
}
});
export const LISTENER = 'Toast';
export default class Toast extends React.Component {
componentDidMount() {
EventEmitter.addEventListener(LISTENER, this.showToast);
}
shouldComponentUpdate() {
return false;
}
componentWillUnmount() {
EventEmitter.removeListener(LISTENER);
}
showToast = ({ message }) => {
this.toast.show(message, 1000);
}
render() {
return (
<EasyToast
ref={toast => this.toast = toast}
position='center'
style={styles.toast}
textStyle={styles.text}
opacity={0.9}
/>
);
}
}

View File

@ -16,6 +16,7 @@ import { initializePushNotifications, onNotification } from './notifications/pus
import store from './lib/createStore'; import store from './lib/createStore';
import NotificationBadge from './notifications/inApp'; import NotificationBadge from './notifications/inApp';
import { defaultHeader, onNavigationStateChange } from './utils/navigation'; import { defaultHeader, onNavigationStateChange } from './utils/navigation';
import Toast from './containers/Toast';
useScreens(); useScreens();
@ -231,6 +232,7 @@ class CustomInsideStack extends React.Component {
<React.Fragment> <React.Fragment>
<InsideStackModal navigation={navigation} /> <InsideStackModal navigation={navigation} />
<NotificationBadge navigation={navigation} /> <NotificationBadge navigation={navigation} />
<Toast />
</React.Fragment> </React.Fragment>
); );
} }

View File

@ -1,32 +1,3 @@
import React from 'react'; import { Alert } from 'react-native';
import { Alert, StyleSheet } from 'react-native';
import EasyToast from 'react-native-easy-toast';
import { COLOR_TOAST, COLOR_WHITE } from '../constants/colors';
import { isNotch } from './deviceInfo';
import sharedStyles from '../views/Styles';
const styles = StyleSheet.create({
toast: {
backgroundColor: COLOR_TOAST
},
text: {
...sharedStyles.textRegular,
color: COLOR_WHITE,
fontSize: 14
}
});
const positionValue = isNotch ? 230 : 200;
export const Toast = React.forwardRef((props, ref) => (
<EasyToast
{...props}
ref={ref}
positionValue={positionValue}
style={styles.toast}
textStyle={styles.text}
opacity={0.8}
/>
));
export const showErrorAlert = (message, title, onPress = () => {}) => Alert.alert(title, message, [{ text: 'OK', onPress }], { cancelable: true }); export const showErrorAlert = (message, title, onPress = () => {}) => Alert.alert(title, message, [{ text: 'OK', onPress }], { cancelable: true });

View File

@ -13,7 +13,9 @@ import KeyboardView from '../../presentation/KeyboardView';
import sharedStyles from '../Styles'; import sharedStyles from '../Styles';
import styles from './styles'; import styles from './styles';
import scrollPersistTaps from '../../utils/scrollPersistTaps'; import scrollPersistTaps from '../../utils/scrollPersistTaps';
import { showErrorAlert, Toast } from '../../utils/info'; import { showErrorAlert } from '../../utils/info';
import { LISTENER } from '../../containers/Toast';
import EventEmitter from '../../utils/events';
import RocketChat from '../../lib/rocketchat'; import RocketChat from '../../lib/rocketchat';
import RCTextInput from '../../containers/TextInput'; import RCTextInput from '../../containers/TextInput';
import log from '../../utils/log'; import log from '../../utils/log';
@ -222,7 +224,7 @@ export default class ProfileView extends React.Component {
setUser({ ...params }); setUser({ ...params });
} }
this.setState({ saving: false, showPasswordAlert: false }); this.setState({ saving: false, showPasswordAlert: false });
this.toast.show(I18n.t('Profile_saved_successfully')); EventEmitter.emit(LISTENER, { message: I18n.t('Profile_saved_successfully') });
this.init(); this.init();
} }
} catch (e) { } catch (e) {
@ -235,7 +237,7 @@ export default class ProfileView extends React.Component {
try { try {
const { user } = this.props; const { user } = this.props;
await RocketChat.resetAvatar(user.id); await RocketChat.resetAvatar(user.id);
this.toast.show(I18n.t('Avatar_changed_successfully')); EventEmitter.emit(LISTENER, { message: I18n.t('Avatar_changed_successfully') });
this.init(); this.init();
} catch (e) { } catch (e) {
this.handleError(e, 'resetAvatar', 'changing_avatar'); this.handleError(e, 'resetAvatar', 'changing_avatar');
@ -386,7 +388,6 @@ export default class ProfileView extends React.Component {
keyboardVerticalOffset={128} keyboardVerticalOffset={128}
> >
<StatusBar /> <StatusBar />
<Toast ref={toast => this.toast = toast} />
<ScrollView <ScrollView
contentContainerStyle={sharedStyles.containerScrollView} contentContainerStyle={sharedStyles.containerScrollView}
testID='profile-view-list' testID='profile-view-list'

View File

@ -12,7 +12,9 @@ import KeyboardView from '../../presentation/KeyboardView';
import sharedStyles from '../Styles'; import sharedStyles from '../Styles';
import styles from './styles'; import styles from './styles';
import scrollPersistTaps from '../../utils/scrollPersistTaps'; import scrollPersistTaps from '../../utils/scrollPersistTaps';
import { showErrorAlert, Toast } from '../../utils/info'; import { showErrorAlert } from '../../utils/info';
import { LISTENER } from '../../containers/Toast';
import EventEmitter from '../../utils/events';
import database, { safeAddListener } from '../../lib/realm'; import database, { safeAddListener } from '../../lib/realm';
import RocketChat from '../../lib/rocketchat'; import RocketChat from '../../lib/rocketchat';
import RCTextInput from '../../containers/TextInput'; import RCTextInput from '../../containers/TextInput';
@ -215,7 +217,7 @@ export default class RoomInfoEditView extends React.Component {
if (error) { if (error) {
showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t('saving_settings') })); showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t('saving_settings') }));
} else { } else {
this.toast.show(I18n.t('Settings_succesfully_changed')); EventEmitter.emit(LISTENER, { message: I18n.t('Settings_succesfully_changed') });
} }
}, 100); }, 100);
} }
@ -428,7 +430,6 @@ export default class RoomInfoEditView extends React.Component {
<Text style={[sharedStyles.button_inverted, styles.colorDanger]} accessibilityTraits='button'>{I18n.t('DELETE')}</Text> <Text style={[sharedStyles.button_inverted, styles.colorDanger]} accessibilityTraits='button'>{I18n.t('DELETE')}</Text>
</TouchableOpacity> </TouchableOpacity>
<Loading visible={saving} /> <Loading visible={saving} />
<Toast ref={toast => this.toast = toast} />
</SafeAreaView> </SafeAreaView>
</ScrollView> </ScrollView>
</KeyboardView> </KeyboardView>

View File

@ -12,7 +12,8 @@ import UserItem from '../../presentation/UserItem';
import scrollPersistTaps from '../../utils/scrollPersistTaps'; import scrollPersistTaps from '../../utils/scrollPersistTaps';
import RocketChat from '../../lib/rocketchat'; import RocketChat from '../../lib/rocketchat';
import database, { safeAddListener } from '../../lib/realm'; import database, { safeAddListener } from '../../lib/realm';
import { Toast } from '../../utils/info'; import { LISTENER } from '../../containers/Toast';
import EventEmitter from '../../utils/events';
import log from '../../utils/log'; import log from '../../utils/log';
import I18n from '../../i18n'; import I18n from '../../i18n';
import SearchBox from '../../containers/SearchBox'; import SearchBox from '../../containers/SearchBox';
@ -232,7 +233,7 @@ export default class RoomMembersView extends React.Component {
const { rid, userLongPressed } = this.state; const { rid, userLongPressed } = this.state;
try { try {
await RocketChat.toggleMuteUserInRoom(rid, userLongPressed.username, !userLongPressed.muted); await RocketChat.toggleMuteUserInRoom(rid, userLongPressed.username, !userLongPressed.muted);
this.toast.show(I18n.t('User_has_been_key', { key: userLongPressed.muted ? I18n.t('unmuted') : I18n.t('muted') })); EventEmitter.emit(LISTENER, { message: I18n.t('User_has_been_key', { key: userLongPressed.muted ? I18n.t('unmuted') : I18n.t('muted') }) });
} catch (e) { } catch (e) {
log('err_handle_mute', e); log('err_handle_mute', e);
} }
@ -299,7 +300,6 @@ export default class RoomMembersView extends React.Component {
windowSize={10} windowSize={10}
{...scrollPersistTaps} {...scrollPersistTaps}
/> />
<Toast ref={toast => this.toast = toast} />
</SafeAreaView> </SafeAreaView>
); );
} }

View File

@ -41,7 +41,7 @@ import debounce from '../../utils/debounce';
import buildMessage from '../../lib/methods/helpers/buildMessage'; import buildMessage from '../../lib/methods/helpers/buildMessage';
import FileModal from '../../containers/FileModal'; import FileModal from '../../containers/FileModal';
import ReactionsModal from '../../containers/ReactionsModal'; import ReactionsModal from '../../containers/ReactionsModal';
import { Toast } from '../../utils/info'; import { LISTENER } from '../../containers/Toast';
import { isReadOnly, isBlocked } from '../../utils/room'; import { isReadOnly, isBlocked } from '../../utils/room';
@connect(state => ({ @connect(state => ({
@ -472,7 +472,7 @@ export default class RoomView extends React.Component {
toggleFollowThread = async(isFollowingThread) => { toggleFollowThread = async(isFollowingThread) => {
try { try {
await RocketChat.toggleFollowMessage(this.tmid, !isFollowingThread); await RocketChat.toggleFollowMessage(this.tmid, !isFollowingThread);
this.toast.show(isFollowingThread ? 'Unfollowed thread' : 'Following thread'); EventEmitter.emit(LISTENER, { message: isFollowingThread ? 'Unfollowed thread' : 'Following thread' });
} catch (e) { } catch (e) {
log('err_toggle_follow_thread', e); log('err_toggle_follow_thread', e);
} }
@ -600,7 +600,7 @@ export default class RoomView extends React.Component {
return ( return (
<React.Fragment> <React.Fragment>
{room._id && showActions {room._id && showActions
? <MessageActions room={room} tmid={this.tmid} user={user} toast={this.toast} /> ? <MessageActions room={room} tmid={this.tmid} user={user} />
: null : null
} }
{showErrorActions ? <MessageErrorActions /> : null} {showErrorActions ? <MessageErrorActions /> : null}
@ -638,7 +638,6 @@ export default class RoomView extends React.Component {
user={user} user={user}
baseUrl={baseUrl} baseUrl={baseUrl}
/> />
<Toast ref={toast => this.toast = toast} />
</SafeAreaView> </SafeAreaView>
); );
} }