Rocket.Chat.ReactNative/app/views/ProfileView/index.tsx

584 lines
18 KiB
TypeScript
Raw Normal View History

import { StackNavigationOptions } from '@react-navigation/stack';
import { sha256 } from 'js-sha256';
2018-06-05 01:17:02 +00:00
import React from 'react';
import { Keyboard, ScrollView, TextInput, View } from 'react-native';
import RNPickerSelect from 'react-native-picker-select';
import { connect } from 'react-redux';
2018-06-05 01:17:02 +00:00
import { setUser } from '../../actions/login';
import { IActionSheetProvider, withActionSheet } from '../../containers/ActionSheet';
import ActionSheetContentWithInputAndSubmit from '../../containers/ActionSheet/ActionSheetContentWithInputAndSubmit';
import { AvatarWithEdit } from '../../containers/Avatar';
import Button from '../../containers/Button';
import * as HeaderButton from '../../containers/HeaderButton';
import KeyboardView from '../../containers/KeyboardView';
import SafeAreaView from '../../containers/SafeAreaView';
2019-03-12 16:23:06 +00:00
import StatusBar from '../../containers/StatusBar';
import { FormTextInput } from '../../containers/TextInput';
import { LISTENER } from '../../containers/Toast';
import Touch from '../../containers/Touch';
import { IApplicationState, IAvatarButton, IBaseScreen, IProfileParams, IUser } from '../../definitions';
import { TwoFactorMethods } from '../../definitions/ITotp';
import I18n from '../../i18n';
import { themes } from '../../lib/constants';
import { compareServerVersion, showConfirmationAlert, showErrorAlert } from '../../lib/methods/helpers';
import EventEmitter from '../../lib/methods/helpers/events';
import { events, logEvent } from '../../lib/methods/helpers/log';
import scrollPersistTaps from '../../lib/methods/helpers/scrollPersistTaps';
import { Services } from '../../lib/services';
import { twoFactor } from '../../lib/services/twoFactor';
import { getUserSelector } from '../../selectors/login';
import { ProfileStackParamList } from '../../stacks/types';
import { TSupportedThemes, withTheme } from '../../theme';
import sharedStyles from '../Styles';
import { DeleteAccountActionSheetContent } from './components/DeleteAccountActionSheetContent';
import styles from './styles';
// https://github.com/RocketChat/Rocket.Chat/blob/174c28d40b3d5a52023ee2dca2e81dd77ff33fa5/apps/meteor/app/lib/server/functions/saveUser.js#L24-L25
const MAX_BIO_LENGTH = 260;
const MAX_NICKNAME_LENGTH = 120;
interface IProfileViewProps extends IActionSheetProvider, IBaseScreen<ProfileStackParamList, 'ProfileView'> {
user: IUser;
baseUrl: string;
Accounts_AllowEmailChange: boolean;
Accounts_AllowPasswordChange: boolean;
Accounts_AllowRealNameChange: boolean;
Accounts_AllowUserAvatarChange: boolean;
Accounts_AllowUsernameChange: boolean;
Accounts_CustomFields: string;
theme: TSupportedThemes;
Accounts_AllowDeleteOwnAccount: boolean;
isMasterDetail: boolean;
serverVersion: string;
}
interface IProfileViewState {
saving: boolean;
name: string;
username: string;
email: string | null;
bio?: string;
nickname?: string;
newPassword: string | null;
currentPassword: string | null;
customFields: {
[key: string | number]: string;
};
twoFactorCode: null | {
twoFactorCode: string;
twoFactorMethod: string;
};
}
2018-06-05 01:17:02 +00:00
class ProfileView extends React.Component<IProfileViewProps, IProfileViewState> {
private name?: TextInput | null;
private username?: TextInput | null;
private email?: TextInput | null;
private avatarUrl?: TextInput | null;
private newPassword?: TextInput | null;
private nickname?: TextInput | null;
private bio?: TextInput | null;
private focusListener = () => {};
setHeader = () => {
const { navigation, isMasterDetail } = this.props;
const options: StackNavigationOptions = {
[CHORE] Update react-navigation to v5 (#2154) * react-navigation v5 installed * compiling * Outside working * InsideStack compiling * Switch stack * Starting room * RoomView header * SafeAreaView * Slide from right stack animation * stash * Fix params * Create channel * inapp notification * Custom status * Add server working * Refactor appStart * Attachment * in-app notification * AuthLoadingView * Remove compat * Navigation * Outside animations * Fix new server icon * block modal * AttachmentView header * Remove unnecessary code * SelectedUsersView header * StatusView * CreateDiscussionView * RoomInfoView * RoomInfoEditView style * RoomMembersView * RoomsListView header * RoomView header * Share extension * getParam * Focus/blur * Trying to fix inapp * Lint * Simpler app container * Update libs * Revert "Simpler app container" This reverts commit 1e49d80bb49481c34f415831b9da5e9d53e66057. * Load messages faster * Fix safearea on ReactionsModal * Update safe area to v3 * lint * Fix transition * stash - drawer replace working * stash - modal nav * RoomActionsView as tablet modal * RoomStack * Stop showing RoomView header when there's no room * Custom Header and different navigation based on stack * Refactor setHeader * MasterDetailContext * RoomView header * Fix isMasterDetail rule * KeyCommands kind of working * Create channel on tablet * RoomView sCU * Remove withSplit * Settings opening as modal * Settings * StatusView headerLeft * Admin panel * TwoFactor style * DirectoryView * ServerDropdown and SortDropdown animations * ThreadMessagesView * Navigate to empty RoomView on server switch when in master detail * ProfileView header * Fix navigation issues * Nav to any room info on tablet * Room info * Refactoring * Fix rooms search * Roomslist commands * SearchMessagesView close modal * Key commands * Fix undefined subscription * Disallow navigate to focused room * isFocused state on RoomsListView * Blur text inputs when focus is lost * Replace animation * Default nav theme * Refactoring * Always open Attachment with close modal button * ModalContainer backdrop following themes * Screen tracking * Refactor get active route for in-app notification * Only mark room as focused when in master detail layout * Lint * Open modals as fade from bottom on Android * typo * Fixing tests * Fix in-app update * Fixing goRoom issues * Refactor stack names * Fix unreadsCount * Fix stack * Fix header animation * Refactor ShareNavigation * Refactor navigation theme * Make sure title is set * Fix create discussion navigation * Remove unused variable * Create discussions from actions fixed * Layout animation * Screen lock on share extension * Unnecessary change * Admin border * Set header after state callback * Fix key commands on outside stack * Fix back button pressed * Remove layout animations from Android * Tweak animations on Android * Disable swipe gesture to open drawer * Fix current item on RoomsListView * Fix add server * Fix drawer * Fix broadcast * LayoutAnimation instead of Transitions * Fix onboarding back press * Fix assorted tests * Create discussion fix * RoomInfoView header * Drawer active item
2020-06-15 14:00:46 +00:00
title: I18n.t('Profile')
};
if (!isMasterDetail) {
options.headerLeft = () => <HeaderButton.Drawer navigation={navigation} />;
[CHORE] Update react-navigation to v5 (#2154) * react-navigation v5 installed * compiling * Outside working * InsideStack compiling * Switch stack * Starting room * RoomView header * SafeAreaView * Slide from right stack animation * stash * Fix params * Create channel * inapp notification * Custom status * Add server working * Refactor appStart * Attachment * in-app notification * AuthLoadingView * Remove compat * Navigation * Outside animations * Fix new server icon * block modal * AttachmentView header * Remove unnecessary code * SelectedUsersView header * StatusView * CreateDiscussionView * RoomInfoView * RoomInfoEditView style * RoomMembersView * RoomsListView header * RoomView header * Share extension * getParam * Focus/blur * Trying to fix inapp * Lint * Simpler app container * Update libs * Revert "Simpler app container" This reverts commit 1e49d80bb49481c34f415831b9da5e9d53e66057. * Load messages faster * Fix safearea on ReactionsModal * Update safe area to v3 * lint * Fix transition * stash - drawer replace working * stash - modal nav * RoomActionsView as tablet modal * RoomStack * Stop showing RoomView header when there's no room * Custom Header and different navigation based on stack * Refactor setHeader * MasterDetailContext * RoomView header * Fix isMasterDetail rule * KeyCommands kind of working * Create channel on tablet * RoomView sCU * Remove withSplit * Settings opening as modal * Settings * StatusView headerLeft * Admin panel * TwoFactor style * DirectoryView * ServerDropdown and SortDropdown animations * ThreadMessagesView * Navigate to empty RoomView on server switch when in master detail * ProfileView header * Fix navigation issues * Nav to any room info on tablet * Room info * Refactoring * Fix rooms search * Roomslist commands * SearchMessagesView close modal * Key commands * Fix undefined subscription * Disallow navigate to focused room * isFocused state on RoomsListView * Blur text inputs when focus is lost * Replace animation * Default nav theme * Refactoring * Always open Attachment with close modal button * ModalContainer backdrop following themes * Screen tracking * Refactor get active route for in-app notification * Only mark room as focused when in master detail layout * Lint * Open modals as fade from bottom on Android * typo * Fixing tests * Fix in-app update * Fixing goRoom issues * Refactor stack names * Fix unreadsCount * Fix stack * Fix header animation * Refactor ShareNavigation * Refactor navigation theme * Make sure title is set * Fix create discussion navigation * Remove unused variable * Create discussions from actions fixed * Layout animation * Screen lock on share extension * Unnecessary change * Admin border * Set header after state callback * Fix key commands on outside stack * Fix back button pressed * Remove layout animations from Android * Tweak animations on Android * Disable swipe gesture to open drawer * Fix current item on RoomsListView * Fix add server * Fix drawer * Fix broadcast * LayoutAnimation instead of Transitions * Fix onboarding back press * Fix assorted tests * Create discussion fix * RoomInfoView header * Drawer active item
2020-06-15 14:00:46 +00:00
}
[NEW] User notification preferences (#2403) * Button to preferences view Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Create screen to preferences and listItem to notifications Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Refactoring NotificationPreferencesView Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * List notification preferences Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Adding translations to labels Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * SetUserPreferences api call Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Saving new user preference in API Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Fix lint Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Add in-app notification test Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Fix in app mentions preference Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Improve object in testInAppNotification Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Removing improper options for NotificationpreferencesView Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Adding API version Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Use redux in UserNotificationPrefView Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Remove in app test Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Use components from another view Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Removing verification for testing in-app notifications Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Move to ProfileView Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-08-21 13:30:11 +00:00
options.headerRight = () => (
<HeaderButton.Preferences onPress={() => navigation?.navigate('UserPreferencesView')} testID='preferences-view-open' />
[NEW] User notification preferences (#2403) * Button to preferences view Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Create screen to preferences and listItem to notifications Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Refactoring NotificationPreferencesView Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * List notification preferences Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Adding translations to labels Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * SetUserPreferences api call Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Saving new user preference in API Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Fix lint Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Add in-app notification test Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Fix in app mentions preference Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Improve object in testInAppNotification Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Removing improper options for NotificationpreferencesView Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Adding API version Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Use redux in UserNotificationPrefView Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Remove in app test Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Use components from another view Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Removing verification for testing in-app notifications Signed-off-by: Ezequiel De Oliveira <ezequiel1de1oliveira@gmail.com> * Move to ProfileView Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-08-21 13:30:11 +00:00
);
navigation.setOptions(options);
};
constructor(props: IProfileViewProps) {
super(props);
this.setHeader();
}
state: IProfileViewState = {
saving: false,
name: '',
username: '',
email: '',
bio: '',
nickname: '',
newPassword: '',
currentPassword: '',
customFields: {},
twoFactorCode: null
};
feat: Change Avatar View (#4746) * [NEW] Change Avatar View * change avatar view and avatar suggestion * avatar Url * change avatar for profile it's done, missing fix revalidate the avatar in profile and drawer * pick image * clean profile view * Finished the profile and fixed the avatar when change the user profile * fix the profile update through all the app * refactor avatar suggestion * fix the delete from rooms and finished RoomInfoView, missing RoomInfoEditView * room info edit view * ipad navigation * refactor the submit function * refactor the e2e test * minor tweak with themes and buttons * minor tweak in edit button * minor tweaks * tweak IAvatarContainer * fixing pt-br * removed the avatarETagUser and search by username and text * created the useHooke useAvatarETag * fix lint * refactor image.ts and test * refactor avatar component * fix the edit button * refactor useAvatarETag * fix the pt-br translation * minor tweak tests * back handleError to views and refactor the submit * avatar suggestion item * types for change avatar view context * fix avatar on header for tablets * minor tweak changeavatarview * refactor avatar url to use hook form * tweak on yup validation * minor tweak with handle error * minor tweak * minor tweak * interface avatar container * minor tweak * Refactor all the changeAvatarView and fix how to test the image url * fixed the layout * minor refactor * minor tweaks * fix the visual bug when the user change the avatar to new then clear cache * fix the flicker when upload an image * update package.json * test the reset, discard alert, cancel and discard * separate the avatar test from profile and create new tests for change avatar * mock imagepicker * minor tweak, adding console and add echo to config.yml * use RUNNING_E2E_TESTS as env to other files * exprt env at android build * change the to way to set the running e2e test env * update test * delete the .env and update the e2e/readme and the file review * minor tweak * minor tweak * update the test, fixing how to dismiss the keyboard --------- Co-authored-by: Gleidson Daniel Silva <gleidson10daniel@hotmail.com>
2023-04-10 14:59:00 +00:00
componentDidMount() {
this.focusListener = this.props.navigation.addListener('focus', () => {
this.init();
});
}
componentWillUnmount() {
this.focusListener();
}
init = (user?: IUser) => {
const { user: userProps } = this.props;
const { name, username, emails, customFields, bio, nickname } = user || userProps;
this.setState({
name: name as string,
username,
email: emails ? emails[0].address : null,
newPassword: null,
currentPassword: null,
customFields: customFields || {},
bio,
nickname
});
};
formIsChanged = () => {
const { name, username, email, newPassword, customFields, bio, nickname } = this.state;
const { user } = this.props;
let customFieldsChanged = false;
const customFieldsKeys = Object.keys(customFields);
if (customFieldsKeys.length) {
customFieldsKeys.forEach(key => {
if (!user.customFields || user.customFields[key] !== customFields[key]) {
customFieldsChanged = true;
}
});
}
return !(
user.name === name &&
user.username === username &&
user.bio === bio &&
user.nickname === nickname &&
!newPassword &&
user.emails &&
user.emails[0].address === email &&
!customFieldsChanged
);
};
submit = async (): Promise<void> => {
Keyboard.dismiss();
if (!this.formIsChanged()) {
return;
}
this.setState({ saving: true });
const { name, username, email, newPassword, currentPassword, customFields, twoFactorCode, bio, nickname } = this.state;
const { user, dispatch } = this.props;
const params = {} as IProfileParams;
// Name
if (user.name !== name) {
2022-09-16 15:04:25 +00:00
params.realname = name;
}
// Username
if (user.username !== username) {
params.username = username;
}
// Email
if (user.emails && user.emails[0].address !== email) {
params.email = email;
}
if (user.bio !== bio) {
params.bio = bio;
}
if (user.nickname !== nickname) {
params.nickname = nickname;
}
// newPassword
if (newPassword) {
params.newPassword = newPassword;
}
// currentPassword
if (currentPassword) {
params.currentPassword = sha256(currentPassword);
}
const requirePassword = !!params.email || newPassword;
if (requirePassword && !params.currentPassword) {
2020-03-03 20:27:38 +00:00
this.setState({ saving: false });
this.props.showActionSheet({
children: (
<ActionSheetContentWithInputAndSubmit
title={I18n.t('Please_enter_your_password')}
description={I18n.t('For_your_security_you_must_enter_your_current_password_to_continue')}
testID='profile-view-enter-password-sheet'
placeholder={I18n.t('Password')}
onSubmit={(p: string) => {
this.props.hideActionSheet();
this.setState({ currentPassword: p }, () => this.submit());
}}
onCancel={this.props.hideActionSheet}
/>
)
});
2020-03-03 20:27:38 +00:00
return;
}
try {
const twoFactorOptions = params.currentPassword
? {
twoFactorCode: params.currentPassword,
twoFactorMethod: TwoFactorMethods.PASSWORD
}
: null;
const result = await Services.saveUserProfileMethod(params, customFields, twoFactorCode || twoFactorOptions);
if (result) {
[NEW] Log events from RoomsList, SideDrawer and Profile (#2190) * Create method to track user event to isolate the logic to improve future refactoring * Track Onboarding view * Track NewServer view * Refactor track method due to firebase already send the current screen * Track default login and all the oAuth options * Track default sign up in RegisterView * Change trackUserEvent signature and update all the files * Track the remaining login services * track add server, change server and search * Track SidebarView and refactor to use react-navigation * Track profile events and handle exceptions * Track create channel flux * Track send message to user via NewMessageView * Track create direct message flux * Handle failure of create channel and group in the saga * Track create discussion flux * Track navigate to directory and its actions * Track read, favorite and hide a channel, handling its errors * Track all channels sorting and grouping * Resolve requests to improve the importing logs and events * Remove unused events file * Leave a bugsnag breadcrumb when logging an event * Move all logEvent to the top of code block and log remaining fail events * Move all the non-logic-dependent logEvent to the top of code block * Improve the logging of sidebar events * Improve events from onboarding and newserver * Improve events from login and register view, and log enter with apple * Improve NewMessageView events * Improve CreateChannel events * Improve CreateDiscussion and SelectedUsers create group events * Improve RoomsList events and log trivial events * Improve ProfileView events * Remove single line function body for the sidebarNavigate * Navigate to Status and AdminPanel View using the defined sidebarNavigate method Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-07-30 13:26:17 +00:00
logEvent(events.PROFILE_SAVE_CHANGES);
if ('realname' in params) {
params.name = params.realname;
delete params.realname;
}
2019-06-05 16:29:07 +00:00
if (customFields) {
dispatch(setUser({ customFields, ...params }));
this.setState({ ...this.state, customFields, ...params });
2019-06-05 16:29:07 +00:00
} else {
dispatch(setUser({ ...params }));
this.setState({ ...this.state, ...params });
}
2019-07-23 14:02:57 +00:00
EventEmitter.emit(LISTENER, { message: I18n.t('Profile_saved_successfully') });
}
this.setState({ saving: false, currentPassword: null, twoFactorCode: null });
} catch (e: any) {
if (e?.error === 'totp-invalid' && e?.details.method !== TwoFactorMethods.PASSWORD) {
try {
const code = await twoFactor({ method: e?.details.method, invalid: e?.error === 'totp-invalid' && !!twoFactorCode });
return this.setState({ twoFactorCode: code }, () => this.submit());
} catch {
// cancelled twoFactor modal
}
}
[NEW] Log events from RoomsList, SideDrawer and Profile (#2190) * Create method to track user event to isolate the logic to improve future refactoring * Track Onboarding view * Track NewServer view * Refactor track method due to firebase already send the current screen * Track default login and all the oAuth options * Track default sign up in RegisterView * Change trackUserEvent signature and update all the files * Track the remaining login services * track add server, change server and search * Track SidebarView and refactor to use react-navigation * Track profile events and handle exceptions * Track create channel flux * Track send message to user via NewMessageView * Track create direct message flux * Handle failure of create channel and group in the saga * Track create discussion flux * Track navigate to directory and its actions * Track read, favorite and hide a channel, handling its errors * Track all channels sorting and grouping * Resolve requests to improve the importing logs and events * Remove unused events file * Leave a bugsnag breadcrumb when logging an event * Move all logEvent to the top of code block and log remaining fail events * Move all the non-logic-dependent logEvent to the top of code block * Improve the logging of sidebar events * Improve events from onboarding and newserver * Improve events from login and register view, and log enter with apple * Improve NewMessageView events * Improve CreateChannel events * Improve CreateDiscussion and SelectedUsers create group events * Improve RoomsList events and log trivial events * Improve ProfileView events * Remove single line function body for the sidebarNavigate * Navigate to Status and AdminPanel View using the defined sidebarNavigate method Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-07-30 13:26:17 +00:00
logEvent(events.PROFILE_SAVE_CHANGES_F);
this.setState({ saving: false, currentPassword: null, twoFactorCode: null });
feat: Change Avatar View (#4746) * [NEW] Change Avatar View * change avatar view and avatar suggestion * avatar Url * change avatar for profile it's done, missing fix revalidate the avatar in profile and drawer * pick image * clean profile view * Finished the profile and fixed the avatar when change the user profile * fix the profile update through all the app * refactor avatar suggestion * fix the delete from rooms and finished RoomInfoView, missing RoomInfoEditView * room info edit view * ipad navigation * refactor the submit function * refactor the e2e test * minor tweak with themes and buttons * minor tweak in edit button * minor tweaks * tweak IAvatarContainer * fixing pt-br * removed the avatarETagUser and search by username and text * created the useHooke useAvatarETag * fix lint * refactor image.ts and test * refactor avatar component * fix the edit button * refactor useAvatarETag * fix the pt-br translation * minor tweak tests * back handleError to views and refactor the submit * avatar suggestion item * types for change avatar view context * fix avatar on header for tablets * minor tweak changeavatarview * refactor avatar url to use hook form * tweak on yup validation * minor tweak with handle error * minor tweak * minor tweak * interface avatar container * minor tweak * Refactor all the changeAvatarView and fix how to test the image url * fixed the layout * minor refactor * minor tweaks * fix the visual bug when the user change the avatar to new then clear cache * fix the flicker when upload an image * update package.json * test the reset, discard alert, cancel and discard * separate the avatar test from profile and create new tests for change avatar * mock imagepicker * minor tweak, adding console and add echo to config.yml * use RUNNING_E2E_TESTS as env to other files * exprt env at android build * change the to way to set the running e2e test env * update test * delete the .env and update the e2e/readme and the file review * minor tweak * minor tweak * update the test, fixing how to dismiss the keyboard --------- Co-authored-by: Gleidson Daniel Silva <gleidson10daniel@hotmail.com>
2023-04-10 14:59:00 +00:00
this.handleError(e, 'saving_profile');
}
};
resetAvatar = async () => {
const { Accounts_AllowUserAvatarChange } = this.props;
if (!Accounts_AllowUserAvatarChange) {
return;
}
try {
const { user } = this.props;
await Services.resetAvatar(user.id);
2019-07-23 14:02:57 +00:00
EventEmitter.emit(LISTENER, { message: I18n.t('Avatar_changed_successfully') });
this.init();
} catch (e) {
feat: Change Avatar View (#4746) * [NEW] Change Avatar View * change avatar view and avatar suggestion * avatar Url * change avatar for profile it's done, missing fix revalidate the avatar in profile and drawer * pick image * clean profile view * Finished the profile and fixed the avatar when change the user profile * fix the profile update through all the app * refactor avatar suggestion * fix the delete from rooms and finished RoomInfoView, missing RoomInfoEditView * room info edit view * ipad navigation * refactor the submit function * refactor the e2e test * minor tweak with themes and buttons * minor tweak in edit button * minor tweaks * tweak IAvatarContainer * fixing pt-br * removed the avatarETagUser and search by username and text * created the useHooke useAvatarETag * fix lint * refactor image.ts and test * refactor avatar component * fix the edit button * refactor useAvatarETag * fix the pt-br translation * minor tweak tests * back handleError to views and refactor the submit * avatar suggestion item * types for change avatar view context * fix avatar on header for tablets * minor tweak changeavatarview * refactor avatar url to use hook form * tweak on yup validation * minor tweak with handle error * minor tweak * minor tweak * interface avatar container * minor tweak * Refactor all the changeAvatarView and fix how to test the image url * fixed the layout * minor refactor * minor tweaks * fix the visual bug when the user change the avatar to new then clear cache * fix the flicker when upload an image * update package.json * test the reset, discard alert, cancel and discard * separate the avatar test from profile and create new tests for change avatar * mock imagepicker * minor tweak, adding console and add echo to config.yml * use RUNNING_E2E_TESTS as env to other files * exprt env at android build * change the to way to set the running e2e test env * update test * delete the .env and update the e2e/readme and the file review * minor tweak * minor tweak * update the test, fixing how to dismiss the keyboard --------- Co-authored-by: Gleidson Daniel Silva <gleidson10daniel@hotmail.com>
2023-04-10 14:59:00 +00:00
this.handleError(e, 'changing_avatar');
}
};
feat: Change Avatar View (#4746) * [NEW] Change Avatar View * change avatar view and avatar suggestion * avatar Url * change avatar for profile it's done, missing fix revalidate the avatar in profile and drawer * pick image * clean profile view * Finished the profile and fixed the avatar when change the user profile * fix the profile update through all the app * refactor avatar suggestion * fix the delete from rooms and finished RoomInfoView, missing RoomInfoEditView * room info edit view * ipad navigation * refactor the submit function * refactor the e2e test * minor tweak with themes and buttons * minor tweak in edit button * minor tweaks * tweak IAvatarContainer * fixing pt-br * removed the avatarETagUser and search by username and text * created the useHooke useAvatarETag * fix lint * refactor image.ts and test * refactor avatar component * fix the edit button * refactor useAvatarETag * fix the pt-br translation * minor tweak tests * back handleError to views and refactor the submit * avatar suggestion item * types for change avatar view context * fix avatar on header for tablets * minor tweak changeavatarview * refactor avatar url to use hook form * tweak on yup validation * minor tweak with handle error * minor tweak * minor tweak * interface avatar container * minor tweak * Refactor all the changeAvatarView and fix how to test the image url * fixed the layout * minor refactor * minor tweaks * fix the visual bug when the user change the avatar to new then clear cache * fix the flicker when upload an image * update package.json * test the reset, discard alert, cancel and discard * separate the avatar test from profile and create new tests for change avatar * mock imagepicker * minor tweak, adding console and add echo to config.yml * use RUNNING_E2E_TESTS as env to other files * exprt env at android build * change the to way to set the running e2e test env * update test * delete the .env and update the e2e/readme and the file review * minor tweak * minor tweak * update the test, fixing how to dismiss the keyboard --------- Co-authored-by: Gleidson Daniel Silva <gleidson10daniel@hotmail.com>
2023-04-10 14:59:00 +00:00
handleError = (e: any, action: string) => {
if (e.data && e.data.error.includes('[error-too-many-requests]')) {
return showErrorAlert(e.data.error);
}
feat: Change Avatar View (#4746) * [NEW] Change Avatar View * change avatar view and avatar suggestion * avatar Url * change avatar for profile it's done, missing fix revalidate the avatar in profile and drawer * pick image * clean profile view * Finished the profile and fixed the avatar when change the user profile * fix the profile update through all the app * refactor avatar suggestion * fix the delete from rooms and finished RoomInfoView, missing RoomInfoEditView * room info edit view * ipad navigation * refactor the submit function * refactor the e2e test * minor tweak with themes and buttons * minor tweak in edit button * minor tweaks * tweak IAvatarContainer * fixing pt-br * removed the avatarETagUser and search by username and text * created the useHooke useAvatarETag * fix lint * refactor image.ts and test * refactor avatar component * fix the edit button * refactor useAvatarETag * fix the pt-br translation * minor tweak tests * back handleError to views and refactor the submit * avatar suggestion item * types for change avatar view context * fix avatar on header for tablets * minor tweak changeavatarview * refactor avatar url to use hook form * tweak on yup validation * minor tweak with handle error * minor tweak * minor tweak * interface avatar container * minor tweak * Refactor all the changeAvatarView and fix how to test the image url * fixed the layout * minor refactor * minor tweaks * fix the visual bug when the user change the avatar to new then clear cache * fix the flicker when upload an image * update package.json * test the reset, discard alert, cancel and discard * separate the avatar test from profile and create new tests for change avatar * mock imagepicker * minor tweak, adding console and add echo to config.yml * use RUNNING_E2E_TESTS as env to other files * exprt env at android build * change the to way to set the running e2e test env * update test * delete the .env and update the e2e/readme and the file review * minor tweak * minor tweak * update the test, fixing how to dismiss the keyboard --------- Co-authored-by: Gleidson Daniel Silva <gleidson10daniel@hotmail.com>
2023-04-10 14:59:00 +00:00
if (I18n.isTranslated(e.error)) {
return showErrorAlert(I18n.t(e.error));
}
let msg = I18n.t('There_was_an_error_while_action', { action: I18n.t(action) });
let title = '';
if (typeof e.reason === 'string') {
title = msg;
msg = e.reason;
}
showErrorAlert(msg, title);
};
feat: Change Avatar View (#4746) * [NEW] Change Avatar View * change avatar view and avatar suggestion * avatar Url * change avatar for profile it's done, missing fix revalidate the avatar in profile and drawer * pick image * clean profile view * Finished the profile and fixed the avatar when change the user profile * fix the profile update through all the app * refactor avatar suggestion * fix the delete from rooms and finished RoomInfoView, missing RoomInfoEditView * room info edit view * ipad navigation * refactor the submit function * refactor the e2e test * minor tweak with themes and buttons * minor tweak in edit button * minor tweaks * tweak IAvatarContainer * fixing pt-br * removed the avatarETagUser and search by username and text * created the useHooke useAvatarETag * fix lint * refactor image.ts and test * refactor avatar component * fix the edit button * refactor useAvatarETag * fix the pt-br translation * minor tweak tests * back handleError to views and refactor the submit * avatar suggestion item * types for change avatar view context * fix avatar on header for tablets * minor tweak changeavatarview * refactor avatar url to use hook form * tweak on yup validation * minor tweak with handle error * minor tweak * minor tweak * interface avatar container * minor tweak * Refactor all the changeAvatarView and fix how to test the image url * fixed the layout * minor refactor * minor tweaks * fix the visual bug when the user change the avatar to new then clear cache * fix the flicker when upload an image * update package.json * test the reset, discard alert, cancel and discard * separate the avatar test from profile and create new tests for change avatar * mock imagepicker * minor tweak, adding console and add echo to config.yml * use RUNNING_E2E_TESTS as env to other files * exprt env at android build * change the to way to set the running e2e test env * update test * delete the .env and update the e2e/readme and the file review * minor tweak * minor tweak * update the test, fixing how to dismiss the keyboard --------- Co-authored-by: Gleidson Daniel Silva <gleidson10daniel@hotmail.com>
2023-04-10 14:59:00 +00:00
handleEditAvatar = () => {
const { navigation } = this.props;
navigation.navigate('ChangeAvatarView', { context: 'profile' });
};
[NEW] Log events from RoomsList, SideDrawer and Profile (#2190) * Create method to track user event to isolate the logic to improve future refactoring * Track Onboarding view * Track NewServer view * Refactor track method due to firebase already send the current screen * Track default login and all the oAuth options * Track default sign up in RegisterView * Change trackUserEvent signature and update all the files * Track the remaining login services * track add server, change server and search * Track SidebarView and refactor to use react-navigation * Track profile events and handle exceptions * Track create channel flux * Track send message to user via NewMessageView * Track create direct message flux * Handle failure of create channel and group in the saga * Track create discussion flux * Track navigate to directory and its actions * Track read, favorite and hide a channel, handling its errors * Track all channels sorting and grouping * Resolve requests to improve the importing logs and events * Remove unused events file * Leave a bugsnag breadcrumb when logging an event * Move all logEvent to the top of code block and log remaining fail events * Move all the non-logic-dependent logEvent to the top of code block * Improve the logging of sidebar events * Improve events from onboarding and newserver * Improve events from login and register view, and log enter with apple * Improve NewMessageView events * Improve CreateChannel events * Improve CreateDiscussion and SelectedUsers create group events * Improve RoomsList events and log trivial events * Improve ProfileView events * Remove single line function body for the sidebarNavigate * Navigate to Status and AdminPanel View using the defined sidebarNavigate method Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-07-30 13:26:17 +00:00
renderAvatarButton = ({ key, child, onPress, disabled = false }: IAvatarButton) => {
2019-12-04 16:39:53 +00:00
const { theme } = this.props;
return (
<Touch
key={key}
testID={key}
onPress={onPress}
style={[styles.avatarButton, { opacity: disabled ? 0.5 : 1 }, { backgroundColor: themes[theme].borderColor }]}
enabled={!disabled}
>
{child}
2019-12-04 16:39:53 +00:00
</Touch>
);
};
renderCustomFields = () => {
const { customFields } = this.state;
const { Accounts_CustomFields } = this.props;
if (!Accounts_CustomFields) {
return null;
}
try {
const parsedCustomFields = JSON.parse(Accounts_CustomFields);
return Object.keys(parsedCustomFields).map((key, index, array) => {
if (parsedCustomFields[key].type === 'select') {
const options = parsedCustomFields[key].options.map((option: string) => ({ label: option, value: option }));
return (
<RNPickerSelect
key={key}
items={options}
onValueChange={value => {
const newValue: { [key: string]: string } = {};
newValue[key] = value;
this.setState({ customFields: { ...customFields, ...newValue } });
}}
value={customFields[key]}
>
<FormTextInput
inputRef={e => {
// @ts-ignore
this[key] = e;
}}
label={key}
placeholder={key}
value={customFields[key]}
testID='settings-view-language'
/>
</RNPickerSelect>
);
}
return (
<FormTextInput
inputRef={e => {
// @ts-ignore
this[key] = e;
}}
key={key}
label={key}
placeholder={key}
value={customFields[key]}
onChangeText={value => {
const newValue: { [key: string]: string } = {};
newValue[key] = value;
this.setState({ customFields: { ...customFields, ...newValue } });
}}
onSubmitEditing={() => {
if (array.length - 1 > index) {
// @ts-ignore
return this[array[index + 1]].focus();
}
this.avatarUrl?.focus();
}}
/>
);
});
} catch (error) {
return null;
}
};
2018-06-05 01:17:02 +00:00
logoutOtherLocations = () => {
logEvent(events.PL_OTHER_LOCATIONS);
showConfirmationAlert({
message: I18n.t('You_will_be_logged_out_from_other_locations'),
confirmationText: I18n.t('Logout'),
onPress: async () => {
try {
await Services.logoutOtherLocations();
EventEmitter.emit(LISTENER, { message: I18n.t('Logged_out_of_other_clients_successfully') });
} catch {
logEvent(events.PL_OTHER_LOCATIONS_F);
EventEmitter.emit(LISTENER, { message: I18n.t('Logout_failed') });
}
}
});
};
deleteOwnAccount = () => {
logEvent(events.DELETE_OWN_ACCOUNT);
this.props.showActionSheet({
children: <DeleteAccountActionSheetContent />
});
};
2018-06-05 01:17:02 +00:00
render() {
const { name, username, email, newPassword, customFields, saving, nickname, bio } = this.state;
2019-12-04 16:39:53 +00:00
const {
user,
theme,
Accounts_AllowEmailChange,
Accounts_AllowPasswordChange,
Accounts_AllowRealNameChange,
Accounts_AllowUserAvatarChange,
Accounts_AllowUsernameChange,
Accounts_CustomFields,
Accounts_AllowDeleteOwnAccount,
serverVersion
2019-12-04 16:39:53 +00:00
} = this.props;
2018-06-05 01:17:02 +00:00
return (
<KeyboardView
2019-12-04 16:39:53 +00:00
style={{ backgroundColor: themes[theme].auxiliaryBackground }}
contentContainerStyle={sharedStyles.container}
keyboardVerticalOffset={128}
>
<StatusBar />
<SafeAreaView testID='profile-view'>
<ScrollView contentContainerStyle={sharedStyles.containerScrollView} testID='profile-view-list' {...scrollPersistTaps}>
<View style={styles.avatarContainer} testID='profile-view-avatar'>
feat: Change Avatar View (#4746) * [NEW] Change Avatar View * change avatar view and avatar suggestion * avatar Url * change avatar for profile it's done, missing fix revalidate the avatar in profile and drawer * pick image * clean profile view * Finished the profile and fixed the avatar when change the user profile * fix the profile update through all the app * refactor avatar suggestion * fix the delete from rooms and finished RoomInfoView, missing RoomInfoEditView * room info edit view * ipad navigation * refactor the submit function * refactor the e2e test * minor tweak with themes and buttons * minor tweak in edit button * minor tweaks * tweak IAvatarContainer * fixing pt-br * removed the avatarETagUser and search by username and text * created the useHooke useAvatarETag * fix lint * refactor image.ts and test * refactor avatar component * fix the edit button * refactor useAvatarETag * fix the pt-br translation * minor tweak tests * back handleError to views and refactor the submit * avatar suggestion item * types for change avatar view context * fix avatar on header for tablets * minor tweak changeavatarview * refactor avatar url to use hook form * tweak on yup validation * minor tweak with handle error * minor tweak * minor tweak * interface avatar container * minor tweak * Refactor all the changeAvatarView and fix how to test the image url * fixed the layout * minor refactor * minor tweaks * fix the visual bug when the user change the avatar to new then clear cache * fix the flicker when upload an image * update package.json * test the reset, discard alert, cancel and discard * separate the avatar test from profile and create new tests for change avatar * mock imagepicker * minor tweak, adding console and add echo to config.yml * use RUNNING_E2E_TESTS as env to other files * exprt env at android build * change the to way to set the running e2e test env * update test * delete the .env and update the e2e/readme and the file review * minor tweak * minor tweak * update the test, fixing how to dismiss the keyboard --------- Co-authored-by: Gleidson Daniel Silva <gleidson10daniel@hotmail.com>
2023-04-10 14:59:00 +00:00
<AvatarWithEdit
text={user.username}
handleEdit={Accounts_AllowUserAvatarChange ? this.handleEditAvatar : undefined}
/>
</View>
<FormTextInput
editable={Accounts_AllowRealNameChange}
inputStyle={[!Accounts_AllowRealNameChange && styles.disabled]}
inputRef={e => (this.name = e)}
label={I18n.t('Name')}
placeholder={I18n.t('Name')}
value={name}
onChangeText={(value: string) => this.setState({ name: value })}
onSubmitEditing={() => {
this.username?.focus();
}}
testID='profile-view-name'
/>
<FormTextInput
editable={Accounts_AllowUsernameChange}
inputStyle={[!Accounts_AllowUsernameChange && styles.disabled]}
inputRef={e => (this.username = e)}
label={I18n.t('Username')}
placeholder={I18n.t('Username')}
value={username}
onChangeText={value => this.setState({ username: value })}
onSubmitEditing={() => {
this.email?.focus();
}}
testID='profile-view-username'
/>
<FormTextInput
editable={Accounts_AllowEmailChange}
inputStyle={[!Accounts_AllowEmailChange && styles.disabled]}
inputRef={e => (this.email = e)}
label={I18n.t('Email')}
placeholder={I18n.t('Email')}
value={email || undefined}
onChangeText={value => this.setState({ email: value })}
onSubmitEditing={() => {
this.nickname?.focus();
}}
testID='profile-view-email'
/>
{compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '3.5.0') ? (
<FormTextInput
inputRef={e => (this.nickname = e)}
label={I18n.t('Nickname')}
value={nickname}
onChangeText={value => this.setState({ nickname: value })}
onSubmitEditing={() => {
this.bio?.focus();
}}
testID='profile-view-nickname'
maxLength={MAX_NICKNAME_LENGTH}
/>
) : null}
{compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '3.1.0') ? (
<FormTextInput
inputRef={e => (this.bio = e)}
label={I18n.t('Bio')}
inputStyle={styles.inputBio}
multiline
maxLength={MAX_BIO_LENGTH}
value={bio}
onChangeText={value => this.setState({ bio: value })}
onSubmitEditing={() => {
this.newPassword?.focus();
}}
testID='profile-view-bio'
/>
) : null}
<FormTextInput
editable={Accounts_AllowPasswordChange}
inputStyle={[!Accounts_AllowPasswordChange && styles.disabled]}
inputRef={e => (this.newPassword = e)}
label={I18n.t('New_Password')}
placeholder={I18n.t('New_Password')}
value={newPassword || undefined}
onChangeText={value => this.setState({ newPassword: value })}
onSubmitEditing={() => {
if (Accounts_CustomFields && Object.keys(customFields).length) {
// @ts-ignore
return this[Object.keys(customFields)[0]].focus();
}
this.avatarUrl?.focus();
}}
secureTextEntry
testID='profile-view-new-password'
/>
{this.renderCustomFields()}
<Button
title={I18n.t('Save_Changes')}
type='primary'
onPress={this.submit}
disabled={!this.formIsChanged()}
testID='profile-view-submit'
loading={saving}
/>
<Button
title={I18n.t('Logout_from_other_logged_in_locations')}
type='secondary'
backgroundColor={themes[theme].chatComponentBackground}
onPress={this.logoutOtherLocations}
testID='profile-view-logout-other-locations'
/>
{Accounts_AllowDeleteOwnAccount ? (
<Button
title={I18n.t('Delete_my_account')}
type='primary'
backgroundColor={themes[theme].dangerColor}
onPress={this.deleteOwnAccount}
testID='profile-view-delete-my-account'
/>
) : null}
2019-12-04 16:39:53 +00:00
</ScrollView>
</SafeAreaView>
</KeyboardView>
2018-06-05 01:17:02 +00:00
);
}
}
const mapStateToProps = (state: IApplicationState) => ({
2020-02-11 14:09:14 +00:00
user: getUserSelector(state),
isMasterDetail: state.app.isMasterDetail,
Accounts_AllowEmailChange: state.settings.Accounts_AllowEmailChange as boolean,
Accounts_AllowPasswordChange: state.settings.Accounts_AllowPasswordChange as boolean,
Accounts_AllowRealNameChange: state.settings.Accounts_AllowRealNameChange as boolean,
Accounts_AllowUserAvatarChange: state.settings.Accounts_AllowUserAvatarChange as boolean,
Accounts_AllowUsernameChange: state.settings.Accounts_AllowUsernameChange as boolean,
Accounts_CustomFields: state.settings.Accounts_CustomFields as string,
baseUrl: state.server.server,
serverVersion: state.server.version,
Accounts_AllowDeleteOwnAccount: state.settings.Accounts_AllowDeleteOwnAccount as boolean
});
export default connect(mapStateToProps)(withTheme(withActionSheet(ProfileView)));