MOBILE-2327 messages: Add badge to main menu
This commit is contained in:
		
							parent
							
								
									7c42b886b1
								
							
						
					
					
						commit
						7790596edf
					
				@ -56,6 +56,7 @@ export class AddonMessagesModule {
 | 
			
		||||
        contentLinksDelegate.registerHandler(discussionLinkHandler);
 | 
			
		||||
        userDelegate.registerHandler(sendMessageHandler);
 | 
			
		||||
        cronDelegate.register(syncHandler);
 | 
			
		||||
        cronDelegate.register(mainmenuHandler);
 | 
			
		||||
 | 
			
		||||
        // Sync some discussions when device goes online.
 | 
			
		||||
        network.onConnect().subscribe(() => {
 | 
			
		||||
 | 
			
		||||
@ -14,17 +14,43 @@
 | 
			
		||||
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { AddonMessagesProvider } from './messages';
 | 
			
		||||
import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '../../../core/mainmenu/providers/delegate';
 | 
			
		||||
import { CoreMainMenuDelegate, CoreMainMenuHandler, CoreMainMenuHandlerToDisplay } from
 | 
			
		||||
    '../../../core/mainmenu/providers/delegate';
 | 
			
		||||
import { CoreCronHandler } from '../../../providers/cron';
 | 
			
		||||
import { CoreSitesProvider } from '../../../providers/sites';
 | 
			
		||||
import { CoreEventsProvider } from '../../../providers/events';
 | 
			
		||||
import { CoreAppProvider } from '../../../providers/app';
 | 
			
		||||
import { CoreTextUtilsProvider } from '../../../providers/utils/text';
 | 
			
		||||
import { CoreLocalNotificationsProvider } from '../../../providers/local-notifications';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handler to inject an option into main menu.
 | 
			
		||||
 */
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class AddonMessagesMainMenuHandler implements CoreMainMenuHandler {
 | 
			
		||||
export class AddonMessagesMainMenuHandler implements CoreMainMenuHandler, CoreCronHandler {
 | 
			
		||||
    name = 'AddonMessages';
 | 
			
		||||
    priority = 600;
 | 
			
		||||
    protected badge = '';
 | 
			
		||||
    protected loading = true;
 | 
			
		||||
 | 
			
		||||
    constructor(private messagesProvider: AddonMessagesProvider) { }
 | 
			
		||||
    constructor(private messagesProvider: AddonMessagesProvider, private sitesProvider: CoreSitesProvider,
 | 
			
		||||
            private eventsProvider: CoreEventsProvider, private appProvider: CoreAppProvider,
 | 
			
		||||
            private localNotificationsProvider: CoreLocalNotificationsProvider, private textUtils: CoreTextUtilsProvider) {
 | 
			
		||||
 | 
			
		||||
        eventsProvider.on(AddonMessagesProvider.READ_CHANGED_EVENT, (data) => {
 | 
			
		||||
            this.updateBadge(data.siteId);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        eventsProvider.on(AddonMessagesProvider.READ_CRON_EVENT, (data) => {
 | 
			
		||||
            this.updateBadge(data.siteId);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Reset info on logout.
 | 
			
		||||
        eventsProvider.on(CoreEventsProvider.LOGOUT, (data) => {
 | 
			
		||||
            this.badge = '';
 | 
			
		||||
            this.loading = true;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if the handler is enabled on a site level.
 | 
			
		||||
@ -38,14 +64,133 @@ export class AddonMessagesMainMenuHandler implements CoreMainMenuHandler {
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the data needed to render the handler.
 | 
			
		||||
     *
 | 
			
		||||
     * @return {CoreMainMenuHandlerData} Data needed to render the handler.
 | 
			
		||||
     * @return {CoreMainMenuHandlerToDisplay} Data needed to render the handler.
 | 
			
		||||
     */
 | 
			
		||||
    getDisplayData(): CoreMainMenuHandlerData {
 | 
			
		||||
    getDisplayData(): CoreMainMenuHandlerToDisplay {
 | 
			
		||||
        if (this.loading) {
 | 
			
		||||
            this.updateBadge();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            icon: 'chatbubbles',
 | 
			
		||||
            title: 'addon.messages.messages',
 | 
			
		||||
            page: 'AddonMessagesIndexPage',
 | 
			
		||||
            class: 'addon-messages-handler'
 | 
			
		||||
            class: 'addon-messages-handler',
 | 
			
		||||
            showBadge: true, // Do not check isMessageCountEnabled because we'll use fallback it not enabled.,
 | 
			
		||||
            badge: this.badge,
 | 
			
		||||
            loading: this.loading
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Triggers an update for the badge number and loading status. Mandatory if showBadge is enabled.
 | 
			
		||||
     *
 | 
			
		||||
     * @param {string} siteId Site ID or current Site if undefined.
 | 
			
		||||
     */
 | 
			
		||||
    updateBadge(siteId?: string): void {
 | 
			
		||||
        siteId = siteId || this.sitesProvider.getCurrentSiteId();
 | 
			
		||||
        if (!siteId) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.messagesProvider.getUnreadConversationsCount(undefined, siteId).then((unread) => {
 | 
			
		||||
            // Leave badge enter if there is a 0+ or a 0.
 | 
			
		||||
            this.badge = parseInt(unread, 10) > 0 ? unread : '';
 | 
			
		||||
            // Update badge.
 | 
			
		||||
            /*
 | 
			
		||||
            $mmaPushNotifications = $mmAddonManager.get('$mmaPushNotifications');
 | 
			
		||||
            if ($mmaPushNotifications) {
 | 
			
		||||
                $mmaPushNotifications.updateAddonCounter(siteId, 'mmaMessages', unread);
 | 
			
		||||
            }*/
 | 
			
		||||
        }).catch(() => {
 | 
			
		||||
            this.badge = '';
 | 
			
		||||
        }).finally(() => {
 | 
			
		||||
            this.loading = false;
 | 
			
		||||
            this.eventsProvider.trigger(CoreMainMenuDelegate.UPDATE_BADGE_EVENT, {
 | 
			
		||||
                name: this.name,
 | 
			
		||||
                badge: this.badge
 | 
			
		||||
            }, siteId);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the process.
 | 
			
		||||
     * Receives the ID of the site affected, undefined for all sites.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  {string} [siteId] ID of the site affected, undefined for all sites.
 | 
			
		||||
     * @return {Promise<any>}         Promise resolved when done, rejected if failure.
 | 
			
		||||
     */
 | 
			
		||||
    execute(siteId?: string): Promise<any> {
 | 
			
		||||
        if (this.sitesProvider.isCurrentSite(siteId)) {
 | 
			
		||||
            this.eventsProvider.trigger(AddonMessagesProvider.READ_CRON_EVENT, undefined, siteId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.appProvider.isDesktop() && this.localNotificationsProvider.isAvailable()) {
 | 
			
		||||
            /*$mmEmulatorHelper.checkNewNotifications(
 | 
			
		||||
                    AddonMessagesProvider.PUSH_SIMULATION_COMPONENT, this.fetchMessages, this.getTitleAndText, siteId);*/
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return Promise.resolve();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the time between consecutive executions.
 | 
			
		||||
     *
 | 
			
		||||
     * @return {number} Time between consecutive executions (in ms).
 | 
			
		||||
     */
 | 
			
		||||
    getInterval(): number {
 | 
			
		||||
        return this.appProvider.isDesktop() ? 60000 : 600000; // 1 or 10 minutes.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Whether it's a synchronization process or not.
 | 
			
		||||
     *
 | 
			
		||||
     * @return {boolean} True if is a sync process, false otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    isSync(): boolean {
 | 
			
		||||
        // This is done to use only wifi if using the fallback function.
 | 
			
		||||
        // In desktop it is always sync, since it fetches messages to see if there's a new one.
 | 
			
		||||
        return !this.messagesProvider.isMessageCountEnabled() || this.appProvider.isDesktop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Whether the process should be executed during a manual sync.
 | 
			
		||||
     *
 | 
			
		||||
     * @return {boolean} True if is a manual sync process, false otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    canManualSync(): boolean {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the latest unread received messages from a site.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  {string} [siteId] Site ID. Default current.
 | 
			
		||||
     * @return {Promise<any>}    Promise resolved with the notifications.
 | 
			
		||||
     */
 | 
			
		||||
    protected fetchMessages(siteId?: string): Promise<any> {
 | 
			
		||||
        return this.messagesProvider.getUnreadReceivedMessages(true, false, true, siteId).then((response) => {
 | 
			
		||||
            return response.messages;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Given a message, return the title and the text for the message.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  {any} message Message.
 | 
			
		||||
     * @return {Promise<any>}        Promise resolved with an object with title and text.
 | 
			
		||||
     */
 | 
			
		||||
    protected getTitleAndText(message: any): Promise<any> {
 | 
			
		||||
        const data = {
 | 
			
		||||
            title: message.userfromfullname,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return this.textUtils.formatText(message.text, true, true).catch(() => {
 | 
			
		||||
            return message.text;
 | 
			
		||||
        }).then((formattedText) => {
 | 
			
		||||
            data['text'] = formattedText;
 | 
			
		||||
 | 
			
		||||
            return data;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -140,9 +140,9 @@ export class AddonMessagesProvider {
 | 
			
		||||
            if (lfReceivedUnread > 0 || lfReceivedRead > 0 || lfSentUnread > 0 || lfSentRead > 0) {
 | 
			
		||||
                // Do not use cache when retrieving older messages. This is to prevent storing too much data
 | 
			
		||||
                // and to prevent inconsistencies between "pages" loaded.
 | 
			
		||||
                preSets['getFromCache'] = 0;
 | 
			
		||||
                preSets['saveToCache'] = 0;
 | 
			
		||||
                preSets['emergencyCache'] = 0;
 | 
			
		||||
                preSets['getFromCache'] = false;
 | 
			
		||||
                preSets['saveToCache'] = false;
 | 
			
		||||
                preSets['emergencyCache'] = false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Get message received by current user.
 | 
			
		||||
@ -385,6 +385,94 @@ export class AddonMessagesProvider {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get unread conversations count. Do not cache calls.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  {number} [userId] The user id who received the message. If not defined, use current user.
 | 
			
		||||
     * @param  {string} [siteId] Site ID. If not defined, use current site.
 | 
			
		||||
     * @return {Promise<any>}    Promise resolved with the message unread count.
 | 
			
		||||
     */
 | 
			
		||||
    getUnreadConversationsCount(userId?: number, siteId?: string): Promise<any> {
 | 
			
		||||
        return this.sitesProvider.getSite(siteId).then((site) => {
 | 
			
		||||
            userId = userId || site.getUserId();
 | 
			
		||||
 | 
			
		||||
            // @since 3.2
 | 
			
		||||
            if (site.wsAvailable('core_message_get_unread_conversations_count')) {
 | 
			
		||||
                const params = {
 | 
			
		||||
                        useridto: userId
 | 
			
		||||
                    },
 | 
			
		||||
                    preSets = {
 | 
			
		||||
                        getFromCache: false,
 | 
			
		||||
                        emergencyCache: false,
 | 
			
		||||
                        saveToCache: false,
 | 
			
		||||
                        typeExpected: 'number'
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                return site.read('core_message_get_unread_conversations_count', params, preSets).catch(() => {
 | 
			
		||||
                    // Return no messages if the call fails.
 | 
			
		||||
                    return 0;
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Fallback call.
 | 
			
		||||
            const params = {
 | 
			
		||||
                read: 0,
 | 
			
		||||
                limitfrom: 0,
 | 
			
		||||
                limitnum: this.LIMIT_MESSAGES + 1,
 | 
			
		||||
                useridto: userId,
 | 
			
		||||
                useridfrom: 0,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            return this.getMessages(params, undefined, false, siteId).then((response) => {
 | 
			
		||||
                // Count the discussions by filtering same senders.
 | 
			
		||||
                const discussions = {};
 | 
			
		||||
                let count;
 | 
			
		||||
                response.messages.forEach((message) => {
 | 
			
		||||
                    discussions[message.useridto] = 1;
 | 
			
		||||
                });
 | 
			
		||||
                count = Object.keys(discussions).length;
 | 
			
		||||
 | 
			
		||||
                // Add + sign if there are more than the limit reachable.
 | 
			
		||||
                return (count > this.LIMIT_MESSAGES) ? count + '+' : count;
 | 
			
		||||
            }).catch(() => {
 | 
			
		||||
                // Return no messages if the call fails.
 | 
			
		||||
                return 0;
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the latest unread received messages.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  {boolean} [toDisplay=true] True if messages will be displayed to the user, either in view or in a notification.
 | 
			
		||||
     * @param  {boolean} [forceCache]     True if it should return cached data. Has priority over ignoreCache.
 | 
			
		||||
     * @param  {boolean} [ignoreCache]    True if it should ignore cached data (it will always fail in offline or server down).
 | 
			
		||||
     * @param  {string} [siteId]          Site ID. If not defined, use current site.
 | 
			
		||||
     * @return {Promise<any>}                  Promise resolved with the message unread count.
 | 
			
		||||
     */
 | 
			
		||||
    getUnreadReceivedMessages(toDisplay: boolean = true, forceCache: boolean = false, ignoreCache: boolean = false,
 | 
			
		||||
            siteId?: string): Promise<any> {
 | 
			
		||||
        return this.sitesProvider.getSite(siteId).then((site) => {
 | 
			
		||||
            const params = {
 | 
			
		||||
                    read: 0,
 | 
			
		||||
                    limitfrom: 0,
 | 
			
		||||
                    limitnum: this.LIMIT_MESSAGES,
 | 
			
		||||
                    useridto: site.getUserId(),
 | 
			
		||||
                    useridfrom: 0
 | 
			
		||||
                },
 | 
			
		||||
                preSets = {};
 | 
			
		||||
 | 
			
		||||
            if (forceCache) {
 | 
			
		||||
                preSets['omitExpires'] = true;
 | 
			
		||||
            } else if (ignoreCache) {
 | 
			
		||||
                preSets['getFromCache'] = false;
 | 
			
		||||
                preSets['emergencyCache'] = false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return this.getMessages(params, preSets, toDisplay, siteId);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Invalidate contacts cache.
 | 
			
		||||
     *
 | 
			
		||||
@ -436,6 +524,16 @@ export class AddonMessagesProvider {
 | 
			
		||||
        return this.sitesProvider.getCurrentSite().wsAvailable('core_message_mark_all_messages_as_read');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns whether or not we can count unread messages.
 | 
			
		||||
     *
 | 
			
		||||
     * @return {boolean} True if enabled, false otherwise.
 | 
			
		||||
     * @since  3.2
 | 
			
		||||
     */
 | 
			
		||||
    isMessageCountEnabled(): boolean {
 | 
			
		||||
        return this.sitesProvider.getCurrentSite().wsAvailable('core_message_get_unread_conversations_count');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns whether or not the plugin is enabled in a certain site.
 | 
			
		||||
     *
 | 
			
		||||
 | 
			
		||||
@ -43,7 +43,7 @@ core-course-module {
 | 
			
		||||
            pointer-events: auto;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .core-module-buttons-more  .spinner {
 | 
			
		||||
        .core-module-buttons-more .spinner {
 | 
			
		||||
            right: 13px;
 | 
			
		||||
            position: absolute;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
<ion-tabs *ngIf="loaded" #mainTabs [selectedIndex]="initialTab" tabsPlacement="bottom" tabsLayout="title-hide">
 | 
			
		||||
    <ion-tab [enabled]="false" [show]="false" [root]="redirectPage" [rootParams]="redirectParams"></ion-tab>
 | 
			
		||||
    <ion-tab *ngFor="let tab of tabs" [root]="tab.page" [tabTitle]="tab.title | translate" [tabIcon]="tab.icon" class="{{tab.class}}"></ion-tab>
 | 
			
		||||
    <ion-tab *ngFor="let tab of tabs" [root]="tab.page" [tabTitle]="tab.title | translate" [tabIcon]="tab.icon" [tabBadge]="tab.badge" class="{{tab.class}}"></ion-tab>
 | 
			
		||||
</ion-tabs>
 | 
			
		||||
@ -64,9 +64,10 @@ export class CoreMainMenuPage implements OnDestroy {
 | 
			
		||||
    };
 | 
			
		||||
    protected moreTabAdded = false;
 | 
			
		||||
    protected redirectPageLoaded = false;
 | 
			
		||||
    protected updateBadgeObserver;
 | 
			
		||||
 | 
			
		||||
    constructor(private menuDelegate: CoreMainMenuDelegate, private sitesProvider: CoreSitesProvider, navParams: NavParams,
 | 
			
		||||
            private navCtrl: NavController, eventsProvider: CoreEventsProvider) {
 | 
			
		||||
            private navCtrl: NavController, private eventsProvider: CoreEventsProvider) {
 | 
			
		||||
        this.redirectPage = navParams.get('redirectPage');
 | 
			
		||||
        this.redirectParams = navParams.get('redirectParams');
 | 
			
		||||
    }
 | 
			
		||||
@ -84,6 +85,16 @@ export class CoreMainMenuPage implements OnDestroy {
 | 
			
		||||
        const site = this.sitesProvider.getCurrentSite(),
 | 
			
		||||
            displaySiteHome = site.getInfo() && site.getInfo().userhomepage === 0;
 | 
			
		||||
 | 
			
		||||
        this.updateBadgeObserver = this.eventsProvider.on(CoreMainMenuDelegate.UPDATE_BADGE_EVENT, (data) => {
 | 
			
		||||
            const tab = this.tabs.find((tab) => {
 | 
			
		||||
                return tab.showBadge && tab['name'] == data.name;
 | 
			
		||||
            });
 | 
			
		||||
            if (tab) {
 | 
			
		||||
                tab.badge = data.badge;
 | 
			
		||||
                tab.loading = false;
 | 
			
		||||
            }
 | 
			
		||||
        }, site.getId());
 | 
			
		||||
 | 
			
		||||
        this.subscription = this.menuDelegate.getHandlers().subscribe((handlers) => {
 | 
			
		||||
            handlers = handlers.slice(0, CoreMainMenuProvider.NUM_MAIN_HANDLERS); // Get main handlers.
 | 
			
		||||
 | 
			
		||||
@ -128,5 +139,6 @@ export class CoreMainMenuPage implements OnDestroy {
 | 
			
		||||
     */
 | 
			
		||||
    ngOnDestroy(): void {
 | 
			
		||||
        this.subscription && this.subscription.unsubscribe();
 | 
			
		||||
        this.updateBadgeObserver && this.updateBadgeObserver.off();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -18,9 +18,8 @@
 | 
			
		||||
        <ion-item *ngFor="let handler of handlers" [ngClass]="['core-moremenu-handler', handler.class]" (click)="openHandler(handler)" title="{{ handler.title | translate }}" detail-push>
 | 
			
		||||
            <ion-icon [name]="handler.icon" item-start></ion-icon>
 | 
			
		||||
            <p>{{ handler.title | translate}}</p>
 | 
			
		||||
            <!-- @todo: Badge. -->
 | 
			
		||||
            <!-- <span ng-show="!loading && badge" class="badge badge-positive">{{badge}}</span>
 | 
			
		||||
            <ion-spinner ng-if="loading" class="icon"></ion-spinner> -->
 | 
			
		||||
            <ion-badge item-end *ngIf="handler.showBadge" [hidden]="handler.loading || !handler.badge">{{badge}}</ion-badge>
 | 
			
		||||
            <ion-spinner item-end *ngIf="handler.showBadge && handler.loading"></ion-spinner>
 | 
			
		||||
        </ion-item>
 | 
			
		||||
        <div *ngFor="let item of customItems" class="core-moremenu-customitem">
 | 
			
		||||
            <a ion-item *ngIf="item.type != 'embedded'" [href]="item.url" core-link [capture]="item.type == 'app'" [inApp]="item.type == 'inappbrowser'" title="{{item.label}}">
 | 
			
		||||
 | 
			
		||||
@ -40,9 +40,11 @@ export class CoreMainMenuMorePage implements OnDestroy {
 | 
			
		||||
    protected subscription;
 | 
			
		||||
    protected langObserver;
 | 
			
		||||
    protected updateSiteObserver;
 | 
			
		||||
    protected updateBadgeObserver;
 | 
			
		||||
 | 
			
		||||
    constructor(private menuDelegate: CoreMainMenuDelegate, private sitesProvider: CoreSitesProvider,
 | 
			
		||||
            private navCtrl: NavController, private mainMenuProvider: CoreMainMenuProvider, eventsProvider: CoreEventsProvider) {
 | 
			
		||||
            private navCtrl: NavController, private mainMenuProvider: CoreMainMenuProvider,
 | 
			
		||||
            private eventsProvider: CoreEventsProvider) {
 | 
			
		||||
 | 
			
		||||
        this.langObserver = eventsProvider.on(CoreEventsProvider.LANGUAGE_CHANGED, this.loadSiteInfo.bind(this));
 | 
			
		||||
        this.updateSiteObserver = eventsProvider.on(CoreEventsProvider.SITE_UPDATED, this.loadSiteInfo.bind(this),
 | 
			
		||||
@ -59,6 +61,16 @@ export class CoreMainMenuMorePage implements OnDestroy {
 | 
			
		||||
            this.handlers = handlers.slice(CoreMainMenuProvider.NUM_MAIN_HANDLERS); // Remove the main handlers.
 | 
			
		||||
            this.handlersLoaded = this.menuDelegate.areHandlersLoaded();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.updateBadgeObserver = this.eventsProvider.on(CoreMainMenuDelegate.UPDATE_BADGE_EVENT, (data) => {
 | 
			
		||||
            const handler = this.handlers.find((handler) => {
 | 
			
		||||
                return handler.showBadge && handler['name'] == data.name;
 | 
			
		||||
            });
 | 
			
		||||
            if (handler) {
 | 
			
		||||
                handler.badge = data.badge;
 | 
			
		||||
                handler.loading = false;
 | 
			
		||||
            }
 | 
			
		||||
        }, this.sitesProvider.getCurrentSiteId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -68,6 +80,7 @@ export class CoreMainMenuMorePage implements OnDestroy {
 | 
			
		||||
        if (this.subscription) {
 | 
			
		||||
            this.subscription.unsubscribe();
 | 
			
		||||
        }
 | 
			
		||||
        this.updateBadgeObserver && this.updateBadgeObserver.off();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -32,7 +32,6 @@ export interface CoreMainMenuHandler extends CoreDelegateHandler {
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the data needed to render the handler.
 | 
			
		||||
     *
 | 
			
		||||
     * @param {number} courseId The course ID.
 | 
			
		||||
     * @return {CoreMainMenuHandlerData} Data.
 | 
			
		||||
     */
 | 
			
		||||
    getDisplayData(): CoreMainMenuHandlerData;
 | 
			
		||||
@ -65,13 +64,30 @@ export interface CoreMainMenuHandlerData {
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     */
 | 
			
		||||
    class?: string;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * If the handler has badge to show or not.
 | 
			
		||||
     * @type {boolean}
 | 
			
		||||
     */
 | 
			
		||||
    showBadge?: boolean;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Text to display on the badge. Only used if showBadge is true.
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     */
 | 
			
		||||
    badge?: string;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * If true, the badge number is being loaded. Only used if showBadge is true.
 | 
			
		||||
     * @type {boolean}
 | 
			
		||||
     */
 | 
			
		||||
    loading?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Data returned by the delegate for each handler.
 | 
			
		||||
 */
 | 
			
		||||
export interface CoreMainMenuHandlerToDisplay extends CoreMainMenuHandlerData {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Name of the handler.
 | 
			
		||||
     * @type {string}
 | 
			
		||||
@ -91,6 +107,8 @@ export class CoreMainMenuDelegate extends CoreDelegate {
 | 
			
		||||
    protected siteHandlers: Subject<CoreMainMenuHandlerToDisplay[]> = new BehaviorSubject<CoreMainMenuHandlerToDisplay[]>([]);
 | 
			
		||||
    protected featurePrefix = '$mmSideMenuDelegate_';
 | 
			
		||||
 | 
			
		||||
    static UPDATE_BADGE_EVENT = 'update_main_menu_badge';
 | 
			
		||||
 | 
			
		||||
    constructor(protected loggerProvider: CoreLoggerProvider, protected sitesProvider: CoreSitesProvider,
 | 
			
		||||
            protected eventsProvider: CoreEventsProvider) {
 | 
			
		||||
        super('CoreMainMenuDelegate', loggerProvider, sitesProvider, eventsProvider);
 | 
			
		||||
@ -135,6 +153,7 @@ export class CoreMainMenuDelegate extends CoreDelegate {
 | 
			
		||||
                data = handler.getDisplayData();
 | 
			
		||||
 | 
			
		||||
            handlersData.push({
 | 
			
		||||
                name: name,
 | 
			
		||||
                data: data,
 | 
			
		||||
                priority: handler.priority
 | 
			
		||||
            });
 | 
			
		||||
@ -147,6 +166,8 @@ export class CoreMainMenuDelegate extends CoreDelegate {
 | 
			
		||||
 | 
			
		||||
        // Return only the display data.
 | 
			
		||||
        const displayData = handlersData.map((item) => {
 | 
			
		||||
            item.data.name = item.name;
 | 
			
		||||
 | 
			
		||||
            return item.data;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user