From 04c6f4480d3846f18e0692a603c9b67052906ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 21 Jan 2021 16:34:47 +0100 Subject: [PATCH] MOBILE-3631 messages: Add contacts page --- src/addons/messages/messages-lazy.module.ts | 25 ++- .../contacts-confirmed.html | 30 ++++ .../contacts-confirmed.module.ts | 45 +++++ .../contacts-confirmed.page.ts | 165 ++++++++++++++++++ .../contacts-requests/contacts-requests.html | 24 +++ .../contacts-requests.module.ts | 45 +++++ .../contacts-requests.page.ts | 161 +++++++++++++++++ .../messages/pages/contacts/contacts.html | 19 ++ .../pages/contacts/contacts.module.ts | 64 +++++++ .../messages/pages/contacts/contacts.page.ts | 134 ++++++++++++++ .../messages-contacts-routing.module.ts | 33 ++++ src/addons/messages/services/messages.ts | 9 + 12 files changed, 753 insertions(+), 1 deletion(-) create mode 100644 src/addons/messages/pages/contacts-confirmed/contacts-confirmed.html create mode 100644 src/addons/messages/pages/contacts-confirmed/contacts-confirmed.module.ts create mode 100644 src/addons/messages/pages/contacts-confirmed/contacts-confirmed.page.ts create mode 100644 src/addons/messages/pages/contacts-requests/contacts-requests.html create mode 100644 src/addons/messages/pages/contacts-requests/contacts-requests.module.ts create mode 100644 src/addons/messages/pages/contacts-requests/contacts-requests.page.ts create mode 100644 src/addons/messages/pages/contacts/contacts.html create mode 100644 src/addons/messages/pages/contacts/contacts.module.ts create mode 100644 src/addons/messages/pages/contacts/contacts.page.ts create mode 100644 src/addons/messages/pages/contacts/messages-contacts-routing.module.ts diff --git a/src/addons/messages/messages-lazy.module.ts b/src/addons/messages/messages-lazy.module.ts index ebc68e7be..b49237824 100644 --- a/src/addons/messages/messages-lazy.module.ts +++ b/src/addons/messages/messages-lazy.module.ts @@ -16,6 +16,7 @@ import { Injector, NgModule } from '@angular/core'; import { RouterModule, ROUTES, Routes } from '@angular/router'; import { buildTabMainRoutes } from '@features/mainmenu/mainmenu-tab-routing.module'; +import { AddonMessagesContactsRoutingModule } from './pages/contacts/messages-contacts-routing.module'; import { AddonMessagesIndexRoutingModule } from './pages/index-35/messages-index-routing.module'; function buildRoutes(injector: Injector): Routes { @@ -34,6 +35,11 @@ function buildRoutes(injector: Injector): Routes { loadChildren: () => import('./pages/search/search.module') .then(m => m.AddonMessagesSearchPageModule), }, + { + path: 'contacts', // 3.6 or greater. + loadChildren: () => import('./pages/contacts/contacts.module') + .then(m => m.AddonMessagesContactsPageModule), + }, ...buildTabMainRoutes(injector, { redirectTo: 'index', pathMatch: 'full', @@ -53,8 +59,25 @@ const indexTabRoutes: Routes = [ }, ]; +// 3.6 or greater. +const contactsTabRoutes: Routes = [ + { + path: 'confirmed', + loadChildren: () => import('./pages/contacts-confirmed/contacts-confirmed.module') + .then(m => m.AddonMessagesContactsConfirmedPageModule), + }, + { + path: 'requests', + loadChildren: () => import('./pages/contacts-requests/contacts-requests.module') + .then(m => m.AddonMessagesContactsRequestsPageModule), + }, +]; + @NgModule({ - imports: [AddonMessagesIndexRoutingModule.forChild({ children: indexTabRoutes })], + imports: [ + AddonMessagesIndexRoutingModule.forChild({ children: indexTabRoutes }), + AddonMessagesContactsRoutingModule.forChild({ children: contactsTabRoutes }), + ], exports: [RouterModule], providers: [ { diff --git a/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.html b/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.html new file mode 100644 index 000000000..234176390 --- /dev/null +++ b/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.html @@ -0,0 +1,30 @@ + + + + + + + + + +

+ {{ contact.fullname }} + + +

+
+
+
+ + + + + + +
+
diff --git a/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.module.ts b/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.module.ts new file mode 100644 index 000000000..0506ffeb9 --- /dev/null +++ b/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.module.ts @@ -0,0 +1,45 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { IonicModule } from '@ionic/angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { RouterModule, Routes } from '@angular/router'; +import { CommonModule } from '@angular/common'; + +import { CoreSharedModule } from '@/core/shared.module'; + +import { AddonMessagesContactsConfirmedPage } from './contacts-confirmed.page'; + +const routes: Routes = [ + { + path: '', + component: AddonMessagesContactsConfirmedPage, + }, +]; + +@NgModule({ + imports: [ + RouterModule.forChild(routes), + CommonModule, + IonicModule, + TranslateModule.forChild(), + CoreSharedModule, + ], + declarations: [ + AddonMessagesContactsConfirmedPage, + ], + exports: [RouterModule], +}) +export class AddonMessagesContactsConfirmedPageModule {} diff --git a/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.page.ts b/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.page.ts new file mode 100644 index 000000000..433958fbf --- /dev/null +++ b/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.page.ts @@ -0,0 +1,165 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; +import { CoreSites } from '@services/sites'; +import { + AddonMessagesProvider, + AddonMessagesConversationMember, + AddonMessages, + AddonMessagesMemberInfoChangedEventData, + AddonMessagesSplitViewLoadContactsEventData, +} from '../../services/messages'; +import { CoreDomUtils } from '@services/utils/dom'; +import { IonRefresher } from '@ionic/angular'; +import { CoreNavigator } from '@services/navigator'; + +/** + * Component that displays the list of confirmed contacts. + */ +@Component({ + selector: 'addon-messages-confirmed-contacts', + templateUrl: 'contacts-confirmed.html', +}) +export class AddonMessagesContactsConfirmedPage implements OnInit, OnDestroy { + + loaded = false; + canLoadMore = false; + loadMoreError = false; + contacts: AddonMessagesConversationMember[] = []; + selectedUserId?: number; + + protected memberInfoObserver: CoreEventObserver; + + constructor() { + // this.onUserSelected = new EventEmitter(); + + // Update block status of a user. + this.memberInfoObserver = CoreEvents.on( + AddonMessagesProvider.MEMBER_INFO_CHANGED_EVENT, + (data) => { + if (data.userBlocked || data.userUnblocked) { + const user = this.contacts.find((user) => user.id == data.userId); + if (user) { + user.isblocked = !!data.userBlocked; + } + } else if (data.contactRemoved) { + const index = this.contacts.findIndex((contact) => contact.id == data.userId); + if (index >= 0) { + this.contacts.splice(index, 1); + } + } else if (data.contactRequestConfirmed) { + this.refreshData(); + } + }, + CoreSites.instance.getCurrentSiteId(), + ); + } + + /** + * Component loaded. + */ + async ngOnInit(): Promise { + try { + await this.fetchData(); + if (this.contacts.length) { + this.selectUser(this.contacts[0].id, true); + } + } finally { + this.loaded = true; + } + // Workaround for infinite scrolling. + // @todo this.content.resize(); + } + + /** + * Fetch contacts. + * + * @param refresh True if we are refreshing contacts, false if we are loading more. + * @return Promise resolved when done. + */ + async fetchData(refresh: boolean = false): Promise { + this.loadMoreError = false; + + const limitFrom = refresh ? 0 : this.contacts.length; + + if (limitFrom === 0) { + // Always try to get latest data from server. + await AddonMessages.instance.invalidateUserContacts(); + } + + try { + const result = await AddonMessages.instance.getUserContacts(limitFrom); + this.contacts = refresh ? result.contacts : this.contacts.concat(result.contacts); + this.canLoadMore = result.canLoadMore; + } catch (error) { + this.loadMoreError = true; + CoreDomUtils.instance.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingcontacts', true); + } + } + + /** + * Refresh contacts. + * + * @param refresher Refresher. + * @return Promise resolved when done. + */ + async refreshData(refresher?: CustomEvent): Promise { + // No need to invalidate contacts, we always try to get the latest. + await this.fetchData(true).finally(() => { + refresher?.detail.complete(); + }); + } + + /** + * Load more contacts. + * + * @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading. + * @return Resolved when done. + */ + async loadMore(infiniteComplete?: () => void): Promise { + await this.fetchData().finally(() => { + infiniteComplete && infiniteComplete(); + }); + } + + /** + * Notify that a contact has been selected. + * + * @param userId User id. + * @param onInit Whether the contact is selected on initial load. + */ + selectUser(userId: number, onInit: boolean = false): void { + this.selectedUserId = userId; + + const data: AddonMessagesSplitViewLoadContactsEventData = { + userId, + onInit, + }; + + CoreEvents.trigger(AddonMessagesProvider.SPLIT_VIEW_LOAD_CONTACTS_EVENT, data); + + // @todo: Check if split view is visible before + CoreNavigator.instance.navigateToSitePath('discussion', { params : { userId } }); + } + + /** + * Component destroyed. + */ + ngOnDestroy(): void { + this.memberInfoObserver?.off(); + } + +} diff --git a/src/addons/messages/pages/contacts-requests/contacts-requests.html b/src/addons/messages/pages/contacts-requests/contacts-requests.html new file mode 100644 index 000000000..4d52cdd62 --- /dev/null +++ b/src/addons/messages/pages/contacts-requests/contacts-requests.html @@ -0,0 +1,24 @@ + + + + + + + + + +

{{ request.fullname }}

+

+ {{ 'addon.messages.wouldliketocontactyou' | translate }} +

+
+
+
+ + + + +
+
diff --git a/src/addons/messages/pages/contacts-requests/contacts-requests.module.ts b/src/addons/messages/pages/contacts-requests/contacts-requests.module.ts new file mode 100644 index 000000000..00306f478 --- /dev/null +++ b/src/addons/messages/pages/contacts-requests/contacts-requests.module.ts @@ -0,0 +1,45 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { IonicModule } from '@ionic/angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { RouterModule, Routes } from '@angular/router'; +import { CommonModule } from '@angular/common'; + +import { CoreSharedModule } from '@/core/shared.module'; + +import { AddonMessagesContactsRequestsPage } from './contacts-requests.page'; + +const routes: Routes = [ + { + path: '', + component: AddonMessagesContactsRequestsPage, + }, +]; + +@NgModule({ + imports: [ + RouterModule.forChild(routes), + CommonModule, + IonicModule, + TranslateModule.forChild(), + CoreSharedModule, + ], + declarations: [ + AddonMessagesContactsRequestsPage, + ], + exports: [RouterModule], +}) +export class AddonMessagesContactsRequestsPageModule {} diff --git a/src/addons/messages/pages/contacts-requests/contacts-requests.page.ts b/src/addons/messages/pages/contacts-requests/contacts-requests.page.ts new file mode 100644 index 000000000..0cc7d05c5 --- /dev/null +++ b/src/addons/messages/pages/contacts-requests/contacts-requests.page.ts @@ -0,0 +1,161 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; +import { CoreSites } from '@services/sites'; +import { + AddonMessagesProvider, + AddonMessagesConversationMember, + AddonMessagesSplitViewLoadContactsEventData, + AddonMessages, + AddonMessagesMemberInfoChangedEventData, +} from '../../services/messages'; +import { CoreDomUtils } from '@services/utils/dom'; +import { CoreNavigator } from '@services/navigator'; +import { IonRefresher } from '@ionic/angular'; + +/** + * Component that displays the list of contact requests. + */ +@Component({ + selector: 'addon-messages-contact-requests', + templateUrl: 'contacts-requests.html', +}) +export class AddonMessagesContactsRequestsPage implements OnInit, OnDestroy { + + loaded = false; + canLoadMore = false; + loadMoreError = false; + requests: AddonMessagesConversationMember[] = []; + selectedUserId?: number; + + protected memberInfoObserver: CoreEventObserver; + + constructor() { + + // Hide the "Would like to contact you" message when a contact request is confirmed. + this.memberInfoObserver = CoreEvents.on( + AddonMessagesProvider.MEMBER_INFO_CHANGED_EVENT, + (data) => { + if (data.contactRequestConfirmed || data.contactRequestDeclined) { + const index = this.requests.findIndex((request) => request.id == data.userId); + if (index >= 0) { + this.requests.splice(index, 1); + } + } + }, + + CoreSites.instance.getCurrentSiteId(), + ); + } + + /** + * Component loaded. + */ + async ngOnInit(): Promise { + try { + await this.fetchData(); + if (this.requests.length) { + this.selectUser(this.requests[0].id, true); + } + } finally { + this.loaded = true; + } + // Workaround for infinite scrolling. + // @todo this.content.resize(); + } + + /** + * Fetch contact requests. + * + * @param refresh True if we are refreshing contact requests, false if we are loading more. + * @return Promise resolved when done. + */ + async fetchData(refresh: boolean = false): Promise { + this.loadMoreError = false; + + const limitFrom = refresh ? 0 : this.requests.length; + + if (limitFrom === 0) { + // Always try to get latest data from server. + await AddonMessages.instance.invalidateContactRequestsCache(); + } + + try { + const result = await AddonMessages.instance.getContactRequests(limitFrom); + this.requests = refresh ? result.requests : this.requests.concat(result.requests); + this.canLoadMore = result.canLoadMore; + } catch (error) { + this.loadMoreError = true; + CoreDomUtils.instance.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingcontacts', true); + } + } + + /** + * Refresh contact requests. + * + * @param refresher Refresher. + * @return Promise resolved when done. + */ + async refreshData(refresher?: CustomEvent): Promise { + // Refresh the number of contacts requests to update badges. + AddonMessages.instance.refreshContactRequestsCount(); + + // No need to invalidate contact requests, we always try to get the latest. + await this.fetchData(true).finally(() => { + refresher?.detail.complete(); + }); + } + + /** + * Load more contact requests. + * + * @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading. + * @return Resolved when done. + */ + async loadMore(infiniteComplete?: () => void): Promise { + await this.fetchData().finally(() => { + infiniteComplete && infiniteComplete(); + }); + } + + /** + * Notify that a contact has been selected. + * + * @param userId User id. + * @param onInit Whether the contact is selected on initial load. + */ + selectUser(userId: number, onInit: boolean = false): void { + this.selectedUserId = userId; + + const data: AddonMessagesSplitViewLoadContactsEventData = { + userId, + onInit, + }; + + CoreEvents.trigger(AddonMessagesProvider.SPLIT_VIEW_LOAD_CONTACTS_EVENT, data); + + // @todo: Check if split view is visible before + CoreNavigator.instance.navigateToSitePath('discussion', { params : { userId } }); + } + + /** + * Component destroyed. + */ + ngOnDestroy(): void { + this.memberInfoObserver?.off(); + } + +} diff --git a/src/addons/messages/pages/contacts/contacts.html b/src/addons/messages/pages/contacts/contacts.html new file mode 100644 index 000000000..c224ccf4b --- /dev/null +++ b/src/addons/messages/pages/contacts/contacts.html @@ -0,0 +1,19 @@ + + + + + + {{ 'addon.messages.contacts' | translate }} + + + + + + + + + + + + + diff --git a/src/addons/messages/pages/contacts/contacts.module.ts b/src/addons/messages/pages/contacts/contacts.module.ts new file mode 100644 index 000000000..c49a9d810 --- /dev/null +++ b/src/addons/messages/pages/contacts/contacts.module.ts @@ -0,0 +1,64 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injector, NgModule } from '@angular/core'; +import { IonicModule } from '@ionic/angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { RouterModule, ROUTES, Routes } from '@angular/router'; +import { CommonModule } from '@angular/common'; + +import { CoreSharedModule } from '@/core/shared.module'; + +import { ADDON_MESSAGES_CONTACTS_ROUTES } from './messages-contacts-routing.module'; +import { AddonMessagesContactsPage } from './contacts.page'; +import { buildTabMainRoutes } from '@features/mainmenu/mainmenu-tab-routing.module'; +import { resolveModuleRoutes } from '@/app/app-routing.module'; + +const routes: Routes = [ + { + path: '', + component: AddonMessagesContactsPage, + }, +]; + +function buildRoutes(injector: Injector): Routes { + const routes = resolveModuleRoutes(injector, ADDON_MESSAGES_CONTACTS_ROUTES); + + return [ + ...buildTabMainRoutes(injector, { + path: '', + component: AddonMessagesContactsPage, + children: routes.children, + }), + ...routes.siblings, + ]; +} + +@NgModule({ + imports: [ + RouterModule.forChild(routes), + CommonModule, + IonicModule, + TranslateModule.forChild(), + CoreSharedModule, + ], + providers: [ + { provide: ROUTES, multi: true, useFactory: buildRoutes, deps: [Injector] }, + ], + declarations: [ + AddonMessagesContactsPage, + ], + exports: [RouterModule], +}) +export class AddonMessagesContactsPageModule {} diff --git a/src/addons/messages/pages/contacts/contacts.page.ts b/src/addons/messages/pages/contacts/contacts.page.ts new file mode 100644 index 000000000..279d83c6b --- /dev/null +++ b/src/addons/messages/pages/contacts/contacts.page.ts @@ -0,0 +1,134 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; +import { CoreSites } from '@services/sites'; +import { + AddonMessages, + AddonMessagesContactRequestCountEventData, + AddonMessagesProvider, + AddonMessagesSplitViewLoadContactsEventData, +} from '../../services/messages'; +import { CoreTab } from '@components/tabs/tabs'; +import { CoreNavigator } from '@services/navigator'; +// @todo import { CoreSplitViewComponent } from '@components/split-view/split-view'; + +/** + * Page that displays contacts and contact requests. + */ +@Component({ + selector: 'page-addon-messages-contacts', + templateUrl: 'contacts.html', +}) +export class AddonMessagesContactsPage implements OnInit, OnDestroy { + + // @todo @ViewChild(CoreSplitViewComponent) splitviewCtrl: CoreSplitViewComponent; + + protected contactsTab: CoreTab = { + id: 'contacts-confirmed', + class: '', + title: 'addon.messages.contacts', + icon: 'fas-address-book', + enabled: true, + page: 'main/messages/contacts/confirmed', + }; + + protected requestsTab: CoreTab = { + id: 'contact-requests', + class: '', + title: 'addon.messages.requests', + icon: 'fas-user-plus', + enabled: true, + page: 'main/messages/contacts/requests', + badge: '', + }; + + tabs: CoreTab[] = []; + + protected siteId: string; + protected contactRequestsCountObserver: CoreEventObserver; + protected splitViewObserver: CoreEventObserver; + protected selectedUserId?: number; // User id of the conversation opened in the split view. + + constructor() { + + this.tabs = [this.contactsTab, this.requestsTab]; + + this.siteId = CoreSites.instance.getCurrentSiteId(); + + // Update the contact requests badge. + this.contactRequestsCountObserver = CoreEvents.on( + AddonMessagesProvider.CONTACT_REQUESTS_COUNT_EVENT, + (data) => { + this.requestsTab.badge = data.count > 0 ? String(data.count) : ''; + }, + this.siteId, + ); + + // Update the contact requests badge. + this.splitViewObserver = CoreEvents.on( + AddonMessagesProvider.SPLIT_VIEW_LOAD_CONTACTS_EVENT, + (data) => { + this.selectUser(data.userId, data.onInit); + }, + this.siteId, + ); + } + + /** + * Page being initialized. + */ + ngOnInit(): void { + AddonMessages.instance.getContactRequestsCount(this.siteId); // Badge already updated by the observer. + } + + /** + * Navigate to the search page. + */ + gotoSearch(): void { + CoreNavigator.instance.navigateToSitePath('search'); + } + + /** + * Set the selected user and open the conversation in the split view if needed. + * + * @param userId Id of the selected user, undefined to use the last selected user in the tab. + * @param onInit Whether the contact was selected on initial load. + */ + selectUser(userId: number, onInit = false): void { + /* @todo if (userId == this.selectedUserId && this.splitviewCtrl.isOn()) { + // No user conversation to open or it is already opened. + return; + } + + if (onInit && !this.splitviewCtrl.isOn()) { + // Do not open a conversation by default when split view is not visible. + return; + }*/ + + this.selectedUserId = userId; + // @todo this.splitviewCtrl.push('AddonMessagesDiscussionPage', { userId }); + CoreNavigator.instance.navigateToSitePath('discussion', { params : { userId } }); + } + + /** + * Page destroyed. + */ + ngOnDestroy(): void { + this.contactRequestsCountObserver?.off(); + this.splitViewObserver?.off(); + } + +} diff --git a/src/addons/messages/pages/contacts/messages-contacts-routing.module.ts b/src/addons/messages/pages/contacts/messages-contacts-routing.module.ts new file mode 100644 index 000000000..5da763d85 --- /dev/null +++ b/src/addons/messages/pages/contacts/messages-contacts-routing.module.ts @@ -0,0 +1,33 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { InjectionToken, ModuleWithProviders, NgModule } from '@angular/core'; + +import { ModuleRoutesConfig } from '@/app/app-routing.module'; + +export const ADDON_MESSAGES_CONTACTS_ROUTES = new InjectionToken('ADDON_MESSAGES_CONTACTS_ROUTES'); + +@NgModule() +export class AddonMessagesContactsRoutingModule { + + static forChild(routes: ModuleRoutesConfig): ModuleWithProviders { + return { + ngModule: AddonMessagesContactsRoutingModule, + providers: [ + { provide: ADDON_MESSAGES_CONTACTS_ROUTES, multi: true, useValue: routes }, + ], + }; + } + +} diff --git a/src/addons/messages/services/messages.ts b/src/addons/messages/services/messages.ts index eeac460f9..fcc510658 100644 --- a/src/addons/messages/services/messages.ts +++ b/src/addons/messages/services/messages.ts @@ -43,6 +43,7 @@ export class AddonMessagesProvider { static readonly READ_CHANGED_EVENT = 'addon_messages_read_changed_event'; static readonly OPEN_CONVERSATION_EVENT = 'addon_messages_open_conversation_event'; // Notify a conversation should be opened. static readonly SPLIT_VIEW_LOAD_INDEX_EVENT = 'addon_messages_split_view_load_index_event'; // Used on 3.5 or lower. + static readonly SPLIT_VIEW_LOAD_CONTACTS_EVENT = 'addon_messages_split_view_load_contacts_event'; // Used on 3.6 or greater. static readonly UPDATE_CONVERSATION_LIST_EVENT = 'addon_messages_update_conversation_list_event'; static readonly MEMBER_INFO_CHANGED_EVENT = 'addon_messages_member_changed_event'; static readonly UNREAD_CONVERSATION_COUNTS_EVENT = 'addon_messages_unread_conversation_counts_event'; @@ -3639,3 +3640,11 @@ export type AddonMessagesSplitViewLoadIndexEventData = { onlyWithSplitView?: boolean; message?: number; }; + +/** + * Data sent by SPLIT_VIEW_LOAD_CONTACTS_EVENT event. Used on 3.6 or greater. + */ +export type AddonMessagesSplitViewLoadContactsEventData = { + userId: number; + onInit: boolean; +};