Merge pull request #3043 from dpalou/MOBILE-3951

MOBILE-3951 calendar: Schedule notifications from service
main
Pau Ferrer Ocaña 2022-01-11 12:42:51 +01:00 committed by GitHub
commit af9e1ce486
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 49 additions and 79 deletions

View File

@ -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

View File

@ -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,13 +557,6 @@ class AddonCalendarMonthSlidesItemsManagerSource extends CoreSwipeSlidesDynamicI
weeks.forEach((week) => {
week.days.forEach((day) => {
// Schedule notifications for the events retrieved (only future events will be scheduled).
AddonCalendar.scheduleEventsNotifications(day.eventsFormated || []);
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) => {
@ -601,7 +574,6 @@ class AddonCalendarMonthSlidesItemsManagerSource extends CoreSwipeSlidesDynamicI
day.eventsFormated =
AddonCalendarHelper.sortEvents(day.eventsFormated.concat(monthOfflineEvents[day.mday]));
}
}
});
});
}

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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 = '';

View File

@ -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);