MOBILE-4120 messages: Fix wrong messages displayed in split view

main
Dani Palou 2022-10-17 09:03:18 +02:00
parent 134a6ab79e
commit fa9f074209
17 changed files with 107 additions and 110 deletions

View File

@ -18,11 +18,18 @@ import { Route, RouterModule, ROUTES, Routes } from '@angular/router';
import { buildTabMainRoutes } from '@features/mainmenu/mainmenu-tab-routing.module'; import { buildTabMainRoutes } from '@features/mainmenu/mainmenu-tab-routing.module';
import { AddonMessagesIndexGuard } from './guards'; import { AddonMessagesIndexGuard } from './guards';
export const AddonMessagesDiscussionRoute: Route = { export const DISCUSSION_ROUTES: Route[] = [
path: 'discussion', {
path: 'discussion/user/:userId',
loadChildren: () => import('./pages/discussion/discussion.module') loadChildren: () => import('./pages/discussion/discussion.module')
.then(m => m.AddonMessagesDiscussionPageModule), .then(m => m.AddonMessagesDiscussionPageModule),
}; },
{
path: 'discussion/:conversationId',
loadChildren: () => import('./pages/discussion/discussion.module')
.then(m => m.AddonMessagesDiscussionPageModule),
},
];
function buildRoutes(injector: Injector): Routes { function buildRoutes(injector: Injector): Routes {
return [ return [
@ -40,7 +47,7 @@ function buildRoutes(injector: Injector): Routes {
loadChildren: () => import('./pages/group-conversations/group-conversations.module') loadChildren: () => import('./pages/group-conversations/group-conversations.module')
.then(m => m.AddonMessagesGroupConversationsPageModule), .then(m => m.AddonMessagesGroupConversationsPageModule),
}, },
AddonMessagesDiscussionRoute, ...DISCUSSION_ROUTES,
{ {
path: 'search', path: 'search',
loadChildren: () => import('./pages/search/search.module') loadChildren: () => import('./pages/search/search.module')

View File

@ -15,7 +15,7 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { conditionalRoutes } from '@/app/app-routing.module'; import { conditionalRoutes } from '@/app/app-routing.module';
import { AddonMessagesDiscussionRoute } from '@addons/messages/messages-lazy.module'; import { DISCUSSION_ROUTES } from '@addons/messages/messages-lazy.module';
import { CoreScreen } from '@services/screen'; import { CoreScreen } from '@services/screen';
import { CoreSharedModule } from '@/core/shared.module'; import { CoreSharedModule } from '@/core/shared.module';
@ -28,16 +28,14 @@ const mobileRoutes: Routes = [
path: '', path: '',
component: AddonMessagesContacts35Page, component: AddonMessagesContacts35Page,
}, },
AddonMessagesDiscussionRoute, ...DISCUSSION_ROUTES,
]; ];
const tabletRoutes: Routes = [ const tabletRoutes: Routes = [
{ {
path: '', path: '',
component: AddonMessagesContacts35Page, component: AddonMessagesContacts35Page,
children: [ children: DISCUSSION_ROUTES,
AddonMessagesDiscussionRoute,
],
}, },
]; ];

View File

@ -25,7 +25,7 @@ import {
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreApp } from '@services/app'; import { CoreApp } from '@services/app';
import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { ActivatedRoute, Params } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { Translate } from '@singletons'; import { Translate } from '@singletons';
import { CoreScreen } from '@services/screen'; import { CoreScreen } from '@services/screen';
import { CoreNavigator } from '@services/navigator'; import { CoreNavigator } from '@services/navigator';
@ -241,15 +241,10 @@ export class AddonMessagesContacts35Page implements OnInit, OnDestroy {
gotoDiscussion(discussionUserId: number): void { gotoDiscussion(discussionUserId: number): void {
this.discussionUserId = discussionUserId; this.discussionUserId = discussionUserId;
const params: Params = { const path = CoreNavigator.getRelativePathToParent('/messages/contacts-35') + `discussion/user/${discussionUserId}`;
userId: discussionUserId,
};
const splitViewLoaded = CoreNavigator.isCurrentPathInTablet('**/messages/contacts-35/discussion');
const path = (splitViewLoaded ? '../' : '') + 'discussion';
// @todo Check why this is failing on ngInit. // @todo Check why this is failing on ngInit.
CoreNavigator.navigate(path, { params }); CoreNavigator.navigate(path);
} }
/** /**

View File

@ -15,7 +15,7 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { conditionalRoutes } from '@/app/app-routing.module'; import { conditionalRoutes } from '@/app/app-routing.module';
import { AddonMessagesDiscussionRoute } from '@addons/messages/messages-lazy.module'; import { DISCUSSION_ROUTES } from '@addons/messages/messages-lazy.module';
import { CoreScreen } from '@services/screen'; import { CoreScreen } from '@services/screen';
import { CoreSharedModule } from '@/core/shared.module'; import { CoreSharedModule } from '@/core/shared.module';
@ -27,16 +27,14 @@ const mobileRoutes: Routes = [
path: '', path: '',
component: AddonMessagesContactsPage, component: AddonMessagesContactsPage,
}, },
AddonMessagesDiscussionRoute, ...DISCUSSION_ROUTES,
]; ];
const tabletRoutes: Routes = [ const tabletRoutes: Routes = [
{ {
path: '', path: '',
component: AddonMessagesContactsPage, component: AddonMessagesContactsPage,
children: [ children: DISCUSSION_ROUTES,
AddonMessagesDiscussionRoute,
],
}, },
]; ];

View File

@ -291,10 +291,8 @@ export class AddonMessagesContactsPage implements OnInit, OnDestroy {
this.selectedUserId = userId; this.selectedUserId = userId;
const splitViewLoaded = CoreNavigator.isCurrentPathInTablet('**/messages/contacts/discussion'); const path = CoreNavigator.getRelativePathToParent('/messages/contacts') + `discussion/user/${userId}`;
const path = (splitViewLoaded ? '../' : '') + 'discussion'; CoreNavigator.navigate(path);
CoreNavigator.navigate(path, { params : { userId } });
} }
/** /**

View File

@ -154,28 +154,14 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
* Setup code for the page. * Setup code for the page.
*/ */
async ngOnInit(): Promise<void> { async ngOnInit(): Promise<void> {
this.conversationId = CoreNavigator.getRouteNumberParam('conversationId');
this.route.queryParams.subscribe(async (params) => { this.userId = CoreNavigator.getRouteNumberParam('userId');
const oldConversationId = this.conversationId; this.showInfo = !CoreNavigator.getRouteBooleanParam('hideInfo');
const oldUserId = this.userId; this.showKeyboard = !!CoreNavigator.getRouteBooleanParam('showKeyboard');
let forceScrollToBottom = false;
this.conversationId = CoreNavigator.getRouteNumberParam('conversationId', { params }) || undefined;
this.userId = CoreNavigator.getRouteNumberParam('userId', { params }) || undefined;
this.showInfo = !params.hideInfo;
if (oldConversationId != this.conversationId || oldUserId != this.userId) {
// Showing reload again can break animations.
this.loaded = false;
this.initialized = false;
forceScrollToBottom = true;
}
this.showKeyboard = CoreNavigator.getRouteBooleanParam('showKeyboard', { params }) || false;
await this.fetchData(); await this.fetchData();
this.scrollToBottom(forceScrollToBottom); this.scrollToBottom(true);
});
} }
/** /**
@ -1265,7 +1251,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
}); });
if (userId !== undefined) { if (userId !== undefined) {
const splitViewLoaded = CoreNavigator.isCurrentPathInTablet('**/messages/**/discussion'); const splitViewLoaded = CoreNavigator.isCurrentPathInTablet('**/messages/**/discussion/**');
// Open user conversation. // Open user conversation.
if (splitViewLoaded) { if (splitViewLoaded) {
@ -1277,7 +1263,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
); );
} else { } else {
// Open the discussion in a new view. // Open the discussion in a new view.
CoreNavigator.navigateToSitePath('/messages/discussion', { params: { userId } }); CoreNavigator.navigateToSitePath(`/messages/discussion/user/${userId}`);
} }
} }
} else { } else {

View File

@ -16,7 +16,7 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { CoreScreen } from '@services/screen'; import { CoreScreen } from '@services/screen';
import { conditionalRoutes } from '@/app/app-routing.module'; import { conditionalRoutes } from '@/app/app-routing.module';
import { AddonMessagesDiscussionRoute } from '@addons/messages/messages-lazy.module'; import { DISCUSSION_ROUTES } from '@addons/messages/messages-lazy.module';
import { CoreSharedModule } from '@/core/shared.module'; import { CoreSharedModule } from '@/core/shared.module';
import { CoreSearchComponentsModule } from '@features/search/components/components.module'; import { CoreSearchComponentsModule } from '@features/search/components/components.module';
@ -33,7 +33,7 @@ const mobileRoutes: Routes = [
}, },
component: AddonMessagesDiscussions35Page, component: AddonMessagesDiscussions35Page,
}, },
AddonMessagesDiscussionRoute, ...DISCUSSION_ROUTES,
]; ];
const tabletRoutes: Routes = [ const tabletRoutes: Routes = [
@ -43,9 +43,7 @@ const tabletRoutes: Routes = [
mainMenuTabRoot: AddonMessagesMainMenuHandlerService.PAGE_NAME, mainMenuTabRoot: AddonMessagesMainMenuHandlerService.PAGE_NAME,
}, },
component: AddonMessagesDiscussions35Page, component: AddonMessagesDiscussions35Page,
children: [ children: DISCUSSION_ROUTES,
AddonMessagesDiscussionRoute,
],
}, },
]; ];

View File

@ -257,16 +257,13 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy {
async gotoDiscussion(discussionUserId: number, messageId?: number): Promise<void> { async gotoDiscussion(discussionUserId: number, messageId?: number): Promise<void> {
this.discussionUserId = discussionUserId; this.discussionUserId = discussionUserId;
const params: Params = { const params: Params = {};
userId: discussionUserId,
};
if (messageId) { if (messageId) {
params.message = messageId; params.message = messageId;
} }
const splitViewLoaded = CoreNavigator.isCurrentPathInTablet('**/messages/index/discussion'); const path = CoreNavigator.getRelativePathToParent('/messages/index') + `discussion/user/${discussionUserId}`;
const path = (splitViewLoaded ? '../' : '') + 'discussion';
await CoreNavigator.navigate(path, { params }); await CoreNavigator.navigate(path, { params });
} }

View File

@ -15,7 +15,7 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { conditionalRoutes } from '@/app/app-routing.module'; import { conditionalRoutes } from '@/app/app-routing.module';
import { AddonMessagesDiscussionRoute } from '@addons/messages/messages-lazy.module'; import { DISCUSSION_ROUTES } from '@addons/messages/messages-lazy.module';
import { CoreScreen } from '@services/screen'; import { CoreScreen } from '@services/screen';
import { CoreSharedModule } from '@/core/shared.module'; import { CoreSharedModule } from '@/core/shared.module';
@ -32,7 +32,7 @@ const mobileRoutes: Routes = [
}, },
component: AddonMessagesGroupConversationsPage, component: AddonMessagesGroupConversationsPage,
}, },
AddonMessagesDiscussionRoute, ...DISCUSSION_ROUTES,
]; ];
const tabletRoutes: Routes = [ const tabletRoutes: Routes = [
@ -42,9 +42,7 @@ const tabletRoutes: Routes = [
mainMenuTabRoot: AddonMessagesMainMenuHandlerService.PAGE_NAME, mainMenuTabRoot: AddonMessagesMainMenuHandlerService.PAGE_NAME,
}, },
component: AddonMessagesGroupConversationsPage, component: AddonMessagesGroupConversationsPage,
children: [ children: DISCUSSION_ROUTES,
AddonMessagesDiscussionRoute,
],
}, },
]; ];

View File

@ -519,18 +519,12 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
this.selectedUserId = userId; this.selectedUserId = userId;
const params: Params = {}; const params: Params = {};
if (conversationId) {
params.conversationId = conversationId;
}
if (userId) {
params.userId = userId;
}
if (messageId) { if (messageId) {
params.message = messageId; params.message = messageId;
} }
const splitViewLoaded = CoreNavigator.isCurrentPathInTablet('**/messages/group-conversations/discussion'); const path = CoreNavigator.getRelativePathToParent('/messages/group-conversations') + 'discussion/' +
const path = (splitViewLoaded ? '../' : '') + 'discussion'; (conversationId ? conversationId : `user/${userId}`);
await CoreNavigator.navigate(path, { params }); await CoreNavigator.navigate(path, { params });
} }
@ -539,7 +533,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
* Navigate to message settings. * Navigate to message settings.
*/ */
gotoSettings(): void { gotoSettings(): void {
CoreNavigator.navigateToSitePath('../message-settings'); CoreNavigator.navigateToSitePath('message-settings');
} }
/** /**

View File

@ -16,7 +16,7 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { CoreScreen } from '@services/screen'; import { CoreScreen } from '@services/screen';
import { conditionalRoutes } from '@/app/app-routing.module'; import { conditionalRoutes } from '@/app/app-routing.module';
import { AddonMessagesDiscussionRoute } from '@addons/messages/messages-lazy.module'; import { DISCUSSION_ROUTES } from '@addons/messages/messages-lazy.module';
import { CoreSharedModule } from '@/core/shared.module'; import { CoreSharedModule } from '@/core/shared.module';
import { CoreSearchComponentsModule } from '@features/search/components/components.module'; import { CoreSearchComponentsModule } from '@features/search/components/components.module';
@ -28,16 +28,14 @@ const mobileRoutes: Routes = [
path: '', path: '',
component: AddonMessagesSearchPage, component: AddonMessagesSearchPage,
}, },
AddonMessagesDiscussionRoute, ...DISCUSSION_ROUTES,
]; ];
const tabletRoutes: Routes = [ const tabletRoutes: Routes = [
{ {
path: '', path: '',
component: AddonMessagesSearchPage, component: AddonMessagesSearchPage,
children: [ children: DISCUSSION_ROUTES,
AddonMessagesDiscussionRoute,
],
}, },
]; ];

View File

@ -24,7 +24,6 @@ import {
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreApp } from '@services/app'; import { CoreApp } from '@services/app';
import { CoreNavigator } from '@services/navigator'; import { CoreNavigator } from '@services/navigator';
import { Params } from '@angular/router';
import { CoreScreen } from '@services/screen'; import { CoreScreen } from '@services/screen';
/** /**
@ -107,9 +106,9 @@ export class AddonMessagesSearchPage implements OnDestroy {
this.displayResults = false; this.displayResults = false;
// Empty details. // Empty details.
const splitViewLoaded = CoreNavigator.isCurrentPathInTablet('**/messages/search/discussion'); const path = CoreNavigator.getRelativePathToParent('/messages/search');
if (splitViewLoaded) { if (path) {
CoreNavigator.navigate('../'); CoreNavigator.navigate(path);
} }
} }
@ -250,16 +249,18 @@ export class AddonMessagesSearchPage implements OnDestroy {
if (!onInit || CoreScreen.isTablet) { if (!onInit || CoreScreen.isTablet) {
this.selectedResult = result; this.selectedResult = result;
const params: Params = {}; let conversationId: number | undefined;
let userId: number | undefined;
if ('conversationid' in result) { if ('conversationid' in result) {
params.conversationId = result.conversationid; conversationId = result.conversationid;
} else { } else {
params.userId = result.id; userId = result.id;
} }
const splitViewLoaded = CoreNavigator.isCurrentPathInTablet('**/messages/search/discussion'); const path = CoreNavigator.getRelativePathToParent('/messages/search') + 'discussion/' +
const path = (splitViewLoaded ? '../' : '') + 'discussion'; (conversationId ? conversationId : `user/${userId}`);
CoreNavigator.navigate(path, { params });
CoreNavigator.navigate(path);
} }
} }

View File

@ -46,10 +46,8 @@ export class AddonMessagesDiscussionLinkHandlerService extends CoreContentLinksH
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> { ): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
return [{ return [{
action: (siteId): void => { action: (siteId): void => {
const stateParams = { const userId = parseInt(params.id || params.user2, 10);
userId: parseInt(params.id || params.user2, 10), CoreNavigator.navigateToSitePath(`/messages/discussion/user/${userId}`, { siteId });
};
CoreNavigator.navigateToSitePath('/messages/discussion', { params: stateParams, siteId });
}, },
}]; }];
} }

View File

@ -13,7 +13,6 @@
// limitations under the License. // limitations under the License.
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate'; import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications'; import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreNavigator } from '@services/navigator'; import { CoreNavigator } from '@services/navigator';
@ -63,28 +62,22 @@ export class AddonMessagesPushClickHandlerService implements CorePushNotificatio
// Check if group messaging is enabled, to determine which page should be loaded. // Check if group messaging is enabled, to determine which page should be loaded.
const enabled = await AddonMessages.isGroupMessagingEnabledInSite(notification.site); const enabled = await AddonMessages.isGroupMessagingEnabledInSite(notification.site);
let nextPageParams: Params | undefined; let conversationId: number | undefined;
let userId: number | undefined;
// Check if we have enough information to open the conversation. // Check if we have enough information to open the conversation.
if (notification.convid && enabled) { if (notification.convid && enabled) {
nextPageParams = { conversationId = Number(notification.convid);
conversationId: Number(notification.convid),
};
} else if (notification.userfromid) { } else if (notification.userfromid) {
nextPageParams = { userId = Number(notification.userfromid);
userId: Number(notification.userfromid),
};
} }
await CoreNavigator.navigateToSitePath(AddonMessagesMainMenuHandlerService.PAGE_NAME, { await CoreNavigator.navigateToSitePath(AddonMessagesMainMenuHandlerService.PAGE_NAME, {
siteId: notification.site, siteId: notification.site,
preferCurrentTab: false, preferCurrentTab: false,
nextNavigation: nextPageParams ? nextNavigation: conversationId ?
{ { path: `discussion/${conversationId}` } :
path: 'discussion', (userId ? { path: `discussion/user/${userId}` } : undefined),
options: { params: nextPageParams },
} :
undefined,
}); });
} }

View File

@ -71,10 +71,9 @@ export class AddonMessagesSendMessageUserHandlerService implements CoreUserProfi
const pageParams: Params = { const pageParams: Params = {
showKeyboard: true, showKeyboard: true,
userId: user.id,
hideInfo: true, hideInfo: true,
}; };
CoreNavigator.navigateToSitePath('/messages/discussion', { params: pageParams }); CoreNavigator.navigateToSitePath(`/messages/discussion/user/${user.id}`, { params: pageParams });
}, },
}; };
} }

View File

@ -700,6 +700,29 @@ export class CoreNavigatorService {
return promise; return promise;
} }
/**
* Get the relative path to a parent path.
* E.g. if parent path is '/foo' and current path is '/foo/bar/baz' it will return '../../'.
*
* @param parentPath Parent path.
* @return Relative path to the parent, empty if same path or parent path not found.
* @todo If messaging is refactored to use list managers, this function might not be needed anymore.
*/
getRelativePathToParent(parentPath: string): string {
// Add an ending slash to avoid collisions with other routes (e.g. /foo and /foobar).
parentPath = CoreTextUtils.addEndingSlash(parentPath);
const path = this.getCurrentPath();
const parentRouteIndex = path.indexOf(parentPath);
if (parentRouteIndex === -1) {
return '';
}
const depth = (path.substring(parentRouteIndex + parentPath.length - 1).match(/\//g) ?? []).length;
return '../'.repeat(depth);
}
} }
export const CoreNavigator = makeSingleton(CoreNavigatorService); export const CoreNavigator = makeSingleton(CoreNavigatorService);

View File

@ -14,7 +14,7 @@
import { NavController as NavControllerService } from '@ionic/angular'; import { NavController as NavControllerService } from '@ionic/angular';
import { mockSingleton } from '@/testing/utils'; import { mock, mockSingleton } from '@/testing/utils';
import { CoreNavigatorService } from '@services/navigator'; import { CoreNavigatorService } from '@services/navigator';
import { NavController, Router } from '@singletons'; import { NavController, Router } from '@singletons';
@ -156,6 +156,22 @@ describe('CoreNavigator', () => {
expect(navControllerMock.navigateRoot).toHaveBeenCalledWith(['/main/initialpage'], {}); expect(navControllerMock.navigateRoot).toHaveBeenCalledWith(['/main/initialpage'], {});
}); });
it('calculates relative paths to parent paths', () => {
navigator = mock(navigator, {
getCurrentPath: () => '/foo/bar/baz/xyz',
});
expect(navigator.getRelativePathToParent('/foo/bar/baz/xyz')).toEqual('');
expect(navigator.getRelativePathToParent('/foo/bar/baz')).toEqual('../');
expect(navigator.getRelativePathToParent('/foo/bar')).toEqual('../../');
expect(navigator.getRelativePathToParent('/bar')).toEqual('../../');
expect(navigator.getRelativePathToParent('/foo')).toEqual('../../../');
expect(navigator.getRelativePathToParent('/foo/')).toEqual('../../../');
expect(navigator.getRelativePathToParent('foo')).toEqual('../../../');
expect(navigator.getRelativePathToParent('/invalid')).toEqual('');
expect(navigator.getRelativePathToParent('/fo')).toEqual('');
});
it.todo('navigates to a different site'); it.todo('navigates to a different site');
it.todo('navigates to login credentials'); it.todo('navigates to login credentials');
it.todo('navigates to NO_SITE_ID site'); it.todo('navigates to NO_SITE_ID site');