MOBILE-2850 choice: Prefetch data after sync choice

main
Dani Palou 2019-02-25 11:10:01 +01:00
parent 63d84eec23
commit ceca8cb5c6
9 changed files with 167 additions and 77 deletions

View File

@ -352,14 +352,13 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
} }
const modal = this.domUtils.showModalLoading('core.sending', true); const modal = this.domUtils.showModalLoading('core.sending', true);
this.choiceProvider.submitResponse(this.choice.id, this.choice.name, this.courseId, responses).then(() => { this.choiceProvider.submitResponse(this.choice.id, this.choice.name, this.courseId, responses).then((online) => {
// Success! // Success!
// Check completion since it could be configured to complete once the user answers the choice. // Check completion since it could be configured to complete once the user answers the choice.
this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata);
this.domUtils.scrollToTop(this.content); this.domUtils.scrollToTop(this.content);
// Let's refresh the data. return this.dataUpdated(online);
return this.refreshContent(false);
}).catch((message) => { }).catch((message) => {
this.domUtils.showErrorModalDefault(message, 'addon.mod_choice.cannotsubmit', true); this.domUtils.showErrorModalDefault(message, 'addon.mod_choice.cannotsubmit', true);
}).finally(() => { }).finally(() => {
@ -377,7 +376,7 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
this.choiceProvider.deleteResponses(this.choice.id, this.choice.name, this.courseId).then(() => { this.choiceProvider.deleteResponses(this.choice.id, this.choice.name, this.courseId).then(() => {
this.domUtils.scrollToTop(this.content); this.domUtils.scrollToTop(this.content);
// Success! Let's refresh the data. // Refresh the data. Don't call dataUpdated because deleting an answer doesn't mark the choice as outdated.
return this.refreshContent(false); return this.refreshContent(false);
}).catch((message) => { }).catch((message) => {
this.domUtils.showErrorModalDefault(message, 'addon.mod_choice.cannotsubmit', true); this.domUtils.showErrorModalDefault(message, 'addon.mod_choice.cannotsubmit', true);
@ -389,6 +388,28 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
}); });
} }
/**
* Function to call when some data has changed. It will refresh/prefetch data.
*
* @param {boolean} online Whether the data was sent to server or stored in offline.
* @return {Promise<any>} Promise resolved when done.
*/
protected dataUpdated(online: boolean): Promise<any> {
if (online && this.isPrefetched()) {
// The choice is downloaded, update the data.
return this.choiceSync.prefetchAfterUpdate(this.module, this.courseId).then(() => {
// Update the view.
this.showLoadingAndFetch(false, false);
}).catch(() => {
// Prefetch failed, refresh the data.
return this.refreshContent(false);
});
} else {
// Not downloaded, refresh the data.
return this.refreshContent(false);
}
}
/** /**
* Performs the sync of the activity. * Performs the sync of the activity.
* *

View File

@ -19,6 +19,7 @@ import { CoreAppProvider } from '@providers/app';
import { CoreFilepoolProvider } from '@providers/filepool'; import { CoreFilepoolProvider } from '@providers/filepool';
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
import { AddonModChoiceOfflineProvider } from './offline'; import { AddonModChoiceOfflineProvider } from './offline';
import { CoreSiteWSPreSets } from '@classes/site';
/** /**
* Service that provides some features for choices. * Service that provides some features for choices.
@ -68,9 +69,9 @@ export class AddonModChoiceProvider {
* @param {number} courseId Course ID the choice belongs to. * @param {number} courseId Course ID the choice belongs to.
* @param {number[]} [responses] IDs of the answers. If not defined, delete all the answers of the current user. * @param {number[]} [responses] IDs of the answers. If not defined, delete all the answers of the current user.
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when the options are deleted. * @return {Promise<boolean>} Promise resolved with boolean: true if response was sent to server, false if stored in device.
*/ */
deleteResponses(choiceId: number, name: string, courseId: number, responses?: number[], siteId?: string): Promise<any> { deleteResponses(choiceId: number, name: string, courseId: number, responses?: number[], siteId?: string): Promise<boolean> {
siteId = siteId || this.sitesProvider.getCurrentSiteId(); siteId = siteId || this.sitesProvider.getCurrentSiteId();
responses = responses || []; responses = responses || [];
@ -173,20 +174,29 @@ export class AddonModChoiceProvider {
* @param {number} courseId Course ID. * @param {number} courseId Course ID.
* @param {string} key Name of the property to check. * @param {string} key Name of the property to check.
* @param {any} value Value to search. * @param {any} value Value to search.
* @param {boolean} [forceCache=false] True to always get the value from cache, false otherwise. Default false. * @param {boolean} [forceCache] True to always get the value from cache, false otherwise. Default false.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @return {Promise<any>} Promise resolved when the choice is retrieved. * @return {Promise<any>} Promise resolved when the choice is retrieved.
*/ */
protected getChoiceByDataKey(siteId: string, courseId: number, key: string, value: any, forceCache: boolean = false) protected getChoiceByDataKey(siteId: string, courseId: number, key: string, value: any, forceCache?: boolean,
: Promise<any> { ignoreCache?: boolean): Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
const params = { const params = {
courseids: [courseId] courseids: [courseId]
}; };
const preSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getChoiceDataCacheKey(courseId), cacheKey: this.getChoiceDataCacheKey(courseId),
omitExpires: forceCache omitExpires: forceCache
}; };
if (forceCache) {
preSets.omitExpires = true;
} else if (ignoreCache) {
preSets.getFromCache = false;
preSets.emergencyCache = false;
}
return site.read('mod_choice_get_choices_by_courses', params, preSets).then((response) => { return site.read('mod_choice_get_choices_by_courses', params, preSets).then((response) => {
if (response && response.choices) { if (response && response.choices) {
const currentChoice = response.choices.find((choice) => choice[key] == value); const currentChoice = response.choices.find((choice) => choice[key] == value);
@ -206,11 +216,12 @@ export class AddonModChoiceProvider {
* @param {number} courseId Course ID. * @param {number} courseId Course ID.
* @param {number} cmId Course module ID. * @param {number} cmId Course module ID.
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @param {boolean} [forceCache=false] True to always get the value from cache, false otherwise. Default false. * @param {boolean} [forceCache] True to always get the value from cache, false otherwise. Default false.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @return {Promise<any>} Promise resolved when the choice is retrieved. * @return {Promise<any>} Promise resolved when the choice is retrieved.
*/ */
getChoice(courseId: number, cmId: number, siteId?: string, forceCache: boolean = false): Promise<any> { getChoice(courseId: number, cmId: number, siteId?: string, forceCache?: boolean, ignoreCache?: boolean): Promise<any> {
return this.getChoiceByDataKey(siteId, courseId, 'coursemodule', cmId, forceCache); return this.getChoiceByDataKey(siteId, courseId, 'coursemodule', cmId, forceCache, ignoreCache);
} }
/** /**
@ -219,29 +230,36 @@ export class AddonModChoiceProvider {
* @param {number} courseId Course ID. * @param {number} courseId Course ID.
* @param {number} choiceId Choice ID. * @param {number} choiceId Choice ID.
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @param {boolean} [forceCache=false] True to always get the value from cache, false otherwise. Default false. * @param {boolean} [forceCache] True to always get the value from cache, false otherwise. Default false.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @return {Promise<any>} Promise resolved when the choice is retrieved. * @return {Promise<any>} Promise resolved when the choice is retrieved.
*/ */
getChoiceById(courseId: number, choiceId: number, siteId?: string, forceCache: boolean = false): Promise<any> { getChoiceById(courseId: number, choiceId: number, siteId?: string, forceCache?: boolean, ignoreCache?: boolean): Promise<any> {
return this.getChoiceByDataKey(siteId, courseId, 'id', choiceId, forceCache); return this.getChoiceByDataKey(siteId, courseId, 'id', choiceId, forceCache, ignoreCache);
} }
/** /**
* Get choice options. * Get choice options.
* *
* @param {number} choiceId Choice ID. * @param {number} choiceId Choice ID.
* @param {string} [siteId] Site ID. If not defined, current site. * @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, current site.
* @return {Promise<any>} Promise resolved with choice options. * @return {Promise<any>} Promise resolved with choice options.
*/ */
getOptions(choiceId: number, siteId?: string): Promise<any> { getOptions(choiceId: number, ignoreCache?: boolean, siteId?: string): Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
const params = { const params = {
choiceid: choiceId choiceid: choiceId
}; };
const preSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getChoiceOptionsCacheKey(choiceId) cacheKey: this.getChoiceOptionsCacheKey(choiceId)
}; };
if (ignoreCache) {
preSets.getFromCache = false;
preSets.emergencyCache = false;
}
return site.read('mod_choice_get_choice_options', params, preSets).then((response) => { return site.read('mod_choice_get_choice_options', params, preSets).then((response) => {
if (response.options) { if (response.options) {
return response.options; return response.options;
@ -255,19 +273,25 @@ export class AddonModChoiceProvider {
/** /**
* Get choice results. * Get choice results.
* *
* @param {number} choiceId Choice ID. * @param {number} choiceId Choice ID.
* @param {string} [siteId] Site ID. If not defined, current site. * @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, current site.
* @return {Promise<any>} Promise resolved with choice results. * @return {Promise<any>} Promise resolved with choice results.
*/ */
getResults(choiceId: number, siteId?: string): Promise<any> { getResults(choiceId: number, ignoreCache?: boolean, siteId?: string): Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
const params = { const params = {
choiceid: choiceId choiceid: choiceId
}; };
const preSets = { const preSets: CoreSiteWSPreSets = {
cacheKey: this.getChoiceResultsCacheKey(choiceId) cacheKey: this.getChoiceResultsCacheKey(choiceId)
}; };
if (ignoreCache) {
preSets.getFromCache = false;
preSets.emergencyCache = false;
}
return site.read('mod_choice_get_choice_results', params, preSets).then((response) => { return site.read('mod_choice_get_choice_results', params, preSets).then((response) => {
if (response.options) { if (response.options) {
return response.options; return response.options;

View File

@ -23,7 +23,6 @@ import { CoreCourseProvider } from '@core/course/providers/course';
import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/activity-prefetch-handler'; import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/activity-prefetch-handler';
import { CoreUserProvider } from '@core/user/providers/user'; import { CoreUserProvider } from '@core/user/providers/user';
import { AddonModChoiceProvider } from './choice'; import { AddonModChoiceProvider } from './choice';
import { AddonModChoiceSyncProvider } from './sync';
/** /**
* Handler to prefetch choices. * Handler to prefetch choices.
@ -38,7 +37,7 @@ export class AddonModChoicePrefetchHandler extends CoreCourseActivityPrefetchHan
constructor(translate: TranslateService, appProvider: CoreAppProvider, utils: CoreUtilsProvider, constructor(translate: TranslateService, appProvider: CoreAppProvider, utils: CoreUtilsProvider,
courseProvider: CoreCourseProvider, filepoolProvider: CoreFilepoolProvider, sitesProvider: CoreSitesProvider, courseProvider: CoreCourseProvider, filepoolProvider: CoreFilepoolProvider, sitesProvider: CoreSitesProvider,
domUtils: CoreDomUtilsProvider, protected choiceProvider: AddonModChoiceProvider, domUtils: CoreDomUtilsProvider, protected choiceProvider: AddonModChoiceProvider,
protected syncProvider: AddonModChoiceSyncProvider, protected userProvider: CoreUserProvider) { protected userProvider: CoreUserProvider) {
super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils); super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils);
} }
@ -66,12 +65,12 @@ export class AddonModChoicePrefetchHandler extends CoreCourseActivityPrefetchHan
* @return {Promise<any>} Promise resolved when done. * @return {Promise<any>} Promise resolved when done.
*/ */
protected prefetchChoice(module: any, courseId: number, single: boolean, siteId: string): Promise<any> { protected prefetchChoice(module: any, courseId: number, single: boolean, siteId: string): Promise<any> {
return this.choiceProvider.getChoice(courseId, module.id, siteId).then((choice) => { return this.choiceProvider.getChoice(courseId, module.id, siteId, false, true).then((choice) => {
const promises = []; const promises = [];
// Get the options and results. // Get the options and results.
promises.push(this.choiceProvider.getOptions(choice.id, siteId)); promises.push(this.choiceProvider.getOptions(choice.id, true, siteId));
promises.push(this.choiceProvider.getResults(choice.id, siteId).then((options) => { promises.push(this.choiceProvider.getResults(choice.id, true, siteId).then((options) => {
// If we can see the users that answered, prefetch their profile and avatar. // If we can see the users that answered, prefetch their profile and avatar.
const subPromises = []; const subPromises = [];
options.forEach((option) => { options.forEach((option) => {

View File

@ -14,7 +14,6 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CoreLoggerProvider } from '@providers/logger'; import { CoreLoggerProvider } from '@providers/logger';
import { CoreSyncBaseProvider } from '@classes/base-sync';
import { CoreSitesProvider } from '@providers/sites'; import { CoreSitesProvider } from '@providers/sites';
import { CoreAppProvider } from '@providers/app'; import { CoreAppProvider } from '@providers/app';
import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreUtilsProvider } from '@providers/utils/utils';
@ -26,13 +25,16 @@ import { CoreEventsProvider } from '@providers/events';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreCourseProvider } from '@core/course/providers/course';
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate';
import { CoreCourseActivitySyncBaseProvider } from '@core/course/classes/activity-sync';
import { CoreSyncProvider } from '@providers/sync'; import { CoreSyncProvider } from '@providers/sync';
import { AddonModChoicePrefetchHandler } from './prefetch-handler';
/** /**
* Service to sync choices. * Service to sync choices.
*/ */
@Injectable() @Injectable()
export class AddonModChoiceSyncProvider extends CoreSyncBaseProvider { export class AddonModChoiceSyncProvider extends CoreCourseActivitySyncBaseProvider {
static AUTO_SYNCED = 'addon_mod_choice_autom_synced'; static AUTO_SYNCED = 'addon_mod_choice_autom_synced';
protected componentTranslate: string; protected componentTranslate: string;
@ -42,9 +44,11 @@ export class AddonModChoiceSyncProvider extends CoreSyncBaseProvider {
private eventsProvider: CoreEventsProvider, private choiceProvider: AddonModChoiceProvider, private eventsProvider: CoreEventsProvider, private choiceProvider: AddonModChoiceProvider,
translate: TranslateService, private utils: CoreUtilsProvider, protected textUtils: CoreTextUtilsProvider, translate: TranslateService, private utils: CoreUtilsProvider, protected textUtils: CoreTextUtilsProvider,
courseProvider: CoreCourseProvider, syncProvider: CoreSyncProvider, timeUtils: CoreTimeUtilsProvider, courseProvider: CoreCourseProvider, syncProvider: CoreSyncProvider, timeUtils: CoreTimeUtilsProvider,
private logHelper: CoreCourseLogHelperProvider) { private logHelper: CoreCourseLogHelperProvider, prefetchHandler: AddonModChoicePrefetchHandler,
prefetchDelegate: CoreCourseModulePrefetchDelegate) {
super('AddonModChoiceSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, super('AddonModChoiceSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate,
timeUtils); timeUtils, prefetchDelegate, prefetchHandler);
this.componentTranslate = courseProvider.translateModuleName('choice'); this.componentTranslate = courseProvider.translateModuleName('choice');
} }
@ -195,16 +199,8 @@ export class AddonModChoiceSyncProvider extends CoreSyncBaseProvider {
}); });
}).then(() => { }).then(() => {
if (courseId) { if (courseId) {
const promises = [ // Data has been sent to server, prefetch choice if needed.
this.choiceProvider.invalidateChoiceData(courseId), return this.prefetchAfterUpdate(module, courseId, undefined, siteId).catch(() => {
choiceId ? this.choiceProvider.invalidateOptions(choiceId) : Promise.resolve(),
choiceId ? this.choiceProvider.invalidateResults(choiceId) : Promise.resolve(),
];
// Data has been sent to server, update choice data.
return Promise.all(promises).then(() => {
return this.choiceProvider.getChoiceById(courseId, choiceId, siteId);
}).catch(() => {
// Ignore errors. // Ignore errors.
}); });
} }

View File

@ -25,7 +25,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils';
import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreCourseProvider } from '@core/course/providers/course';
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate'; import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate';
import { CoreSyncBaseProvider } from '@classes/base-sync'; import { CoreCourseActivitySyncBaseProvider } from '@core/course/classes/activity-sync';
import { AddonModScormProvider, AddonModScormAttemptCountResult } from './scorm'; import { AddonModScormProvider, AddonModScormAttemptCountResult } from './scorm';
import { AddonModScormOfflineProvider } from './scorm-offline'; import { AddonModScormOfflineProvider } from './scorm-offline';
import { AddonModScormPrefetchHandler } from './prefetch-handler'; import { AddonModScormPrefetchHandler } from './prefetch-handler';
@ -57,7 +57,7 @@ export interface AddonModScormSyncResult {
* Service to sync SCORMs. * Service to sync SCORMs.
*/ */
@Injectable() @Injectable()
export class AddonModScormSyncProvider extends CoreSyncBaseProvider { export class AddonModScormSyncProvider extends CoreCourseActivitySyncBaseProvider {
static AUTO_SYNCED = 'addon_mod_scorm_autom_synced'; static AUTO_SYNCED = 'addon_mod_scorm_autom_synced';
@ -67,12 +67,12 @@ export class AddonModScormSyncProvider extends CoreSyncBaseProvider {
syncProvider: CoreSyncProvider, textUtils: CoreTextUtilsProvider, translate: TranslateService, syncProvider: CoreSyncProvider, textUtils: CoreTextUtilsProvider, translate: TranslateService,
private eventsProvider: CoreEventsProvider, timeUtils: CoreTimeUtilsProvider, private eventsProvider: CoreEventsProvider, timeUtils: CoreTimeUtilsProvider,
private scormProvider: AddonModScormProvider, private scormOfflineProvider: AddonModScormOfflineProvider, private scormProvider: AddonModScormProvider, private scormOfflineProvider: AddonModScormOfflineProvider,
private prefetchHandler: AddonModScormPrefetchHandler, private utils: CoreUtilsProvider, prefetchHandler: AddonModScormPrefetchHandler, private utils: CoreUtilsProvider,
private prefetchDelegate: CoreCourseModulePrefetchDelegate, private courseProvider: CoreCourseProvider, prefetchDelegate: CoreCourseModulePrefetchDelegate, private courseProvider: CoreCourseProvider,
private logHelper: CoreCourseLogHelperProvider) { private logHelper: CoreCourseLogHelperProvider) {
super('AddonModScormSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, super('AddonModScormSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate,
timeUtils); timeUtils, prefetchDelegate, prefetchHandler);
this.componentTranslate = courseProvider.translateModuleName('scorm'); this.componentTranslate = courseProvider.translateModuleName('scorm');
} }
@ -196,7 +196,7 @@ export class AddonModScormSyncProvider extends CoreSyncBaseProvider {
if (updated) { if (updated) {
// Update downloaded data. // Update downloaded data.
promise = this.courseProvider.getModuleBasicInfoByInstance(scorm.id, 'scorm', siteId).then((module) => { promise = this.courseProvider.getModuleBasicInfoByInstance(scorm.id, 'scorm', siteId).then((module) => {
return this.prefetchAfterUpdate(module, scorm.course); return this.prefetchAfterUpdate(module, scorm.course, undefined, siteId);
}).catch(() => { }).catch(() => {
// Ignore errors. // Ignore errors.
}); });
@ -361,31 +361,6 @@ export class AddonModScormSyncProvider extends CoreSyncBaseProvider {
}); });
} }
/**
* Prefetch data after an update. It won't prefetch the data if the package file was updated.
*
* @param {any} module Module.
* @param {number} courseId Course ID.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when done.
*/
prefetchAfterUpdate(module: any, courseId: number, siteId?: string): Promise<any> {
// Get the module updates to check if the package was updated or not.
return this.prefetchDelegate.getModuleUpdates(module, courseId, true, siteId).then((result) => {
if (result && result.updates) {
// Only prefetch if the package file hasn't changed.
const fileChanged = !!result.updates.find((entry) => {
return entry.name == 'packagefiles';
});
if (!fileChanged) {
return this.prefetchHandler.download(module, courseId);
}
}
});
}
/** /**
* Save a snapshot from a synchronization. * Save a snapshot from a synchronization.
* *

View File

@ -46,9 +46,6 @@ export class CoreSyncBaseProvider {
// Store sync promises. // Store sync promises.
protected syncPromises: { [siteId: string]: { [uniqueId: string]: Promise<any> } } = {}; protected syncPromises: { [siteId: string]: { [uniqueId: string]: Promise<any> } } = {};
// List of services that will be injected using injector.
// It's done like this so subclasses don't have to send all the services to the parent in the constructor.
constructor(component: string, loggerProvider: CoreLoggerProvider, protected sitesProvider: CoreSitesProvider, constructor(component: string, loggerProvider: CoreLoggerProvider, protected sitesProvider: CoreSitesProvider,
protected appProvider: CoreAppProvider, protected syncProvider: CoreSyncProvider, protected appProvider: CoreAppProvider, protected syncProvider: CoreSyncProvider,
protected textUtils: CoreTextUtilsProvider, protected translate: TranslateService, protected textUtils: CoreTextUtilsProvider, protected translate: TranslateService,

View File

@ -0,0 +1,67 @@
// (C) Copyright 2015 Martin Dougiamas
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { TranslateService } from '@ngx-translate/core';
import { CoreSitesProvider } from '@providers/sites';
import { CoreSyncProvider } from '@providers/sync';
import { CoreLoggerProvider } from '@providers/logger';
import { CoreAppProvider } from '@providers/app';
import { CoreTextUtilsProvider } from '@providers/utils/text';
import { CoreTimeUtilsProvider } from '@providers/utils/time';
import { CoreSyncBaseProvider } from '@classes/base-sync';
import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate';
import { CoreCourseModulePrefetchHandlerBase } from './module-prefetch-handler';
/**
* Base class to create activity sync providers. It provides some common functions.
*/
export class CoreCourseActivitySyncBaseProvider extends CoreSyncBaseProvider {
constructor(component: string, loggerProvider: CoreLoggerProvider, protected sitesProvider: CoreSitesProvider,
protected appProvider: CoreAppProvider, protected syncProvider: CoreSyncProvider,
protected textUtils: CoreTextUtilsProvider, protected translate: TranslateService,
protected timeUtils: CoreTimeUtilsProvider, protected prefetchDelegate: CoreCourseModulePrefetchDelegate,
protected prefetchHandler: CoreCourseModulePrefetchHandlerBase) {
super(component, loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, timeUtils);
}
/**
* Conveniece function to refetch data after an update.
*
* @param {any} module Module.
* @param {number} courseId Course ID.
* @param {RegExp} [regex] RegExp to check if it should download data. Defaults to check files.
* @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when done.
*/
prefetchAfterUpdate(module: any, courseId: number, regex?: RegExp, siteId?: string): Promise<any> {
regex = regex || /^.*files$/;
// Get the module updates to check if the data was updated or not.
return this.prefetchDelegate.getModuleUpdates(module, courseId, true, siteId).then((result) => {
if (result && result.updates) {
// Only prefetch if files haven't changed.
const fileChanged = !!result.updates.find((entry) => {
return entry.match(regex);
});
if (!fileChanged) {
return this.prefetchHandler.download(module, courseId);
}
}
});
}
}

View File

@ -23,6 +23,7 @@ import { CoreCourseModuleMainComponent, CoreCourseModuleDelegate } from '@core/c
import { CoreCourseSectionPage } from '@core/course/pages/section/section.ts'; import { CoreCourseSectionPage } from '@core/course/pages/section/section.ts';
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper'; import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
import { AddonBlogProvider } from '@addon/blog/providers/blog'; import { AddonBlogProvider } from '@addon/blog/providers/blog';
import { CoreConstants } from '@core/constants';
/** /**
* Template class to easily create CoreCourseModuleMainComponent of resources (or activities without syncing). * Template class to easily create CoreCourseModuleMainComponent of resources (or activities without syncing).
@ -42,6 +43,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
description: string; // Module description. description: string; // Module description.
refreshIcon: string; // Refresh icon, normally spinner or refresh. refreshIcon: string; // Refresh icon, normally spinner or refresh.
prefetchStatusIcon: string; // Used when calling fillContextMenu. prefetchStatusIcon: string; // Used when calling fillContextMenu.
prefetchStatus: string; // Used when calling fillContextMenu.
prefetchText: string; // Used when calling fillContextMenu. prefetchText: string; // Used when calling fillContextMenu.
size: string; // Used when calling fillContextMenu. size: string; // Used when calling fillContextMenu.
@ -222,6 +224,14 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
this.courseHelper.fillContextMenu(this, this.module, this.courseId, refresh, this.component); this.courseHelper.fillContextMenu(this, this.module, this.courseId, refresh, this.component);
} }
/**
* Check if the module is prefetched or being prefetched. To make it faster, just use the data calculated by fillContextMenu.
* This means that you need to call fillContextMenu to make this work.
*/
protected isPrefetched(): boolean {
return this.prefetchStatus != CoreConstants.NOT_DOWNLOADABLE && this.prefetchStatus != CoreConstants.NOT_DOWNLOADED;
}
/** /**
* Expand the description. * Expand the description.
*/ */

View File

@ -732,6 +732,7 @@ export class CoreCourseHelperProvider {
return this.getModulePrefetchInfo(module, courseId, invalidateCache, component).then((moduleInfo) => { return this.getModulePrefetchInfo(module, courseId, invalidateCache, component).then((moduleInfo) => {
instance.size = moduleInfo.size > 0 ? moduleInfo.sizeReadable : 0; instance.size = moduleInfo.size > 0 ? moduleInfo.sizeReadable : 0;
instance.prefetchStatusIcon = moduleInfo.statusIcon; instance.prefetchStatusIcon = moduleInfo.statusIcon;
instance.prefetchStatus = moduleInfo.status;
if (moduleInfo.status != CoreConstants.NOT_DOWNLOADABLE) { if (moduleInfo.status != CoreConstants.NOT_DOWNLOADABLE) {
// Module is downloadable, get the text to display to prefetch. // Module is downloadable, get the text to display to prefetch.