MOBILE-3636 sync: Small improvements on previous sync services

main
Pau Ferrer Ocaña 2021-02-10 11:36:54 +01:00
parent 6d6cb0e36f
commit a4225b8c02
12 changed files with 44 additions and 40 deletions

View File

@ -19,11 +19,13 @@ import { CoreSharedModule } from '@/core/shared.module';
import { CoreEditorComponentsModule } from '@features/editor/components/components.module'; import { CoreEditorComponentsModule } from '@features/editor/components/components.module';
import { AddonCalendarEditEventPage } from './edit-event.page'; import { AddonCalendarEditEventPage } from './edit-event.page';
import { CanLeaveGuard } from '@guards/can-leave';
const routes: Routes = [ const routes: Routes = [
{ {
path: '', path: '',
component: AddonCalendarEditEventPage, component: AddonCalendarEditEventPage,
canDeactivate: [CanLeaveGuard],
}, },
]; ];

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CoreSyncBaseProvider } from '@classes/base-sync'; import { CoreSyncBaseProvider, CoreSyncBlockedError } from '@classes/base-sync';
import { CoreApp } from '@services/app'; import { CoreApp } from '@services/app';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
@ -27,9 +27,9 @@ import {
import { AddonCalendarOffline } from './calendar-offline'; import { AddonCalendarOffline } from './calendar-offline';
import { AddonCalendarHelper } from './calendar-helper'; import { AddonCalendarHelper } from './calendar-helper';
import { makeSingleton, Translate } from '@singletons'; import { makeSingleton, Translate } from '@singletons';
import { CoreError } from '@classes/errors/error';
import { CoreSync } from '@services/sync'; import { CoreSync } from '@services/sync';
import { CoreTextUtils } from '@services/utils/text'; import { CoreTextUtils } from '@services/utils/text';
import { CoreNetworkError } from '@classes/errors/network-error';
/** /**
* Service to sync calendar. * Service to sync calendar.
@ -52,21 +52,23 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider<AddonCalenda
* @param force Wether to force sync not depending on last execution. * @param force Wether to force sync not depending on last execution.
* @return Promise resolved if sync is successful, rejected if sync fails. * @return Promise resolved if sync is successful, rejected if sync fails.
*/ */
async syncAllEvents(siteId?: string, force?: boolean): Promise<void> { async syncAllEvents(siteId?: string, force = false): Promise<void> {
await this.syncOnSites('all calendar events', this.syncAllEventsFunc.bind(this, [force]), siteId); await this.syncOnSites('all calendar events', this.syncAllEventsFunc.bind(this, [force]), siteId);
} }
/** /**
* Sync all events on a site. * Sync all events on a site.
* *
* @param siteId Site ID to sync.
* @param force Wether to force sync not depending on last execution. * @param force Wether to force sync not depending on last execution.
* @param siteId Site ID to sync.
* @return Promise resolved if sync is successful, rejected if sync fails. * @return Promise resolved if sync is successful, rejected if sync fails.
*/ */
protected async syncAllEventsFunc(siteId: string, force?: boolean): Promise<void> { protected async syncAllEventsFunc(force = false, siteId?: string): Promise<void> {
const result = await (force ? this.syncEvents(siteId) : this.syncEventsIfNeeded(siteId)); const result = force
? await this.syncEvents(siteId)
: await this.syncEventsIfNeeded(siteId);
if (result && result.updated) { if (result?.updated) {
// Sync successful, send event. // Sync successful, send event.
CoreEvents.trigger<AddonCalendarSyncEvents>(AddonCalendarSyncProvider.AUTO_SYNCED, result, siteId); CoreEvents.trigger<AddonCalendarSyncEvents>(AddonCalendarSyncProvider.AUTO_SYNCED, result, siteId);
} }
@ -78,13 +80,13 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider<AddonCalenda
* @param siteId Site ID. If not defined, current site. * @param siteId Site ID. If not defined, current site.
* @return Promise resolved when the events are synced or if it doesn't need to be synced. * @return Promise resolved when the events are synced or if it doesn't need to be synced.
*/ */
async syncEventsIfNeeded(siteId?: string): Promise<void> { async syncEventsIfNeeded(siteId?: string): Promise<AddonCalendarSyncEvents | undefined> {
siteId = siteId || CoreSites.instance.getCurrentSiteId(); siteId = siteId || CoreSites.instance.getCurrentSiteId();
const needed = await this.isSyncNeeded(AddonCalendarSyncProvider.SYNC_ID, siteId); const needed = await this.isSyncNeeded(AddonCalendarSyncProvider.SYNC_ID, siteId);
if (needed) { if (needed) {
await this.syncEvents(siteId); return this.syncEvents(siteId);
} }
} }
@ -125,17 +127,12 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider<AddonCalenda
updated: false, updated: false,
}; };
let eventIds: number[] = []; const eventIds: number[] = await CoreUtils.instance.ignoreErrors(AddonCalendarOffline.instance.getAllEventsIds(siteId), []);
try {
eventIds = await AddonCalendarOffline.instance.getAllEventsIds(siteId);
} catch {
// No offline data found.
}
if (eventIds.length > 0) { if (eventIds.length > 0) {
if (!CoreApp.instance.isOnline()) { if (!CoreApp.instance.isOnline()) {
// Cannot sync in offline. // Cannot sync in offline.
throw new CoreError('Cannot sync while offline'); throw new CoreNetworkError();
} }
const promises = eventIds.map((eventId) => this.syncOfflineEvent(eventId, result, siteId)); const promises = eventIds.map((eventId) => this.syncOfflineEvent(eventId, result, siteId));
@ -175,10 +172,10 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider<AddonCalenda
if (CoreSync.instance.isBlocked(AddonCalendarProvider.COMPONENT, eventId, siteId)) { if (CoreSync.instance.isBlocked(AddonCalendarProvider.COMPONENT, eventId, siteId)) {
this.logger.debug('Cannot sync event ' + eventId + ' because it is blocked.'); this.logger.debug('Cannot sync event ' + eventId + ' because it is blocked.');
throw Translate.instance.instant( throw new CoreSyncBlockedError(Translate.instance.instant(
'core.errorsyncblocked', 'core.errorsyncblocked',
{ $a: Translate.instance.instant('addon.calendar.calendarevent') }, { $a: Translate.instance.instant('addon.calendar.calendarevent') },
); ));
} }
// First of all, check if the event has been deleted. // First of all, check if the event has been deleted.

View File

@ -17,7 +17,7 @@ import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [ const routes: Routes = [
{ {
path: ':courseId/:cmdId', path: ':courseId/:cmId',
loadChildren: () => import('./pages/index/index.module').then( m => m.AddonModBookIndexPageModule), loadChildren: () => import('./pages/index/index.module').then( m => m.AddonModBookIndexPageModule),
}, },
]; ];

View File

@ -8,7 +8,7 @@
(action)="expandDescription()" iconAction="fas-arrow-right"> (action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item> </core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" <core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}"
[iconAction]="'far-newspaper'" (action)="gotoBlog()"> iconAction="far-newspaper" (action)="gotoBlog()">
</core-context-menu-item> </core-context-menu-item>
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"> (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">

View File

@ -17,7 +17,7 @@ import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [ const routes: Routes = [
{ {
path: ':courseId/:cmdId', path: ':courseId/:cmId',
loadChildren: () => import('./pages/index/index.module').then( m => m.AddonModLessonIndexPageModule), loadChildren: () => import('./pages/index/index.module').then( m => m.AddonModLessonIndexPageModule),
}, },
{ {

View File

@ -257,7 +257,7 @@ export class AddonModLessonPrefetchHandlerService extends CoreCourseActivityPref
*/ */
protected async prefetchLesson(module: CoreCourseAnyModuleData, courseId?: number, single?: boolean): Promise<void> { protected async prefetchLesson(module: CoreCourseAnyModuleData, courseId?: number, single?: boolean): Promise<void> {
const siteId = CoreSites.instance.getCurrentSiteId(); const siteId = CoreSites.instance.getCurrentSiteId();
courseId = courseId || module.course || 1; courseId = courseId || module.course || CoreSites.instance.getCurrentSiteHomeId();
const commonOptions = { const commonOptions = {
readingStrategy: CoreSitesReadingStrategy.OnlyNetwork, readingStrategy: CoreSitesReadingStrategy.OnlyNetwork,

View File

@ -14,7 +14,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CoreError } from '@classes/errors/error'; import { CoreSyncBlockedError } from '@classes/base-sync';
import { CoreNetworkError } from '@classes/errors/network-error'; import { CoreNetworkError } from '@classes/errors/network-error';
import { CoreCourseActivitySyncBaseProvider } from '@features/course/classes/activity-sync'; import { CoreCourseActivitySyncBaseProvider } from '@features/course/classes/activity-sync';
import { CoreCourse } from '@features/course/services/course'; import { CoreCourse } from '@features/course/services/course';
@ -122,7 +122,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid
* @param force Wether to force sync not depending on last execution. * @param force Wether to force sync not depending on last execution.
* @return Promise resolved if sync is successful, rejected if sync fails. * @return Promise resolved if sync is successful, rejected if sync fails.
*/ */
syncAllLessons(siteId?: string, force?: boolean): Promise<void> { syncAllLessons(siteId?: string, force = false): Promise<void> {
return this.syncOnSites('all lessons', this.syncAllLessonsFunc.bind(this, !!force), siteId); return this.syncOnSites('all lessons', this.syncAllLessonsFunc.bind(this, !!force), siteId);
} }
@ -163,7 +163,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid
*/ */
async syncLessonIfNeeded( async syncLessonIfNeeded(
lessonId: number, lessonId: number,
askPassword?: boolean, askPassword = false,
siteId?: string, siteId?: string,
): Promise<AddonModLessonSyncResult | undefined> { ): Promise<AddonModLessonSyncResult | undefined> {
const needed = await this.isSyncNeeded(lessonId, siteId); const needed = await this.isSyncNeeded(lessonId, siteId);
@ -184,8 +184,8 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid
*/ */
async syncLesson( async syncLesson(
lessonId: number, lessonId: number,
askPassword?: boolean, askPassword = false,
ignoreBlock?: boolean, ignoreBlock = false,
siteId?: string, siteId?: string,
): Promise<AddonModLessonSyncResult> { ): Promise<AddonModLessonSyncResult> {
siteId = siteId || CoreSites.instance.getCurrentSiteId(); siteId = siteId || CoreSites.instance.getCurrentSiteId();
@ -201,7 +201,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid
if (!ignoreBlock && CoreSync.instance.isBlocked(AddonModLessonProvider.COMPONENT, lessonId, siteId)) { if (!ignoreBlock && CoreSync.instance.isBlocked(AddonModLessonProvider.COMPONENT, lessonId, siteId)) {
this.logger.debug('Cannot sync lesson ' + lessonId + ' because it is blocked.'); this.logger.debug('Cannot sync lesson ' + lessonId + ' because it is blocked.');
throw new CoreError(Translate.instance.instant('core.errorsyncblocked', { $a: this.componentTranslate })); throw new CoreSyncBlockedError(Translate.instance.instant('core.errorsyncblocked', { $a: this.componentTranslate }));
} }
this.logger.debug('Try to sync lesson ' + lessonId + ' in site ' + siteId); this.logger.debug('Try to sync lesson ' + lessonId + ' in site ' + siteId);
@ -222,8 +222,8 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid
*/ */
protected async performSyncLesson( protected async performSyncLesson(
lessonId: number, lessonId: number,
askPassword?: boolean, askPassword = false,
ignoreBlock?: boolean, ignoreBlock = false,
siteId?: string, siteId?: string,
): Promise<AddonModLessonSyncResult> { ): Promise<AddonModLessonSyncResult> {
// Sync offline logs. // Sync offline logs.
@ -270,7 +270,7 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid
protected async syncAttempts( protected async syncAttempts(
lessonId: number, lessonId: number,
result: AddonModLessonSyncResult, result: AddonModLessonSyncResult,
askPassword?: boolean, askPassword = false,
siteId?: string, siteId?: string,
): Promise<AddonModLessonGetPasswordResult | undefined> { ): Promise<AddonModLessonGetPasswordResult | undefined> {
let attempts = await AddonModLessonOffline.instance.getLessonAttempts(lessonId, siteId); let attempts = await AddonModLessonOffline.instance.getLessonAttempts(lessonId, siteId);
@ -408,8 +408,8 @@ export class AddonModLessonSyncProvider extends CoreCourseActivitySyncBaseProvid
lessonId: number, lessonId: number,
result: AddonModLessonSyncResult, result: AddonModLessonSyncResult,
passwordData?: AddonModLessonGetPasswordResult, passwordData?: AddonModLessonGetPasswordResult,
askPassword?: boolean, askPassword = false,
ignoreBlock?: boolean, ignoreBlock = false,
siteId?: string, siteId?: string,
): Promise<void> { ): Promise<void> {
// Attempts sent or there was none. If there is a finished retake, send it. // Attempts sent or there was none. If there is a finished retake, send it.

View File

@ -17,7 +17,7 @@ import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [ const routes: Routes = [
{ {
path: ':courseId/:cmdId', path: ':courseId/:cmId',
loadChildren: () => import('./pages/index/index.module').then( m => m.AddonModPageIndexPageModule), loadChildren: () => import('./pages/index/index.module').then( m => m.AddonModPageIndexPageModule),
}, },
]; ];

View File

@ -231,7 +231,7 @@ export class CoreSyncBaseProvider<T = void> {
* @param time Time to set. If not defined, current time. * @param time Time to set. If not defined, current time.
* @return Promise resolved when the time is set. * @return Promise resolved when the time is set.
*/ */
async setSyncTime(id: string, siteId?: string, time?: number): Promise<void> { async setSyncTime(id: string | number, siteId?: string, time?: number): Promise<void> {
time = typeof time != 'undefined' ? time : Date.now(); time = typeof time != 'undefined' ? time : Date.now();
await CoreSync.instance.insertOrUpdateSyncRecord(this.component, id, { time: time }, siteId); await CoreSync.instance.insertOrUpdateSyncRecord(this.component, id, { time: time }, siteId);
@ -245,7 +245,7 @@ export class CoreSyncBaseProvider<T = void> {
* @param siteId Site ID. If not defined, current site. * @param siteId Site ID. If not defined, current site.
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
async setSyncWarnings(id: string, warnings: string[], siteId?: string): Promise<void> { async setSyncWarnings(id: string | number, warnings: string[], siteId?: string): Promise<void> {
const warningsText = JSON.stringify(warnings || []); const warningsText = JSON.stringify(warnings || []);
await CoreSync.instance.insertOrUpdateSyncRecord(this.component, id, { warnings: warningsText }, siteId); await CoreSync.instance.insertOrUpdateSyncRecord(this.component, id, { warnings: warningsText }, siteId);

View File

@ -20,7 +20,7 @@ import { CoreCourseModulePrefetchHandlerBase } from './module-prefetch-handler';
/** /**
* Base class to create activity sync providers. It provides some common functions. * Base class to create activity sync providers. It provides some common functions.
*/ */
export class CoreCourseActivitySyncBaseProvider<T> extends CoreSyncBaseProvider<T> { export class CoreCourseActivitySyncBaseProvider<T = void> extends CoreSyncBaseProvider<T> {
/** /**
* Conveniece function to prefetch data after an update. * Conveniece function to prefetch data after an update.

View File

@ -112,11 +112,16 @@ export class CoreSyncProvider {
* @param siteId Site ID. If not defined, current site. * @param siteId Site ID. If not defined, current site.
* @return Promise resolved with done. * @return Promise resolved with done.
*/ */
async insertOrUpdateSyncRecord(component: string, id: string, data: Partial<CoreSyncRecord>, siteId?: string): Promise<void> { async insertOrUpdateSyncRecord(
component: string,
id: string | number,
data: Partial<CoreSyncRecord>,
siteId?: string,
): Promise<void> {
const db = await CoreSites.instance.getSiteDb(siteId); const db = await CoreSites.instance.getSiteDb(siteId);
data.component = component; data.component = component;
data.id = id; data.id = id + '';
await db.insertRecord(SYNC_TABLE_NAME, data); await db.insertRecord(SYNC_TABLE_NAME, data);
} }

View File

@ -1607,7 +1607,7 @@ export class CoreUtilsProvider {
const result = await promise; const result = await promise;
return result; return result;
} catch (error) { } catch {
// Ignore errors. // Ignore errors.
return fallback; return fallback;
} }