1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2025-01-14 14:43:17 +08:00

improving searching and search related lightbox navigation

This commit is contained in:
Patrik J. Braun 2018-12-04 21:43:07 +01:00
parent 77b66c49c9
commit 037c366e80
14 changed files with 124 additions and 78 deletions

View File

@ -184,7 +184,6 @@ export class DiskMangerWorker {
const data = Buffer.allocUnsafe(Config.Server.photoMetadataSize); const data = Buffer.allocUnsafe(Config.Server.photoMetadataSize);
fs.read(fd, data, 0, Config.Server.photoMetadataSize, 0, (err) => { fs.read(fd, data, 0, Config.Server.photoMetadataSize, 0, (err) => {
// fs.readFile(fullPath, (err, data) => {
if (err) { if (err) {
fs.closeSync(fd); fs.closeSync(fd);
return reject({file: fullPath, error: err}); return reject({file: fullPath, error: err});
@ -234,7 +233,6 @@ export class DiskMangerWorker {
metadata.orientation = exif.tags.Orientation; metadata.orientation = exif.tags.Orientation;
} }
console.log(exif);
if (exif.imageSize) { if (exif.imageSize) {
metadata.size = <MediaDimension>{width: exif.imageSize.width, height: exif.imageSize.height}; metadata.size = <MediaDimension>{width: exif.imageSize.width, height: exif.imageSize.height};
} else if (exif.tags.RelatedImageWidth && exif.tags.RelatedImageHeight) { } else if (exif.tags.RelatedImageWidth && exif.tags.RelatedImageHeight) {

View File

@ -24,6 +24,10 @@ export class MediaIcon {
return this.media.readyIcon; return this.media.readyIcon;
} }
getRelativePath(): string {
return Utils.concatUrls(this.media.directory.path, this.media.directory.name, this.media.name);
}
getIconPath() { getIconPath() {
return Utils.concatUrls(Config.Client.urlBase, return Utils.concatUrls(Config.Client.urlBase,
'/api/gallery/content/', '/api/gallery/content/',
@ -37,7 +41,7 @@ export class MediaIcon {
} }
equals(other: PhotoDTO | MediaIcon): boolean { equals(other: MediaDTO | MediaIcon): boolean {
// is gridphoto // is gridphoto
if (other instanceof MediaIcon) { if (other instanceof MediaIcon) {
return this.media.directory.path === other.media.directory.path && return this.media.directory.path === other.media.directory.path &&

View File

@ -97,7 +97,7 @@ export class GalleryCacheService {
public getSearch(text: string, type?: SearchTypes): SearchResultDTO { public getSearch(text: string, type?: SearchTypes): SearchResultDTO {
let key = GalleryCacheService.SEARCH_PREFIX + text; let key = GalleryCacheService.SEARCH_PREFIX + text;
if (typeof type !== 'undefined') { if (typeof type !== 'undefined' && type !== null) {
key += GalleryCacheService.SEARCH_TYPE_PREFIX + type; key += GalleryCacheService.SEARCH_TYPE_PREFIX + type;
} }
const tmp = localStorage.getItem(key); const tmp = localStorage.getItem(key);
@ -118,7 +118,7 @@ export class GalleryCacheService {
item: searchResult item: searchResult
}; };
let key = GalleryCacheService.SEARCH_PREFIX + text; let key = GalleryCacheService.SEARCH_PREFIX + text;
if (typeof type !== 'undefined') { if (typeof type !== 'undefined' && type !== null) {
key += GalleryCacheService.SEARCH_TYPE_PREFIX + type; key += GalleryCacheService.SEARCH_TYPE_PREFIX + type;
} }
try { try {

View File

@ -37,7 +37,7 @@
<app-gallery-map *ngIf="isPhotoWithLocation && mapEnabled" <app-gallery-map *ngIf="isPhotoWithLocation && mapEnabled"
[photos]="_galleryService.content.value.directory.media" [photos]="_galleryService.content.value.directory.media"
[metaFiles]="_galleryService.content.value.directory.metaFile"></app-gallery-map> [metaFiles]="_galleryService.content.value.directory.metaFile"></app-gallery-map>
<app-gallery-grid [photos]="_galleryService.content.value.directory.media" <app-gallery-grid [media]="_galleryService.content.value.directory.media"
[lightbox]="lightbox"></app-gallery-grid> [lightbox]="lightbox"></app-gallery-grid>
</div> </div>
<!-- Search--> <!-- Search-->
@ -56,7 +56,7 @@
<app-gallery-directory *ngFor="let directory of directories" <app-gallery-directory *ngFor="let directory of directories"
[directory]="directory"></app-gallery-directory> [directory]="directory"></app-gallery-directory>
</div> </div>
<app-gallery-grid [photos]="_galleryService.content.value.searchResult.media" <app-gallery-grid [media]="_galleryService.content.value.searchResult.media"
[lightbox]="lightbox"></app-gallery-grid> [lightbox]="lightbox"></app-gallery-grid>
</div> </div>

View File

@ -76,14 +76,13 @@ export class GalleryComponent implements OnInit, OnDestroy {
const searchText = params['searchText']; const searchText = params['searchText'];
if (searchText && searchText !== '') { if (searchText && searchText !== '') {
const typeString: string = params['type']; const typeString: string = params['type'];
let type: SearchTypes = null;
if (typeString && typeString !== '') { if (typeString && typeString !== '') {
const type: SearchTypes = <any>SearchTypes[<any>typeString]; type = <any>SearchTypes[<any>typeString];
this._galleryService.search(searchText, type).catch(console.error);
return;
} }
this._galleryService.search(searchText).catch(console.error); this._galleryService.search(searchText, type).catch(console.error);
return; return;
} }

View File

@ -1,4 +1,5 @@
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {Location} from '@angular/common';
import {NetworkService} from '../model/network/network.service'; import {NetworkService} from '../model/network/network.service';
import {ContentWrapper} from '../../../common/entities/ConentWrapper'; import {ContentWrapper} from '../../../common/entities/ConentWrapper';
import {DirectoryDTO} from '../../../common/entities/DirectoryDTO'; import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
@ -16,16 +17,25 @@ import {QueryParams} from '../../../common/QueryParams';
@Injectable() @Injectable()
export class GalleryService { export class GalleryService {
public content: BehaviorSubject<ContentWrapper>; public content: BehaviorSubject<ContentWrapper>;
public sorting: BehaviorSubject<SortingMethods>; public sorting: BehaviorSubject<SortingMethods>;
private lastDirectory: DirectoryDTO; private lastDirectory: DirectoryDTO;
private searchId: any; private searchId: any;
private ongoingSearch: {
text: string,
type: SearchTypes
} = null;
private ongoingInstantSearch: {
text: string,
type: SearchTypes
} = null;
private runInstantSearchFor: string;
constructor(private networkService: NetworkService, constructor(private networkService: NetworkService,
private galleryCacheService: GalleryCacheService, private galleryCacheService: GalleryCacheService,
private _shareService: ShareService, private _shareService: ShareService,
private navigationService: NavigationService) { private navigationService: NavigationService,
private location: Location) {
this.content = new BehaviorSubject<ContentWrapper>(new ContentWrapper()); this.content = new BehaviorSubject<ContentWrapper>(new ContentWrapper());
this.sorting = new BehaviorSubject<SortingMethods>(Config.Client.Other.defaultPhotoSortingMethod); this.sorting = new BehaviorSubject<SortingMethods>(Config.Client.Other.defaultPhotoSortingMethod);
} }
@ -85,11 +95,11 @@ export class GalleryService {
}).catch((e) => { }).catch((e) => {
console.error(e); console.error(e);
this.navigationService.toGallery(); this.navigationService.toGallery().catch(console.error);
}); });
} }
public async search(text: string, type?: SearchTypes): Promise<ContentWrapper> { public async search(text: string, type?: SearchTypes): Promise<void> {
if (this.searchId != null) { if (this.searchId != null) {
clearTimeout(this.searchId); clearTimeout(this.searchId);
} }
@ -97,22 +107,32 @@ export class GalleryService {
return null; return null;
} }
this.ongoingSearch = {text: text, type: type};
this.content.next(new ContentWrapper()); this.content.next(new ContentWrapper());
const cw = new ContentWrapper(); const cw = new ContentWrapper();
cw.searchResult = this.galleryCacheService.getSearch(text, type); cw.searchResult = this.galleryCacheService.getSearch(text, type);
if (cw.searchResult == null) { if (cw.searchResult == null) {
if (this.runInstantSearchFor === text && !type) {
await this.instantSearch(text, type);
return;
}
const params: { type?: SearchTypes } = {}; const params: { type?: SearchTypes } = {};
if (typeof type !== 'undefined') { if (typeof type !== 'undefined' && type !== null) {
params['type'] = type; params['type'] = type;
} }
cw.searchResult = (await this.networkService.getJson<ContentWrapper>('/search/' + text, params)).searchResult; cw.searchResult = (await this.networkService.getJson<ContentWrapper>('/search/' + text, params)).searchResult;
if (this.ongoingSearch &&
(this.ongoingSearch.text !== text || this.ongoingSearch.type !== type)) {
return;
}
this.galleryCacheService.setSearch(text, type, cw.searchResult); this.galleryCacheService.setSearch(text, type, cw.searchResult);
} }
this.content.next(cw); this.content.next(cw);
return cw;
} }
public async instantSearch(text: string): Promise<ContentWrapper> { public async instantSearch(text: string, type?: SearchTypes): Promise<ContentWrapper> {
if (text === null || text === '' || text.trim() === '.') { if (text === null || text === '' || text.trim() === '.') {
const content = new ContentWrapper(this.lastDirectory); const content = new ContentWrapper(this.lastDirectory);
this.content.next(content); this.content.next(content);
@ -128,15 +148,17 @@ export class GalleryService {
if (this.searchId != null) { if (this.searchId != null) {
clearTimeout(this.searchId); clearTimeout(this.searchId);
} }
this.runInstantSearchFor = null;
this.ongoingInstantSearch = {text: text, type: type};
const cw = new ContentWrapper(); const cw = new ContentWrapper();
cw.directory = null; cw.directory = null;
cw.searchResult = this.galleryCacheService.getSearch(text); cw.searchResult = this.galleryCacheService.getSearch(text);
if (cw.searchResult == null) { if (cw.searchResult == null) {
// If result is not search cache, try to load load more // If result is not search cache, try to load more
this.searchId = setTimeout(() => { this.searchId = setTimeout(() => {
this.search(text); this.search(text, type);
this.searchId = null; this.searchId = null;
}, Config.Client.Search.InstantSearchTimeout); }, Config.Client.Search.InstantSearchTimeout);
@ -144,6 +166,10 @@ export class GalleryService {
if (cw.searchResult == null) { if (cw.searchResult == null) {
cw.searchResult = (await this.networkService.getJson<ContentWrapper>('/instant-search/' + text)).searchResult; cw.searchResult = (await this.networkService.getJson<ContentWrapper>('/instant-search/' + text)).searchResult;
if (this.ongoingInstantSearch &&
(this.ongoingInstantSearch.text !== text || this.ongoingInstantSearch.type !== type)) {
return;
}
this.galleryCacheService.setInstantSearch(text, cw.searchResult); this.galleryCacheService.setInstantSearch(text, cw.searchResult);
} }
} }
@ -163,4 +189,13 @@ export class GalleryService {
return this.networkService.getJson<SharingDTO>('/share/' + sharingKey); return this.networkService.getJson<SharingDTO>('/share/' + sharingKey);
} }
isSearchResult(): boolean {
return !!this.content.value.searchResult;
}
runInstantSearch(searchText: string) {
this.runInstantSearchFor = searchText;
}
} }

View File

@ -3,12 +3,12 @@ import {MediaDTO} from '../../../../common/entities/MediaDTO';
export class GridRowBuilder { export class GridRowBuilder {
private photoRow: PhotoDTO[] = []; private photoRow: MediaDTO[] = [];
private photoIndex = 0; // index of the last pushed media to the photoRow private photoIndex = 0; // index of the last pushed media to the photoRow
constructor(private photos: PhotoDTO[], constructor(private photos: MediaDTO[],
private startIndex: number, private startIndex: number,
private photoMargin: number, private photoMargin: number,
private containerWidth: number) { private containerWidth: number) {
@ -42,7 +42,7 @@ export class GridRowBuilder {
return true; return true;
} }
public getPhotoRow(): PhotoDTO[] { public getPhotoRow(): MediaDTO[] {
return this.photoRow; return this.photoRow;
} }

View File

@ -1,9 +1,7 @@
<div #gridContainer> <div #gridContainer>
<app-gallery-grid-photo <app-gallery-grid-photo
*ngFor="let gridPhoto of photosToRender" *ngFor="let gridPhoto of photosToRender"
(click)="photoClicked(gridPhoto.media)"
[routerLink]="[]"
[queryParams]="queryService.getParams(gridPhoto.media)"
[gridPhoto]="gridPhoto" [gridPhoto]="gridPhoto"
[style.width.px]="gridPhoto.renderWidth" [style.width.px]="gridPhoto.renderWidth"
[style.height.px]="gridPhoto.renderHeight" [style.height.px]="gridPhoto.renderHeight"

View File

@ -27,6 +27,7 @@ import {GalleryService} from '../gallery.service';
import {SortingMethods} from '../../../../common/entities/SortingMethods'; import {SortingMethods} from '../../../../common/entities/SortingMethods';
import {MediaDTO} from '../../../../common/entities/MediaDTO'; import {MediaDTO} from '../../../../common/entities/MediaDTO';
import {QueryParams} from '../../../../common/QueryParams'; import {QueryParams} from '../../../../common/QueryParams';
import {Media} from '../Media';
@Component({ @Component({
selector: 'app-gallery-grid', selector: 'app-gallery-grid',
@ -39,7 +40,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
@ViewChildren(GalleryPhotoComponent) gridPhotoQL: QueryList<GalleryPhotoComponent>; @ViewChildren(GalleryPhotoComponent) gridPhotoQL: QueryList<GalleryPhotoComponent>;
private scrollListenerPhotos: GalleryPhotoComponent[] = []; private scrollListenerPhotos: GalleryPhotoComponent[] = [];
@Input() photos: Array<PhotoDTO>; @Input() media: MediaDTO[];
@Input() lightbox: GalleryLightboxComponent; @Input() lightbox: GalleryLightboxComponent;
photosToRender: Array<GridMedia> = []; photosToRender: Array<GridMedia> = [];
@ -76,11 +77,11 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
this.subscriptions.route = this.route.queryParams.subscribe((params: Params) => { this.subscriptions.route = this.route.queryParams.subscribe((params: Params) => {
if (params[QueryParams.gallery.photo] && params[QueryParams.gallery.photo] !== '') { if (params[QueryParams.gallery.photo] && params[QueryParams.gallery.photo] !== '') {
this.delayedRenderUpToPhoto = params[QueryParams.gallery.photo]; this.delayedRenderUpToPhoto = params[QueryParams.gallery.photo];
if (!this.photos || this.photos.length === 0) { if (!this.media || this.media.length === 0) {
return; return;
} }
this.renderUpToPhoto(params[QueryParams.gallery.photo]); this.renderUpToMedia(params[QueryParams.gallery.photo]);
} }
}); });
this.subscriptions.sorting = this.galleryService.sorting.subscribe(() => { this.subscriptions.sorting = this.galleryService.sorting.subscribe(() => {
@ -100,7 +101,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
this.helperTime = window.setTimeout(() => { this.helperTime = window.setTimeout(() => {
this.renderPhotos(); this.renderPhotos();
if (this.delayedRenderUpToPhoto) { if (this.delayedRenderUpToPhoto) {
this.renderUpToPhoto(this.delayedRenderUpToPhoto); this.renderUpToMedia(this.delayedRenderUpToPhoto);
} }
}, 0); }, 0);
} }
@ -135,6 +136,10 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
this.renderPhotos(renderedIndex); this.renderPhotos(renderedIndex);
} }
photoClicked(media: MediaDTO) {
this.router.navigate([], {queryParams: this.queryService.getParams(media)});
}
ngAfterViewInit() { ngAfterViewInit() {
this.lightbox.setGridPhotoQL(this.gridPhotoQL); this.lightbox.setGridPhotoQL(this.gridPhotoQL);
@ -155,8 +160,8 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
} }
private renderUpToPhoto(photoName: string) { private renderUpToMedia(mediaStringId: string) {
const index = this.photos.findIndex(p => p.name === photoName); const index = this.media.findIndex(p => this.queryService.getMediaStringId(p) === mediaStringId);
if (index === -1) { if (index === -1) {
this.router.navigate([], {queryParams: this.queryService.getParams()}); this.router.navigate([], {queryParams: this.queryService.getParams()});
return; return;
@ -166,7 +171,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
} }
public renderARow(): number { public renderARow(): number {
if (this.renderedPhotoIndex >= this.photos.length if (this.renderedPhotoIndex >= this.media.length
|| this.containerWidth === 0) { || this.containerWidth === 0) {
return null; return null;
} }
@ -174,7 +179,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
let maxRowHeight = this.screenHeight / this.MIN_ROW_COUNT; let maxRowHeight = this.screenHeight / this.MIN_ROW_COUNT;
const minRowHeight = this.screenHeight / this.MAX_ROW_COUNT; const minRowHeight = this.screenHeight / this.MAX_ROW_COUNT;
const photoRowBuilder = new GridRowBuilder(this.photos, const photoRowBuilder = new GridRowBuilder(this.media,
this.renderedPhotoIndex, this.renderedPhotoIndex,
this.IMAGE_MARGIN, this.IMAGE_MARGIN,
this.containerWidth - this.overlayService.getPhantomScrollbarWidth() this.containerWidth - this.overlayService.getPhantomScrollbarWidth()
@ -208,7 +213,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
private sortPhotos() { private sortPhotos() {
switch (this.galleryService.sorting.value) { switch (this.galleryService.sorting.value) {
case SortingMethods.ascName: case SortingMethods.ascName:
this.photos.sort((a: PhotoDTO, b: PhotoDTO) => { this.media.sort((a: PhotoDTO, b: PhotoDTO) => {
if (a.name.toLowerCase() < b.name.toLowerCase()) { if (a.name.toLowerCase() < b.name.toLowerCase()) {
return -1; return -1;
} }
@ -219,7 +224,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
}); });
break; break;
case SortingMethods.descName: case SortingMethods.descName:
this.photos.sort((a: PhotoDTO, b: PhotoDTO) => { this.media.sort((a: PhotoDTO, b: PhotoDTO) => {
if (a.name.toLowerCase() < b.name.toLowerCase()) { if (a.name.toLowerCase() < b.name.toLowerCase()) {
return 1; return 1;
} }
@ -230,12 +235,12 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
}); });
break; break;
case SortingMethods.ascDate: case SortingMethods.ascDate:
this.photos.sort((a: PhotoDTO, b: PhotoDTO) => { this.media.sort((a: PhotoDTO, b: PhotoDTO) => {
return a.metadata.creationDate - b.metadata.creationDate; return a.metadata.creationDate - b.metadata.creationDate;
}); });
break; break;
case SortingMethods.descDate: case SortingMethods.descDate:
this.photos.sort((a: PhotoDTO, b: PhotoDTO) => { this.media.sort((a: PhotoDTO, b: PhotoDTO) => {
return b.metadata.creationDate - a.metadata.creationDate; return b.metadata.creationDate - a.metadata.creationDate;
}); });
break; break;
@ -248,14 +253,14 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
// merge new data with old one // merge new data with old one
let lastSameIndex = 0; let lastSameIndex = 0;
let lastRowId = null; let lastRowId = null;
for (let i = 0; i < this.photos.length && i < this.photosToRender.length; ++i) { for (let i = 0; i < this.media.length && i < this.photosToRender.length; ++i) {
// If a media changed the whole row has to be removed // If a media changed the whole row has to be removed
if (this.photosToRender[i].rowId !== lastRowId) { if (this.photosToRender[i].rowId !== lastRowId) {
lastSameIndex = i; lastSameIndex = i;
lastRowId = this.photosToRender[i].rowId; lastRowId = this.photosToRender[i].rowId;
} }
if (this.photosToRender[i].equals(this.photos[i]) === false) { if (this.photosToRender[i].equals(this.media[i]) === false) {
break; break;
} }
} }
@ -286,7 +291,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
onScroll() { onScroll() {
if (!this.onScrollFired && if (!this.onScrollFired &&
// should we trigger this at all? // should we trigger this at all?
(this.renderedPhotoIndex < this.photos.length || this.scrollListenerPhotos.length > 0)) { (this.renderedPhotoIndex < this.media.length || this.scrollListenerPhotos.length > 0)) {
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
this.renderPhotos(); this.renderPhotos();
@ -305,7 +310,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
private renderPhotos(numberOfPhotos: number = 0) { private renderPhotos(numberOfPhotos: number = 0) {
if (this.containerWidth === 0 || if (this.containerWidth === 0 ||
this.renderedPhotoIndex >= this.photos.length || this.renderedPhotoIndex >= this.media.length ||
!this.shouldRenderMore()) { !this.shouldRenderMore()) {
return; return;
} }
@ -313,7 +318,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O
let renderedContentHeight = 0; let renderedContentHeight = 0;
while (this.renderedPhotoIndex < this.photos.length && while (this.renderedPhotoIndex < this.media.length &&
(this.shouldRenderMore(renderedContentHeight) === true || (this.shouldRenderMore(renderedContentHeight) === true ||
this.renderedPhotoIndex < numberOfPhotos)) { this.renderedPhotoIndex < numberOfPhotos)) {
const ret = this.renderARow(); const ret = this.renderARow();

View File

@ -23,6 +23,7 @@ import {PageHelper} from '../../model/page.helper';
import {QueryService} from '../../model/query.service'; import {QueryService} from '../../model/query.service';
import {MediaDTO} from '../../../../common/entities/MediaDTO'; import {MediaDTO} from '../../../../common/entities/MediaDTO';
import {QueryParams} from '../../../../common/QueryParams'; import {QueryParams} from '../../../../common/QueryParams';
import {GalleryService} from '../gallery.service';
export enum LightboxStates { export enum LightboxStates {
Open = 1, Open = 1,
@ -67,7 +68,7 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
startPhotoDimension: Dimension = <Dimension>{top: 0, left: 0, width: 0, height: 0}; startPhotoDimension: Dimension = <Dimension>{top: 0, left: 0, width: 0, height: 0};
iPvisibilityTimer: number = null; iPvisibilityTimer: number = null;
visibilityTimer: number = null; visibilityTimer: number = null;
delayedPhotoShow: string = null; delayedMediaShow: string = null;
constructor(public fullScreenService: FullScreenService, constructor(public fullScreenService: FullScreenService,
@ -76,6 +77,7 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
private _builder: AnimationBuilder, private _builder: AnimationBuilder,
private router: Router, private router: Router,
private queryService: QueryService, private queryService: QueryService,
private galleryService: GalleryService,
private route: ActivatedRoute) { private route: ActivatedRoute) {
} }
@ -84,11 +86,11 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
this.subscription.route = this.route.queryParams.subscribe((params: Params) => { this.subscription.route = this.route.queryParams.subscribe((params: Params) => {
if (params[QueryParams.gallery.photo] && params[QueryParams.gallery.photo] !== '') { if (params[QueryParams.gallery.photo] && params[QueryParams.gallery.photo] !== '') {
if (!this.gridPhotoQL) { if (!this.gridPhotoQL) {
return this.delayedPhotoShow = params[QueryParams.gallery.photo]; return this.delayedMediaShow = params[QueryParams.gallery.photo];
} }
this.onNavigateTo(params[QueryParams.gallery.photo]); this.onNavigateTo(params[QueryParams.gallery.photo]);
} else if (this.status === LightboxStates.Open) { } else if (this.status === LightboxStates.Open) {
this.delayedPhotoShow = null; this.delayedMediaShow = null;
this.hideLigthbox(); this.hideLigthbox();
} }
}); });
@ -111,20 +113,20 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
} }
} }
onNavigateTo(photoName: string) { onNavigateTo(photoStringId: string) {
if (this.activePhoto && this.activePhoto.gridPhoto.media.name === photoName) { if (this.activePhoto && this.queryService.getMediaStringId(this.activePhoto.gridPhoto.media) === photoStringId) {
return; return;
} }
const photo = this.gridPhotoQL.find(i => i.gridPhoto.media.name === photoName); const photo = this.gridPhotoQL.find(i => this.queryService.getMediaStringId(i.gridPhoto.media) === photoStringId);
if (!photo) { if (!photo) {
return this.delayedPhotoShow = photoName; return this.delayedMediaShow = photoStringId;
} }
if (this.status === LightboxStates.Closed) { if (this.status === LightboxStates.Closed) {
this.showLigthbox(photo.gridPhoto.media); this.showLigthbox(photo.gridPhoto.media);
} else { } else {
this.showPhoto(this.gridPhotoQL.toArray().indexOf(photo)); this.showPhoto(this.gridPhotoQL.toArray().indexOf(photo));
} }
this.delayedPhotoShow = null; this.delayedMediaShow = null;
} }
setGridPhotoQL(value: QueryList<GalleryPhotoComponent>) { setGridPhotoQL(value: QueryList<GalleryPhotoComponent>) {
@ -136,13 +138,13 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
if (this.activePhotoId != null && this.gridPhotoQL.length > this.activePhotoId) { if (this.activePhotoId != null && this.gridPhotoQL.length > this.activePhotoId) {
this.updateActivePhoto(this.activePhotoId); this.updateActivePhoto(this.activePhotoId);
} }
if (this.delayedPhotoShow) { if (this.delayedMediaShow) {
this.onNavigateTo(this.delayedPhotoShow); this.onNavigateTo(this.delayedMediaShow);
} }
}); });
if (this.delayedPhotoShow) { if (this.delayedMediaShow) {
this.onNavigateTo(this.delayedPhotoShow); this.onNavigateTo(this.delayedMediaShow);
} }
} }
@ -177,10 +179,6 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
private navigateToPhoto(photoIndex: number) { private navigateToPhoto(photoIndex: number) {
this.router.navigate([], this.router.navigate([],
{queryParams: this.queryService.getParams(this.gridPhotoQL.toArray()[photoIndex].gridPhoto.media)}); {queryParams: this.queryService.getParams(this.gridPhotoQL.toArray()[photoIndex].gridPhoto.media)});
/*
this.activePhoto = null;
this.changeDetector.detectChanges();
this.updateActivePhoto(photoIndex, resize);*/
} }
private showPhoto(photoIndex: number, resize: boolean = true) { private showPhoto(photoIndex: number, resize: boolean = true) {

View File

@ -33,7 +33,8 @@
</div> </div>
<div class="input-group-btn" style="display: block"> <div class="input-group-btn" style="display: block">
<button class="btn btn-default" type="button" (click)="onSearch()"> <button class="btn btn-default" type="button"
[routerLink]="['/search', searchText]">
<span class="oi oi-magnifying-glass"></span> <span class="oi oi-magnifying-glass"></span>
</button> </button>
</div> </div>

View File

@ -5,6 +5,7 @@ import {ActivatedRoute, Params, RouterLink} from '@angular/router';
import {GalleryService} from '../gallery.service'; import {GalleryService} from '../gallery.service';
import {Subscription} from 'rxjs'; import {Subscription} from 'rxjs';
import {Config} from '../../../../common/config/public/Config'; import {Config} from '../../../../common/config/public/Config';
import {NavigationService} from '../../model/navigation.service';
@Component({ @Component({
selector: 'app-gallery-search', selector: 'app-gallery-search',
@ -27,6 +28,7 @@ export class GallerySearchComponent implements OnDestroy {
constructor(private _autoCompleteService: AutoCompleteService, constructor(private _autoCompleteService: AutoCompleteService,
private _galleryService: GalleryService, private _galleryService: GalleryService,
private navigationService: NavigationService,
private _route: ActivatedRoute) { private _route: ActivatedRoute) {
this.SearchTypes = SearchTypes; this.SearchTypes = SearchTypes;
@ -52,26 +54,17 @@ export class GallerySearchComponent implements OnDestroy {
if (Config.Client.Search.autocompleteEnabled && this.cache.lastAutocomplete !== searchText) { if (Config.Client.Search.autocompleteEnabled && this.cache.lastAutocomplete !== searchText) {
this.cache.lastAutocomplete = searchText; this.cache.lastAutocomplete = searchText;
this.autocomplete(searchText); this.autocomplete(searchText).catch(console.error);
} }
if (Config.Client.Search.instantSearchEnabled && this.cache.lastInstantSearch !== searchText) { if (Config.Client.Search.instantSearchEnabled && this.cache.lastInstantSearch !== searchText) {
this.cache.lastInstantSearch = searchText; this.cache.lastInstantSearch = searchText;
this._galleryService.instantSearch(searchText); this._galleryService.runInstantSearch(searchText);
this.navigationService.search(searchText).catch(console.error);
// this._galleryService.instantSearch(searchText).catch(console.error);
} }
} }
public onSearch() {
if (Config.Client.Search.enabled) {
this._galleryService.search(this.searchText);
}
}
public search(item: AutoCompleteItem) {
this.searchText = item.text;
this.onSearch();
}
public setMouseOverAutoComplete(value: boolean) { public setMouseOverAutoComplete(value: boolean) {
this.mouseOverAutoComplete = value; this.mouseOverAutoComplete = value;
@ -84,7 +77,7 @@ export class GallerySearchComponent implements OnDestroy {
} }
public onFocus() { public onFocus() {
this.autocomplete(this.searchText); this.autocomplete(this.searchText).catch(console.error);
} }
private emptyAutoComplete() { private emptyAutoComplete() {
@ -113,7 +106,7 @@ export class GallerySearchComponent implements OnDestroy {
} }
} }
private showSuggestions(suggestions: Array<AutoCompleteItem>, searchText: string) { private showSuggestions(suggestions: AutoCompleteItem[], searchText: string) {
this.emptyAutoComplete(); this.emptyAutoComplete();
suggestions.forEach((item: AutoCompleteItem) => { suggestions.forEach((item: AutoCompleteItem) => {
const renderItem = new AutoCompleteRenderItem(item.text, searchText, item.type); const renderItem = new AutoCompleteRenderItem(item.text, searchText, item.type);

View File

@ -33,4 +33,8 @@ export class NavigationService {
return this._router.navigate(['gallery', '']); return this._router.navigate(['gallery', '']);
} }
} }
public async search(searchText: string) {
return this._router.navigate(['search', searchText]);
}
} }

View File

@ -3,18 +3,29 @@ import {ShareService} from '../gallery/share.service';
import {PhotoDTO} from '../../../common/entities/PhotoDTO'; import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {MediaDTO} from '../../../common/entities/MediaDTO'; import {MediaDTO} from '../../../common/entities/MediaDTO';
import {QueryParams} from '../../../common/QueryParams'; import {QueryParams} from '../../../common/QueryParams';
import {Utils} from '../../../common/Utils';
import {GalleryService} from '../gallery/gallery.service';
@Injectable() @Injectable()
export class QueryService { export class QueryService {
constructor(private shareService: ShareService) { constructor(private shareService: ShareService,
private galleryService: GalleryService) {
}
getMediaStringId(media: MediaDTO): string {
if (this.galleryService.isSearchResult()) {
return Utils.concatUrls(media.directory.path, media.directory.name, media.name);
} else {
return media.name;
}
} }
getParams(media?: MediaDTO): { [key: string]: string } { getParams(media?: MediaDTO): { [key: string]: string } {
const query: { [key: string]: string } = {}; const query: { [key: string]: string } = {};
if (media) { if (media) {
query[QueryParams.gallery.photo] = media.name; query[QueryParams.gallery.photo] = this.getMediaStringId(media);
} }
if (this.shareService.isSharing()) { if (this.shareService.isSharing()) {
query[QueryParams.gallery.sharingKey_short] = this.shareService.getSharingKey(); query[QueryParams.gallery.sharingKey_short] = this.shareService.getSharingKey();