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:
parent
77b66c49c9
commit
037c366e80
@ -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) {
|
||||||
|
@ -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 &&
|
||||||
|
@ -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 {
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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();
|
||||||
|
@ -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) {
|
||||||
|
@ -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>
|
||||||
|
@ -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);
|
||||||
|
@ -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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user