MOBILE-3134 Site add-ons: Update context menu when file is downloaded
parent
333f3f7188
commit
df79abe1e8
|
@ -68,6 +68,12 @@ export class CoreConstants {
|
||||||
static OUTDATED = 'outdated';
|
static OUTDATED = 'outdated';
|
||||||
static NOT_DOWNLOADABLE = 'notdownloadable';
|
static NOT_DOWNLOADABLE = 'notdownloadable';
|
||||||
|
|
||||||
|
// File status constants.
|
||||||
|
static FILE_DOWNLOAD = 'download';
|
||||||
|
static FILE_DOWNLOADING = 'downloading';
|
||||||
|
static FILE_DELETED = 'deleted';
|
||||||
|
static FILE_OUTDATE = 'outdated';
|
||||||
|
|
||||||
// Constants from Moodle's resourcelib.
|
// Constants from Moodle's resourcelib.
|
||||||
static RESOURCELIB_DISPLAY_AUTO = 0; // Try the best way.
|
static RESOURCELIB_DISPLAY_AUTO = 0; // Try the best way.
|
||||||
static RESOURCELIB_DISPLAY_EMBED = 1; // Display using object tag.
|
static RESOURCELIB_DISPLAY_EMBED = 1; // Display using object tag.
|
||||||
|
|
|
@ -49,6 +49,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
||||||
|
|
||||||
protected isDestroyed; // Whether the component is destroyed, used when calling fillContextMenu.
|
protected isDestroyed; // Whether the component is destroyed, used when calling fillContextMenu.
|
||||||
protected contextMenuStatusObserver; // Observer of package status changed, used when calling fillContextMenu.
|
protected contextMenuStatusObserver; // Observer of package status changed, used when calling fillContextMenu.
|
||||||
|
protected contextFileStatusObserver; // Observer of file status changed, used when calling fillContextMenu.
|
||||||
protected fetchContentDefaultError = 'core.course.errorgetmodule'; // Default error to show when loading contents.
|
protected fetchContentDefaultError = 'core.course.errorgetmodule'; // Default error to show when loading contents.
|
||||||
protected isCurrentView: boolean; // Whether the component is in the current view.
|
protected isCurrentView: boolean; // Whether the component is in the current view.
|
||||||
|
|
||||||
|
@ -285,6 +286,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.isDestroyed = true;
|
this.isDestroyed = true;
|
||||||
this.contextMenuStatusObserver && this.contextMenuStatusObserver.off();
|
this.contextMenuStatusObserver && this.contextMenuStatusObserver.off();
|
||||||
|
this.contextFileStatusObserver && this.contextFileStatusObserver.off();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -827,6 +827,18 @@ export class CoreCourseHelperProvider {
|
||||||
}
|
}
|
||||||
}, this.sitesProvider.getCurrentSiteId());
|
}, this.sitesProvider.getCurrentSiteId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof instance.contextFileStatusObserver == 'undefined' && component) {
|
||||||
|
const componentFileChangeStatusEvent = CoreFilepoolProvider.getComponentEventName(
|
||||||
|
this.sitesProvider.getCurrentSiteId(), component, module.id);
|
||||||
|
instance.contextFileStatusObserver = this.eventsProvider.on(componentFileChangeStatusEvent, (data) => {
|
||||||
|
if (((data.action == CoreConstants.FILE_DOWNLOAD && data.success == true) ||
|
||||||
|
data.action == CoreConstants.FILE_DELETED) &&
|
||||||
|
moduleInfo.status != CoreConstants.DOWNLOADING) {
|
||||||
|
this.fillContextMenu(instance, module, courseId, true, component);
|
||||||
|
}
|
||||||
|
}, this.sitesProvider.getCurrentSiteId());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -596,7 +596,7 @@ export class CoreFilepoolProvider {
|
||||||
|
|
||||||
// Check if the queue is running.
|
// Check if the queue is running.
|
||||||
this.checkQueueProcessing();
|
this.checkQueueProcessing();
|
||||||
this.notifyFileDownloading(siteId, fileId);
|
this.notifyFileDownloading(siteId, fileId, link ? [link] : []);
|
||||||
|
|
||||||
return this.getQueuePromise(siteId, fileId, true, onProgress);
|
return this.getQueuePromise(siteId, fileId, true, onProgress);
|
||||||
}
|
}
|
||||||
|
@ -877,6 +877,17 @@ export class CoreFilepoolProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare links from component and componentId.
|
||||||
|
*
|
||||||
|
* @param component The component to link the file to.
|
||||||
|
* @param componentId An ID to use in conjunction with the component.
|
||||||
|
* @return Resolved means yes, rejected means no.
|
||||||
|
*/
|
||||||
|
createFileLinks(component: string, componentId: string | number): any[] {
|
||||||
|
return [{ component: component, componentId: this.fixComponentId(componentId) }];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given the current status of a list of packages and the status of one of the packages,
|
* Given the current status of a list of packages and the status of one of the packages,
|
||||||
* determine the new status for the list of packages. The status of a list of packages is:
|
* determine the new status for the list of packages. The status of a list of packages is:
|
||||||
|
@ -1197,14 +1208,14 @@ export class CoreFilepoolProvider {
|
||||||
|
|
||||||
if (typeof fileObject === 'undefined') {
|
if (typeof fileObject === 'undefined') {
|
||||||
// We do not have the file, download and add to pool.
|
// We do not have the file, download and add to pool.
|
||||||
this.notifyFileDownloading(siteId, fileId);
|
this.notifyFileDownloading(siteId, fileId, this.createFileLinks(component, componentId));
|
||||||
|
|
||||||
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress);
|
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress);
|
||||||
|
|
||||||
} else if (this.isFileOutdated(fileObject, options.revision, options.timemodified) &&
|
} else if (this.isFileOutdated(fileObject, options.revision, options.timemodified) &&
|
||||||
this.appProvider.isOnline() && !ignoreStale) {
|
this.appProvider.isOnline() && !ignoreStale) {
|
||||||
// The file is outdated, force the download and update it.
|
// The file is outdated, force the download and update it.
|
||||||
this.notifyFileDownloading(siteId, fileId);
|
this.notifyFileDownloading(siteId, fileId, this.createFileLinks(component, componentId));
|
||||||
|
|
||||||
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject);
|
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject);
|
||||||
}
|
}
|
||||||
|
@ -1220,14 +1231,14 @@ export class CoreFilepoolProvider {
|
||||||
return response;
|
return response;
|
||||||
}, () => {
|
}, () => {
|
||||||
// The file was not found in the pool, weird.
|
// The file was not found in the pool, weird.
|
||||||
this.notifyFileDownloading(siteId, fileId);
|
this.notifyFileDownloading(siteId, fileId, this.createFileLinks(component, componentId));
|
||||||
|
|
||||||
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject);
|
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject);
|
||||||
});
|
});
|
||||||
|
|
||||||
}, () => {
|
}, () => {
|
||||||
// The file is not in the pool just yet.
|
// The file is not in the pool just yet.
|
||||||
this.notifyFileDownloading(siteId, fileId);
|
this.notifyFileDownloading(siteId, fileId, this.createFileLinks(component, componentId));
|
||||||
|
|
||||||
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress);
|
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress);
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
|
@ -1236,11 +1247,11 @@ export class CoreFilepoolProvider {
|
||||||
// Ignore errors.
|
// Ignore errors.
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.notifyFileDownloaded(siteId, fileId);
|
this.notifyFileDownloaded(siteId, fileId, this.createFileLinks(component, componentId));
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
this.notifyFileDownloadError(siteId, fileId);
|
this.notifyFileDownloadError(siteId, fileId, this.createFileLinks(component, componentId));
|
||||||
|
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
});
|
});
|
||||||
|
@ -1393,6 +1404,18 @@ export class CoreFilepoolProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the event used to notify file status to component (CoreEventsProvider).
|
||||||
|
*
|
||||||
|
* @param siteId The site ID.
|
||||||
|
* @param component The component name.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
* @return Event name.
|
||||||
|
*/
|
||||||
|
static getComponentEventName(siteId: string, component: string, componentId: string | number): string {
|
||||||
|
return 'ComponentEventFileChangeStatus:' + siteId + ':' + component + ':' + componentId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience function to get component files.
|
* Convenience function to get component files.
|
||||||
*
|
*
|
||||||
|
@ -2439,14 +2462,35 @@ export class CoreFilepoolProvider {
|
||||||
return !!entry.isexternalfile || (entry.revision < 1 && !entry.timemodified);
|
return !!entry.isexternalfile || (entry.revision < 1 && !entry.timemodified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify a file has been changed status to Component.
|
||||||
|
*
|
||||||
|
* @param siteId The site ID.
|
||||||
|
* @param fileId The file ID.
|
||||||
|
* @param fileStatus The file status after changed
|
||||||
|
* @param links The links to the Components
|
||||||
|
*/
|
||||||
|
protected notifyFileStatusToComponents(siteId: string, fileId: string, fileStatus: any, links: any[]): void {
|
||||||
|
fileStatus.fileId = fileId;
|
||||||
|
links.forEach((link) => {
|
||||||
|
this.eventsProvider.trigger(CoreFilepoolProvider.getComponentEventName(siteId, link.component, link.componentId),
|
||||||
|
fileStatus, siteId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify a file has been deleted.
|
* Notify a file has been deleted.
|
||||||
*
|
*
|
||||||
* @param siteId The site ID.
|
* @param siteId The site ID.
|
||||||
* @param fileId The file ID.
|
* @param fileId The file ID.
|
||||||
|
* @param links The links to components.
|
||||||
*/
|
*/
|
||||||
protected notifyFileDeleted(siteId: string, fileId: string): void {
|
protected notifyFileDeleted(siteId: string, fileId: string, links: any[]): void {
|
||||||
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'deleted' });
|
const fileStatus = {
|
||||||
|
action: CoreConstants.FILE_DELETED
|
||||||
|
};
|
||||||
|
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus);
|
||||||
|
this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2454,9 +2498,15 @@ export class CoreFilepoolProvider {
|
||||||
*
|
*
|
||||||
* @param siteId The site ID.
|
* @param siteId The site ID.
|
||||||
* @param fileId The file ID.
|
* @param fileId The file ID.
|
||||||
|
* @param links The links to components.
|
||||||
*/
|
*/
|
||||||
protected notifyFileDownloaded(siteId: string, fileId: string): void {
|
protected notifyFileDownloaded(siteId: string, fileId: string, links: any[]): void {
|
||||||
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'download', success: true });
|
const fileStatus = {
|
||||||
|
action: CoreConstants.FILE_DOWNLOAD,
|
||||||
|
success: true
|
||||||
|
};
|
||||||
|
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus);
|
||||||
|
this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2464,9 +2514,15 @@ export class CoreFilepoolProvider {
|
||||||
*
|
*
|
||||||
* @param siteId The site ID.
|
* @param siteId The site ID.
|
||||||
* @param fileId The file ID.
|
* @param fileId The file ID.
|
||||||
|
* @param links The links to components.
|
||||||
*/
|
*/
|
||||||
protected notifyFileDownloadError(siteId: string, fileId: string): void {
|
protected notifyFileDownloadError(siteId: string, fileId: string, links: any[]): void {
|
||||||
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'download', success: false });
|
const fileStatus = {
|
||||||
|
action: CoreConstants.FILE_DOWNLOAD,
|
||||||
|
success: false
|
||||||
|
};
|
||||||
|
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus);
|
||||||
|
this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2474,9 +2530,15 @@ export class CoreFilepoolProvider {
|
||||||
*
|
*
|
||||||
* @param siteId The site ID.
|
* @param siteId The site ID.
|
||||||
* @param fileId The file ID.
|
* @param fileId The file ID.
|
||||||
|
* @param links The links to components.
|
||||||
*/
|
*/
|
||||||
protected notifyFileDownloading(siteId: string, fileId: string): void {
|
protected notifyFileDownloading(siteId: string, fileId: string, links: any[]): void {
|
||||||
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'downloading' });
|
const fileStatus = {
|
||||||
|
action: CoreConstants.FILE_DOWNLOADING
|
||||||
|
};
|
||||||
|
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus);
|
||||||
|
this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2484,9 +2546,14 @@ export class CoreFilepoolProvider {
|
||||||
*
|
*
|
||||||
* @param siteId The site ID.
|
* @param siteId The site ID.
|
||||||
* @param fileId The file ID.
|
* @param fileId The file ID.
|
||||||
|
* @param links The links to components.
|
||||||
*/
|
*/
|
||||||
protected notifyFileOutdated(siteId: string, fileId: string): void {
|
protected notifyFileOutdated(siteId: string, fileId: string, links: any[]): void {
|
||||||
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'outdated' });
|
const fileStatus = {
|
||||||
|
action: CoreConstants.FILE_OUTDATE
|
||||||
|
};
|
||||||
|
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), fileStatus);
|
||||||
|
this.notifyFileStatusToComponents(siteId, fileId, fileStatus, links);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2612,7 +2679,7 @@ export class CoreFilepoolProvider {
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.treatQueueDeferred(siteId, fileId, true);
|
this.treatQueueDeferred(siteId, fileId, true);
|
||||||
});
|
});
|
||||||
this.notifyFileDownloaded(siteId, fileId);
|
this.notifyFileDownloaded(siteId, fileId, links);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2627,7 +2694,7 @@ export class CoreFilepoolProvider {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.treatQueueDeferred(siteId, fileId, true);
|
this.treatQueueDeferred(siteId, fileId, true);
|
||||||
this.notifyFileDownloaded(siteId, fileId);
|
this.notifyFileDownloaded(siteId, fileId, links);
|
||||||
|
|
||||||
// Wait for the item to be removed from queue before resolving the promise.
|
// Wait for the item to be removed from queue before resolving the promise.
|
||||||
// If the item could not be removed from queue we still resolve the promise.
|
// If the item could not be removed from queue we still resolve the promise.
|
||||||
|
@ -2677,12 +2744,12 @@ export class CoreFilepoolProvider {
|
||||||
// Consider this as a silent error, never reject the promise here.
|
// Consider this as a silent error, never reject the promise here.
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.treatQueueDeferred(siteId, fileId, false, errorMessage);
|
this.treatQueueDeferred(siteId, fileId, false, errorMessage);
|
||||||
this.notifyFileDownloadError(siteId, fileId);
|
this.notifyFileDownloadError(siteId, fileId, links);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// We considered the file as legit but did not get it, failure.
|
// We considered the file as legit but did not get it, failure.
|
||||||
this.treatQueueDeferred(siteId, fileId, false, errorMessage);
|
this.treatQueueDeferred(siteId, fileId, false, errorMessage);
|
||||||
this.notifyFileDownloadError(siteId, fileId);
|
this.notifyFileDownloadError(siteId, fileId, links);
|
||||||
|
|
||||||
return Promise.reject(errorObject);
|
return Promise.reject(errorObject);
|
||||||
}
|
}
|
||||||
|
@ -2730,30 +2797,37 @@ export class CoreFilepoolProvider {
|
||||||
// If file not found, use the path without extension.
|
// If file not found, use the path without extension.
|
||||||
return path;
|
return path;
|
||||||
}).then((path) => {
|
}).then((path) => {
|
||||||
const promises = [];
|
const conditions = {
|
||||||
|
fileId: fileId
|
||||||
|
};
|
||||||
|
|
||||||
// Remove entry from filepool store.
|
// Get links to components to notify to them before remove.
|
||||||
promises.push(db.deleteRecords(this.FILES_TABLE, { fileId: fileId }));
|
return db.getRecords(this.LINKS_TABLE, conditions).then((links) => {
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
// Remove links.
|
// Remove entry from filepool store.
|
||||||
promises.push(db.deleteRecords(this.LINKS_TABLE, { fileId: fileId }));
|
promises.push(db.deleteRecords(this.FILES_TABLE, conditions));
|
||||||
|
|
||||||
// Remove the file.
|
// Remove links.
|
||||||
if (this.fileProvider.isAvailable()) {
|
promises.push(db.deleteRecords(this.LINKS_TABLE, conditions));
|
||||||
promises.push(this.fileProvider.removeFile(path).catch((error) => {
|
|
||||||
if (error && error.code == 1) {
|
|
||||||
// Not found, ignore error since maybe it was deleted already.
|
|
||||||
} else {
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.all(promises).then(() => {
|
// Remove the file.
|
||||||
this.notifyFileDeleted(siteId, fileId);
|
if (this.fileProvider.isAvailable()) {
|
||||||
|
promises.push(this.fileProvider.removeFile(path).catch((error) => {
|
||||||
|
if (error && error.code == 1) {
|
||||||
|
// Not found, ignore error since maybe it was deleted already.
|
||||||
|
} else {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
return this.pluginFileDelegate.fileDeleted(fileUrl, path, siteId).catch((error) => {
|
return Promise.all(promises).then(() => {
|
||||||
// Ignore errors.
|
this.notifyFileDeleted(siteId, fileId, links);
|
||||||
|
|
||||||
|
return this.pluginFileDelegate.fileDeleted(fileUrl, path, siteId).catch((error) => {
|
||||||
|
// Ignore errors.
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue