From 531f3d014708242b23a65aef2ec52a135a40e189 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto <47038980+reinaldonetof@users.noreply.github.com> Date: Thu, 13 Oct 2022 18:29:55 -0300 Subject: [PATCH 01/10] [IMPROVE] Add ignore user to user profile (#4600) * button ignore and pased the param * load room from database and check is is ignored * move handleIgnore to lib/method/helpers * Ignore and Unignore, also reactivity * block and unblock user * pass fromRid from actionView to InfoView too * remove console.log * unsubscribe subscriptionFrom * block and unblock user from dm * test to block user and ignore user * minor tweak * tweak data * minor tweak * add test before tapBack * refactor names --- app/lib/methods/helpers/handleIgnore.ts | 19 +++++ app/lib/methods/helpers/log/events.ts | 1 + app/stacks/types.ts | 1 + app/views/RoomActionsView/index.tsx | 3 +- app/views/RoomInfoView/index.tsx | 107 +++++++++++++++++++----- app/views/RoomMembersView/helpers.ts | 14 ---- app/views/RoomMembersView/index.tsx | 4 +- app/views/RoomView/index.tsx | 3 + e2e/data.ts | 3 + e2e/tests/room/10-ignoreuser.spec.ts | 103 +++++++++++++++++++++++ 10 files changed, 220 insertions(+), 38 deletions(-) create mode 100644 app/lib/methods/helpers/handleIgnore.ts create mode 100644 e2e/tests/room/10-ignoreuser.spec.ts diff --git a/app/lib/methods/helpers/handleIgnore.ts b/app/lib/methods/helpers/handleIgnore.ts new file mode 100644 index 000000000..70a713308 --- /dev/null +++ b/app/lib/methods/helpers/handleIgnore.ts @@ -0,0 +1,19 @@ +import { LISTENER } from '../../../containers/Toast'; +import I18n from '../../../i18n'; +import EventEmitter from './events'; +import log from './log'; +import { Services } from '../../services'; + +export const handleIgnore = async (userId: string, ignore: boolean, rid: string) => { + try { + await Services.ignoreUser({ + rid, + userId, + ignore + }); + const message = I18n.t(ignore ? 'User_has_been_ignored' : 'User_has_been_unignored'); + EventEmitter.emit(LISTENER, { message }); + } catch (e) { + log(e); + } +}; diff --git a/app/lib/methods/helpers/log/events.ts b/app/lib/methods/helpers/log/events.ts index b4562b6c5..f280a2b1c 100644 --- a/app/lib/methods/helpers/log/events.ts +++ b/app/lib/methods/helpers/log/events.ts @@ -280,6 +280,7 @@ export default { RI_GO_RI_EDIT: 'ri_go_ri_edit', RI_GO_LIVECHAT_EDIT: 'ri_go_livechat_edit', RI_GO_ROOM_USER: 'ri_go_room_user', + RI_TOGGLE_BLOCK_USER: 'ri_toggle_block_user', // ROOM INFO EDIT VIEW RI_EDIT_TOGGLE_ROOM_TYPE: 'ri_edit_toggle_room_type', diff --git a/app/stacks/types.ts b/app/stacks/types.ts index dab02f251..d83f7f2c8 100644 --- a/app/stacks/types.ts +++ b/app/stacks/types.ts @@ -68,6 +68,7 @@ export type ChatsStackParamList = { rid: string; t: SubscriptionType; showCloseModal?: boolean; + fromRid?: string; }; RoomInfoEditView: { rid: string; diff --git a/app/views/RoomActionsView/index.tsx b/app/views/RoomActionsView/index.tsx index e2d911dbb..9c3a4eaaa 100644 --- a/app/views/RoomActionsView/index.tsx +++ b/app/views/RoomActionsView/index.tsx @@ -760,7 +760,8 @@ class RoomActionsView extends React.Component { @@ -121,22 +124,29 @@ class RoomInfoView extends React.Component; + private fromRid?: string; + + private subscriptionRoomFromRid?: Subscription; + constructor(props: IRoomInfoViewProps) { super(props); const room = props.route.params?.room; const roomUser = props.route.params?.member; this.rid = props.route.params?.rid; this.t = props.route.params?.t; + this.fromRid = props.route.params?.fromRid; this.state = { room: (room || { rid: this.rid, t: this.t }) as any, roomUser: roomUser || {}, - showEdit: false + showEdit: false, + roomFromRid: undefined }; } componentDidMount() { if (this.isDirect) { this.loadUser(); + this.loadRoomFromRid(); } else { this.loadRoom(); } @@ -154,6 +164,9 @@ class RoomInfoView extends React.Component { + if (this.fromRid) { + try { + const sub = await getSubscriptionByRoomId(this.fromRid); + this.subscriptionRoomFromRid = sub?.observe().subscribe(roomFromRid => { + this.setState({ roomFromRid }); + }); + } catch (e) { + // do nothing + } + } + }; + loadRoom = async () => { const { room: roomState } = this.state; const { route, editRoomPermission, editOmnichannelContact, editLivechatRoomCustomfields } = this.props; @@ -351,11 +377,32 @@ class RoomInfoView extends React.Component void) => { + try { + if (this.isDirect) { + await this.createDirect(); + } + onPress(); + } catch { + EventEmitter.emit(LISTENER, { + message: I18n.t('error-action-not-allowed', { action: I18n.t('Create_Direct_Messages') }) + }); + } + }; + videoCall = () => { const { room } = this.state; callJitsi(room); }; + handleBlockUser = async (rid: string, blocked: string, block: boolean) => { + logEvent(events.RI_TOGGLE_BLOCK_USER); + try { + await Services.toggleBlockUser(rid, blocked, block); + } catch (e) { + log(e); + } + }; renderAvatar = (room: ISubscription, roomUser: IUserParsed) => { const { theme } = this.props; @@ -370,36 +417,54 @@ class RoomInfoView extends React.Component void, iconName: TIconsName, text: string) => { + renderButton = (onPress: () => void, iconName: TIconsName, text: string, danger?: boolean) => { const { theme } = this.props; - - const onActionPress = async () => { - try { - if (this.isDirect) { - await this.createDirect(); - } - onPress(); - } catch { - EventEmitter.emit(LISTENER, { - message: I18n.t('error-action-not-allowed', { action: I18n.t('Create_Direct_Messages') }) - }); - } - }; - + const color = danger ? themes[theme].dangerColor : themes[theme].actionTintColor; return ( - - - {text} + + + {text} ); }; renderButtons = () => { + const { roomFromRid, roomUser } = this.state; const { jitsiEnabled } = this.props; + + const isFromDm = roomFromRid?.rid ? new RegExp(roomUser._id).test(roomFromRid.rid) : false; + const isDirectFromSaved = this.isDirect && this.fromRid && roomFromRid; + + // Following the web behavior, when is a DM with myself, shouldn't appear block or ignore option + const isDmWithMyself = roomFromRid?.uids && roomFromRid.uids?.filter(uid => uid !== roomUser._id).length === 0; + + const ignored = roomFromRid?.ignored; + const isIgnored = ignored?.includes?.(roomUser._id); + + const blocker = roomFromRid?.blocker; + return ( - {this.renderButton(this.goRoom, 'message', I18n.t('Message'))} - {jitsiEnabled && this.isDirect ? this.renderButton(this.videoCall, 'camera', I18n.t('Video_call')) : null} + {this.renderButton(() => this.handleCreateDirectMessage(this.goRoom), 'message', I18n.t('Message'))} + {jitsiEnabled && this.isDirect + ? this.renderButton(() => this.handleCreateDirectMessage(this.videoCall), 'camera', I18n.t('Video_call')) + : null} + {isDirectFromSaved && !isFromDm && !isDmWithMyself + ? this.renderButton( + () => handleIgnore(roomUser._id, !isIgnored, roomFromRid.rid), + 'ignore', + I18n.t(isIgnored ? 'Unignore' : 'Ignore'), + true + ) + : null} + {isDirectFromSaved && isFromDm + ? this.renderButton( + () => this.handleBlockUser(roomFromRid.rid, roomUser._id, !blocker), + 'ignore', + I18n.t(`${blocker ? 'Unblock' : 'Block'}_user`), + true + ) + : null} ); }; diff --git a/app/views/RoomMembersView/helpers.ts b/app/views/RoomMembersView/helpers.ts index 696de2c56..ff622dbf4 100644 --- a/app/views/RoomMembersView/helpers.ts +++ b/app/views/RoomMembersView/helpers.ts @@ -217,20 +217,6 @@ export const handleRemoveUserFromRoom = async ( } }; -export const handleIgnore = async (selectedUser: TUserModel, ignore: boolean, rid: string) => { - try { - await Services.ignoreUser({ - rid, - userId: selectedUser._id, - ignore - }); - const message = I18n.t(ignore ? 'User_has_been_ignored' : 'User_has_been_unignored'); - EventEmitter.emit(LISTENER, { message }); - } catch (e) { - log(e); - } -}; - export const handleOwner = async ( selectedUser: TUserModel, isOwner: boolean, diff --git a/app/views/RoomMembersView/index.tsx b/app/views/RoomMembersView/index.tsx index 80d4a337a..99f20d35c 100644 --- a/app/views/RoomMembersView/index.tsx +++ b/app/views/RoomMembersView/index.tsx @@ -16,6 +16,7 @@ import { TSubscriptionModel, TUserModel } from '../../definitions'; import I18n from '../../i18n'; import { useAppSelector, usePermissions } from '../../lib/hooks'; import { getRoomTitle, isGroupChat } from '../../lib/methods/helpers'; +import { handleIgnore } from '../../lib/methods/helpers/handleIgnore'; import { showConfirmationAlert } from '../../lib/methods/helpers/info'; import log from '../../lib/methods/helpers/log'; import scrollPersistTaps from '../../lib/methods/helpers/scrollPersistTaps'; @@ -28,7 +29,6 @@ import ActionsSection from './components/ActionsSection'; import { fetchRole, fetchRoomMembersRoles, - handleIgnore, handleLeader, handleModerator, handleMute, @@ -207,7 +207,7 @@ const RoomMembersView = (): React.ReactElement => { options.push({ icon: 'ignore', title: I18n.t(isIgnored ? 'Unignore' : 'Ignore'), - onPress: () => handleIgnore(selectedUser, !isIgnored, room.rid), + onPress: () => handleIgnore(selectedUser._id, !isIgnored, room.rid), testID: 'action-sheet-ignore-user' }); } diff --git a/app/views/RoomView/index.tsx b/app/views/RoomView/index.tsx index 4b76660a2..03786b4c3 100644 --- a/app/views/RoomView/index.tsx +++ b/app/views/RoomView/index.tsx @@ -1109,10 +1109,13 @@ class RoomView extends React.Component { navToRoomInfo = (navParam: any) => { const { navigation, user, isMasterDetail } = this.props; + const { room } = this.state; + logEvent(events[`ROOM_GO_${navParam.t === 'd' ? 'USER' : 'ROOM'}_INFO`]); if (navParam.rid === user.id) { return; } + navParam.fromRid = room.rid; if (isMasterDetail) { navParam.showCloseModal = true; // @ts-ignore diff --git a/e2e/data.ts b/e2e/data.ts index 5947a86d9..63bb8c0c3 100644 --- a/e2e/data.ts +++ b/e2e/data.ts @@ -51,6 +51,9 @@ const data = { detoxpublicprotected: { name: 'detox-public-protected', joinCode: '123' + }, + detoxpublicignore: { + name: `detox-public-ignore-${value}` } }, groups: { diff --git a/e2e/tests/room/10-ignoreuser.spec.ts b/e2e/tests/room/10-ignoreuser.spec.ts new file mode 100644 index 000000000..9f057253a --- /dev/null +++ b/e2e/tests/room/10-ignoreuser.spec.ts @@ -0,0 +1,103 @@ +import { expect } from 'detox'; + +import data from '../../data'; +import { navigateToLogin, login, searchRoom, sleep, platformTypes, TTextMatcher, tapBack } from '../../helpers/app'; +import { sendMessage } from '../../helpers/data_setup'; + +async function navigateToRoom(user: string) { + await searchRoom(`${user}`); + await element(by.id(`rooms-list-view-item-${user}`)).tap(); + await waitFor(element(by.id('room-view'))) + .toBeVisible() + .withTimeout(5000); +} + +async function navigateToInfoView() { + await element(by.id('room-header')).tap(); + await waitFor(element(by.id('room-actions-view'))) + .toExist() + .withTimeout(5000); + await element(by.id('room-actions-info')).tap(); + await waitFor(element(by.id('room-info-view'))) + .toExist() + .withTimeout(2000); +} + +describe('Ignore/Block User', () => { + const user = data.users.alternate.username; + let textMatcher: TTextMatcher; + + before(async () => { + await device.launchApp({ permissions: { notifications: 'YES' }, delete: true }); + ({ textMatcher } = platformTypes[device.getPlatform()]); + await navigateToLogin(); + await login(data.users.regular.username, data.users.regular.password); + }); + + describe('Usage', () => { + describe('Block user from DM', () => { + it('should go to user info view', async () => { + await navigateToRoom(user); + await navigateToInfoView(); + }); + it('should block user', async () => { + await expect(element(by.id('room-info-view-ignore').withDescendant(by[textMatcher]('Block user')))).toExist(); + await element(by.id('room-info-view-ignore')).tap(); + await waitFor(element(by.id('room-info-view-ignore').withDescendant(by[textMatcher]('Unblock user')))) + .toExist() + .withTimeout(2000); + await tapBack(); + await waitFor(element(by.id('room-actions-view'))) + .toBeVisible() + .withTimeout(5000); + await tapBack(); + await expect(element(by[textMatcher]('This room is blocked'))).toExist(); + }); + + it('should unblock user', async () => { + await navigateToInfoView(); + await element(by.id('room-info-view-ignore')).tap(); + await expect(element(by.id('room-info-view-ignore').withDescendant(by[textMatcher]('Block user')))).toExist(); + await tapBack(); + await waitFor(element(by.id('room-actions-view'))) + .toBeVisible() + .withTimeout(5000); + await tapBack(); + await expect(element(by.id('messagebox'))).toBeVisible(); + await tapBack(); + }); + }); + describe('Ignore user from Message', () => { + it('should ignore user from message', async () => { + const channelName = data.channels.detoxpublicignore.name; + await navigateToRoom(channelName); + await element(by.id('room-view-join-button')).tap(); + await sleep(300); + await sendMessage(data.users.alternate, channelName, 'message-01'); + await sendMessage(data.users.alternate, channelName, 'message-02'); + await waitFor(element(by[textMatcher](user)).atIndex(0)) + .toExist() + .withTimeout(30000); + await sleep(300); + await element(by[textMatcher](user)).atIndex(0).tap(); + await expect(element(by.id('room-info-view-ignore').withDescendant(by[textMatcher]('Ignore')))).toExist(); + await element(by.id('room-info-view-ignore')).tap(); + await expect(element(by.id('room-info-view-ignore').withDescendant(by[textMatcher]('Unignore')))).toExist(); + await tapBack(); + }); + it('should tap to display message', async () => { + await expect(element(by[textMatcher]('Message ignored. Tap to display it.')).atIndex(0)).toExist(); + await element(by[textMatcher]('Message ignored. Tap to display it.')).atIndex(0).tap(); + await waitFor(element(by[textMatcher](user))) + .toBeVisible() + .withTimeout(1000); + await element(by[textMatcher](user)).atIndex(0).tap(); + await expect(element(by.id('room-info-view-ignore').withDescendant(by[textMatcher]('Unignore')))).toExist(); + await element(by.id('room-info-view-ignore')).tap(); + await expect(element(by.id('room-info-view-ignore').withDescendant(by[textMatcher]('Ignore')))).toExist(); + await tapBack(); + await expect(element(by[textMatcher]('message-02')).atIndex(0)).toBeVisible(); + }); + }); + }); +}); From ef753086a98e49ece663c772a19473ede140fa45 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Mon, 17 Oct 2022 15:54:51 -0300 Subject: [PATCH 02/10] Bump version to 4.33.0 (#4615) --- android/app/build.gradle | 2 +- ios/RocketChatRN.xcodeproj/project.pbxproj | 4 ++-- ios/RocketChatRN/Info.plist | 2 +- ios/ShareRocketChatRN/Info.plist | 2 +- package.json | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index cfb08e8fa..493b9874d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -147,7 +147,7 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode VERSIONCODE as Integer - versionName "4.32.0" + versionName "4.33.0" vectorDrawables.useSupportLibrary = true if (!isFoss) { manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String] diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj index 543343529..ec33386cb 100644 --- a/ios/RocketChatRN.xcodeproj/project.pbxproj +++ b/ios/RocketChatRN.xcodeproj/project.pbxproj @@ -1767,7 +1767,7 @@ INFOPLIST_FILE = NotificationService/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; - MARKETING_VERSION = 4.32.0; + MARKETING_VERSION = 4.33.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; @@ -1806,7 +1806,7 @@ INFOPLIST_FILE = NotificationService/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; - MARKETING_VERSION = 4.32.0; + MARKETING_VERSION = 4.33.0; MTL_FAST_MATH = YES; OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = chat.rocket.reactnative.NotificationService; diff --git a/ios/RocketChatRN/Info.plist b/ios/RocketChatRN/Info.plist index a47c0f151..53af2cee5 100644 --- a/ios/RocketChatRN/Info.plist +++ b/ios/RocketChatRN/Info.plist @@ -26,7 +26,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 4.32.0 + 4.33.0 CFBundleSignature ???? CFBundleURLTypes diff --git a/ios/ShareRocketChatRN/Info.plist b/ios/ShareRocketChatRN/Info.plist index af4a45c9d..27a4c4b3a 100644 --- a/ios/ShareRocketChatRN/Info.plist +++ b/ios/ShareRocketChatRN/Info.plist @@ -26,7 +26,7 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 4.32.0 + 4.33.0 CFBundleVersion 1 KeychainGroup diff --git a/package.json b/package.json index 7f1426cde..491965054 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rocket-chat-reactnative", - "version": "4.32.0", + "version": "4.33.0", "private": true, "scripts": { "start": "react-native start", From 6dd95784130d90409809c33a7b6de91d5f14d863 Mon Sep 17 00:00:00 2001 From: Luciano Marcos Pierdona Junior <64279791+LucianoPierdona@users.noreply.github.com> Date: Tue, 18 Oct 2022 08:39:06 -0300 Subject: [PATCH 03/10] [FIX] Team creation not adding members (#4588) Co-authored-by: Gleidson Daniel Silva --- app/definitions/rest/v1/teams.ts | 2 +- app/lib/services/restApi.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/definitions/rest/v1/teams.ts b/app/definitions/rest/v1/teams.ts index e282e630f..89b4e330a 100644 --- a/app/definitions/rest/v1/teams.ts +++ b/app/definitions/rest/v1/teams.ts @@ -24,7 +24,7 @@ export type TeamsEndpoints = { 'teams.create': { POST: (params: { name: string; - users: string[]; + members: string[]; type: TEAM_TYPE; room: { readOnly: boolean; extraData: { broadcast: boolean; encrypted: boolean } }; }) => { team: ITeam }; diff --git a/app/lib/services/restApi.ts b/app/lib/services/restApi.ts index 045318059..54f169ebf 100644 --- a/app/lib/services/restApi.ts +++ b/app/lib/services/restApi.ts @@ -160,7 +160,7 @@ export const createTeam = ({ }) => { const params = { name, - users, + members: users, type: type ? TEAM_TYPE.PRIVATE : TEAM_TYPE.PUBLIC, room: { readOnly, From 525f84885a60d7d07ca34a93581c7d79472b298e Mon Sep 17 00:00:00 2001 From: Gleidson Daniel Silva Date: Tue, 18 Oct 2022 15:25:15 -0300 Subject: [PATCH 04/10] remove wrong logic on badge prop (#4564) Co-authored-by: Reinaldo Neto <47038980+reinaldonetof@users.noreply.github.com> --- .../message/Components/RightIcons/ReadReceipt.tsx | 2 +- app/containers/message/Components/RightIcons/index.tsx | 6 +++--- app/containers/message/Message.tsx | 4 ++-- app/containers/message/User.tsx | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/containers/message/Components/RightIcons/ReadReceipt.tsx b/app/containers/message/Components/RightIcons/ReadReceipt.tsx index 3a361bf7b..e7b8f87b5 100644 --- a/app/containers/message/Components/RightIcons/ReadReceipt.tsx +++ b/app/containers/message/Components/RightIcons/ReadReceipt.tsx @@ -5,7 +5,7 @@ import { CustomIcon } from '../../../CustomIcon'; import styles from '../../styles'; import { useTheme } from '../../../../theme'; -const ReadReceipt = React.memo(({ isReadReceiptEnabled, unread }: { isReadReceiptEnabled?: boolean; unread: boolean }) => { +const ReadReceipt = React.memo(({ isReadReceiptEnabled, unread }: { isReadReceiptEnabled?: boolean; unread?: boolean }) => { const { theme } = useTheme(); if (isReadReceiptEnabled && !unread && unread !== null) { return ; diff --git a/app/containers/message/Components/RightIcons/index.tsx b/app/containers/message/Components/RightIcons/index.tsx index d2e1f5158..fb96aaaf5 100644 --- a/app/containers/message/Components/RightIcons/index.tsx +++ b/app/containers/message/Components/RightIcons/index.tsx @@ -17,8 +17,8 @@ interface IRightIcons { type: MessageType; msg?: string; isEdited: boolean; - isReadReceiptEnabled: boolean; - unread: boolean; + isReadReceiptEnabled?: boolean; + unread?: boolean; hasError: boolean; } @@ -27,7 +27,7 @@ const RightIcons = ({ type, msg, isEdited, hasError, isReadReceiptEnabled, unrea - + ); diff --git a/app/containers/message/Message.tsx b/app/containers/message/Message.tsx index 8b6906507..d6c706cbf 100644 --- a/app/containers/message/Message.tsx +++ b/app/containers/message/Message.tsx @@ -97,8 +97,8 @@ const Message = React.memo((props: IMessage) => { msg={props.msg} isEdited={props.isEdited} hasError={props.hasError} - isReadReceiptEnabled={props.isReadReceiptEnabled || false} - unread={props.unread || false} + isReadReceiptEnabled={props.isReadReceiptEnabled} + unread={props.unread} /> ) : null} diff --git a/app/containers/message/User.tsx b/app/containers/message/User.tsx index 2d908ac7c..2ecf99611 100644 --- a/app/containers/message/User.tsx +++ b/app/containers/message/User.tsx @@ -114,8 +114,8 @@ const User = React.memo( type={type} isEdited={isEdited} hasError={hasError} - isReadReceiptEnabled={props.isReadReceiptEnabled || false} - unread={props.unread || false} + isReadReceiptEnabled={props.isReadReceiptEnabled} + unread={props.unread} /> ); From 761aef2c045246c52a07c0048f803441146ae188 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto <47038980+reinaldonetof@users.noreply.github.com> Date: Tue, 18 Oct 2022 16:26:49 -0300 Subject: [PATCH 05/10] [FIX] Screen Lock's Password screen UI is broken on tablets (#4583) * [FIX] Screen Lock's Password screen UI is broken on tablets * minor tweak and added comment * minor tweak * minor tweak * minor tweak --- app/containers/Passcode/Base/Button.tsx | 7 +-- app/containers/Passcode/Base/index.tsx | 57 +++++++++++++++++-------- app/containers/Passcode/Base/styles.ts | 7 +-- 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/app/containers/Passcode/Base/Button.tsx b/app/containers/Passcode/Base/Button.tsx index b768fb50c..28e9a7234 100644 --- a/app/containers/Passcode/Base/Button.tsx +++ b/app/containers/Passcode/Base/Button.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Text } from 'react-native'; +import { Text, StyleProp, ViewStyle } from 'react-native'; import styles from './styles'; import { themes } from '../../../lib/constants'; @@ -12,16 +12,17 @@ interface IPasscodeButton { icon?: TIconsName; disabled?: boolean; onPress?: Function; + style?: StyleProp; } -const Button = React.memo(({ text, disabled, onPress, icon }: IPasscodeButton) => { +const Button = React.memo(({ style, text, disabled, onPress, icon }: IPasscodeButton) => { const { theme } = useTheme(); const press = () => onPress && onPress(text); return ( ( ({ type, onEndProcess, previousPasscode, title, subtitle, onError, showBiometry, onBiometryPress }, ref) => { + useLayoutEffect(() => { + if (!isTablet) { + Orientation.lockToPortrait(); + } + + return () => { + if (!isTablet) { + Orientation.unlockAllOrientations(); + } + }; + }, []); + const { theme } = useTheme(); + const { height } = useDimensions(); + + // 206 is the height of the header calculating the margins, icon size height, title font size and subtitle height. + // 56 is a fixed number to decrease the height of button numbers. + const dinamicHeight = (height - 206 - 56) / 4; + const heightButtonRow = { height: dinamicHeight > 102 ? 102 : dinamicHeight }; const rootRef = useRef(null); const dotsRef = useRef(null); @@ -103,40 +124,40 @@ const Base = forwardRef( - + {range(1, 4).map(i => ( - -