You've already forked pigallery2
							
							
				mirror of
				https://github.com/bpatrik/pigallery2.git
				synced 2025-10-30 23:57:43 +02:00 
			
		
		
		
	ui directory refactoring
adding thumbnail loader for faces
This commit is contained in:
		| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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(); | ||||
|   | ||||
| @@ -18,4 +18,7 @@ export class PersonEntry implements PersonDTO { | ||||
|  | ||||
|   @OneToMany(type => FaceRegionEntry, faceRegion => faceRegion.person) | ||||
|   public faces: FaceRegionEntry[]; | ||||
|  | ||||
|  | ||||
|   readyThumbnail: boolean; | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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'; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -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'; | ||||
|  | ||||
|   | ||||
| @@ -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}, | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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') + ')'); | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -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); | ||||
|   } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -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); | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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> { | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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'; | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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'; | ||||
|  | ||||
|   | ||||
| @@ -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({ | ||||
| @@ -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; | ||||
| @@ -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'; | ||||
| 
 | ||||
| 
 | ||||
| @@ -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'; | ||||
| 
 | ||||
| @@ -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> | ||||
							
								
								
									
										46
									
								
								frontend/app/ui/faces/face/face.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								frontend/app/ui/faces/face/face.component.ts
									
									
									
									
									
										Normal 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(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -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> | ||||
							
								
								
									
										36
									
								
								frontend/app/ui/faces/faces.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								frontend/app/ui/faces/faces.component.ts
									
									
									
									
									
										Normal 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); | ||||
|   } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -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() | ||||
| @@ -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', | ||||
| @@ -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 { | ||||
| 
 | ||||
| @@ -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 { | ||||
| 
 | ||||
| @@ -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; | ||||
| @@ -0,0 +1,4 @@ | ||||
| app-gallery-directory { | ||||
|   margin: 2px; | ||||
|   display: inline-block; | ||||
| } | ||||
| @@ -0,0 +1,4 @@ | ||||
| <app-gallery-directory *ngFor="let directory of directories" | ||||
|                        [directory]="directory" | ||||
|                        [size]="size"></app-gallery-directory> | ||||
|  | ||||
							
								
								
									
										28
									
								
								frontend/app/ui/gallery/directories/directories.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								frontend/app/ui/gallery/directories/directories.component.ts
									
									
									
									
									
										Normal 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); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -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> | ||||
| @@ -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); | ||||
|     } | ||||
|   */ | ||||
| } | ||||
|  | ||||
| @@ -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; | ||||
| @@ -11,10 +11,6 @@ app-gallery-map { | ||||
|   margin-left: 2px; | ||||
| } | ||||
| 
 | ||||
| app-gallery-directory { | ||||
|   margin: 2px; | ||||
|   display: inline-block; | ||||
| } | ||||
| 
 | ||||
| .spinner { | ||||
|   margin-top: 50px; | ||||
| @@ -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> | ||||
| @@ -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: [] | ||||
| @@ -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() | ||||
| @@ -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 { | ||||
| 
 | ||||
| @@ -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 { | ||||
| 
 | ||||
| @@ -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', | ||||
| @@ -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', | ||||
| @@ -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({ | ||||
| @@ -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, | ||||
| @@ -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({ | ||||
| @@ -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', | ||||
| @@ -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'; | ||||
| 
 | ||||
| @@ -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 { | ||||
| @@ -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', | ||||
| @@ -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 { | ||||
| @@ -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'; | ||||
| 
 | ||||
| 
 | ||||
| @@ -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() | ||||
| @@ -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', | ||||
| @@ -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 { | ||||
| @@ -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'; | ||||
| @@ -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; | ||||
| } | ||||
| 
 | ||||
| @@ -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
		Reference in New Issue
	
	Block a user