diff --git a/scripts/langindex.json b/scripts/langindex.json index a2efd09d1..52408d77d 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1333,6 +1333,7 @@ "core.dismiss": "local_moodlemobileapp", "core.done": "survey", "core.download": "moodle", + "core.downloaded": "local_moodlemobileapp", "core.downloading": "local_moodlemobileapp", "core.edit": "moodle", "core.emptysplit": "local_moodlemobileapp", diff --git a/src/addon/mod/resource/providers/helper.ts b/src/addon/mod/resource/providers/helper.ts index 2d357c615..3b3f53d4d 100644 --- a/src/addon/mod/resource/providers/helper.ts +++ b/src/addon/mod/resource/providers/helper.ts @@ -115,6 +115,7 @@ export class AddonModResourceHelperProvider { isDisplayedEmbedded(module: any, display: number): boolean { if ((!module.contents.length && !module.contentsinfo) || !this.fileProvider.isAvailable() || (!this.sitesProvider.getCurrentSite().isVersionGreaterEqualThan('3.7') && this.isNextcloudFile(module))) { + return false; } let ext; diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index 66ca0a25a..0f9984153 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1333,6 +1333,7 @@ "core.dismiss": "Dismiss", "core.done": "Done", "core.download": "Download", + "core.downloaded": "Downloaded", "core.downloading": "Downloading", "core.edit": "Edit", "core.emptysplit": "This page will appear blank if the left panel is empty or is loading.", diff --git a/src/components/components.module.ts b/src/components/components.module.ts index e72475548..434b1213d 100644 --- a/src/components/components.module.ts +++ b/src/components/components.module.ts @@ -34,6 +34,7 @@ import { CoreContextMenuPopoverComponent } from './context-menu/context-menu-pop import { CoreCoursePickerMenuPopoverComponent } from './course-picker-menu/course-picker-menu-popover'; import { CoreChartComponent } from './chart/chart'; import { CoreChronoComponent } from './chrono/chrono'; +import { CoreDownloadRefreshComponent } from './download-refresh/download-refresh'; import { CoreLocalFileComponent } from './local-file/local-file'; import { CoreSitePickerComponent } from './site-picker/site-picker'; import { CoreTabsComponent } from './tabs/tabs'; @@ -72,6 +73,7 @@ import { CoreStyleComponent } from './style/style'; CoreCoursePickerMenuPopoverComponent, CoreChartComponent, CoreChronoComponent, + CoreDownloadRefreshComponent, CoreLocalFileComponent, CoreSitePickerComponent, CoreTabsComponent, @@ -118,6 +120,7 @@ import { CoreStyleComponent } from './style/style'; CoreContextMenuItemComponent, CoreChartComponent, CoreChronoComponent, + CoreDownloadRefreshComponent, CoreLocalFileComponent, CoreSitePickerComponent, CoreTabsComponent, diff --git a/src/components/download-refresh/core-download-refresh.html b/src/components/download-refresh/core-download-refresh.html new file mode 100644 index 000000000..c9b23a15a --- /dev/null +++ b/src/components/download-refresh/core-download-refresh.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/download-refresh/download-refresh.scss b/src/components/download-refresh/download-refresh.scss new file mode 100644 index 000000000..46381a154 --- /dev/null +++ b/src/components/download-refresh/download-refresh.scss @@ -0,0 +1,13 @@ +ion-app.app-root core-download-refresh { + font-size: 1.4rem; + + button, ion-icon { + cursor: pointer; + pointer-events: auto; + text-align: center; + } + + ion-icon, .core-icon-downloaded { + font-size: 1.8em; + } +} diff --git a/src/components/download-refresh/download-refresh.ts b/src/components/download-refresh/download-refresh.ts new file mode 100644 index 000000000..87d964c9b --- /dev/null +++ b/src/components/download-refresh/download-refresh.ts @@ -0,0 +1,55 @@ +// (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 { Component, Input, Output, EventEmitter } from '@angular/core'; +import { CoreConstants } from '@core/constants'; + +/** + * Component to show a download button with refresh option, the spinner and the status of it. + * + * Usage: + * + */ +@Component({ + selector: 'core-download-refresh', + templateUrl: 'core-download-refresh.html' +}) +export class CoreDownloadRefreshComponent { + @Input() status: string; // Download status. + @Input() enabled = false; // Whether the download is enabled. + @Input() loading = true; // Force loading status when is not downloading. + @Input() canTrustDownload = false; // If false, refresh will be shown if downloaded. + @Output() action: EventEmitter; // Will emit an event when the item clicked. + + statusDownloaded = CoreConstants.DOWNLOADED; + statusNotDownloaded = CoreConstants.NOT_DOWNLOADED; + statusOutdated = CoreConstants.OUTDATED; + statusDownloading = CoreConstants.DOWNLOADING; + + constructor() { + this.action = new EventEmitter(); + } + + /** + * Download clicked. + * + * @param {Event} e Click event. + * @param {boolean} refresh Whether it's refreshing. + */ + download(e: Event, refresh: boolean): void { + e.preventDefault(); + e.stopPropagation(); + this.action.emit(refresh); + } +} diff --git a/src/components/file/core-file.html b/src/components/file/core-file.html index 1ae020dfa..071deec11 100644 --- a/src/components/file/core-file.html +++ b/src/components/file/core-file.html @@ -3,13 +3,12 @@

{{fileName}}

{{ fileSizeReadable }}

{{ timemodified * 1000 | coreFormatDate }}

+
- + +
- diff --git a/src/components/file/file.scss b/src/components/file/file.scss index a39dcde10..227c565b8 100644 --- a/src/components/file/file.scss +++ b/src/components/file/file.scss @@ -7,6 +7,10 @@ ion-app.app-root { .card-ios core-file + core-file > .item-ios.item-block > .item-inner, core-file + core-file > .item-ios.item-block > .item-inner { border-top: $hairlines-width solid $list-ios-border-color; + .buttons { + min-height: 53px; + min-width: 58px; + } } .card-wp core-file + core-file > .item-wp.item-block > .item-inner, @@ -16,5 +20,16 @@ ion-app.app-root { core-file > .item.item-block > .item-inner { border-bottom: 0; + @include padding(null, 0, null, null); + .buttons { + display: flex; + flex-flow: row; + align-items: center; + z-index: 1; + justify-content: space-around; + align-content: center; + min-height: 52px; + min-width: 53px; + } } } \ No newline at end of file diff --git a/src/components/file/file.ts b/src/components/file/file.ts index 53fb53aa6..22d0c98af 100644 --- a/src/components/file/file.ts +++ b/src/components/file/file.ts @@ -44,9 +44,7 @@ export class CoreFileComponent implements OnInit, OnDestroy { @Input() showTime?: boolean | string = true; // Whether show file time modified. @Output() onDelete?: EventEmitter; // Will notify when the delete button is clicked. - isDownloaded: boolean; isDownloading: boolean; - showDownload: boolean; fileIcon: string; fileName: string; fileSizeReadable: string; @@ -110,13 +108,10 @@ export class CoreFileComponent implements OnInit, OnDestroy { */ protected calculateState(): Promise { return this.filepoolProvider.getFileStateByUrl(this.siteId, this.fileUrl, this.timemodified).then((state) => { - const canDownload = this.sitesProvider.getCurrentSite().canDownloadFiles(); + this.canDownload = this.sitesProvider.getCurrentSite().canDownloadFiles(); this.state = state; - this.isDownloaded = state === CoreConstants.DOWNLOADED || state === CoreConstants.OUTDATED; - this.isDownloading = canDownload && state === CoreConstants.DOWNLOADING; - this.showDownload = canDownload && (state === CoreConstants.NOT_DOWNLOADED || state === CoreConstants.OUTDATED || - (this.alwaysDownload && state === CoreConstants.DOWNLOADED)); + this.isDownloading = this.canDownload && state === CoreConstants.DOWNLOADING; }); } @@ -139,12 +134,12 @@ export class CoreFileComponent implements OnInit, OnDestroy { /** * Download a file and, optionally, open it afterwards. * - * @param {Event} e Click event. + * @param {Event} [e] Click event. * @param {boolean} openAfterDownload Whether the file should be opened after download. */ - download(e: Event, openAfterDownload: boolean): void { - e.preventDefault(); - e.stopPropagation(); + download(e?: Event, openAfterDownload: boolean = false): void { + e && e.preventDefault(); + e && e.stopPropagation(); let promise; @@ -168,7 +163,8 @@ export class CoreFileComponent implements OnInit, OnDestroy { return; } - if (!this.appProvider.isOnline() && (!openAfterDownload || (openAfterDownload && !this.isDownloaded))) { + if (!this.appProvider.isOnline() && (!openAfterDownload || (openAfterDownload && + !(this.state === CoreConstants.DOWNLOADED || this.state === CoreConstants.OUTDATED)))) { this.domUtils.showErrorModal('core.networkerrormsg', true); return; diff --git a/src/core/course/components/format/core-course-format.html b/src/core/course/components/format/core-course-format.html index 2600ed8fc..9ba99a96c 100644 --- a/src/core/course/components/format/core-course-format.html +++ b/src/core/course/components/format/core-course-format.html @@ -90,17 +90,9 @@
- - - - {{section.count}} / {{section.total}} - - + +
diff --git a/src/core/course/components/format/format.ts b/src/core/course/components/format/format.ts index 8c5bdbffe..1c87d2aed 100644 --- a/src/core/course/components/format/format.ts +++ b/src/core/course/components/format/format.ts @@ -119,7 +119,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { this.courseHelper.calculateSectionStatus(section, this.course.id, false).then(() => { if (section.isDownloading && !prefetchDelegate.isBeingDownloaded(downloadId)) { // All the modules are now downloading, set a download all promise. - this.prefetch(section, false); + this.prefetch(section); } }); } @@ -339,13 +339,10 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { /** * Confirm and prefetch a section. If the section is "all sections", prefetch all the sections. * - * @param {Event} e Click event. * @param {any} section Section to download. + * @param {boolean} refresh Refresh clicked (not used). */ - prefetch(e: Event, section: any): void { - e.preventDefault(); - e.stopPropagation(); - + prefetch(section: any, refresh: boolean = false): void { section.isCalculating = true; this.courseHelper.confirmDownloadSizeSection(this.course.id, section, this.sections).then(() => { this.prefetchSection(section, true); diff --git a/src/core/course/components/module-completion/module-completion.scss b/src/core/course/components/module-completion/module-completion.scss index 95674dc1c..23a677924 100644 --- a/src/core/course/components/module-completion/module-completion.scss +++ b/src/core/course/components/module-completion/module-completion.scss @@ -1,4 +1,6 @@ ion-app.app-root core-course-module-completion a { + display: block; + img { padding: 5px; width: 30px; diff --git a/src/core/course/components/module/core-course-module.html b/src/core/course/components/module/core-course-module.html index af880f447..6958c4dca 100644 --- a/src/core/course/components/module/core-course-module.html +++ b/src/core/course/components/module/core-course-module.html @@ -10,23 +10,12 @@
- - - - - + - - -
diff --git a/src/core/course/components/module/module.scss b/src/core/course/components/module/module.scss index 2541dd63a..2efad78fd 100644 --- a/src/core/course/components/module/module.scss +++ b/src/core/course/components/module/module.scss @@ -36,6 +36,8 @@ ion-app.app-root core-course-module { flex-flow: row; align-items: center; z-index: 1; + justify-content: space-around; + align-content: center; } .core-module-buttons core-course-module-completion, @@ -44,9 +46,8 @@ ion-app.app-root core-course-module { pointer-events: auto; } - .core-module-buttons-more .spinner { - @include position(null, 13px, null, null); - position: absolute; + .core-module-buttons core-course-module-completion { + text-align: center; } } diff --git a/src/core/course/components/module/module.ts b/src/core/course/components/module/module.ts index ed1c7bbf4..b4d8cba41 100644 --- a/src/core/course/components/module/module.ts +++ b/src/core/course/components/module/module.ts @@ -21,7 +21,6 @@ import { CoreCourseHelperProvider } from '../../providers/helper'; import { CoreCourseProvider } from '../../providers/course'; import { CoreCourseModuleHandlerButton } from '../../providers/module-delegate'; import { CoreCourseModulePrefetchDelegate, CoreCourseModulePrefetchHandler } from '../../providers/module-prefetch-delegate'; -import { CoreConstants } from '../../../constants'; /** * Component to display a module entry in a list of modules. @@ -52,9 +51,9 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { } @Output() completionChanged?: EventEmitter; // Will emit an event when the module completion changes. - showDownload: boolean; // Whether to display the download button. - showRefresh: boolean; // Whether to display the refresh button. - spinner: boolean; // Whether to display a spinner. + downloadStatus: string; + canCheckUpdates: boolean; + spinner: boolean; // Whether to display a loading spinner. downloadEnabled: boolean; // Whether the download of sections and modules is enabled. protected prefetchHandler: CoreCourseModulePrefetchHandler; @@ -81,6 +80,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { if (this.module.handlerData.showDownloadButton) { // Listen for changes on this module status, even if download isn't enabled. this.prefetchHandler = this.prefetchDelegate.getPrefetchHandlerFor(this.module); + this.canCheckUpdates = this.prefetchDelegate.canCheckUpdates(); this.statusObserver = this.eventsProvider.on(CoreEventsProvider.PACKAGE_STATUS_CHANGED, (data) => { if (data.componentId === this.module.id && this.prefetchHandler && @@ -135,13 +135,9 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { /** * Download the module. * - * @param {Event} event Click event. * @param {boolean} refresh Whether it's refreshing. */ - download(event: Event, refresh: boolean): void { - event.preventDefault(); - event.stopPropagation(); - + download(refresh: boolean): void { if (!this.prefetchHandler) { return; } @@ -168,10 +164,8 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { */ protected showStatus(status: string): void { if (status) { - this.spinner = status === CoreConstants.DOWNLOADING; - this.showDownload = status === CoreConstants.NOT_DOWNLOADED; - this.showRefresh = status === CoreConstants.OUTDATED || - (!this.prefetchDelegate.canCheckUpdates() && status === CoreConstants.DOWNLOADED); + this.spinner = false; + this.downloadStatus = status; if (this.module.handlerData.updateStatus) { this.module.handlerData.updateStatus(status); diff --git a/src/core/course/providers/helper.ts b/src/core/course/providers/helper.ts index 90df6282a..d1eb53fe5 100644 --- a/src/core/course/providers/helper.ts +++ b/src/core/course/providers/helper.ts @@ -197,11 +197,9 @@ export class CoreCourseHelperProvider { result.status = CoreConstants.DOWNLOADING; } + section.downloadStatus = result.status; + section.canCheckUpdates = this.prefetchDelegate.canCheckUpdates(); // Set this section data. - section.showDownload = result.status === CoreConstants.NOT_DOWNLOADED; - section.showRefresh = result.status === CoreConstants.OUTDATED || - (!this.prefetchDelegate.canCheckUpdates() && result.status === CoreConstants.DOWNLOADED); - if (result.status !== CoreConstants.DOWNLOADING || !this.prefetchDelegate.isBeingDownloaded(section.id)) { section.isDownloading = false; section.total = 0; @@ -250,9 +248,8 @@ export class CoreCourseHelperProvider { return Promise.all(promises).then(() => { if (allSectionsSection) { // Set "All sections" data. - allSectionsSection.showDownload = allSectionsStatus === CoreConstants.NOT_DOWNLOADED; - allSectionsSection.showRefresh = allSectionsStatus === CoreConstants.OUTDATED || - (!this.prefetchDelegate.canCheckUpdates() && allSectionsStatus === CoreConstants.DOWNLOADED); + allSectionsSection.downloadStatus = allSectionsStatus; + allSectionsSection.canCheckUpdates = this.prefetchDelegate.canCheckUpdates(); allSectionsSection.isDownloading = allSectionsStatus === CoreConstants.DOWNLOADING; } }).finally(() => { @@ -981,7 +978,7 @@ export class CoreCourseHelperProvider { */ getCourseStatusIconAndTitleFromStatus(status: string): {icon: string, title: string} { if (status == CoreConstants.DOWNLOADED) { - // Always show refresh icon, we cannot knew if there's anything new in course options. + // Always show refresh icon, we cannot know if there's anything new in course options. return { icon: 'refresh', title: 'core.course.refreshcourse' @@ -1330,9 +1327,8 @@ export class CoreCourseHelperProvider { return this.utils.allPromises(promises).then(() => { // Set "All sections" data. - section.showDownload = allSectionsStatus === CoreConstants.NOT_DOWNLOADED; - section.showRefresh = allSectionsStatus === CoreConstants.OUTDATED || - (!this.prefetchDelegate.canCheckUpdates() && allSectionsStatus === CoreConstants.DOWNLOADED); + section.downloadStatus = allSectionsStatus; + section.canCheckUpdates = this.prefetchDelegate.canCheckUpdates(); section.isDownloading = allSectionsStatus === CoreConstants.DOWNLOADING; }).finally(() => { section.isDownloading = false; diff --git a/src/lang/en.json b/src/lang/en.json index 27e5e170f..d1e2a0c96 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -72,6 +72,7 @@ "dismiss": "Dismiss", "done": "Done", "download": "Download", + "downloaded": "Downloaded", "downloading": "Downloading", "edit": "Edit", "emptysplit": "This page will appear blank if the left panel is empty or is loading.",