From 44552cfe3b1e9a43554f9cad55e8171a17eaab8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Tue, 26 Jan 2021 17:38:23 +0100 Subject: [PATCH] MOBILE-3631 messages: Fix split view on pages with tabs --- src/addons/messages/messages-lazy.module.ts | 39 +--- .../messages/pages/contacts-35/contacts.html | 70 +++--- .../pages/contacts-35/contacts.module.ts | 17 +- .../pages/contacts-35/contacts.page.ts | 33 ++- .../contacts-confirmed.html | 30 --- .../contacts-confirmed.module.ts | 45 ---- .../contacts-confirmed.page.ts | 162 -------------- .../contacts-requests/contacts-requests.html | 24 -- .../contacts-requests.module.ts | 45 ---- .../contacts-requests.page.ts | 160 ------------- .../messages/pages/contacts/contacts.html | 73 +++++- .../pages/contacts/contacts.module.ts | 25 +-- .../messages/pages/contacts/contacts.page.ts | 211 ++++++++++++++---- .../messages-contacts-routing.module.ts | 33 --- src/addons/messages/pages/contacts/tabs.scss | 48 ++++ .../pages/discussions-35/discussions.html | 118 ++++++---- .../discussions-35/discussions.module.ts | 17 +- .../pages/discussions-35/discussions.page.ts | 53 +++-- .../group-conversations.html | 4 +- .../group-conversations.page.ts | 1 - src/addons/messages/pages/index-35/index.html | 17 -- .../messages/pages/index-35/index.module.ts | 79 ------- .../messages/pages/index-35/index.page.ts | 104 --------- .../index-35/messages-index-routing.module.ts | 33 --- src/addons/messages/services/messages.ts | 19 -- src/theme/variables.scss | 31 +-- 26 files changed, 522 insertions(+), 969 deletions(-) delete mode 100644 src/addons/messages/pages/contacts-confirmed/contacts-confirmed.html delete mode 100644 src/addons/messages/pages/contacts-confirmed/contacts-confirmed.module.ts delete mode 100644 src/addons/messages/pages/contacts-confirmed/contacts-confirmed.page.ts delete mode 100644 src/addons/messages/pages/contacts-requests/contacts-requests.html delete mode 100644 src/addons/messages/pages/contacts-requests/contacts-requests.module.ts delete mode 100644 src/addons/messages/pages/contacts-requests/contacts-requests.page.ts delete mode 100644 src/addons/messages/pages/contacts/messages-contacts-routing.module.ts create mode 100644 src/addons/messages/pages/contacts/tabs.scss delete mode 100644 src/addons/messages/pages/index-35/index.html delete mode 100644 src/addons/messages/pages/index-35/index.module.ts delete mode 100644 src/addons/messages/pages/index-35/index.page.ts delete mode 100644 src/addons/messages/pages/index-35/messages-index-routing.module.ts diff --git a/src/addons/messages/messages-lazy.module.ts b/src/addons/messages/messages-lazy.module.ts index ca2bdf0af..52bb5f592 100644 --- a/src/addons/messages/messages-lazy.module.ts +++ b/src/addons/messages/messages-lazy.module.ts @@ -16,8 +16,6 @@ import { Injector, NgModule } from '@angular/core'; import { Route, 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'; import { AddonMessagesSettingsHandlerService } from './services/handlers/settings'; export const discussionRoute: Route = { @@ -30,7 +28,12 @@ function buildRoutes(injector: Injector): Routes { return [ { path: 'index', // 3.5 or lower. - loadChildren: () => import('./pages/index-35/index.module').then( m => m.AddonMessagesIndex35PageModule), + loadChildren: () => + import('./pages/discussions-35/discussions.module').then(m => m.AddonMessagesDiscussions35PageModule), + }, + { + path: 'contacts-35', // 3.5 or lower. + loadChildren: () => import('./pages/contacts-35/contacts.module').then(m => m.AddonMessagesContacts35PageModule), }, { path: 'group-conversations', // 3.6 or greater. @@ -60,37 +63,7 @@ function buildRoutes(injector: Injector): Routes { ]; } -// 3.5 or lower. -const indexTabRoutes: Routes = [ - { - path: 'discussions', - loadChildren: () => import('./pages/discussions-35/discussions.module').then(m => m.AddonMessagesDiscussions35PageModule), - }, - { - path: 'contacts', - loadChildren: () => import('./pages/contacts-35/contacts.module').then(m => m.AddonMessagesContacts35PageModule), - }, -]; - -// 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 }), - AddonMessagesContactsRoutingModule.forChild({ children: contactsTabRoutes }), - ], exports: [RouterModule], providers: [ { diff --git a/src/addons/messages/pages/contacts-35/contacts.html b/src/addons/messages/pages/contacts-35/contacts.html index 769e65391..7ab57b086 100644 --- a/src/addons/messages/pages/contacts-35/contacts.html +++ b/src/addons/messages/pages/contacts-35/contacts.html @@ -1,35 +1,49 @@ + + + + + + {{ 'addon.messages.contacts' | translate }} + + + + + + - - - + + + + - + - - + + - + - - - -

{{ 'addon.messages.type_' + contactType | translate }}

- {{ contacts[contactType].length }} -
- - - - -

{{ contact.fullname }}

-
+ + + +

{{ 'addon.messages.type_' + contactType | translate }}

+ {{ contacts[contactType].length }} +
+ + + + +

{{ contact.fullname }}

+
+
-
-
-
+ +
+
diff --git a/src/addons/messages/pages/contacts-35/contacts.module.ts b/src/addons/messages/pages/contacts-35/contacts.module.ts index 75fab619a..952cff0c6 100644 --- a/src/addons/messages/pages/contacts-35/contacts.module.ts +++ b/src/addons/messages/pages/contacts-35/contacts.module.ts @@ -17,6 +17,9 @@ import { IonicModule } from '@ionic/angular'; import { TranslateModule } from '@ngx-translate/core'; import { RouterModule, Routes } from '@angular/router'; import { CommonModule } from '@angular/common'; +import { conditionalRoutes } from '@/app/app-routing.module'; +import { discussionRoute } from '@addons/messages/messages-lazy.module'; +import { CoreScreen } from '@services/screen'; import { CoreSharedModule } from '@/core/shared.module'; import { CoreSearchComponentsModule } from '@features/search/components/components.module'; @@ -25,9 +28,21 @@ import { AddonMessagesContacts35Page } from './contacts.page'; const routes: Routes = [ { - path: '', + matcher: segments => { + const matches = CoreScreen.instance.isMobile ? segments.length === 0 : true; + + return matches ? { consumed: [] } : null; + }, component: AddonMessagesContacts35Page, + children: conditionalRoutes([ + { + path: '', + pathMatch: 'full', + }, + discussionRoute, + ], () => CoreScreen.instance.isTablet), }, + ...conditionalRoutes([discussionRoute], () => CoreScreen.instance.isMobile), ]; @NgModule({ diff --git a/src/addons/messages/pages/contacts-35/contacts.page.ts b/src/addons/messages/pages/contacts-35/contacts.page.ts index 72c298b23..c3fe92f3c 100644 --- a/src/addons/messages/pages/contacts-35/contacts.page.ts +++ b/src/addons/messages/pages/contacts-35/contacts.page.ts @@ -21,14 +21,15 @@ import { AddonMessagesSearchContactsContact, AddonMessagesGetContactsContact, AddonMessages, - AddonMessagesSplitViewLoadIndexEventData, AddonMessagesMemberInfoChangedEventData, } from '../../services/messages'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreApp } from '@services/app'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, Params } from '@angular/router'; import { Translate } from '@singletons'; +import { CoreScreen } from '@services/screen'; +import { CoreNavigator } from '@services/navigator'; /** * Page that displays the list of contacts. @@ -89,7 +90,15 @@ export class AddonMessagesContacts35Page implements OnInit, OnDestroy { */ ngOnInit(): void { this.route.queryParams.subscribe(async params => { - this.discussionUserId = params['discussionUserId'] || undefined; + const discussionUserId = params['discussionUserId'] + ? parseInt(params['discussionUserId'], 10) + : (params['userId'] ? parseInt(params['userId'], 10) : undefined); + + if (this.loaded && this.discussionUserId == discussionUserId) { + return; + } + + this.discussionUserId = discussionUserId; if (this.discussionUserId) { // There is a discussion to load, open the discussion in a new state. @@ -98,7 +107,7 @@ export class AddonMessagesContacts35Page implements OnInit, OnDestroy { try { await this.fetchData(); - if (!this.discussionUserId && this.hasContacts) { + if (!this.discussionUserId && this.hasContacts && CoreScreen.instance.isTablet) { let contact: AddonMessagesGetContactsContact | undefined; for (const x in this.contacts) { if (this.contacts[x].length > 0) { @@ -109,7 +118,7 @@ export class AddonMessagesContacts35Page implements OnInit, OnDestroy { if (contact) { // Take first and load it. - this.gotoDiscussion(contact.id, true); + this.gotoDiscussion(contact.id); } } } finally { @@ -235,16 +244,18 @@ export class AddonMessagesContacts35Page implements OnInit, OnDestroy { * Navigate to a particular discussion. * * @param discussionUserId Discussion Id to load. - * @param onlyWithSplitView Only go to Discussion if split view is on. */ - gotoDiscussion(discussionUserId: number, onlyWithSplitView: boolean = false): void { + gotoDiscussion(discussionUserId: number): void { this.discussionUserId = discussionUserId; - const params: AddonMessagesSplitViewLoadIndexEventData = { - discussion: discussionUserId, - onlyWithSplitView: onlyWithSplitView, + const params: Params = { + userId: discussionUserId, }; - CoreEvents.trigger(AddonMessagesProvider.SPLIT_VIEW_LOAD_INDEX_EVENT, params, this.siteId); + + const splitViewLoaded = CoreNavigator.instance.isSplitViewOutletLoaded('**/messages/contacts-35/discussion'); + const path = (splitViewLoaded ? '../' : '') + 'discussion'; + + CoreNavigator.instance.navigate(path, { params }); } /** diff --git a/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.html b/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.html deleted file mode 100644 index 8f2e6571c..000000000 --- a/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - -

- - - -

-
-
-
- - - - - - -
-
diff --git a/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.module.ts b/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.module.ts deleted file mode 100644 index 0506ffeb9..000000000 --- a/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.module.ts +++ /dev/null @@ -1,45 +0,0 @@ -// (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 deleted file mode 100644 index c15c4d635..000000000 --- a/src/addons/messages/pages/contacts-confirmed/contacts-confirmed.page.ts +++ /dev/null @@ -1,162 +0,0 @@ -// (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 { CoreScreen } from '@services/screen'; - -/** - * Component that displays the list of confirmed contacts. - */ -@Component({ - selector: 'addon-messages-confirmed-contacts', - templateUrl: 'contacts-confirmed.html', - styleUrls: ['../../messages-common.scss'], -}) -export class AddonMessagesContactsConfirmedPage implements OnInit, OnDestroy { - - loaded = false; - canLoadMore = false; - loadMoreError = false; - contacts: AddonMessagesConversationMember[] = []; - selectedUserId?: number; - - protected memberInfoObserver: CoreEventObserver; - - constructor() { - // 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 && CoreScreen.instance.isTablet) { - 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; - - CoreEvents.trigger( - AddonMessagesProvider.SPLIT_VIEW_LOAD_CONTACTS_EVENT, - { - userId, - onInit, - }, - ); - } - - /** - * 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 deleted file mode 100644 index 9a1deed81..000000000 --- a/src/addons/messages/pages/contacts-requests/contacts-requests.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - -

- {{ '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 deleted file mode 100644 index 00306f478..000000000 --- a/src/addons/messages/pages/contacts-requests/contacts-requests.module.ts +++ /dev/null @@ -1,45 +0,0 @@ -// (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 deleted file mode 100644 index 6927f62b1..000000000 --- a/src/addons/messages/pages/contacts-requests/contacts-requests.page.ts +++ /dev/null @@ -1,160 +0,0 @@ -// (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'; -import { CoreScreen } from '@services/screen'; - -/** - * Component that displays the list of contact requests. - */ -@Component({ - selector: 'addon-messages-contact-requests', - templateUrl: 'contacts-requests.html', - styleUrls: ['../../messages-common.scss'], -}) -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 && CoreScreen.instance.isTablet) { - 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); - } - - /** - * 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 index f1f945ca9..cf02631a1 100644 --- a/src/addons/messages/pages/contacts/contacts.html +++ b/src/addons/messages/pages/contacts/contacts.html @@ -15,6 +15,77 @@ - + + + + {{ 'addon.messages.contacts' | translate}} + + + + {{ 'addon.messages.requests' | translate}} + {{ requestsBadge }} + + + + +
+ + + + + + + + +

+ + + + +

+
+
+
+ + + + + + +
+
+
+ + + + + + + + + + +

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

+
+
+
+ + + + +
+
+
diff --git a/src/addons/messages/pages/contacts/contacts.module.ts b/src/addons/messages/pages/contacts/contacts.module.ts index 21da19fb4..b6ff6303c 100644 --- a/src/addons/messages/pages/contacts/contacts.module.ts +++ b/src/addons/messages/pages/contacts/contacts.module.ts @@ -12,22 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Injector, NgModule } from '@angular/core'; +import { NgModule } from '@angular/core'; import { IonicModule } from '@ionic/angular'; import { TranslateModule } from '@ngx-translate/core'; -import { RouterModule, ROUTES, Routes } from '@angular/router'; +import { RouterModule, Routes } from '@angular/router'; import { CommonModule } from '@angular/common'; -import { conditionalRoutes, resolveModuleRoutes } from '@/app/app-routing.module'; +import { conditionalRoutes } from '@/app/app-routing.module'; import { discussionRoute } from '@addons/messages/messages-lazy.module'; import { CoreScreen } from '@services/screen'; 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'; -// @todo mix both routes to get messages/contacts/requests/discussion and messages/contacts/confirmed/discussion working const routes: Routes = [ { matcher: segments => { @@ -47,19 +44,6 @@ const routes: Routes = [ ...conditionalRoutes([discussionRoute], () => CoreScreen.instance.isMobile), ]; -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), @@ -68,9 +52,6 @@ function buildRoutes(injector: Injector): Routes { TranslateModule.forChild(), CoreSharedModule, ], - providers: [ - { provide: ROUTES, multi: true, useFactory: buildRoutes, deps: [Injector] }, - ], declarations: [ AddonMessagesContactsPage, ], diff --git a/src/addons/messages/pages/contacts/contacts.page.ts b/src/addons/messages/pages/contacts/contacts.page.ts index d23a55ffc..32d3bdb7f 100644 --- a/src/addons/messages/pages/contacts/contacts.page.ts +++ b/src/addons/messages/pages/contacts/contacts.page.ts @@ -18,12 +18,14 @@ import { CoreSites } from '@services/sites'; import { AddonMessages, AddonMessagesContactRequestCountEventData, + AddonMessagesConversationMember, + AddonMessagesMemberInfoChangedEventData, AddonMessagesProvider, - AddonMessagesSplitViewLoadContactsEventData, } from '../../services/messages'; -import { CoreTab } from '@components/tabs/tabs'; import { CoreNavigator } from '@services/navigator'; import { CoreScreen } from '@services/screen'; +import { CoreDomUtils } from '@services/utils/dom'; +import { IonRefresher } from '@ionic/angular'; /** * Page that displays contacts and contact requests. @@ -31,56 +33,71 @@ import { CoreScreen } from '@services/screen'; @Component({ selector: 'page-addon-messages-contacts', templateUrl: 'contacts.html', + styleUrls: [ + 'tabs.scss', + '../../messages-common.scss', + ], }) export class AddonMessagesContactsPage implements OnInit, OnDestroy { - protected contactsTab: CoreTab = { - id: 'contacts-confirmed', - class: '', - title: 'addon.messages.contacts', - icon: 'fas-address-book', - enabled: true, - page: '/main/messages/contacts/confirmed', - }; + selected = 'confirmed'; + requestsBadge = ''; + selectedUserId?: number; // User id of the conversation opened in the split view. - protected requestsTab: CoreTab = { - id: 'contact-requests', - class: '', - title: 'addon.messages.requests', - icon: 'fas-user-plus', - enabled: true, - page: '/main/messages/contacts/requests', - badge: '', - }; + confirmedLoaded = false; + confirmedCanLoadMore = false; + confirmedLoadMoreError = false; + confirmedContacts: AddonMessagesConversationMember[] = []; - tabs: CoreTab[] = []; + requestsLoaded = false; + requestsCanLoadMore = false; + requestsLoadMoreError = false; + requests: AddonMessagesConversationMember[] = []; protected siteId: string; protected contactRequestsCountObserver: CoreEventObserver; - protected splitViewObserver: CoreEventObserver; - protected selectedUserId?: number; // User id of the conversation opened in the split view. + protected memberInfoObserver: CoreEventObserver; + 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.requestsBadge = data.count > 0 ? String(data.count) : ''; }, this.siteId, ); - // Update the contact requests badge. - this.splitViewObserver = CoreEvents.on( - AddonMessagesProvider.SPLIT_VIEW_LOAD_CONTACTS_EVENT, + // Update block status of a user. + this.memberInfoObserver = CoreEvents.on( + AddonMessagesProvider.MEMBER_INFO_CHANGED_EVENT, (data) => { - this.selectUser(data.userId, data.onInit); + if (data.userBlocked || data.userUnblocked) { + const user = this.confirmedContacts.find((user) => user.id == data.userId); + if (user) { + user.isblocked = !!data.userBlocked; + } + } else if (data.contactRemoved) { + const index = this.confirmedContacts.findIndex((contact) => contact.id == data.userId); + if (index >= 0) { + this.confirmedContacts.splice(index, 1); + } + } else if (data.contactRequestConfirmed) { + this.refreshData(); + } + + 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(), ); } @@ -88,8 +105,123 @@ export class AddonMessagesContactsPage implements OnInit, OnDestroy { /** * Page being initialized. */ - ngOnInit(): void { + async ngOnInit(): Promise { AddonMessages.instance.getContactRequestsCount(this.siteId); // Badge already updated by the observer. + + if (this.selected == 'confirmed') { + try { + + await this.confirmedFetchData(); + if (this.confirmedContacts.length && CoreScreen.instance.isTablet) { + this.selectUser(this.confirmedContacts[0].id, true); + } + } finally { + this.confirmedLoaded = true; + } + } else { + try { + await this.requestsFetchData(); + if (this.requests.length && CoreScreen.instance.isTablet) { + this.selectUser(this.requests[0].id, true); + } + } finally { + this.requestsLoaded = true; + } + } + } + + /** + * Fetch contacts. + * + * @param refresh True if we are refreshing contacts, false if we are loading more. + * @return Promise resolved when done. + */ + async confirmedFetchData(refresh: boolean = false): Promise { + this.confirmedLoadMoreError = false; + + const limitFrom = refresh ? 0 : this.confirmedContacts.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.confirmedContacts = refresh ? result.contacts : this.confirmedContacts.concat(result.contacts); + this.confirmedCanLoadMore = result.canLoadMore; + } catch (error) { + this.confirmedLoadMoreError = true; + CoreDomUtils.instance.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingcontacts', true); + } + } + + /** + * Fetch contact requests. + * + * @param refresh True if we are refreshing contact requests, false if we are loading more. + * @return Promise resolved when done. + */ + async requestsFetchData(refresh: boolean = false): Promise { + this.requestsLoadMoreError = 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.requestsCanLoadMore = result.canLoadMore; + } catch (error) { + this.requestsLoadMoreError = true; + CoreDomUtils.instance.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingcontacts', true); + } + } + + /** + * Refresh contacts or requests. + * + * @param refresher Refresher. + * @return Promise resolved when done. + */ + async refreshData(refresher?: CustomEvent): Promise { + try { + if (this.selected == 'confirmed') { + // No need to invalidate contacts, we always try to get the latest. + await this.confirmedFetchData(true); + } else { + // 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.requestsFetchData(true); + } + } finally { + refresher?.detail.complete(); + } + } + + /** + * Load more contacts or requests. + * + * @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading. + * @return Resolved when done. + */ + async loadMore(infiniteComplete?: () => void): Promise { + try { + if (this.selected == 'confirmed') { + // No need to invalidate contacts, we always try to get the latest. + await this.confirmedFetchData(); + } else { + await this.requestsFetchData(); + } + } finally { + infiniteComplete && infiniteComplete(); + } } /** @@ -99,6 +231,14 @@ export class AddonMessagesContactsPage implements OnInit, OnDestroy { CoreNavigator.instance.navigateToSitePath('search'); } + selectTab(selected: string): void { + this.selected = selected; + + if ((this.selected == 'confirmed' && !this.confirmedLoaded) || (this.selected != 'confirmed' && !this.requestsLoaded)) { + this.ngOnInit(); + } + } + /** * Set the selected user and open the conversation in the split view if needed. * @@ -118,14 +258,8 @@ export class AddonMessagesContactsPage implements OnInit, OnDestroy { this.selectedUserId = userId; - // @todo it does not seem to work load anything. - let path = 'discussion'; - if (CoreScreen.instance.isMobile) { - path = '../../' + path; - } else { - const splitViewLoaded = CoreNavigator.instance.isSplitViewOutletLoaded('**/messages/contacts/**/discussion'); - path = (splitViewLoaded ? '../' : '') + path; - } + const splitViewLoaded = CoreNavigator.instance.isSplitViewOutletLoaded('**/messages/contacts/discussion'); + const path = (splitViewLoaded ? '../' : '') + 'discussion'; CoreNavigator.instance.navigate(path, { params : { userId } }); } @@ -135,7 +269,6 @@ export class AddonMessagesContactsPage implements OnInit, OnDestroy { */ 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 deleted file mode 100644 index 5da763d85..000000000 --- a/src/addons/messages/pages/contacts/messages-contacts-routing.module.ts +++ /dev/null @@ -1,33 +0,0 @@ -// (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/pages/contacts/tabs.scss b/src/addons/messages/pages/contacts/tabs.scss new file mode 100644 index 000000000..8bb0948a5 --- /dev/null +++ b/src/addons/messages/pages/contacts/tabs.scss @@ -0,0 +1,48 @@ +:host { + ion-tab-bar.core-tabs-bar { + position: relative; + width: 100%; + background: var(--core-tabs-background); + color: var(--core-tab-color); + -webkit-filter: drop-shadow(0px 3px 3px rgba(var(--drop-shadow))); + filter: drop-shadow(0px 3px 3px rgba(var(--drop-shadow))); + border: 0; + + ion-row { + width: 100%; + } + + .tab-slide { + border-bottom: 2px solid transparent; + min-width: 100px; + min-height: 56px; + cursor: pointer; + overflow: hidden; + display: flex; + align-items: center; + justify-content: center; + padding: 0; + margin-bottom: 1px; + + ion-label { + font-size: 16px; + font-weight: 400; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + word-wrap: break-word; + max-width: 100%; + line-height: 1.2em; + margin: 16px auto; + } + + &[aria-selected=true] { + color: var(--core-tab-border-color-active); + border-bottom-color: var(--core-tab-color-active); + ion-tab-button { + color: var(--core-tab-border-color-active); + } + } + } + } +} diff --git a/src/addons/messages/pages/discussions-35/discussions.html b/src/addons/messages/pages/discussions-35/discussions.html index b0a2316b8..64d6e92a5 100644 --- a/src/addons/messages/pages/discussions-35/discussions.html +++ b/src/addons/messages/pages/discussions-35/discussions.html @@ -1,56 +1,78 @@ + + + + + + {{ 'addon.messages.messages' | translate }} + + + + + + - - - + + + + - + - + - - - -

{{ 'core.searchresults' | translate }}

-
- {{ search.results.length }} -
- - - -

{{ result.fullname }}

-

-
-
-
+ - - - - -

{{ discussion.fullname }}

- - - {{discussion.message!.timecreated / 1000 | coreDateDayOrTime}} - -

- - -

-
-
-
+ + +

{{ 'addon.messages.contacts' | translate }}

+
- + + + +

{{ 'core.searchresults' | translate }}

+
+ {{ search.results.length }} +
+ + + +

{{ result.fullname }}

+

+
+
+
+ + + + +

{{ discussion.fullname }}

+ + + {{discussion.message!.timecreated / 1000 | coreDateDayOrTime}} + +

+ + +

+
+
+
+
- -
+ + + +
+
diff --git a/src/addons/messages/pages/discussions-35/discussions.module.ts b/src/addons/messages/pages/discussions-35/discussions.module.ts index 414211e23..99ef467a3 100644 --- a/src/addons/messages/pages/discussions-35/discussions.module.ts +++ b/src/addons/messages/pages/discussions-35/discussions.module.ts @@ -17,6 +17,9 @@ import { IonicModule } from '@ionic/angular'; import { TranslateModule } from '@ngx-translate/core'; import { RouterModule, Routes } from '@angular/router'; import { CommonModule } from '@angular/common'; +import { CoreScreen } from '@services/screen'; +import { conditionalRoutes } from '@/app/app-routing.module'; +import { discussionRoute } from '@addons/messages/messages-lazy.module'; import { CoreSharedModule } from '@/core/shared.module'; import { CoreSearchComponentsModule } from '@features/search/components/components.module'; @@ -25,9 +28,21 @@ import { AddonMessagesDiscussions35Page } from './discussions.page'; const routes: Routes = [ { - path: '', + matcher: segments => { + const matches = CoreScreen.instance.isMobile ? segments.length === 0 : true; + + return matches ? { consumed: [] } : null; + }, component: AddonMessagesDiscussions35Page, + children: conditionalRoutes([ + { + path: '', + pathMatch: 'full', + }, + discussionRoute, + ], () => CoreScreen.instance.isTablet), }, + ...conditionalRoutes([discussionRoute], () => CoreScreen.instance.isMobile), ]; @NgModule({ diff --git a/src/addons/messages/pages/discussions-35/discussions.page.ts b/src/addons/messages/pages/discussions-35/discussions.page.ts index 411ae91b7..562aefbcb 100644 --- a/src/addons/messages/pages/discussions-35/discussions.page.ts +++ b/src/addons/messages/pages/discussions-35/discussions.page.ts @@ -22,17 +22,18 @@ import { AddonMessagesNewMessagedEventData, AddonMessagesProvider, AddonMessagesReadChangedEventData, - AddonMessagesSplitViewLoadIndexEventData, } from '../../services/messages'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; import { CoreApp } from '@services/app'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, Params } from '@angular/router'; import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications'; import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; import { Subscription } from 'rxjs'; import { Translate, Platform } from '@singletons'; import { IonRefresher } from '@ionic/angular'; +import { CoreNavigator } from '@services/navigator'; +import { CoreScreen } from '@services/screen'; /** * Page that displays the list of discussions. @@ -46,7 +47,6 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy { protected newMessagesObserver: CoreEventObserver; protected readChangedObserver: CoreEventObserver; - protected cronObserver: CoreEventObserver; protected appResumeSubscription: Subscription; protected pushObserver: Subscription; protected loadingMessages: string; @@ -121,11 +121,6 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy { this.siteId, ); - // Update unread conversation counts. - this.cronObserver = CoreEvents.on(AddonMessagesProvider.UNREAD_CONVERSATION_COUNTS_EVENT, () => { - AddonMessages.instance.refreshUnreadConversationCounts(this.siteId); - }, this.siteId); - // Refresh the view when the app is resumed. this.appResumeSubscription = Platform.instance.resume.subscribe(() => { if (!this.loaded) { @@ -152,7 +147,15 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy { */ ngOnInit(): void { this.route.queryParams.subscribe(async params => { - this.discussionUserId = params['discussionUserId'] || undefined; + const discussionUserId = params['discussionUserId'] + ? parseInt(params['discussionUserId'], 10) + : (params['userId'] ? parseInt(params['userId'], 10) : undefined); + + if (this.loaded && this.discussionUserId == discussionUserId) { + return; + } + + this.discussionUserId = discussionUserId; if (this.discussionUserId) { // There is a discussion to load, open the discussion in a new state. @@ -161,9 +164,9 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy { await this.fetchData(); - if (!this.discussionUserId && this.discussions.length > 0) { + if (!this.discussionUserId && this.discussions.length > 0 && CoreScreen.instance.isTablet) { // Take first and load it. - this.gotoDiscussion(this.discussions[0].message!.user, undefined, true); + this.gotoDiscussion(this.discussions[0].message!.user); } }); } @@ -267,17 +270,34 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy { * @param messageId Message to scroll after loading the discussion. Used when searching. * @param onlyWithSplitView Only go to Discussion if split view is on. */ - gotoDiscussion(discussionUserId: number, messageId?: number, onlyWithSplitView: boolean = false): void { + gotoDiscussion(discussionUserId: number, messageId?: number): void { this.discussionUserId = discussionUserId; - const params: AddonMessagesSplitViewLoadIndexEventData = { - discussion: discussionUserId, - onlyWithSplitView: onlyWithSplitView, + const params: Params = { + userId: discussionUserId, }; + if (messageId) { params.message = messageId; } - CoreEvents.trigger(AddonMessagesProvider.SPLIT_VIEW_LOAD_INDEX_EVENT, params, this.siteId); + + const splitViewLoaded = CoreNavigator.instance.isSplitViewOutletLoaded('**/messages/index/discussion'); + const path = (splitViewLoaded ? '../' : '') + 'discussion'; + + CoreNavigator.instance.navigate(path, { params }); + } + + /** + * Navigate to contacts view. + */ + gotoContacts(): void { + const params: Params = {}; + + if (CoreScreen.instance.isTablet && this.discussionUserId) { + params.discussionUserId = this.discussionUserId; + } + + CoreNavigator.instance.navigateToSitePath('contacts-35', { params }); } /** @@ -286,7 +306,6 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy { ngOnDestroy(): void { this.newMessagesObserver?.off(); this.readChangedObserver?.off(); - this.cronObserver?.off(); this.appResumeSubscription?.unsubscribe(); this.pushObserver?.unsubscribe(); } diff --git a/src/addons/messages/pages/group-conversations/group-conversations.html b/src/addons/messages/pages/group-conversations/group-conversations.html index d1dd2a68d..a1701348d 100644 --- a/src/addons/messages/pages/group-conversations/group-conversations.html +++ b/src/addons/messages/pages/group-conversations/group-conversations.html @@ -25,8 +25,8 @@ - +

{{ 'addon.messages.contacts' | translate }}

{{contactRequestsCount}} diff --git a/src/addons/messages/pages/group-conversations/group-conversations.page.ts b/src/addons/messages/pages/group-conversations/group-conversations.page.ts index 69e8df449..932a23e1d 100644 --- a/src/addons/messages/pages/group-conversations/group-conversations.page.ts +++ b/src/addons/messages/pages/group-conversations/group-conversations.page.ts @@ -511,7 +511,6 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy { */ gotoContacts(): void { CoreNavigator.instance.navigateToSitePath('contacts'); - } /** diff --git a/src/addons/messages/pages/index-35/index.html b/src/addons/messages/pages/index-35/index.html deleted file mode 100644 index 120f1573c..000000000 --- a/src/addons/messages/pages/index-35/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - {{ 'addon.messages.messages' | translate }} - - - - - - - - - - - diff --git a/src/addons/messages/pages/index-35/index.module.ts b/src/addons/messages/pages/index-35/index.module.ts deleted file mode 100644 index c10ae8264..000000000 --- a/src/addons/messages/pages/index-35/index.module.ts +++ /dev/null @@ -1,79 +0,0 @@ -// (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 { conditionalRoutes, resolveModuleRoutes } from '@/app/app-routing.module'; -import { discussionRoute } from '@addons/messages/messages-lazy.module'; -import { CoreScreen } from '@services/screen'; - -import { CoreSharedModule } from '@/core/shared.module'; - -import { AddonMessagesIndex35Page } from './index.page'; -import { ADDON_MESSAGES_INDEX_ROUTES } from './messages-index-routing.module'; -import { buildTabMainRoutes } from '@features/mainmenu/mainmenu-tab-routing.module'; - -// @todo mix both routes to get messages/index/discussions/discussion and messages/index/contacts/discussion working -const routes: Routes = [ - { - matcher: segments => { - const matches = CoreScreen.instance.isMobile ? segments.length === 0 : true; - - return matches ? { consumed: [] } : null; - }, - component: AddonMessagesIndex35Page, - children: conditionalRoutes([ - { - path: '', - pathMatch: 'full', - }, - discussionRoute, - ], () => CoreScreen.instance.isTablet), - }, - ...conditionalRoutes([discussionRoute], () => CoreScreen.instance.isMobile), -]; - -function buildRoutes(injector: Injector): Routes { - const routes = resolveModuleRoutes(injector, ADDON_MESSAGES_INDEX_ROUTES); - - return [ - ...buildTabMainRoutes(injector, { - path: '', - component: AddonMessagesIndex35Page, - 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: [ - AddonMessagesIndex35Page, - ], - exports: [RouterModule], -}) -export class AddonMessagesIndex35PageModule {} diff --git a/src/addons/messages/pages/index-35/index.page.ts b/src/addons/messages/pages/index-35/index.page.ts deleted file mode 100644 index 08b5c87d6..000000000 --- a/src/addons/messages/pages/index-35/index.page.ts +++ /dev/null @@ -1,104 +0,0 @@ -// (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 } from '@angular/core'; -import { CoreEventObserver, CoreEvents } from '@singletons/events'; -import { CoreSites } from '@services/sites'; -import { CoreTab } from '@components/tabs/tabs'; -import { Params } from '@angular/router'; -import { AddonMessagesProvider, AddonMessagesSplitViewLoadIndexEventData } from '../../services/messages'; -import { CoreNavigator } from '@services/navigator'; -import { CoreScreen } from '@services/screen'; - -/** - * Page that displays the messages index page. - */ -@Component({ - selector: 'page-addon-messages-index', - templateUrl: 'index.html', -}) -export class AddonMessagesIndex35Page implements OnDestroy { - - tabs: CoreTab[] = [ - { - id: 'discussions-35', - class: '', - title: 'addon.messages.messages', - icon: 'fas-comments', - enabled: true, - page: 'main/messages/index/discussions', - }, - { - id: 'contacts-35', - class: '', - title: 'addon.messages.contacts', - icon: 'fas-address-book', - enabled: true, - page: 'main/messages/index/contacts', - }, - ]; - - protected loadSplitViewObserver?: CoreEventObserver; - protected siteId: string; - - constructor() { - this.siteId = CoreSites.instance.getCurrentSiteId(); - - // Update split view or navigate. - this.loadSplitViewObserver = CoreEvents.on( - AddonMessagesProvider.SPLIT_VIEW_LOAD_INDEX_EVENT, - (data) => { - if (data.discussion && (CoreScreen.instance.isTablet || !data.onlyWithSplitView)) { - this.gotoDiscussion(data.discussion, data.message); - } - }, - ); - } - - /** - * Navigate to a particular discussion. - * - * @param discussionUserId Discussion Id to load. - * @param messageId Message to scroll after loading the discussion. Used when searching. - */ - gotoDiscussion(discussionUserId: number, messageId?: number): void { - const params: Params = { - userId: discussionUserId, - }; - - if (messageId) { - params.message = messageId; - } - - let path = 'discussion'; - if (CoreScreen.instance.isMobile) { - path = '../../' + path; - } else { - const splitViewLoaded = CoreNavigator.instance.isSplitViewOutletLoaded('**/messages/index/**/discussion'); - path = (splitViewLoaded ? '../' : '') + path; - } - - CoreNavigator.instance.navigate(path, { params }); - - } - - - /** - * Page destroyed. - */ - ngOnDestroy(): void { - this.loadSplitViewObserver?.off(); - } - -} diff --git a/src/addons/messages/pages/index-35/messages-index-routing.module.ts b/src/addons/messages/pages/index-35/messages-index-routing.module.ts deleted file mode 100644 index fe0972485..000000000 --- a/src/addons/messages/pages/index-35/messages-index-routing.module.ts +++ /dev/null @@ -1,33 +0,0 @@ -// (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_INDEX_ROUTES = new InjectionToken('ADDON_MESSAGES_INDEX_ROUTES'); - -@NgModule() -export class AddonMessagesIndexRoutingModule { - - static forChild(routes: ModuleRoutesConfig): ModuleWithProviders { - return { - ngModule: AddonMessagesIndexRoutingModule, - providers: [ - { provide: ADDON_MESSAGES_INDEX_ROUTES, multi: true, useValue: routes }, - ], - }; - } - -} diff --git a/src/addons/messages/services/messages.ts b/src/addons/messages/services/messages.ts index 9d8fc2123..d47ac63d0 100644 --- a/src/addons/messages/services/messages.ts +++ b/src/addons/messages/services/messages.ts @@ -42,8 +42,6 @@ export class AddonMessagesProvider { static readonly NEW_MESSAGE_EVENT = 'addon_messages_new_message_event'; 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'; @@ -3696,23 +3694,6 @@ export type AddonMessagesMemberInfoChangedEventData = { contactRemoved?: boolean; }; -/** - * Data sent by SPLIT_VIEW_LOAD_INDEX_EVENT event. Used on 3.5 or lower. - */ -export type AddonMessagesSplitViewLoadIndexEventData = { - discussion: number; - 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; -}; - /** * Data sent by READ_CHANGED_EVENT event. */ diff --git a/src/theme/variables.scss b/src/theme/variables.scss index 30ab4fcc5..5c7858c5b 100644 --- a/src/theme/variables.scss +++ b/src/theme/variables.scss @@ -135,14 +135,21 @@ } } + --core-tabs-background: var(--custom-tabs-background, var(--white)); + --core-tab-background: var(--custom-tab-background, var(--core-tabs-background)); + --core-tab-color: var(--custom-tab-color, var(--gray-dark)); + --core-tab-border-color: var(--custom-tab-border-color, var(--gray)); + --core-tab-color-active: var(--custom-tab-color-active, var(--core-color)); + --core-tab-border-color-active: var(--custom-tab-border-color-active, var(--core-color)); + core-tabs { - --background: var(--custom-tabs-background, var(--white)); + --background: var(--core-tabs-background); ion-slide { - --background: var(--custom-tab-background, var(--white)); - --color: var(--custom-tab-background, var(--gray-dark)); - --border-color: var(--custom-tab-border-color, var(--gray)); - --color-active: var(--custom-tab-color-active, var(--color)); - --border-color-active: var(--custom-tab-border-color-active, var(--core-color)); + --background: var(--core-tab-background); + --color: var(--core-tab-color); + --border-color: var(--core-tab-border-colo); + --color-active: var(--core-tab-color-active); + --border-color-active: var(--core-tab-border-color-active); } } @@ -276,14 +283,10 @@ --contrast-background: var(--ion-background-color); } - core-tabs { - --background: var(--custom-tabs-background, #3a3a3a); - ion-slide { - --background: var(--custom-tab-background, #3a3a3a); - --color: var(--custom-tab-background, var(--white)); - --border-color: var(--custom-tab-border-color, var(--gray-light)); - } - } + --core-tabs-background: var(--custom-tabs-background, #3a3a3a); + --core-tab-background: var(--custom-tab-background, #3a3a3a); + --core-tab-color: var(--custom-tab-color, var(--white)); + --core-tab-border-color: var(--custom-tab-border-color, var(--gray-light)); core-progress-bar { --text-color: var(--custom-progress-text-color, var(--gray-lighter));