MOBILE-3773 video: Fix placeholder displayed if no poster
This commit is contained in:
		
							parent
							
								
									4a07245455
								
							
						
					
					
						commit
						d1bd392a68
					
				@ -266,9 +266,11 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
 | 
				
			|||||||
            finalUrl = CoreFile.convertFileSrc(finalUrl);
 | 
					            finalUrl = CoreFile.convertFileSrc(finalUrl);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!CoreUrlUtils.isLocalFileUrl(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
 | 
					            /* 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 a hash to the URL so both URLs are different. */
 | 
					               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';
 | 
					            finalUrl = finalUrl + '#moodlemobile-embedded';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -555,7 +555,7 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        videos.forEach((video) => {
 | 
					        videos.forEach((video) => {
 | 
				
			||||||
            this.treatMedia(video);
 | 
					            this.treatMedia(video, true);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        iframes.forEach((iframe) => {
 | 
					        iframes.forEach((iframe) => {
 | 
				
			||||||
@ -673,8 +673,9 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
     * Add media adapt class and apply CoreExternalContentDirective to the media element and its sources and tracks.
 | 
					     * Add media adapt class and apply CoreExternalContentDirective to the media element and its sources and tracks.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param element Video or audio to treat.
 | 
					     * @param element Video or audio to treat.
 | 
				
			||||||
 | 
					     * @param isVideo Whether it's a video.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected treatMedia(element: HTMLElement): void {
 | 
					    protected treatMedia(element: HTMLElement, isVideo: boolean = false): void {
 | 
				
			||||||
        this.addMediaAdaptClass(element);
 | 
					        this.addMediaAdaptClass(element);
 | 
				
			||||||
        this.addExternalContent(element);
 | 
					        this.addExternalContent(element);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -692,8 +693,16 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        const sources = Array.from(element.querySelectorAll('source'));
 | 
					        const sources = Array.from(element.querySelectorAll('source'));
 | 
				
			||||||
        const tracks = Array.from(element.querySelectorAll('track'));
 | 
					        const tracks = Array.from(element.querySelectorAll('track'));
 | 
				
			||||||
 | 
					        const hasPoster = isVideo && !!element.getAttribute('poster');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (isVideo && !hasPoster) {
 | 
				
			||||||
 | 
					            this.fixVideoSrcPlaceholder(element);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sources.forEach((source) => {
 | 
					        sources.forEach((source) => {
 | 
				
			||||||
 | 
					            if (isVideo && !hasPoster) {
 | 
				
			||||||
 | 
					                this.fixVideoSrcPlaceholder(source);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            source.setAttribute('target-src', source.getAttribute('src') || '');
 | 
					            source.setAttribute('target-src', source.getAttribute('src') || '');
 | 
				
			||||||
            source.removeAttribute('src');
 | 
					            source.removeAttribute('src');
 | 
				
			||||||
            this.addExternalContent(source);
 | 
					            this.addExternalContent(source);
 | 
				
			||||||
@ -709,6 +718,24 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Try to fix the placeholder displayed when a video doesn't have a poster.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param element Element to fix.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected fixVideoSrcPlaceholder(element: HTMLElement): void {
 | 
				
			||||||
 | 
					        const src = element.getAttribute('src');
 | 
				
			||||||
 | 
					        if (!src) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (src.match(/#t=\d/)) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        element.setAttribute('src', src + '#t=0.001');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Add media adapt class and treat the iframe source.
 | 
					     * Add media adapt class and treat the iframe source.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
 | 
				
			|||||||
@ -47,6 +47,7 @@ import {
 | 
				
			|||||||
    CoreFilepoolQueueDBEntry,
 | 
					    CoreFilepoolQueueDBEntry,
 | 
				
			||||||
} from '@services/database/filepool';
 | 
					} from '@services/database/filepool';
 | 
				
			||||||
import { CoreFileHelper } from './file-helper';
 | 
					import { CoreFileHelper } from './file-helper';
 | 
				
			||||||
 | 
					import { CoreUrl } from '@singletons/url';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Factory for handling downloading files and retrieve downloaded files.
 | 
					 * Factory for handling downloading files and retrieve downloaded files.
 | 
				
			||||||
@ -672,6 +673,13 @@ export class CoreFilepoolProvider {
 | 
				
			|||||||
        poolFileObject?: CoreFilepoolFileEntry,
 | 
					        poolFileObject?: CoreFilepoolFileEntry,
 | 
				
			||||||
    ): Promise<string> {
 | 
					    ): Promise<string> {
 | 
				
			||||||
        const fileId = this.getFileIdByUrl(fileUrl);
 | 
					        const fileId = this.getFileIdByUrl(fileUrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Extract the anchor from the URL (if any).
 | 
				
			||||||
 | 
					        const anchor = CoreUrl.getUrlAnchor(fileUrl);
 | 
				
			||||||
 | 
					        if (anchor) {
 | 
				
			||||||
 | 
					            fileUrl = fileUrl.replace(anchor, '');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const extension = CoreMimetypeUtils.guessExtensionFromUrl(fileUrl);
 | 
					        const extension = CoreMimetypeUtils.guessExtensionFromUrl(fileUrl);
 | 
				
			||||||
        const addExtension = typeof filePath == 'undefined';
 | 
					        const addExtension = typeof filePath == 'undefined';
 | 
				
			||||||
        const path = filePath || (await this.getFilePath(siteId, fileId, extension));
 | 
					        const path = filePath || (await this.getFilePath(siteId, fileId, extension));
 | 
				
			||||||
@ -712,7 +720,8 @@ export class CoreFilepoolProvider {
 | 
				
			|||||||
                extension: fileEntry.extension,
 | 
					                extension: fileEntry.extension,
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return fileEntry.toURL();
 | 
					            // Add the anchor again to the local URL.
 | 
				
			||||||
 | 
					            return fileEntry.toURL() + (anchor || '');
 | 
				
			||||||
        }).finally(() => {
 | 
					        }).finally(() => {
 | 
				
			||||||
            // Download finished, delete the promise.
 | 
					            // Download finished, delete the promise.
 | 
				
			||||||
            delete this.filePromises[siteId][downloadId];
 | 
					            delete this.filePromises[siteId][downloadId];
 | 
				
			||||||
@ -1015,7 +1024,10 @@ export class CoreFilepoolProvider {
 | 
				
			|||||||
                url = await this.getInternalUrlById(siteId, fileId);
 | 
					                url = await this.getInternalUrlById(siteId, fileId);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return finishSuccessfulDownload(url);
 | 
					            // Add the anchor to the local URL if any.
 | 
				
			||||||
 | 
					            const anchor = CoreUrl.getUrlAnchor(fileUrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return finishSuccessfulDownload(url + (anchor || ''));
 | 
				
			||||||
        } catch (error) {
 | 
					        } catch (error) {
 | 
				
			||||||
            // The file is not downloaded or it's outdated.
 | 
					            // The file is not downloaded or it's outdated.
 | 
				
			||||||
            this.notifyFileDownloading(siteId, fileId, links);
 | 
					            this.notifyFileDownloading(siteId, fileId, links);
 | 
				
			||||||
@ -1284,6 +1296,9 @@ export class CoreFilepoolProvider {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Remove the anchor.
 | 
				
			||||||
 | 
					        url = CoreUrl.removeUrlAnchor(url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Try to guess the filename the target file should have.
 | 
					        // Try to guess the filename the target file should have.
 | 
				
			||||||
        // We want to keep the original file name so people can easily identify the files after the download.
 | 
					        // We want to keep the original file name so people can easily identify the files after the download.
 | 
				
			||||||
        const filename = this.guessFilenameFromUrl(url);
 | 
					        const filename = this.guessFilenameFromUrl(url);
 | 
				
			||||||
@ -1446,7 +1461,7 @@ export class CoreFilepoolProvider {
 | 
				
			|||||||
            return CoreConstants.NOT_DOWNLOADABLE;
 | 
					            return CoreConstants.NOT_DOWNLOADABLE;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fileUrl = CoreFileHelper.getFileUrl(file);
 | 
					        fileUrl = CoreUrl.removeUrlAnchor(CoreFileHelper.getFileUrl(file));
 | 
				
			||||||
        timemodified = file.timemodified || timemodified;
 | 
					        timemodified = file.timemodified || timemodified;
 | 
				
			||||||
        revision = revision || this.getRevisionFromUrl(fileUrl);
 | 
					        revision = revision || this.getRevisionFromUrl(fileUrl);
 | 
				
			||||||
        const fileId = this.getFileIdByUrl(fileUrl);
 | 
					        const fileId = this.getFileIdByUrl(fileUrl);
 | 
				
			||||||
@ -1556,11 +1571,14 @@ export class CoreFilepoolProvider {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            // We found the file entry, now look for the file on disk.
 | 
					            // We found the file entry, now look for the file on disk.
 | 
				
			||||||
            if (mode === 'src') {
 | 
					            const path = mode === 'src' ?
 | 
				
			||||||
                return await this.getInternalSrcById(siteId, fileId);
 | 
					                await this.getInternalSrcById(siteId, fileId) :
 | 
				
			||||||
            } else {
 | 
					                await this.getInternalUrlById(siteId, fileId);
 | 
				
			||||||
                return await this.getInternalUrlById(siteId, fileId);
 | 
					
 | 
				
			||||||
            }
 | 
					            // Add the anchor to the local URL if any.
 | 
				
			||||||
 | 
					            const anchor = CoreUrl.getUrlAnchor(fileUrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return path + (anchor || '');
 | 
				
			||||||
        } catch (error) {
 | 
					        } catch (error) {
 | 
				
			||||||
            // The file is not on disk.
 | 
					            // The file is not on disk.
 | 
				
			||||||
            // We could not retrieve the file, delete the entries associated with that ID.
 | 
					            // We could not retrieve the file, delete the entries associated with that ID.
 | 
				
			||||||
 | 
				
			|||||||
@ -313,6 +313,11 @@ export class CoreMimetypeUtilsProvider {
 | 
				
			|||||||
            if (position > -1) {
 | 
					            if (position > -1) {
 | 
				
			||||||
                candidate = candidate.substr(0, position);
 | 
					                candidate = candidate.substr(0, position);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            // Remove anchor if any.
 | 
				
			||||||
 | 
					            position = candidate.indexOf('#');
 | 
				
			||||||
 | 
					            if (position > -1) {
 | 
				
			||||||
 | 
					                candidate = candidate.substr(0, position);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (EXTENSION_REGEX.test(candidate)) {
 | 
					            if (EXTENSION_REGEX.test(candidate)) {
 | 
				
			||||||
                extension = candidate;
 | 
					                extension = candidate;
 | 
				
			||||||
 | 
				
			|||||||
@ -58,6 +58,10 @@ export class CoreUrlUtilsProvider {
 | 
				
			|||||||
     * @return URL with params.
 | 
					     * @return URL with params.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    addParamsToUrl(url: string, params?: Record<string, unknown>, anchor?: string, boolToNumber?: boolean): string {
 | 
					    addParamsToUrl(url: string, params?: Record<string, unknown>, anchor?: string, boolToNumber?: boolean): string {
 | 
				
			||||||
 | 
					        // Remove any existing anchor to add the params before it.
 | 
				
			||||||
 | 
					        const urlAndAnchor = url.split('#');
 | 
				
			||||||
 | 
					        url = urlAndAnchor[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let separator = url.indexOf('?') != -1 ? '&' : '?';
 | 
					        let separator = url.indexOf('?') != -1 ? '&' : '?';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (const key in params) {
 | 
					        for (const key in params) {
 | 
				
			||||||
@ -75,6 +79,15 @@ export class CoreUrlUtilsProvider {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Re-add the anchor if any.
 | 
				
			||||||
 | 
					        if (urlAndAnchor.length > 1) {
 | 
				
			||||||
 | 
					            // Remove the URL from the array.
 | 
				
			||||||
 | 
					            urlAndAnchor.shift();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Use a join in case there is more than one #.
 | 
				
			||||||
 | 
					            url += '#' + urlAndAnchor.join('#');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (anchor) {
 | 
					        if (anchor) {
 | 
				
			||||||
            url += '#' + anchor;
 | 
					            url += '#' + anchor;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -203,4 +203,32 @@ export class CoreUrl {
 | 
				
			|||||||
            && CoreText.removeEndingSlash(partsA?.path) === CoreText.removeEndingSlash(partsB?.path);
 | 
					            && CoreText.removeEndingSlash(partsA?.path) === CoreText.removeEndingSlash(partsB?.path);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the anchor of a URL. If there's more than one they'll all be returned, separated by #.
 | 
				
			||||||
 | 
					     * E.g. myurl.com#foo=1#bar=2 will return #foo=1#bar=2.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param url URL.
 | 
				
			||||||
 | 
					     * @return Anchor, undefined if no anchor.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    static getUrlAnchor(url: string): string | undefined {
 | 
				
			||||||
 | 
					        const firstAnchorIndex = url.indexOf('#');
 | 
				
			||||||
 | 
					        if (firstAnchorIndex === -1) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return url.substr(firstAnchorIndex);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Remove the anchor from a URL.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param url URL.
 | 
				
			||||||
 | 
					     * @return URL without anchor if any.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    static removeUrlAnchor(url: string): string {
 | 
				
			||||||
 | 
					        const urlAndAnchor = url.split('#');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return urlAndAnchor[0];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user