diff --git a/src/backend/middlewares/GalleryMWs.ts b/src/backend/middlewares/GalleryMWs.ts index fa70df2b..94e4e8de 100644 --- a/src/backend/middlewares/GalleryMWs.ts +++ b/src/backend/middlewares/GalleryMWs.ts @@ -74,6 +74,7 @@ export class GalleryMWs { delete (m).metadata.bitRate; delete (m).metadata.duration; } else if (MediaDTO.isVideo(m)) { + delete (m).metadata.rating; delete (m).metadata.caption; delete (m).metadata.cameraData; delete (m).metadata.orientation; diff --git a/src/backend/model/database/sql/enitites/MediaEntity.ts b/src/backend/model/database/sql/enitites/MediaEntity.ts index 24a877c1..9f267435 100644 --- a/src/backend/model/database/sql/enitites/MediaEntity.ts +++ b/src/backend/model/database/sql/enitites/MediaEntity.ts @@ -43,6 +43,9 @@ export class MediaMetadataEntity implements MediaMetadata { @Column(type => PositionMetaDataEntity) positionData: PositionMetaDataEntity; + @Column('tinyint', {unsigned: true}) + rating: 0 | 1 | 2 | 3 | 4 | 5; + @Column('tinyint', {unsigned: true, default: OrientationTypes.TOP_LEFT}) orientation: OrientationTypes; diff --git a/src/backend/model/threading/MetadataLoader.ts b/src/backend/model/threading/MetadataLoader.ts index 47fc9581..c63b4d09 100644 --- a/src/backend/model/threading/MetadataLoader.ts +++ b/src/backend/model/threading/MetadataLoader.ts @@ -203,16 +203,20 @@ export class MetadataLoader { metadata.creationDate = metadata.creationDate || 0; - if (Config.Client.Faces.enabled) { - try { - - const ret = ExifReader.load(data); + try { + // TODO: clean up the three different exif readers, + // and keep the minimum amount only + const exif = ExifReader.load(data); + if (exif.Rating) { + metadata.rating = parseInt(exif.Rating.value, 10); + } + if (Config.Client.Faces.enabled) { const faces: FaceRegion[] = []; - if (ret.Regions && ret.Regions.value.RegionList && ret.Regions.value.RegionList.value) { - for (let i = 0; i < ret.Regions.value.RegionList.value.length; i++) { + if (exif.Regions && exif.Regions.value.RegionList && exif.Regions.value.RegionList.value) { + for (let i = 0; i < exif.Regions.value.RegionList.value.length; i++) { let type, name, box; - const regionRoot = ret.Regions.value.RegionList.value[i] as any; + const regionRoot = exif.Regions.value.RegionList.value[i] as any; const createFaceBox = (w: string, h: string, x: string, y: string) => { return { width: Math.round(parseFloat(w) * metadata.size.width), @@ -268,8 +272,8 @@ export class MetadataLoader { } }); } - } catch (err) { } + } catch (err) { } diff --git a/src/common/entities/PhotoDTO.ts b/src/common/entities/PhotoDTO.ts index 130d8fbb..88b05f31 100644 --- a/src/common/entities/PhotoDTO.ts +++ b/src/common/entities/PhotoDTO.ts @@ -24,6 +24,7 @@ export interface FaceRegion { } export interface PhotoMetadata extends MediaMetadata { + rating?: 0 | 1 | 2 | 3 | 4 | 5; caption?: string; keywords?: string[]; cameraData?: CameraMetadata; diff --git a/src/frontend/app/pipes/GPXFilesFilterPipe.ts b/src/frontend/app/pipes/GPXFilesFilterPipe.ts index fc150f31..69e7957c 100644 --- a/src/frontend/app/pipes/GPXFilesFilterPipe.ts +++ b/src/frontend/app/pipes/GPXFilesFilterPipe.ts @@ -5,6 +5,9 @@ import {FileDTO} from '../../../common/entities/FileDTO'; @Pipe({name: 'gpxFiles'}) export class GPXFilesFilterPipe implements PipeTransform { transform(metaFiles: FileDTO[]) { + if (!metaFiles) { + return null; + } return metaFiles.filter((f: FileDTO) => f.name.toLocaleLowerCase().endsWith('.gpx')); } } diff --git a/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts b/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts index 31c23149..a3c5a4cd 100644 --- a/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts +++ b/src/frontend/app/ui/gallery/grid/grid.gallery.component.ts @@ -40,7 +40,7 @@ export class GalleryGridComponent implements OnChanges, OnInit, AfterViewInit, O @ViewChildren(GalleryPhotoComponent) gridPhotoQL: QueryList; @Input() media: MediaDTO[]; @Input() lightbox: GalleryLightboxComponent; - photosToRender: Array = []; + photosToRender: GridMedia[] = []; containerWidth = 0; screenHeight = 0; public IMAGE_MARGIN = 2; diff --git a/test/backend/assets/test image öüóőúéáű-.,.json b/test/backend/assets/test image öüóőúéáű-.,.json index 4493fb79..4b148292 100644 --- a/test/backend/assets/test image öüóőúéáű-.,.json +++ b/test/backend/assets/test image öüóőúéáű-.,.json @@ -47,6 +47,7 @@ "country": "test country őúéáűóöí-.,)(=/%!+\"'", "state": "test state őúéáűóöí-.,)(" }, + "rating": 3, "size": { "height": 10, "width": 14 diff --git a/test/backend/unit/model/sql/TestHelper.ts b/test/backend/unit/model/sql/TestHelper.ts index 12151c50..136bd47c 100644 --- a/test/backend/unit/model/sql/TestHelper.ts +++ b/test/backend/unit/model/sql/TestHelper.ts @@ -10,7 +10,14 @@ import {OrientationTypes} from 'ts-exif-parser'; import {DirectoryEntity} from '../../../../../src/backend/model/database/sql/enitites/DirectoryEntity'; import {VideoEntity, VideoMetadataEntity} from '../../../../../src/backend/model/database/sql/enitites/VideoEntity'; import {MediaDimension} from '../../../../../src/common/entities/MediaDTO'; -import {CameraMetadata, FaceRegion, GPSMetadata, PhotoDTO, PhotoMetadata, PositionMetaData} from '../../../../../src/common/entities/PhotoDTO'; +import { + CameraMetadata, + FaceRegion, + GPSMetadata, + PhotoDTO, + PhotoMetadata, + PositionMetaData +} from '../../../../../src/common/entities/PhotoDTO'; import {DirectoryDTO} from '../../../../../src/common/entities/DirectoryDTO'; import {FileDTO} from '../../../../../src/common/entities/FileDTO'; import {DiskMangerWorker} from '../../../../../src/backend/model/threading/DiskMangerWorker'; @@ -59,6 +66,7 @@ export class TestHelper { m.creationDate = Date.now(); m.fileSize = 123456789; m.orientation = OrientationTypes.TOP_LEFT; + m.rating = 2; // TODO: remove when typeorm is fixed m.duration = null; @@ -81,6 +89,7 @@ export class TestHelper { const m = new VideoMetadataEntity(); m.caption = null; m.keywords = null; + m.rating = null; m.size = sd; m.creationDate = Date.now(); m.fileSize = 123456789; @@ -252,7 +261,8 @@ export class TestHelper { creationDate: Date.now(), fileSize: rndInt(10000), orientation: OrientationTypes.TOP_LEFT, - caption: rndStr() + caption: rndStr(), + rating: rndInt(5), };