MOBILE-3437 files: Ignore downloaded files on prefetch calculations
parent
4f9adba63e
commit
2052080673
|
@ -28,6 +28,7 @@ import { CoreGroupsProvider } from '@providers/groups';
|
||||||
import { AddonModFeedbackSyncProvider } from './sync';
|
import { AddonModFeedbackSyncProvider } from './sync';
|
||||||
import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
|
import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
|
||||||
import { CorePluginFileDelegate } from '@providers/plugin-file-delegate';
|
import { CorePluginFileDelegate } from '@providers/plugin-file-delegate';
|
||||||
|
import { CoreWSExternalFile } from '@providers/ws';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler to prefetch feedbacks.
|
* Handler to prefetch feedbacks.
|
||||||
|
@ -68,26 +69,31 @@ export class AddonModFeedbackPrefetchHandler extends CoreCourseActivityPrefetchH
|
||||||
* @param single True if we're downloading a single module, false if we're downloading a whole section.
|
* @param single True if we're downloading a single module, false if we're downloading a whole section.
|
||||||
* @return Promise resolved with the list of files.
|
* @return Promise resolved with the list of files.
|
||||||
*/
|
*/
|
||||||
getFiles(module: any, courseId: number, single?: boolean): Promise<any[]> {
|
async getFiles(module: any, courseId: number, single?: boolean): Promise<CoreWSExternalFile[]> {
|
||||||
let files = [];
|
let files = [];
|
||||||
|
|
||||||
return this.feedbackProvider.getFeedback(courseId, module.id).then((feedback) => {
|
const feedback = await this.feedbackProvider.getFeedback(courseId, module.id);
|
||||||
|
|
||||||
// Get intro files and page after submit files.
|
// Get intro files and page after submit files.
|
||||||
files = feedback.pageaftersubmitfiles || [];
|
files = feedback.pageaftersubmitfiles || [];
|
||||||
files = files.concat(this.getIntroFilesFromInstance(module, feedback));
|
files = files.concat(this.getIntroFilesFromInstance(module, feedback));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await this.feedbackProvider.getItems(feedback.id);
|
||||||
|
|
||||||
return this.feedbackProvider.getItems(feedback.id);
|
|
||||||
}).then((response) => {
|
|
||||||
response.items.forEach((item) => {
|
response.items.forEach((item) => {
|
||||||
files = files.concat(item.itemfiles);
|
files = files.concat(item.itemfiles.map((file) => {
|
||||||
|
file.fileurl = file.fileurl || file.url;
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
return files;
|
} catch (e) {
|
||||||
}).catch(() => {
|
// Ignore errors.
|
||||||
// Any error, return the list we have.
|
}
|
||||||
return files;
|
|
||||||
});
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,7 +103,7 @@ export class AddonModFeedbackPrefetchHandler extends CoreCourseActivityPrefetchH
|
||||||
* @param courseId Course ID.
|
* @param courseId Course ID.
|
||||||
* @return Promise resolved with list of intro files.
|
* @return Promise resolved with list of intro files.
|
||||||
*/
|
*/
|
||||||
getIntroFiles(module: any, courseId: number): Promise<any[]> {
|
getIntroFiles(module: any, courseId: number): Promise<CoreWSExternalFile[]> {
|
||||||
return this.feedbackProvider.getFeedback(courseId, module.id).catch(() => {
|
return this.feedbackProvider.getFeedback(courseId, module.id).catch(() => {
|
||||||
// Not found, return undefined so module description is used.
|
// Not found, return undefined so module description is used.
|
||||||
}).then((feedback) => {
|
}).then((feedback) => {
|
||||||
|
|
|
@ -111,7 +111,7 @@ export class AddonModLessonPrefetchHandler extends CoreCourseActivityPrefetchHan
|
||||||
let files = lesson.mediafiles || [];
|
let files = lesson.mediafiles || [];
|
||||||
files = files.concat(this.getIntroFilesFromInstance(module, lesson));
|
files = files.concat(this.getIntroFilesFromInstance(module, lesson));
|
||||||
|
|
||||||
return this.pluginFileDelegate.getFilesSize(files);
|
return this.pluginFileDelegate.getFilesDownloadSize(files);
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
result = res;
|
result = res;
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ export class AddonModWikiPrefetchHandler extends CoreCourseActivityPrefetchHandl
|
||||||
siteId = this.sitesProvider.getCurrentSiteId();
|
siteId = this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
promises.push(this.getFiles(module, courseId, single, siteId).then((files) => {
|
promises.push(this.getFiles(module, courseId, single, siteId).then((files) => {
|
||||||
return this.pluginFileDelegate.getFilesSize(files);
|
return this.pluginFileDelegate.getFilesDownloadSize(files);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
promises.push(this.getAllPages(module, courseId, false, true, siteId).then((pages) => {
|
promises.push(this.getAllPages(module, courseId, false, true, siteId).then((pages) => {
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { CoreCourseProvider } from '../providers/course';
|
import { CoreCourseProvider } from '../providers/course';
|
||||||
|
import { CoreWSExternalFile } from '@providers/ws';
|
||||||
import { CoreCourseModulePrefetchHandler } from '../providers/module-prefetch-delegate';
|
import { CoreCourseModulePrefetchHandler } from '../providers/module-prefetch-delegate';
|
||||||
import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
|
import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
|
||||||
import { CorePluginFileDelegate } from '@providers/plugin-file-delegate';
|
import { CorePluginFileDelegate } from '@providers/plugin-file-delegate';
|
||||||
|
@ -114,7 +115,7 @@ export class CoreCourseModulePrefetchHandlerBase implements CoreCourseModulePref
|
||||||
* @param module The module object returned by WS.
|
* @param module The module object returned by WS.
|
||||||
* @return List of files.
|
* @return List of files.
|
||||||
*/
|
*/
|
||||||
getContentDownloadableFiles(module: any): any[] {
|
getContentDownloadableFiles(module: any): CoreWSExternalFile[] {
|
||||||
const files = [];
|
const files = [];
|
||||||
|
|
||||||
if (module.contents && module.contents.length) {
|
if (module.contents && module.contents.length) {
|
||||||
|
@ -139,7 +140,7 @@ export class CoreCourseModulePrefetchHandlerBase implements CoreCourseModulePref
|
||||||
*/
|
*/
|
||||||
getDownloadSize(module: any, courseId: number, single?: boolean): Promise<{ size: number, total: boolean }> {
|
getDownloadSize(module: any, courseId: number, single?: boolean): Promise<{ size: number, total: boolean }> {
|
||||||
return this.getFiles(module, courseId).then((files) => {
|
return this.getFiles(module, courseId).then((files) => {
|
||||||
return this.pluginFileDelegate.getFilesSize(files);
|
return this.pluginFileDelegate.getFilesDownloadSize(files);
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
return { size: -1, total: false };
|
return { size: -1, total: false };
|
||||||
});
|
});
|
||||||
|
@ -166,7 +167,7 @@ export class CoreCourseModulePrefetchHandlerBase implements CoreCourseModulePref
|
||||||
* @param single True if we're downloading a single module, false if we're downloading a whole section.
|
* @param single True if we're downloading a single module, false if we're downloading a whole section.
|
||||||
* @return Promise resolved with the list of files.
|
* @return Promise resolved with the list of files.
|
||||||
*/
|
*/
|
||||||
getFiles(module: any, courseId: number, single?: boolean): Promise<any[]> {
|
getFiles(module: any, courseId: number, single?: boolean): Promise<CoreWSExternalFile[]> {
|
||||||
// To be overridden.
|
// To be overridden.
|
||||||
return Promise.resolve([]);
|
return Promise.resolve([]);
|
||||||
}
|
}
|
||||||
|
@ -179,7 +180,7 @@ export class CoreCourseModulePrefetchHandlerBase implements CoreCourseModulePref
|
||||||
* @param ignoreCache True if it should ignore cached data (it will always fail in offline or server down).
|
* @param ignoreCache True if it should ignore cached data (it will always fail in offline or server down).
|
||||||
* @return Promise resolved with list of intro files.
|
* @return Promise resolved with list of intro files.
|
||||||
*/
|
*/
|
||||||
getIntroFiles(module: any, courseId: number, ignoreCache?: boolean): Promise<any[]> {
|
getIntroFiles(module: any, courseId: number, ignoreCache?: boolean): Promise<CoreWSExternalFile[]> {
|
||||||
return Promise.resolve(this.getIntroFilesFromInstance(module));
|
return Promise.resolve(this.getIntroFilesFromInstance(module));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +191,7 @@ export class CoreCourseModulePrefetchHandlerBase implements CoreCourseModulePref
|
||||||
* @param instance The instance to get the intro files (book, assign, ...). If not defined, module will be used.
|
* @param instance The instance to get the intro files (book, assign, ...). If not defined, module will be used.
|
||||||
* @return List of intro files.
|
* @return List of intro files.
|
||||||
*/
|
*/
|
||||||
getIntroFilesFromInstance(module: any, instance?: any): any[] {
|
getIntroFilesFromInstance(module: any, instance?: any): CoreWSExternalFile[] {
|
||||||
if (instance) {
|
if (instance) {
|
||||||
if (typeof instance.introfiles != 'undefined') {
|
if (typeof instance.introfiles != 'undefined') {
|
||||||
return instance.introfiles;
|
return instance.introfiles;
|
||||||
|
|
|
@ -1397,7 +1397,7 @@ export class CoreFilepoolProvider {
|
||||||
* @param html HTML code.
|
* @param html HTML code.
|
||||||
* @return List of fake file objects with file URLs.
|
* @return List of fake file objects with file URLs.
|
||||||
*/
|
*/
|
||||||
extractDownloadableFilesFromHtmlAsFakeFileObjects(html: string): any[] {
|
extractDownloadableFilesFromHtmlAsFakeFileObjects(html: string): CoreWSExternalFile[] {
|
||||||
const urls = this.extractDownloadableFilesFromHtml(html);
|
const urls = this.extractDownloadableFilesFromHtml(html);
|
||||||
|
|
||||||
// Convert them to fake file objects.
|
// Convert them to fake file objects.
|
||||||
|
@ -1768,46 +1768,50 @@ export class CoreFilepoolProvider {
|
||||||
* @param revision File revision. If not defined, it will be calculated using the URL.
|
* @param revision File revision. If not defined, it will be calculated using the URL.
|
||||||
* @return Promise resolved with the file state.
|
* @return Promise resolved with the file state.
|
||||||
*/
|
*/
|
||||||
getFileStateByUrl(siteId: string, fileUrl: string, timemodified: number = 0, filePath?: string, revision?: number)
|
async getFileStateByUrl(siteId: string, fileUrl: string, timemodified: number = 0, filePath?: string, revision?: number)
|
||||||
: Promise<string> {
|
: Promise<string> {
|
||||||
let fileId;
|
let file;
|
||||||
|
|
||||||
return this.fixPluginfileURL(siteId, fileUrl, timemodified).then((file) => {
|
try {
|
||||||
|
file = await this.fixPluginfileURL(siteId, fileUrl, timemodified);
|
||||||
fileUrl = file.fileurl;
|
} catch (e) {
|
||||||
timemodified = file.timemodified || timemodified;
|
|
||||||
revision = revision || this.getRevisionFromUrl(fileUrl);
|
|
||||||
fileId = this.getFileIdByUrl(fileUrl);
|
|
||||||
|
|
||||||
// Check if the file is in queue (waiting to be downloaded).
|
|
||||||
return this.hasFileInQueue(siteId, fileId).then(() => {
|
|
||||||
return CoreConstants.DOWNLOADING;
|
|
||||||
}).catch(() => {
|
|
||||||
// Check if the file is being downloaded right now.
|
|
||||||
const extension = this.mimeUtils.guessExtensionFromUrl(fileUrl),
|
|
||||||
path = filePath ? filePath : this.getFilePath(siteId, fileId, extension);
|
|
||||||
|
|
||||||
return Promise.resolve(path).then((filePath) => {
|
|
||||||
const downloadId = this.getFileDownloadId(fileUrl, filePath);
|
|
||||||
if (this.filePromises[siteId] && this.filePromises[siteId][downloadId]) {
|
|
||||||
return CoreConstants.DOWNLOADING;
|
|
||||||
}
|
|
||||||
|
|
||||||
// File is not being downloaded. Check if it's downloaded and if it's outdated.
|
|
||||||
return this.hasFileInPool(siteId, fileId).then((entry) => {
|
|
||||||
if (this.isFileOutdated(entry, revision, timemodified)) {
|
|
||||||
return CoreConstants.OUTDATED;
|
|
||||||
} else {
|
|
||||||
return CoreConstants.DOWNLOADED;
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
return CoreConstants.NOT_DOWNLOADED;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, () => {
|
|
||||||
return CoreConstants.NOT_DOWNLOADABLE;
|
return CoreConstants.NOT_DOWNLOADABLE;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
fileUrl = file.fileurl;
|
||||||
|
timemodified = file.timemodified || timemodified;
|
||||||
|
revision = revision || this.getRevisionFromUrl(fileUrl);
|
||||||
|
const fileId = this.getFileIdByUrl(fileUrl);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check if the file is in queue (waiting to be downloaded).
|
||||||
|
await this.hasFileInQueue(siteId, fileId);
|
||||||
|
|
||||||
|
return CoreConstants.DOWNLOADING;
|
||||||
|
} catch (e) {
|
||||||
|
// Check if the file is being downloaded right now.
|
||||||
|
const extension = this.mimeUtils.guessExtensionFromUrl(fileUrl);
|
||||||
|
filePath = filePath || (await this.getFilePath(siteId, fileId, extension));
|
||||||
|
|
||||||
|
const downloadId = this.getFileDownloadId(fileUrl, filePath);
|
||||||
|
|
||||||
|
if (this.filePromises[siteId] && this.filePromises[siteId][downloadId]) {
|
||||||
|
return CoreConstants.DOWNLOADING;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// File is not being downloaded. Check if it's downloaded and if it's outdated.
|
||||||
|
const entry = await this.hasFileInPool(siteId, fileId);
|
||||||
|
|
||||||
|
if (this.isFileOutdated(entry, revision, timemodified)) {
|
||||||
|
return CoreConstants.OUTDATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CoreConstants.DOWNLOADED;
|
||||||
|
} catch (e) {
|
||||||
|
return CoreConstants.NOT_DOWNLOADED;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,6 +18,8 @@ import { CoreLoggerProvider } from './logger';
|
||||||
import { CoreSitesProvider } from './sites';
|
import { CoreSitesProvider } from './sites';
|
||||||
import { CoreWSExternalFile } from '@providers/ws';
|
import { CoreWSExternalFile } from '@providers/ws';
|
||||||
import { FileEntry } from '@ionic-native/file';
|
import { FileEntry } from '@ionic-native/file';
|
||||||
|
import { CoreFilepool } from './filepool';
|
||||||
|
import { CoreConstants } from '@core/constants';
|
||||||
import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate';
|
import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate';
|
||||||
import { makeSingleton } from '@singletons/core.singletons';
|
import { makeSingleton } from '@singletons/core.singletons';
|
||||||
|
|
||||||
|
@ -234,6 +236,27 @@ export class CorePluginFileDelegate extends CoreDelegate {
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sum the filesizes from a list if they are not downloaded.
|
||||||
|
*
|
||||||
|
* @param files List of files to sum its filesize.
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
|
* @return Promise resolved with file size and a boolean to indicate if it is the total size or only partial.
|
||||||
|
*/
|
||||||
|
async getFilesDownloadSize(files: CoreWSExternalFile[], siteId?: string): Promise<{ size: number, total: boolean }> {
|
||||||
|
const filteredFiles = [];
|
||||||
|
|
||||||
|
await Promise.all(files.map(async (file) => {
|
||||||
|
const state = await CoreFilepool.instance.getFileStateByUrl(siteId, file.fileurl, file.timemodified);
|
||||||
|
|
||||||
|
if (state != CoreConstants.DOWNLOADED && state != CoreConstants.NOT_DOWNLOADABLE) {
|
||||||
|
filteredFiles.push(file);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
return this.getFilesSize(filteredFiles, siteId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sum the filesizes from a list of files checking if the size will be partial or totally calculated.
|
* Sum the filesizes from a list of files checking if the size will be partial or totally calculated.
|
||||||
*
|
*
|
||||||
|
@ -241,27 +264,24 @@ export class CorePluginFileDelegate extends CoreDelegate {
|
||||||
* @param siteId Site ID. If not defined, current site.
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return Promise resolved with file size and a boolean to indicate if it is the total size or only partial.
|
* @return Promise resolved with file size and a boolean to indicate if it is the total size or only partial.
|
||||||
*/
|
*/
|
||||||
getFilesSize(files: CoreWSExternalFile[], siteId?: string): Promise<{ size: number, total: boolean }> {
|
async getFilesSize(files: CoreWSExternalFile[], siteId?: string): Promise<{ size: number, total: boolean }> {
|
||||||
const promises = [],
|
const result = {
|
||||||
result = {
|
size: 0,
|
||||||
size: 0,
|
total: true
|
||||||
total: true
|
};
|
||||||
};
|
|
||||||
|
|
||||||
files.forEach((file) => {
|
await Promise.all(files.map(async (file) => {
|
||||||
promises.push(this.getFileSize(file, siteId).then((size) => {
|
const size = await this.getFileSize(file, siteId);
|
||||||
if (typeof size == 'undefined') {
|
|
||||||
// We don't have the file size, cannot calculate its total size.
|
|
||||||
result.total = false;
|
|
||||||
} else {
|
|
||||||
result.size += size;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises).then(() => {
|
if (typeof size == 'undefined') {
|
||||||
return result;
|
// We don't have the file size, cannot calculate its total size.
|
||||||
});
|
result.total = false;
|
||||||
|
} else {
|
||||||
|
result.size += size;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue