Skip to content
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

chore: Release 4.49.1 #5721

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode VERSIONCODE as Integer
versionName "4.49.0"
versionName "4.49.1"
vectorDrawables.useSupportLibrary = true
if (!isFoss) {
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useState, useRef } from 'react';
import { StyleSheet, Text, View } from 'react-native';

import { CustomIcon, TIconsName } from '../../CustomIcon';
Expand Down Expand Up @@ -42,22 +42,28 @@ const FooterButtons = ({
confirmTitle = '',
disabled = false,
cancelBackgroundColor = '',
confirmBackgroundColor = ''
confirmBackgroundColor = '',
testID = ''
}): React.ReactElement => {
const { colors } = useTheme();
return (
<View style={styles.footerButtonsContainer}>
<Button
style={[styles.buttonSeparator, { flex: 1, backgroundColor: cancelBackgroundColor || colors.buttonBackgroundSecondaryDefault }]}
style={[
styles.buttonSeparator,
{ flex: 1, backgroundColor: cancelBackgroundColor || colors.buttonBackgroundSecondaryDefault }
]}
color={colors.backdropColor}
title={cancelTitle}
onPress={cancelAction}
testID={`${testID}-cancel`}
/>
<Button
style={{ flex: 1, backgroundColor: confirmBackgroundColor || colors.buttonBackgroundDangerDefault }}
title={confirmTitle}
onPress={confirmAction}
disabled={disabled}
testID={`${testID}-confirm`}
/>
</View>
);
Expand All @@ -76,62 +82,104 @@ const ActionSheetContentWithInputAndSubmit = ({
iconColor,
customText,
confirmBackgroundColor,
showInput = true
showInput = true,
inputs = [],
isDisabled
}: {
onSubmit: (inputValue: string) => void;
onSubmit: (inputValue: string | string[]) => void;
onCancel?: () => void;
title: string;
description: string;
description?: string;
testID: string;
secureTextEntry?: boolean;
placeholder: string;
placeholder?: string;
confirmTitle?: string;
iconName?: TIconsName;
iconColor?: string;
customText?: React.ReactElement;
confirmBackgroundColor?: string;
showInput?: boolean;
inputs?: { placeholder: string; secureTextEntry?: boolean; key: string }[];
isDisabled?: (inputValues: string[]) => boolean;
}): React.ReactElement => {
const { colors } = useTheme();
const [inputValue, setInputValue] = useState('');
const [inputValues, setInputValues] = useState(inputs.map(() => ''));
const inputRefs = useRef(inputs.map(() => React.createRef()));

const handleInputChange = (value: string, index: number) => {
const newInputValues = [...inputValues];
newInputValues[index] = value;
setInputValues(newInputValues);
};

const { hideActionSheet } = useActionSheet();

const renderInputs = () => {
if (inputs.length > 0) {
return inputs.map((inputConfig, index) => (
<FormTextInput
key={inputConfig.key}
value={inputValues[index]}
placeholder={inputConfig.placeholder}
onChangeText={value => handleInputChange(value, index)}
onSubmitEditing={() => {
if (index < inputs.length - 1) {
(inputRefs.current[index + 1] as any).current.focus();
} else {
setTimeout(() => {
hideActionSheet();
}, 100);
if (inputValues.every(value => value)) onSubmit(inputValues);
}
}}
inputRef={inputRefs.current[index] as any}
testID={`${testID}-input-${inputConfig.key}`}
secureTextEntry={inputConfig.secureTextEntry}
bottomSheet={isIOS}
/>
));
}

return (
<FormTextInput
value={inputValues[0]}
placeholder={placeholder}
onChangeText={value => handleInputChange(value, 0)}
onSubmitEditing={() => {
setTimeout(() => {
hideActionSheet();
}, 100);
if (inputValues[0]) onSubmit(inputValues[0]);
}}
testID={`${testID}-input`}
secureTextEntry={secureTextEntry}
bottomSheet={isIOS}
/>
);
};

const defaultDisabled = showInput && inputValues.some(value => !value);
const disabled = isDisabled ? isDisabled(inputValues) : defaultDisabled;

return (
<View style={sharedStyles.containerScrollView} testID='action-sheet-content-with-input-and-submit'>
<>
<View style={styles.titleContainer}>
{iconName ? <CustomIcon name={iconName} size={32} color={iconColor || colors.buttonBackgroundDangerDefault} /> : null}
<Text style={[styles.titleContainerText, { color: colors.fontDefault, paddingLeft: iconName ? 16 : 0 }]}>
{title}
</Text>
<Text style={[styles.titleContainerText, { color: colors.fontDefault, paddingLeft: iconName ? 16 : 0 }]}>{title}</Text>
</View>
<Text style={[styles.subtitleText, { color: colors.fontTitlesLabels }]}>{description}</Text>
{description ? <Text style={[styles.subtitleText, { color: colors.fontTitlesLabels }]}>{description}</Text> : null}
{customText}
</>
{showInput ? (
<FormTextInput
value={inputValue}
placeholder={placeholder}
onChangeText={value => setInputValue(value)}
onSubmitEditing={() => {
// fix android animation
setTimeout(() => {
hideActionSheet();
}, 100);
if (inputValue) onSubmit(inputValue);
}}
testID={testID}
secureTextEntry={secureTextEntry}
bottomSheet={isIOS}
/>
) : null}
{showInput ? renderInputs() : null}
<FooterButtons
confirmBackgroundColor={confirmBackgroundColor || colors.fontHint}
cancelAction={onCancel || hideActionSheet}
confirmAction={() => onSubmit(inputValue)}
confirmAction={() => onSubmit(inputs.length > 0 ? inputValues : inputValues[0])}
cancelTitle={i18n.t('Cancel')}
confirmTitle={confirmTitle || i18n.t('Save')}
disabled={!showInput ? false : !inputValue}
disabled={disabled}
testID={testID}
/>
</View>
);
Expand Down
107 changes: 107 additions & 0 deletions app/containers/ChangePasswordRequired.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import React, { useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { useDispatch } from 'react-redux';

import { logout, setUser } from '../actions/login';
import I18n from '../i18n';
import { useSetting } from '../lib/hooks/useSetting';
import { showErrorAlert } from '../lib/methods/helpers';
import { Services } from '../lib/services';
import { useTheme } from '../theme';
import sharedStyles from '../views/Styles';
import { useActionSheet } from './ActionSheet';
import ActionSheetContentWithInputAndSubmit from './ActionSheet/ActionSheetContentWithInputAndSubmit';
import Button from './Button';
import { CustomIcon } from './CustomIcon';

export const ChangePasswordRequired = () => {
const [loading, setLoading] = useState(false);
const { colors } = useTheme();
const dispatch = useDispatch();
const { showActionSheet, hideActionSheet } = useActionSheet();

const requiresPasswordConfirmation = useSetting('Accounts_RequirePasswordConfirmation');
const passwordPlaceholder = useSetting('Accounts_PasswordPlaceholder') as string;
const passwordConfirmationPlaceholder = useSetting('Accounts_ConfirmPasswordPlaceholder') as string;

const changePassword = async (password: string) => {
setLoading(true);
try {
await Services.setUserPassword(password);
dispatch(setUser({ requirePasswordChange: false }));
hideActionSheet();
} catch (error: any) {
showErrorAlert(error?.reason || error?.message, I18n.t('Oops'));
}
setLoading(false);
};

const showActionSheetPassword = () => {
const inputs = [{ placeholder: passwordPlaceholder || I18n.t('Password'), secureTextEntry: true, key: 'password' }];
if (requiresPasswordConfirmation) {
inputs.push({
placeholder: passwordConfirmationPlaceholder || I18n.t('Confirm_your_password'),
secureTextEntry: true,
key: 'confirm-password'
});
}
showActionSheet({
children: (
<ActionSheetContentWithInputAndSubmit
title={I18n.t('Please_Enter_your_new_password')}
testID='change-password-required-sheet'
inputs={inputs}
onSubmit={input => changePassword(input[0])}
isDisabled={input => (loading || input[0] === '' || requiresPasswordConfirmation ? input[0] !== input[1] : false)}
/>
)
});
};

return (
<View style={[styles.container, { paddingTop: 120, backgroundColor: colors.surfaceLight }]}>
<View style={styles.iconContainer}>
<CustomIcon name='info' size={36} color={colors.statusFontWarning} />
</View>
<Text style={[styles.title, { color: colors.fontTitlesLabels }]}>{I18n.t('You_need_to_change_your_password')}</Text>
<Text style={[styles.description, { color: colors.fontDefault }]}>{I18n.t('To_continue_using_RocketChat')}</Text>
<Button
testID='change-password-required-button'
title={I18n.t('Change_password')}
type='primary'
onPress={showActionSheetPassword}
/>
<Button
testID='change-password-required-logout'
title={I18n.t('Logout')}
type='secondary'
backgroundColor={colors.surfaceTint}
onPress={() => dispatch(logout())}
/>
</View>
);
};

const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
backgroundColor: '#fff'
},
iconContainer: {
alignItems: 'center',
padding: 24
},
title: {
fontSize: 20,
lineHeight: 30,
marginBottom: 24,
...sharedStyles.textBold
},
description: {
fontSize: 16,
lineHeight: 24,
marginBottom: 24,
...sharedStyles.textRegular
}
});
1 change: 1 addition & 0 deletions app/definitions/ILoggedUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface ILoggedUser {
alsoSendThreadToChannel: 'default' | 'always' | 'never';
bio?: string;
nickname?: string;
requirePasswordChange?: boolean;
}

export interface ILoggedUserResultFromServer
Expand Down
5 changes: 5 additions & 0 deletions app/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
"Certificate_password": "Certificate password",
"Change_Language": "Change language",
"Change_language_loading": "Changing language.",
"Change_password": "Change password",
"changed_room_announcement": "changed room announcement to: {{announcement}}",
"changed_room_description": "changed room description to: {{description}}",
"changing_avatar": "changing avatar",
Expand Down Expand Up @@ -127,6 +128,7 @@
"Condensed": "Condensed",
"conference_call": "Conference call",
"Confirm": "Confirm",
"Confirm_your_password": "Confirm your password",
"Confirmation": "Confirmation",
"Connect": "Connect",
"Connecting": "Connecting...",
Expand Down Expand Up @@ -523,6 +525,7 @@
"Pinned_a_message": "Pinned a message:",
"Place_chat_on_hold": "Place chat on hold",
"Please_add_a_comment": "Please add a comment",
"Please_Enter_your_new_password": "Please enter your new password",
"Please_enter_your_password": "Please enter your password",
"Please_wait": "Please wait.",
"Preferences": "Preferences",
Expand Down Expand Up @@ -724,6 +727,7 @@
"Threads_displaying_following": "Displaying following",
"Threads_displaying_unread": "Displaying unread",
"Timezone": "Timezone",
"To_continue_using_RocketChat": "To continue using the mobile app, you need to change your password.",
"Token_expired": "Your session has expired. Please log in again.",
"Topic": "Topic",
"topic": "topic",
Expand Down Expand Up @@ -822,6 +826,7 @@
"You_colon": "You: ",
"You_dont_have_permission_to_perform_this_action": "You don’t have permission to perform this action. Check with a workspace administrator.",
"You_need_to_access_at_least_one_RocketChat_server_to_share_something": "You need to access at least one Rocket.Chat workspace to share something.",
"You_need_to_change_your_password": "You need to change your password",
"You_need_to_verifiy_your_email_address_to_get_notications": "You need to verify your email address to get notifications",
"you_were_mentioned": "you were mentioned",
"You_were_removed_from_channel": "You were removed from {{channel}}",
Expand Down
5 changes: 5 additions & 0 deletions app/i18n/locales/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"Certificate_password": "Senha do certificado",
"Change_Language": "Alterar idioma",
"Change_language_loading": "Alterando idioma.",
"Change_password": "Alterar senha",
"changed_room_announcement": "alterou o anúncio da sala para: {{announcement}}",
"changed_room_description": "alterou a descrição da sala para: {{description}}",
"changing_avatar": "trocando avatar",
Expand Down Expand Up @@ -124,6 +125,7 @@
"Condensed": "Condensado",
"conference_call": "Video conferência",
"Confirm": "Confirmar",
"Confirm_your_password": "Confirme sua senha",
"Confirmation": "Confirmação",
"Connect": "Conectar",
"Connecting": "Conectando...",
Expand Down Expand Up @@ -515,6 +517,7 @@
"Pinned_a_message": "Fixou uma mensagem:",
"Place_chat_on_hold": "Colocar conversa em espera",
"Please_add_a_comment": "Por favor, adicione um comentário",
"Please_Enter_your_new_password": "Por favor, insira sua nova senha",
"Please_enter_your_password": "Por favor, digite sua senha",
"Please_wait": "Por favor, aguarde.",
"Preferences": "Preferências",
Expand Down Expand Up @@ -713,6 +716,7 @@
"Threads_displaying_following": "Mostrando seguindo",
"Threads_displaying_unread": "Mostrando não lidos",
"Timezone": "Fuso horário",
"To_continue_using_RocketChat": "Para continuar usando o aplicativo móvel, você precisa alterar sua senha.",
"Token_expired": "Sua sessão expirou. Por favor entre novamente.",
"Topic": "Tópico",
"topic": "tópico",
Expand Down Expand Up @@ -810,6 +814,7 @@
"You_colon": "Você: ",
"You_dont_have_permission_to_perform_this_action": "Você não tem permissão para realizar esta ação. Verifique com um administrador do espaço de trabalho.",
"You_need_to_access_at_least_one_RocketChat_server_to_share_something": "Você precisa acessar pelo menos uma workspace Rocket.Chat para compartilhar.",
"You_need_to_change_your_password": "Você precisa alterar sua senha",
"You_need_to_verifiy_your_email_address_to_get_notications": "Você precisa confirmar seu endereço de e-mail para obter notificações",
"you_were_mentioned": "você foi mencionado",
"You_were_removed_from_channel": "Você foi removido de {{channel}}",
Expand Down
12 changes: 6 additions & 6 deletions app/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -628,12 +628,12 @@
"Uploading": "Загрузка",
"Use": "Использовать",
"User": "Пользователь",
"User__username__is_now_a_leader_of__room_name_": "Пользователь {{username}} больше не лидер в чате {{room_name}}",
"User__username__is_now_a_moderator_of__room_name_": "Пользователь {{username}} больше не модератор в чате {{room_name}}",
"User__username__is_now_a_owner_of__room_name_": "Пользователь {{username}} больше не владелец в чате {{room_name}}",
"User__username__removed_from__room_name__leaders": "Пользователь {{username}} удален из {{room_name}} лидеров",
"User__username__removed_from__room_name__moderators": "Пользователь {{username}} удален из {{room_name}} модераторов",
"User__username__removed_from__room_name__owners": "Пользователь {{username}} удален из {{room_name}} владельцев",
"User__username__is_now_a_leader_of__room_name_": "Пользователь {{username}} теперь лидер в чате {{room_name}}",
"User__username__is_now_a_moderator_of__room_name_": "Пользователь {{username}} теперь модератор в чате {{room_name}}",
"User__username__is_now_a_owner_of__room_name_": "Пользователь {{username}} теперь владелец в чате {{room_name}}",
"User__username__removed_from__room_name__leaders": "Пользователь {{username}} удален из лидеров чата {{room_name}}",
"User__username__removed_from__room_name__moderators": "Пользователь {{username}} удален из модераторов чата {{room_name}}",
"User__username__removed_from__room_name__owners": "Пользователь {{username}} удален из владельцев чата {{room_name}}",
"User_has_been_ignored": "Пользователь теперь игнорируется",
"User_has_been_key": "Пользователь был {{key}}",
"User_has_been_removed_from_s": "Пользователь удален из {{s}}",
Expand Down
Loading