feat: add `readThreads` params to `subscriptions.read` (#5184)
* add readThreads params to subscriptions.read * add tunread verification * fix e2e test * search cat message * fix when grouping by unread * increase timeout --------- Co-authored-by: Reinaldo Neto <reinaldonetof@hotmail.com> Co-authored-by: Reinaldo Neto <47038980+reinaldonetof@users.noreply.github.com>
This commit is contained in:
parent
780f426031
commit
c31cb9b124
|
@ -3,6 +3,6 @@ export type SubscriptionsEndpoints = {
|
||||||
POST: (params: { firstUnreadMessage: { _id: string } } | { roomId: string }) => {};
|
POST: (params: { firstUnreadMessage: { _id: string } } | { roomId: string }) => {};
|
||||||
};
|
};
|
||||||
'subscriptions.read': {
|
'subscriptions.read': {
|
||||||
POST: (params: { rid: string }) => {};
|
POST: (params: { rid: string; readThreads?: boolean }) => {};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -254,6 +254,8 @@ const debouncedUpdate = (subscription: ISubscription) => {
|
||||||
if (batch[key]) {
|
if (batch[key]) {
|
||||||
if (/SUB/.test(key)) {
|
if (/SUB/.test(key)) {
|
||||||
const sub = batch[key] as ISubscription;
|
const sub = batch[key] as ISubscription;
|
||||||
|
// When calling the api subscriptions.read passing readThreads as true it does not return this prop
|
||||||
|
if (!sub.tunread) sub.tunread = [];
|
||||||
const roomQueueId = getRoomQueueId(sub.rid);
|
const roomQueueId = getRoomQueueId(sub.rid);
|
||||||
const room = batch[roomQueueId] as IRoom;
|
const room = batch[roomQueueId] as IRoom;
|
||||||
delete batch[roomQueueId];
|
delete batch[roomQueueId];
|
||||||
|
|
|
@ -1,26 +1,28 @@
|
||||||
import {
|
import {
|
||||||
|
IAvatarSuggestion,
|
||||||
IMessage,
|
IMessage,
|
||||||
INotificationPreferences,
|
INotificationPreferences,
|
||||||
IPreviewItem,
|
IPreviewItem,
|
||||||
|
IProfileParams,
|
||||||
IRoom,
|
IRoom,
|
||||||
IRoomNotifications,
|
IRoomNotifications,
|
||||||
SubscriptionType,
|
IServerRoom,
|
||||||
IUser,
|
IUser,
|
||||||
IAvatarSuggestion,
|
|
||||||
IProfileParams,
|
|
||||||
RoomType,
|
RoomType,
|
||||||
IServerRoom
|
SubscriptionType
|
||||||
} from '../../definitions';
|
} from '../../definitions';
|
||||||
|
import { TParams } from '../../definitions/ILivechatEditView';
|
||||||
|
import { ILivechatTag } from '../../definitions/ILivechatTag';
|
||||||
import { ISpotlight } from '../../definitions/ISpotlight';
|
import { ISpotlight } from '../../definitions/ISpotlight';
|
||||||
import { TEAM_TYPE } from '../../definitions/ITeam';
|
import { TEAM_TYPE } from '../../definitions/ITeam';
|
||||||
|
import { OperationParams, ResultFor } from '../../definitions/rest/helpers';
|
||||||
|
import { SubscriptionsEndpoints } from '../../definitions/rest/v1/subscriptions';
|
||||||
import { Encryption } from '../encryption';
|
import { Encryption } from '../encryption';
|
||||||
import { TParams } from '../../definitions/ILivechatEditView';
|
|
||||||
import { store as reduxStore } from '../store/auxStore';
|
|
||||||
import { getDeviceToken } from '../notifications';
|
|
||||||
import { RoomTypes, roomTypeToApiType, unsubscribeRooms } from '../methods';
|
import { RoomTypes, roomTypeToApiType, unsubscribeRooms } from '../methods';
|
||||||
import sdk from './sdk';
|
|
||||||
import { compareServerVersion, getBundleId, isIOS } from '../methods/helpers';
|
import { compareServerVersion, getBundleId, isIOS } from '../methods/helpers';
|
||||||
import { ILivechatTag } from '../../definitions/ILivechatTag';
|
import { getDeviceToken } from '../notifications';
|
||||||
|
import { store as reduxStore } from '../store/auxStore';
|
||||||
|
import sdk from './sdk';
|
||||||
|
|
||||||
export const createChannel = ({
|
export const createChannel = ({
|
||||||
name,
|
name,
|
||||||
|
@ -310,11 +312,33 @@ export const setReaction = (emoji: string, messageId: string) =>
|
||||||
// RC 0.62.2
|
// RC 0.62.2
|
||||||
sdk.post('chat.react', { emoji, messageId });
|
sdk.post('chat.react', { emoji, messageId });
|
||||||
|
|
||||||
export const toggleRead = (read: boolean, roomId: string) => {
|
/**
|
||||||
if (read) {
|
* Toggles the read status of a room.
|
||||||
return sdk.post('subscriptions.unread', { roomId });
|
*
|
||||||
|
* @param isRead - Whether to mark the room as read or unread.
|
||||||
|
* @param roomId - The ID of the room.
|
||||||
|
* @param includeThreads - Optional flag to include threads when marking as read.
|
||||||
|
* @returns A promise from the sdk post method.
|
||||||
|
*/
|
||||||
|
export const toggleReadStatus = (
|
||||||
|
isRead: boolean,
|
||||||
|
roomId: string,
|
||||||
|
includeThreads?: boolean
|
||||||
|
): Promise<ResultFor<'POST', keyof SubscriptionsEndpoints>> => {
|
||||||
|
let endpoint: keyof SubscriptionsEndpoints;
|
||||||
|
let payload: OperationParams<'POST', keyof SubscriptionsEndpoints> = { roomId };
|
||||||
|
|
||||||
|
if (isRead) {
|
||||||
|
endpoint = 'subscriptions.unread';
|
||||||
|
} else {
|
||||||
|
endpoint = 'subscriptions.read';
|
||||||
|
payload = { rid: roomId };
|
||||||
|
if (includeThreads) {
|
||||||
|
payload.readThreads = includeThreads;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return sdk.post('subscriptions.read', { rid: roomId });
|
|
||||||
|
return sdk.post(endpoint, payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getRoomCounters = (
|
export const getRoomCounters = (
|
||||||
|
|
|
@ -56,7 +56,8 @@ import {
|
||||||
isRead,
|
isRead,
|
||||||
debounce,
|
debounce,
|
||||||
isIOS,
|
isIOS,
|
||||||
isTablet
|
isTablet,
|
||||||
|
compareServerVersion
|
||||||
} from '../../lib/methods/helpers';
|
} from '../../lib/methods/helpers';
|
||||||
import { E2E_BANNER_TYPE, DisplayMode, SortBy, MAX_SIDEBAR_WIDTH, themes } from '../../lib/constants';
|
import { E2E_BANNER_TYPE, DisplayMode, SortBy, MAX_SIDEBAR_WIDTH, themes } from '../../lib/constants';
|
||||||
import { Services } from '../../lib/services';
|
import { Services } from '../../lib/services';
|
||||||
|
@ -103,6 +104,7 @@ interface IRoomsListViewProps {
|
||||||
createPublicChannelPermission: [];
|
createPublicChannelPermission: [];
|
||||||
createPrivateChannelPermission: [];
|
createPrivateChannelPermission: [];
|
||||||
createDiscussionPermission: [];
|
createDiscussionPermission: [];
|
||||||
|
serverVersion: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IRoomsListViewState {
|
interface IRoomsListViewState {
|
||||||
|
@ -703,9 +705,11 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
|
|
||||||
toggleRead = async (rid: string, tIsRead: boolean) => {
|
toggleRead = async (rid: string, tIsRead: boolean) => {
|
||||||
logEvent(tIsRead ? events.RL_UNREAD_CHANNEL : events.RL_READ_CHANNEL);
|
logEvent(tIsRead ? events.RL_UNREAD_CHANNEL : events.RL_READ_CHANNEL);
|
||||||
|
const { serverVersion } = this.props;
|
||||||
try {
|
try {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const result = await Services.toggleRead(tIsRead, rid);
|
const includeThreads = compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '5.4.0');
|
||||||
|
const result = await Services.toggleReadStatus(tIsRead, rid, includeThreads);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
const subCollection = db.get('subscriptions');
|
const subCollection = db.get('subscriptions');
|
||||||
|
@ -715,6 +719,9 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
await subRecord.update(sub => {
|
await subRecord.update(sub => {
|
||||||
sub.alert = tIsRead;
|
sub.alert = tIsRead;
|
||||||
sub.unread = 0;
|
sub.unread = 0;
|
||||||
|
if (includeThreads) {
|
||||||
|
sub.tunread = [];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log(e);
|
log(e);
|
||||||
|
@ -1064,7 +1071,8 @@ const mapStateToProps = (state: IApplicationState) => ({
|
||||||
createDirectMessagePermission: state.permissions['create-d'],
|
createDirectMessagePermission: state.permissions['create-d'],
|
||||||
createPublicChannelPermission: state.permissions['create-c'],
|
createPublicChannelPermission: state.permissions['create-c'],
|
||||||
createPrivateChannelPermission: state.permissions['create-p'],
|
createPrivateChannelPermission: state.permissions['create-p'],
|
||||||
createDiscussionPermission: state.permissions['start-discussion']
|
createDiscussionPermission: state.permissions['start-discussion'],
|
||||||
|
serverVersion: state.server.version
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(withDimensions(withTheme(withSafeAreaInsets(RoomsListView))));
|
export default connect(mapStateToProps)(withDimensions(withTheme(withSafeAreaInsets(RoomsListView))));
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
import { by, device, element, expect, waitFor } from 'detox';
|
import { by, device, element, expect, waitFor } from 'detox';
|
||||||
|
|
||||||
import { TTextMatcher, login, navigateToLogin, platformTypes, searchRoom, tapBack, tryTapping } from '../../helpers/app';
|
import { TTextMatcher, login, navigateToLogin, platformTypes, searchRoom, sleep, tapBack, tryTapping } from '../../helpers/app';
|
||||||
import { ITestUser, createRandomRoom, createRandomUser, initApi } from '../../helpers/data_setup';
|
import { ITestUser, createRandomRoom, createRandomUser, initApi } from '../../helpers/data_setup';
|
||||||
import random from '../../helpers/random';
|
import random from '../../helpers/random';
|
||||||
|
|
||||||
const roomId = '64b846e4760e618aa9f91ab7';
|
const roomId = '64b846e4760e618aa9f91ab7';
|
||||||
|
|
||||||
|
function getIndex() {
|
||||||
|
if (device.getPlatform() === 'android') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const sendMessageOnTranslationTestRoom = async (msg: string): Promise<{ user: ITestUser; msgId: string }> => {
|
const sendMessageOnTranslationTestRoom = async (msg: string): Promise<{ user: ITestUser; msgId: string }> => {
|
||||||
const user = await createRandomUser();
|
const user = await createRandomUser();
|
||||||
const api = await initApi(user.username, user.password);
|
const api = await initApi(user.username, user.password);
|
||||||
|
@ -36,22 +43,37 @@ async function navigateToRoom(roomName: string) {
|
||||||
.withTimeout(5000);
|
.withTimeout(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function searchMessage(msg: string, textMatcher: TTextMatcher) {
|
||||||
|
await sleep(1000); // wait for proper load the room
|
||||||
|
await element(by.id('room-view-search')).tap();
|
||||||
|
await waitFor(element(by.id('search-messages-view')))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(5000);
|
||||||
|
await element(by.id('search-message-view-input')).replaceText(msg);
|
||||||
|
await waitFor(element(by[textMatcher](msg)).atIndex(getIndex()))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(30000);
|
||||||
|
await sleep(1000);
|
||||||
|
await element(by[textMatcher](msg)).atIndex(getIndex()).tap();
|
||||||
|
await sleep(10000);
|
||||||
|
}
|
||||||
|
|
||||||
export function waitForVisible(id: string) {
|
export function waitForVisible(id: string) {
|
||||||
return waitFor(element(by.id(id)))
|
return waitFor(element(by.id(id)))
|
||||||
.toBeVisible()
|
.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function waitForVisibleTextMatcher(msg: string, textMatcher: TTextMatcher) {
|
export function waitForVisibleTextMatcher(msg: string, textMatcher: TTextMatcher) {
|
||||||
return waitFor(element(by[textMatcher](msg)).atIndex(0))
|
return waitFor(element(by[textMatcher](msg)).atIndex(0))
|
||||||
.toExist()
|
.toExist()
|
||||||
.withTimeout(5000);
|
.withTimeout(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function waitForNotVisible(id: string) {
|
export function waitForNotVisible(id: string) {
|
||||||
return waitFor(element(by.id(id)))
|
return waitFor(element(by.id(id)))
|
||||||
.not.toBeVisible()
|
.not.toBeVisible()
|
||||||
.withTimeout(5000);
|
.withTimeout(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Auto Translate', () => {
|
describe('Auto Translate', () => {
|
||||||
|
@ -97,6 +119,7 @@ describe('Auto Translate', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should see old message not translated before enable auto translate', async () => {
|
it('should see old message not translated before enable auto translate', async () => {
|
||||||
|
await searchMessage(oldMessage[languages.default] as string, textMatcher);
|
||||||
await waitForVisibleTextMatcher(oldMessage[languages.default] as string, textMatcher);
|
await waitForVisibleTextMatcher(oldMessage[languages.default] as string, textMatcher);
|
||||||
await waitForVisibleTextMatcher(attachmentMessage[languages.default] as string, textMatcher);
|
await waitForVisibleTextMatcher(attachmentMessage[languages.default] as string, textMatcher);
|
||||||
});
|
});
|
||||||
|
@ -141,6 +164,7 @@ describe('Auto Translate', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should see old message translated after enable auto translate', async () => {
|
it('should see old message translated after enable auto translate', async () => {
|
||||||
|
await searchMessage(oldMessage[languages.default] as string, textMatcher);
|
||||||
await waitForVisibleTextMatcher(oldMessage[languages.translated] as string, textMatcher);
|
await waitForVisibleTextMatcher(oldMessage[languages.translated] as string, textMatcher);
|
||||||
await waitForVisibleTextMatcher(attachmentMessage[languages.translated] as string, textMatcher);
|
await waitForVisibleTextMatcher(attachmentMessage[languages.translated] as string, textMatcher);
|
||||||
});
|
});
|
||||||
|
@ -148,6 +172,7 @@ describe('Auto Translate', () => {
|
||||||
it('should see new message translated', async () => {
|
it('should see new message translated', async () => {
|
||||||
const randomMatcher = random();
|
const randomMatcher = random();
|
||||||
const data = await sendMessageOnTranslationTestRoom(`${newMessage[languages.default]} - ${randomMatcher}`);
|
const data = await sendMessageOnTranslationTestRoom(`${newMessage[languages.default]} - ${randomMatcher}`);
|
||||||
|
await searchMessage(`${newMessage[languages.default]} - ${randomMatcher}`, textMatcher); // will scroll the messages list to the last one
|
||||||
await waitForVisibleTextMatcher(`${newMessage[languages.translated]} - ${randomMatcher}`, textMatcher);
|
await waitForVisibleTextMatcher(`${newMessage[languages.translated]} - ${randomMatcher}`, textMatcher);
|
||||||
await deleteMessageOnTranslationTestRoom(data);
|
await deleteMessageOnTranslationTestRoom(data);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue