forked from EVOgeek/Vmeda.Online
		
	
						commit
						af24a778ab
					
				@ -12,8 +12,17 @@
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { Directive, Input, AfterViewInit, ElementRef, OnChanges, SimpleChange, Output, EventEmitter } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    Directive,
 | 
			
		||||
    Input,
 | 
			
		||||
    AfterViewInit,
 | 
			
		||||
    ElementRef,
 | 
			
		||||
    OnChanges,
 | 
			
		||||
    SimpleChange,
 | 
			
		||||
    Output,
 | 
			
		||||
    EventEmitter,
 | 
			
		||||
    OnDestroy,
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
import { CoreApp } from '@services/app';
 | 
			
		||||
import { CoreFile } from '@services/file';
 | 
			
		||||
import { CoreFilepool } from '@services/filepool';
 | 
			
		||||
@ -24,6 +33,9 @@ import { CoreUtils } from '@services/utils/utils';
 | 
			
		||||
import { Platform } from '@singletons';
 | 
			
		||||
import { CoreLogger } from '@singletons/logger';
 | 
			
		||||
import { CoreError } from '@classes/errors/error';
 | 
			
		||||
import { CoreSite } from '@classes/site';
 | 
			
		||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
 | 
			
		||||
import { CoreConstants } from '../constants';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Directive to handle external content.
 | 
			
		||||
@ -38,7 +50,7 @@ import { CoreError } from '@classes/errors/error';
 | 
			
		||||
@Directive({
 | 
			
		||||
    selector: '[core-external-content]',
 | 
			
		||||
})
 | 
			
		||||
export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
 | 
			
		||||
export class CoreExternalContentDirective implements AfterViewInit, OnChanges, OnDestroy {
 | 
			
		||||
 | 
			
		||||
    @Input() siteId?: string; // Site ID to use.
 | 
			
		||||
    @Input() component?: string; // Component to link the file to.
 | 
			
		||||
@ -54,6 +66,7 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
 | 
			
		||||
    protected element: Element;
 | 
			
		||||
    protected logger: CoreLogger;
 | 
			
		||||
    protected initialized = false;
 | 
			
		||||
    protected fileEventObserver?: CoreEventObserver;
 | 
			
		||||
 | 
			
		||||
    constructor(element: ElementRef) {
 | 
			
		||||
 | 
			
		||||
@ -183,34 +196,8 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
 | 
			
		||||
    protected async handleExternalContent(targetAttr: string, url: string, siteId?: string): Promise<void> {
 | 
			
		||||
 | 
			
		||||
        const tagName = this.element.tagName;
 | 
			
		||||
 | 
			
		||||
        if (tagName == 'VIDEO' && targetAttr != 'poster') {
 | 
			
		||||
            const video = <HTMLVideoElement> this.element;
 | 
			
		||||
            if (video.textTracks) {
 | 
			
		||||
                // It's a video with subtitles. Fix some issues with subtitles.
 | 
			
		||||
                video.textTracks.onaddtrack = (event): void => {
 | 
			
		||||
                    const track = <TextTrack> event.track;
 | 
			
		||||
                    if (track) {
 | 
			
		||||
                        track.oncuechange = (): void => {
 | 
			
		||||
                            if (!track.cues) {
 | 
			
		||||
                                return;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            const line = Platform.is('tablet') || CoreApp.isAndroid() ? 90 : 80;
 | 
			
		||||
                            // Position all subtitles to a percentage of video height.
 | 
			
		||||
                            // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | 
			
		||||
                            Array.from(track.cues).forEach((cue: any) => {
 | 
			
		||||
                                cue.snapToLines = false;
 | 
			
		||||
                                cue.line = line;
 | 
			
		||||
                                cue.size = 100; // This solves some Android issue.
 | 
			
		||||
                            });
 | 
			
		||||
                            // Delete listener.
 | 
			
		||||
                            track.oncuechange = null;
 | 
			
		||||
                        };
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.handleVideoSubtitles(<HTMLVideoElement> this.element);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const site = await CoreSites.getSite(siteId);
 | 
			
		||||
@ -234,46 +221,7 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
 | 
			
		||||
            throw new CoreError('Site doesn\'t allow downloading files.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Download images, tracks and posters if size is unknown.
 | 
			
		||||
        const downloadUnknown = tagName == 'IMG' || tagName == 'TRACK' || targetAttr == 'poster';
 | 
			
		||||
        let finalUrl: string;
 | 
			
		||||
 | 
			
		||||
        if (targetAttr === 'src' && tagName !== 'SOURCE' && tagName !== 'TRACK' && tagName !== 'VIDEO' && tagName !== 'AUDIO') {
 | 
			
		||||
            finalUrl = await CoreFilepool.getSrcByUrl(
 | 
			
		||||
                site.getId(),
 | 
			
		||||
                url,
 | 
			
		||||
                this.component,
 | 
			
		||||
                this.componentId,
 | 
			
		||||
                0,
 | 
			
		||||
                true,
 | 
			
		||||
                downloadUnknown,
 | 
			
		||||
            );
 | 
			
		||||
        } else if (tagName === 'TRACK') {
 | 
			
		||||
            // Download tracks right away. Using an online URL for tracks can give a CORS error in Android.
 | 
			
		||||
            finalUrl = await CoreFilepool.downloadUrl(site.getId(), url, false, this.component, this.componentId);
 | 
			
		||||
 | 
			
		||||
            finalUrl = CoreFile.convertFileSrc(finalUrl);
 | 
			
		||||
        } else {
 | 
			
		||||
            finalUrl = await CoreFilepool.getUrlByUrl(
 | 
			
		||||
                site.getId(),
 | 
			
		||||
                url,
 | 
			
		||||
                this.component,
 | 
			
		||||
                this.componentId,
 | 
			
		||||
                0,
 | 
			
		||||
                true,
 | 
			
		||||
                downloadUnknown,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            finalUrl = CoreFile.convertFileSrc(finalUrl);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!CoreUrlUtils.isLocalFileUrl(finalUrl) && !finalUrl.includes('#')) {
 | 
			
		||||
            /* In iOS, if we use the same URL in embedded file and background download then the download only
 | 
			
		||||
               downloads a few bytes (cached ones). Add an anchor to the URL so both URLs are different.
 | 
			
		||||
               Don't add this anchor if the URL already has an anchor, otherwise other anchors might not work.
 | 
			
		||||
               The downloaded URL won't have anchors so the URLs will already be different. */
 | 
			
		||||
            finalUrl = finalUrl + '#moodlemobile-embedded';
 | 
			
		||||
        }
 | 
			
		||||
        const finalUrl = await this.getUrlToUse(targetAttr, url, site);
 | 
			
		||||
 | 
			
		||||
        this.logger.debug('Using URL ' + finalUrl + ' for ' + url);
 | 
			
		||||
        if (tagName === 'SOURCE') {
 | 
			
		||||
@ -295,28 +243,7 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
 | 
			
		||||
            this.element.setAttribute('data-original-' + targetAttr, url);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Set events to download big files (not downloaded automatically).
 | 
			
		||||
        if (!CoreUrlUtils.isLocalFileUrl(finalUrl) && targetAttr != 'poster' &&
 | 
			
		||||
            (tagName == 'VIDEO' || tagName == 'AUDIO' || tagName == 'A' || tagName == 'SOURCE')) {
 | 
			
		||||
            const eventName = tagName == 'A' ? 'click' : 'play';
 | 
			
		||||
            let clickableEl = this.element;
 | 
			
		||||
 | 
			
		||||
            if (tagName == 'SOURCE') {
 | 
			
		||||
                clickableEl = <HTMLElement> CoreDomUtils.closest(this.element, 'video,audio');
 | 
			
		||||
                if (!clickableEl) {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            clickableEl.addEventListener(eventName, () => {
 | 
			
		||||
                // User played media or opened a downloadable link.
 | 
			
		||||
                // Download the file if in wifi and it hasn't been downloaded already (for big files).
 | 
			
		||||
                if (CoreApp.isWifi()) {
 | 
			
		||||
                    // We aren't using the result, so it doesn't matter which of the 2 functions we call.
 | 
			
		||||
                    CoreFilepool.getUrlByUrl(site.getId(), url, this.component, this.componentId, 0, false);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        this.setListeners(targetAttr, url, site);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -359,6 +286,153 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle video subtitles if any.
 | 
			
		||||
     *
 | 
			
		||||
     * @param video Video element.
 | 
			
		||||
     */
 | 
			
		||||
    protected handleVideoSubtitles(video: HTMLVideoElement): void {
 | 
			
		||||
        if (!video.textTracks) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // It's a video with subtitles. Fix some issues with subtitles.
 | 
			
		||||
        video.textTracks.onaddtrack = (event): void => {
 | 
			
		||||
            const track = <TextTrack> event.track;
 | 
			
		||||
            if (track) {
 | 
			
		||||
                track.oncuechange = (): void => {
 | 
			
		||||
                    if (!track.cues) {
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    const line = Platform.is('tablet') || CoreApp.isAndroid() ? 90 : 80;
 | 
			
		||||
                    // Position all subtitles to a percentage of video height.
 | 
			
		||||
                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | 
			
		||||
                    Array.from(track.cues).forEach((cue: any) => {
 | 
			
		||||
                        cue.snapToLines = false;
 | 
			
		||||
                        cue.line = line;
 | 
			
		||||
                        cue.size = 100; // This solves some Android issue.
 | 
			
		||||
                    });
 | 
			
		||||
                    // Delete listener.
 | 
			
		||||
                    track.oncuechange = null;
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the URL to use in the element. E.g. if the file is already downloaded it will return the local URL.
 | 
			
		||||
     *
 | 
			
		||||
     * @param targetAttr Attribute to modify.
 | 
			
		||||
     * @param url Original URL to treat.
 | 
			
		||||
     * @param site Site.
 | 
			
		||||
     * @return Promise resolved with the URL.
 | 
			
		||||
     */
 | 
			
		||||
    protected async getUrlToUse(targetAttr: string, url: string, site: CoreSite): Promise<string> {
 | 
			
		||||
        const tagName = this.element.tagName;
 | 
			
		||||
        let finalUrl: string;
 | 
			
		||||
 | 
			
		||||
        // Download images, tracks and posters if size is unknown.
 | 
			
		||||
        const downloadUnknown = tagName == 'IMG' || tagName == 'TRACK' || targetAttr == 'poster';
 | 
			
		||||
 | 
			
		||||
        if (targetAttr === 'src' && tagName !== 'SOURCE' && tagName !== 'TRACK' && tagName !== 'VIDEO' && tagName !== 'AUDIO') {
 | 
			
		||||
            finalUrl = await CoreFilepool.getSrcByUrl(
 | 
			
		||||
                site.getId(),
 | 
			
		||||
                url,
 | 
			
		||||
                this.component,
 | 
			
		||||
                this.componentId,
 | 
			
		||||
                0,
 | 
			
		||||
                true,
 | 
			
		||||
                downloadUnknown,
 | 
			
		||||
            );
 | 
			
		||||
        } else if (tagName === 'TRACK') {
 | 
			
		||||
            // Download tracks right away. Using an online URL for tracks can give a CORS error in Android.
 | 
			
		||||
            finalUrl = await CoreFilepool.downloadUrl(site.getId(), url, false, this.component, this.componentId);
 | 
			
		||||
 | 
			
		||||
            finalUrl = CoreFile.convertFileSrc(finalUrl);
 | 
			
		||||
        } else {
 | 
			
		||||
            finalUrl = await CoreFilepool.getUrlByUrl(
 | 
			
		||||
                site.getId(),
 | 
			
		||||
                url,
 | 
			
		||||
                this.component,
 | 
			
		||||
                this.componentId,
 | 
			
		||||
                0,
 | 
			
		||||
                true,
 | 
			
		||||
                downloadUnknown,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            finalUrl = CoreFile.convertFileSrc(finalUrl);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!CoreUrlUtils.isLocalFileUrl(finalUrl) && !finalUrl.includes('#') && tagName !== 'A') {
 | 
			
		||||
            /* In iOS, if we use the same URL in embedded file and background download then the download only
 | 
			
		||||
               downloads a few bytes (cached ones). Add an anchor to the URL so both URLs are different.
 | 
			
		||||
               Don't add this anchor if the URL already has an anchor, otherwise other anchors might not work.
 | 
			
		||||
               The downloaded URL won't have anchors so the URLs will already be different. */
 | 
			
		||||
            finalUrl = finalUrl + '#moodlemobile-embedded';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return finalUrl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set listeners if needed.
 | 
			
		||||
     *
 | 
			
		||||
     * @param targetAttr Attribute to modify.
 | 
			
		||||
     * @param url Original URL to treat.
 | 
			
		||||
     * @param site Site.
 | 
			
		||||
     * @return Promise resolved when done.
 | 
			
		||||
     */
 | 
			
		||||
    protected async setListeners(targetAttr: string, url: string, site: CoreSite): Promise<void> {
 | 
			
		||||
        if (this.fileEventObserver) {
 | 
			
		||||
            // Already listening to events.
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const tagName = this.element.tagName;
 | 
			
		||||
        let state = await CoreFilepool.getFileStateByUrl(site.getId(), url);
 | 
			
		||||
 | 
			
		||||
        // Listen for download changes in the file.
 | 
			
		||||
        const eventName = await CoreFilepool.getFileEventNameByUrl(site.getId(), url);
 | 
			
		||||
 | 
			
		||||
        this.fileEventObserver = CoreEvents.on(eventName, async () => {
 | 
			
		||||
            const newState = await CoreFilepool.getFileStateByUrl(site.getId(), url);
 | 
			
		||||
            if (newState === state) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            state = newState;
 | 
			
		||||
            if (state === CoreConstants.DOWNLOADING) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // The file state has changed. Handle the file again, maybe it's downloaded now or the file has been deleted.
 | 
			
		||||
            this.checkAndHandleExternalContent();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Set events to download big files (not downloaded automatically).
 | 
			
		||||
        if (targetAttr !== 'poster' && (tagName === 'VIDEO' || tagName === 'AUDIO' || tagName === 'A' || tagName === 'SOURCE')) {
 | 
			
		||||
            const eventName = tagName == 'A' ? 'click' : 'play';
 | 
			
		||||
            let clickableEl = this.element;
 | 
			
		||||
 | 
			
		||||
            if (tagName == 'SOURCE') {
 | 
			
		||||
                clickableEl = <HTMLElement> CoreDomUtils.closest(this.element, 'video,audio');
 | 
			
		||||
                if (!clickableEl) {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            clickableEl.addEventListener(eventName, () => {
 | 
			
		||||
                // User played media or opened a downloadable link.
 | 
			
		||||
                // Download the file if in wifi and it hasn't been downloaded already (for big files).
 | 
			
		||||
                if (state !== CoreConstants.DOWNLOADED && state !== CoreConstants.DOWNLOADING && CoreApp.isWifi()) {
 | 
			
		||||
                    // We aren't using the result, so it doesn't matter which of the 2 functions we call.
 | 
			
		||||
                    CoreFilepool.getUrlByUrl(site.getId(), url, this.component, this.componentId, 0, false);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Wait for the image to be loaded or error, and emit an event when it happens.
 | 
			
		||||
     */
 | 
			
		||||
@ -374,4 +448,11 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
 | 
			
		||||
        this.element.addEventListener('error', listener);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    ngOnDestroy(): void {
 | 
			
		||||
        this.fileEventObserver?.off();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,7 @@ import { CoreConstants } from '@/core/constants';
 | 
			
		||||
import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper';
 | 
			
		||||
import { CoreCustomURLSchemes } from '@services/urlschemes';
 | 
			
		||||
import { DomSanitizer } from '@singletons';
 | 
			
		||||
import { CoreFilepool } from '@services/filepool';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Directive to open a link in external browser or in the app.
 | 
			
		||||
@ -218,6 +219,26 @@ export class CoreLinkDirective implements OnInit {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (currentSite.isSitePluginFileUrl(href)) {
 | 
			
		||||
            // It's a site file. Check if it's being downloaded right now.
 | 
			
		||||
            const isDownloading = await CoreFilepool.isFileDownloadingByUrl(currentSite.getId(), href);
 | 
			
		||||
 | 
			
		||||
            if (isDownloading) {
 | 
			
		||||
                // Wait for the download to finish before opening the file to prevent downloading it twice.
 | 
			
		||||
                const modal = await CoreDomUtils.showModalLoading();
 | 
			
		||||
 | 
			
		||||
                try {
 | 
			
		||||
                    const path = await CoreFilepool.downloadUrl(currentSite.getId(), href);
 | 
			
		||||
 | 
			
		||||
                    return this.openLocalFile(path);
 | 
			
		||||
                } catch {
 | 
			
		||||
                    // Error downloading, just open the original URL.
 | 
			
		||||
                } finally {
 | 
			
		||||
                    modal.dismiss();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.autoLogin == 'yes') {
 | 
			
		||||
            if (this.inApp) {
 | 
			
		||||
                await currentSite.openInAppWithAutoLogin(href);
 | 
			
		||||
 | 
			
		||||
@ -457,13 +457,10 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate<CoreCo
 | 
			
		||||
                        size += fileSize;
 | 
			
		||||
                    } catch {
 | 
			
		||||
                        // Error getting size. Check if the file is being downloaded.
 | 
			
		||||
                        try {
 | 
			
		||||
                            await CoreFilepool.isFileDownloadingByUrl(siteId, CoreFileHelper.getFileUrl(file));
 | 
			
		||||
 | 
			
		||||
                        const isDownloading = await CoreFilepool.isFileDownloadingByUrl(siteId, CoreFileHelper.getFileUrl(file));
 | 
			
		||||
                        if (isDownloading) {
 | 
			
		||||
                            // If downloading, count as downloaded.
 | 
			
		||||
                            size += file.filesize || 0;
 | 
			
		||||
                        } catch {
 | 
			
		||||
                            // Not downloading and not found in disk, don't add any size
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }));
 | 
			
		||||
 | 
			
		||||
@ -231,7 +231,7 @@ export class CoreSettingsHelperProvider {
 | 
			
		||||
     * @return Sync promise or null if site is not being syncrhonized.
 | 
			
		||||
     */
 | 
			
		||||
    getSiteSyncPromise(siteId: string): Promise<void> | void {
 | 
			
		||||
        if (this.syncPromises[siteId]) {
 | 
			
		||||
        if (this.syncPromises[siteId] !== undefined) {
 | 
			
		||||
            return this.syncPromises[siteId];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -244,7 +244,7 @@ export class CoreSettingsHelperProvider {
 | 
			
		||||
     * @return Promise resolved when synchronized, rejected if failure.
 | 
			
		||||
     */
 | 
			
		||||
    async synchronizeSite(syncOnlyOnWifi: boolean, siteId: string): Promise<void> {
 | 
			
		||||
        if (this.syncPromises[siteId]) {
 | 
			
		||||
        if (this.syncPromises[siteId] !== undefined) {
 | 
			
		||||
            // There's already a sync ongoing for this site, return the promise.
 | 
			
		||||
            return this.syncPromises[siteId];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -559,10 +559,19 @@ export class CoreFilepoolProvider {
 | 
			
		||||
    async clearFilepool(siteId: string): Promise<void> {
 | 
			
		||||
        const db = await CoreSites.getSiteDb(siteId);
 | 
			
		||||
 | 
			
		||||
        // Read the data first to be able to notify the deletions.
 | 
			
		||||
        const filesEntries = await db.getAllRecords<CoreFilepoolFileEntry>(FILES_TABLE_NAME);
 | 
			
		||||
        const filesLinks = await db.getAllRecords<CoreFilepoolLinksRecord>(LINKS_TABLE_NAME);
 | 
			
		||||
 | 
			
		||||
        await Promise.all([
 | 
			
		||||
            db.deleteRecords(FILES_TABLE_NAME),
 | 
			
		||||
            db.deleteRecords(LINKS_TABLE_NAME),
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        // Notify now.
 | 
			
		||||
        const filesLinksMap = CoreUtils.arrayToObjectMultiple(filesLinks, 'fileId');
 | 
			
		||||
 | 
			
		||||
        filesEntries.forEach(entry => this.notifyFileDeleted(siteId, entry.fileId, filesLinksMap[entry.fileId] || []));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -2271,13 +2280,19 @@ export class CoreFilepoolProvider {
 | 
			
		||||
     *
 | 
			
		||||
     * @param siteId The site ID.
 | 
			
		||||
     * @param fileUrl File URL.
 | 
			
		||||
     * @param Promise resolved if file is downloading, rejected otherwise.
 | 
			
		||||
     * @param Promise resolved with boolean: whether the file is downloading.
 | 
			
		||||
     */
 | 
			
		||||
    async isFileDownloadingByUrl(siteId: string, fileUrl: string): Promise<void> {
 | 
			
		||||
    async isFileDownloadingByUrl(siteId: string, fileUrl: string): Promise<boolean> {
 | 
			
		||||
        const file = await this.fixPluginfileURL(siteId, fileUrl);
 | 
			
		||||
        const fileId = this.getFileIdByUrl(CoreFileHelper.getFileUrl(file));
 | 
			
		||||
 | 
			
		||||
        await this.hasFileInQueue(siteId, fileId);
 | 
			
		||||
        try {
 | 
			
		||||
            await this.hasFileInQueue(siteId, fileId);
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        } catch {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,7 @@ information provided here is intended especially for developers.
 | 
			
		||||
  Now you have to pass all items and 3 optional params have been added.
 | 
			
		||||
- CoreCourseModulePrefetchDelegate.getPrefetchHandlerFor now admits module name instead of full module object.
 | 
			
		||||
- CoreCourse.getModuleBasicInfoByInstance and CoreCourse.getModuleBasicInfo have been modified to accept an "options" parameter instead of only siteId.
 | 
			
		||||
- The function CoreFilepool.isFileDownloadingByUrl now returns Promise<boolean> instead of relying on resolve/reject.
 | 
			
		||||
 | 
			
		||||
=== 3.9.5 ===
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user