diff --git a/src/common/SupportedFormats.ts b/src/common/SupportedFormats.ts index b8138e46..3d671cd2 100644 --- a/src/common/SupportedFormats.ts +++ b/src/common/SupportedFormats.ts @@ -29,11 +29,18 @@ export const SupportedFormats = { Photos: [], Videos: [], MetaFiles: [], + TranscodeNeed: { + Photos: [], + Videos: [], + } } }; + SupportedFormats.Photos = SupportedFormats.Photos.concat(SupportedFormats.TranscodeNeed.Photos); SupportedFormats.Videos = SupportedFormats.Videos.concat(SupportedFormats.TranscodeNeed.Videos); SupportedFormats.WithDots.Photos = SupportedFormats.Photos.map(f => '.' + f); SupportedFormats.WithDots.Videos = SupportedFormats.Videos.map(f => '.' + f); SupportedFormats.WithDots.MetaFiles = SupportedFormats.MetaFiles.map(f => '.' + f); +SupportedFormats.WithDots.TranscodeNeed.Photos = SupportedFormats.TranscodeNeed.Photos.map(f => '.' + f); +SupportedFormats.WithDots.TranscodeNeed.Videos = SupportedFormats.TranscodeNeed.Videos.map(f => '.' + f); diff --git a/src/common/entities/MediaDTO.ts b/src/common/entities/MediaDTO.ts index b4280365..7a78e6e7 100644 --- a/src/common/entities/MediaDTO.ts +++ b/src/common/entities/MediaDTO.ts @@ -11,6 +11,7 @@ export interface MediaDTO extends FileDTO { metadata: MediaMetadata; readyThumbnails: Array; readyIcon: boolean; + } @@ -64,6 +65,17 @@ export module MediaDTO { return false; }; + export const isVideoTranscodingNeeded = (media: MediaDTO): boolean => { + const lower = media.name.toLowerCase(); + for (const ext of SupportedFormats.WithDots.TranscodeNeed.Videos) { + if (lower.endsWith(ext)) { + return true; + } + } + return false; + }; + + export const getRotatedSize = (photo: MediaDTO): MediaDimension => { if (isSideWay(photo)) { // noinspection JSSuspiciousNameCombination diff --git a/src/frontend/app/ui/gallery/grid/GridMedia.ts b/src/frontend/app/ui/gallery/grid/GridMedia.ts index f258949d..875b08ae 100644 --- a/src/frontend/app/ui/gallery/grid/GridMedia.ts +++ b/src/frontend/app/ui/gallery/grid/GridMedia.ts @@ -15,6 +15,14 @@ export class GridMedia extends Media { return (this.media).metadata.orientation || OrientationTypes.TOP_LEFT; } + get Video(): VideoDTO { + return this.media; + } + + get Photo(): PhotoDTO { + return this.media; + } + isPhoto(): boolean { return MediaDTO.isPhoto(this.media); } @@ -23,12 +31,7 @@ export class GridMedia extends Media { return MediaDTO.isVideo(this.media); } - get Video(): VideoDTO { - return this.media; + public isVideoTranscodingNeeded() { + return MediaDTO.isVideoTranscodingNeeded(this.media); } - get Photo(): PhotoDTO { - return this.media; - } - - } diff --git a/src/frontend/app/ui/gallery/lightbox/lightbox.gallery.component.css b/src/frontend/app/ui/gallery/lightbox/lightbox.gallery.component.css index e4e257a7..7ed624d9 100644 --- a/src/frontend/app/ui/gallery/lightbox/lightbox.gallery.component.css +++ b/src/frontend/app/ui/gallery/lightbox/lightbox.gallery.component.css @@ -41,3 +41,4 @@ app-info-panel { -moz-transition: all 0.3s ease-in-out; -webkit-transition: all 0.3s ease-in-out; } + diff --git a/src/frontend/app/ui/gallery/lightbox/lightbox.gallery.component.html b/src/frontend/app/ui/gallery/lightbox/lightbox.gallery.component.html index 0caf7c94..900d64f6 100644 --- a/src/frontend/app/ui/gallery/lightbox/lightbox.gallery.component.html +++ b/src/frontend/app/ui/gallery/lightbox/lightbox.gallery.component.html @@ -10,8 +10,28 @@ [zoom]="controls ? controls.Zoom : 1" [drag]="controls ? controls.drag : {x:0,y:0}" [windowAspect]="photoFrameDim.aspect" + (videoSourceError)="onVideoSourceError()" #photo> + +
+
+
+ Error during loading the video. +
+ + Most likely the video is not transcoded. + It can be done in the settings. + You need to transcode these videos to watch them online: + + *.{{ext}} + + +
+
+ +
+ {top: 0, left: 0, width: 0, height: 0}; private iPvisibilityTimer: number = null; private visibilityTimer: number = null; @@ -55,7 +58,6 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { route: null }; - constructor(public fullScreenService: FullScreenService, private changeDetector: ChangeDetectorRef, private overlayService: OverlayService, @@ -325,10 +327,14 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { public isVisible(): boolean { return this.status !== LightboxStates.Closed; } + public isOpen(): boolean { return this.status === LightboxStates.Open; } + onVideoSourceError() { + this.videoSourceError = true; + } private updatePhotoFrameDim = () => { this.photoFrameDim.width = Math.max(window.innerWidth - this.infoPanelWidth, 0); @@ -389,6 +395,7 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { if (photoIndex < 0 || photoIndex > this.gridPhotoQL.length) { throw new Error('Can\'t find the media'); } + this.videoSourceError = false; this.activePhotoId = photoIndex; this.activePhoto = pcList[photoIndex]; @@ -407,7 +414,6 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { } - private findPhotoComponent(media: MediaDTO): GalleryPhotoComponent { const galleryPhotoComponents = this.gridPhotoQL.toArray(); for (let i = 0; i < galleryPhotoComponents.length; i++) { diff --git a/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.css b/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.css index 69ab778b..9fca2e32 100644 --- a/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.css +++ b/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.css @@ -6,4 +6,3 @@ transform: translate(-50%, -50%); } - diff --git a/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.html b/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.html index 4cf694b1..b7f7c790 100644 --- a/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.html +++ b/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.html @@ -22,9 +22,11 @@ (error)="onImageError()" (timeupdate)="onVideoProgress()" #video> - + + Something went wrong. + diff --git a/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.ts b/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.ts index e46bfce8..afa515e1 100644 --- a/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.ts +++ b/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.ts @@ -1,8 +1,9 @@ -import {Component, ElementRef, Input, Output, OnChanges, ViewChild} from '@angular/core'; +import {Component, ElementRef, EventEmitter, Input, OnChanges, Output, ViewChild} from '@angular/core'; import {GridMedia} from '../../grid/GridMedia'; import {FixOrientationPipe} from '../../../../pipes/FixOrientationPipe'; import {MediaDTO} from '../../../../../../common/entities/MediaDTO'; import {DomSanitizer, SafeStyle} from '@angular/platform-browser'; +import {SupportedFormats} from '../../../../../../common/SupportedFormats'; @Component({ selector: 'app-gallery-lightbox-media', @@ -16,18 +17,18 @@ export class GalleryLightboxMediaComponent implements OnChanges { @Input() windowAspect = 1; @Input() zoom = 1; @Input() drag = {x: 0, y: 0}; + @Output() videoSourceError = new EventEmitter(); @ViewChild('video', {static: false}) video: ElementRef; prevGirdPhoto: GridMedia = null; public imageSize = {width: 'auto', height: '100'}; - - private imageLoaded = false; public imageLoadFinished = false; - thumbnailSrc: string = null; photoSrc: string = null; + public transcodeNeedVideos = SupportedFormats.TranscodeNeed.Videos; + private mediaLoaded = false; private videoProgress = 0; constructor(public elementRef: ElementRef, @@ -40,35 +41,19 @@ export class GalleryLightboxMediaComponent implements OnChanges { -50 / this.zoom + '% + ' + this.drag.y / this.zoom + 'px))'); } - ngOnChanges() { - if (this.prevGirdPhoto !== this.gridMedia) { - this.prevGirdPhoto = this.gridMedia; - this.thumbnailSrc = null; - this.photoSrc = null; - this.imageLoaded = false; - this.imageLoadFinished = false; - this.setImageSize(); - } - if (this.thumbnailSrc == null && this.gridMedia && this.ThumbnailUrl !== null) { - FixOrientationPipe.transform(this.ThumbnailUrl, this.gridMedia.Orientation) - .then((src) => this.thumbnailSrc = src); - } - - if (this.photoSrc == null && this.gridMedia && this.loadMedia) { - FixOrientationPipe.transform(this.gridMedia.getMediaPath(), this.gridMedia.Orientation) - .then((src) => this.photoSrc = src); - } - } - - /** Video **/ - private onVideoProgress() { - this.videoProgress = (100 / this.video.nativeElement.duration) * this.video.nativeElement.currentTime; - } - public get VideoProgress(): number { return this.videoProgress; } + public set VideoProgress(value: number) { + if (!this.video && value === null && typeof value === 'undefined') { + return; + } + this.video.nativeElement.currentTime = this.video.nativeElement.duration * (value / 100); + if (this.video.nativeElement.paused) { + this.video.nativeElement.play().catch(console.error); + } + } public get VideoVolume(): number { if (!this.video) { @@ -85,17 +70,6 @@ export class GalleryLightboxMediaComponent implements OnChanges { this.video.nativeElement.volume = value; } - public set VideoProgress(value: number) { - if (!this.video && value === null && typeof value === 'undefined') { - return; - } - this.video.nativeElement.currentTime = this.video.nativeElement.duration * (value / 100); - if (this.video.nativeElement.paused) { - this.video.nativeElement.play().catch(console.error); - } - } - - public get Muted(): boolean { if (!this.video) { return false; @@ -103,6 +77,48 @@ export class GalleryLightboxMediaComponent implements OnChanges { return this.video.nativeElement.muted; } + public get Paused(): boolean { + if (!this.video) { + return true; + } + return this.video.nativeElement.paused; + } + + public get PhotoSrc(): string { + return this.gridMedia.getMediaPath(); + } + + private get ThumbnailUrl(): string { + if (this.gridMedia.isThumbnailAvailable() === true) { + return this.gridMedia.getThumbnailPath(); + } + + if (this.gridMedia.isReplacementThumbnailAvailable() === true) { + return this.gridMedia.getReplacementThumbnailPath(); + } + return null; + } + + ngOnChanges() { + if (this.prevGirdPhoto !== this.gridMedia) { + this.prevGirdPhoto = this.gridMedia; + this.thumbnailSrc = null; + this.photoSrc = null; + this.mediaLoaded = false; + this.imageLoadFinished = false; + this.setImageSize(); + } + if (this.thumbnailSrc == null && this.gridMedia && this.ThumbnailUrl !== null) { + FixOrientationPipe.transform(this.ThumbnailUrl, this.gridMedia.Orientation) + .then((src) => this.thumbnailSrc = src); + } + + if (this.photoSrc == null && this.gridMedia && this.loadMedia) { + FixOrientationPipe.transform(this.gridMedia.getMediaPath(), this.gridMedia.Orientation) + .then((src) => this.photoSrc = src); + } + } + public mute() { if (!this.video) { return; @@ -122,48 +138,34 @@ export class GalleryLightboxMediaComponent implements OnChanges { } } - public get Paused(): boolean { - if (!this.video) { - return true; - } - return this.video.nativeElement.paused; - } - - onImageError() { // TODO:handle error this.imageLoadFinished = true; console.error('Error: cannot load media for lightbox url: ' + this.gridMedia.getMediaPath()); } - onImageLoad() { this.imageLoadFinished = true; - this.imageLoaded = true; - } - - private get ThumbnailUrl(): string { - if (this.gridMedia.isThumbnailAvailable() === true) { - return this.gridMedia.getThumbnailPath(); - } - - if (this.gridMedia.isReplacementThumbnailAvailable() === true) { - return this.gridMedia.getReplacementThumbnailPath(); - } - return null; - } - - public get PhotoSrc(): string { - return this.gridMedia.getMediaPath(); + this.mediaLoaded = true; } public showThumbnail(): boolean { return this.gridMedia && - !this.imageLoaded && + !this.mediaLoaded && this.thumbnailSrc !== null && (this.gridMedia.isThumbnailAvailable() || this.gridMedia.isReplacementThumbnailAvailable()); } + onSourceError($event: any) { + this.mediaLoaded = false; + this.videoSourceError.emit(); + } + + /** Video **/ + private onVideoProgress() { + this.videoProgress = (100 / this.video.nativeElement.duration) * this.video.nativeElement.currentTime; + } + private setImageSize() { if (!this.gridMedia) { return; @@ -180,6 +182,5 @@ export class GalleryLightboxMediaComponent implements OnChanges { this.imageSize.width = '100'; } } - } diff --git a/src/frontend/translate/messages.en.xlf b/src/frontend/translate/messages.en.xlf index 61c5abd5..2b026863 100644 --- a/src/frontend/translate/messages.en.xlf +++ b/src/frontend/translate/messages.en.xlf @@ -180,6 +180,30 @@ Zoom in, key: '+' + + Error during loading the video. + + app/ui/gallery/lightbox/lightbox.gallery.component.html + 20 + + Error during loading the video. + + + + Most likely the video is not transcoded. + It can be done in the settings. + You need to transcode these videos to watch them online: + + + app/ui/gallery/lightbox/lightbox.gallery.component.html + 22 + + + Most likely the video is not transcoded. + It can be done in the settings. + You need to transcode these videos to watch them online: + + Link availability diff --git a/src/frontend/translate/messages.fr.xlf b/src/frontend/translate/messages.fr.xlf index fe8eba0b..132adb2f 100644 --- a/src/frontend/translate/messages.fr.xlf +++ b/src/frontend/translate/messages.fr.xlf @@ -180,6 +180,30 @@ Zoom avant, touche : '+' + + Error during loading the video. + + app/ui/gallery/lightbox/lightbox.gallery.component.html + 20 + + Error during loading the video. + + + + Most likely the video is not transcoded. + It can be done in the settings. + You need to transcode these videos to watch them online: + + + app/ui/gallery/lightbox/lightbox.gallery.component.html + 22 + + + Most likely the video is not transcoded. + It can be done in the settings. + You need to transcode these videos to watch them online: + + Link availability diff --git a/src/frontend/translate/messages.hu.xlf b/src/frontend/translate/messages.hu.xlf index 7430f821..cfb56c1c 100644 --- a/src/frontend/translate/messages.hu.xlf +++ b/src/frontend/translate/messages.hu.xlf @@ -180,6 +180,29 @@ Nagyítás, gyorsgomb: '+' + + Error during loading the video. + + app/ui/gallery/lightbox/lightbox.gallery.component.html + 20 + + Hiba a videó betöltése közben. + + + + Most likely the video is not transcoded. + It can be done in the settings. + You need to transcode these videos to watch them online: + + + app/ui/gallery/lightbox/lightbox.gallery.component.html + 22 + + + Valószínűleg a videó nincs átkonvertálva. Ezt a beállításokban megteheted. + Ezek a videó formátumok csak átkonvertálás után játszhatók le: + + Link availability @@ -2480,4 +2503,4 @@ - \ No newline at end of file + diff --git a/src/frontend/translate/messages.ro.xlf b/src/frontend/translate/messages.ro.xlf index b52c2f28..7c171710 100644 --- a/src/frontend/translate/messages.ro.xlf +++ b/src/frontend/translate/messages.ro.xlf @@ -180,6 +180,30 @@ Mărește, tasta: '+' + + Error during loading the video. + + app/ui/gallery/lightbox/lightbox.gallery.component.html + 20 + + Error during loading the video. + + + + Most likely the video is not transcoded. + It can be done in the settings. + You need to transcode these videos to watch them online: + + + app/ui/gallery/lightbox/lightbox.gallery.component.html + 22 + + + Most likely the video is not transcoded. + It can be done in the settings. + You need to transcode these videos to watch them online: + + Link availability diff --git a/src/frontend/translate/messages.ru.xlf b/src/frontend/translate/messages.ru.xlf index 4a2c7b63..5e7078a3 100644 --- a/src/frontend/translate/messages.ru.xlf +++ b/src/frontend/translate/messages.ru.xlf @@ -180,6 +180,30 @@ Увеличить, клавиша: '+' + + Error during loading the video. + + app/ui/gallery/lightbox/lightbox.gallery.component.html + 20 + + Error during loading the video. + + + + Most likely the video is not transcoded. + It can be done in the settings. + You need to transcode these videos to watch them online: + + + app/ui/gallery/lightbox/lightbox.gallery.component.html + 22 + + + Most likely the video is not transcoded. + It can be done in the settings. + You need to transcode these videos to watch them online: + + Link availability