1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-01-12 04:23:09 +02:00

ui directory refactoring

adding thumbnail loader for faces
This commit is contained in:
Patrik J. Braun 2019-03-03 10:30:12 +01:00
parent 5eb69746e5
commit 0d3b8823e4
160 changed files with 760 additions and 525 deletions

View File

@ -1,6 +1,8 @@
import {NextFunction, Request, Response} from 'express';
import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
import {ObjectManagers} from '../model/ObjectManagers';
import {PersonDTO} from '../../common/entities/PersonDTO';
import {PhotoDTO} from '../../common/entities/PhotoDTO';
const LOG_TAG = '[PersonMWs]';
@ -9,8 +11,6 @@ export class PersonMWs {
public static async listPersons(req: Request, res: Response, next: NextFunction) {
try {
req.resultPipe = await ObjectManagers.getInstance()
.PersonManager.getAll();
@ -23,6 +23,43 @@ export class PersonMWs {
}
public static async addSamplePhotoForAll(req: Request, res: Response, next: NextFunction) {
if (!req.resultPipe) {
return next();
}
try {
const persons = (req.resultPipe as PersonWithPhoto[]);
for (let i = 0; i < persons.length; i++) {
persons[i].samplePhoto = await ObjectManagers.getInstance()
.PersonManager.getSamplePhoto(persons[i].name);
}
req.resultPipe = persons;
return next();
} catch (err) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during listing the directory', err));
}
}
public static async removeSamplePhotoForAll(req: Request, res: Response, next: NextFunction) {
if (!req.resultPipe) {
return next();
}
try {
const persons = (req.resultPipe as PersonWithPhoto[]);
for (let i = 0; i < persons.length; i++) {
delete persons[i].samplePhoto;
}
req.resultPipe = persons;
return next();
} catch (err) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during listing the directory', err));
}
}
public static async getSamplePhoto(req: Request, res: Response, next: NextFunction) {
if (!req.params.name) {
return next();
@ -44,3 +81,8 @@ export class PersonMWs {
}
}
export interface PersonWithPhoto extends PersonDTO {
samplePhoto: PhotoDTO;
}

View File

@ -14,6 +14,7 @@ import {RendererInput, ThumbnailSourceType, ThumbnailWorker} from '../../model/t
import {MediaDTO} from '../../../common/entities/MediaDTO';
import {ITaskExecuter, TaskExecuter} from '../../model/threading/TaskExecuter';
import {FaceRegion, PhotoDTO} from '../../../common/entities/PhotoDTO';
import {PersonWithPhoto} from '../PersonMWs';
export class ThumbnailGeneratorMWs {
@ -73,6 +74,39 @@ export class ThumbnailGeneratorMWs {
}
public static addThumbnailInfoForPersons(req: Request, res: Response, next: NextFunction) {
if (!req.resultPipe) {
return next();
}
try {
const size: number = Config.Client.Thumbnail.personThumbnailSize;
const persons: PersonWithPhoto[] = req.resultPipe;
for (let i = 0; i < persons.length; i++) {
// load parameters
const mediaPath = path.join(ProjectPath.ImageFolder,
persons[i].samplePhoto.directory.path,
persons[i].samplePhoto.directory.name, persons[i].samplePhoto.name);
// generate thumbnail path
const thPath = path.join(ProjectPath.ThumbnailFolder,
ThumbnailGeneratorMWs.generatePersonThumbnailName(mediaPath, persons[i].samplePhoto.metadata.faces[0], size));
persons[i].readyThumbnail = fs.existsSync(thPath);
}
} catch (error) {
return next(new ErrorDTO(ErrorCodes.SERVER_ERROR, 'error during postprocessing result (adding thumbnail info)', error.toString()));
}
return next();
}
public static async generatePersonThumbnail(req: Request, res: Response, next: NextFunction) {
if (!req.resultPipe) {
return next();

View File

@ -18,4 +18,7 @@ export class PersonEntry implements PersonDTO {
@OneToMany(type => FaceRegionEntry, faceRegion => faceRegion.person)
public faces: FaceRegionEntry[];
readyThumbnail: boolean;
}

View File

@ -15,19 +15,28 @@ export class PersonRouter {
private static addPersons(app: Express) {
app.get(['/api/person'],
// common part
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.User),
VersionMWs.injectGalleryVersion,
// specific part
PersonMWs.listPersons,
PersonMWs.addSamplePhotoForAll,
ThumbnailGeneratorMWs.addThumbnailInfoForPersons,
PersonMWs.removeSamplePhotoForAll,
RenderingMWs.renderResult
);
}
private static getPersonThumbnail(app: Express) {
app.get(['/api/person/:name/thumbnail'],
// common part
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.User),
VersionMWs.injectGalleryVersion,
// specific part
PersonMWs.getSamplePhoto,
ThumbnailGeneratorMWs.generatePersonThumbnail,
RenderingMWs.renderFile

View File

@ -2,5 +2,21 @@ export interface PersonDTO {
id: number;
name: string;
count: number;
readyThumbnail: boolean;
}
export class Person implements PersonDTO {
count: number;
id: number;
name: string;
readyThumbnail: boolean;
constructor() {
}
public static getThumbnailUrl(that: PersonDTO): string {
return '/api/person/' + that.name + '/thumbnail';
}
}

View File

@ -4,7 +4,7 @@ import {UserDTO} from '../../common/entities/UserDTO';
import {Router} from '@angular/router';
import {Config} from '../../common/config/public/Config';
import {Title} from '@angular/platform-browser';
import {ShareService} from './gallery/share.service';
import {ShareService} from './ui/gallery/share.service';
import 'hammerjs';
import {Subscription} from 'rxjs';

View File

@ -4,80 +4,81 @@ import {FormsModule} from '@angular/forms';
import {AppComponent} from './app.component';
import {appRoutes} from './app.routing';
import {UserService} from './model/network/user.service';
import {GalleryService} from './gallery/gallery.service';
import {GalleryService} from './ui/gallery/gallery.service';
import {NetworkService} from './model/network/network.service';
import {GalleryCacheService} from './gallery/cache.gallery.service';
import {FullScreenService} from './gallery/fullscreen.service';
import {GalleryCacheService} from './ui/gallery/cache.gallery.service';
import {FullScreenService} from './ui/gallery/fullscreen.service';
import {AuthenticationService} from './model/network/authentication.service';
import {UserMangerSettingsComponent} from './settings/usermanager/usermanager.settings.component';
import {FrameComponent} from './frame/frame.component';
import {UserMangerSettingsComponent} from './ui/settings/usermanager/usermanager.settings.component';
import {FrameComponent} from './ui/frame/frame.component';
import {YagaModule} from '@yaga/leaflet-ng2';
import {GalleryLightboxMediaComponent} from './gallery/lightbox/media/media.lightbox.gallery.component';
import {GalleryPhotoLoadingComponent} from './gallery/grid/photo/loading/loading.photo.grid.gallery.component';
import {GalleryNavigatorComponent} from './gallery/navigator/navigator.gallery.component';
import {GallerySearchComponent} from './gallery/search/search.gallery.component';
import {GalleryLightboxComponent} from './gallery/lightbox/lightbox.gallery.component';
import {GalleryDirectoryComponent} from './gallery/directory/directory.gallery.component';
import {GalleryGridComponent} from './gallery/grid/grid.gallery.component';
import {GalleryPhotoComponent} from './gallery/grid/photo/photo.grid.gallery.component';
import {LoginComponent} from './login/login.component';
import {AdminComponent} from './admin/admin.component';
import {GalleryComponent} from './gallery/gallery.component';
import {GalleryLightboxMediaComponent} from './ui/gallery/lightbox/media/media.lightbox.gallery.component';
import {GalleryPhotoLoadingComponent} from './ui/gallery/grid/photo/loading/loading.photo.grid.gallery.component';
import {GalleryNavigatorComponent} from './ui/gallery/navigator/navigator.gallery.component';
import {GallerySearchComponent} from './ui/gallery/search/search.gallery.component';
import {GalleryLightboxComponent} from './ui/gallery/lightbox/lightbox.gallery.component';
import {GalleryDirectoryComponent} from './ui/gallery/directories/directory/directory.gallery.component';
import {GalleryGridComponent} from './ui/gallery/grid/grid.gallery.component';
import {GalleryPhotoComponent} from './ui/gallery/grid/photo/photo.grid.gallery.component';
import {LoginComponent} from './ui/login/login.component';
import {AdminComponent} from './ui/admin/admin.component';
import {GalleryComponent} from './ui/gallery/gallery.component';
import {StringifyRole} from './pipes/StringifyRolePipe';
import {GalleryMapComponent} from './gallery/map/map.gallery.component';
import {GalleryMapLightboxComponent} from './gallery/map/lightbox/lightbox.map.gallery.component';
import {ThumbnailManagerService} from './gallery/thumbnailManager.service';
import {OverlayService} from './gallery/overlay.service';
import {GalleryMapComponent} from './ui/gallery/map/map.gallery.component';
import {GalleryMapLightboxComponent} from './ui/gallery/map/lightbox/lightbox.map.gallery.component';
import {ThumbnailManagerService} from './ui/gallery/thumbnailManager.service';
import {OverlayService} from './ui/gallery/overlay.service';
import {SlimLoadingBarModule} from 'ng2-slim-loading-bar';
import {GalleryShareComponent} from './gallery/share/share.gallery.component';
import {ShareLoginComponent} from './sharelogin/share-login.component';
import {ShareService} from './gallery/share.service';
import {GalleryShareComponent} from './ui/gallery/share/share.gallery.component';
import {ShareLoginComponent} from './ui/sharelogin/share-login.component';
import {ShareService} from './ui/gallery/share.service';
import {ModalModule} from 'ngx-bootstrap/modal';
import {BsDatepickerModule} from 'ngx-bootstrap/datepicker';
import {DatabaseSettingsComponent} from './settings/database/database.settings.component';
import {DatabaseSettingsComponent} from './ui/settings/database/database.settings.component';
import {ToastrModule} from 'ngx-toastr';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {NotificationService} from './model/notification.service';
import {JwBootstrapSwitchNg2Module} from 'jw-bootstrap-switch-ng2';
import {ClipboardModule} from 'ngx-clipboard';
import {NavigationService} from './model/navigation.service';
import {InfoPanelLightboxComponent} from './gallery/lightbox/infopanel/info-panel.lightbox.gallery.component';
import {MapSettingsComponent} from './settings/map/map.settings.component';
import {InfoPanelLightboxComponent} from './ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component';
import {MapSettingsComponent} from './ui/settings/map/map.settings.component';
import {TooltipModule} from 'ngx-bootstrap/tooltip';
import {BsDropdownModule} from 'ngx-bootstrap/dropdown';
import {CollapseModule} from 'ngx-bootstrap/collapse';
import {PopoverModule} from 'ngx-bootstrap/popover';
import {ThumbnailSettingsComponent} from './settings/thumbnail/thumbanil.settings.component';
import {SearchSettingsComponent} from './settings/search/search.settings.component';
import {SettingsService} from './settings/settings.service';
import {ShareSettingsComponent} from './settings/share/share.settings.component';
import {BasicSettingsComponent} from './settings/basic/basic.settings.component';
import {OtherSettingsComponent} from './settings/other/other.settings.component';
import {ThumbnailSettingsComponent} from './ui/settings/thumbnail/thumbanil.settings.component';
import {SearchSettingsComponent} from './ui/settings/search/search.settings.component';
import {SettingsService} from './ui/settings/settings.service';
import {ShareSettingsComponent} from './ui/settings/share/share.settings.component';
import {BasicSettingsComponent} from './ui/settings/basic/basic.settings.component';
import {OtherSettingsComponent} from './ui/settings/other/other.settings.component';
import {HttpClientModule} from '@angular/common/http';
import {DefaultUrlSerializer, UrlSerializer, UrlTree} from '@angular/router';
import {IndexingSettingsComponent} from './settings/indexing/indexing.settings.component';
import {LanguageComponent} from './language/language.component';
import {IndexingSettingsComponent} from './ui/settings/indexing/indexing.settings.component';
import {LanguageComponent} from './ui/language/language.component';
import {I18n} from '@ngx-translate/i18n-polyfill';
import {QueryService} from './model/query.service';
import {IconizeSortingMethod} from './pipes/IconizeSortingMethod';
import {StringifySortingMethod} from './pipes/StringifySortingMethod';
import {RandomQueryBuilderGalleryComponent} from './gallery/random-query-builder/random-query-builder.gallery.component';
import {RandomPhotoSettingsComponent} from './settings/random-photo/random-photo.settings.component';
import {FixOrientationPipe} from './gallery/FixOrientationPipe';
import {VideoSettingsComponent} from './settings/video/video.settings.component';
import {RandomQueryBuilderGalleryComponent} from './ui/gallery/random-query-builder/random-query-builder.gallery.component';
import {RandomPhotoSettingsComponent} from './ui/settings/random-photo/random-photo.settings.component';
import {FixOrientationPipe} from './pipes/FixOrientationPipe';
import {VideoSettingsComponent} from './ui/settings/video/video.settings.component';
import {DurationPipe} from './pipes/DurationPipe';
import {MapService} from './gallery/map/map.service';
import {MetaFileSettingsComponent} from './settings/metafiles/metafile.settings.component';
import {ThumbnailLoaderService} from './gallery/thumbnailLoader.service';
import {MapService} from './ui/gallery/map/map.service';
import {MetaFileSettingsComponent} from './ui/settings/metafiles/metafile.settings.component';
import {ThumbnailLoaderService} from './ui/gallery/thumbnailLoader.service';
import {FileSizePipe} from './pipes/FileSizePipe';
import {DuplicateService} from './duplicates/duplicates.service';
import {DuplicateComponent} from './duplicates/duplicates.component';
import {DuplicatesPhotoComponent} from './duplicates/photo/photo.duplicates.component';
import {DuplicateService} from './ui/duplicates/duplicates.service';
import {DuplicateComponent} from './ui/duplicates/duplicates.component';
import {DuplicatesPhotoComponent} from './ui/duplicates/photo/photo.duplicates.component';
import {SeededRandomService} from './model/seededRandom.service';
import {FacesComponent} from './faces/faces.component';
import {FacesService} from './faces/faces.service';
import {FaceComponent} from './faces/face/face.component';
import {FacesComponent} from './ui/faces/faces.component';
import {FacesService} from './ui/faces/faces.service';
import {FaceComponent} from './ui/faces/face/face.component';
import {VersionService} from './model/version.service';
import { DirectoriesComponent } from './ui/gallery/directories/directories.component';
@Injectable()
@ -111,6 +112,11 @@ declare const require: (path: string) => string;
export function translationsFactory(locale: string) {
locale = locale || 'en'; // default to english if no locale
// default locale, nothing to translate
if (locale === 'en') {
return '';
}
return require(`raw-loader!../translate/messages.${locale}.xlf`);
}
@ -179,7 +185,8 @@ export function translationsFactory(locale: string) {
StringifySortingMethod,
FixOrientationPipe,
DurationPipe,
FileSizePipe
FileSizePipe,
DirectoriesComponent
],
providers: [
{provide: UrlSerializer, useClass: CustomUrlSerializer},

View File

@ -1,12 +1,12 @@
import {ModuleWithProviders} from '@angular/core';
import {RouterModule, Routes, UrlMatchResult, UrlSegment} from '@angular/router';
import {LoginComponent} from './login/login.component';
import {GalleryComponent} from './gallery/gallery.component';
import {AdminComponent} from './admin/admin.component';
import {ShareLoginComponent} from './sharelogin/share-login.component';
import {LoginComponent} from './ui/login/login.component';
import {GalleryComponent} from './ui/gallery/gallery.component';
import {AdminComponent} from './ui/admin/admin.component';
import {ShareLoginComponent} from './ui/sharelogin/share-login.component';
import {QueryParams} from '../../common/QueryParams';
import {DuplicateComponent} from './duplicates/duplicates.component';
import {FacesComponent} from './faces/faces.component';
import {DuplicateComponent} from './ui/duplicates/duplicates.component';
import {FacesComponent} from './ui/faces/faces.component';
export function galleryMatcherFunction(
segments: UrlSegment[]): UrlMatchResult | null {

View File

@ -1,31 +0,0 @@
import {Component, Input} from '@angular/core';
import {RouterLink} from '@angular/router';
import {PersonDTO} from '../../../../common/entities/PersonDTO';
import {SearchTypes} from '../../../../common/entities/AutoCompleteItem';
import {DomSanitizer} from '@angular/platform-browser';
@Component({
selector: 'app-face',
templateUrl: './face.component.html',
styleUrls: ['./face.component.css'],
providers: [RouterLink],
})
export class FaceComponent {
@Input() person: PersonDTO;
SearchTypes = SearchTypes;
constructor(private _sanitizer: DomSanitizer) {
}
getSanitizedThUrl() {
return this._sanitizer.bypassSecurityTrustStyle('url(' +
encodeURI('/api/person/' + this.person.name + '/thumbnail')
.replace(/\(/g, '%28')
.replace(/'/g, '%27')
.replace(/\)/g, '%29') + ')');
}
}

View File

@ -1,21 +0,0 @@
import {Component} from '@angular/core';
import {FacesService} from './faces.service';
import {QueryService} from '../model/query.service';
@Component({
selector: 'app-faces',
templateUrl: './faces.component.html',
styleUrls: ['./faces.component.css']
})
export class FacesComponent {
constructor(public facesService: FacesService,
public queryService: QueryService) {
this.facesService.getPersons().catch(console.error);
}
}

View File

@ -1,79 +0,0 @@
import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {DomSanitizer} from '@angular/platform-browser';
import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {RouterLink} from '@angular/router';
import {Utils} from '../../../../common/Utils';
import {Media} from '../Media';
import {Thumbnail, ThumbnailManagerService} from '../thumbnailManager.service';
import {PageHelper} from '../../model/page.helper';
import {QueryService} from '../../model/query.service';
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {MediaDTO} from '../../../../common/entities/MediaDTO';
@Component({
selector: 'app-gallery-directory',
templateUrl: './directory.gallery.component.html',
styleUrls: ['./directory.gallery.component.css'],
providers: [RouterLink],
})
export class GalleryDirectoryComponent implements OnInit, OnDestroy {
@Input() directory: DirectoryDTO;
@ViewChild('dirContainer') container: ElementRef;
thumbnail: Thumbnail = null;
constructor(private thumbnailService: ThumbnailManagerService,
private _sanitizer: DomSanitizer,
public queryService: QueryService) {
}
size: number = null;
public get SamplePhoto(): MediaDTO {
if (this.directory.media.length > 0) {
return this.directory.media[0];
}
return null;
}
getSanitizedThUrl() {
return this._sanitizer.bypassSecurityTrustStyle('url(' +
encodeURI(this.thumbnail.Src)
.replace(/\(/g, '%28')
.replace(/'/g, '%27')
.replace(/\)/g, '%29') + ')');
}
// TODO: implement scroll
isInView(): boolean {
return document.body.scrollTop < this.container.nativeElement.offsetTop + this.container.nativeElement.clientHeight
&& document.body.scrollTop + window.innerHeight > this.container.nativeElement.offsetTop;
}
getDirectoryPath() {
return Utils.concatUrls(this.directory.path, this.directory.name);
}
ngOnDestroy() {
if (this.thumbnail != null) {
this.thumbnail.destroy();
}
}
ngOnInit() {
if (this.directory.media.length > 0) {
this.thumbnail = this.thumbnailService.getThumbnail(new Media(this.SamplePhoto, this.calcSize(), this.calcSize()));
}
}
calcSize() {
if (this.size == null || PageHelper.isScrollYVisible()) {
const size = 220 + 5;
const containerWidth = this.container.nativeElement.parentElement.parentElement.clientWidth;
this.size = containerWidth / Math.round((containerWidth / size));
}
return Math.floor(this.size - 5);
}
}

View File

@ -1,7 +1,7 @@
import {Injectable} from '@angular/core';
import {Router} from '@angular/router';
import {ShareService} from '../gallery/share.service';
import {ShareService} from '../ui/gallery/share.service';
@Injectable()
export class NavigationService {

View File

@ -6,7 +6,7 @@ import {AuthenticationService} from './authentication.service';
import {NetworkService} from './network.service';
import {ErrorDTO} from '../../../../common/entities/Error';
import {VersionService} from '../version.service';
import {ShareService} from '../../gallery/share.service';
import {ShareService} from '../../ui/gallery/share.service';
class MockUserService {
public login(credential: LoginCredential): Promise<UserDTO> {

View File

@ -8,7 +8,7 @@ import {Config} from '../../../../common/config/public/Config';
import {NetworkService} from './network.service';
import {ErrorCodes, ErrorDTO} from '../../../../common/entities/Error';
import {CookieNames} from '../../../../common/CookieNames';
import {ShareService} from '../../gallery/share.service';
import {ShareService} from '../../ui/gallery/share.service';
declare module ServerInject {
export let user: UserDTO;

View File

@ -2,7 +2,6 @@ import {Injectable} from '@angular/core';
import {HttpClient, HttpResponse} from '@angular/common/http';
import {Message} from '../../../../common/entities/Message';
import {SlimLoadingBarService} from 'ng2-slim-loading-bar';
import 'rxjs/Rx';
import {ErrorCodes, ErrorDTO} from '../../../../common/entities/Error';
import {Config} from '../../../../common/config/public/Config';
import {Utils} from '../../../../common/Utils';

View File

@ -4,7 +4,7 @@ import {NetworkService} from './network.service';
import {UserService} from './user.service';
import {LoginCredential} from '../../../../common/entities/LoginCredential';
import {SlimLoadingBarService} from 'ng2-slim-loading-bar';
import {ShareService} from '../../gallery/share.service';
import {ShareService} from '../../ui/gallery/share.service';
import {VersionService} from '../version.service';
class MockShareService {

View File

@ -3,7 +3,7 @@ import {LoginCredential} from '../../../../common/entities/LoginCredential';
import {NetworkService} from './network.service';
import {UserDTO} from '../../../../common/entities/UserDTO';
import {Config} from '../../../../common/config/public/Config';
import {ShareService} from '../../gallery/share.service';
import {ShareService} from '../../ui/gallery/share.service';
@Injectable()
export class UserService {

View File

@ -1,9 +1,9 @@
import {Injectable} from '@angular/core';
import {ShareService} from '../gallery/share.service';
import {ShareService} from '../ui/gallery/share.service';
import {MediaDTO} from '../../../common/entities/MediaDTO';
import {QueryParams} from '../../../common/QueryParams';
import {Utils} from '../../../common/Utils';
import {GalleryService} from '../gallery/gallery.service';
import {GalleryService} from '../ui/gallery/gallery.service';
import {Config} from '../../../common/config/public/Config';
import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';

View File

@ -1,9 +1,9 @@
import {Component, OnInit} from '@angular/core';
import {AuthenticationService} from '../model/network/authentication.service';
import {UserRoles} from '../../../common/entities/UserDTO';
import {NotificationService} from '../model/notification.service';
import {NotificationType} from '../../../common/entities/NotificationDTO';
import {NavigationService} from '../model/navigation.service';
import {AuthenticationService} from '../../model/network/authentication.service';
import {UserRoles} from '../../../../common/entities/UserDTO';
import {NotificationService} from '../../model/notification.service';
import {NotificationType} from '../../../../common/entities/NotificationDTO';
import {NavigationService} from '../../model/navigation.service';
import {I18n} from '@ngx-translate/i18n-polyfill';
@Component({

View File

@ -1,12 +1,12 @@
import {Component, HostListener, OnDestroy} from '@angular/core';
import {DuplicateService} from './duplicates.service';
import {Utils} from '../../../common/Utils';
import {QueryService} from '../model/query.service';
import {DuplicatesDTO} from '../../../common/entities/DuplicatesDTO';
import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {Utils} from '../../../../common/Utils';
import {QueryService} from '../../model/query.service';
import {DuplicatesDTO} from '../../../../common/entities/DuplicatesDTO';
import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {Subscription} from 'rxjs';
import {Config} from '../../../common/config/public/Config';
import {PageHelper} from '../model/page.helper';
import {Config} from '../../../../common/config/public/Config';
import {PageHelper} from '../../model/page.helper';
interface GroupedDuplicate {
name: string;

View File

@ -1,6 +1,6 @@
import {Injectable} from '@angular/core';
import {NetworkService} from '../model/network/network.service';
import {DuplicatesDTO} from '../../../common/entities/DuplicatesDTO';
import {NetworkService} from '../../model/network/network.service';
import {DuplicatesDTO} from '../../../../common/entities/DuplicatesDTO';
import {BehaviorSubject} from 'rxjs';

View File

@ -1,8 +1,8 @@
import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import {MediaDTO} from '../../../../common/entities/MediaDTO';
import {MediaDTO} from '../../../../../common/entities/MediaDTO';
import {Media} from '../../gallery/Media';
import {IconThumbnail, Thumbnail, ThumbnailManagerService} from '../../gallery/thumbnailManager.service';
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {PhotoDTO} from '../../../../../common/entities/PhotoDTO';
import {OrientationTypes} from 'ts-exif-parser';
import {MediaIcon} from '../../gallery/MediaIcon';

View File

@ -4,15 +4,20 @@
<div class="photo-container"
[style.width.px]="200"
[style.height.px]="200">
[style.width.px]="size"
[style.height.px]="size">
<div class="photo"
*ngIf="thumbnail && thumbnail.Available"
[style.background-image]="getSanitizedThUrl()"></div>
<span *ngIf="!thumbnail || !thumbnail.Available" class="oi oi-person no-image"
aria-hidden="true">
</span>
</div>
<!--Info box -->
<div #info class="info">
<div class="info">
<div class="person-name">{{person.name}} ({{person.count}})</div>
</div>

View File

@ -0,0 +1,46 @@
import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import {RouterLink} from '@angular/router';
import {PersonDTO} from '../../../../../common/entities/PersonDTO';
import {SearchTypes} from '../../../../../common/entities/AutoCompleteItem';
import {DomSanitizer} from '@angular/platform-browser';
import {PersonThumbnail, ThumbnailManagerService} from '../../gallery/thumbnailManager.service';
@Component({
selector: 'app-face',
templateUrl: './face.component.html',
styleUrls: ['./face.component.css'],
providers: [RouterLink],
})
export class FaceComponent implements OnInit, OnDestroy {
@Input() person: PersonDTO;
@Input() size: number;
thumbnail: PersonThumbnail = null;
SearchTypes = SearchTypes;
constructor(private thumbnailService: ThumbnailManagerService,
private _sanitizer: DomSanitizer) {
}
ngOnInit() {
this.thumbnail = this.thumbnailService.getPersonThumbnail(this.person);
}
getSanitizedThUrl() {
return this._sanitizer.bypassSecurityTrustStyle('url(' +
encodeURI(this.thumbnail.Src)
.replace(/\(/g, '%28')
.replace(/'/g, '%27')
.replace(/\)/g, '%29') + ')');
}
ngOnDestroy() {
if (this.thumbnail != null) {
this.thumbnail.destroy();
}
}
}

View File

@ -2,6 +2,7 @@
<div body class="container-fluid">
<app-face *ngFor="let person of facesService.persons.value"
[person]="person"></app-face>
[person]="person"
[size]="size"></app-face>
</div>
</app-frame>

View File

@ -0,0 +1,36 @@
import {Component, ElementRef} from '@angular/core';
import {FacesService} from './faces.service';
import {QueryService} from '../../model/query.service';
@Component({
selector: 'app-faces',
templateUrl: './faces.component.html',
styleUrls: ['./faces.component.css']
})
export class FacesComponent {
size: number;
constructor(public facesService: FacesService,
public queryService: QueryService,
private container: ElementRef) {
this.facesService.getPersons().catch(console.error);
}
ngOnChanges() {
this.updateSize();
}
private updateSize() {
const size = 220 + 5;
const containerWidth = this.container.nativeElement.parentElement.clientWidth;
this.size = (containerWidth / Math.round((containerWidth / size))) - 5;
console.log(containerWidth, this.size);
}
}

View File

@ -1,7 +1,7 @@
import {Injectable} from '@angular/core';
import {NetworkService} from '../model/network/network.service';
import {NetworkService} from '../../model/network/network.service';
import {BehaviorSubject} from 'rxjs';
import {PersonDTO} from '../../../common/entities/PersonDTO';
import {PersonDTO} from '../../../../common/entities/PersonDTO';
@Injectable()

View File

@ -1,11 +1,11 @@
import {Component, ViewEncapsulation} from '@angular/core';
import {RouterLink} from '@angular/router';
import {AuthenticationService} from '../model/network/authentication.service';
import {UserDTO, UserRoles} from '../../../common/entities/UserDTO';
import {Config} from '../../../common/config/public/Config';
import {AuthenticationService} from '../../model/network/authentication.service';
import {UserDTO, UserRoles} from '../../../../common/entities/UserDTO';
import {Config} from '../../../../common/config/public/Config';
import {BehaviorSubject} from 'rxjs';
import {NotificationService} from '../model/notification.service';
import {QueryService} from '../model/query.service';
import {NotificationService} from '../../model/notification.service';
import {QueryService} from '../../model/query.service';
@Component({
selector: 'app-frame',

View File

@ -1,7 +1,7 @@
import {Utils} from '../../../common/Utils';
import {Utils} from '../../../../common/Utils';
import {MediaIcon} from './MediaIcon';
import {Config} from '../../../common/config/public/Config';
import {MediaDTO} from '../../../common/entities/MediaDTO';
import {Config} from '../../../../common/config/public/Config';
import {MediaDTO} from '../../../../common/entities/MediaDTO';
export class Media extends MediaIcon {

View File

@ -1,6 +1,6 @@
import {Utils} from '../../../common/Utils';
import {Config} from '../../../common/config/public/Config';
import {MediaDTO} from '../../../common/entities/MediaDTO';
import {Utils} from '../../../../common/Utils';
import {Config} from '../../../../common/config/public/Config';
import {MediaDTO} from '../../../../common/entities/MediaDTO';
export class MediaIcon {

View File

@ -1,12 +1,12 @@
import {Injectable} from '@angular/core';
import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {Utils} from '../../../common/Utils';
import {Config} from '../../../common/config/public/Config';
import {AutoCompleteItem, SearchTypes} from '../../../common/entities/AutoCompleteItem';
import {SearchResultDTO} from '../../../common/entities/SearchResultDTO';
import {MediaDTO} from '../../../common/entities/MediaDTO';
import {SortingMethods} from '../../../common/entities/SortingMethods';
import {VersionService} from '../model/version.service';
import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {Utils} from '../../../../common/Utils';
import {Config} from '../../../../common/config/public/Config';
import {AutoCompleteItem, SearchTypes} from '../../../../common/entities/AutoCompleteItem';
import {SearchResultDTO} from '../../../../common/entities/SearchResultDTO';
import {MediaDTO} from '../../../../common/entities/MediaDTO';
import {SortingMethods} from '../../../../common/entities/SortingMethods';
import {VersionService} from '../../model/version.service';
interface CacheItem<T> {
timestamp: number;

View File

@ -0,0 +1,4 @@
app-gallery-directory {
margin: 2px;
display: inline-block;
}

View File

@ -0,0 +1,4 @@
<app-gallery-directory *ngFor="let directory of directories"
[directory]="directory"
[size]="size"></app-gallery-directory>

View File

@ -0,0 +1,28 @@
import {Component, ElementRef, Input, OnChanges, OnInit} from '@angular/core';
import {DirectoryDTO} from '../../../../../common/entities/DirectoryDTO';
@Component({
selector: 'app-gallery-directories',
templateUrl: './directories.component.html',
styleUrls: ['./directories.component.css']
})
export class DirectoriesComponent implements OnChanges {
@Input() directories: DirectoryDTO[];
size: number;
constructor(private container: ElementRef) {
}
ngOnChanges() {
this.updateSize();
}
private updateSize() {
const size = 220 + 5;
const containerWidth = this.container.nativeElement.parentElement.clientWidth;
this.size = (containerWidth / Math.round((containerWidth / size))) - 5;
console.log(containerWidth, this.size);
}
}

View File

@ -1,13 +1,13 @@
<a #dirContainer class="button btn btn-secondary"
<a class="button btn btn-secondary"
[routerLink]="['/gallery', getDirectoryPath()]"
[queryParams]="queryService.getParams()"
style="display: inline-block;">
<div class="photo-container"
[style.width.px]="calcSize()"
[style.height.px]="calcSize()">
<div [ngClass]="'photo ' + (SamplePhoto ? 'photo-orientation-'+SamplePhoto.metadata.orientation : '')"
[style.width.px]="size"
[style.height.px]="size">
<div [ngClass]="'photo photo-orientation-'+Orientation"
*ngIf="thumbnail && thumbnail.Available"
[style.background-image]="getSanitizedThUrl()"></div>
@ -16,7 +16,7 @@
</span>
</div>
<!--Info box -->
<div #info class="info">
<div class="info">
<div class="directory-name">{{directory.name}}</div>
</div>

View File

@ -0,0 +1,84 @@
import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import {DomSanitizer} from '@angular/platform-browser';
import {DirectoryDTO} from '../../../../../../common/entities/DirectoryDTO';
import {RouterLink} from '@angular/router';
import {Utils} from '../../../../../../common/Utils';
import {Media} from '../../Media';
import {Thumbnail, ThumbnailManagerService} from '../../thumbnailManager.service';
import {QueryService} from '../../../../model/query.service';
import {MediaDTO} from '../../../../../../common/entities/MediaDTO';
import {PhotoDTO} from '../../../../../../common/entities/PhotoDTO';
import {OrientationTypes} from 'ts-exif-parser';
@Component({
selector: 'app-gallery-directory',
templateUrl: './directory.gallery.component.html',
styleUrls: ['./directory.gallery.component.css'],
providers: [RouterLink],
})
export class GalleryDirectoryComponent implements OnInit, OnDestroy {
@Input() directory: DirectoryDTO;
@Input() size: number;
// @ViewChild('dirContainer') container: ElementRef;
thumbnail: Thumbnail = null;
constructor(private thumbnailService: ThumbnailManagerService,
private _sanitizer: DomSanitizer,
public queryService: QueryService) {
}
public get SamplePhoto(): MediaDTO {
if (this.directory.media.length > 0) {
return this.directory.media[0];
}
return null;
}
public get Orientation(): OrientationTypes {
return (this.SamplePhoto && (this.SamplePhoto as PhotoDTO).metadata.orientation)
|| OrientationTypes.TOP_LEFT;
}
getSanitizedThUrl() {
return this._sanitizer.bypassSecurityTrustStyle('url(' +
encodeURI(this.thumbnail.Src)
.replace(/\(/g, '%28')
.replace(/'/g, '%27')
.replace(/\)/g, '%29') + ')');
}
// TODO: implement scroll
/* isInView(): boolean {
return document.body.scrollTop < this.container.nativeElement.offsetTop + this.container.nativeElement.clientHeight
&& document.body.scrollTop + window.innerHeight > this.container.nativeElement.offsetTop;
}*/
getDirectoryPath() {
return Utils.concatUrls(this.directory.path, this.directory.name);
}
ngOnDestroy() {
if (this.thumbnail != null) {
this.thumbnail.destroy();
}
}
ngOnInit() {
if (this.directory.media.length > 0) {
this.thumbnail = this.thumbnailService.getThumbnail(new Media(this.SamplePhoto, this.size, this.size));
}
}
/*
calcSize() {
if (this.size == null || PageHelper.isScrollYVisible()) {
const size = 220 + 5;
const containerWidth = this.container.nativeElement.parentElement.parentElement.clientWidth;
this.size = containerWidth / Math.round((containerWidth / size));
}
return Math.floor(this.size - 5);
}
*/
}

View File

@ -1,5 +1,5 @@
import {Injectable} from '@angular/core';
import {Event} from '../../../common/event/Event';
import {Event} from '../../../../common/event/Event';
declare const document: {
fullscreenElement: any;

View File

@ -11,10 +11,6 @@ app-gallery-map {
margin-left: 2px;
}
app-gallery-directory {
margin: 2px;
display: inline-block;
}
.spinner {
margin-top: 50px;

View File

@ -30,10 +30,8 @@
<div body class="container-fluid" style="width: 100%; padding:0" *ngIf="_galleryService.content.value.directory">
<app-gallery-navbar [directory]="_galleryService.content.value.directory"></app-gallery-navbar>
<div class="directories">
<app-gallery-directory *ngFor="let directory of directories"
[directory]="directory"></app-gallery-directory>
</div>
<app-gallery-directories class="directories" [directories]="directories"></app-gallery-directories>
<app-gallery-map *ngIf="isPhotoWithLocation && mapEnabled"
[photos]="_galleryService.content.value.directory.media"
[metaFiles]="_galleryService.content.value.directory.metaFile"></app-gallery-map>
@ -52,10 +50,8 @@
[photos]="_galleryService.content.value.searchResult.media"
[metaFiles]="_galleryService.content.value.searchResult.metaFile"></app-gallery-map>
<div class="directories">
<app-gallery-directory *ngFor="let directory of directories"
[directory]="directory"></app-gallery-directory>
</div>
<app-gallery-directories class="directories" [directories]="directories"></app-gallery-directories>
<app-gallery-grid [media]="_galleryService.content.value.searchResult.media"
[lightbox]="lightbox"></app-gallery-grid>
</div>

View File

@ -1,22 +1,22 @@
import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {AuthenticationService} from '../model/network/authentication.service';
import {AuthenticationService} from '../../model/network/authentication.service';
import {ActivatedRoute, Params, Router} from '@angular/router';
import {GalleryService} from './gallery.service';
import {GalleryGridComponent} from './grid/grid.gallery.component';
import {SearchTypes} from '../../../common/entities/AutoCompleteItem';
import {Config} from '../../../common/config/public/Config';
import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {SearchResultDTO} from '../../../common/entities/SearchResultDTO';
import {SearchTypes} from '../../../../common/entities/AutoCompleteItem';
import {Config} from '../../../../common/config/public/Config';
import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {SearchResultDTO} from '../../../../common/entities/SearchResultDTO';
import {ShareService} from './share.service';
import {NavigationService} from '../model/navigation.service';
import {UserRoles} from '../../../common/entities/UserDTO';
import {NavigationService} from '../../model/navigation.service';
import {UserRoles} from '../../../../common/entities/UserDTO';
import {interval, Observable, Subscription} from 'rxjs';
import {ContentWrapper} from '../../../common/entities/ConentWrapper';
import {PageHelper} from '../model/page.helper';
import {SortingMethods} from '../../../common/entities/SortingMethods';
import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {QueryParams} from '../../../common/QueryParams';
import {SeededRandomService} from '../model/seededRandom.service';
import {ContentWrapper} from '../../../../common/entities/ConentWrapper';
import {PageHelper} from '../../model/page.helper';
import {SortingMethods} from '../../../../common/entities/SortingMethods';
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {QueryParams} from '../../../../common/QueryParams';
import {SeededRandomService} from '../../model/seededRandom.service';
@Component({
selector: 'app-gallery',
@ -142,10 +142,6 @@ export class GalleryComponent implements OnInit, OnDestroy {
};
private onContentChange = (content: ContentWrapper) => {
const ascdirSorter = (a: DirectoryDTO, b: DirectoryDTO) => {
return a.name.localeCompare(b.name);
};
const tmp = <DirectoryDTO | SearchResultDTO>(content.searchResult || content.directory || {
directories: [],
media: []

View File

@ -1,16 +1,16 @@
import {Injectable} from '@angular/core';
import {NetworkService} from '../model/network/network.service';
import {ContentWrapper} from '../../../common/entities/ConentWrapper';
import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {SearchTypes} from '../../../common/entities/AutoCompleteItem';
import {NetworkService} from '../../model/network/network.service';
import {ContentWrapper} from '../../../../common/entities/ConentWrapper';
import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {SearchTypes} from '../../../../common/entities/AutoCompleteItem';
import {GalleryCacheService} from './cache.gallery.service';
import {BehaviorSubject} from 'rxjs';
import {SharingDTO} from '../../../common/entities/SharingDTO';
import {Config} from '../../../common/config/public/Config';
import {SharingDTO} from '../../../../common/entities/SharingDTO';
import {Config} from '../../../../common/config/public/Config';
import {ShareService} from './share.service';
import {NavigationService} from '../model/navigation.service';
import {SortingMethods} from '../../../common/entities/SortingMethods';
import {QueryParams} from '../../../common/QueryParams';
import {NavigationService} from '../../model/navigation.service';
import {SortingMethods} from '../../../../common/entities/SortingMethods';
import {QueryParams} from '../../../../common/QueryParams';
@Injectable()

View File

@ -1,8 +1,8 @@
import {Media} from '../Media';
import {MediaDTO} from '../../../../common/entities/MediaDTO';
import {MediaDTO} from '../../../../../common/entities/MediaDTO';
import {OrientationTypes} from 'ts-exif-parser';
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {VideoDTO} from '../../../../common/entities/VideoDTO';
import {PhotoDTO} from '../../../../../common/entities/PhotoDTO';
import {VideoDTO} from '../../../../../common/entities/VideoDTO';
export class GridMedia extends Media {

View File

@ -1,5 +1,5 @@
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {MediaDTO} from '../../../../common/entities/MediaDTO';
import {PhotoDTO} from '../../../../../common/entities/PhotoDTO';
import {MediaDTO} from '../../../../../common/entities/MediaDTO';
export class GridRowBuilder {

View File

@ -12,22 +12,22 @@ import {
ViewChild,
ViewChildren
} from '@angular/core';
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {PhotoDTO} from '../../../../../common/entities/PhotoDTO';
import {GridRowBuilder} from './GridRowBuilder';
import {GalleryLightboxComponent} from '../lightbox/lightbox.gallery.component';
import {GridMedia} from './GridMedia';
import {GalleryPhotoComponent} from './photo/photo.grid.gallery.component';
import {OverlayService} from '../overlay.service';
import {Config} from '../../../../common/config/public/Config';
import {PageHelper} from '../../model/page.helper';
import {Config} from '../../../../../common/config/public/Config';
import {PageHelper} from '../../../model/page.helper';
import {Subscription} from 'rxjs';
import {ActivatedRoute, Params, Router} from '@angular/router';
import {QueryService} from '../../model/query.service';
import {QueryService} from '../../../model/query.service';
import {GalleryService} from '../gallery.service';
import {SortingMethods} from '../../../../common/entities/SortingMethods';
import {MediaDTO} from '../../../../common/entities/MediaDTO';
import {QueryParams} from '../../../../common/QueryParams';
import {SeededRandomService} from '../../model/seededRandom.service';
import {SortingMethods} from '../../../../../common/entities/SortingMethods';
import {MediaDTO} from '../../../../../common/entities/MediaDTO';
import {QueryParams} from '../../../../../common/QueryParams';
import {SeededRandomService} from '../../../model/seededRandom.service';
@Component({
selector: 'app-gallery-grid',

View File

@ -1,12 +1,12 @@
import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {Dimension, IRenderable} from '../../../model/IRenderable';
import {Dimension, IRenderable} from '../../../../model/IRenderable';
import {GridMedia} from '../GridMedia';
import {SearchTypes} from '../../../../../common/entities/AutoCompleteItem';
import {SearchTypes} from '../../../../../../common/entities/AutoCompleteItem';
import {RouterLink} from '@angular/router';
import {Thumbnail, ThumbnailManagerService} from '../../thumbnailManager.service';
import {Config} from '../../../../../common/config/public/Config';
import {PageHelper} from '../../../model/page.helper';
import {PhotoDTO, PhotoMetadata} from '../../../../../common/entities/PhotoDTO';
import {Config} from '../../../../../../common/config/public/Config';
import {PageHelper} from '../../../../model/page.helper';
import {PhotoDTO, PhotoMetadata} from '../../../../../../common/entities/PhotoDTO';
@Component({
selector: 'app-gallery-grid-photo',

View File

@ -1,10 +1,10 @@
import {Component, EventEmitter, Input, Output} from '@angular/core';
import {CameraMetadata, PhotoDTO, PositionMetaData} from '../../../../../common/entities/PhotoDTO';
import {Config} from '../../../../../common/config/public/Config';
import {MediaDTO} from '../../../../../common/entities/MediaDTO';
import {VideoDTO, VideoMetadata} from '../../../../../common/entities/VideoDTO';
import {Utils} from '../../../../../common/Utils';
import {QueryService} from '../../../model/query.service';
import {CameraMetadata, PhotoDTO, PositionMetaData} from '../../../../../../common/entities/PhotoDTO';
import {Config} from '../../../../../../common/config/public/Config';
import {MediaDTO} from '../../../../../../common/entities/MediaDTO';
import {VideoDTO, VideoMetadata} from '../../../../../../common/entities/VideoDTO';
import {Utils} from '../../../../../../common/Utils';
import {QueryService} from '../../../../model/query.service';
import {MapService} from '../../map/map.service';
@Component({

View File

@ -9,7 +9,7 @@ import {
ViewChild
} from '@angular/core';
import {GalleryPhotoComponent} from '../grid/photo/photo.grid.gallery.component';
import {Dimension} from '../../model/IRenderable';
import {Dimension} from '../../../model/IRenderable';
import {FullScreenService} from '../fullscreen.service';
import {OverlayService} from '../overlay.service';
import {animate, AnimationBuilder, AnimationPlayer, style} from '@angular/animations';
@ -17,12 +17,12 @@ import {GalleryLightboxMediaComponent} from './media/media.lightbox.gallery.comp
import {Observable, Subscription, timer} from 'rxjs';
import {filter} from 'rxjs/operators';
import {ActivatedRoute, Params, Router} from '@angular/router';
import {PageHelper} from '../../model/page.helper';
import {QueryService} from '../../model/query.service';
import {MediaDTO} from '../../../../common/entities/MediaDTO';
import {QueryParams} from '../../../../common/QueryParams';
import {PageHelper} from '../../../model/page.helper';
import {QueryService} from '../../../model/query.service';
import {MediaDTO} from '../../../../../common/entities/MediaDTO';
import {QueryParams} from '../../../../../common/QueryParams';
import {GalleryService} from '../gallery.service';
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {PhotoDTO} from '../../../../../common/entities/PhotoDTO';
export enum LightboxStates {
Open = 1,

View File

@ -1,7 +1,7 @@
import {Component, ElementRef, Input, Output, OnChanges, ViewChild} from '@angular/core';
import {GridMedia} from '../../grid/GridMedia';
import {FixOrientationPipe} from '../../FixOrientationPipe';
import {MediaDTO} from '../../../../../common/entities/MediaDTO';
import {FixOrientationPipe} from '../../../../pipes/FixOrientationPipe';
import {MediaDTO} from '../../../../../../common/entities/MediaDTO';
import {DomSanitizer, SafeStyle} from '@angular/platform-browser';
@Component({

View File

@ -1,20 +1,20 @@
import {Component, ElementRef, HostListener, Input, OnChanges, ViewChild, AfterViewInit} from '@angular/core';
import {PhotoDTO} from '../../../../../common/entities/PhotoDTO';
import {Dimension} from '../../../model/IRenderable';
import {PhotoDTO} from '../../../../../../common/entities/PhotoDTO';
import {Dimension} from '../../../../model/IRenderable';
import {FullScreenService} from '../../fullscreen.service';
import {IconThumbnail, Thumbnail, ThumbnailManagerService} from '../../thumbnailManager.service';
import {MediaIcon} from '../../MediaIcon';
import {Media} from '../../Media';
import {PageHelper} from '../../../model/page.helper';
import {PageHelper} from '../../../../model/page.helper';
import {OrientationTypes} from 'ts-exif-parser';
import {MediaDTO} from '../../../../../common/entities/MediaDTO';
import {FileDTO} from '../../../../../common/entities/FileDTO';
import {Utils} from '../../../../../common/Utils';
import {Config} from '../../../../../common/config/public/Config';
import {MediaDTO} from '../../../../../../common/entities/MediaDTO';
import {FileDTO} from '../../../../../../common/entities/FileDTO';
import {Utils} from '../../../../../../common/Utils';
import {Config} from '../../../../../../common/config/public/Config';
import {MapService} from '../map.service';
import {LatLng, Point} from 'leaflet';
import {MapComponent} from '@yaga/leaflet-ng2';
import {FixOrientationPipe} from '../../FixOrientationPipe';
import {FixOrientationPipe} from '../../../../pipes/FixOrientationPipe';
@Component({
selector: 'app-gallery-map-lightbox',

View File

@ -1,8 +1,8 @@
import {Component, ElementRef, Input, OnChanges, ViewChild, AfterViewInit} from '@angular/core';
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {Dimension, IRenderable} from '../../model/IRenderable';
import {PhotoDTO} from '../../../../../common/entities/PhotoDTO';
import {Dimension, IRenderable} from '../../../model/IRenderable';
import {GalleryMapLightboxComponent} from './lightbox/lightbox.map.gallery.component';
import {FileDTO} from '../../../../common/entities/FileDTO';
import {FileDTO} from '../../../../../common/entities/FileDTO';
import {MapService} from './map.service';
import {MapComponent} from '@yaga/leaflet-ng2';

View File

@ -1,9 +1,9 @@
import {Injectable} from '@angular/core';
import {NetworkService} from '../../model/network/network.service';
import {FileDTO} from '../../../../common/entities/FileDTO';
import {Utils} from '../../../../common/Utils';
import {Config} from '../../../../common/config/public/Config';
import {ClientConfig} from '../../../../common/config/public/ConfigClass';
import {NetworkService} from '../../../model/network/network.service';
import {FileDTO} from '../../../../../common/entities/FileDTO';
import {Utils} from '../../../../../common/Utils';
import {Config} from '../../../../../common/config/public/Config';
import {ClientConfig} from '../../../../../common/config/public/ConfigClass';
@Injectable()
export class MapService {

View File

@ -1,16 +1,16 @@
import {Component, HostListener, Input, OnChanges} from '@angular/core';
import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {DirectoryDTO} from '../../../../../common/entities/DirectoryDTO';
import {Router, RouterLink} from '@angular/router';
import {UserDTO} from '../../../../common/entities/UserDTO';
import {AuthenticationService} from '../../model/network/authentication.service';
import {UserDTO} from '../../../../../common/entities/UserDTO';
import {AuthenticationService} from '../../../model/network/authentication.service';
import {I18n} from '@ngx-translate/i18n-polyfill';
import {QueryService} from '../../model/query.service';
import {QueryService} from '../../../model/query.service';
import {GalleryService} from '../gallery.service';
import {Utils} from '../../../../common/Utils';
import {SortingMethods} from '../../../../common/entities/SortingMethods';
import {Config} from '../../../../common/config/public/Config';
import {SearchResultDTO} from '../../../../common/entities/SearchResultDTO';
import {SearchTypes} from '../../../../common/entities/AutoCompleteItem';
import {Utils} from '../../../../../common/Utils';
import {SortingMethods} from '../../../../../common/entities/SortingMethods';
import {Config} from '../../../../../common/config/public/Config';
import {SearchResultDTO} from '../../../../../common/entities/SearchResultDTO';
import {SearchTypes} from '../../../../../common/entities/AutoCompleteItem';
@Component({
selector: 'app-gallery-navbar',

View File

@ -1,6 +1,6 @@
import {Injectable} from '@angular/core';
import {Event} from '../../../common/event/Event';
import {PageHelper} from '../model/page.helper';
import {Event} from '../../../../common/event/Event';
import {PageHelper} from '../../model/page.helper';
@Injectable()
export class OverlayService {

View File

@ -1,15 +1,15 @@
import {Component, OnDestroy, OnInit, TemplateRef} from '@angular/core';
import {Utils} from '../../../../common/Utils';
import {Utils} from '../../../../../common/Utils';
import {GalleryService} from '../gallery.service';
import {ContentWrapper} from '../../../../common/entities/ConentWrapper';
import {Config} from '../../../../common/config/public/Config';
import {NotificationService} from '../../model/notification.service';
import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {ContentWrapper} from '../../../../../common/entities/ConentWrapper';
import {Config} from '../../../../../common/config/public/Config';
import {NotificationService} from '../../../model/notification.service';
import {DirectoryDTO} from '../../../../../common/entities/DirectoryDTO';
import {I18n} from '@ngx-translate/i18n-polyfill';
import {BsModalService} from 'ngx-bootstrap/modal';
import {BsModalRef} from 'ngx-bootstrap/modal/bs-modal-ref.service';
import {OrientationType, RandomQueryDTO} from '../../../../common/entities/RandomQueryDTO';
import {NetworkService} from '../../model/network/network.service';
import {OrientationType, RandomQueryDTO} from '../../../../../common/entities/RandomQueryDTO';
import {NetworkService} from '../../../model/network/network.service';
import {Subscription} from 'rxjs';

View File

@ -1,6 +1,6 @@
import {Injectable} from '@angular/core';
import {NetworkService} from '../../model/network/network.service';
import {AutoCompleteItem} from '../../../../common/entities/AutoCompleteItem';
import {NetworkService} from '../../../model/network/network.service';
import {AutoCompleteItem} from '../../../../../common/entities/AutoCompleteItem';
import {GalleryCacheService} from '../cache.gallery.service';
@Injectable()

View File

@ -1,12 +1,12 @@
import {Component, OnDestroy} from '@angular/core';
import {AutoCompleteService} from './autocomplete.service';
import {AutoCompleteItem, SearchTypes} from '../../../../common/entities/AutoCompleteItem';
import {AutoCompleteItem, SearchTypes} from '../../../../../common/entities/AutoCompleteItem';
import {ActivatedRoute, Params, RouterLink} from '@angular/router';
import {GalleryService} from '../gallery.service';
import {Subscription} from 'rxjs';
import {Config} from '../../../../common/config/public/Config';
import {NavigationService} from '../../model/navigation.service';
import {QueryParams} from '../../../../common/QueryParams';
import {Config} from '../../../../../common/config/public/Config';
import {NavigationService} from '../../../model/navigation.service';
import {QueryParams} from '../../../../../common/QueryParams';
@Component({
selector: 'app-gallery-search',

View File

@ -1,10 +1,10 @@
import {Injectable} from '@angular/core';
import {NetworkService} from '../model/network/network.service';
import {CreateSharingDTO, SharingDTO} from '../../../common/entities/SharingDTO';
import {NetworkService} from '../../model/network/network.service';
import {CreateSharingDTO, SharingDTO} from '../../../../common/entities/SharingDTO';
import {Router, RoutesRecognized} from '@angular/router';
import {BehaviorSubject, Observable} from 'rxjs';
import {QueryParams} from '../../../common/QueryParams';
import {UserDTO} from '../../../common/entities/UserDTO';
import {QueryParams} from '../../../../common/QueryParams';
import {UserDTO} from '../../../../common/entities/UserDTO';
@Injectable()
export class ShareService {

View File

@ -1,12 +1,12 @@
import {Component, OnDestroy, OnInit, TemplateRef} from '@angular/core';
import {Utils} from '../../../../common/Utils';
import {Utils} from '../../../../../common/Utils';
import {ShareService} from '../share.service';
import {GalleryService} from '../gallery.service';
import {ContentWrapper} from '../../../../common/entities/ConentWrapper';
import {SharingDTO} from '../../../../common/entities/SharingDTO';
import {Config} from '../../../../common/config/public/Config';
import {NotificationService} from '../../model/notification.service';
import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {ContentWrapper} from '../../../../../common/entities/ConentWrapper';
import {SharingDTO} from '../../../../../common/entities/SharingDTO';
import {Config} from '../../../../../common/config/public/Config';
import {NotificationService} from '../../../model/notification.service';
import {DirectoryDTO} from '../../../../../common/entities/DirectoryDTO';
import {I18n} from '@ngx-translate/i18n-polyfill';
import {BsModalService} from 'ngx-bootstrap/modal';
import {BsModalRef} from 'ngx-bootstrap/modal/bs-modal-ref.service';

View File

@ -2,9 +2,8 @@ import {Injectable} from '@angular/core';
import {GalleryCacheService} from './cache.gallery.service';
import {Media} from './Media';
import {MediaIcon} from './MediaIcon';
import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {Config} from '../../../common/config/public/Config';
import {MediaDTO} from '../../../common/entities/MediaDTO';
import {Config} from '../../../../common/config/public/Config';
import {Person, PersonDTO} from '../../../../common/entities/PersonDTO';
export enum ThumbnailLoadingPriority {
extraHigh = 4, high = 3, medium = 2, low = 1
@ -36,7 +35,6 @@ export class ThumbnailLoaderService {
const curImg = new Image();
curImg.onload = () => {
task.onLoaded();
this.galleryCacheService.mediaUpdated(task.media);
task.taskEntities.forEach((te: ThumbnailTaskEntity) => te.listener.onLoad());
this.taskReady(task);
@ -74,73 +72,71 @@ export class ThumbnailLoaderService {
}
loadIcon(photo: MediaIcon, priority: ThumbnailLoadingPriority, listener: ThumbnailLoadingListener): ThumbnailTaskEntity {
let thTask: ThumbnailTask = null;
// is image already qued?
for (let i = 0; i < this.que.length; i++) {
if (this.que[i].path === photo.getIconPath()) {
thTask = this.que[i];
break;
}
}
if (thTask == null) {
thTask = {
media: photo.media,
inProgress: false,
taskEntities: [],
onLoaded: () => {
photo.iconLoaded();
},
path: photo.getIconPath()
};
this.que.push(thTask);
}
const thumbnailTaskEntity = {priority: priority, listener: listener, parentTask: thTask};
thTask.taskEntities.push(thumbnailTaskEntity);
if (thTask.inProgress === true) {
listener.onStartedLoading();
}
loadIcon(media: MediaIcon, priority: ThumbnailLoadingPriority, listener: ThumbnailLoadingListener): ThumbnailTaskEntity {
setTimeout(this.run, 0);
return thumbnailTaskEntity;
return this.load(media.getIconPath(),
() => {
media.iconLoaded();
this.galleryCacheService.mediaUpdated(media.media);
},
priority,
listener);
}
loadImage(media: Media, priority: ThumbnailLoadingPriority, listener: ThumbnailLoadingListener): ThumbnailTaskEntity {
return this.load(media.getThumbnailPath(),
() => {
media.thumbnailLoaded();
this.galleryCacheService.mediaUpdated(media.media);
},
priority,
listener);
}
loadPersonThumbnail(person: PersonDTO, priority: ThumbnailLoadingPriority, listener: ThumbnailLoadingListener): ThumbnailTaskEntity {
return this.load(Person.getThumbnailUrl(person),
() => {
},
priority,
listener);
}
private load(path: string,
onLoaded: () => void,
priority: ThumbnailLoadingPriority,
listener: ThumbnailLoadingListener): ThumbnailTaskEntity {
let thTask: ThumbnailTask = null;
// is image already qued?
// is image already queued?
for (let i = 0; i < this.que.length; i++) {
if (this.que[i].path === media.getThumbnailPath()) {
if (this.que[i].path === path) {
thTask = this.que[i];
break;
}
}
if (thTask == null) {
thTask = {
media: media.media,
inProgress: false,
taskEntities: [],
onLoaded: () => {
media.thumbnailLoaded();
},
path: media.getThumbnailPath()
onLoaded: onLoaded,
path: path
};
this.que.push(thTask);
}
const thumbnailTaskEntity = {priority: priority, listener: listener, parentTask: thTask};
// add to poolTask
thTask.taskEntities.push(thumbnailTaskEntity);
if (thTask.inProgress === true) {
listener.onStartedLoading();
}
setTimeout(this.run, 0);
return thumbnailTaskEntity;
}
private getNextTask(): ThumbnailTask {
@ -194,10 +190,9 @@ export interface ThumbnailTaskEntity {
}
interface ThumbnailTask {
media: MediaDTO;
inProgress: boolean;
taskEntities: Array<ThumbnailTaskEntity>;
path: string;
onLoaded: Function;
onLoaded: () => void;
}

View File

@ -2,6 +2,7 @@ import {Injectable} from '@angular/core';
import {ThumbnailLoaderService, ThumbnailLoadingListener, ThumbnailLoadingPriority, ThumbnailTaskEntity} from './thumbnailLoader.service';
import {Media} from './Media';
import {MediaIcon} from './MediaIcon';
import {Person, PersonDTO} from '../../../../common/entities/PersonDTO';
@Injectable()
@ -19,18 +20,22 @@ export class ThumbnailManagerService {
return new Thumbnail(photo, this.thumbnailLoader, false);
}
public getIcon(photo: MediaIcon) {
return new IconThumbnail(photo, this.thumbnailLoader);
}
public getPersonThumbnail(person: PersonDTO): PersonThumbnail {
return new PersonThumbnail(person, this.thumbnailLoader);
}
}
export abstract class ThumbnailBase {
public loading = false;
protected available = false;
protected src: string = null;
public loading = false;
protected error = false;
protected onLoad: Function = null;
protected thumbnailTask: ThumbnailTaskEntity = null;
@ -71,6 +76,64 @@ export abstract class ThumbnailBase {
}
export class PersonThumbnail extends ThumbnailBase {
constructor(private person: PersonDTO, thumbnailService: ThumbnailLoaderService) {
super(thumbnailService);
this.src = '';
this.error = false;
if (this.person.readyThumbnail) {
this.src = Person.getThumbnailUrl(person);
this.available = true;
if (this.onLoad) {
this.onLoad();
}
return;
}
setTimeout(() => {
const listener: ThumbnailLoadingListener = {
onStartedLoading: () => { // onLoadStarted
this.loading = true;
},
onLoad: () => {// onLoaded
this.src = Person.getThumbnailUrl(person);
if (this.onLoad) {
this.onLoad();
}
this.available = true;
this.loading = false;
this.thumbnailTask = null;
},
onError: () => {// onError
this.thumbnailTask = null;
this.loading = false;
this.error = true;
}
};
this.thumbnailTask = this.thumbnailService.loadPersonThumbnail(person, ThumbnailLoadingPriority.high, listener);
}, 0);
}
set Visible(visible: boolean) {
if (!this.thumbnailTask) {
return;
}
if (visible === true) {
this.thumbnailTask.priority = ThumbnailLoadingPriority.high;
} else {
this.thumbnailTask.priority = ThumbnailLoadingPriority.medium;
}
}
}
export class IconThumbnail extends ThumbnailBase {
constructor(private media: MediaIcon, thumbnailService: ThumbnailLoaderService) {

Some files were not shown because too many files have changed in this diff Show More