From 481351c6821628e2b7570271490cdd33d5cfe96c Mon Sep 17 00:00:00 2001 From: Albert Gasset Date: Fri, 7 Dec 2018 13:06:00 +0100 Subject: [PATCH] MOBILE-2620 messages: Combined search page --- src/addon/messages/pages/search/search.html | 56 ++++ .../messages/pages/search/search.module.ts | 37 +++ src/addon/messages/pages/search/search.ts | 244 ++++++++++++++++++ 3 files changed, 337 insertions(+) create mode 100644 src/addon/messages/pages/search/search.html create mode 100644 src/addon/messages/pages/search/search.module.ts create mode 100644 src/addon/messages/pages/search/search.ts diff --git a/src/addon/messages/pages/search/search.html b/src/addon/messages/pages/search/search.html new file mode 100644 index 000000000..1acad9cb8 --- /dev/null +++ b/src/addon/messages/pages/search/search.html @@ -0,0 +1,56 @@ + + + {{ 'addon.messages.searchcombined' | translate }} + + + + + + + + + + + + + + + + + + + + + + + + {{ item.titleString | translate }} + + {{ item.emptyString | translate }} + + + + + +

+ + +

+ + {{result.lastmessagedate | coreDateDayOrTime}} + + +
+ + + +
+ +
+
+ +
+
+
\ No newline at end of file diff --git a/src/addon/messages/pages/search/search.module.ts b/src/addon/messages/pages/search/search.module.ts new file mode 100644 index 000000000..c7513f688 --- /dev/null +++ b/src/addon/messages/pages/search/search.module.ts @@ -0,0 +1,37 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { IonicPageModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { AddonMessagesSearchPage } from './search'; +import { CoreComponentsModule } from '@components/components.module'; +import { CoreDirectivesModule } from '@directives/directives.module'; +import { CorePipesModule } from '@pipes/pipes.module'; +import { AddonMessagesComponentsModule } from '../../components/components.module'; + +@NgModule({ + declarations: [ + AddonMessagesSearchPage, + ], + imports: [ + CoreComponentsModule, + CoreDirectivesModule, + CorePipesModule, + AddonMessagesComponentsModule, + IonicPageModule.forChild(AddonMessagesSearchPage), + TranslateModule.forChild() + ], +}) +export class AddonMessagesSearchPageModule {} diff --git a/src/addon/messages/pages/search/search.ts b/src/addon/messages/pages/search/search.ts new file mode 100644 index 000000000..205d10427 --- /dev/null +++ b/src/addon/messages/pages/search/search.ts @@ -0,0 +1,244 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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, ViewChild } from '@angular/core'; +import { IonicPage } from 'ionic-angular'; +import { CoreEventsProvider } from '@providers/events'; +import { CoreSitesProvider } from '@providers/sites'; +import { AddonMessagesProvider } from '../../providers/messages'; +import { CoreSplitViewComponent } from '@components/split-view/split-view'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; +import { CoreAppProvider } from '@providers/app'; + +/** + * Page for searching users. + */ +@IonicPage({ segment: 'addon-messages-search' }) +@Component({ + selector: 'page-addon-messages-search', + templateUrl: 'search.html', +}) +export class AddonMessagesSearchPage implements OnDestroy { + + disableSearch = false; + displaySearching = false; + displayResults = false; + query = ''; + contacts = { + type: 'contacts', + titleString: 'addon.messages.contacts', + emptyString: 'addon.messages.searchnocontactsfound', + results: [], + canLoadMore: false, + loadingMore: false + }; + nonContacts = { + type: 'noncontacts', + titleString: 'addon.messages.noncontacts', + emptyString: 'addon.messages.searchnononcontactsfound', + results: [], + canLoadMore: false, + loadingMore: false + }; + messages = { + type: 'messages', + titleString: 'addon.messages.messages', + emptyString: 'addon.messages.searchnomessagesfound', + results: [], + canLoadMore: false, + loadingMore: false, + loadMoreError: false + }; + selectedUserId = null; + + protected memberInfoObserver; + + @ViewChild(CoreSplitViewComponent) splitviewCtrl: CoreSplitViewComponent; + + constructor(private appProvider: CoreAppProvider, private domUtils: CoreDomUtilsProvider, eventsProvider: CoreEventsProvider, + sitesProvider: CoreSitesProvider, private messagesProvider: AddonMessagesProvider) { + + // Update block status of a user. + this.memberInfoObserver = eventsProvider.on(AddonMessagesProvider.MEMBER_INFO_CHANGED_EVENT, (data) => { + if (!data.userBlocked && !data.userUnblocked) { + // The block status has not changed, ignore. + return; + } + + const contact = this.contacts.results.find((user) => user.id == data.userId); + if (contact) { + contact.isblocked = data.userBlocked; + } else { + const nonContact = this.nonContacts.results.find((user) => user.id == data.userId); + if (nonContact) { + nonContact.isblocked = data.userBlocked; + } + } + + this.messages.results.forEach((message: any): void => { + if (message.userid == data.userId) { + message.isblocked = data.userBlocked; + } + }); + }, sitesProvider.getCurrentSiteId()); + } + + /** + * Clear search. + */ + clearSearch(): void { + this.query = ''; + this.displayResults = false; + this.splitviewCtrl.emptyDetails(); + } + + /** + * Start a new search or load more results. + * + * @param {string} query Text to search for. + * @param {strings} loadMore Load more contacts, noncontacts or messages. If undefined, start a new search. + * @param {any} [infiniteComplete] Infinite scroll complete function. Only used from core-infinite-loading. + * @return {Promise} Resolved when done. + */ + search(query: string, loadMore?: 'contacts' | 'noncontacts' | 'messages', infiniteComplete?: any): Promise { + this.appProvider.closeKeyboard(); + + this.query = query; + this.disableSearch = true; + this.displaySearching = !loadMore; + + const promises = []; + let newContacts = []; + let newNonContacts = []; + let newMessages = []; + let canLoadMoreContacts = false; + let canLoadMoreNonContacts = false; + let canLoadMoreMessages = false; + + if (!loadMore || loadMore == 'contacts' || loadMore == 'noncontacts') { + const limitNum = loadMore ? AddonMessagesProvider.LIMIT_SEARCH : AddonMessagesProvider.LIMIT_INITIAL_USER_SEARCH; + let limitFrom = 0; + if (loadMore == 'contacts') { + limitFrom = this.contacts.results.length; + this.contacts.loadingMore = true; + } else if (loadMore == 'noncontacts') { + limitFrom = this.nonContacts.results.length; + this.nonContacts.loadingMore = true; + } + + promises.push( + this.messagesProvider.searchUsers(query, limitFrom, limitNum).then((result) => { + if (!loadMore || loadMore == 'contacts') { + newContacts = result.contacts; + canLoadMoreContacts = result.canLoadMoreContacts; + } + if (!loadMore || loadMore == 'noncontacts') { + newNonContacts = result.nonContacts; + canLoadMoreNonContacts = result.canLoadMoreNonContacts; + } + }) + ); + } + + if (!loadMore || loadMore == 'messages') { + let limitFrom = 0; + if (loadMore == 'messages') { + limitFrom = this.messages.results.length; + this.messages.loadingMore = true; + } + + promises.push( + this.messagesProvider.searchMessages(query, undefined, limitFrom).then((result) => { + newMessages = result.messages; + canLoadMoreMessages = result.canLoadMore; + }) + ); + } + + return Promise.all(promises).then(() => { + if (!loadMore) { + this.contacts.results = []; + this.nonContacts.results = []; + this.messages.results = []; + } + + this.displayResults = true; + + if (!loadMore || loadMore == 'contacts') { + this.contacts.results.push(...newContacts); + this.contacts.canLoadMore = canLoadMoreContacts; + } + + if (!loadMore || loadMore == 'noncontacts') { + this.nonContacts.results.push(...newNonContacts); + this.nonContacts.canLoadMore = canLoadMoreNonContacts; + } + + if (!loadMore || loadMore == 'messages') { + this.messages.results.push(...newMessages); + this.messages.canLoadMore = canLoadMoreMessages; + this.messages.loadMoreError = false; + } + + if (!loadMore) { + if (this.contacts.results.length > 0) { + this.openDiscussion(this.contacts.results[0].id, true); + } else if (this.nonContacts.results.length > 0) { + this.openDiscussion(this.nonContacts.results[0].id, true); + } else if (this.messages.results.length > 0) { + this.openDiscussion(this.messages.results[0].userid, true); + } + } + }).catch((error) => { + this.domUtils.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingusers', true); + + if (loadMore == 'messages') { + this.messages.loadMoreError = true; + } + }).finally(() => { + this.disableSearch = false; + this.displaySearching = false; + + if (loadMore == 'contacts') { + this.contacts.loadingMore = false; + } else if (loadMore == 'noncontacts') { + this.nonContacts.loadingMore = false; + } else if (loadMore == 'messages') { + this.messages.loadingMore = false; + } + + infiniteComplete && infiniteComplete(); + }); + } + + /** + * Open a discussion in the split view. + * + * @param {number} userId User id. + * @param {boolean} [onInit=false] Whether the tser was selected on initial load. + */ + openDiscussion(userId: number, onInit: boolean = false): void { + if (!onInit || this.splitviewCtrl.isOn()) { + this.selectedUserId = userId; + this.splitviewCtrl.push('AddonMessagesDiscussionPage', { userId }); + } + } + + /** + * Component destroyed. + */ + ngOnDestroy(): void { + this.memberInfoObserver && this.memberInfoObserver.off(); + } +}