2022-11-25 22:56:33 +01:00
|
|
|
import {DirectoryPathDTO} from './DirectoryDTO';
|
|
|
|
import {PhotoDTO} from './PhotoDTO';
|
|
|
|
import {FileDTO} from './FileDTO';
|
|
|
|
import {SupportedFormats} from '../SupportedFormats';
|
2021-04-01 21:48:38 +02:00
|
|
|
|
2021-06-27 19:33:37 +02:00
|
|
|
export interface MediaDTO extends FileDTO {
|
2018-11-04 19:28:32 +01:00
|
|
|
id: number;
|
|
|
|
name: string;
|
2021-06-27 19:33:37 +02:00
|
|
|
directory: DirectoryPathDTO;
|
2018-11-04 19:28:32 +01:00
|
|
|
metadata: MediaMetadata;
|
2022-03-26 11:55:15 +01:00
|
|
|
missingThumbnails?: number;
|
2018-11-04 19:28:32 +01:00
|
|
|
}
|
|
|
|
|
2023-11-26 10:53:08 +12:00
|
|
|
export type RatingTypes = 0 | 1 | 2 | 3 | 4 | 5;
|
|
|
|
|
2018-11-04 19:28:32 +01:00
|
|
|
export interface MediaMetadata {
|
|
|
|
size: MediaDimension;
|
|
|
|
creationDate: number;
|
|
|
|
fileSize: number;
|
2024-02-11 15:55:26 +01:00
|
|
|
creationDateOffset?: string;
|
2023-11-26 10:53:08 +12:00
|
|
|
keywords?: string[];
|
|
|
|
rating?: RatingTypes;
|
2023-11-27 22:47:24 +00:00
|
|
|
title?: string;
|
|
|
|
caption?: string;
|
2018-11-04 19:28:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface MediaDimension {
|
|
|
|
width: number;
|
|
|
|
height: number;
|
|
|
|
}
|
|
|
|
|
2023-12-04 12:13:38 +12:00
|
|
|
export interface SideCar {
|
2024-03-01 19:55:01 +01:00
|
|
|
exif?: SideCarExif;
|
2023-12-04 12:13:38 +12:00
|
|
|
dc?: SideCarDc;
|
|
|
|
xmp?: SideCarXmp;
|
2024-03-01 13:20:09 +01:00
|
|
|
photoshop?: SideCarPhotoshop;
|
2023-12-04 12:13:38 +12:00
|
|
|
}
|
|
|
|
|
2024-03-01 19:55:01 +01:00
|
|
|
export interface SideCarExif {
|
|
|
|
GPSLatitude?: string;
|
|
|
|
GPSLongitude?: string;
|
|
|
|
}
|
|
|
|
|
2023-12-04 12:13:38 +12:00
|
|
|
export interface SideCarDc {
|
|
|
|
subject?: string[];
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface SideCarXmp {
|
|
|
|
Rating?: RatingTypes;
|
2024-03-11 23:47:44 +01:00
|
|
|
CreateDate?: string;
|
2024-03-01 13:20:09 +01:00
|
|
|
ModifyDate?: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface SideCarPhotoshop {
|
|
|
|
// Corresponds to Exif.Photo.DateTimeOriginal. No corresponding key exists in
|
|
|
|
// the xmp namespace!
|
|
|
|
DateCreated?: string;
|
2023-12-04 12:13:38 +12:00
|
|
|
}
|
|
|
|
|
2021-04-18 15:48:35 +02:00
|
|
|
export const MediaDTOUtils = {
|
2021-06-27 19:33:37 +02:00
|
|
|
hasPositionData: (media: MediaDTO): boolean => {
|
2022-04-04 19:37:31 +02:00
|
|
|
return (
|
2023-09-11 18:57:51 +02:00
|
|
|
!!(media as PhotoDTO).metadata.positionData &&
|
|
|
|
!!(
|
|
|
|
(media as PhotoDTO).metadata.positionData.city ||
|
|
|
|
(media as PhotoDTO).metadata.positionData.state ||
|
|
|
|
(media as PhotoDTO).metadata.positionData.country ||
|
|
|
|
((media as PhotoDTO).metadata.positionData.GPSData &&
|
|
|
|
(media as PhotoDTO).metadata.positionData.GPSData.latitude &&
|
|
|
|
(media as PhotoDTO).metadata.positionData.GPSData.longitude)
|
|
|
|
)
|
2022-04-04 19:37:31 +02:00
|
|
|
);
|
2021-04-18 15:48:35 +02:00
|
|
|
},
|
2021-06-27 19:33:37 +02:00
|
|
|
isPhoto: (media: FileDTO): boolean => {
|
2021-04-18 15:48:35 +02:00
|
|
|
return !MediaDTOUtils.isVideo(media);
|
|
|
|
},
|
2018-11-04 19:28:32 +01:00
|
|
|
|
2021-06-27 19:33:37 +02:00
|
|
|
isVideo: (media: FileDTO): boolean => {
|
2018-12-05 17:29:33 +01:00
|
|
|
const lower = media.name.toLowerCase();
|
2019-12-09 17:19:28 +01:00
|
|
|
for (const ext of SupportedFormats.WithDots.Videos) {
|
|
|
|
if (lower.endsWith(ext)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2021-04-18 15:48:35 +02:00
|
|
|
},
|
2018-11-17 19:32:31 +01:00
|
|
|
|
2021-04-18 15:48:35 +02:00
|
|
|
isVideoPath: (path: string): boolean => {
|
2019-12-30 17:52:58 +01:00
|
|
|
const lower = path.toLowerCase();
|
|
|
|
for (const ext of SupportedFormats.WithDots.Videos) {
|
|
|
|
if (lower.endsWith(ext)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2021-04-18 15:48:35 +02:00
|
|
|
},
|
2019-12-30 17:52:58 +01:00
|
|
|
|
2021-06-27 19:33:37 +02:00
|
|
|
isVideoTranscodingNeeded: (media: FileDTO): boolean => {
|
2019-12-10 12:50:02 +01:00
|
|
|
const lower = media.name.toLowerCase();
|
|
|
|
for (const ext of SupportedFormats.WithDots.TranscodeNeed.Videos) {
|
|
|
|
if (lower.endsWith(ext)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2021-04-18 15:48:35 +02:00
|
|
|
},
|
2019-12-10 12:50:02 +01:00
|
|
|
|
2021-06-27 19:33:37 +02:00
|
|
|
calcAspectRatio: (photo: MediaDTO): number => {
|
2023-03-02 00:00:37 +01:00
|
|
|
return (photo.metadata.size.width / photo.metadata.size.height) || 1; // NaN should be treated as square photo
|
2022-04-04 19:37:31 +02:00
|
|
|
},
|
2023-09-08 19:45:56 +02:00
|
|
|
|
|
|
|
equals: (a: MediaDTO, b: MediaDTO): boolean => {
|
|
|
|
return a.directory.path === b.directory.path &&
|
2023-09-11 18:57:51 +02:00
|
|
|
a.directory.name === b.directory.name &&
|
|
|
|
a.name === b.name;
|
2023-09-08 19:45:56 +02:00
|
|
|
}
|
2021-04-18 15:48:35 +02:00
|
|
|
};
|