[NEW] Direct link to a threaded conversation (#3406)
* [FIX] deeplinking to thread * fix how to find threadId * tmid as route params jumpToThreaId * minor tweak * minor tweak on logic * E2E Test * minor tweak * wait for the return of the thread * Minor refactor * Fix e2e tests for docker * popToRoot when focused and there is a jumpToThread Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
parent
72d50887a4
commit
2ab1bacdb3
|
@ -45,8 +45,10 @@ const navigate = function* navigate({ params }) {
|
||||||
if (params.path || params.rid) {
|
if (params.path || params.rid) {
|
||||||
let type;
|
let type;
|
||||||
let name;
|
let name;
|
||||||
|
let jumpToThreadId;
|
||||||
if (params.path) {
|
if (params.path) {
|
||||||
[type, name] = params.path.split('/');
|
// Following this pattern: {channelType}/{channelName}/thread/{threadId}
|
||||||
|
[type, name, , jumpToThreadId] = params.path.split('/');
|
||||||
}
|
}
|
||||||
if (type !== 'invite' || params.rid) {
|
if (type !== 'invite' || params.rid) {
|
||||||
const room = yield RocketChat.canOpenRoom(params);
|
const room = yield RocketChat.canOpenRoom(params);
|
||||||
|
@ -65,14 +67,19 @@ const navigate = function* navigate({ params }) {
|
||||||
if (focusedRooms.includes(room.rid)) {
|
if (focusedRooms.includes(room.rid)) {
|
||||||
// if there's one room on the list or last room is the one
|
// if there's one room on the list or last room is the one
|
||||||
if (focusedRooms.length === 1 || focusedRooms[0] === room.rid) {
|
if (focusedRooms.length === 1 || focusedRooms[0] === room.rid) {
|
||||||
yield goRoom({ item, isMasterDetail, jumpToMessageId });
|
if (jumpToThreadId) {
|
||||||
|
// With this conditional when there is a jumpToThreadId we can avoid the thread open again
|
||||||
|
// above other thread and the room could call again the thread
|
||||||
|
popToRoot({ isMasterDetail });
|
||||||
|
}
|
||||||
|
yield goRoom({ item, isMasterDetail, jumpToMessageId, jumpToThreadId });
|
||||||
} else {
|
} else {
|
||||||
popToRoot({ isMasterDetail });
|
popToRoot({ isMasterDetail });
|
||||||
yield goRoom({ item, isMasterDetail, jumpToMessageId });
|
yield goRoom({ item, isMasterDetail, jumpToMessageId, jumpToThreadId });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
popToRoot({ isMasterDetail });
|
popToRoot({ isMasterDetail });
|
||||||
yield goRoom({ item, isMasterDetail, jumpToMessageId });
|
yield goRoom({ item, isMasterDetail, jumpToMessageId, jumpToThreadId });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.isCall) {
|
if (params.isCall) {
|
||||||
|
|
|
@ -149,6 +149,7 @@ class RoomView extends React.Component {
|
||||||
prid
|
prid
|
||||||
};
|
};
|
||||||
this.jumpToMessageId = props.route.params?.jumpToMessageId;
|
this.jumpToMessageId = props.route.params?.jumpToMessageId;
|
||||||
|
this.jumpToThreadId = props.route.params?.jumpToThreadId;
|
||||||
const roomUserId = props.route.params?.roomUserId ?? RocketChat.getUidDirectMessage(room);
|
const roomUserId = props.route.params?.roomUserId ?? RocketChat.getUidDirectMessage(room);
|
||||||
this.state = {
|
this.state = {
|
||||||
joined: true,
|
joined: true,
|
||||||
|
@ -209,6 +210,9 @@ class RoomView extends React.Component {
|
||||||
if (this.jumpToMessageId) {
|
if (this.jumpToMessageId) {
|
||||||
this.jumpToMessage(this.jumpToMessageId);
|
this.jumpToMessage(this.jumpToMessageId);
|
||||||
}
|
}
|
||||||
|
if (this.jumpToThreadId && !this.jumpToMessageId) {
|
||||||
|
this.navToThread({ tmid: this.jumpToThreadId });
|
||||||
|
}
|
||||||
if (isIOS && this.rid) {
|
if (isIOS && this.rid) {
|
||||||
this.updateUnreadCount();
|
this.updateUnreadCount();
|
||||||
}
|
}
|
||||||
|
@ -254,6 +258,10 @@ class RoomView extends React.Component {
|
||||||
this.jumpToMessage(route?.params?.jumpToMessageId);
|
this.jumpToMessage(route?.params?.jumpToMessageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (route?.params?.jumpToThreadId !== prevProps.route?.params?.jumpToThreadId) {
|
||||||
|
this.navToThread({ tmid: route?.params?.jumpToThreadId });
|
||||||
|
}
|
||||||
|
|
||||||
if (appState === 'foreground' && appState !== prevProps.appState && this.rid) {
|
if (appState === 'foreground' && appState !== prevProps.appState && this.rid) {
|
||||||
// Fire List.query() just to keep observables working
|
// Fire List.query() just to keep observables working
|
||||||
if (this.list && this.list.current) {
|
if (this.list && this.list.current) {
|
||||||
|
@ -872,7 +880,12 @@ class RoomView extends React.Component {
|
||||||
if (item.tmid) {
|
if (item.tmid) {
|
||||||
let name = item.tmsg;
|
let name = item.tmsg;
|
||||||
if (!name) {
|
if (!name) {
|
||||||
name = await this.getThreadName(item.tmid, item.id);
|
const result = await this.getThreadName(item.tmid, item.id);
|
||||||
|
// test if there isn't a thread
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
name = result;
|
||||||
}
|
}
|
||||||
if (item.t === E2E_MESSAGE_TYPE && item.e2e !== E2E_STATUS.DONE) {
|
if (item.t === E2E_MESSAGE_TYPE && item.e2e !== E2E_STATUS.DONE) {
|
||||||
name = I18n.t('Encrypted_message');
|
name = I18n.t('Encrypted_message');
|
||||||
|
|
|
@ -44,6 +44,9 @@ const data = {
|
||||||
},
|
},
|
||||||
alternate: {
|
alternate: {
|
||||||
name: `detox-alternate-${value}`
|
name: `detox-alternate-${value}`
|
||||||
|
},
|
||||||
|
alternate2: {
|
||||||
|
name: `detox-alternate2-${value}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
teams: {
|
teams: {
|
||||||
|
|
|
@ -45,6 +45,9 @@ const data = {
|
||||||
},
|
},
|
||||||
alternate: {
|
alternate: {
|
||||||
name: `detox-alternate-${value}`
|
name: `detox-alternate-${value}`
|
||||||
|
},
|
||||||
|
alternate2: {
|
||||||
|
name: `detox-alternate2-${value}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
teams: {
|
teams: {
|
||||||
|
|
|
@ -116,11 +116,12 @@ const changeChannelJoinCode = async (roomId, joinCode) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const sendMessage = async (user, channel, msg) => {
|
const sendMessage = async (user, channel, msg, tmid) => {
|
||||||
console.log(`Sending message to ${channel}`);
|
console.log(`Sending message to ${channel}`);
|
||||||
try {
|
try {
|
||||||
await login(user.username, user.password);
|
await login(user.username, user.password);
|
||||||
await rocketchat.post('chat.postMessage', { channel, msg });
|
const response = await rocketchat.post('chat.postMessage', { channel, msg, tmid });
|
||||||
|
return response.data;
|
||||||
} catch (infoError) {
|
} catch (infoError) {
|
||||||
console.log(JSON.stringify(infoError));
|
console.log(JSON.stringify(infoError));
|
||||||
throw new Error('Failed to find or create private group');
|
throw new Error('Failed to find or create private group');
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const data = require('../../data');
|
const data = require('../../data');
|
||||||
const { tapBack, checkServer, navigateToRegister } = require('../../helpers/app');
|
const { tapBack, checkServer, navigateToRegister } = require('../../helpers/app');
|
||||||
const { get, login } = require('../../helpers/data_setup');
|
const { get, login, sendMessage } = require('../../helpers/data_setup');
|
||||||
|
|
||||||
const DEEPLINK_METHODS = { AUTH: 'auth', ROOM: 'room' };
|
const DEEPLINK_METHODS = { AUTH: 'auth', ROOM: 'room' };
|
||||||
const getDeepLink = (method, server, params) => {
|
const getDeepLink = (method, server, params) => {
|
||||||
|
@ -12,9 +12,15 @@ const getDeepLink = (method, server, params) => {
|
||||||
describe('Deep linking', () => {
|
describe('Deep linking', () => {
|
||||||
let userId;
|
let userId;
|
||||||
let authToken;
|
let authToken;
|
||||||
|
let threadId;
|
||||||
|
const threadMessage = `to-thread-${data.random}`;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const loginResult = await login(data.users.regular.username, data.users.regular.password);
|
const loginResult = await login(data.users.regular.username, data.users.regular.password);
|
||||||
({ userId, authToken } = loginResult);
|
({ userId, authToken } = loginResult);
|
||||||
|
// create a thread with api
|
||||||
|
const result = await sendMessage(data.users.regular, data.groups.alternate2.name, threadMessage);
|
||||||
|
threadId = result.message._id;
|
||||||
|
await sendMessage(data.users.regular, result.message.rid, data.random, threadId);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Authentication', () => {
|
describe('Authentication', () => {
|
||||||
|
@ -87,6 +93,18 @@ describe('Deep linking', () => {
|
||||||
.withTimeout(10000);
|
.withTimeout(10000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should navigate to the thread using path', async () => {
|
||||||
|
await device.launchApp({
|
||||||
|
permissions: { notifications: 'YES' },
|
||||||
|
newInstance: true,
|
||||||
|
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `path=group/${data.groups.alternate2.name}/thread/${threadId}`),
|
||||||
|
sourceApp: 'com.apple.mobilesafari'
|
||||||
|
});
|
||||||
|
await waitFor(element(by.id(`room-view-title-${threadMessage}`)))
|
||||||
|
.toExist()
|
||||||
|
.withTimeout(10000);
|
||||||
|
});
|
||||||
|
|
||||||
it('should navigate to the room using rid', async () => {
|
it('should navigate to the room using rid', async () => {
|
||||||
const roomResult = await get(`groups.info?roomName=${data.groups.private.name}`);
|
const roomResult = await get(`groups.info?roomName=${data.groups.private.name}`);
|
||||||
await device.launchApp({
|
await device.launchApp({
|
||||||
|
|
Loading…
Reference in New Issue