diff --git a/android/app/build.gradle b/android/app/build.gradle
index fe11088a0..54ef907cf 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.33.0"
+ versionName "4.33.1"
vectorDrawables.useSupportLibrary = true
if (!isFoss) {
manifestPlaceholders = [BugsnagAPIKey: BugsnagAPIKey as String]
diff --git a/app/containers/MessageActions/Header.tsx b/app/containers/MessageActions/Header.tsx
index 26d35d4cc..f9c809e5e 100644
--- a/app/containers/MessageActions/Header.tsx
+++ b/app/containers/MessageActions/Header.tsx
@@ -14,12 +14,12 @@ import { IEmoji, TAnyMessageModel } from '../../definitions';
import Touch from '../Touch';
export interface IHeader {
- handleReaction: (emoji: IEmoji, message: TAnyMessageModel) => void;
+ handleReaction: (emoji: IEmoji | null, message: TAnyMessageModel) => void;
message: TAnyMessageModel;
isMasterDetail: boolean;
}
-type TOnReaction = ({ emoji }: { emoji: IEmoji }) => void;
+type TOnReaction = ({ emoji }: { emoji?: IEmoji }) => void;
interface THeaderItem {
item: IEmoji;
@@ -94,8 +94,10 @@ const Header = React.memo(({ handleReaction, message, isMasterDetail }: IHeader)
const quantity = Math.trunc(size / (ITEM_SIZE + ITEM_MARGIN * 2) - 1);
const onReaction: TOnReaction = ({ emoji }) => {
- handleReaction(emoji, message);
- addFrequentlyUsed(emoji);
+ handleReaction(emoji || null, message);
+ if (emoji) {
+ addFrequentlyUsed(emoji);
+ }
};
const renderItem = ({ item }: { item: IEmoji }) => ;
diff --git a/app/containers/MessageActions/index.tsx b/app/containers/MessageActions/index.tsx
index 925d14613..38d77c14e 100644
--- a/app/containers/MessageActions/index.tsx
+++ b/app/containers/MessageActions/index.tsx
@@ -285,10 +285,10 @@ const MessageActions = React.memo(
}
};
- const handleReaction: IHeader['handleReaction'] = (shortname, message) => {
+ const handleReaction: IHeader['handleReaction'] = (emoji, message) => {
logEvent(events.ROOM_MSG_ACTION_REACTION);
- if (shortname) {
- onReactionPress(shortname, message.id);
+ if (emoji) {
+ onReactionPress(emoji, message.id);
} else {
setTimeout(() => reactionInit(message), ACTION_SHEET_ANIMATION_DURATION);
}
diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json
index e62df8189..3fe3ea01b 100644
--- a/app/i18n/locales/en.json
+++ b/app/i18n/locales/en.json
@@ -565,6 +565,8 @@
"Unsupported_system_message": "Unsupported system message",
"Updating": "Updating...",
"Uploading": "Uploading",
+ "FileUpload_Error": "File Upload Error",
+ "Upload_in_progress": "Upload in progress",
"Upload_file_question_mark": "Upload file?",
"User": "User",
"Users": "Users",
diff --git a/app/i18n/locales/pt-BR.json b/app/i18n/locales/pt-BR.json
index 3bb4de322..014d785a1 100644
--- a/app/i18n/locales/pt-BR.json
+++ b/app/i18n/locales/pt-BR.json
@@ -513,6 +513,8 @@
"Unsupported_system_message": "Mensagem de sistema não suportada",
"Updating": "Atualizando...",
"Uploading": "Subindo arquivo",
+ "FileUpload_Error": "Erro de upload de arquivo",
+ "Upload_in_progress": "Carregamento em andamento",
"Upload_file_question_mark": "Enviar arquivo?",
"User": "Usuário",
"Users": "Usuários",
diff --git a/app/lib/methods/sendFileMessage.ts b/app/lib/methods/sendFileMessage.ts
index c8facc473..dbbe6317e 100644
--- a/app/lib/methods/sendFileMessage.ts
+++ b/app/lib/methods/sendFileMessage.ts
@@ -1,27 +1,35 @@
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
import { settings as RocketChatSettings } from '@rocket.chat/sdk';
-import { FetchBlobResponse, StatefulPromise } from 'rn-fetch-blob';
import isEmpty from 'lodash/isEmpty';
+import { FetchBlobResponse, StatefulPromise } from 'rn-fetch-blob';
+import { Alert } from 'react-native';
-import FileUpload from './helpers/fileUpload';
-import database from '../database';
-import log from './helpers/log';
import { IUpload, IUser, TUploadModel } from '../../definitions';
+import i18n from '../../i18n';
+import database from '../database';
+import FileUpload from './helpers/fileUpload';
import { IFileUpload } from './helpers/fileUpload/interfaces';
+import log from './helpers/log';
const uploadQueue: { [index: string]: StatefulPromise } = {};
-export function isUploadActive(path: string): boolean {
- return !!uploadQueue[path];
+const getUploadPath = (path: string, rid: string) => `${path}-${rid}`;
+
+export function isUploadActive(path: string, rid: string): boolean {
+ return !!uploadQueue[getUploadPath(path, rid)];
}
-export async function cancelUpload(item: TUploadModel): Promise {
- if (!isEmpty(uploadQueue[item.path])) {
+export async function cancelUpload(item: TUploadModel, rid: string): Promise {
+ const uploadPath = getUploadPath(item.path, rid);
+ if (!isEmpty(uploadQueue[uploadPath])) {
try {
- await uploadQueue[item.path].cancel();
+ await uploadQueue[uploadPath].cancel();
} catch {
// Do nothing
}
+ delete uploadQueue[uploadPath];
+ }
+ if (item.id) {
try {
const db = database.active;
await db.write(async () => {
@@ -30,7 +38,6 @@ export async function cancelUpload(item: TUploadModel): Promise {
} catch (e) {
log(e);
}
- delete uploadQueue[item.path];
}
}
@@ -51,14 +58,18 @@ export function sendFileMessage(
const db = database.active;
const uploadsCollection = db.get('uploads');
+ const uploadPath = getUploadPath(fileInfo.path, rid);
let uploadRecord: TUploadModel;
try {
- uploadRecord = await uploadsCollection.find(fileInfo.path);
+ uploadRecord = await uploadsCollection.find(uploadPath);
+ if (uploadRecord.id) {
+ return Alert.alert(i18n.t('FileUpload_Error'), i18n.t('Upload_in_progress'));
+ }
} catch (error) {
try {
await db.write(async () => {
uploadRecord = await uploadsCollection.create(u => {
- u._raw = sanitizedRaw({ id: fileInfo.path }, uploadsCollection.schema);
+ u._raw = sanitizedRaw({ id: uploadPath }, uploadsCollection.schema);
Object.assign(u, fileInfo);
if (u.subscription) {
u.subscription.id = rid;
@@ -99,9 +110,9 @@ export function sendFileMessage(
'X-User-Id': id
};
- uploadQueue[fileInfo.path] = FileUpload.fetch('POST', uploadUrl, headers, formData);
+ uploadQueue[uploadPath] = FileUpload.fetch('POST', uploadUrl, headers, formData);
- uploadQueue[fileInfo.path].uploadProgress(async (loaded: number, total: number) => {
+ uploadQueue[uploadPath].uploadProgress(async (loaded: number, total: number) => {
try {
await db.write(async () => {
await uploadRecord.update(u => {
@@ -113,7 +124,7 @@ export function sendFileMessage(
}
});
- uploadQueue[fileInfo.path].then(async response => {
+ uploadQueue[uploadPath].then(async response => {
if (response.respInfo.status >= 200 && response.respInfo.status < 400) {
// If response is all good...
try {
@@ -142,7 +153,7 @@ export function sendFileMessage(
}
});
- uploadQueue[fileInfo.path].catch(async error => {
+ uploadQueue[uploadPath].catch(async error => {
try {
await db.write(async () => {
await uploadRecord.update(u => {
diff --git a/app/views/RoomView/UploadProgress.tsx b/app/views/RoomView/UploadProgress.tsx
index a6791c3e2..2509870c9 100644
--- a/app/views/RoomView/UploadProgress.tsx
+++ b/app/views/RoomView/UploadProgress.tsx
@@ -112,9 +112,10 @@ class UploadProgress extends Component {
this.ranInitialUploadCheck = true;
+ const { rid } = this.props;
const { uploads } = this.state;
uploads.forEach(async u => {
- if (!isUploadActive(u.path)) {
+ if (!isUploadActive(u.path, rid)) {
try {
const db = database.active;
await db.write(async () => {
@@ -141,8 +142,9 @@ class UploadProgress extends Component {
+ const { rid } = this.props;
try {
- await cancelUpload(item);
+ await cancelUpload(item, rid);
} catch (e) {
log(e);
}
@@ -210,7 +212,7 @@ class UploadProgress extends Component {
showReactionPicker = () => {
const { showActionSheet } = this.props;
const { selectedMessage } = this.state;
- showActionSheet({
- children: (
-
- ),
- snaps: [400],
- enableContentPanningGesture: false
- });
+ setTimeout(() => {
+ showActionSheet({
+ children: (
+
+ ),
+ snaps: [400],
+ enableContentPanningGesture: false
+ });
+ }, 100);
};
onReactionInit = (message: TAnyMessageModel) => {
diff --git a/app/views/ThreadMessagesView/index.tsx b/app/views/ThreadMessagesView/index.tsx
index 2aee455b8..2769b3302 100644
--- a/app/views/ThreadMessagesView/index.tsx
+++ b/app/views/ThreadMessagesView/index.tsx
@@ -142,7 +142,7 @@ class ThreadMessagesView extends React.Component (
-
+
)
};
@@ -242,7 +242,7 @@ class ThreadMessagesView extends React.Component ({ messages: [...messages, ...update] }));
return;
}
diff --git a/e2e/tests/assorted/09-joinfromdirectory.spec.ts b/e2e/tests/assorted/09-joinfromdirectory.spec.ts
index ab181b9ed..c9e19efb2 100644
--- a/e2e/tests/assorted/09-joinfromdirectory.spec.ts
+++ b/e2e/tests/assorted/09-joinfromdirectory.spec.ts
@@ -1,5 +1,6 @@
import data from '../../data';
import { navigateToLogin, login, tapBack, sleep } from '../../helpers/app';
+import { sendMessage } from '../../helpers/data_setup';
const testuser = data.users.regular;
@@ -26,6 +27,13 @@ describe('Join room from directory', () => {
});
describe('Usage', () => {
+ const threadMessage = `thread-${data.random}`;
+ before(async () => {
+ const result = await sendMessage(data.users.alternate, data.channels.detoxpublic.name, threadMessage);
+ const threadId = result.message._id;
+ await sendMessage(data.users.alternate, result.message.rid, data.random, threadId);
+ });
+
it('should tap directory', async () => {
await element(by.id('rooms-list-view-directory')).tap();
await waitFor(element(by.id('directory-view')))
@@ -37,6 +45,20 @@ describe('Join room from directory', () => {
await navigateToRoom(data.channels.detoxpublic.name);
});
+ it('should navigate to thread messages view and load messages', async () => {
+ await waitFor(element(by.id('room-view-header-threads')))
+ .toBeVisible()
+ .withTimeout(2000);
+ await element(by.id('room-view-header-threads')).tap();
+ await waitFor(element(by.id(`thread-messages-view-${threadMessage}`)))
+ .toBeVisible()
+ .withTimeout(2000);
+ await tapBack();
+ await waitFor(element(by.id('room-view-header-threads')))
+ .toBeVisible()
+ .withTimeout(2000);
+ });
+
it('should search user and navigate', async () => {
await tapBack();
await element(by.id('rooms-list-view-directory')).tap();
diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj
index 1ea9c760d..0ec07074b 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.33.0;
+ MARKETING_VERSION = 4.33.1;
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.33.0;
+ MARKETING_VERSION = 4.33.1;
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 53af2cee5..f2923f6f0 100644
--- a/ios/RocketChatRN/Info.plist
+++ b/ios/RocketChatRN/Info.plist
@@ -26,7 +26,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 4.33.0
+ 4.33.1
CFBundleSignature
????
CFBundleURLTypes
diff --git a/ios/ShareRocketChatRN/Info.plist b/ios/ShareRocketChatRN/Info.plist
index 27a4c4b3a..95f67d724 100644
--- a/ios/ShareRocketChatRN/Info.plist
+++ b/ios/ShareRocketChatRN/Info.plist
@@ -26,7 +26,7 @@
CFBundlePackageType
XPC!
CFBundleShortVersionString
- 4.33.0
+ 4.33.1
CFBundleVersion
1
KeychainGroup
diff --git a/package.json b/package.json
index 04b433fc5..7df1d31bf 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "rocket-chat-reactnative",
- "version": "4.33.0",
+ "version": "4.33.1",
"private": true,
"scripts": {
"start": "react-native start",
diff --git a/yarn.lock b/yarn.lock
index bc9ac843c..4f3e5d74e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -17379,7 +17379,7 @@ react-native-text-size@4.0.0-rc.1:
react-native-ui-lib@RocketChat/react-native-ui-lib:
version "4.2.0"
- resolved "https://codeload.github.com/RocketChat/react-native-ui-lib/tar.gz/d20c1bcd09b694fc5133fc2232fd510f5f4ba581"
+ resolved "https://codeload.github.com/RocketChat/react-native-ui-lib/tar.gz/fd5869e493b5b9cf888cec4a252c9ef292364b02"
dependencies:
babel-plugin-transform-inline-environment-variables "^0.0.2"
color "^3.1.0"