Skip to content

Commit e245e50

Browse files
authored
Merge pull request #2273 from dpalou/MOBILE-3332
Mobile 3332
2 parents 357c18f + 3aea77a commit e245e50

File tree

18 files changed

+319
-58
lines changed

18 files changed

+319
-58
lines changed

scripts/langindex.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,7 @@
16191619
"core.h5p.offlineDialogRetryButtonLabel": "h5p",
16201620
"core.h5p.offlineDialogRetryMessage": "h5p",
16211621
"core.h5p.offlineSuccessfulSubmit": "h5p",
1622+
"core.h5p.offlinedisabled": "local_moodlemobileapp",
16221623
"core.h5p.originator": "h5p",
16231624
"core.h5p.pd": "h5p",
16241625
"core.h5p.pddl": "h5p",

src/addon/mod/book/components/index/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
119119
protected fetchContent(refresh?: boolean): Promise<any> {
120120
const promises = [];
121121
let downloadFailed = false;
122+
let downloadFailError;
122123

123124
// Try to get the book data.
124125
promises.push(this.bookProvider.getBook(this.courseId, this.module.id).then((book) => {
@@ -129,9 +130,10 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
129130
}));
130131

131132
// Download content. This function also loads module contents if needed.
132-
promises.push(this.prefetchDelegate.download(this.module, this.courseId).catch(() => {
133+
promises.push(this.prefetchDelegate.download(this.module, this.courseId).catch((error) => {
133134
// Mark download as failed but go on since the main files could have been downloaded.
134135
downloadFailed = true;
136+
downloadFailError = error;
135137

136138
if (!this.module.contents.length) {
137139
// Try to load module contents for offline usage.
@@ -163,7 +165,7 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
163165
return this.loadChapter(this.currentChapter).then(() => {
164166
if (downloadFailed && this.appProvider.isOnline()) {
165167
// We could load the main file but the download failed. Show error message.
166-
this.domUtils.showErrorModal('core.errordownloadingsomefiles', true);
168+
this.showErrorDownloadingSomeFiles(downloadFailError);
167169
}
168170
}).catch(() => {
169171
// Ignore errors, they're handled inside the loadChapter function.

src/addon/mod/imscp/components/index/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,16 +76,18 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom
7676
*/
7777
protected fetchContent(refresh?: boolean): Promise<any> {
7878
let downloadFailed = false;
79+
let downloadFailError;
7980
const promises = [];
8081

8182
promises.push(this.imscpProvider.getImscp(this.courseId, this.module.id).then((imscp) => {
8283
this.description = imscp.intro;
8384
this.dataRetrieved.emit(imscp);
8485
}));
8586

86-
promises.push(this.imscpPrefetch.download(this.module, this.courseId).catch(() => {
87+
promises.push(this.imscpPrefetch.download(this.module, this.courseId).catch((error) => {
8788
// Mark download as failed but go on since the main files could have been downloaded.
8889
downloadFailed = true;
90+
downloadFailError = error;
8991

9092
return this.courseProvider.loadModuleContents(this.module, this.courseId).catch((error) => {
9193
// Error getting module contents, fail.
@@ -109,7 +111,7 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom
109111
}).then(() => {
110112
if (downloadFailed && this.appProvider.isOnline()) {
111113
// We could load the main file but the download failed. Show error message.
112-
this.domUtils.showErrorModal('core.errordownloadingsomefiles', true);
114+
this.showErrorDownloadingSomeFiles(downloadFailError);
113115
}
114116

115117
}).finally(() => {

src/addon/mod/page/components/index/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,13 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp
7878
*/
7979
protected fetchContent(refresh?: boolean): Promise<any> {
8080
let downloadFailed = false;
81+
let downloadFailError;
8182

8283
// Download content. This function also loads module contents if needed.
83-
return this.pagePrefetch.download(this.module, this.courseId).catch(() => {
84+
return this.pagePrefetch.download(this.module, this.courseId).catch((error) => {
8485
// Mark download as failed but go on since the main files could have been downloaded.
8586
downloadFailed = true;
87+
downloadFailError = error;
8688
}).then(() => {
8789
if (!this.module.contents.length) {
8890
// Try to load module contents for offline usage.
@@ -132,7 +134,7 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp
132134

133135
if (downloadFailed && this.appProvider.isOnline()) {
134136
// We could load the main file but the download failed. Show error message.
135-
this.domUtils.showErrorModal('core.errordownloadingsomefiles', true);
137+
this.showErrorDownloadingSomeFiles(downloadFailError);
136138
}
137139
}));
138140

src/addon/mod/resource/components/index/index.ts

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import { Component, Injector } from '@angular/core';
1616
import { CoreAppProvider } from '@providers/app';
17+
import { CoreFilepoolProvider } from '@providers/filepool';
1718
import { CoreSitesProvider } from '@providers/sites';
1819
import { CoreUtilsProvider } from '@providers/utils/utils';
1920
import { CoreCourseProvider } from '@core/course/providers/course';
@@ -38,10 +39,15 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
3839
contentText: string;
3940
displayDescription = true;
4041

41-
constructor(injector: Injector, private resourceProvider: AddonModResourceProvider, private courseProvider: CoreCourseProvider,
42-
private appProvider: CoreAppProvider, private prefetchHandler: AddonModResourcePrefetchHandler,
43-
private resourceHelper: AddonModResourceHelperProvider, private sitesProvider: CoreSitesProvider,
44-
private utils: CoreUtilsProvider) {
42+
constructor(injector: Injector,
43+
protected resourceProvider: AddonModResourceProvider,
44+
protected courseProvider: CoreCourseProvider,
45+
protected appProvider: CoreAppProvider,
46+
protected prefetchHandler: AddonModResourcePrefetchHandler,
47+
protected resourceHelper: AddonModResourceHelperProvider,
48+
protected sitesProvider: CoreSitesProvider,
49+
protected utils: CoreUtilsProvider,
50+
protected filepoolProvider: CoreFilepoolProvider) {
4551
super(injector);
4652
}
4753

@@ -104,10 +110,12 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
104110

105111
if (this.resourceHelper.isDisplayedInIframe(this.module)) {
106112
let downloadFailed = false;
113+
let downloadFailError;
107114

108-
return this.prefetchHandler.download(this.module, this.courseId).catch(() => {
115+
return this.prefetchHandler.download(this.module, this.courseId).catch((error) => {
109116
// Mark download as failed but go on since the main files could have been downloaded.
110117
downloadFailed = true;
118+
downloadFailError = error;
111119
}).then(() => {
112120
return this.resourceHelper.getIframeSrc(this.module).then((src) => {
113121
this.mode = 'iframe';
@@ -125,7 +133,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
125133

126134
if (downloadFailed && this.appProvider.isOnline()) {
127135
// We could load the main file but the download failed. Show error message.
128-
this.domUtils.showErrorModal('core.errordownloadingsomefiles', true);
136+
this.showErrorDownloadingSomeFiles(downloadFailError);
129137
}
130138
});
131139
});
@@ -147,15 +155,23 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
147155

148156
/**
149157
* Opens a file.
158+
*
159+
* @return Promise resolved when done.
150160
*/
151-
open(): void {
152-
this.prefetchHandler.isDownloadable(this.module, this.courseId).then((downloadable) => {
161+
async open(): Promise<void> {
162+
let downloadable = await this.prefetchHandler.isDownloadable(this.module, this.courseId);
163+
164+
if (downloadable) {
165+
// Check if the main file is downloadle.
166+
// This isn't done in "isDownloadable" to prevent extra WS calls in the course page.
167+
downloadable = await this.resourceHelper.isMainFileDownloadable(this.module);
168+
153169
if (downloadable) {
154-
this.resourceHelper.openModuleFile(this.module, this.courseId);
155-
} else {
156-
// The resource cannot be downloaded, open the activity in browser.
157-
return this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(this.module.url);
170+
return this.resourceHelper.openModuleFile(this.module, this.courseId);
158171
}
159-
});
172+
}
173+
174+
// The resource cannot be downloaded, open the activity in browser.
175+
return this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(this.module.url);
160176
}
161177
}

src/addon/mod/resource/providers/helper.ts

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { AddonModResourceProvider } from './resource';
2020
import { CoreSitesProvider } from '@providers/sites';
2121
import { CoreFilepoolProvider } from '@providers/filepool';
2222
import { CoreFileProvider } from '@providers/file';
23+
import { CoreFileHelperProvider } from '@providers/file-helper';
2324
import { CoreAppProvider } from '@providers/app';
2425
import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype';
2526
import { CoreTextUtilsProvider } from '@providers/utils/text';
@@ -36,11 +37,17 @@ export class AddonModResourceHelperProvider {
3637
// Display using object tag.
3738
protected DISPLAY_EMBED = 1;
3839

39-
constructor(private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider,
40-
private resourceProvider: AddonModResourceProvider, private courseHelper: CoreCourseHelperProvider,
41-
private textUtils: CoreTextUtilsProvider, private mimetypeUtils: CoreMimetypeUtilsProvider,
42-
private fileProvider: CoreFileProvider, private appProvider: CoreAppProvider,
43-
private filepoolProvider: CoreFilepoolProvider, private sitesProvider: CoreSitesProvider) {
40+
constructor(protected courseProvider: CoreCourseProvider,
41+
protected domUtils: CoreDomUtilsProvider,
42+
protected resourceProvider: AddonModResourceProvider,
43+
protected courseHelper: CoreCourseHelperProvider,
44+
protected textUtils: CoreTextUtilsProvider,
45+
protected mimetypeUtils: CoreMimetypeUtilsProvider,
46+
protected fileProvider: CoreFileProvider,
47+
protected appProvider: CoreAppProvider,
48+
protected filepoolProvider: CoreFilepoolProvider,
49+
protected sitesProvider: CoreSitesProvider,
50+
protected fileHelper: CoreFileHelperProvider) {
4451
}
4552

4653
/**
@@ -136,6 +143,23 @@ export class AddonModResourceHelperProvider {
136143
return mimetype == 'text/html';
137144
}
138145

146+
/**
147+
* Check if main file of resource is downloadable.
148+
*
149+
* @param module Module instance.
150+
* @param siteId Site ID. If not defined, current site.
151+
* @return Promise resolved with boolean: whether main file is downloadable.
152+
*/
153+
isMainFileDownloadable(module: any, siteId?: string): Promise<boolean> {
154+
siteId = siteId || this.sitesProvider.getCurrentSiteId();
155+
156+
const mainFile = module.contents[0];
157+
const fileUrl = this.fileHelper.getFileUrl(mainFile);
158+
const timemodified = this.fileHelper.getFileTimemodified(mainFile);
159+
160+
return this.filepoolProvider.isFileDownloadable(siteId, fileUrl, timemodified);
161+
}
162+
139163
/**
140164
* Check if the resource is a Nextcloud file.
141165
*

src/assets/lang/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,7 @@
16191619
"core.h5p.offlineDialogRetryButtonLabel": "Retry now",
16201620
"core.h5p.offlineDialogRetryMessage": "Retrying in :num....",
16211621
"core.h5p.offlineSuccessfulSubmit": "Successfully submitted results.",
1622+
"core.h5p.offlinedisabled": "The site doesn't allow downloading H5P packages.",
16221623
"core.h5p.originator": "Originator",
16231624
"core.h5p.pd": "Public Domain",
16241625
"core.h5p.pddl": "Public Domain Dedication and Licence",

src/components/file/file.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { CoreFileHelperProvider } from '@providers/file-helper';
2020
import { CoreSitesProvider } from '@providers/sites';
2121
import { CoreDomUtilsProvider } from '@providers/utils/dom';
2222
import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype';
23+
import { CoreUrlUtilsProvider } from '@providers/utils/url';
2324
import { CoreUtilsProvider } from '@providers/utils/utils';
2425
import { CoreTextUtilsProvider } from '@providers/utils/text';
2526
import { CoreConstants } from '@core/constants';
@@ -57,16 +58,17 @@ export class CoreFileComponent implements OnInit, OnDestroy {
5758
protected timemodified: number;
5859
protected observer;
5960

60-
constructor(private sitesProvider: CoreSitesProvider,
61-
private utils: CoreUtilsProvider,
62-
private domUtils: CoreDomUtilsProvider,
63-
private filepoolProvider: CoreFilepoolProvider,
64-
private appProvider: CoreAppProvider,
65-
private fileHelper: CoreFileHelperProvider,
66-
private mimeUtils: CoreMimetypeUtilsProvider,
67-
private eventsProvider: CoreEventsProvider,
68-
private textUtils: CoreTextUtilsProvider,
69-
private pluginFileDelegate: CorePluginFileDelegate) {
61+
constructor(protected sitesProvider: CoreSitesProvider,
62+
protected utils: CoreUtilsProvider,
63+
protected domUtils: CoreDomUtilsProvider,
64+
protected filepoolProvider: CoreFilepoolProvider,
65+
protected appProvider: CoreAppProvider,
66+
protected fileHelper: CoreFileHelperProvider,
67+
protected mimeUtils: CoreMimetypeUtilsProvider,
68+
protected eventsProvider: CoreEventsProvider,
69+
protected textUtils: CoreTextUtilsProvider,
70+
protected pluginFileDelegate: CorePluginFileDelegate,
71+
protected urlUtils: CoreUrlUtilsProvider) {
7072
this.onDelete = new EventEmitter();
7173
}
7274

@@ -104,6 +106,8 @@ export class CoreFileComponent implements OnInit, OnDestroy {
104106
this.observer = this.eventsProvider.on(eventName, () => {
105107
this.calculateState();
106108
});
109+
}).catch(() => {
110+
// File not downloadable.
107111
});
108112
}
109113
}
@@ -152,14 +156,14 @@ export class CoreFileComponent implements OnInit, OnDestroy {
152156
return;
153157
}
154158

155-
if (!this.canDownload) {
159+
if (!this.canDownload || !this.state || this.state == CoreConstants.NOT_DOWNLOADABLE) {
156160
// File cannot be downloaded, just open it.
157161
if (this.file.toURL) {
158162
// Local file.
159163
this.utils.openFile(this.file.toURL());
160164
} else if (this.fileUrl) {
161165
if (this.fileUrl.indexOf('http') === 0) {
162-
this.utils.openOnlineFile(this.fileUrl);
166+
this.utils.openOnlineFile(this.urlUtils.unfixPluginfileURL(this.fileUrl));
163167
} else {
164168
this.utils.openFile(this.fileUrl);
165169
}

src/core/course/classes/main-resource-component.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { NavController } from 'ionic-angular';
1717
import { TranslateService } from '@ngx-translate/core';
1818
import { CoreLoggerProvider } from '@providers/logger';
1919
import { CoreDomUtilsProvider } from '@providers/utils/dom';
20-
import { CoreTextUtilsProvider } from '@providers/utils/text';
20+
import { CoreTextUtilsProvider, CoreTextErrorObject } from '@providers/utils/text';
2121
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
2222
import { CoreCourseModuleMainComponent, CoreCourseModuleDelegate } from '@core/course/providers/module-delegate';
2323
import { CoreCourseSectionPage } from '@core/course/pages/section/section.ts';
@@ -265,6 +265,20 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
265265
this.courseHelper.confirmAndRemoveFiles(this.module, this.courseId);
266266
}
267267

268+
/**
269+
* Show an error occurred while downloading files.
270+
*
271+
* @param error The specific error.
272+
*/
273+
protected showErrorDownloadingSomeFiles(error: string | CoreTextErrorObject): void {
274+
const errorMessage = this.textUtils.buildSeveralParagraphsMessage([
275+
this.translate.instant('core.errordownloadingsomefiles'),
276+
error,
277+
]);
278+
279+
this.domUtils.showErrorModal(errorMessage);
280+
}
281+
268282
/**
269283
* Component being destroyed.
270284
*/

src/core/courses/providers/course-link-handler.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,9 @@ export class CoreCoursesCourseLinkHandler extends CoreContentLinksHandlerBase {
178178
error = this.translate.instant('core.courses.notenroled');
179179
}
180180

181-
const body = this.translate.instant('core.twoparagraphs',
182-
{ p1: error, p2: this.translate.instant('core.confirmopeninbrowser') });
181+
const body = this.textUtils.buildSeveralParagraphsMessage(
182+
[error, this.translate.instant('core.confirmopeninbrowser')]);
183+
183184
this.domUtils.showConfirm(body).then(() => {
184185
this.sitesProvider.getCurrentSite().openInBrowserWithAutoLogin(url);
185186
}).catch(() => {

0 commit comments

Comments
 (0)