From d90f7d7c2fe2048a2039fa0b5f21e9cb3684e45e Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 25 Nov 2015 11:52:39 +0100 Subject: [PATCH] MOBILE-1325 folder: Support prefetch folder --- www/addons/mod_folder/main.js | 5 +- .../services/course_content_handler.js | 60 ++++++++++++++- www/addons/mod_folder/services/folder.js | 72 +++++++++++++++++- .../mod_folder/services/prefetch_handler.js | 75 +++++++++++++++++++ .../course/services/prefetchdelegate.js | 5 ++ 5 files changed, 213 insertions(+), 4 deletions(-) create mode 100644 www/addons/mod_folder/services/prefetch_handler.js diff --git a/www/addons/mod_folder/main.js b/www/addons/mod_folder/main.js index 4bb79b37c20..364f7e05678 100644 --- a/www/addons/mod_folder/main.js +++ b/www/addons/mod_folder/main.js @@ -14,6 +14,8 @@ angular.module('mm.addons.mod_folder', ['mm.core']) +.constant('mmaModFolderComponent', 'mmaModFolder') + .config(function($stateProvider) { $stateProvider @@ -36,6 +38,7 @@ angular.module('mm.addons.mod_folder', ['mm.core']) }) -.config(function($mmCourseDelegateProvider) { +.config(function($mmCourseDelegateProvider, $mmCoursePrefetchDelegateProvider) { $mmCourseDelegateProvider.registerContentHandler('mmaModFolder', 'folder', '$mmaModFolderCourseContentHandler'); + $mmCoursePrefetchDelegateProvider.registerPrefetchHandler('mmaModFolder', 'folder', '$mmaModFolderPrefetchHandler'); }); diff --git a/www/addons/mod_folder/services/course_content_handler.js b/www/addons/mod_folder/services/course_content_handler.js index 1c6f18a0c5a..b5fcf773bcf 100644 --- a/www/addons/mod_folder/services/course_content_handler.js +++ b/www/addons/mod_folder/services/course_content_handler.js @@ -21,7 +21,9 @@ angular.module('mm.addons.mod_folder') * @ngdoc service * @name $mmaModFolderCourseContentHandler */ -.factory('$mmaModFolderCourseContentHandler', function($mmCourse, $mmaModFolder, $state) { +.factory('$mmaModFolderCourseContentHandler', function($mmCourse, $mmaModFolder, $mmEvents, $state, $mmSite, $mmUtil, $mmFilepool, + $mmCoursePrefetchDelegate, mmCoreDownloading, mmCoreNotDownloaded, mmCoreOutdated, mmCoreEventPackageStatusChanged, + mmaModFolderComponent) { var self = {}; /** @@ -49,11 +51,67 @@ angular.module('mm.addons.mod_folder') */ self.getController = function(module, courseid, sectionid) { return function($scope) { + var downloadBtn, + refreshBtn, + revision = $mmFilepool.getRevisionFromFileList(module.contents), + timemodified = $mmFilepool.getTimemodifiedFromFileList(module.contents); + + // Prefetch folder contents. + function prefetchFolder(e) { + e.preventDefault(); + e.stopPropagation(); + $mmaModFolder.prefetchContent(module).catch(function() { + $mmUtil.showErrorModal('mm.core.errordownloading', true); + }); + } + + downloadBtn = { + hidden: true, + icon: 'ion-ios-cloud-download', + label: 'mm.core.download', + action: prefetchFolder + }; + + refreshBtn = { + hidden: true, + icon: 'ion-android-refresh', + label: 'mm.core.refresh', + action: prefetchFolder + }; + $scope.icon = $mmCourse.getModuleIconSrc('folder'); $scope.title = module.name; + $scope.buttons = [downloadBtn, refreshBtn]; + $scope.spinner = false; + $scope.action = function(e) { + e.preventDefault(); + e.stopPropagation(); $state.go('site.mod_folder', {module: module, courseid: courseid, sectionid: sectionid}); }; + + // Show buttons according to module status. + function showStatus(status) { + if (status) { + $scope.spinner = status === mmCoreDownloading; + downloadBtn.hidden = status !== mmCoreNotDownloaded; + refreshBtn.hidden = status !== mmCoreOutdated; + } + } + + // Listen for changes on this module status. + var statusObserver = $mmEvents.on(mmCoreEventPackageStatusChanged, function(data) { + if (data.siteid === $mmSite.getId() && data.componentId === module.id && data.component === mmaModFolderComponent) { + showStatus(data.status); + } + }); + + // Get current status to decide which icon should be shown. + $mmCoursePrefetchDelegate.getModuleStatus(module, revision, timemodified).then(showStatus); + + $scope.$on('$destroy', function() { + statusObserver && statusObserver.off && statusObserver.off(); + }); }; }; diff --git a/www/addons/mod_folder/services/folder.js b/www/addons/mod_folder/services/folder.js index 108da0ca220..30bbc969a2c 100644 --- a/www/addons/mod_folder/services/folder.js +++ b/www/addons/mod_folder/services/folder.js @@ -20,14 +20,32 @@ angular.module('mm.addons.mod_folder') * @module mm.addons.mod_folder * @ngdoc service * @name $mmaModFolder + * @todo Adding a new file in a folder updates the revision of all the files, so they're all shown as outdated. + * To ignore revision in folders we'll have to modify $mmCoursePrefetchDelegate, mm-file and $mmFilepool. */ -.factory('$mmaModFolder', function($mmSite, $mmUtil, $mmCourse, $q) { +.factory('$mmaModFolder', function($mmSite, $mmCourse, $q, $mmFilepool, mmaModFolderComponent) { var self = {}; + /** + * Download all the content. + * + * @module mm.addons.mod_folder + * @ngdoc method + * @name $mmaModFolder#downloadAllContent + * @param {Object} module The module object. + * @return {Promise} Promise resolved when all content is downloaded. Data returned is not reliable. + */ + self.downloadAllContent = function(module) { + var files = self.getDownloadableFiles(module), + revision = $mmFilepool.getRevisionFromFileList(module.contents), + timemod = $mmFilepool.getTimemodifiedFromFileList(module.contents); + return $mmFilepool.downloadPackage($mmSite.getId(), files, mmaModFolderComponent, module.id, revision, timemod); + }; + /** * Format folder contents, creating directory structure. * - * @module mm.addons.mod_url + * @module mm.addons.mod_folder * @ngdoc method * @name $mmaModFolder#formatContents * @param {Object[]} contents Folder contents. @@ -94,6 +112,40 @@ angular.module('mm.addons.mod_folder') return folders.concat(files); }; + /** + * Returns a list of files that can be downloaded. + * + * @module mm.addons.mod_folder + * @ngdoc method + * @name $mmaModFolder#getDownloadableFiles + * @param {Object} module The module object returned by WS. + * @return {Object[]} List of files. + */ + self.getDownloadableFiles = function(module) { + var files = []; + + angular.forEach(module.contents, function(content) { + if (self.isFileDownloadable(content)) { + files.push(content); + } + }); + + return files; + }; + + /** + * Check if a file is downloadable. The file param must have a 'type' attribute like in core_course_get_contents response. + * + * @module mm.addons.mod_folder + * @ngdoc method + * @name $mmaModFolder#isFileDownloadable + * @param {Object} file File to check. + * @return {Boolean} True if downloadable, false otherwise. + */ + self.isFileDownloadable = function(file) { + return file.type === 'file'; + }; + /** * Report a folder as being viewed. * @@ -113,5 +165,21 @@ angular.module('mm.addons.mod_folder') return $q.reject(); }; + /** + * Prefetch the content. + * + * @module mm.addons.mod_folder + * @ngdoc method + * @name $mmaModFolder#prefetchContent + * @param {Object} module The module object. + * @return {Promise} Promise resolved when all content is downloaded. Data returned is not reliable. + */ + self.prefetchContent = function(module) { + var files = self.getDownloadableFiles(module), + revision = $mmFilepool.getRevisionFromFileList(module.contents), + timemod = $mmFilepool.getTimemodifiedFromFileList(module.contents); + return $mmFilepool.prefetchPackage($mmSite.getId(), files, mmaModFolderComponent, module.id, revision, timemod); + }; + return self; }); diff --git a/www/addons/mod_folder/services/prefetch_handler.js b/www/addons/mod_folder/services/prefetch_handler.js new file mode 100644 index 00000000000..6f77751afdc --- /dev/null +++ b/www/addons/mod_folder/services/prefetch_handler.js @@ -0,0 +1,75 @@ +// (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. + +angular.module('mm.addons.mod_folder') + +/** + * Mod folder prefetch handler. + * + * @module mm.addons.mod_folder + * @ngdoc service + * @name $mmaModFolderPrefetchHandler + */ +.factory('$mmaModFolderPrefetchHandler', function($mmaModFolder, $mmSite, mmaModFolderComponent) { + + var self = {}; + + self.component = mmaModFolderComponent; + + /** + * Get the download size of a module. + * + * @module mm.addons.mod_folder + * @ngdoc method + * @name $mmaModFolderPrefetchHandler#getDownloadSize + * @param {Object} module Module to get the size. + * @return {Number} Size. + */ + self.getDownloadSize = function(module) { + var size = 0; + angular.forEach(module.contents, function(content) { + if ($mmaModFolder.isFileDownloadable(content) && content.filesize) { + size = size + content.filesize; + } + }); + return size; + }; + + /** + * Whether or not the module is enabled for the site. + * + * @module mm.addons.mod_folder + * @ngdoc method + * @name $mmaModFolderPrefetchHandler#isEnabled + * @return {Boolean} + */ + self.isEnabled = function() { + return true; + }; + + /** + * Prefetch the module. + * + * @module mm.addons.mod_folder + * @ngdoc method + * @name $mmaModFolderPrefetchHandler#prefetch + * @param {Object} module The module object returned by WS. + * @return {Promise} Promise resolved when all files have been downloaded. Data returned is not reliable. + */ + self.prefetch = function(module) { + return $mmaModFolder.prefetchContent(module); + }; + + return self; +}); diff --git a/www/core/components/course/services/prefetchdelegate.js b/www/core/components/course/services/prefetchdelegate.js index bc987243e36..e83d8a63d06 100644 --- a/www/core/components/course/services/prefetchdelegate.js +++ b/www/core/components/course/services/prefetchdelegate.js @@ -170,6 +170,11 @@ angular.module('mm.core') if (handler.getFiles) { // If the handler defines its own function to determine the files, use it. files = handler.getFiles(module); } + + if (files.length === 0) { // No files, treat is as downloaded. + return $q.when(mmCoreDownloaded); + } + revision = revision || $mmFilepool.getRevisionFromFileList(files); timemodified = timemodified || $mmFilepool.getTimemodifiedFromFileList(files);