commit
df815e2191
|
@ -1373,6 +1373,8 @@
|
||||||
"core.cannotconnecttrouble": "local_moodlemobileapp",
|
"core.cannotconnecttrouble": "local_moodlemobileapp",
|
||||||
"core.cannotconnectverify": "local_moodlemobileapp",
|
"core.cannotconnectverify": "local_moodlemobileapp",
|
||||||
"core.cannotdownloadfiles": "local_moodlemobileapp",
|
"core.cannotdownloadfiles": "local_moodlemobileapp",
|
||||||
|
"core.cannotopeninapp": "local_moodlemobileapp",
|
||||||
|
"core.cannotopeninappdownload": "local_moodlemobileapp",
|
||||||
"core.captureaudio": "local_moodlemobileapp",
|
"core.captureaudio": "local_moodlemobileapp",
|
||||||
"core.capturedimage": "local_moodlemobileapp",
|
"core.capturedimage": "local_moodlemobileapp",
|
||||||
"core.captureimage": "local_moodlemobileapp",
|
"core.captureimage": "local_moodlemobileapp",
|
||||||
|
@ -1525,6 +1527,7 @@
|
||||||
"core.done": "survey",
|
"core.done": "survey",
|
||||||
"core.download": "moodle",
|
"core.download": "moodle",
|
||||||
"core.downloaded": "local_moodlemobileapp",
|
"core.downloaded": "local_moodlemobileapp",
|
||||||
|
"core.downloadfile": "moodle",
|
||||||
"core.downloading": "local_moodlemobileapp",
|
"core.downloading": "local_moodlemobileapp",
|
||||||
"core.edit": "moodle",
|
"core.edit": "moodle",
|
||||||
"core.editor.autosavesucceeded": "editor_atto",
|
"core.editor.autosavesucceeded": "editor_atto",
|
||||||
|
@ -1916,6 +1919,7 @@
|
||||||
"core.offline": "message",
|
"core.offline": "message",
|
||||||
"core.ok": "moodle",
|
"core.ok": "moodle",
|
||||||
"core.online": "message",
|
"core.online": "message",
|
||||||
|
"core.openfile": "local_moodlemobileapp",
|
||||||
"core.openfullimage": "local_moodlemobileapp",
|
"core.openfullimage": "local_moodlemobileapp",
|
||||||
"core.openinbrowser": "local_moodlemobileapp",
|
"core.openinbrowser": "local_moodlemobileapp",
|
||||||
"core.openmodinbrowser": "local_moodlemobileapp",
|
"core.openmodinbrowser": "local_moodlemobileapp",
|
||||||
|
|
|
@ -873,6 +873,10 @@ ion-app.app-root {
|
||||||
height: 100% !important;
|
height: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.core-modal-force-on-top {
|
||||||
|
z-index: 100000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
@media only screen and (min-height: 400px) and (min-width: 300px) {
|
@media only screen and (min-height: 400px) and (min-width: 300px) {
|
||||||
.core-modal-lateral {
|
.core-modal-lateral {
|
||||||
@include core-split-area-end();
|
@include core-split-area-end();
|
||||||
|
|
|
@ -1374,6 +1374,8 @@
|
||||||
"core.cannotconnecttrouble": "We're having trouble connecting to your site.",
|
"core.cannotconnecttrouble": "We're having trouble connecting to your site.",
|
||||||
"core.cannotconnectverify": "<strong>Please check the address is correct.</strong>",
|
"core.cannotconnectverify": "<strong>Please check the address is correct.</strong>",
|
||||||
"core.cannotdownloadfiles": "File downloading is disabled. Please contact your site administrator.",
|
"core.cannotdownloadfiles": "File downloading is disabled. Please contact your site administrator.",
|
||||||
|
"core.cannotopeninapp": "This file may not work as expected on this device. Would you like to open it anyway?",
|
||||||
|
"core.cannotopeninappdownload": "This file may not work as expected on this device. Would you like to download it anyway?",
|
||||||
"core.captureaudio": "Record audio",
|
"core.captureaudio": "Record audio",
|
||||||
"core.capturedimage": "Taken picture.",
|
"core.capturedimage": "Taken picture.",
|
||||||
"core.captureimage": "Take picture",
|
"core.captureimage": "Take picture",
|
||||||
|
@ -1526,6 +1528,7 @@
|
||||||
"core.done": "Done",
|
"core.done": "Done",
|
||||||
"core.download": "Download",
|
"core.download": "Download",
|
||||||
"core.downloaded": "Downloaded",
|
"core.downloaded": "Downloaded",
|
||||||
|
"core.downloadfile": "Download file",
|
||||||
"core.downloading": "Downloading",
|
"core.downloading": "Downloading",
|
||||||
"core.edit": "Edit",
|
"core.edit": "Edit",
|
||||||
"core.editor.autosavesucceeded": "Draft saved.",
|
"core.editor.autosavesucceeded": "Draft saved.",
|
||||||
|
@ -1917,6 +1920,7 @@
|
||||||
"core.offline": "Offline",
|
"core.offline": "Offline",
|
||||||
"core.ok": "OK",
|
"core.ok": "OK",
|
||||||
"core.online": "Online",
|
"core.online": "Online",
|
||||||
|
"core.openfile": "Open file",
|
||||||
"core.openfullimage": "Click here to display the full size image",
|
"core.openfullimage": "Click here to display the full size image",
|
||||||
"core.openinbrowser": "Open in browser",
|
"core.openinbrowser": "Open in browser",
|
||||||
"core.openmodinbrowser": "Open {{$a}} in browser",
|
"core.openmodinbrowser": "Open {{$a}} in browser",
|
||||||
|
|
|
@ -148,7 +148,7 @@ export class CoreFileComponent implements OnInit, OnDestroy {
|
||||||
* @param e Click event.
|
* @param e Click event.
|
||||||
* @param openAfterDownload Whether the file should be opened after download.
|
* @param openAfterDownload Whether the file should be opened after download.
|
||||||
*/
|
*/
|
||||||
download(e?: Event, openAfterDownload: boolean = false): void {
|
async download(e?: Event, openAfterDownload: boolean = false): Promise<void> {
|
||||||
e && e.preventDefault();
|
e && e.preventDefault();
|
||||||
e && e.stopPropagation();
|
e && e.stopPropagation();
|
||||||
|
|
||||||
|
@ -181,32 +181,45 @@ export class CoreFileComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
if (openAfterDownload) {
|
if (openAfterDownload) {
|
||||||
// File needs to be opened now.
|
// File needs to be opened now.
|
||||||
this.openFile().catch((error) => {
|
try {
|
||||||
|
await this.openFile();
|
||||||
|
} catch (error) {
|
||||||
this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
||||||
});
|
}
|
||||||
} else {
|
} else {
|
||||||
// File doesn't need to be opened (it's a prefetch). Show confirm modal if file size is defined and it's big.
|
// File doesn't need to be opened (it's a prefetch).
|
||||||
this.pluginFileDelegate.getFileSize({fileurl: this.fileUrl, filesize: this.fileSize}, this.siteId).then((size) => {
|
if (!this.fileHelper.isOpenableInApp(this.file)) {
|
||||||
|
try {
|
||||||
|
await this.fileHelper.showConfirmOpenUnsupportedFile(true);
|
||||||
|
} catch (error) {
|
||||||
|
return; // Cancelled, stop.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const promise = size ? this.domUtils.confirmDownloadSize({ size: size, total: true }) : Promise.resolve();
|
try {
|
||||||
|
// Show confirm modal if file size is defined and it's big.
|
||||||
|
const size = await this.pluginFileDelegate.getFileSize({fileurl: this.fileUrl, filesize: this.fileSize},
|
||||||
|
this.siteId);
|
||||||
|
|
||||||
return promise.then(() => {
|
if (size) {
|
||||||
// User confirmed, add the file to queue.
|
await this.domUtils.confirmDownloadSize({ size: size, total: true });
|
||||||
return this.filepoolProvider.invalidateFileByUrl(this.siteId, this.fileUrl).finally(() => {
|
}
|
||||||
this.isDownloading = true;
|
|
||||||
|
|
||||||
this.filepoolProvider.addToQueueByUrl(this.siteId, this.fileUrl, this.component,
|
// User confirmed, add the file to queue.
|
||||||
this.componentId, this.timemodified, undefined, undefined, 0, this.file).catch((error) => {
|
await this.utils.ignoreErrors(this.filepoolProvider.invalidateFileByUrl(this.siteId, this.fileUrl));
|
||||||
this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
|
||||||
this.calculateState();
|
this.isDownloading = true;
|
||||||
});
|
|
||||||
});
|
try {
|
||||||
}).catch(() => {
|
await this.filepoolProvider.addToQueueByUrl(this.siteId, this.fileUrl, this.component,
|
||||||
// User cancelled.
|
this.componentId, this.timemodified, undefined, undefined, 0, this.file);
|
||||||
});
|
} catch (error) {
|
||||||
}).catch((error) => {
|
this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
||||||
|
this.calculateState();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import { Component, Input, Output, OnInit, EventEmitter, ViewChild, ElementRef } from '@angular/core';
|
import { Component, Input, Output, OnInit, EventEmitter, ViewChild, ElementRef } from '@angular/core';
|
||||||
import { CoreEventsProvider } from '@providers/events';
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
import { CoreFileProvider } from '@providers/file';
|
import { CoreFileProvider } from '@providers/file';
|
||||||
|
import { CoreFileHelper } from '@providers/file-helper';
|
||||||
import { CoreSitesProvider } from '@providers/sites';
|
import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype';
|
import { CoreMimetypeUtilsProvider } from '@providers/utils/mimetype';
|
||||||
|
@ -103,7 +104,7 @@ export class CoreLocalFileComponent implements OnInit {
|
||||||
*
|
*
|
||||||
* @param e Click event.
|
* @param e Click event.
|
||||||
*/
|
*/
|
||||||
fileClicked(e: Event): void {
|
async fileClicked(e: Event): Promise<void> {
|
||||||
if (this.editMode) {
|
if (this.editMode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +115,14 @@ export class CoreLocalFileComponent implements OnInit {
|
||||||
if (this.utils.isTrueOrOne(this.overrideClick) && this.onClick.observers.length) {
|
if (this.utils.isTrueOrOne(this.overrideClick) && this.onClick.observers.length) {
|
||||||
this.onClick.emit();
|
this.onClick.emit();
|
||||||
} else {
|
} else {
|
||||||
|
if (!CoreFileHelper.instance.isOpenableInApp(this.file)) {
|
||||||
|
try {
|
||||||
|
await CoreFileHelper.instance.showConfirmOpenUnsupportedFile();
|
||||||
|
} catch (error) {
|
||||||
|
return; // Cancelled, stop.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.utils.openFile(this.file.toURL());
|
this.utils.openFile(this.file.toURL());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -585,6 +585,10 @@ export class CoreCourseHelperProvider {
|
||||||
return Promise.reject(this.utils.createFakeWSError('core.filenotfound', true));
|
return Promise.reject(this.utils.createFakeWSError('core.filenotfound', true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.fileHelper.isOpenableInApp(module.contents[0])) {
|
||||||
|
return this.fileHelper.showConfirmOpenUnsupportedFile();
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
return this.sitesProvider.getSite(siteId);
|
return this.sitesProvider.getSite(siteId);
|
||||||
}).then((site) => {
|
}).then((site) => {
|
||||||
const mainFile = files[0],
|
const mainFile = files[0],
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
import { Directive, Input, OnInit, ElementRef, Optional } from '@angular/core';
|
import { Directive, Input, OnInit, ElementRef, Optional } from '@angular/core';
|
||||||
import { NavController, Content } from 'ionic-angular';
|
import { NavController, Content } from 'ionic-angular';
|
||||||
|
import { CoreFileHelper } from '@providers/file-helper';
|
||||||
import { CoreSitesProvider } from '@providers/sites';
|
import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
import { CoreUrlUtilsProvider } from '@providers/utils/url';
|
import { CoreUrlUtilsProvider } from '@providers/utils/url';
|
||||||
|
@ -21,7 +22,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
|
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
|
||||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||||
import { CoreCustomURLSchemesProvider, CoreCustomURLSchemesHandleError } from '@providers/urlschemes';
|
import { CoreCustomURLSchemesProvider } from '@providers/urlschemes';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directive to open a link in external browser.
|
* Directive to open a link in external browser.
|
||||||
|
@ -94,14 +95,27 @@ export class CoreLinkDirective implements OnInit {
|
||||||
* Convenience function to correctly navigate, open file or url in the browser.
|
* Convenience function to correctly navigate, open file or url in the browser.
|
||||||
*
|
*
|
||||||
* @param href HREF to be opened.
|
* @param href HREF to be opened.
|
||||||
|
* @return Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
protected navigate(href: string): void {
|
protected async navigate(href: string): Promise<void> {
|
||||||
|
|
||||||
if (this.urlUtils.isLocalFileUrl(href)) {
|
if (this.urlUtils.isLocalFileUrl(href)) {
|
||||||
// We have a local file.
|
// We have a local file.
|
||||||
this.utils.openFile(href).catch((error) => {
|
const filename = href.substr(href.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
|
if (!CoreFileHelper.instance.isOpenableInApp({ filename })) {
|
||||||
|
try {
|
||||||
|
await CoreFileHelper.instance.showConfirmOpenUnsupportedFile();
|
||||||
|
} catch (error) {
|
||||||
|
return; // Cancelled, stop.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.utils.openFile(href);
|
||||||
|
} catch (error) {
|
||||||
this.domUtils.showErrorModal(error);
|
this.domUtils.showErrorModal(error);
|
||||||
});
|
}
|
||||||
} else if (href.charAt(0) == '#') {
|
} else if (href.charAt(0) == '#') {
|
||||||
href = href.substr(1);
|
href = href.substr(1);
|
||||||
// In site links
|
// In site links
|
||||||
|
@ -113,9 +127,11 @@ export class CoreLinkDirective implements OnInit {
|
||||||
this.domUtils.scrollToElementBySelector(this.content, '#' + href + ', [name=\'' + href + '\']');
|
this.domUtils.scrollToElementBySelector(this.content, '#' + href + ', [name=\'' + href + '\']');
|
||||||
}
|
}
|
||||||
} else if (this.urlSchemesProvider.isCustomURL(href)) {
|
} else if (this.urlSchemesProvider.isCustomURL(href)) {
|
||||||
this.urlSchemesProvider.handleCustomURL(href).catch((error: CoreCustomURLSchemesHandleError) => {
|
try {
|
||||||
|
await this.urlSchemesProvider.handleCustomURL(href);
|
||||||
|
} catch (error) {
|
||||||
this.urlSchemesProvider.treatHandleCustomURLError(error);
|
this.urlSchemesProvider.treatHandleCustomURLError(error);
|
||||||
});
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// It's an external link, we will open with browser. Check if we need to auto-login.
|
// It's an external link, we will open with browser. Check if we need to auto-login.
|
||||||
|
@ -139,9 +155,9 @@ export class CoreLinkDirective implements OnInit {
|
||||||
|
|
||||||
if (this.autoLogin == 'yes') {
|
if (this.autoLogin == 'yes') {
|
||||||
if (this.inApp) {
|
if (this.inApp) {
|
||||||
this.sitesProvider.getCurrentSite().openInAppWithAutoLogin(href);
|
await this.sitesProvider.getCurrentSite().openInAppWithAutoLogin(href);
|
||||||
} else {
|
} else {
|
||||||
this.sitesProvider.getCurrentSite().openInBrowserWithAutoLogin(href);
|
await this.sitesProvider.getCurrentSite().openInBrowserWithAutoLogin(href);
|
||||||
}
|
}
|
||||||
} else if (this.autoLogin == 'no') {
|
} else if (this.autoLogin == 'no') {
|
||||||
if (this.inApp) {
|
if (this.inApp) {
|
||||||
|
@ -151,9 +167,9 @@ export class CoreLinkDirective implements OnInit {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.inApp) {
|
if (this.inApp) {
|
||||||
this.sitesProvider.getCurrentSite().openInAppWithAutoLoginIfSameSite(href);
|
await this.sitesProvider.getCurrentSite().openInAppWithAutoLoginIfSameSite(href);
|
||||||
} else {
|
} else {
|
||||||
this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(href);
|
await this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(href);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
"cannotconnecttrouble": "We're having trouble connecting to your site.",
|
"cannotconnecttrouble": "We're having trouble connecting to your site.",
|
||||||
"cannotconnectverify": "<strong>Please check the address is correct.</strong>",
|
"cannotconnectverify": "<strong>Please check the address is correct.</strong>",
|
||||||
"cannotdownloadfiles": "File downloading is disabled. Please contact your site administrator.",
|
"cannotdownloadfiles": "File downloading is disabled. Please contact your site administrator.",
|
||||||
|
"cannotopeninapp": "This file may not work as expected on this device. Would you like to open it anyway?",
|
||||||
|
"cannotopeninappdownload": "This file may not work as expected on this device. Would you like to download it anyway?",
|
||||||
"captureaudio": "Record audio",
|
"captureaudio": "Record audio",
|
||||||
"capturedimage": "Taken picture.",
|
"capturedimage": "Taken picture.",
|
||||||
"captureimage": "Take picture",
|
"captureimage": "Take picture",
|
||||||
|
@ -82,6 +84,7 @@
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"downloaded": "Downloaded",
|
"downloaded": "Downloaded",
|
||||||
|
"downloadfile": "Download file",
|
||||||
"downloading": "Downloading",
|
"downloading": "Downloading",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"emptysplit": "This page will appear blank if the left panel is empty or is loading.",
|
"emptysplit": "This page will appear blank if the left panel is empty or is loading.",
|
||||||
|
@ -200,6 +203,7 @@
|
||||||
"offline": "Offline",
|
"offline": "Offline",
|
||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"online": "Online",
|
"online": "Online",
|
||||||
|
"openfile": "Open file",
|
||||||
"openfullimage": "Click here to display the full size image",
|
"openfullimage": "Click here to display the full size image",
|
||||||
"openinbrowser": "Open in browser",
|
"openinbrowser": "Open in browser",
|
||||||
"openmodinbrowser": "Open {{$a}} in browser",
|
"openmodinbrowser": "Open {{$a}} in browser",
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { CoreAppProvider } from './app';
|
import { CoreAppProvider } from './app';
|
||||||
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
import { CoreFileProvider } from './file';
|
import { CoreFileProvider } from './file';
|
||||||
import { CoreFilepoolProvider } from './filepool';
|
import { CoreFilepoolProvider } from './filepool';
|
||||||
import { CoreSitesProvider } from './sites';
|
import { CoreSitesProvider } from './sites';
|
||||||
|
@ -30,7 +31,8 @@ import { makeSingleton } from '@singletons/core.singletons';
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CoreFileHelperProvider {
|
export class CoreFileHelperProvider {
|
||||||
|
|
||||||
constructor(protected fileProvider: CoreFileProvider,
|
constructor(protected domUtils: CoreDomUtilsProvider,
|
||||||
|
protected fileProvider: CoreFileProvider,
|
||||||
protected filepoolProvider: CoreFilepoolProvider,
|
protected filepoolProvider: CoreFilepoolProvider,
|
||||||
protected sitesProvider: CoreSitesProvider,
|
protected sitesProvider: CoreSitesProvider,
|
||||||
protected appProvider: CoreAppProvider,
|
protected appProvider: CoreAppProvider,
|
||||||
|
@ -49,63 +51,58 @@ export class CoreFileHelperProvider {
|
||||||
* @param siteId The site ID. If not defined, current site.
|
* @param siteId The site ID. If not defined, current site.
|
||||||
* @return Resolved on success.
|
* @return Resolved on success.
|
||||||
*/
|
*/
|
||||||
downloadAndOpenFile(file: any, component: string, componentId: string | number, state?: string,
|
async downloadAndOpenFile(file: any, component: string, componentId: string | number, state?: string,
|
||||||
onProgress?: (event: any) => any, siteId?: string): Promise<any> {
|
onProgress?: (event: any) => any, siteId?: string): Promise<void> {
|
||||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
const fileUrl = this.getFileUrl(file),
|
const fileUrl = this.getFileUrl(file);
|
||||||
timemodified = this.getFileTimemodified(file);
|
const timemodified = this.getFileTimemodified(file);
|
||||||
|
|
||||||
|
if (!this.isOpenableInApp(file)) {
|
||||||
|
await this.showConfirmOpenUnsupportedFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
let url = await this.downloadFileIfNeeded(file, fileUrl, component, componentId, timemodified, state, onProgress, siteId);
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CoreUrlUtils.instance.isLocalFileUrl(url)) {
|
||||||
|
/* In iOS, if we use the same URL in embedded browser and background download then the download only
|
||||||
|
downloads a few bytes (cached ones). Add a hash to the URL so both URLs are different. */
|
||||||
|
url = url + '#moodlemobile-embedded';
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.utils.openOnlineFile(url);
|
||||||
|
|
||||||
return this.downloadFileIfNeeded(file, fileUrl, component, componentId, timemodified, state, onProgress, siteId)
|
|
||||||
.then((url) => {
|
|
||||||
if (!url) {
|
|
||||||
return;
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
// Error opening the file, some apps don't allow opening online files.
|
||||||
|
if (!this.fileProvider.isAvailable()) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the state.
|
||||||
|
if (!state) {
|
||||||
|
state = await this.filepoolProvider.getFileStateByUrl(siteId, fileUrl, timemodified);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == CoreConstants.DOWNLOADING) {
|
||||||
|
throw new Error(this.translate.instant('core.erroropenfiledownloading'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state === CoreConstants.NOT_DOWNLOADED) {
|
||||||
|
// File is not downloaded, download and then return the local URL.
|
||||||
|
url = await this.downloadFile(fileUrl, component, componentId, timemodified, onProgress, file, siteId);
|
||||||
|
} else {
|
||||||
|
// File is outdated and can't be opened in online, return the local URL.
|
||||||
|
url = await this.filepoolProvider.getInternalUrlByUrl(siteId, fileUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!CoreUrlUtils.instance.isLocalFileUrl(url)) {
|
return this.utils.openFile(url);
|
||||||
/* In iOS, if we use the same URL in embedded browser and background download then the download only
|
|
||||||
downloads a few bytes (cached ones). Add a hash to the URL so both URLs are different. */
|
|
||||||
url = url + '#moodlemobile-embedded';
|
|
||||||
|
|
||||||
return this.utils.openOnlineFile(url).catch((error) => {
|
|
||||||
// Error opening the file, some apps don't allow opening online files.
|
|
||||||
if (!this.fileProvider.isAvailable()) {
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
let promise;
|
|
||||||
|
|
||||||
// Get the state.
|
|
||||||
if (state) {
|
|
||||||
promise = Promise.resolve(state);
|
|
||||||
} else {
|
|
||||||
promise = this.filepoolProvider.getFileStateByUrl(siteId, fileUrl, timemodified);
|
|
||||||
}
|
|
||||||
|
|
||||||
return promise.then((state) => {
|
|
||||||
if (state == CoreConstants.DOWNLOADING) {
|
|
||||||
return Promise.reject(this.translate.instant('core.erroropenfiledownloading'));
|
|
||||||
}
|
|
||||||
|
|
||||||
let promise;
|
|
||||||
|
|
||||||
if (state === CoreConstants.NOT_DOWNLOADED) {
|
|
||||||
// File is not downloaded, download and then return the local URL.
|
|
||||||
promise = this.downloadFile(fileUrl, component, componentId, timemodified, onProgress, file, siteId);
|
|
||||||
} else {
|
|
||||||
// File is outdated and can't be opened in online, return the local URL.
|
|
||||||
promise = this.filepoolProvider.getInternalUrlByUrl(siteId, fileUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
return promise.then((url) => {
|
|
||||||
return this.utils.openFile(url);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return this.utils.openFile(url);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -339,6 +336,52 @@ export class CoreFileHelperProvider {
|
||||||
|
|
||||||
throw new Error('Couldn\'t determine file size: ' + file.fileurl);
|
throw new Error('Couldn\'t determine file size: ' + file.fileurl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the file openable in app.
|
||||||
|
*
|
||||||
|
* @param file The file to check.
|
||||||
|
* @return bool.
|
||||||
|
*/
|
||||||
|
isOpenableInApp(file: {filename?: string, name?: string}): boolean {
|
||||||
|
const re = /(?:\.([^.]+))?$/;
|
||||||
|
|
||||||
|
const ext = re.exec(file.filename || file.name)[1];
|
||||||
|
|
||||||
|
return !this.isFileTypeExcludedInApp(ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a confirm asking the user if we wants to open the file.
|
||||||
|
*
|
||||||
|
* @param onlyDownload Whether the user is only downloading the file, not opening it.
|
||||||
|
* @return Promise resolved if confirmed, rejected otherwise.
|
||||||
|
*/
|
||||||
|
showConfirmOpenUnsupportedFile(onlyDownload?: boolean): Promise<void> {
|
||||||
|
const message = this.translate.instant('core.cannotopeninapp' + (onlyDownload ? 'download' : ''));
|
||||||
|
const okButton = this.translate.instant(onlyDownload ? 'core.downloadfile' : 'core.openfile');
|
||||||
|
|
||||||
|
return this.domUtils.showConfirm(message, undefined, okButton, undefined, { cssClass: 'core-modal-force-on-top' });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the file type excluded to open in app.
|
||||||
|
*
|
||||||
|
* @param file The file to check.
|
||||||
|
* @return bool.
|
||||||
|
*/
|
||||||
|
isFileTypeExcludedInApp(fileType: string): boolean {
|
||||||
|
const currentSite = this.sitesProvider.getCurrentSite();
|
||||||
|
const fileTypeExcludeList = currentSite && currentSite.getStoredConfig('tool_mobile_filetypeexclusionlist');
|
||||||
|
|
||||||
|
if (!fileTypeExcludeList) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const regEx = new RegExp('(,|^)' + fileType + '(,|$)', 'g');
|
||||||
|
|
||||||
|
return !!fileTypeExcludeList.match(regEx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CoreFileHelper extends makeSingleton(CoreFileHelperProvider) {}
|
export class CoreFileHelper extends makeSingleton(CoreFileHelperProvider) {}
|
||||||
|
|
|
@ -1287,7 +1287,7 @@ export class CoreDomUtilsProvider {
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!title) {
|
if (!title) {
|
||||||
options.cssClass = 'core-nohead';
|
options.cssClass = (options.cssClass || '') + ' core-nohead';
|
||||||
}
|
}
|
||||||
|
|
||||||
this.showAlertWithOptions(options, 0);
|
this.showAlertWithOptions(options, 0);
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { TranslateService } from '@ngx-translate/core';
|
||||||
import { Network } from '@ionic-native/network';
|
import { Network } from '@ionic-native/network';
|
||||||
import { CoreApp, CoreAppProvider } from '../app';
|
import { CoreApp, CoreAppProvider } from '../app';
|
||||||
import { CoreFileProvider } from '../file';
|
import { CoreFileProvider } from '../file';
|
||||||
|
import { CoreFileHelper } from '../file-helper';
|
||||||
import { CoreLoggerProvider } from '../logger';
|
import { CoreLoggerProvider } from '../logger';
|
||||||
import { CoreSitesProvider } from '../sites';
|
import { CoreSitesProvider } from '../sites';
|
||||||
import { CoreDomUtilsProvider } from './dom';
|
import { CoreDomUtilsProvider } from './dom';
|
||||||
|
@ -390,6 +391,16 @@ export class CoreIframeUtilsProvider {
|
||||||
}
|
}
|
||||||
} else if (this.urlUtils.isLocalFileUrl(url)) {
|
} else if (this.urlUtils.isLocalFileUrl(url)) {
|
||||||
// It's a local file.
|
// It's a local file.
|
||||||
|
const filename = url.substr(url.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
|
if (!CoreFileHelper.instance.isOpenableInApp({ filename })) {
|
||||||
|
try {
|
||||||
|
await CoreFileHelper.instance.showConfirmOpenUnsupportedFile();
|
||||||
|
} catch (error) {
|
||||||
|
return; // Cancelled, stop.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.utils.openFile(url);
|
await this.utils.openFile(url);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -409,9 +420,10 @@ export class CoreIframeUtilsProvider {
|
||||||
* @param link Data of the link clicked.
|
* @param link Data of the link clicked.
|
||||||
* @param element Frame element.
|
* @param element Frame element.
|
||||||
* @param event Click event.
|
* @param event Click event.
|
||||||
|
* @return Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
protected linkClicked(link: {href: string, target?: string}, element?: HTMLFrameElement | HTMLObjectElement, event?: Event)
|
protected async linkClicked(link: {href: string, target?: string}, element?: HTMLFrameElement | HTMLObjectElement,
|
||||||
: void {
|
event?: Event): Promise<void> {
|
||||||
if (event && event.defaultPrevented) {
|
if (event && event.defaultPrevented) {
|
||||||
// Event already prevented by some other code.
|
// Event already prevented by some other code.
|
||||||
return;
|
return;
|
||||||
|
@ -445,14 +457,27 @@ export class CoreIframeUtilsProvider {
|
||||||
if (!this.sitesProvider.isLoggedIn()) {
|
if (!this.sitesProvider.isLoggedIn()) {
|
||||||
this.utils.openInBrowser(link.href);
|
this.utils.openInBrowser(link.href);
|
||||||
} else {
|
} else {
|
||||||
this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(link.href);
|
await this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(link.href);
|
||||||
}
|
}
|
||||||
} else if (link.target == '_parent' || link.target == '_top' || link.target == '_blank') {
|
} else if (link.target == '_parent' || link.target == '_top' || link.target == '_blank') {
|
||||||
// Opening links with _parent, _top or _blank can break the app. We'll open it in InAppBrowser.
|
// Opening links with _parent, _top or _blank can break the app. We'll open it in InAppBrowser.
|
||||||
event && event.preventDefault();
|
event && event.preventDefault();
|
||||||
this.utils.openFile(link.href).catch((error) => {
|
|
||||||
|
const filename = link.href.substr(link.href.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
|
if (!CoreFileHelper.instance.isOpenableInApp({ filename })) {
|
||||||
|
try {
|
||||||
|
await CoreFileHelper.instance.showConfirmOpenUnsupportedFile();
|
||||||
|
} catch (error) {
|
||||||
|
return; // Cancelled, stop.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.utils.openFile(link.href);
|
||||||
|
} catch (error) {
|
||||||
this.domUtils.showErrorModal(error);
|
this.domUtils.showErrorModal(error);
|
||||||
});
|
}
|
||||||
} else if (CoreApp.instance.isIOS() && (!link.target || link.target == '_self') && element) {
|
} else if (CoreApp.instance.isIOS() && (!link.target || link.target == '_self') && element) {
|
||||||
// In cordova ios 4.1.0 links inside iframes stopped working. We'll manually treat them.
|
// In cordova ios 4.1.0 links inside iframes stopped working. We'll manually treat them.
|
||||||
event && event.preventDefault();
|
event && event.preventDefault();
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { NavController } from 'ionic-angular';
|
import { NavController } from 'ionic-angular';
|
||||||
|
import { CoreFileHelper } from '@providers/file-helper';
|
||||||
import { CoreSites } from '@providers/sites';
|
import { CoreSites } from '@providers/sites';
|
||||||
import { CoreUrlUtils } from '@providers/utils/url';
|
import { CoreUrlUtils } from '@providers/utils/url';
|
||||||
import { CoreUtils } from '@providers/utils/utils';
|
import { CoreUtils } from '@providers/utils/utils';
|
||||||
|
@ -43,6 +44,16 @@ export class CoreWindow {
|
||||||
*/
|
*/
|
||||||
static async open(url: string, name?: string, options?: CoreWindowOpenOptions): Promise<void> {
|
static async open(url: string, name?: string, options?: CoreWindowOpenOptions): Promise<void> {
|
||||||
if (CoreUrlUtils.instance.isLocalFileUrl(url)) {
|
if (CoreUrlUtils.instance.isLocalFileUrl(url)) {
|
||||||
|
const filename = url.substr(url.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
|
if (!CoreFileHelper.instance.isOpenableInApp({ filename })) {
|
||||||
|
try {
|
||||||
|
await CoreFileHelper.instance.showConfirmOpenUnsupportedFile();
|
||||||
|
} catch (error) {
|
||||||
|
return; // Cancelled, stop.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await CoreUtils.instance.openFile(url);
|
await CoreUtils.instance.openFile(url);
|
||||||
} else {
|
} else {
|
||||||
let treated: boolean;
|
let treated: boolean;
|
||||||
|
|
Loading…
Reference in New Issue