mirror of
https://github.com/xuthus83/pigallery2.git
synced 2025-01-14 14:43:17 +08:00
adding video indicator for videos
This commit is contained in:
parent
5625f37d6b
commit
d7eb805186
@ -137,7 +137,7 @@ apt-get install build-essential libkrb5-dev gcc g++
|
|||||||
* Setup page
|
* Setup page
|
||||||
* Random photo url
|
* Random photo url
|
||||||
* You can generate an url that returns a random photo from your gallery. You can use this feature to develop 3rd party applications, like: changing desktop background
|
* You can generate an url that returns a random photo from your gallery. You can use this feature to develop 3rd party applications, like: changing desktop background
|
||||||
* video support - `future plan`
|
* video support
|
||||||
* **Markdown based blogging support** - `future plan`
|
* **Markdown based blogging support** - `future plan`
|
||||||
* you can write some note in the blog.md for every directory
|
* you can write some note in the blog.md for every directory
|
||||||
* bug free :) - `In progress`
|
* bug free :) - `In progress`
|
||||||
|
@ -74,6 +74,7 @@ import {RandomQueryBuilderGalleryComponent} from './gallery/random-query-builder
|
|||||||
import {RandomPhotoSettingsComponent} from './settings/random-photo/random-photo.settings.component';
|
import {RandomPhotoSettingsComponent} from './settings/random-photo/random-photo.settings.component';
|
||||||
import {FixOrientationPipe} from './gallery/FixOrientationPipe';
|
import {FixOrientationPipe} from './gallery/FixOrientationPipe';
|
||||||
import {VideoSettingsComponent} from './settings/video/video.settings.component';
|
import {VideoSettingsComponent} from './settings/video/video.settings.component';
|
||||||
|
import {DurationPipe} from './pipes/DurationPipe';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GoogleMapsConfig {
|
export class GoogleMapsConfig {
|
||||||
@ -170,7 +171,8 @@ export function translationsFactory(locale: string) {
|
|||||||
StringifyRole,
|
StringifyRole,
|
||||||
IconizeSortingMethod,
|
IconizeSortingMethod,
|
||||||
StringifySortingMethod,
|
StringifySortingMethod,
|
||||||
FixOrientationPipe
|
FixOrientationPipe,
|
||||||
|
DurationPipe
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: UrlSerializer, useClass: CustomUrlSerializer},
|
{provide: UrlSerializer, useClass: CustomUrlSerializer},
|
||||||
|
@ -2,6 +2,7 @@ import {Media} from '../Media';
|
|||||||
import {MediaDTO} from '../../../../common/entities/MediaDTO';
|
import {MediaDTO} from '../../../../common/entities/MediaDTO';
|
||||||
import {OrientationTypes} from 'ts-exif-parser';
|
import {OrientationTypes} from 'ts-exif-parser';
|
||||||
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
|
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
|
||||||
|
import {VideoDTO} from '../../../../common/entities/VideoDTO';
|
||||||
|
|
||||||
export class GridMedia extends Media {
|
export class GridMedia extends Media {
|
||||||
|
|
||||||
@ -22,5 +23,9 @@ export class GridMedia extends Media {
|
|||||||
return MediaDTO.isVideo(this.media);
|
return MediaDTO.isVideo(this.media);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get Video(): VideoDTO {
|
||||||
|
return <VideoDTO>this.media;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,6 @@ img {
|
|||||||
|
|
||||||
a {
|
a {
|
||||||
color: white;
|
color: white;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-keywords {
|
.photo-keywords {
|
||||||
@ -92,3 +91,11 @@ a {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.video-indicator{
|
||||||
|
font-size: large;
|
||||||
|
padding: 10px;
|
||||||
|
position: absolute;
|
||||||
|
transform: translate(-100%);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
<div #photoContainer class="photo-container" (mouseover)="mouseOver()" (mouseout)="mouseOut()">
|
<div #photoContainer class="photo-container" (mouseover)="mouseOver()" (mouseout)="mouseOut()">
|
||||||
<img #img [src]="thumbnail.Src | fixOrientation:gridPhoto.media.metadata.orientation | async"
|
|
||||||
|
|
||||||
|
<img #img [src]="thumbnail.Src | fixOrientation:gridPhoto.Orientation | async"
|
||||||
*ngIf="thumbnail.Available">
|
*ngIf="thumbnail.Available">
|
||||||
|
|
||||||
|
<div *ngIf="gridPhoto.isVideo()" class="video-indicator"
|
||||||
|
[style.marginTop.px]="-container.nativeElement.offsetHeight"
|
||||||
|
[style.marginLeft.px]="container.nativeElement.offsetWidth">
|
||||||
|
{{gridPhoto.Video.metadata.duration | duration}} <span class="oi oi-video"></span></div>
|
||||||
|
|
||||||
<app-gallery-grid-photo-loading
|
<app-gallery-grid-photo-loading
|
||||||
[error]="thumbnail.Error"
|
[error]="thumbnail.Error"
|
||||||
[animate]="thumbnail.loading"
|
[animate]="thumbnail.loading"
|
||||||
|
@ -45,8 +45,8 @@
|
|||||||
{{"Video"}}
|
{{"Video"}}
|
||||||
</div>
|
</div>
|
||||||
<div class="details-sub row">
|
<div class="details-sub row">
|
||||||
<div class="col-6" *ngIf="VideoData.duration">length: {{renderDuration(VideoData.duration)}}</div>
|
<div class="col-6" *ngIf="VideoData.duration"><ng-container i18n>duration</ng-container>: {{VideoData.duration | duration}}</div>
|
||||||
<div class="col-6" *ngIf="VideoData.bitRate">bit rate: {{calcSize(VideoData.bitRate)}}/s</div>
|
<div class="col-6" *ngIf="VideoData.bitRate"><ng-container i18n>bit rate</ng-container>: {{calcSize(VideoData.bitRate)}}/s</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -28,14 +28,6 @@ export class InfoPanelLightboxComponent {
|
|||||||
return (this.media.metadata.size.width * this.media.metadata.size.height / 1000000).toFixed(2);
|
return (this.media.metadata.size.width * this.media.metadata.size.height / 1000000).toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDuration(time: number) {
|
|
||||||
const h = Math.floor(time / 1000 / 60 / 60);
|
|
||||||
time %= 1000 * 60 * 60;
|
|
||||||
const m = Math.floor(time / 1000 / 60);
|
|
||||||
time %= 1000 * 60;
|
|
||||||
const s = Math.floor(time / 1000);
|
|
||||||
return Utils.zeroPrefix(h, 2) + ':' + Utils.zeroPrefix(m, 2) + ':' + Utils.zeroPrefix(s, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
calcSize(size: number) {
|
calcSize(size: number) {
|
||||||
const postFixes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
const postFixes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||||
|
30
frontend/app/pipes/DurationPipe.ts
Normal file
30
frontend/app/pipes/DurationPipe.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import {Pipe, PipeTransform} from '@angular/core';
|
||||||
|
import {I18n} from '@ngx-translate/i18n-polyfill';
|
||||||
|
|
||||||
|
|
||||||
|
@Pipe({name: 'duration'})
|
||||||
|
export class DurationPipe implements PipeTransform {
|
||||||
|
constructor(private i18n: I18n) {
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(time: number): string {
|
||||||
|
const h = Math.floor(time / 1000 / 60 / 60);
|
||||||
|
time %= 1000 * 60 * 60;
|
||||||
|
const m = Math.floor(time / 1000 / 60);
|
||||||
|
time %= 1000 * 60;
|
||||||
|
const s = Math.floor(time / 1000);
|
||||||
|
|
||||||
|
let str = '';
|
||||||
|
if (h > 0) {
|
||||||
|
str += h + this.i18n({value: 'h', meaning: 'hour'});
|
||||||
|
}
|
||||||
|
if (m > 0) {
|
||||||
|
str += m + this.i18n({value: 'm', meaning: 'minute'});
|
||||||
|
}
|
||||||
|
if (s > 0) {
|
||||||
|
str += s + this.i18n({value: 's', meaning: 'second'});
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -54,7 +54,8 @@ gulp.task('build-frontend', function (done) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('copy-static', function () {
|
gulp.task('copy-static', function () {
|
||||||
return gulp.src([
|
return gulp.src([
|
||||||
|
"backend/model/diagnostics/blank.jpg",
|
||||||
"README.md",
|
"README.md",
|
||||||
"LICENSE"], {base: "."})
|
"LICENSE"], {base: "."})
|
||||||
.pipe(gulp.dest('./release'));
|
.pipe(gulp.dest('./release'));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user