forked from EVOgeek/Vmeda.Online
		
	Merge pull request #3043 from dpalou/MOBILE-3951
MOBILE-3951 calendar: Schedule notifications from service
This commit is contained in:
		
						commit
						af9e1ce486
					
				
							
								
								
									
										6
									
								
								.github/workflows/performance.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/performance.yml
									
									
									
									
										vendored
									
									
								
							@ -18,9 +18,9 @@ jobs:
 | 
			
		||||
        node-version: '${{ steps.nvmrc.outputs.node_version }}'
 | 
			
		||||
    - name: Additional checkouts
 | 
			
		||||
      run: |
 | 
			
		||||
        git clone --branch master --depth 1 git://github.com/moodle/moodle $GITHUB_WORKSPACE/moodle
 | 
			
		||||
        git clone --branch integration --depth 1 git://github.com/moodlehq/moodle-local_moodlemobileapp $GITHUB_WORKSPACE/moodle/local/moodlemobileapp
 | 
			
		||||
        git clone --branch master --depth 1 git://github.com/moodlehq/moodle-docker $GITHUB_WORKSPACE/moodle-docker
 | 
			
		||||
        git clone --branch master --depth 1 https://github.com/moodle/moodle $GITHUB_WORKSPACE/moodle
 | 
			
		||||
        git clone --branch integration --depth 1 https://github.com/moodlehq/moodle-local_moodlemobileapp $GITHUB_WORKSPACE/moodle/local/moodlemobileapp
 | 
			
		||||
        git clone --branch master --depth 1 https://github.com/moodlehq/moodle-docker $GITHUB_WORKSPACE/moodle-docker
 | 
			
		||||
    - name: Install npm packages
 | 
			
		||||
      run: npm ci
 | 
			
		||||
    - name: Generate Behat tests plugin
 | 
			
		||||
 | 
			
		||||
@ -41,7 +41,6 @@ import { AddonCalendarFilter, AddonCalendarHelper } from '../../services/calenda
 | 
			
		||||
import { AddonCalendarOffline } from '../../services/calendar-offline';
 | 
			
		||||
import { CoreCategoryData, CoreCourses } from '@features/courses/services/courses';
 | 
			
		||||
import { CoreApp } from '@services/app';
 | 
			
		||||
import { CoreLocalNotifications } from '@services/local-notifications';
 | 
			
		||||
import { CoreSwipeSlidesComponent } from '@components/swipe-slides/swipe-slides';
 | 
			
		||||
import {
 | 
			
		||||
    CoreSwipeSlidesDynamicItem,
 | 
			
		||||
@ -78,7 +77,6 @@ export class AddonCalendarCalendarComponent implements OnInit, DoCheck, OnDestro
 | 
			
		||||
    protected differ: KeyValueDiffer<unknown, unknown>; // To detect changes in the data input.
 | 
			
		||||
    // Observers and listeners.
 | 
			
		||||
    protected undeleteEventObserver: CoreEventObserver;
 | 
			
		||||
    protected obsDefaultTimeChange?: CoreEventObserver;
 | 
			
		||||
    protected managerUnsubscribe?: () => void;
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
@ -86,23 +84,6 @@ export class AddonCalendarCalendarComponent implements OnInit, DoCheck, OnDestro
 | 
			
		||||
    ) {
 | 
			
		||||
        this.currentSiteId = CoreSites.getCurrentSiteId();
 | 
			
		||||
 | 
			
		||||
        if (CoreLocalNotifications.isAvailable()) {
 | 
			
		||||
            // Re-schedule events if default time changes.
 | 
			
		||||
            this.obsDefaultTimeChange = CoreEvents.on(AddonCalendarProvider.DEFAULT_NOTIFICATION_TIME_CHANGED, () => {
 | 
			
		||||
                this.manager?.getSource().getItems()?.forEach((month) => {
 | 
			
		||||
                    if (!month.loaded) {
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    month.weeks?.forEach((week) => {
 | 
			
		||||
                        week.days.forEach((day) => {
 | 
			
		||||
                            AddonCalendar.scheduleEventsNotifications(day.eventsFormated || []);
 | 
			
		||||
                        });
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
            }, this.currentSiteId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Listen for events "undeleted" (offline).
 | 
			
		||||
        this.undeleteEventObserver = CoreEvents.on(
 | 
			
		||||
            AddonCalendarProvider.UNDELETED_EVENT_EVENT,
 | 
			
		||||
@ -329,7 +310,6 @@ export class AddonCalendarCalendarComponent implements OnInit, DoCheck, OnDestro
 | 
			
		||||
     */
 | 
			
		||||
    ngOnDestroy(): void {
 | 
			
		||||
        this.undeleteEventObserver?.off();
 | 
			
		||||
        this.obsDefaultTimeChange?.off();
 | 
			
		||||
        this.managerUnsubscribe && this.managerUnsubscribe();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -577,30 +557,22 @@ class AddonCalendarMonthSlidesItemsManagerSource extends CoreSwipeSlidesDynamicI
 | 
			
		||||
 | 
			
		||||
        weeks.forEach((week) => {
 | 
			
		||||
            week.days.forEach((day) => {
 | 
			
		||||
                if (this.deletedEvents.length) {
 | 
			
		||||
                    // Mark as deleted the events that were deleted in offline.
 | 
			
		||||
                    day.eventsFormated?.forEach((event) => {
 | 
			
		||||
                        event.deleted = this.deletedEvents.indexOf(event.id) != -1;
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Schedule notifications for the events retrieved (only future events will be scheduled).
 | 
			
		||||
                AddonCalendar.scheduleEventsNotifications(day.eventsFormated || []);
 | 
			
		||||
                if (this.offlineEditedEventsIds.length) {
 | 
			
		||||
                    // Remove the online events that were modified in offline.
 | 
			
		||||
                    day.events = day.events.filter((event) => this.offlineEditedEventsIds.indexOf(event.id) == -1);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (monthOfflineEvents || this.deletedEvents.length) {
 | 
			
		||||
                    // There is offline data, merge it.
 | 
			
		||||
 | 
			
		||||
                    if (this.deletedEvents.length) {
 | 
			
		||||
                        // Mark as deleted the events that were deleted in offline.
 | 
			
		||||
                        day.eventsFormated?.forEach((event) => {
 | 
			
		||||
                            event.deleted = this.deletedEvents.indexOf(event.id) != -1;
 | 
			
		||||
                        });
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (this.offlineEditedEventsIds.length) {
 | 
			
		||||
                        // Remove the online events that were modified in offline.
 | 
			
		||||
                        day.events = day.events.filter((event) => this.offlineEditedEventsIds.indexOf(event.id) == -1);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (monthOfflineEvents && monthOfflineEvents[day.mday] && day.eventsFormated) {
 | 
			
		||||
                        // Add the offline events (either new or edited).
 | 
			
		||||
                        day.eventsFormated =
 | 
			
		||||
                            AddonCalendarHelper.sortEvents(day.eventsFormated.concat(monthOfflineEvents[day.mday]));
 | 
			
		||||
                    }
 | 
			
		||||
                if (monthOfflineEvents && monthOfflineEvents[day.mday] && day.eventsFormated) {
 | 
			
		||||
                    // Add the offline events (either new or edited).
 | 
			
		||||
                    day.eventsFormated =
 | 
			
		||||
                        AddonCalendarHelper.sortEvents(day.eventsFormated.concat(monthOfflineEvents[day.mday]));
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,6 @@ import { AddonCalendarHelper, AddonCalendarFilter } from '../../services/calenda
 | 
			
		||||
import { AddonCalendarOffline } from '../../services/calendar-offline';
 | 
			
		||||
import { CoreCategoryData, CoreCourses } from '@features/courses/services/courses';
 | 
			
		||||
import { CoreConstants } from '@/core/constants';
 | 
			
		||||
import { CoreLocalNotifications } from '@services/local-notifications';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Component that displays upcoming events.
 | 
			
		||||
@ -58,19 +57,12 @@ export class AddonCalendarUpcomingEventsComponent implements OnInit, DoCheck, On
 | 
			
		||||
 | 
			
		||||
    // Observers.
 | 
			
		||||
    protected undeleteEventObserver: CoreEventObserver;
 | 
			
		||||
    protected obsDefaultTimeChange?: CoreEventObserver;
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        differs: KeyValueDiffers,
 | 
			
		||||
    ) {
 | 
			
		||||
        this.currentSiteId = CoreSites.getCurrentSiteId();
 | 
			
		||||
 | 
			
		||||
        if (CoreLocalNotifications.isAvailable()) {            // Re-schedule events if default time changes.
 | 
			
		||||
            this.obsDefaultTimeChange = CoreEvents.on(AddonCalendarProvider.DEFAULT_NOTIFICATION_TIME_CHANGED, () => {
 | 
			
		||||
                AddonCalendar.scheduleEventsNotifications(this.onlineEvents);
 | 
			
		||||
            }, this.currentSiteId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Listen for events "undeleted" (offline).
 | 
			
		||||
        this.undeleteEventObserver = CoreEvents.on(
 | 
			
		||||
            AddonCalendarProvider.UNDELETED_EVENT_EVENT,
 | 
			
		||||
@ -174,8 +166,6 @@ export class AddonCalendarUpcomingEventsComponent implements OnInit, DoCheck, On
 | 
			
		||||
        // Don't pass courseId and categoryId, we'll filter them locally.
 | 
			
		||||
        const result = await AddonCalendar.getUpcomingEvents();
 | 
			
		||||
        this.onlineEvents = await Promise.all(result.events.map((event) => AddonCalendarHelper.formatEventData(event)));
 | 
			
		||||
        // Schedule notifications for the events retrieved.
 | 
			
		||||
        AddonCalendar.scheduleEventsNotifications(this.onlineEvents);
 | 
			
		||||
        // Merge the online events with offline data.
 | 
			
		||||
        this.events = this.mergeEvents();
 | 
			
		||||
        // Filter events by course.
 | 
			
		||||
@ -313,7 +303,6 @@ export class AddonCalendarUpcomingEventsComponent implements OnInit, DoCheck, On
 | 
			
		||||
     */
 | 
			
		||||
    ngOnDestroy(): void {
 | 
			
		||||
        this.undeleteEventObserver?.off();
 | 
			
		||||
        this.obsDefaultTimeChange?.off();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -16,7 +16,6 @@ import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
 | 
			
		||||
import { IonRefresher } from '@ionic/angular';
 | 
			
		||||
import { CoreApp } from '@services/app';
 | 
			
		||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
 | 
			
		||||
import { CoreLocalNotifications } from '@services/local-notifications';
 | 
			
		||||
import { CoreSites } from '@services/sites';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
import { CoreTimeUtils } from '@services/utils/time';
 | 
			
		||||
@ -70,7 +69,6 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
 | 
			
		||||
    protected syncObserver: CoreEventObserver;
 | 
			
		||||
    protected manualSyncObserver: CoreEventObserver;
 | 
			
		||||
    protected onlineObserver: Subscription;
 | 
			
		||||
    protected obsDefaultTimeChange?: CoreEventObserver;
 | 
			
		||||
    protected filterChangedObserver: CoreEventObserver;
 | 
			
		||||
    protected managerUnsubscribe?: () => void;
 | 
			
		||||
 | 
			
		||||
@ -93,15 +91,6 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.currentSiteId = CoreSites.getCurrentSiteId();
 | 
			
		||||
 | 
			
		||||
        if (CoreLocalNotifications.isAvailable()) {
 | 
			
		||||
            // Re-schedule events if default time changes.
 | 
			
		||||
            this.obsDefaultTimeChange = CoreEvents.on(AddonCalendarProvider.DEFAULT_NOTIFICATION_TIME_CHANGED, () => {
 | 
			
		||||
                this.manager?.getSource().getItems()?.forEach(day => {
 | 
			
		||||
                    AddonCalendar.scheduleEventsNotifications(day.onlineEvents || []);
 | 
			
		||||
                });
 | 
			
		||||
            }, this.currentSiteId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Listen for events added. When an event is added, reload the data.
 | 
			
		||||
        this.newEventObserver = CoreEvents.on(
 | 
			
		||||
            AddonCalendarProvider.NEW_EVENT_EVENT,
 | 
			
		||||
@ -464,7 +453,6 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
 | 
			
		||||
        this.manualSyncObserver?.off();
 | 
			
		||||
        this.onlineObserver?.unsubscribe();
 | 
			
		||||
        this.filterChangedObserver?.off();
 | 
			
		||||
        this.obsDefaultTimeChange?.off();
 | 
			
		||||
        this.managerUnsubscribe && this.managerUnsubscribe();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -684,9 +672,6 @@ class AddonCalendarDaySlidesItemsManagerSource extends CoreSwipeSlidesDynamicIte
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Schedule notifications for the events retrieved (only future events will be scheduled).
 | 
			
		||||
        AddonCalendar.scheduleEventsNotifications(preloadedDay.onlineEvents || []);
 | 
			
		||||
 | 
			
		||||
        // Merge the online events with offline data.
 | 
			
		||||
        preloadedDay.events = this.mergeEvents(preloadedDay);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -129,10 +129,6 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy {
 | 
			
		||||
        // Reload reminders if default notification time changes.
 | 
			
		||||
        this.defaultTimeChangedObserver = CoreEvents.on(AddonCalendarProvider.DEFAULT_NOTIFICATION_TIME_CHANGED, () => {
 | 
			
		||||
            this.loadReminders();
 | 
			
		||||
 | 
			
		||||
            if (this.event) {
 | 
			
		||||
                AddonCalendar.scheduleEventsNotifications([this.event]);
 | 
			
		||||
            }
 | 
			
		||||
        }, this.currentSiteId);
 | 
			
		||||
 | 
			
		||||
        // Set and update current time. Use a 5 seconds error margin.
 | 
			
		||||
@ -225,9 +221,8 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy {
 | 
			
		||||
                return; // At this point we should always have the event, adding this check to avoid TS errors.
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Load reminders, and re-schedule them if needed (maybe the event time has changed).
 | 
			
		||||
            // Load reminders.
 | 
			
		||||
            this.loadReminders();
 | 
			
		||||
            AddonCalendar.scheduleEventsNotifications([this.event]);
 | 
			
		||||
 | 
			
		||||
            // Reset some of the calculated data.
 | 
			
		||||
            this.categoryPath = '';
 | 
			
		||||
 | 
			
		||||
@ -39,6 +39,7 @@ import { SafeUrl } from '@angular/platform-browser';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { AddonCalendarFilter } from './calendar-helper';
 | 
			
		||||
import { AddonCalendarSyncEvents, AddonCalendarSyncProvider } from './calendar-sync';
 | 
			
		||||
import { CoreEvents } from '@singletons/events';
 | 
			
		||||
 | 
			
		||||
const ROOT_CACHE_KEY = 'mmaCalendar:';
 | 
			
		||||
 | 
			
		||||
@ -351,6 +352,28 @@ export class AddonCalendarProvider {
 | 
			
		||||
            },
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if (CoreLocalNotifications.isAvailable()) {
 | 
			
		||||
            CoreEvents.on(AddonCalendarProvider.DEFAULT_NOTIFICATION_TIME_CHANGED, async (data) => {
 | 
			
		||||
                const site = await CoreSites.getSite(data.siteId);
 | 
			
		||||
 | 
			
		||||
                // Get all the events that have a default reminder.
 | 
			
		||||
                const query = 'SELECT events.*, reminders.id AS reminderid ' +
 | 
			
		||||
                    'FROM ' + EVENTS_TABLE + ' events ' +
 | 
			
		||||
                    'INNER JOIN ' + REMINDERS_TABLE + ' reminders ON events.id = reminders.eventid ' +
 | 
			
		||||
                    'WHERE reminders.time IS NULL';
 | 
			
		||||
 | 
			
		||||
                const result = await site.getDb().execute(query);
 | 
			
		||||
 | 
			
		||||
                // Reschedule all the default reminders.
 | 
			
		||||
                for (let i = 0; i < result.rows.length; i++) {
 | 
			
		||||
                    const event = result.rows.item(i) as AddonCalendarEventDBRecord & {
 | 
			
		||||
                        reminderid: number;
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                    this.scheduleEventNotification(event, event.reminderid, null, site.getId());
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -674,6 +697,9 @@ export class AddonCalendarProvider {
 | 
			
		||||
            const response: AddonCalendarGetCalendarEventByIdWSResponse =
 | 
			
		||||
                await site.read('core_calendar_get_calendar_event_by_id', params, preSets);
 | 
			
		||||
 | 
			
		||||
            this.storeEventInLocalDb(response.event, { siteId });
 | 
			
		||||
            this.scheduleEventsNotifications([response.event], siteId);
 | 
			
		||||
 | 
			
		||||
            return response.event;
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            try {
 | 
			
		||||
@ -837,6 +863,7 @@ export class AddonCalendarProvider {
 | 
			
		||||
        }
 | 
			
		||||
        const response: AddonCalendarCalendarDay = await site.read('core_calendar_get_calendar_day_view', params, preSets);
 | 
			
		||||
        this.storeEventsInLocalDB(response.events, { siteId });
 | 
			
		||||
        this.scheduleEventsNotifications(response.events, siteId);
 | 
			
		||||
 | 
			
		||||
        return response;
 | 
			
		||||
    }
 | 
			
		||||
@ -1040,7 +1067,8 @@ export class AddonCalendarProvider {
 | 
			
		||||
        const response = await site.read<AddonCalendarMonth>('core_calendar_get_calendar_monthly_view', params, preSets);
 | 
			
		||||
        response.weeks.forEach((week) => {
 | 
			
		||||
            week.days.forEach((day) => {
 | 
			
		||||
                this.storeEventsInLocalDB(day.events as AddonCalendarCalendarEvent[], { siteId });
 | 
			
		||||
                this.storeEventsInLocalDB(day.events, { siteId });
 | 
			
		||||
                this.scheduleEventsNotifications(day.events, siteId);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@ -1154,6 +1182,7 @@ export class AddonCalendarProvider {
 | 
			
		||||
 | 
			
		||||
        const response = await site.read<AddonCalendarUpcoming>('core_calendar_get_calendar_upcoming_view', params, preSets);
 | 
			
		||||
        this.storeEventsInLocalDB(response.events, { siteId });
 | 
			
		||||
        this.scheduleEventsNotifications(response.events, siteId);
 | 
			
		||||
 | 
			
		||||
        return response;
 | 
			
		||||
    }
 | 
			
		||||
@ -1512,7 +1541,7 @@ export class AddonCalendarProvider {
 | 
			
		||||
        const promises = events.map(async (event) => {
 | 
			
		||||
            if (event.timestart * 1000 <= Date.now()) {
 | 
			
		||||
                // The event has already started, don't schedule it.
 | 
			
		||||
                return this.deleteLocalEvent(event.id, siteId);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const reminders = await this.getEventReminders(event.id, siteId);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user