commit
						182da5a642
					
				@ -87,8 +87,20 @@ export class AddonMessagesConfirmedContactsComponent implements OnInit, OnDestro
 | 
				
			|||||||
        this.loadMoreError = false;
 | 
					        this.loadMoreError = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const limitFrom = refresh ? 0 : this.contacts.length;
 | 
					        const limitFrom = refresh ? 0 : this.contacts.length;
 | 
				
			||||||
 | 
					        let promise;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return this.messagesProvider.getUserContacts(limitFrom).then((result) => {
 | 
					        if (limitFrom === 0) {
 | 
				
			||||||
 | 
					            // Always try to get latest data from server.
 | 
				
			||||||
 | 
					            promise = this.messagesProvider.invalidateUserContacts().catch(() => {
 | 
				
			||||||
 | 
					                // Shouldn't happen.
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            promise = Promise.resolve();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return promise.then(() => {
 | 
				
			||||||
 | 
					            return this.messagesProvider.getUserContacts(limitFrom);
 | 
				
			||||||
 | 
					        }).then((result) => {
 | 
				
			||||||
            this.contacts = refresh ? result.contacts : this.contacts.concat(result.contacts);
 | 
					            this.contacts = refresh ? result.contacts : this.contacts.concat(result.contacts);
 | 
				
			||||||
            this.canLoadMore = result.canLoadMore;
 | 
					            this.canLoadMore = result.canLoadMore;
 | 
				
			||||||
        }).catch((error) => {
 | 
					        }).catch((error) => {
 | 
				
			||||||
@ -104,9 +116,8 @@ export class AddonMessagesConfirmedContactsComponent implements OnInit, OnDestro
 | 
				
			|||||||
     * @return {Promise<any>} Promise resolved when done.
 | 
					     * @return {Promise<any>} Promise resolved when done.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    refreshData(refresher?: any): Promise<any> {
 | 
					    refreshData(refresher?: any): Promise<any> {
 | 
				
			||||||
        return this.messagesProvider.invalidateUserContacts().then(() => {
 | 
					        // No need to invalidate contacts, we always try to get the latest.
 | 
				
			||||||
            return this.fetchData(true);
 | 
					        return this.fetchData(true).finally(() => {
 | 
				
			||||||
        }).finally(() => {
 | 
					 | 
				
			||||||
            refresher && refresher.complete();
 | 
					            refresher && refresher.complete();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -78,8 +78,20 @@ export class AddonMessagesContactRequestsComponent implements OnInit, OnDestroy
 | 
				
			|||||||
        this.loadMoreError = false;
 | 
					        this.loadMoreError = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const limitFrom = refresh ? 0 : this.requests.length;
 | 
					        const limitFrom = refresh ? 0 : this.requests.length;
 | 
				
			||||||
 | 
					        let promise;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return this.messagesProvider.getContactRequests(limitFrom).then((result) => {
 | 
					        if (limitFrom === 0) {
 | 
				
			||||||
 | 
					            // Always try to get latest data from server.
 | 
				
			||||||
 | 
					            promise = this.messagesProvider.invalidateContactRequestsCache().catch(() => {
 | 
				
			||||||
 | 
					                // Shouldn't happen.
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            promise = Promise.resolve();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return promise.then(() => {
 | 
				
			||||||
 | 
					            return this.messagesProvider.getContactRequests(limitFrom);
 | 
				
			||||||
 | 
					        }).then((result) => {
 | 
				
			||||||
            this.requests = refresh ? result.requests : this.requests.concat(result.requests);
 | 
					            this.requests = refresh ? result.requests : this.requests.concat(result.requests);
 | 
				
			||||||
            this.canLoadMore = result.canLoadMore;
 | 
					            this.canLoadMore = result.canLoadMore;
 | 
				
			||||||
        }).catch((error) => {
 | 
					        }).catch((error) => {
 | 
				
			||||||
@ -98,9 +110,8 @@ export class AddonMessagesContactRequestsComponent implements OnInit, OnDestroy
 | 
				
			|||||||
        // Refresh the number of contacts requests to update badges.
 | 
					        // Refresh the number of contacts requests to update badges.
 | 
				
			||||||
        this.messagesProvider.refreshContactRequestsCount();
 | 
					        this.messagesProvider.refreshContactRequestsCount();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return this.messagesProvider.invalidateContactRequestsCache().then(() => {
 | 
					        // No need to invalidate contact requests, we always try to get the latest.
 | 
				
			||||||
            return this.fetchData(true);
 | 
					        return this.fetchData(true).finally(() => {
 | 
				
			||||||
        }).finally(() => {
 | 
					 | 
				
			||||||
            refresher && refresher.complete();
 | 
					            refresher && refresher.complete();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -47,6 +47,8 @@ export class AddonMessagesContactsComponent {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
    searchString = '';
 | 
					    searchString = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected memberInfoObserver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(sitesProvider: CoreSitesProvider, translate: TranslateService, private appProvider: CoreAppProvider,
 | 
					    constructor(sitesProvider: CoreSitesProvider, translate: TranslateService, private appProvider: CoreAppProvider,
 | 
				
			||||||
            private messagesProvider: AddonMessagesProvider, private domUtils: CoreDomUtilsProvider, navParams: NavParams,
 | 
					            private messagesProvider: AddonMessagesProvider, private domUtils: CoreDomUtilsProvider, navParams: NavParams,
 | 
				
			||||||
            private eventsProvider: CoreEventsProvider) {
 | 
					            private eventsProvider: CoreEventsProvider) {
 | 
				
			||||||
@ -58,6 +60,13 @@ export class AddonMessagesContactsComponent {
 | 
				
			|||||||
        this.loadingMessage = this.loadingMessages;
 | 
					        this.loadingMessage = this.loadingMessages;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.discussionUserId = navParams.get('discussionUserId') || false;
 | 
					        this.discussionUserId = navParams.get('discussionUserId') || false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Refresh the list when a contact request is confirmed.
 | 
				
			||||||
 | 
					        this.memberInfoObserver = eventsProvider.on(AddonMessagesProvider.MEMBER_INFO_CHANGED_EVENT, (data) => {
 | 
				
			||||||
 | 
					            if (data.contactRequestConfirmed) {
 | 
				
			||||||
 | 
					                this.refreshData();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }, sitesProvider.getCurrentSiteId());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -217,4 +226,11 @@ export class AddonMessagesContactsComponent {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
        this.eventsProvider.trigger(AddonMessagesProvider.SPLIT_VIEW_LOAD_EVENT, params, this.siteId);
 | 
					        this.eventsProvider.trigger(AddonMessagesProvider.SPLIT_VIEW_LOAD_EVENT, params, this.siteId);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Component destroyed.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    ngOnDestroy(): void {
 | 
				
			||||||
 | 
					        this.memberInfoObserver && this.memberInfoObserver.off();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -223,7 +223,12 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (this.userId) {
 | 
					                    if (this.userId) {
 | 
				
			||||||
                        promises.push(this.messagesProvider.getMemberInfo(this.userId).then((member) => {
 | 
					                        // Get the member info. Invalidate first to make sure we get the latest status.
 | 
				
			||||||
 | 
					                        promises.push(this.messagesProvider.invalidateMemberInfo(this.userId).catch(() => {
 | 
				
			||||||
 | 
					                            // Shouldn't happen.
 | 
				
			||||||
 | 
					                        }).then(() => {
 | 
				
			||||||
 | 
					                            return this.messagesProvider.getMemberInfo(this.userId);
 | 
				
			||||||
 | 
					                        }).then((member) => {
 | 
				
			||||||
                            this.otherMember = member;
 | 
					                            this.otherMember = member;
 | 
				
			||||||
                            if (!exists && member) {
 | 
					                            if (!exists && member) {
 | 
				
			||||||
                                this.conversationImage = member.profileimageurl;
 | 
					                                this.conversationImage = member.profileimageurl;
 | 
				
			||||||
@ -630,7 +635,9 @@ export class AddonMessagesDiscussionPage implements OnDestroy {
 | 
				
			|||||||
                conversationId: this.conversationId,
 | 
					                conversationId: this.conversationId,
 | 
				
			||||||
                userId: this.userId,
 | 
					                userId: this.userId,
 | 
				
			||||||
                message: this.lastMessage.text,
 | 
					                message: this.lastMessage.text,
 | 
				
			||||||
                timecreated: this.lastMessage.timecreated
 | 
					                timecreated: this.lastMessage.timecreated,
 | 
				
			||||||
 | 
					                isfavourite: this.conversation && this.conversation.isfavourite,
 | 
				
			||||||
 | 
					                type: this.conversation && this.conversation.type
 | 
				
			||||||
            }, this.siteId);
 | 
					            }, this.siteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Update navBar links and buttons.
 | 
					            // Update navBar links and buttons.
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@
 | 
				
			|||||||
</ion-header>
 | 
					</ion-header>
 | 
				
			||||||
<core-split-view>
 | 
					<core-split-view>
 | 
				
			||||||
    <ion-content class="core-expand-max">
 | 
					    <ion-content class="core-expand-max">
 | 
				
			||||||
        <ion-refresher [enabled]="loaded" (ionRefresh)="refreshData($event)">
 | 
					        <ion-refresher [enabled]="loaded && (!currentListEl || currentListEl.scrollTop < 5)" (ionRefresh)="refreshData($event)">
 | 
				
			||||||
            <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
					            <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
				
			||||||
        </ion-refresher>
 | 
					        </ion-refresher>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -27,51 +27,61 @@
 | 
				
			|||||||
                    <ion-badge *ngIf="contactRequestsCount > 0" item-end>{{contactRequestsCount}}</ion-badge>
 | 
					                    <ion-badge *ngIf="contactRequestsCount > 0" item-end>{{contactRequestsCount}}</ion-badge>
 | 
				
			||||||
                </a>
 | 
					                </a>
 | 
				
			||||||
                <!-- Favourite conversations. -->
 | 
					                <!-- Favourite conversations. -->
 | 
				
			||||||
                <ion-item-divider text-wrap *ngIf="favourites.conversations" (click)="toggle(favourites)" class="core-expandable">
 | 
					                <ion-item-divider text-wrap (click)="toggle(favourites)" class="core-expandable">
 | 
				
			||||||
                    <core-icon *ngIf="!favourites.expanded" name="fa-caret-right" item-start></core-icon>
 | 
					                    <core-icon *ngIf="!favourites.expanded" name="fa-caret-right" item-start></core-icon>
 | 
				
			||||||
                    <core-icon *ngIf="favourites.expanded" name="fa-caret-down" item-start></core-icon>
 | 
					                    <core-icon *ngIf="favourites.expanded" name="fa-caret-down" item-start></core-icon>
 | 
				
			||||||
                    {{ 'core.favourites' | translate }} ({{ favourites.count }})
 | 
					                    {{ 'core.favourites' | translate }} ({{ favourites.count }})
 | 
				
			||||||
                    <ion-badge item-end *ngIf="favourites.unread">{{ favourites.unread }}</ion-badge>
 | 
					                    <ion-badge item-end *ngIf="favourites.unread">{{ favourites.unread }}</ion-badge>
 | 
				
			||||||
                </ion-item-divider>
 | 
					                </ion-item-divider>
 | 
				
			||||||
                <div *ngIf="favourites.conversations && favourites.expanded">
 | 
					                <div [hidden]="!favourites.conversations || !favourites.expanded || favourites.loading" #favlist>
 | 
				
			||||||
                    <ng-container *ngTemplateOutlet="conversationsTemplate; context: {conversations: favourites.conversations}"></ng-container>
 | 
					                    <ng-container *ngTemplateOutlet="conversationsTemplate; context: {conversations: favourites.conversations}"></ng-container>
 | 
				
			||||||
                    <!-- The infinite loading cannot be inside the ng-template, it fails because it doesn't find ion-content. -->
 | 
					                    <!-- The infinite loading cannot be inside the ng-template, it fails because it doesn't find ion-content. -->
 | 
				
			||||||
                    <core-infinite-loading [enabled]="favourites.canLoadMore" (action)="loadMoreConversations(favourites, $event)" [error]="favourites.loadMoreError"></core-infinite-loading>
 | 
					                    <core-infinite-loading [enabled]="favourites.canLoadMore" (action)="loadMoreConversations(favourites, $event)" [error]="favourites.loadMoreError"></core-infinite-loading>
 | 
				
			||||||
                    <ion-item text-wrap *ngIf="favourites.conversations.length == 0">
 | 
					                    <ion-item text-wrap *ngIf="favourites.conversations && favourites.conversations.length == 0">
 | 
				
			||||||
                        <p>{{ 'addon.messages.nofavourites' | translate }}</p>
 | 
					                        <p>{{ 'addon.messages.nofavourites' | translate }}</p>
 | 
				
			||||||
                    </ion-item>
 | 
					                    </ion-item>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					                <ion-item text-center *ngIf="favourites.loading">
 | 
				
			||||||
 | 
					                    <ion-spinner></ion-spinner>
 | 
				
			||||||
 | 
					                </ion-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <!-- Group conversations. -->
 | 
					                <!-- Group conversations. -->
 | 
				
			||||||
                <ion-item-divider text-wrap *ngIf="group.conversations" (click)="toggle(group)" class="core-expandable">
 | 
					                <ion-item-divider text-wrap (click)="toggle(group)" class="core-expandable">
 | 
				
			||||||
                    <core-icon *ngIf="!group.expanded" name="fa-caret-right" item-start></core-icon>
 | 
					                    <core-icon *ngIf="!group.expanded" name="fa-caret-right" item-start></core-icon>
 | 
				
			||||||
                    <core-icon *ngIf="group.expanded" name="fa-caret-down" item-start></core-icon>
 | 
					                    <core-icon *ngIf="group.expanded" name="fa-caret-down" item-start></core-icon>
 | 
				
			||||||
                    {{ 'addon.messages.groupconversations' | translate }} ({{ group.count }})
 | 
					                    {{ 'addon.messages.groupconversations' | translate }} ({{ group.count }})
 | 
				
			||||||
                    <ion-badge item-end *ngIf="group.unread">{{ group.unread }}</ion-badge>
 | 
					                    <ion-badge item-end *ngIf="group.unread">{{ group.unread }}</ion-badge>
 | 
				
			||||||
                </ion-item-divider>
 | 
					                </ion-item-divider>
 | 
				
			||||||
                <div *ngIf="group.conversations && group.expanded">
 | 
					                <div [hidden]="!group.conversations || !group.expanded || group.loading" #grouplist>
 | 
				
			||||||
                    <ng-container *ngTemplateOutlet="conversationsTemplate; context: {conversations: group.conversations}"></ng-container>
 | 
					                    <ng-container *ngTemplateOutlet="conversationsTemplate; context: {conversations: group.conversations}"></ng-container>
 | 
				
			||||||
                    <!-- The infinite loading cannot be inside the ng-template, it fails because it doesn't find ion-content. -->
 | 
					                    <!-- The infinite loading cannot be inside the ng-template, it fails because it doesn't find ion-content. -->
 | 
				
			||||||
                    <core-infinite-loading [enabled]="group.canLoadMore" (action)="loadMoreConversations(group, $event)" [error]="group.loadMoreError"></core-infinite-loading>
 | 
					                    <core-infinite-loading [enabled]="group.canLoadMore" (action)="loadMoreConversations(group, $event)" [error]="group.loadMoreError"></core-infinite-loading>
 | 
				
			||||||
                    <ion-item text-wrap *ngIf="group.conversations.length == 0">
 | 
					                    <ion-item text-wrap *ngIf="group.conversations && group.conversations.length == 0">
 | 
				
			||||||
                        <p>{{ 'addon.messages.nogroupconversations' | translate }}</p>
 | 
					                        <p>{{ 'addon.messages.nogroupconversations' | translate }}</p>
 | 
				
			||||||
                    </ion-item>
 | 
					                    </ion-item>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					                <ion-item text-center *ngIf="group.loading">
 | 
				
			||||||
 | 
					                    <ion-spinner></ion-spinner>
 | 
				
			||||||
 | 
					                </ion-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <ion-item-divider text-wrap *ngIf="individual.conversations" (click)="toggle(individual)" class="core-expandable">
 | 
					                <ion-item-divider text-wrap (click)="toggle(individual)" class="core-expandable">
 | 
				
			||||||
                    <core-icon *ngIf="!individual.expanded" name="fa-caret-right" item-start></core-icon>
 | 
					                    <core-icon *ngIf="!individual.expanded" name="fa-caret-right" item-start></core-icon>
 | 
				
			||||||
                    <core-icon *ngIf="individual.expanded" name="fa-caret-down" item-start></core-icon>
 | 
					                    <core-icon *ngIf="individual.expanded" name="fa-caret-down" item-start></core-icon>
 | 
				
			||||||
                    {{ 'addon.messages.individualconversations' | translate }} ({{ individual.count }})
 | 
					                    {{ 'addon.messages.individualconversations' | translate }} ({{ individual.count }})
 | 
				
			||||||
                    <ion-badge item-end *ngIf="individual.unread">{{ individual.unread }}</ion-badge>
 | 
					                    <ion-badge item-end *ngIf="individual.unread">{{ individual.unread }}</ion-badge>
 | 
				
			||||||
                </ion-item-divider>
 | 
					                </ion-item-divider>
 | 
				
			||||||
                <div *ngIf="individual.conversations && individual.expanded">
 | 
					                <div [hidden]="!individual.conversations || !individual.expanded || individual.loading" #indlist>
 | 
				
			||||||
                    <ng-container *ngTemplateOutlet="conversationsTemplate; context: {conversations: individual.conversations}"></ng-container>
 | 
					                    <ng-container *ngTemplateOutlet="conversationsTemplate; context: {conversations: individual.conversations}"></ng-container>
 | 
				
			||||||
                    <!-- The infinite loading cannot be inside the ng-template, it fails because it doesn't find ion-content. -->
 | 
					                    <!-- The infinite loading cannot be inside the ng-template, it fails because it doesn't find ion-content. -->
 | 
				
			||||||
                    <core-infinite-loading [enabled]="individual.canLoadMore" (action)="loadMoreConversations(individual, $event)" [error]="individual.loadMoreError"></core-infinite-loading>
 | 
					                    <core-infinite-loading [enabled]="individual.canLoadMore" (action)="loadMoreConversations(individual, $event)" [error]="individual.loadMoreError"></core-infinite-loading>
 | 
				
			||||||
                    <ion-item text-wrap *ngIf="individual.conversations.length == 0">
 | 
					                    <ion-item text-wrap *ngIf="individual.conversations && individual.conversations.length == 0">
 | 
				
			||||||
                        <p>{{ 'addon.messages.noindividualconversations' | translate }}</p>
 | 
					                        <p>{{ 'addon.messages.noindividualconversations' | translate }}</p>
 | 
				
			||||||
                    </ion-item>
 | 
					                    </ion-item>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					                <ion-item text-center *ngIf="individual.loading">
 | 
				
			||||||
 | 
					                    <ion-spinner></ion-spinner>
 | 
				
			||||||
 | 
					                </ion-item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            </ion-list>
 | 
					            </ion-list>
 | 
				
			||||||
        </core-loading>
 | 
					        </core-loading>
 | 
				
			||||||
    </ion-content>
 | 
					    </ion-content>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
 | 
					import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { IonicPage, Platform, NavController, NavParams, Content } from 'ionic-angular';
 | 
					import { IonicPage, Platform, NavController, NavParams, Content } from 'ionic-angular';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
import { CoreEventsProvider } from '@providers/events';
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
@ -36,6 +36,9 @@ import { CoreUserProvider } from '@core/user/providers/user';
 | 
				
			|||||||
export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
					export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			||||||
    @ViewChild(CoreSplitViewComponent) splitviewCtrl: CoreSplitViewComponent;
 | 
					    @ViewChild(CoreSplitViewComponent) splitviewCtrl: CoreSplitViewComponent;
 | 
				
			||||||
    @ViewChild(Content) content: Content;
 | 
					    @ViewChild(Content) content: Content;
 | 
				
			||||||
 | 
					    @ViewChild('favlist') favListEl: ElementRef;
 | 
				
			||||||
 | 
					    @ViewChild('grouplist') groupListEl: ElementRef;
 | 
				
			||||||
 | 
					    @ViewChild('indlist') indListEl: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    loaded = false;
 | 
					    loaded = false;
 | 
				
			||||||
    loadingMessage: string;
 | 
					    loadingMessage: string;
 | 
				
			||||||
@ -61,6 +64,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
        unread: 0
 | 
					        unread: 0
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    typeIndividual = AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_INDIVIDUAL;
 | 
					    typeIndividual = AddonMessagesProvider.MESSAGE_CONVERSATION_TYPE_INDIVIDUAL;
 | 
				
			||||||
 | 
					    currentListEl: HTMLElement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected loadingString: string;
 | 
					    protected loadingString: string;
 | 
				
			||||||
    protected siteId: string;
 | 
					    protected siteId: string;
 | 
				
			||||||
@ -89,8 +93,16 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Update conversations when new message is received.
 | 
					        // Update conversations when new message is received.
 | 
				
			||||||
        this.newMessagesObserver = eventsProvider.on(AddonMessagesProvider.NEW_MESSAGE_EVENT, (data) => {
 | 
					        this.newMessagesObserver = eventsProvider.on(AddonMessagesProvider.NEW_MESSAGE_EVENT, (data) => {
 | 
				
			||||||
 | 
					            // Check if the new message belongs to the option that is currently expanded.
 | 
				
			||||||
 | 
					            const expandedOption = this.getExpandedOption(),
 | 
				
			||||||
 | 
					                messageOption = this.getConversationOption(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (expandedOption != messageOption) {
 | 
				
			||||||
 | 
					                return; // Message doesn't belong to current list, stop.
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Search the conversation to update.
 | 
					            // Search the conversation to update.
 | 
				
			||||||
            const conversation = this.findConversation(data.conversationId, data.userId);
 | 
					            const conversation = this.findConversation(data.conversationId, data.userId, expandedOption);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (typeof conversation == 'undefined') {
 | 
					            if (typeof conversation == 'undefined') {
 | 
				
			||||||
                // Probably a new conversation, refresh the list.
 | 
					                // Probably a new conversation, refresh the list.
 | 
				
			||||||
@ -135,7 +147,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
        // Load a discussion if we receive an event to do so.
 | 
					        // Load a discussion if we receive an event to do so.
 | 
				
			||||||
        this.openConversationObserver = eventsProvider.on(AddonMessagesProvider.OPEN_CONVERSATION_EVENT, (data) => {
 | 
					        this.openConversationObserver = eventsProvider.on(AddonMessagesProvider.OPEN_CONVERSATION_EVENT, (data) => {
 | 
				
			||||||
            if (data.conversationId || data.userId) {
 | 
					            if (data.conversationId || data.userId) {
 | 
				
			||||||
                this.gotoConversation(data.conversationId, data.userId, undefined, true);
 | 
					                this.gotoConversation(data.conversationId, data.userId);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }, this.siteId);
 | 
					        }, this.siteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -183,18 +195,17 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const updateConversations = (conversations: any[]): void => {
 | 
					            const expandedOption = this.getExpandedOption();
 | 
				
			||||||
                if (!conversations || conversations.length <= 0) {
 | 
					            if (expandedOption == this.individual || expandedOption == this.favourites) {
 | 
				
			||||||
 | 
					                if (!expandedOption.conversations || expandedOption.conversations.length <= 0) {
 | 
				
			||||||
                    return;
 | 
					                    return;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                const conversation = conversations.find((conv) => conv.userid == data.userId);
 | 
					
 | 
				
			||||||
 | 
					                const conversation = this.findConversation(undefined, data.userId, expandedOption);
 | 
				
			||||||
                if (conversation) {
 | 
					                if (conversation) {
 | 
				
			||||||
                    conversation.isblocked = data.userBlocked;
 | 
					                    conversation.isblocked = data.userBlocked;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            };
 | 
					            }
 | 
				
			||||||
 | 
					 | 
				
			||||||
            updateConversations(this.individual.conversations);
 | 
					 | 
				
			||||||
            updateConversations(this.favourites.conversations);
 | 
					 | 
				
			||||||
        }, this.siteId);
 | 
					        }, this.siteId);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -211,13 +222,10 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
            if (!this.conversationId && this.splitviewCtrl.isOn()) {
 | 
					            if (!this.conversationId && this.splitviewCtrl.isOn()) {
 | 
				
			||||||
                // Load the first conversation.
 | 
					                // Load the first conversation.
 | 
				
			||||||
                let conversation;
 | 
					                let conversation;
 | 
				
			||||||
 | 
					                const expandedOption = this.getExpandedOption();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (this.favourites.expanded) {
 | 
					                if (expandedOption) {
 | 
				
			||||||
                    conversation = this.favourites.conversations[0];
 | 
					                    conversation = expandedOption.conversations[0];
 | 
				
			||||||
                } else if (this.group.expanded) {
 | 
					 | 
				
			||||||
                    conversation = this.group.conversations[0];
 | 
					 | 
				
			||||||
                } else if (this.individual.expanded) {
 | 
					 | 
				
			||||||
                    conversation = this.individual.conversations[0];
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (conversation) {
 | 
					                if (conversation) {
 | 
				
			||||||
@ -230,53 +238,53 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Fetch conversations.
 | 
					     * Fetch conversations.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
 | 
					     * @param {booleam} [refreshUnreadCounts=true] Whether to refresh unread counts.
 | 
				
			||||||
     * @return {Promise<any>} Promise resolved when done.
 | 
					     * @return {Promise<any>} Promise resolved when done.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected fetchData(): Promise<any> {
 | 
					    protected fetchData(refreshUnreadCounts: boolean = true): Promise<any> {
 | 
				
			||||||
        this.loadingMessage = this.loadingString;
 | 
					        this.loadingMessage = this.loadingString;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Load the first conversations of each type.
 | 
					        // Load the amount of conversations and contact requests.
 | 
				
			||||||
        const promises = [];
 | 
					        const promises = [];
 | 
				
			||||||
        let offlineMessages;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        promises.push(this.fetchDataForOption(this.favourites, false));
 | 
					 | 
				
			||||||
        promises.push(this.fetchDataForOption(this.group, false));
 | 
					 | 
				
			||||||
        promises.push(this.fetchDataForOption(this.individual, false));
 | 
					 | 
				
			||||||
        promises.push(this.fetchConversationCounts());
 | 
					        promises.push(this.fetchConversationCounts());
 | 
				
			||||||
        promises.push(this.messagesProvider.getUnreadConversationCounts()); // View updated by the event observer.
 | 
					 | 
				
			||||||
        promises.push(this.messagesProvider.getContactRequestsCount());  // View updated by the event observer.
 | 
					        promises.push(this.messagesProvider.getContactRequestsCount());  // View updated by the event observer.
 | 
				
			||||||
        promises.push(this.messagesOffline.getAllMessages().then((messages) => {
 | 
					 | 
				
			||||||
            offlineMessages = messages;
 | 
					 | 
				
			||||||
        }));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return Promise.all(promises).then(() => {
 | 
					        return Promise.all(promises).then(() => {
 | 
				
			||||||
            return this.loadOfflineMessages(offlineMessages);
 | 
					 | 
				
			||||||
        }).then(() => {
 | 
					 | 
				
			||||||
            if (offlineMessages && offlineMessages.length) {
 | 
					 | 
				
			||||||
                // Sort the conversations, the offline messages could affect the order.
 | 
					 | 
				
			||||||
                this.favourites.conversations = this.messagesProvider.sortConversations(this.favourites.conversations);
 | 
					 | 
				
			||||||
                this.group.conversations = this.messagesProvider.sortConversations(this.group.conversations);
 | 
					 | 
				
			||||||
                this.individual.conversations = this.messagesProvider.sortConversations(this.individual.conversations);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (typeof this.favourites.expanded == 'undefined') {
 | 
					            if (typeof this.favourites.expanded == 'undefined') {
 | 
				
			||||||
                // The expanded status hasn't been initialized. Do it now.
 | 
					                // The expanded status hasn't been initialized. Do it now.
 | 
				
			||||||
                if (this.conversationId) {
 | 
					                if (this.conversationId) {
 | 
				
			||||||
                    // A certain conversation should be opened, expand its option.
 | 
					                    // A certain conversation should be opened.
 | 
				
			||||||
 | 
					                    // We don't know which option it belongs to, so we need to fetch the data for all of them.
 | 
				
			||||||
 | 
					                    const promises = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    promises.push(this.fetchDataForOption(this.favourites, false, refreshUnreadCounts));
 | 
				
			||||||
 | 
					                    promises.push(this.fetchDataForOption(this.group, false, refreshUnreadCounts));
 | 
				
			||||||
 | 
					                    promises.push(this.fetchDataForOption(this.individual, false, refreshUnreadCounts));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return Promise.all(promises).then(() => {
 | 
				
			||||||
 | 
					                        // All conversations have been loaded, find the one we need to load and expand its option.
 | 
				
			||||||
                        const conversation = this.findConversation(this.conversationId);
 | 
					                        const conversation = this.findConversation(this.conversationId);
 | 
				
			||||||
                        if (conversation) {
 | 
					                        if (conversation) {
 | 
				
			||||||
                            const option = this.getConversationOption(conversation);
 | 
					                            const option = this.getConversationOption(conversation);
 | 
				
			||||||
                        this.expandOption(option);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        return;
 | 
					                            return this.expandOption(option, refreshUnreadCounts);
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            // Conversation not found, just open the default option.
 | 
				
			||||||
 | 
					                            this.calculateExpandedStatus();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            // Now load the data for the expanded option.
 | 
				
			||||||
 | 
					                            return this.fetchDataForExpandedOption(refreshUnreadCounts);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // No conversation specified or not found, determine which one should be expanded.
 | 
					                // No conversation specified or not found, determine which one should be expanded.
 | 
				
			||||||
                this.favourites.expanded = this.favourites.count != 0;
 | 
					                this.calculateExpandedStatus();
 | 
				
			||||||
                this.group.expanded = this.favourites.count == 0 && this.group.count != 0;
 | 
					 | 
				
			||||||
                this.individual.expanded = this.favourites.count == 0 && this.group.count == 0;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Now load the data for the expanded option.
 | 
				
			||||||
 | 
					            return this.fetchDataForExpandedOption(refreshUnreadCounts);
 | 
				
			||||||
        }).catch((error) => {
 | 
					        }).catch((error) => {
 | 
				
			||||||
            this.domUtils.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingdiscussions', true);
 | 
					            this.domUtils.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingdiscussions', true);
 | 
				
			||||||
        }).finally(() => {
 | 
					        }).finally(() => {
 | 
				
			||||||
@ -284,27 +292,93 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Calculate which option should be expanded initially.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected calculateExpandedStatus(): void {
 | 
				
			||||||
 | 
					        this.favourites.expanded = this.favourites.count != 0;
 | 
				
			||||||
 | 
					        this.group.expanded = this.favourites.count == 0 && this.group.count != 0;
 | 
				
			||||||
 | 
					        this.individual.expanded = this.favourites.count == 0 && this.group.count == 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.loadCurrentListElement();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Fetch data for the expanded option.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param {booleam} [refreshUnreadCounts=true] Whether to refresh unread counts.
 | 
				
			||||||
 | 
					     * @return {Promise<any>} Promise resolved when done.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected fetchDataForExpandedOption(refreshUnreadCounts: boolean = true): Promise<any> {
 | 
				
			||||||
 | 
					        const expandedOption = this.getExpandedOption();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (expandedOption) {
 | 
				
			||||||
 | 
					            return this.fetchDataForOption(expandedOption, false, refreshUnreadCounts);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // All options are collapsed, update the counts.
 | 
				
			||||||
 | 
					            const promises = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            promises.push(this.fetchConversationCounts());
 | 
				
			||||||
 | 
					            if (refreshUnreadCounts) {
 | 
				
			||||||
 | 
					                promises.push(this.messagesProvider.refreshUnreadConversationCounts()); // View updated by the event observer.
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return Promise.all(promises);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Fetch data for a certain option.
 | 
					     * Fetch data for a certain option.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {any} option The option to fetch data for.
 | 
					     * @param {any} option The option to fetch data for.
 | 
				
			||||||
     * @param {boolean} [loadingMore} Whether we are loading more data or just the first ones.
 | 
					     * @param {boolean} [loadingMore} Whether we are loading more data or just the first ones.
 | 
				
			||||||
 | 
					     * @param {booleam} [refreshUnreadCounts=true] Whether to refresh unread counts.
 | 
				
			||||||
     * @return {Promise<any>} Promise resolved when done.
 | 
					     * @return {Promise<any>} Promise resolved when done.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    fetchDataForOption(option: any, loadingMore?: boolean): Promise<void> {
 | 
					    fetchDataForOption(option: any, loadingMore?: boolean, refreshUnreadCounts: boolean = true): Promise<void> {
 | 
				
			||||||
        option.loadMoreError = false;
 | 
					        option.loadMoreError = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const limitFrom = loadingMore ? option.conversations.length : 0;
 | 
					        const limitFrom = loadingMore ? option.conversations.length : 0,
 | 
				
			||||||
 | 
					            promises = [];
 | 
				
			||||||
 | 
					        let data,
 | 
				
			||||||
 | 
					            offlineMessages;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return this.messagesProvider.getConversations(option.type, option.favourites, limitFrom).then((data) => {
 | 
					        // Get the conversations and, if needed, the offline messages. Always try to get the latest data.
 | 
				
			||||||
            if (loadingMore) {
 | 
					        promises.push(this.messagesProvider.invalidateConversations().catch(() => {
 | 
				
			||||||
                option.conversations = option.conversations.concat(data.conversations);
 | 
					            // Shouldn't happen.
 | 
				
			||||||
            } else {
 | 
					        }).then(() => {
 | 
				
			||||||
                option.conversations = data.conversations;
 | 
					            return this.messagesProvider.getConversations(option.type, option.favourites, limitFrom);
 | 
				
			||||||
 | 
					        }).then((result) => {
 | 
				
			||||||
 | 
					            data = result;
 | 
				
			||||||
 | 
					        }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!loadingMore) {
 | 
				
			||||||
 | 
					            promises.push(this.messagesOffline.getAllMessages().then((data) => {
 | 
				
			||||||
 | 
					                offlineMessages = data;
 | 
				
			||||||
 | 
					            }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            promises.push(this.fetchConversationCounts());
 | 
				
			||||||
 | 
					            if (refreshUnreadCounts) {
 | 
				
			||||||
 | 
					                promises.push(this.messagesProvider.refreshUnreadConversationCounts()); // View updated by the event observer.
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            option.unread = 0; // @todo.
 | 
					        return Promise.all(promises).then(() => {
 | 
				
			||||||
 | 
					            if (loadingMore) {
 | 
				
			||||||
 | 
					                option.conversations = option.conversations.concat(data.conversations);
 | 
				
			||||||
                option.canLoadMore = data.canLoadMore;
 | 
					                option.canLoadMore = data.canLoadMore;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                option.conversations = data.conversations;
 | 
				
			||||||
 | 
					                option.canLoadMore = data.canLoadMore;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (offlineMessages && offlineMessages.length) {
 | 
				
			||||||
 | 
					                    return this.loadOfflineMessages(option, offlineMessages).then(() => {
 | 
				
			||||||
 | 
					                        // Sort the conversations, the offline messages could affect the order.
 | 
				
			||||||
 | 
					                        option.conversations = this.messagesProvider.sortConversations(option.conversations);
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -314,7 +388,12 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
     * @return {Promise<any>} Promise resolved when done.
 | 
					     * @return {Promise<any>} Promise resolved when done.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected fetchConversationCounts(): Promise<void> {
 | 
					    protected fetchConversationCounts(): Promise<void> {
 | 
				
			||||||
        return this.messagesProvider.getConversationCounts().then((counts) => {
 | 
					        // Always try to get the latest data.
 | 
				
			||||||
 | 
					        return this.messagesProvider.invalidateConversationCounts().catch(() => {
 | 
				
			||||||
 | 
					            // Shouldn't happen.
 | 
				
			||||||
 | 
					        }).then(() => {
 | 
				
			||||||
 | 
					            return this.messagesProvider.getConversationCounts();
 | 
				
			||||||
 | 
					        }).then((counts) => {
 | 
				
			||||||
            this.favourites.count = counts.favourites;
 | 
					            this.favourites.count = counts.favourites;
 | 
				
			||||||
            this.individual.count = counts.individual;
 | 
					            this.individual.count = counts.individual;
 | 
				
			||||||
            this.group.count = counts.group;
 | 
					            this.group.count = counts.group;
 | 
				
			||||||
@ -326,25 +405,42 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {number} conversationId The conversation ID to search.
 | 
					     * @param {number} conversationId The conversation ID to search.
 | 
				
			||||||
     * @param {number} userId User ID to search (if no conversationId).
 | 
					     * @param {number} userId User ID to search (if no conversationId).
 | 
				
			||||||
 | 
					     * @param {any} [option] The option to search in. If not defined, search in all options.
 | 
				
			||||||
     * @return {any} Conversation.
 | 
					     * @return {any} Conversation.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected findConversation(conversationId: number, userId?: number): any {
 | 
					    protected findConversation(conversationId: number, userId?: number, option?: any): any {
 | 
				
			||||||
        if (conversationId) {
 | 
					        if (conversationId) {
 | 
				
			||||||
            const conversations = (this.favourites.conversations || []).concat(this.group.conversations || [])
 | 
					            const conversations = option ? (option.conversations || []) : ((this.favourites.conversations || [])
 | 
				
			||||||
                    .concat(this.individual.conversations || []);
 | 
					                    .concat(this.group.conversations || []).concat(this.individual.conversations || []));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return conversations.find((conv) => {
 | 
					            return conversations.find((conv) => {
 | 
				
			||||||
                return conv.id == conversationId;
 | 
					                return conv.id == conversationId;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const conversations = (this.favourites.conversations || []).concat(this.individual.conversations || []);
 | 
					        const conversations = option ? (option.conversations || []) :
 | 
				
			||||||
 | 
					                ((this.favourites.conversations || []).concat(this.individual.conversations || []));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return conversations.find((conv) => {
 | 
					        return conversations.find((conv) => {
 | 
				
			||||||
            return conv.userid == userId;
 | 
					            return conv.userid == userId;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the option that is currently expanded, undefined if they are all collapsed.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return {any} Option currently expanded.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected getExpandedOption(): any {
 | 
				
			||||||
 | 
					        if (this.favourites.expanded) {
 | 
				
			||||||
 | 
					            return this.favourites;
 | 
				
			||||||
 | 
					        } else if (this.group.expanded) {
 | 
				
			||||||
 | 
					            return this.group;
 | 
				
			||||||
 | 
					        } else if (this.individual.expanded) {
 | 
				
			||||||
 | 
					            return this.individual;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Navigate to contacts view.
 | 
					     * Navigate to contacts view.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -358,9 +454,8 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
     * @param {number} conversationId Conversation Id to load.
 | 
					     * @param {number} conversationId Conversation Id to load.
 | 
				
			||||||
     * @param {number} userId User of the conversation. Only if there is no conversationId.
 | 
					     * @param {number} userId User of the conversation. Only if there is no conversationId.
 | 
				
			||||||
     * @param {number} [messageId] Message to scroll after loading the discussion. Used when searching.
 | 
					     * @param {number} [messageId] Message to scroll after loading the discussion. Used when searching.
 | 
				
			||||||
     * @param {boolean} [scrollToConversation] Whether to scroll to the conversation.
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    gotoConversation(conversationId: number, userId?: number, messageId?: number, scrollToConversation?: boolean): void {
 | 
					    gotoConversation(conversationId: number, userId?: number, messageId?: number): void {
 | 
				
			||||||
        this.selectedConversationId = conversationId;
 | 
					        this.selectedConversationId = conversationId;
 | 
				
			||||||
        this.selectedUserId = userId;
 | 
					        this.selectedUserId = userId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -372,23 +467,6 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
            params['message'] = messageId;
 | 
					            params['message'] = messageId;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.splitviewCtrl.push('AddonMessagesDiscussionPage', params);
 | 
					        this.splitviewCtrl.push('AddonMessagesDiscussionPage', params);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (scrollToConversation) {
 | 
					 | 
				
			||||||
            // Search the conversation.
 | 
					 | 
				
			||||||
            const conversation = this.findConversation(conversationId, userId);
 | 
					 | 
				
			||||||
            if (conversation) {
 | 
					 | 
				
			||||||
                // First expand the option if it isn't expanded.
 | 
					 | 
				
			||||||
                const option = this.getConversationOption(conversation);
 | 
					 | 
				
			||||||
                this.expandOption(option);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // Wait for the view to expand the option.
 | 
					 | 
				
			||||||
                setTimeout(() => {
 | 
					 | 
				
			||||||
                    // Now scroll to the conversation.
 | 
					 | 
				
			||||||
                    this.domUtils.scrollToElementBySelector(this.content, '#addon-message-conversation-' +
 | 
					 | 
				
			||||||
                            (conversation.id ? conversation.id : 'user-' + conversation.userid));
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -417,16 +495,17 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Load offline messages into the conversations.
 | 
					     * Load offline messages into the conversations.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
 | 
					     * @param {any} option The option where the messages should be loaded.
 | 
				
			||||||
     * @param {any[]} messages Offline messages.
 | 
					     * @param {any[]} messages Offline messages.
 | 
				
			||||||
     * @return {Promise<any>} Promise resolved when done.
 | 
					     * @return {Promise<any>} Promise resolved when done.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected loadOfflineMessages(messages: any[]): Promise<any> {
 | 
					    protected loadOfflineMessages(option: any, messages: any[]): Promise<any> {
 | 
				
			||||||
        const promises = [];
 | 
					        const promises = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        messages.forEach((message) => {
 | 
					        messages.forEach((message) => {
 | 
				
			||||||
            if (message.conversationid) {
 | 
					            if (message.conversationid) {
 | 
				
			||||||
                // It's an existing conversation. Search it.
 | 
					                // It's an existing conversation. Search it in the current option.
 | 
				
			||||||
                let conversation = this.findConversation(message.conversationid);
 | 
					                let conversation = this.findConversation(message.conversationid, undefined, option);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (conversation) {
 | 
					                if (conversation) {
 | 
				
			||||||
                    // Check if it's the last message. Offline messages are considered more recent than sent messages.
 | 
					                    // Check if it's the last message. Offline messages are considered more recent than sent messages.
 | 
				
			||||||
@ -436,16 +515,19 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
                        this.addLastOfflineMessage(conversation, message);
 | 
					                        this.addLastOfflineMessage(conversation, message);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    // Conversation not found, it's probably an old one. Add it.
 | 
					                    // Conversation not found, it could be an old one or the message could belong to another option.
 | 
				
			||||||
                    conversation = message.conversation || {};
 | 
					                    conversation = message.conversation || {};
 | 
				
			||||||
                    conversation.id = message.conversationid;
 | 
					                    conversation.id = message.conversationid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (this.getConversationOption(conversation) == option) {
 | 
				
			||||||
 | 
					                        // Message belongs to current option, add the conversation.
 | 
				
			||||||
                        this.addLastOfflineMessage(conversation, message);
 | 
					                        this.addLastOfflineMessage(conversation, message);
 | 
				
			||||||
                        this.addOfflineConversation(conversation);
 | 
					                        this.addOfflineConversation(conversation);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
            } else {
 | 
					                }
 | 
				
			||||||
                // Its a new conversation. Check if we already created it (there is more than one message for the same user).
 | 
					            } else if (option == this.individual) {
 | 
				
			||||||
                const conversation = this.findConversation(undefined, message.touserid);
 | 
					                // It's a new conversation. Check if we already created it (there is more than one message for the same user).
 | 
				
			||||||
 | 
					                const conversation = this.findConversation(undefined, message.touserid, option);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                message.text = message.smallmessage;
 | 
					                message.text = message.smallmessage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -455,7 +537,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
                        this.addLastOfflineMessage(conversation, message);
 | 
					                        this.addLastOfflineMessage(conversation, message);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    // Get the user data and create a new conversation.
 | 
					                    // Get the user data and create a new conversation if it belongs to the current option.
 | 
				
			||||||
                    promises.push(this.userProvider.getProfile(message.touserid, undefined, true).catch(() => {
 | 
					                    promises.push(this.userProvider.getProfile(message.touserid, undefined, true).catch(() => {
 | 
				
			||||||
                        // User not found.
 | 
					                        // User not found.
 | 
				
			||||||
                    }).then((user) => {
 | 
					                    }).then((user) => {
 | 
				
			||||||
@ -523,18 +605,13 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
     * @return {Promise<any>} Promise resolved when done.
 | 
					     * @return {Promise<any>} Promise resolved when done.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    refreshData(refresher?: any, refreshUnreadCounts: boolean = true): Promise<any> {
 | 
					    refreshData(refresher?: any, refreshUnreadCounts: boolean = true): Promise<any> {
 | 
				
			||||||
 | 
					        // Don't invalidate conversations and so, they always try to get latest data.
 | 
				
			||||||
        const promises = [
 | 
					        const promises = [
 | 
				
			||||||
            this.messagesProvider.invalidateConversations(),
 | 
					 | 
				
			||||||
            this.messagesProvider.invalidateConversationCounts(),
 | 
					 | 
				
			||||||
            this.messagesProvider.invalidateContactRequestsCountCache()
 | 
					            this.messagesProvider.invalidateContactRequestsCountCache()
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (refreshUnreadCounts) {
 | 
					 | 
				
			||||||
            promises.push(this.messagesProvider.invalidateUnreadConversationCounts());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return this.utils.allPromises(promises).finally(() => {
 | 
					        return this.utils.allPromises(promises).finally(() => {
 | 
				
			||||||
            return this.fetchData().finally(() => {
 | 
					            return this.fetchData(refreshUnreadCounts).finally(() => {
 | 
				
			||||||
                if (refresher) {
 | 
					                if (refresher) {
 | 
				
			||||||
                    refresher.complete();
 | 
					                    refresher.complete();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -551,8 +628,11 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
        if (option.expanded) {
 | 
					        if (option.expanded) {
 | 
				
			||||||
            // Already expanded, close it.
 | 
					            // Already expanded, close it.
 | 
				
			||||||
            option.expanded = false;
 | 
					            option.expanded = false;
 | 
				
			||||||
 | 
					            this.loadCurrentListElement();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            this.expandOption(option);
 | 
					            this.expandOption(option).catch((error) => {
 | 
				
			||||||
 | 
					                this.domUtils.showErrorModalDefault(error, 'addon.messages.errorwhileretrievingdiscussions', true);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -560,13 +640,42 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
     * Expand a certain option.
 | 
					     * Expand a certain option.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {any} option The option to expand.
 | 
					     * @param {any} option The option to expand.
 | 
				
			||||||
 | 
					     * @param {booleam} [refreshUnreadCounts=true] Whether to refresh unread counts.
 | 
				
			||||||
 | 
					     * @return {Promise<any>} Promise resolved when done.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected expandOption(option: any): void {
 | 
					    protected expandOption(option: any, refreshUnreadCounts: boolean = true): Promise<any> {
 | 
				
			||||||
        // Collapse all and expand the right one.
 | 
					        // Collapse all and expand the right one.
 | 
				
			||||||
        this.favourites.expanded = false;
 | 
					        this.favourites.expanded = false;
 | 
				
			||||||
        this.group.expanded = false;
 | 
					        this.group.expanded = false;
 | 
				
			||||||
        this.individual.expanded = false;
 | 
					        this.individual.expanded = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        option.expanded = true;
 | 
					        option.expanded = true;
 | 
				
			||||||
 | 
					        option.loading = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return this.fetchDataForOption(option, false, refreshUnreadCounts).then(() => {
 | 
				
			||||||
 | 
					            this.loadCurrentListElement();
 | 
				
			||||||
 | 
					        }).catch((error) => {
 | 
				
			||||||
 | 
					            option.expanded = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return Promise.reject(error);
 | 
				
			||||||
 | 
					        }).finally(() => {
 | 
				
			||||||
 | 
					            option.loading = false;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Load the current list element based on the expanded list.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected loadCurrentListElement(): void {
 | 
				
			||||||
 | 
					        if (this.favourites.expanded) {
 | 
				
			||||||
 | 
					            this.currentListEl = this.favListEl && this.favListEl.nativeElement;
 | 
				
			||||||
 | 
					        } else if (this.group.expanded) {
 | 
				
			||||||
 | 
					            this.currentListEl = this.groupListEl && this.groupListEl.nativeElement;
 | 
				
			||||||
 | 
					        } else if (this.individual.expanded) {
 | 
				
			||||||
 | 
					            this.currentListEl = this.indListEl && this.indListEl.nativeElement;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            this.currentListEl = undefined;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -187,7 +187,13 @@ export class AddonMessagesMainMenuHandler implements CoreMainMenuHandler, CoreCr
 | 
				
			|||||||
     * @return {number} Time between consecutive executions (in ms).
 | 
					     * @return {number} Time between consecutive executions (in ms).
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    getInterval(): number {
 | 
					    getInterval(): number {
 | 
				
			||||||
        return this.appProvider.isDesktop() ? 60000 : 600000; // 1 or 10 minutes.
 | 
					        if (this.appProvider.isDesktop()) {
 | 
				
			||||||
 | 
					            return 60000; // Desktop usually has a WiFi connection, check it every minute.
 | 
				
			||||||
 | 
					        } else if (this.messagesProvider.isGroupMessagingEnabled() || this.messagesProvider.isMessageCountEnabled()) {
 | 
				
			||||||
 | 
					            return 300000; // We have a WS to check the number, check it every 5 minutes.
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return 600000; // Check it every 10 minutes.
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -917,10 +917,10 @@ export class AddonMessagesProvider {
 | 
				
			|||||||
     * Get the discussions of a certain user. This function is used in Moodle sites higher than 3.6.
 | 
					     * Get the discussions of a certain user. This function is used in Moodle sites higher than 3.6.
 | 
				
			||||||
     * If the site is older than 3.6, please use getDiscussions.
 | 
					     * If the site is older than 3.6, please use getDiscussions.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {number} [limitFrom=0] The offset to start at.
 | 
					 | 
				
			||||||
     * @param {number} [type] Filter by type.
 | 
					     * @param {number} [type] Filter by type.
 | 
				
			||||||
     * @param {boolean} [favourites] Whether to restrict the results to contain NO favourite conversations (false), ONLY favourite
 | 
					     * @param {boolean} [favourites] Whether to restrict the results to contain NO favourite conversations (false), ONLY favourite
 | 
				
			||||||
     *                               conversation (true), or ignore any restriction altogether (undefined or null).
 | 
					     *                               conversation (true), or ignore any restriction altogether (undefined or null).
 | 
				
			||||||
 | 
					     * @param {number} [limitFrom=0] The offset to start at.
 | 
				
			||||||
     * @param {string} [siteId] Site ID. If not defined, use current site.
 | 
					     * @param {string} [siteId] Site ID. If not defined, use current site.
 | 
				
			||||||
     * @param {number} [userId] User ID. If not defined, current user in the site.
 | 
					     * @param {number} [userId] User ID. If not defined, current user in the site.
 | 
				
			||||||
     * @return {Promise<any>} Promise resolved with the conversations.
 | 
					     * @return {Promise<any>} Promise resolved with the conversations.
 | 
				
			||||||
@ -966,13 +966,15 @@ export class AddonMessagesProvider {
 | 
				
			|||||||
     * Get conversation counts by type.
 | 
					     * Get conversation counts by type.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {string} [siteId] Site ID. If not defined, use current site.
 | 
					     * @param {string} [siteId] Site ID. If not defined, use current site.
 | 
				
			||||||
     * @return {Promise<any>} Promise resolved with favourite, individual and group conversation counts.
 | 
					     * @return {Promise<favourites: number, individual: number, group: number>} Promise resolved with favourite, individual and
 | 
				
			||||||
 | 
					     *                                      group conversation counts.
 | 
				
			||||||
     * @since 3.6
 | 
					     * @since 3.6
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    getConversationCounts(siteId?: string): Promise<{favourites: number, individual: number, group: number}> {
 | 
					    getConversationCounts(siteId?: string): Promise<{favourites: number, individual: number, group: number}> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return this.sitesProvider.getSite(siteId).then((site) => {
 | 
					        return this.sitesProvider.getSite(siteId).then((site) => {
 | 
				
			||||||
            const preSets = {
 | 
					            const preSets = {
 | 
				
			||||||
                cacheKey: this.getCacheKeyForConversationCounts(),
 | 
					                cacheKey: this.getCacheKeyForConversationCounts()
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return site.read('core_message_get_conversation_counts', {}, preSets).then((result) => {
 | 
					            return site.read('core_message_get_conversation_counts', {}, preSets).then((result) => {
 | 
				
			||||||
@ -1350,7 +1352,7 @@ export class AddonMessagesProvider {
 | 
				
			|||||||
            if (this.isGroupMessagingEnabled()) {
 | 
					            if (this.isGroupMessagingEnabled()) {
 | 
				
			||||||
                // @since 3.6
 | 
					                // @since 3.6
 | 
				
			||||||
                const preSets = {
 | 
					                const preSets = {
 | 
				
			||||||
                    cacheKey: this.getCacheKeyForUnreadConversationCounts(),
 | 
					                    cacheKey: this.getCacheKeyForUnreadConversationCounts()
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                promise = site.read('core_message_get_unread_conversation_counts', {}, preSets).then((result) => {
 | 
					                promise = site.read('core_message_get_unread_conversation_counts', {}, preSets).then((result) => {
 | 
				
			||||||
@ -1914,12 +1916,11 @@ export class AddonMessagesProvider {
 | 
				
			|||||||
     * Refresh unread conversation counts and trigger event.
 | 
					     * Refresh unread conversation counts and trigger event.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {string} [siteId] Site ID. If not defined, use current site.
 | 
					     * @param {string} [siteId] Site ID. If not defined, use current site.
 | 
				
			||||||
     * @param {number} [conversationId] ID of the conversation that was read.
 | 
					 | 
				
			||||||
     * @param {number} [userId] ID of ther other user of the conversation that was read.
 | 
					 | 
				
			||||||
     * @return {Promise<any>} Resolved with the unread favourite, individual and group conversation counts.
 | 
					     * @return {Promise<any>} Resolved with the unread favourite, individual and group conversation counts.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    refreshUnreadConversationCounts(siteId?: string, conversationId?: number, userId?: number):
 | 
					    refreshUnreadConversationCounts(siteId?: string):
 | 
				
			||||||
            Promise<{favourites: number, individual: number, group: number, orMore?: boolean}> {
 | 
					            Promise<{favourites: number, individual: number, group: number, orMore?: boolean}> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        siteId = siteId || this.sitesProvider.getCurrentSiteId();
 | 
					        siteId = siteId || this.sitesProvider.getCurrentSiteId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return this.invalidateUnreadConversationCounts(siteId).then(() => {
 | 
					        return this.invalidateUnreadConversationCounts(siteId).then(() => {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user