Merge 4.33.1 into master (#4737)
This commit is contained in:
commit
fa2c7f97e6
|
@ -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]
|
||||
|
|
|
@ -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);
|
||||
handleReaction(emoji || null, message);
|
||||
if (emoji) {
|
||||
addFrequentlyUsed(emoji);
|
||||
}
|
||||
};
|
||||
|
||||
const renderItem = ({ item }: { item: IEmoji }) => <HeaderItem item={item} onReaction={onReaction} theme={theme} />;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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<FetchBlobResponse> } = {};
|
||||
|
||||
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<void> {
|
||||
if (!isEmpty(uploadQueue[item.path])) {
|
||||
export async function cancelUpload(item: TUploadModel, rid: string): Promise<void> {
|
||||
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<void> {
|
|||
} 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 => {
|
||||
|
|
|
@ -112,9 +112,10 @@ class UploadProgress extends Component<IUploadProgressProps, IUploadProgressStat
|
|||
|
||||
uploadCheck = () => {
|
||||
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<IUploadProgressProps, IUploadProgressStat
|
|||
};
|
||||
|
||||
handleCancelUpload = async (item: TUploadModel) => {
|
||||
const { rid } = this.props;
|
||||
try {
|
||||
await cancelUpload(item);
|
||||
await cancelUpload(item, rid);
|
||||
} catch (e) {
|
||||
log(e);
|
||||
}
|
||||
|
@ -210,7 +212,7 @@ class UploadProgress extends Component<IUploadProgressProps, IUploadProgressStat
|
|||
key={item.path}
|
||||
style={[
|
||||
styles.item,
|
||||
index !== 0 ? { marginTop: 10 } : {},
|
||||
index !== 0 ? { marginTop: 4 } : {},
|
||||
{
|
||||
backgroundColor: themes[theme!].chatComponentBackground,
|
||||
borderColor: themes[theme!].borderColor
|
||||
|
|
|
@ -833,6 +833,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
showReactionPicker = () => {
|
||||
const { showActionSheet } = this.props;
|
||||
const { selectedMessage } = this.state;
|
||||
setTimeout(() => {
|
||||
showActionSheet({
|
||||
children: (
|
||||
<ReactionPicker message={selectedMessage} onEmojiSelected={this.onReactionPress} reactionClose={this.onReactionClose} />
|
||||
|
@ -840,6 +841,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
|
|||
snaps: [400],
|
||||
enableContentPanningGesture: false
|
||||
});
|
||||
}, 100);
|
||||
};
|
||||
|
||||
onReactionInit = (message: TAnyMessageModel) => {
|
||||
|
|
|
@ -142,7 +142,7 @@ class ThreadMessagesView extends React.Component<IThreadMessagesViewProps, IThre
|
|||
),
|
||||
headerRight: () => (
|
||||
<HeaderButton.Container>
|
||||
<HeaderButton.Item iconName='search' onPress={this.onSearchPress} />
|
||||
<HeaderButton.Item iconName='search' onPress={this.onSearchPress} testID='thread-messages-view-search-icon' />
|
||||
</HeaderButton.Container>
|
||||
)
|
||||
};
|
||||
|
@ -242,7 +242,7 @@ class ThreadMessagesView extends React.Component<IThreadMessagesViewProps, IThre
|
|||
const { subscription } = this.state;
|
||||
// if there's no subscription, manage data on this.state.messages
|
||||
// note: sync will never be called without subscription
|
||||
if (!subscription) {
|
||||
if (!subscription._id) {
|
||||
this.setState(({ messages }) => ({ messages: [...messages, ...update] }));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.33.0</string>
|
||||
<string>4.33.1</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.33.0</string>
|
||||
<string>4.33.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>KeychainGroup</key>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "rocket-chat-reactnative",
|
||||
"version": "4.33.0",
|
||||
"version": "4.33.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "react-native start",
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue