mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-01-08 04:03:48 +02:00
Create customizable lightbox text. fixes #801
This commit is contained in:
parent
7c3bce7179
commit
e68fbbbe44
File diff suppressed because one or more lines are too long
@ -386,6 +386,7 @@ Marker.prototype.options.icon = MarkerFactory.defIcon;
|
||||
CookieService,
|
||||
GPXFilesFilterPipe,
|
||||
MDFilesFilterPipe,
|
||||
FileSizePipe,
|
||||
DatePipe
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
|
@ -98,9 +98,8 @@
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.controls-caption {
|
||||
.controls-title {
|
||||
opacity: 0.7;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
height: initial;
|
||||
text-align: left;
|
||||
@ -110,6 +109,18 @@
|
||||
border-radius: 5px !important;
|
||||
}
|
||||
|
||||
.controls-subtitle-text{
|
||||
font-size: .6em;
|
||||
}
|
||||
|
||||
.controls-top-left-title {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.controls-bottom-left-title {
|
||||
bottom: 2rem;
|
||||
}
|
||||
|
||||
|
||||
.controls-zoom {
|
||||
bottom: 0;
|
||||
@ -291,7 +302,7 @@ input[type="range"].zoom-progress::-moz-range-track {
|
||||
opacity: 0.0;
|
||||
}
|
||||
|
||||
.controls-caption.controls-nodim {
|
||||
.controls-title.controls-nodim {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,19 @@
|
||||
<div id="controllers-container" #root>
|
||||
<div [class.dim-controls]="controllersDimmed" class="controls-caption"
|
||||
<div [class.dim-controls]="controllersDimmed" class="controls-title controls-top-left-title"
|
||||
[class.controls-nodim]="lightboxService.captionAlwaysOn"
|
||||
*ngIf="Title">{{Title}}</div>
|
||||
*ngIf="TopLeftTitle || TopLeftSubtitle">
|
||||
<div class="controls-title-text" *ngIf="TopLeftTitle">{{ TopLeftTitle }}</div>
|
||||
|
||||
<div class="controls-subtitle-text" *ngIf="TopLeftSubtitle">{{ TopLeftSubtitle }}</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div [class.dim-controls]="controllersDimmed"
|
||||
class="controls controls-top">
|
||||
<div class="controls-background rounded-start-bottom">
|
||||
<div class="highlight control-button" (click)="toggleInfoPanel.emit()"
|
||||
title="info key: i" i18n-title>
|
||||
<ng-icon name="ionInformationOutline"></ng-icon>
|
||||
<ng-icon name="ionInformationOutline"></ng-icon>
|
||||
</div>
|
||||
|
||||
<div *ngIf="fullScreenService.isFullScreenEnabled()"
|
||||
@ -23,7 +28,7 @@
|
||||
class="highlight control-button"
|
||||
(click)="toggleFullScreen.emit(true)"
|
||||
title="toggle fullscreen, key: f" i18n-title>
|
||||
<ng-icon size="0.85em"
|
||||
<ng-icon size="0.85em"
|
||||
name="ionExpandOutline"></ng-icon>
|
||||
</div>
|
||||
|
||||
@ -32,7 +37,7 @@
|
||||
class="border-0 highlight control-button"
|
||||
data-bs-auto-close="outside"
|
||||
aria-controls="dropdown-basic">
|
||||
<ng-icon size="1.2em" name="ionMenuOutline"></ng-icon>
|
||||
<ng-icon size="1.2em" name="ionMenuOutline"></ng-icon>
|
||||
</button>
|
||||
<ul id="dropdown-basic" *dropdownMenu class="dropdown-menu dropdown-menu-right"
|
||||
role="menu" aria-labelledby="button-basic">
|
||||
@ -141,7 +146,7 @@
|
||||
<div class="face-box"
|
||||
[class.controls-nodim]="lightboxService.facesAlwaysOn"></div>
|
||||
<span class="face-name"
|
||||
[class.controls-nodim]="lightboxService.facesAlwaysOn">{{face.name}}</span>
|
||||
[class.controls-nodim]="lightboxService.facesAlwaysOn">{{ face.name }}</span>
|
||||
</a>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!searchEnabled">
|
||||
@ -157,7 +162,7 @@
|
||||
</div>
|
||||
<span class="face-name"
|
||||
[class.controls-nodim]="lightboxService.facesAlwaysOn"
|
||||
>{{face.name}}</span>
|
||||
>{{ face.name }}</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
@ -179,6 +184,14 @@
|
||||
#canvas width="55px" height="55px"></canvas>
|
||||
|
||||
</div>
|
||||
<div [class.dim-controls]="controllersDimmed" class="controls-title controls-bottom-left-title"
|
||||
[class.controls-nodim]="lightboxService.captionAlwaysOn"
|
||||
*ngIf="BottomLeftTitle || BottomLeftSubtitle">
|
||||
<div class="controls-title-text" *ngIf="BottomLeftTitle">{{ BottomLeftTitle }}</div>
|
||||
|
||||
<div class="controls-subtitle-text " *ngIf="BottomLeftSubtitle">{{ BottomLeftSubtitle }}</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div [class.dim-controls]="controllersDimmed" class="controls controls-zoom row mb-3" *ngIf="Zoom > 1">
|
||||
<div class="col-1 col-md-4">
|
||||
@ -194,7 +207,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div [class.dim-controls]="controllersDimmed" class="controls controls-playback"
|
||||
*ngIf="zoom == 1 && activePhoto && activePhoto.gridMedia.isPhoto()">
|
||||
<div class="controls-background rounded-start-top pe-1 pb-1">
|
||||
|
@ -11,12 +11,17 @@ import {SearchQueryTypes, TextSearch, TextSearchQueryMatchTypes,} from '../../..
|
||||
import {AuthenticationService} from '../../../../model/network/authentication.service';
|
||||
import {LightboxService} from '../lightbox.service';
|
||||
import {GalleryCacheService} from '../../cache.gallery.service';
|
||||
import {Utils} from '../../../../../../common/Utils';
|
||||
import {FileSizePipe} from '../../../../pipes/FileSizePipe';
|
||||
import {DatePipe} from '@angular/common';
|
||||
import {LightBoxTitleTexts} from '../../../../../../common/config/public/ClientConfig';
|
||||
|
||||
export enum PlayBackStates {
|
||||
Paused = 1,
|
||||
Play = 2,
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-lightbox-controls',
|
||||
styleUrls: ['./controls.lightbox.gallery.component.css', './inputrange.css'],
|
||||
@ -61,10 +66,12 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
|
||||
private prevZoom = 1;
|
||||
|
||||
constructor(
|
||||
public lightboxService: LightboxService,
|
||||
public fullScreenService: FullScreenService,
|
||||
private authService: AuthenticationService,
|
||||
private cacheService: GalleryCacheService
|
||||
public lightboxService: LightboxService,
|
||||
public fullScreenService: FullScreenService,
|
||||
private authService: AuthenticationService,
|
||||
private cacheService: GalleryCacheService,
|
||||
private fileSizePipe: FileSizePipe,
|
||||
private datePipe: DatePipe
|
||||
) {
|
||||
this.searchEnabled = this.authService.canSearch();
|
||||
}
|
||||
@ -97,13 +104,6 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
|
||||
this.checkZoomAndDrag();
|
||||
}
|
||||
|
||||
get Title(): string {
|
||||
if (!this.activePhoto) {
|
||||
return null;
|
||||
}
|
||||
return (this.activePhoto.gridMedia.media as PhotoDTO).metadata.caption;
|
||||
}
|
||||
|
||||
public containerWidth(): void {
|
||||
return this.root.nativeElement.width;
|
||||
}
|
||||
@ -271,14 +271,14 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
|
||||
|
||||
private showNextMedia = () => {
|
||||
if (this.mediaElement.imageLoadFinished.this === false ||
|
||||
this.mediaElement.imageLoadFinished.next === false) {
|
||||
this.mediaElement.imageLoadFinished.next === false) {
|
||||
return;
|
||||
}
|
||||
// do not skip video if its playing
|
||||
if (
|
||||
this.activePhoto &&
|
||||
this.activePhoto.gridMedia.isVideo() &&
|
||||
!this.mediaElement.Paused
|
||||
this.activePhoto &&
|
||||
this.activePhoto.gridMedia.isVideo() &&
|
||||
!this.mediaElement.Paused
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@ -290,8 +290,8 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
|
||||
|
||||
// Video is a special snowflake. It won't go to next media if a video is playing
|
||||
if (!(this.activePhoto &&
|
||||
this.activePhoto.gridMedia.isVideo() &&
|
||||
!this.mediaElement.Paused)) {
|
||||
this.activePhoto.gridMedia.isVideo() &&
|
||||
!this.mediaElement.Paused)) {
|
||||
p = (t % (this.selectedSlideshowSpeed * 10)) / this.selectedSlideshowSpeed / 10; // ticks every 100 ms
|
||||
|
||||
}
|
||||
@ -322,12 +322,12 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
|
||||
this.pause();
|
||||
this.drawSliderProgress(0);
|
||||
this.timerSub = interval(100)
|
||||
.pipe(filter((t) => {
|
||||
this.drawSliderProgress(t);
|
||||
return t % (this.selectedSlideshowSpeed * 10) === 0; // ticks every 100 ms
|
||||
}))
|
||||
.pipe(skip(1)) // do not skip to next photo right away
|
||||
.subscribe(this.showNextMedia);
|
||||
.pipe(filter((t) => {
|
||||
this.drawSliderProgress(t);
|
||||
return t % (this.selectedSlideshowSpeed * 10) === 0; // ticks every 100 ms
|
||||
}))
|
||||
.pipe(skip(1)) // do not skip to next photo right away
|
||||
.subscribe(this.showNextMedia);
|
||||
this.playBackState = PlayBackStates.Play;
|
||||
}
|
||||
|
||||
@ -381,7 +381,7 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
|
||||
}
|
||||
|
||||
const photoAspect = MediaDTOUtils.calcAspectRatio(
|
||||
this.activePhoto.gridMedia.media
|
||||
this.activePhoto.gridMedia.media
|
||||
);
|
||||
const widthFilled = photoAspect > this.photoFrameDim.aspect;
|
||||
const divWidth = this.photoFrameDim.width;
|
||||
@ -442,7 +442,7 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
|
||||
}
|
||||
|
||||
const photoAspect = MediaDTOUtils.calcAspectRatio(
|
||||
this.activePhoto.gridMedia.media
|
||||
this.activePhoto.gridMedia.media
|
||||
);
|
||||
|
||||
if (photoAspect < this.photoFrameDim.aspect) {
|
||||
@ -459,5 +459,70 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
|
||||
this.nextPhoto.emit();
|
||||
}
|
||||
|
||||
|
||||
getText(type: LightBoxTitleTexts): string {
|
||||
if (!this.activePhoto?.gridMedia?.media) {
|
||||
return null;
|
||||
}
|
||||
const m = this.activePhoto.gridMedia.media as PhotoDTO;
|
||||
switch (type) {
|
||||
case LightBoxTitleTexts.file:
|
||||
return Utils.concatUrls(
|
||||
m.directory.path,
|
||||
m.directory.name,
|
||||
m.name
|
||||
);
|
||||
case LightBoxTitleTexts.resolution:
|
||||
return `${m.metadata.size.width}x${m.metadata.size.height}`;
|
||||
case LightBoxTitleTexts.size:
|
||||
return this.fileSizePipe.transform(m.metadata.fileSize);
|
||||
case LightBoxTitleTexts.title:
|
||||
return m.metadata.title;
|
||||
case LightBoxTitleTexts.caption:
|
||||
return m.metadata.caption;
|
||||
case LightBoxTitleTexts.keywords:
|
||||
return m.metadata.keywords.join(', ');
|
||||
case LightBoxTitleTexts.persons:
|
||||
return m.metadata.faces?.map(f => f.name)?.join(', ');
|
||||
case LightBoxTitleTexts.date:
|
||||
return this.datePipe.transform(m.metadata.creationDate, 'longDate');
|
||||
case LightBoxTitleTexts.location:
|
||||
return (
|
||||
m.metadata.positionData?.city ||
|
||||
m.metadata.positionData?.state ||
|
||||
m.metadata.positionData?.country || ''
|
||||
).trim();
|
||||
case LightBoxTitleTexts.camera:
|
||||
return m.metadata.cameraData?.model;
|
||||
case LightBoxTitleTexts.lens:
|
||||
return m.metadata.cameraData?.lens;
|
||||
case LightBoxTitleTexts.iso:
|
||||
return m.metadata.cameraData?.ISO.toString();
|
||||
case LightBoxTitleTexts.fstop:
|
||||
if (m.metadata.cameraData?.fStop > 1) {
|
||||
return m.metadata.cameraData?.fStop.toString();
|
||||
}
|
||||
return '1/' + Math.round(1 / m.metadata.cameraData?.fStop);
|
||||
case LightBoxTitleTexts.focal_length:
|
||||
return m.metadata.cameraData?.focalLength.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
get TopLeftTitle(): string {
|
||||
return this.getText(Config.Gallery.Lightbox.Titles.topLeftTitle);
|
||||
}
|
||||
|
||||
get TopLeftSubtitle(): string {
|
||||
return this.getText(Config.Gallery.Lightbox.Titles.topLeftSubtitle);
|
||||
}
|
||||
|
||||
get BottomLeftTitle(): string {
|
||||
return this.getText(Config.Gallery.Lightbox.Titles.bottomLeftTitle);
|
||||
}
|
||||
get BottomLeftSubtitle(): string {
|
||||
return this.getText(Config.Gallery.Lightbox.Titles.bottomLeftSubtitle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user