forked from CIT/Vmeda.Online
		
	MOBILE-2333 core: Implement download-file directive
This commit is contained in:
		
							parent
							
								
									dc88b83bbb
								
							
						
					
					
						commit
						adbee2991c
					
				@ -50,6 +50,7 @@ import { CoreUpdateManagerProvider } from '@providers/update-manager';
 | 
				
			|||||||
import { CorePluginFileDelegate } from '@providers/plugin-file-delegate';
 | 
					import { CorePluginFileDelegate } from '@providers/plugin-file-delegate';
 | 
				
			||||||
import { CoreSyncProvider } from '@providers/sync';
 | 
					import { CoreSyncProvider } from '@providers/sync';
 | 
				
			||||||
import { CoreAddonManagerProvider } from '@providers/addonmanager';
 | 
					import { CoreAddonManagerProvider } from '@providers/addonmanager';
 | 
				
			||||||
 | 
					import { CoreFileHelperProvider } from '@providers/file-helper';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Core modules.
 | 
					// Core modules.
 | 
				
			||||||
import { CoreComponentsModule } from '@components/components.module';
 | 
					import { CoreComponentsModule } from '@components/components.module';
 | 
				
			||||||
@ -108,7 +109,8 @@ export const CORE_PROVIDERS: any[] = [
 | 
				
			|||||||
    CoreUpdateManagerProvider,
 | 
					    CoreUpdateManagerProvider,
 | 
				
			||||||
    CorePluginFileDelegate,
 | 
					    CorePluginFileDelegate,
 | 
				
			||||||
    CoreSyncProvider,
 | 
					    CoreSyncProvider,
 | 
				
			||||||
    CoreAddonManagerProvider
 | 
					    CoreAddonManagerProvider,
 | 
				
			||||||
 | 
					    CoreFileHelperProvider
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@NgModule({
 | 
					@NgModule({
 | 
				
			||||||
 | 
				
			|||||||
@ -13,11 +13,10 @@
 | 
				
			|||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Component, Input, Output, OnInit, OnDestroy, EventEmitter } from '@angular/core';
 | 
					import { Component, Input, Output, OnInit, OnDestroy, EventEmitter } from '@angular/core';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					 | 
				
			||||||
import { CoreAppProvider } from '@providers/app';
 | 
					import { CoreAppProvider } from '@providers/app';
 | 
				
			||||||
import { CoreEventsProvider } from '@providers/events';
 | 
					import { CoreEventsProvider } from '@providers/events';
 | 
				
			||||||
import { CoreFileProvider } from '@providers/file';
 | 
					 | 
				
			||||||
import { CoreFilepoolProvider } from '@providers/filepool';
 | 
					import { CoreFilepoolProvider } from '@providers/filepool';
 | 
				
			||||||
 | 
					import { CoreFileHelperProvider } 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';
 | 
				
			||||||
@ -36,7 +35,6 @@ export class CoreFileComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
    @Input() file: any; // The file. Must have a property 'filename' and a 'fileurl' or 'url'
 | 
					    @Input() file: any; // The file. Must have a property 'filename' and a 'fileurl' or 'url'
 | 
				
			||||||
    @Input() component?: string; // Component the file belongs to.
 | 
					    @Input() component?: string; // Component the file belongs to.
 | 
				
			||||||
    @Input() componentId?: string | number; // Component ID.
 | 
					    @Input() componentId?: string | number; // Component ID.
 | 
				
			||||||
    @Input() timemodified?: number; // If set, the value will be used to check if the file is outdated.
 | 
					 | 
				
			||||||
    @Input() canDelete?: boolean | string; // Whether file can be deleted.
 | 
					    @Input() canDelete?: boolean | string; // Whether file can be deleted.
 | 
				
			||||||
    @Input() alwaysDownload?: boolean | string; // Whether it should always display the refresh button when the file is downloaded.
 | 
					    @Input() alwaysDownload?: boolean | string; // Whether it should always display the refresh button when the file is downloaded.
 | 
				
			||||||
                                                // Use it for files that you cannot determine if they're outdated or not.
 | 
					                                                // Use it for files that you cannot determine if they're outdated or not.
 | 
				
			||||||
@ -52,12 +50,14 @@ export class CoreFileComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
    protected fileUrl: string;
 | 
					    protected fileUrl: string;
 | 
				
			||||||
    protected siteId: string;
 | 
					    protected siteId: string;
 | 
				
			||||||
    protected fileSize: number;
 | 
					    protected fileSize: number;
 | 
				
			||||||
 | 
					    protected state: string;
 | 
				
			||||||
 | 
					    protected timemodified: number;
 | 
				
			||||||
    protected observer;
 | 
					    protected observer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(private translate: TranslateService, private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider,
 | 
					    constructor(private sitesProvider: CoreSitesProvider, private utils: CoreUtilsProvider, private domUtils: CoreDomUtilsProvider,
 | 
				
			||||||
            private domUtils: CoreDomUtilsProvider, private filepoolProvider: CoreFilepoolProvider,
 | 
					            private filepoolProvider: CoreFilepoolProvider, private appProvider: CoreAppProvider,
 | 
				
			||||||
            private fileProvider: CoreFileProvider, private appProvider: CoreAppProvider,
 | 
					            private fileHelper: CoreFileHelperProvider, private mimeUtils: CoreMimetypeUtilsProvider,
 | 
				
			||||||
            private mimeUtils: CoreMimetypeUtilsProvider, private eventsProvider: CoreEventsProvider) {
 | 
					            private eventsProvider: CoreEventsProvider) {
 | 
				
			||||||
        this.onDelete = new EventEmitter();
 | 
					        this.onDelete = new EventEmitter();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -68,9 +68,9 @@ export class CoreFileComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
        this.canDelete = this.utils.isTrueOrOne(this.canDelete);
 | 
					        this.canDelete = this.utils.isTrueOrOne(this.canDelete);
 | 
				
			||||||
        this.alwaysDownload = this.utils.isTrueOrOne(this.alwaysDownload);
 | 
					        this.alwaysDownload = this.utils.isTrueOrOne(this.alwaysDownload);
 | 
				
			||||||
        this.canDownload = this.utils.isTrueOrOne(this.canDownload);
 | 
					        this.canDownload = this.utils.isTrueOrOne(this.canDownload);
 | 
				
			||||||
        this.timemodified = this.timemodified || 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.fileUrl = this.file.fileurl || this.file.url;
 | 
					        this.fileUrl = this.fileHelper.getFileUrl(this.file);
 | 
				
			||||||
 | 
					        this.timemodified = this.fileHelper.getFileTimemodified(this.file);
 | 
				
			||||||
        this.siteId = this.sitesProvider.getCurrentSiteId();
 | 
					        this.siteId = this.sitesProvider.getCurrentSiteId();
 | 
				
			||||||
        this.fileSize = this.file.filesize;
 | 
					        this.fileSize = this.file.filesize;
 | 
				
			||||||
        this.fileName = this.file.filename;
 | 
					        this.fileName = this.file.filename;
 | 
				
			||||||
@ -102,6 +102,7 @@ export class CoreFileComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
        return this.filepoolProvider.getFileStateByUrl(this.siteId, this.fileUrl, this.timemodified).then((state) => {
 | 
					        return this.filepoolProvider.getFileStateByUrl(this.siteId, this.fileUrl, this.timemodified).then((state) => {
 | 
				
			||||||
            const canDownload = this.sitesProvider.getCurrentSite().canDownloadFiles();
 | 
					            const canDownload = this.sitesProvider.getCurrentSite().canDownloadFiles();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.state = state;
 | 
				
			||||||
            this.isDownloaded = state === CoreConstants.DOWNLOADED || state === CoreConstants.OUTDATED;
 | 
					            this.isDownloaded = state === CoreConstants.DOWNLOADED || state === CoreConstants.OUTDATED;
 | 
				
			||||||
            this.isDownloading = canDownload && state === CoreConstants.DOWNLOADING;
 | 
					            this.isDownloading = canDownload && state === CoreConstants.DOWNLOADING;
 | 
				
			||||||
            this.showDownload = canDownload && (state === CoreConstants.NOT_DOWNLOADED || state === CoreConstants.OUTDATED ||
 | 
					            this.showDownload = canDownload && (state === CoreConstants.NOT_DOWNLOADED || state === CoreConstants.OUTDATED ||
 | 
				
			||||||
@ -109,123 +110,19 @@ export class CoreFileComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Download the file.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return {Promise<string>} Promise resolved when file is downloaded.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    protected downloadFile(): Promise<string> {
 | 
					 | 
				
			||||||
        if (!this.sitesProvider.getCurrentSite().canDownloadFiles()) {
 | 
					 | 
				
			||||||
            this.domUtils.showErrorModal('core.cannotdownloadfiles', true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return Promise.reject(null);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.isDownloading = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return this.filepoolProvider.downloadUrl(this.siteId, this.fileUrl, false, this.component, this.componentId,
 | 
					 | 
				
			||||||
            this.timemodified, undefined, undefined, this.file).catch(() => {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // Call calculateState to make sure we have the right state.
 | 
					 | 
				
			||||||
                return this.calculateState().then(() => {
 | 
					 | 
				
			||||||
                    if (this.isDownloaded) {
 | 
					 | 
				
			||||||
                        return this.filepoolProvider.getInternalUrlByUrl(this.siteId, this.fileUrl);
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        return Promise.reject(null);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Convenience function to open a file, downloading it if needed.
 | 
					     * Convenience function to open a file, downloading it if needed.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return {Promise<string>} Promise resolved when file is opened.
 | 
					     * @return {Promise<string>} Promise resolved when file is opened.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected openFile(): Promise<any> {
 | 
					    protected openFile(): Promise<any> {
 | 
				
			||||||
        const fixedUrl = this.sitesProvider.getCurrentSite().fixPluginfileURL(this.fileUrl);
 | 
					        return this.fileHelper.downloadAndOpenFile(this.file, this.component, this.componentId, this.state, (event) => {
 | 
				
			||||||
        let promise;
 | 
					            if (event && event.calculating) {
 | 
				
			||||||
 | 
					                // The process is calculating some data required for the download, show the spinner.
 | 
				
			||||||
        if (this.fileProvider.isAvailable()) {
 | 
					                this.isDownloading = true;
 | 
				
			||||||
            promise = Promise.resolve().then(() => {
 | 
					 | 
				
			||||||
                // The file system is available.
 | 
					 | 
				
			||||||
                const isWifi = !this.appProvider.isNetworkAccessLimited(),
 | 
					 | 
				
			||||||
                    isOnline = this.appProvider.isOnline();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (this.isDownloaded && !this.showDownload) {
 | 
					 | 
				
			||||||
                    // File is downloaded, get the local file URL.
 | 
					 | 
				
			||||||
                    return this.filepoolProvider.getUrlByUrl(this.siteId, this.fileUrl,
 | 
					 | 
				
			||||||
                        this.component, this.componentId, this.timemodified, false, false, this.file);
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    if (!isOnline && !this.isDownloaded) {
 | 
					 | 
				
			||||||
                        // Not downloaded and user is offline, reject.
 | 
					 | 
				
			||||||
                        return Promise.reject(this.translate.instant('core.networkerrormsg'));
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    const isDownloading = this.isDownloading;
 | 
					 | 
				
			||||||
                    this.isDownloading = true; // This check could take a while, show spinner.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    return this.filepoolProvider.shouldDownloadBeforeOpen(fixedUrl, this.fileSize).then(() => {
 | 
					 | 
				
			||||||
                        if (isDownloading) {
 | 
					 | 
				
			||||||
                            // It's already downloading, stop.
 | 
					 | 
				
			||||||
                            return;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        // Download and then return the local URL.
 | 
					 | 
				
			||||||
                        return this.downloadFile();
 | 
					 | 
				
			||||||
                    }, () => {
 | 
					 | 
				
			||||||
                        // Start the download if in wifi, but return the URL right away so the file is opened.
 | 
					 | 
				
			||||||
                        if (isWifi && isOnline) {
 | 
					 | 
				
			||||||
                            this.downloadFile();
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        if (isDownloading || !this.isDownloaded || isOnline) {
 | 
					 | 
				
			||||||
                            // Not downloaded or outdated and online, return the online URL.
 | 
					 | 
				
			||||||
                            return fixedUrl;
 | 
					 | 
				
			||||||
                        } else {
 | 
					 | 
				
			||||||
                            // Outdated but offline, so we return the local URL.
 | 
					 | 
				
			||||||
                            return this.filepoolProvider.getUrlByUrl(this.siteId, this.fileUrl,
 | 
					 | 
				
			||||||
                                this.component, this.componentId, this.timemodified, false, false, this.file);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            // Use the online URL.
 | 
					 | 
				
			||||||
            promise = Promise.resolve(fixedUrl);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return promise.then((url) => {
 | 
					 | 
				
			||||||
            if (!url) {
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (url.indexOf('http') === 0) {
 | 
					 | 
				
			||||||
                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);
 | 
					 | 
				
			||||||
                    } else if (this.isDownloading) {
 | 
					 | 
				
			||||||
                        return Promise.reject(this.translate.instant('core.erroropenfiledownloading'));
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    let subPromise;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if (status === CoreConstants.NOT_DOWNLOADED) {
 | 
					 | 
				
			||||||
                        // File is not downloaded, download and then return the local URL.
 | 
					 | 
				
			||||||
                        subPromise = this.downloadFile();
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        // File is outdated and can't be opened in online, return the local URL.
 | 
					 | 
				
			||||||
                        subPromise = this.filepoolProvider.getInternalUrlByUrl(this.siteId, this.fileUrl);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    return subPromise.then((url) => {
 | 
					 | 
				
			||||||
                        return this.utils.openFile(url);
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                return this.utils.openFile(url);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }).catch((error) => {
 | 
				
			||||||
 | 
					            this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import { NgModule } from '@angular/core';
 | 
					import { NgModule } from '@angular/core';
 | 
				
			||||||
import { CoreAutoFocusDirective } from './auto-focus';
 | 
					import { CoreAutoFocusDirective } from './auto-focus';
 | 
				
			||||||
 | 
					import { CoreDownloadFileDirective } from './download-file';
 | 
				
			||||||
import { CoreExternalContentDirective } from './external-content';
 | 
					import { CoreExternalContentDirective } from './external-content';
 | 
				
			||||||
import { CoreFormatTextDirective } from './format-text';
 | 
					import { CoreFormatTextDirective } from './format-text';
 | 
				
			||||||
import { CoreLinkDirective } from './link';
 | 
					import { CoreLinkDirective } from './link';
 | 
				
			||||||
@ -25,6 +26,7 @@ import { CoreLongPressDirective } from './long-press';
 | 
				
			|||||||
@NgModule({
 | 
					@NgModule({
 | 
				
			||||||
    declarations: [
 | 
					    declarations: [
 | 
				
			||||||
        CoreAutoFocusDirective,
 | 
					        CoreAutoFocusDirective,
 | 
				
			||||||
 | 
					        CoreDownloadFileDirective,
 | 
				
			||||||
        CoreExternalContentDirective,
 | 
					        CoreExternalContentDirective,
 | 
				
			||||||
        CoreFormatTextDirective,
 | 
					        CoreFormatTextDirective,
 | 
				
			||||||
        CoreKeepKeyboardDirective,
 | 
					        CoreKeepKeyboardDirective,
 | 
				
			||||||
@ -36,6 +38,7 @@ import { CoreLongPressDirective } from './long-press';
 | 
				
			|||||||
    imports: [],
 | 
					    imports: [],
 | 
				
			||||||
    exports: [
 | 
					    exports: [
 | 
				
			||||||
        CoreAutoFocusDirective,
 | 
					        CoreAutoFocusDirective,
 | 
				
			||||||
 | 
					        CoreDownloadFileDirective,
 | 
				
			||||||
        CoreExternalContentDirective,
 | 
					        CoreExternalContentDirective,
 | 
				
			||||||
        CoreFormatTextDirective,
 | 
					        CoreFormatTextDirective,
 | 
				
			||||||
        CoreKeepKeyboardDirective,
 | 
					        CoreKeepKeyboardDirective,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										60
									
								
								src/directives/download-file.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/directives/download-file.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					// (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 { Directive, Input, OnInit, ElementRef } from '@angular/core';
 | 
				
			||||||
 | 
					import { NavController } from 'ionic-angular';
 | 
				
			||||||
 | 
					import { CoreFileHelperProvider } from '../providers/file-helper';
 | 
				
			||||||
 | 
					import { CoreDomUtilsProvider } from '../providers/utils/dom';
 | 
				
			||||||
 | 
					import { CoreUtilsProvider } from '../providers/utils/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Directive to allow downloading and open a file. When the item with this directive is clicked, the file will be
 | 
				
			||||||
 | 
					 * downloaded (if needed) and opened.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Directive({
 | 
				
			||||||
 | 
					    selector: '[core-download-file]'
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export class CoreDownloadFileDirective implements OnInit {
 | 
				
			||||||
 | 
					    @Input('core-download-file') file: any; // The file to download.
 | 
				
			||||||
 | 
					    @Input() component?: string; // Component to link the file to.
 | 
				
			||||||
 | 
					    @Input() componentId?: string | number; // Component ID to use in conjunction with the component.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected element: HTMLElement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor(element: ElementRef, protected domUtils: CoreDomUtilsProvider, protected fileHelper: CoreFileHelperProvider) {
 | 
				
			||||||
 | 
					        this.element = element.nativeElement || element;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Component being initialized.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    ngOnInit(): void {
 | 
				
			||||||
 | 
					        this.element.addEventListener('click', (ev: Event): void => {
 | 
				
			||||||
 | 
					            if (!this.file) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ev.preventDefault();
 | 
				
			||||||
 | 
					            ev.stopPropagation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const modal = this.domUtils.showModalLoading();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.fileHelper.downloadAndOpenFile(this.file, this.component, this.componentId).catch((error) => {
 | 
				
			||||||
 | 
					                this.domUtils.showErrorModalDefault(error, 'core.errordownloading', true);
 | 
				
			||||||
 | 
					            }).finally(() => {
 | 
				
			||||||
 | 
					                modal.dismiss();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										240
									
								
								src/providers/file-helper.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								src/providers/file-helper.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,240 @@
 | 
				
			|||||||
 | 
					// (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 { Injectable } from '@angular/core';
 | 
				
			||||||
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
 | 
					import { CoreAppProvider } from './app';
 | 
				
			||||||
 | 
					import { CoreFileProvider } from './file';
 | 
				
			||||||
 | 
					import { CoreFilepoolProvider } from './filepool';
 | 
				
			||||||
 | 
					import { CoreSitesProvider } from './sites';
 | 
				
			||||||
 | 
					import { CoreUtilsProvider } from './utils/utils';
 | 
				
			||||||
 | 
					import { CoreConstants } from '../core/constants';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Provider to provide some helper functions regarding files and packages.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Injectable()
 | 
				
			||||||
 | 
					export class CoreFileHelperProvider {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor(private fileProvider: CoreFileProvider, private filepoolProvider: CoreFilepoolProvider,
 | 
				
			||||||
 | 
					            private sitesProvider: CoreSitesProvider, private appProvider: CoreAppProvider, private translate: TranslateService,
 | 
				
			||||||
 | 
					            private utils: CoreUtilsProvider) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Convenience function to open a file, downloading it if needed.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param {any} file The file to download.
 | 
				
			||||||
 | 
					     * @param {string} [component] The component to link the file to.
 | 
				
			||||||
 | 
					     * @param {string|number} [componentId] An ID to use in conjunction with the component.
 | 
				
			||||||
 | 
					     * @param {string} [state] The file's state. If not provided, it will be calculated.
 | 
				
			||||||
 | 
					     * @param {Function} [onProgress] Function to call on progress.
 | 
				
			||||||
 | 
					     * @param {string} [siteId] The site ID. If not defined, current site.
 | 
				
			||||||
 | 
					     * @return {Promise<any>} Resolved on success.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    downloadAndOpenFile(file: any, component: string, componentId: string | number, state?: string,
 | 
				
			||||||
 | 
					            onProgress?: (event: any) => any, siteId?: string): Promise<any> {
 | 
				
			||||||
 | 
					        siteId = siteId || this.sitesProvider.getCurrentSiteId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const fileUrl = this.getFileUrl(file),
 | 
				
			||||||
 | 
					            timemodified = this.getFileTimemodified(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return this.downloadFileIfNeeded(file, fileUrl, component, componentId, timemodified, state, onProgress, siteId)
 | 
				
			||||||
 | 
					                .then((url) => {
 | 
				
			||||||
 | 
					            if (!url) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (url.indexOf('http') === 0) {
 | 
				
			||||||
 | 
					                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);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // Get the state.
 | 
				
			||||||
 | 
					                    if (state) {
 | 
				
			||||||
 | 
					                        return state;
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        return this.filepoolProvider.getFileStateByUrl(siteId, fileUrl, timemodified);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }).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);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Download a file if it needs to be downloaded.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param {any} file The file to download.
 | 
				
			||||||
 | 
					     * @param {string} fileUrl The file URL.
 | 
				
			||||||
 | 
					     * @param {string} [component] The component to link the file to.
 | 
				
			||||||
 | 
					     * @param {string|number} [componentId] An ID to use in conjunction with the component.
 | 
				
			||||||
 | 
					     * @param {number} [timemodified] The time this file was modified.
 | 
				
			||||||
 | 
					     * @param {string} [state] The file's state. If not provided, it will be calculated.
 | 
				
			||||||
 | 
					     * @param {Function} [onProgress] Function to call on progress.
 | 
				
			||||||
 | 
					     * @param {string} [siteId] The site ID. If not defined, current site.
 | 
				
			||||||
 | 
					     * @return {Promise<string>} Resolved with the URL to use on success.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected downloadFileIfNeeded(file: any, fileUrl: string, component?: string, componentId?: string | number,
 | 
				
			||||||
 | 
					            timemodified?: number, state?: string, onProgress?: (event: any) => any, siteId?: string): Promise<string> {
 | 
				
			||||||
 | 
					        siteId = siteId || this.sitesProvider.getCurrentSiteId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return this.sitesProvider.getSite(siteId).then((site) => {
 | 
				
			||||||
 | 
					            const fixedUrl = site.fixPluginfileURL(fileUrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (this.fileProvider.isAvailable()) {
 | 
				
			||||||
 | 
					                let promise;
 | 
				
			||||||
 | 
					                if (state) {
 | 
				
			||||||
 | 
					                    promise = Promise.resolve(state);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    // Calculate the state.
 | 
				
			||||||
 | 
					                    promise = this.filepoolProvider.getFileStateByUrl(siteId, fileUrl, timemodified);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return promise.then((state) => {
 | 
				
			||||||
 | 
					                    // The file system is available.
 | 
				
			||||||
 | 
					                    const isWifi = !this.appProvider.isNetworkAccessLimited(),
 | 
				
			||||||
 | 
					                        isOnline = this.appProvider.isOnline();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (state == CoreConstants.DOWNLOADED) {
 | 
				
			||||||
 | 
					                        // File is downloaded, get the local file URL.
 | 
				
			||||||
 | 
					                        return this.filepoolProvider.getUrlByUrl(
 | 
				
			||||||
 | 
					                                siteId, fileUrl, component, componentId, timemodified, false, false, file);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        if (!isOnline && !this.isStateDownloaded(state)) {
 | 
				
			||||||
 | 
					                            // Not downloaded and user is offline, reject.
 | 
				
			||||||
 | 
					                            return Promise.reject(this.translate.instant('core.networkerrormsg'));
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (onProgress) {
 | 
				
			||||||
 | 
					                            // This call can take a while. Send a fake event to notify that we're doing some calculations.
 | 
				
			||||||
 | 
					                            onProgress({calculating: true});
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        return this.filepoolProvider.shouldDownloadBeforeOpen(fixedUrl, file.filesize).then(() => {
 | 
				
			||||||
 | 
					                            if (state == CoreConstants.DOWNLOADING) {
 | 
				
			||||||
 | 
					                                // It's already downloading, stop.
 | 
				
			||||||
 | 
					                                return;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            // Download and then return the local URL.
 | 
				
			||||||
 | 
					                            return this.downloadFile(fileUrl, component, componentId, timemodified, onProgress, file, siteId);
 | 
				
			||||||
 | 
					                        }, () => {
 | 
				
			||||||
 | 
					                            // Start the download if in wifi, but return the URL right away so the file is opened.
 | 
				
			||||||
 | 
					                            if (isWifi && isOnline) {
 | 
				
			||||||
 | 
					                                this.downloadFile(fileUrl, component, componentId, timemodified, onProgress, file, siteId);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            if (!this.isStateDownloaded(state) || isOnline) {
 | 
				
			||||||
 | 
					                                // Not downloaded or online, return the online URL.
 | 
				
			||||||
 | 
					                                return fixedUrl;
 | 
				
			||||||
 | 
					                            } else {
 | 
				
			||||||
 | 
					                                // Outdated but offline, so we return the local URL.
 | 
				
			||||||
 | 
					                                return this.filepoolProvider.getUrlByUrl(
 | 
				
			||||||
 | 
					                                        siteId, fileUrl, component, componentId, timemodified, false, false, file);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        });
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                // Use the online URL.
 | 
				
			||||||
 | 
					                return fixedUrl;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Download the file.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param {string} fileUrl The file URL.
 | 
				
			||||||
 | 
					     * @param {string} [component] The component to link the file to.
 | 
				
			||||||
 | 
					     * @param {string|number} [componentId] An ID to use in conjunction with the component.
 | 
				
			||||||
 | 
					     * @param {number} [timemodified] The time this file was modified.
 | 
				
			||||||
 | 
					     * @param {Function} [onProgress] Function to call on progress.
 | 
				
			||||||
 | 
					     * @param {any} [file] The file to download.
 | 
				
			||||||
 | 
					     * @param {string} [siteId] The site ID. If not defined, current site.
 | 
				
			||||||
 | 
					     * @return {Promise<string>} Resolved with internal URL on success, rejected otherwise.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    downloadFile(fileUrl: string, component?: string, componentId?: string | number, timemodified?: number,
 | 
				
			||||||
 | 
					            onProgress?: (event: any) => any, file?: any, siteId?: string): Promise<string> {
 | 
				
			||||||
 | 
					        siteId = siteId || this.sitesProvider.getCurrentSiteId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Get the site and check if it can download files.
 | 
				
			||||||
 | 
					        return this.sitesProvider.getSite(siteId).then((site) => {
 | 
				
			||||||
 | 
					            if (!site.canDownloadFiles()) {
 | 
				
			||||||
 | 
					                return Promise.reject(this.translate.instant('core.cannotdownloadfiles'));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return this.filepoolProvider.downloadUrl(siteId, fileUrl, false, component, componentId,
 | 
				
			||||||
 | 
					                    timemodified, onProgress, undefined, file).catch((error) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Download failed, check the state again to see if the file was downloaded before.
 | 
				
			||||||
 | 
					                return this.filepoolProvider.getFileStateByUrl(siteId, fileUrl, timemodified).then((state) => {
 | 
				
			||||||
 | 
					                    if (this.isStateDownloaded(state)) {
 | 
				
			||||||
 | 
					                        return this.filepoolProvider.getInternalUrlByUrl(siteId, fileUrl);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        return Promise.reject(error);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the file's URL.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param {any} file The file.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    getFileUrl(file: any): string {
 | 
				
			||||||
 | 
					        return file.fileurl || file.url;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the file's timemodified.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param {any} file The file.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    getFileTimemodified(file: any): number {
 | 
				
			||||||
 | 
					        return file.timemodified || 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Check if a state is downloaded or outdated.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param {string} state The state to check.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    isStateDownloaded(state: string): boolean {
 | 
				
			||||||
 | 
					        return state === CoreConstants.DOWNLOADED || state === CoreConstants.OUTDATED;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user