1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-01-04 03:49:28 +02:00

Adding preview field to Directory and populating it with any photo from subdirectory (based on #165), fixes #31

This commit is contained in:
Patrik J. Braun 2021-03-27 21:31:19 +01:00
parent 8bd04dda8c
commit c670a17e27
13 changed files with 89 additions and 74 deletions

View File

@ -86,7 +86,7 @@ export class GalleryMWs {
if (cw.directory) {
DirectoryDTO.removeReferences(cw.directory);
// TODO: remove when typeorm inheritance is fixed
// TODO: remove when typeorm inheritance is fixed (and handles proper inheritance)
cleanUpMedia(cw.directory.media);
}
if (cw.searchResult) {

View File

@ -31,6 +31,7 @@ export class ThumbnailGeneratorMWs {
}
} catch (error) {
console.error(error);
return next(new ErrorDTO(ErrorCodes.SERVER_ERROR, 'error during postprocessing result (adding thumbnail info)', error.toString()));
}
@ -62,7 +63,8 @@ export class ThumbnailGeneratorMWs {
}
} catch (error) {
return next(new ErrorDTO(ErrorCodes.SERVER_ERROR, 'error during postprocessing result (adding thumbnail info)', error.toString()));
return next(new ErrorDTO(ErrorCodes.SERVER_ERROR, 'error during postprocessing result (adding thumbnail info for persons)',
error.toString()));
}
@ -139,6 +141,9 @@ export class ThumbnailGeneratorMWs {
if (typeof directory.media !== 'undefined') {
ThumbnailGeneratorMWs.addThInfoToPhotos(directory.media);
}
if (directory.preview) {
ThumbnailGeneratorMWs.addThInfoToAPhoto(directory.preview);
}
if (typeof directory.directories !== 'undefined') {
for (let i = 0; i < directory.directories.length; i++) {
ThumbnailGeneratorMWs.addThInfoTODir(directory.directories[i]);
@ -148,22 +153,27 @@ export class ThumbnailGeneratorMWs {
private static addThInfoToPhotos(photos: MediaDTO[]) {
for (let i = 0; i < photos.length; i++) {
const fullMediaPath = path.join(ProjectPath.ImageFolder, photos[i].directory.path, photos[i].directory.name, photos[i].name);
for (let j = 0; j < Config.Client.Media.Thumbnail.thumbnailSizes.length; j++) {
const size = Config.Client.Media.Thumbnail.thumbnailSizes[j];
const thPath = PhotoProcessing.generateConvertedPath(fullMediaPath, size);
if (fs.existsSync(thPath) === true) {
if (typeof photos[i].readyThumbnails === 'undefined') {
photos[i].readyThumbnails = [];
}
photos[i].readyThumbnails.push(size);
this.addThInfoToAPhoto(photos[i]);
}
}
private static addThInfoToAPhoto(photo: MediaDTO) {
const fullMediaPath = path.join(ProjectPath.ImageFolder, photo.directory.path, photo.directory.name, photo.name);
for (let j = 0; j < Config.Client.Media.Thumbnail.thumbnailSizes.length; j++) {
const size = Config.Client.Media.Thumbnail.thumbnailSizes[j];
const thPath = PhotoProcessing.generateConvertedPath(fullMediaPath, size);
if (fs.existsSync(thPath) === true) {
if (typeof photo.readyThumbnails === 'undefined') {
photo.readyThumbnails = [];
}
}
const iconPath = PhotoProcessing.generateConvertedPath(fullMediaPath, Config.Client.Media.Thumbnail.iconSize);
if (fs.existsSync(iconPath) === true) {
photos[i].readyIcon = true;
photo.readyThumbnails.push(size);
}
}
const iconPath = PhotoProcessing.generateConvertedPath(fullMediaPath, Config.Client.Media.Thumbnail.iconSize);
if (fs.existsSync(iconPath) === true) {
photo.readyIcon = true;
}
}
}

View File

@ -36,15 +36,7 @@ export class DiskManager {
} else {
directory = await DiskMangerWorker.scanDirectory(relativeDirectoryName, settings);
}
const addDirs = (dir: DirectoryDTO) => {
dir.media.forEach((ph) => {
ph.directory = dir;
});
dir.directories.forEach((d) => {
addDirs(d);
});
};
addDirs(directory);
DirectoryDTO.addReferences(directory);
return directory;
}

View File

@ -86,7 +86,6 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
}
async countDirectories(): Promise<number> {
const connection = await SQLConnection.getConnection();
return await connection.getRepository(DirectoryEntity)
@ -103,7 +102,6 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
return sum || 0;
}
async countPhotos(): Promise<number> {
const connection = await SQLConnection.getConnection();
return await connection.getRepository(PhotoEntity)
@ -238,38 +236,32 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
}
if (dir.directories) {
for (let i = 0; i < dir.directories.length; i++) {
const dirName = GalleryManager.getAbsoluteDirName(dir.directories[i]);
dir.directories[i].media = await connection
const _path = dir.path;
const currentRoot = (_path === './' ? '' : _path);
const dirName = currentRoot + dir.name + path.sep;
dir.directories[i].media = [];
dir.directories[i].preview = await connection
.getRepository(MediaEntity)
.createQueryBuilder('media')
.innerJoinAndSelect('media.directory', 'directory')
.where('media.directory = :dir', {
dir: dir.directories[i].id
})
.orWhere("directory.path like :parentPath||'%'", {
parentPath: dirName
.orWhere('directory.path like :parentPath||\'%\'', {
parentPath: dirName
})
.orderBy('media.metadata.creationDate', 'DESC')
.limit(Config.Server.Indexing.folderPreviewSize)
.getMany();
.limit(1)
.getOne();
dir.directories[i].isPartial = true;
const dirs = dir.directories[i]
for (let j = 0; j < dirs.media.length; j++) {
const mediaDirName = GalleryManager.getAbsoluteDirName(dirs.media[j].directory);
const name = mediaDirName.substring(dirName.length);
dir.directories[i].media[j].name = name + dir.directories[i].media[j].name
dir.directories[i].media[j].directory = dir.directories[i];
dir.directories[i].media[j].readyThumbnails = [];
dir.directories[i].media[j].readyIcon = false;
if (dir.directories[i].preview) {
dir.directories[i].preview.directory = dir.directories[i];
dir.directories[i].preview.readyThumbnails = [];
dir.directories[i].preview.readyIcon = false;
}
}
}
}
public static getAbsoluteDirName(dir: DirectoryEntity) {
const path = dir.path;
const currentRoot = (path === "./" ? "" : path) ;
return currentRoot + dir.name + "/";
}
}

View File

@ -37,6 +37,9 @@ export class IndexingManager implements IIndexingManager {
const scannedDirectory = await DiskManager.scanDirectory(relativeDirectoryName);
// returning with the result
if (scannedDirectory.preview) {
scannedDirectory.preview.readyThumbnails = [];
}
scannedDirectory.media.forEach(p => p.readyThumbnails = []);
resolve(scannedDirectory);

View File

@ -54,6 +54,8 @@ export class DirectoryEntity implements DirectoryDTO {
@OneToMany(type => DirectoryEntity, dir => dir.parent)
public directories: DirectoryEntity[];
public preview: MediaEntity;
@OneToMany(type => MediaEntity, media => media.directory)
public media: MediaEntity[];

View File

@ -104,6 +104,7 @@ export class DiskMangerWorker {
directories: [],
isPartial: false,
mediaCount: 0,
preview: null,
media: [],
metaFile: []
};
@ -117,7 +118,7 @@ export class DiskMangerWorker {
const file = list[i];
const fullFilePath = path.normalize(path.join(absoluteDirectoryName, file));
if ((await fsp.stat(fullFilePath)).isDirectory()) {
if (settings.noDirectory === true ||
if (settings.noDirectory === true || settings.previewOnly === true ||
await DiskMangerWorker.excludeDir(file, relativeDirectoryName, absoluteDirectoryName)) {
continue;
}
@ -125,11 +126,7 @@ export class DiskMangerWorker {
// create preview directory
const d = await DiskMangerWorker.scanDirectory(path.join(relativeDirectoryName, file),
{
maxPhotos: Config.Server.Indexing.folderPreviewSize,
noMetaFile: true,
noVideo: true,
noDirectory: true,
noPhoto: settings.noChildDirPhotos || settings.noPhoto
previewOnly: true
}
);
@ -141,18 +138,23 @@ export class DiskMangerWorker {
if (settings.noPhoto === true) {
continue;
}
directory.media.push(<PhotoDTO>{
const photo = <PhotoDTO>{
name: file,
directory: null,
metadata: settings.noMetadata === true ? null : await MetadataLoader.loadPhotoMetadata(fullFilePath)
});
};
if (settings.maxPhotos && directory.media.length > settings.maxPhotos) {
if (!directory.preview) {
directory.preview = photo;
}
if (settings.previewOnly === true) {
break;
}
directory.media.push(photo);
} else if (VideoProcessing.isVideo(fullFilePath)) {
if (Config.Client.Media.Video.enabled === false || settings.noVideo === true) {
if (Config.Client.Media.Video.enabled === false || settings.noVideo === true || settings.previewOnly === true) {
continue;
}
try {
@ -166,7 +168,7 @@ export class DiskMangerWorker {
}
} else if (DiskMangerWorker.isMetaFile(fullFilePath)) {
if (Config.Client.MetaFile.enabled === false || settings.noMetaFile === true) {
if (Config.Client.MetaFile.enabled === false || settings.noMetaFile === true || settings.previewOnly === true) {
continue;
}
@ -193,7 +195,7 @@ export class DiskMangerWorker {
export namespace DiskMangerWorker {
export interface DirectoryScanSettings {
maxPhotos?: number;
previewOnly?: boolean;
noMetaFile?: boolean;
noVideo?: boolean;
noPhoto?: boolean;

View File

@ -96,8 +96,6 @@ export module ServerConfig {
@SubConfigClass()
export class IndexingConfig {
@ConfigProperty()
folderPreviewSize: number = 2;
@ConfigProperty()
cachedFolderTimeout: number = 1000 * 60 * 60; // Do not rescans the folder if seems ok
@ConfigProperty({type: ReIndexingSensitivity})

View File

@ -12,6 +12,7 @@ export interface DirectoryDTO<S extends FileDTO = MediaDTO> {
parent: DirectoryDTO<S>;
mediaCount: number;
directories: DirectoryDTO<S>[];
preview: S;
media: S[];
metaFile: FileDTO[];
}
@ -22,6 +23,9 @@ export module DirectoryDTO {
media.directory = dir;
});
if (dir.preview) {
dir.preview.directory = dir;
}
if (dir.metaFile) {
dir.metaFile.forEach((file: FileDTO) => {
file.directory = dir;
@ -42,6 +46,9 @@ export module DirectoryDTO {
media.directory = null;
});
}
if (dir.preview) {
dir.preview.directory = null;
}
if (dir.metaFile) {
dir.metaFile.forEach((file: FileDTO) => {
file.directory = null;

View File

@ -28,10 +28,7 @@ export class GalleryDirectoryComponent implements OnInit, OnDestroy {
}
public get SamplePhoto(): MediaDTO {
if (this.directory.media.length > 0) {
return this.directory.media[0];
}
return null;
return this.directory.preview;
}
getSanitizedThUrl() {
@ -59,7 +56,7 @@ export class GalleryDirectoryComponent implements OnInit, OnDestroy {
}
ngOnInit() {
if (this.directory.media.length > 0) {
if (this.directory.preview) {
this.thumbnail = this.thumbnailService.getThumbnail(new Media(this.SamplePhoto, this.size, this.size));
}
}

View File

@ -16,14 +16,6 @@
required="true">
</app-settings-entry>
<app-settings-entry
name="Sub folder preview size"
description="Reads this many photos from sub folders."
i18n-description i18n-name
[ngModel]="states.folderPreviewSize"
required="true">
</app-settings-entry>
<app-settings-entry
name="Folder reindexing sensitivity"

View File

@ -68,6 +68,9 @@ describe('IndexingManager', (sqlHelper: SQLTestHelper) => {
dir.media.forEach((media: MediaDTO) => {
delete media.id;
});
if (dir.preview) {
delete dir.preview.id;
}
if (dir.metaFile) {
if (dir.metaFile.length === 0) {
delete dir.metaFile;
@ -128,12 +131,16 @@ describe('IndexingManager', (sqlHelper: SQLTestHelper) => {
DirectoryDTO.removeReferences(selected);
removeIds(selected);
subDir1.preview = subDir1.media[0];
subDir1.isPartial = true;
delete subDir1.directories;
delete subDir1.metaFile;
delete subDir1.media;
subDir2.preview = subDir2.media[0];
subDir2.isPartial = true;
delete subDir2.directories;
delete subDir2.metaFile;
delete subDir2.media;
expect(Utils.clone(Utils.removeNullOrEmptyObj(selected)))
.to.deep.equal(Utils.clone(Utils.removeNullOrEmptyObj(parent)));
});
@ -163,8 +170,10 @@ describe('IndexingManager', (sqlHelper: SQLTestHelper) => {
DirectoryDTO.removeReferences(selected);
removeIds(selected);
subDir1.isPartial = true;
subDir1.preview = subDir1.media[0];
delete subDir1.directories;
delete subDir1.metaFile;
delete subDir1.media;
expect(Utils.clone(Utils.removeNullOrEmptyObj(selected)))
.to.deep.equal(Utils.clone(Utils.removeNullOrEmptyObj(parent1)));
}
@ -175,8 +184,10 @@ describe('IndexingManager', (sqlHelper: SQLTestHelper) => {
DirectoryDTO.removeReferences(selected);
removeIds(selected);
subDir2.isPartial = true;
subDir2.preview = subDir2.media[0];
delete subDir2.directories;
delete subDir2.metaFile;
delete subDir2.media;
expect(Utils.clone(Utils.removeNullOrEmptyObj(selected)))
.to.deep.equal(Utils.clone(Utils.removeNullOrEmptyObj(parent2)));
}
@ -212,8 +223,10 @@ describe('IndexingManager', (sqlHelper: SQLTestHelper) => {
DirectoryDTO.removeReferences(selected);
removeIds(selected);
subDir.isPartial = true;
subDir.preview = subDir.media[0];
delete subDir.directories;
delete subDir.metaFile;
delete subDir.media;
expect(Utils.clone(Utils.removeNullOrEmptyObj(selected)))
.to.deep.equal(Utils.clone(Utils.removeNullOrEmptyObj(parent)));
});
@ -248,8 +261,10 @@ describe('IndexingManager', (sqlHelper: SQLTestHelper) => {
DirectoryDTO.removeReferences(selected);
removeIds(selected);
subDir.isPartial = true;
subDir.preview = subDir.media[0];
delete subDir.directories;
delete subDir.metaFile;
delete subDir.media;
expect(Utils.clone(Utils.removeNullOrEmptyObj(selected)))
.to.deep.equal(Utils.clone(Utils.removeNullOrEmptyObj(parent)));
});
@ -277,8 +292,10 @@ describe('IndexingManager', (sqlHelper: SQLTestHelper) => {
DirectoryDTO.removeReferences(selected);
removeIds(selected);
subDir.isPartial = true;
subDir.preview = subDir.media[0];
delete subDir.directories;
delete subDir.metaFile;
delete subDir.media;
expect(Utils.clone(Utils.removeNullOrEmptyObj(selected)))
.to.deep.equal(Utils.clone(Utils.removeNullOrEmptyObj(parent)));
});
@ -405,8 +422,10 @@ describe('IndexingManager', (sqlHelper: SQLTestHelper) => {
DirectoryDTO.removeReferences(selected);
removeIds(selected);
subDir.isPartial = true;
subDir.preview = subDir.media[0];
delete subDir.directories;
delete subDir.metaFile;
delete subDir.media;
delete sp1.metadata.faces;
delete sp2.metadata.faces;
expect(Utils.clone(Utils.removeNullOrEmptyObj(selected)))

View File

@ -259,6 +259,7 @@ export class TestHelper {
mediaCount: 0,
directories: [],
metaFile: [],
preview: null,
media: [],
lastModified: Date.now(),
lastScanned: null,