mirror of
https://github.com/immich-app/immich.git
synced 2025-05-24 01:12:58 -04:00
refactor(server): decouple generated images from image formats (#8246)
* rename thumbnail config update target paths, fix tests rename to image settings replace legacy enum better typing update sql update api remove config option fix * update docs * update other thumbnail configs in migration * keep legacy enum for now * fix jumbled job names * fix jumbled job names in tests * rename thumbhash job * rename dto * fix tests * preserve order * remove unused import * keep old fields in dto, marked deprecated * update sql --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
parent
e520c0d1f5
commit
8edc2fb46f
@ -45,7 +45,7 @@ SELECT * FROM "assets" JOIN "exif" ON "assets"."id" = "exif"."assetId" WHERE "ex
|
|||||||
```
|
```
|
||||||
|
|
||||||
```sql title="Without thumbnails"
|
```sql title="Without thumbnails"
|
||||||
SELECT * FROM "assets" WHERE "assets"."resizePath" IS NULL OR "assets"."webpPath" IS NULL;
|
SELECT * FROM "assets" WHERE "assets"."previewPath" IS NULL OR "assets"."thumbnailPath" IS NULL;
|
||||||
```
|
```
|
||||||
|
|
||||||
```sql title="By type"
|
```sql title="By type"
|
||||||
|
@ -114,9 +114,11 @@ The default configuration looks like this:
|
|||||||
"hashVerificationEnabled": true,
|
"hashVerificationEnabled": true,
|
||||||
"template": "{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}"
|
"template": "{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}"
|
||||||
},
|
},
|
||||||
"thumbnail": {
|
"image": {
|
||||||
"webpSize": 250,
|
"thumbnailFormat": "webp",
|
||||||
"jpegSize": 1440,
|
"thumbnailSize": 250,
|
||||||
|
"previewFormat": "jpeg",
|
||||||
|
"previewSize": 1440,
|
||||||
"quality": 80,
|
"quality": 80,
|
||||||
"colorspace": "p3"
|
"colorspace": "p3"
|
||||||
},
|
},
|
||||||
|
9
mobile/openapi/.openapi-generator/FILES
generated
9
mobile/openapi/.openapi-generator/FILES
generated
@ -72,6 +72,7 @@ doc/FileChecksumResponseDto.md
|
|||||||
doc/FileReportDto.md
|
doc/FileReportDto.md
|
||||||
doc/FileReportFixDto.md
|
doc/FileReportFixDto.md
|
||||||
doc/FileReportItemDto.md
|
doc/FileReportItemDto.md
|
||||||
|
doc/ImageFormat.md
|
||||||
doc/JobApi.md
|
doc/JobApi.md
|
||||||
doc/JobCommand.md
|
doc/JobCommand.md
|
||||||
doc/JobCommandDto.md
|
doc/JobCommandDto.md
|
||||||
@ -145,6 +146,7 @@ doc/SmartSearchDto.md
|
|||||||
doc/SystemConfigApi.md
|
doc/SystemConfigApi.md
|
||||||
doc/SystemConfigDto.md
|
doc/SystemConfigDto.md
|
||||||
doc/SystemConfigFFmpegDto.md
|
doc/SystemConfigFFmpegDto.md
|
||||||
|
doc/SystemConfigImageDto.md
|
||||||
doc/SystemConfigJobDto.md
|
doc/SystemConfigJobDto.md
|
||||||
doc/SystemConfigLibraryDto.md
|
doc/SystemConfigLibraryDto.md
|
||||||
doc/SystemConfigLibraryScanDto.md
|
doc/SystemConfigLibraryScanDto.md
|
||||||
@ -160,7 +162,6 @@ doc/SystemConfigServerDto.md
|
|||||||
doc/SystemConfigStorageTemplateDto.md
|
doc/SystemConfigStorageTemplateDto.md
|
||||||
doc/SystemConfigTemplateStorageOptionDto.md
|
doc/SystemConfigTemplateStorageOptionDto.md
|
||||||
doc/SystemConfigThemeDto.md
|
doc/SystemConfigThemeDto.md
|
||||||
doc/SystemConfigThumbnailDto.md
|
|
||||||
doc/SystemConfigTrashDto.md
|
doc/SystemConfigTrashDto.md
|
||||||
doc/SystemConfigUserDto.md
|
doc/SystemConfigUserDto.md
|
||||||
doc/TagApi.md
|
doc/TagApi.md
|
||||||
@ -284,6 +285,7 @@ lib/model/file_checksum_response_dto.dart
|
|||||||
lib/model/file_report_dto.dart
|
lib/model/file_report_dto.dart
|
||||||
lib/model/file_report_fix_dto.dart
|
lib/model/file_report_fix_dto.dart
|
||||||
lib/model/file_report_item_dto.dart
|
lib/model/file_report_item_dto.dart
|
||||||
|
lib/model/image_format.dart
|
||||||
lib/model/job_command.dart
|
lib/model/job_command.dart
|
||||||
lib/model/job_command_dto.dart
|
lib/model/job_command_dto.dart
|
||||||
lib/model/job_counts_dto.dart
|
lib/model/job_counts_dto.dart
|
||||||
@ -348,6 +350,7 @@ lib/model/smart_info_response_dto.dart
|
|||||||
lib/model/smart_search_dto.dart
|
lib/model/smart_search_dto.dart
|
||||||
lib/model/system_config_dto.dart
|
lib/model/system_config_dto.dart
|
||||||
lib/model/system_config_f_fmpeg_dto.dart
|
lib/model/system_config_f_fmpeg_dto.dart
|
||||||
|
lib/model/system_config_image_dto.dart
|
||||||
lib/model/system_config_job_dto.dart
|
lib/model/system_config_job_dto.dart
|
||||||
lib/model/system_config_library_dto.dart
|
lib/model/system_config_library_dto.dart
|
||||||
lib/model/system_config_library_scan_dto.dart
|
lib/model/system_config_library_scan_dto.dart
|
||||||
@ -363,7 +366,6 @@ lib/model/system_config_server_dto.dart
|
|||||||
lib/model/system_config_storage_template_dto.dart
|
lib/model/system_config_storage_template_dto.dart
|
||||||
lib/model/system_config_template_storage_option_dto.dart
|
lib/model/system_config_template_storage_option_dto.dart
|
||||||
lib/model/system_config_theme_dto.dart
|
lib/model/system_config_theme_dto.dart
|
||||||
lib/model/system_config_thumbnail_dto.dart
|
|
||||||
lib/model/system_config_trash_dto.dart
|
lib/model/system_config_trash_dto.dart
|
||||||
lib/model/system_config_user_dto.dart
|
lib/model/system_config_user_dto.dart
|
||||||
lib/model/tag_response_dto.dart
|
lib/model/tag_response_dto.dart
|
||||||
@ -461,6 +463,7 @@ test/file_checksum_response_dto_test.dart
|
|||||||
test/file_report_dto_test.dart
|
test/file_report_dto_test.dart
|
||||||
test/file_report_fix_dto_test.dart
|
test/file_report_fix_dto_test.dart
|
||||||
test/file_report_item_dto_test.dart
|
test/file_report_item_dto_test.dart
|
||||||
|
test/image_format_test.dart
|
||||||
test/job_api_test.dart
|
test/job_api_test.dart
|
||||||
test/job_command_dto_test.dart
|
test/job_command_dto_test.dart
|
||||||
test/job_command_test.dart
|
test/job_command_test.dart
|
||||||
@ -534,6 +537,7 @@ test/smart_search_dto_test.dart
|
|||||||
test/system_config_api_test.dart
|
test/system_config_api_test.dart
|
||||||
test/system_config_dto_test.dart
|
test/system_config_dto_test.dart
|
||||||
test/system_config_f_fmpeg_dto_test.dart
|
test/system_config_f_fmpeg_dto_test.dart
|
||||||
|
test/system_config_image_dto_test.dart
|
||||||
test/system_config_job_dto_test.dart
|
test/system_config_job_dto_test.dart
|
||||||
test/system_config_library_dto_test.dart
|
test/system_config_library_dto_test.dart
|
||||||
test/system_config_library_scan_dto_test.dart
|
test/system_config_library_scan_dto_test.dart
|
||||||
@ -549,7 +553,6 @@ test/system_config_server_dto_test.dart
|
|||||||
test/system_config_storage_template_dto_test.dart
|
test/system_config_storage_template_dto_test.dart
|
||||||
test/system_config_template_storage_option_dto_test.dart
|
test/system_config_template_storage_option_dto_test.dart
|
||||||
test/system_config_theme_dto_test.dart
|
test/system_config_theme_dto_test.dart
|
||||||
test/system_config_thumbnail_dto_test.dart
|
|
||||||
test/system_config_trash_dto_test.dart
|
test/system_config_trash_dto_test.dart
|
||||||
test/system_config_user_dto_test.dart
|
test/system_config_user_dto_test.dart
|
||||||
test/tag_api_test.dart
|
test/tag_api_test.dart
|
||||||
|
3
mobile/openapi/README.md
generated
3
mobile/openapi/README.md
generated
@ -277,6 +277,7 @@ Class | Method | HTTP request | Description
|
|||||||
- [FileReportDto](doc//FileReportDto.md)
|
- [FileReportDto](doc//FileReportDto.md)
|
||||||
- [FileReportFixDto](doc//FileReportFixDto.md)
|
- [FileReportFixDto](doc//FileReportFixDto.md)
|
||||||
- [FileReportItemDto](doc//FileReportItemDto.md)
|
- [FileReportItemDto](doc//FileReportItemDto.md)
|
||||||
|
- [ImageFormat](doc//ImageFormat.md)
|
||||||
- [JobCommand](doc//JobCommand.md)
|
- [JobCommand](doc//JobCommand.md)
|
||||||
- [JobCommandDto](doc//JobCommandDto.md)
|
- [JobCommandDto](doc//JobCommandDto.md)
|
||||||
- [JobCountsDto](doc//JobCountsDto.md)
|
- [JobCountsDto](doc//JobCountsDto.md)
|
||||||
@ -341,6 +342,7 @@ Class | Method | HTTP request | Description
|
|||||||
- [SmartSearchDto](doc//SmartSearchDto.md)
|
- [SmartSearchDto](doc//SmartSearchDto.md)
|
||||||
- [SystemConfigDto](doc//SystemConfigDto.md)
|
- [SystemConfigDto](doc//SystemConfigDto.md)
|
||||||
- [SystemConfigFFmpegDto](doc//SystemConfigFFmpegDto.md)
|
- [SystemConfigFFmpegDto](doc//SystemConfigFFmpegDto.md)
|
||||||
|
- [SystemConfigImageDto](doc//SystemConfigImageDto.md)
|
||||||
- [SystemConfigJobDto](doc//SystemConfigJobDto.md)
|
- [SystemConfigJobDto](doc//SystemConfigJobDto.md)
|
||||||
- [SystemConfigLibraryDto](doc//SystemConfigLibraryDto.md)
|
- [SystemConfigLibraryDto](doc//SystemConfigLibraryDto.md)
|
||||||
- [SystemConfigLibraryScanDto](doc//SystemConfigLibraryScanDto.md)
|
- [SystemConfigLibraryScanDto](doc//SystemConfigLibraryScanDto.md)
|
||||||
@ -356,7 +358,6 @@ Class | Method | HTTP request | Description
|
|||||||
- [SystemConfigStorageTemplateDto](doc//SystemConfigStorageTemplateDto.md)
|
- [SystemConfigStorageTemplateDto](doc//SystemConfigStorageTemplateDto.md)
|
||||||
- [SystemConfigTemplateStorageOptionDto](doc//SystemConfigTemplateStorageOptionDto.md)
|
- [SystemConfigTemplateStorageOptionDto](doc//SystemConfigTemplateStorageOptionDto.md)
|
||||||
- [SystemConfigThemeDto](doc//SystemConfigThemeDto.md)
|
- [SystemConfigThemeDto](doc//SystemConfigThemeDto.md)
|
||||||
- [SystemConfigThumbnailDto](doc//SystemConfigThumbnailDto.md)
|
|
||||||
- [SystemConfigTrashDto](doc//SystemConfigTrashDto.md)
|
- [SystemConfigTrashDto](doc//SystemConfigTrashDto.md)
|
||||||
- [SystemConfigUserDto](doc//SystemConfigUserDto.md)
|
- [SystemConfigUserDto](doc//SystemConfigUserDto.md)
|
||||||
- [TagResponseDto](doc//TagResponseDto.md)
|
- [TagResponseDto](doc//TagResponseDto.md)
|
||||||
|
8
mobile/openapi/doc/AssetApi.md
generated
8
mobile/openapi/doc/AssetApi.md
generated
@ -886,7 +886,7 @@ void (empty response body)
|
|||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
# **searchAssets**
|
# **searchAssets**
|
||||||
> List<AssetResponseDto> searchAssets(checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, resizePath, size, state, takenAfter, takenBefore, trashedAfter, trashedBefore, type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked)
|
> List<AssetResponseDto> searchAssets(checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, previewPath, resizePath, size, state, takenAfter, takenBefore, thumbnailPath, trashedAfter, trashedBefore, type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -936,11 +936,13 @@ final originalFileName = originalFileName_example; // String |
|
|||||||
final originalPath = originalPath_example; // String |
|
final originalPath = originalPath_example; // String |
|
||||||
final page = 8.14; // num |
|
final page = 8.14; // num |
|
||||||
final personIds = []; // List<String> |
|
final personIds = []; // List<String> |
|
||||||
|
final previewPath = previewPath_example; // String |
|
||||||
final resizePath = resizePath_example; // String |
|
final resizePath = resizePath_example; // String |
|
||||||
final size = 8.14; // num |
|
final size = 8.14; // num |
|
||||||
final state = state_example; // String |
|
final state = state_example; // String |
|
||||||
final takenAfter = 2013-10-20T19:20:30+01:00; // DateTime |
|
final takenAfter = 2013-10-20T19:20:30+01:00; // DateTime |
|
||||||
final takenBefore = 2013-10-20T19:20:30+01:00; // DateTime |
|
final takenBefore = 2013-10-20T19:20:30+01:00; // DateTime |
|
||||||
|
final thumbnailPath = thumbnailPath_example; // String |
|
||||||
final trashedAfter = 2013-10-20T19:20:30+01:00; // DateTime |
|
final trashedAfter = 2013-10-20T19:20:30+01:00; // DateTime |
|
||||||
final trashedBefore = 2013-10-20T19:20:30+01:00; // DateTime |
|
final trashedBefore = 2013-10-20T19:20:30+01:00; // DateTime |
|
||||||
final type = ; // AssetTypeEnum |
|
final type = ; // AssetTypeEnum |
|
||||||
@ -954,7 +956,7 @@ final withPeople = true; // bool |
|
|||||||
final withStacked = true; // bool |
|
final withStacked = true; // bool |
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final result = api_instance.searchAssets(checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, resizePath, size, state, takenAfter, takenBefore, trashedAfter, trashedBefore, type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked);
|
final result = api_instance.searchAssets(checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, previewPath, resizePath, size, state, takenAfter, takenBefore, thumbnailPath, trashedAfter, trashedBefore, type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked);
|
||||||
print(result);
|
print(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Exception when calling AssetApi->searchAssets: $e\n');
|
print('Exception when calling AssetApi->searchAssets: $e\n');
|
||||||
@ -992,11 +994,13 @@ Name | Type | Description | Notes
|
|||||||
**originalPath** | **String**| | [optional]
|
**originalPath** | **String**| | [optional]
|
||||||
**page** | **num**| | [optional]
|
**page** | **num**| | [optional]
|
||||||
**personIds** | [**List<String>**](String.md)| | [optional] [default to const []]
|
**personIds** | [**List<String>**](String.md)| | [optional] [default to const []]
|
||||||
|
**previewPath** | **String**| | [optional]
|
||||||
**resizePath** | **String**| | [optional]
|
**resizePath** | **String**| | [optional]
|
||||||
**size** | **num**| | [optional]
|
**size** | **num**| | [optional]
|
||||||
**state** | **String**| | [optional]
|
**state** | **String**| | [optional]
|
||||||
**takenAfter** | **DateTime**| | [optional]
|
**takenAfter** | **DateTime**| | [optional]
|
||||||
**takenBefore** | **DateTime**| | [optional]
|
**takenBefore** | **DateTime**| | [optional]
|
||||||
|
**thumbnailPath** | **String**| | [optional]
|
||||||
**trashedAfter** | **DateTime**| | [optional]
|
**trashedAfter** | **DateTime**| | [optional]
|
||||||
**trashedBefore** | **DateTime**| | [optional]
|
**trashedBefore** | **DateTime**| | [optional]
|
||||||
**type** | [**AssetTypeEnum**](.md)| | [optional]
|
**type** | [**AssetTypeEnum**](.md)| | [optional]
|
||||||
|
14
mobile/openapi/doc/ImageFormat.md
generated
Normal file
14
mobile/openapi/doc/ImageFormat.md
generated
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# openapi.model.ImageFormat
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
2
mobile/openapi/doc/MetadataSearchDto.md
generated
2
mobile/openapi/doc/MetadataSearchDto.md
generated
@ -35,11 +35,13 @@ Name | Type | Description | Notes
|
|||||||
**originalPath** | **String** | | [optional]
|
**originalPath** | **String** | | [optional]
|
||||||
**page** | **num** | | [optional]
|
**page** | **num** | | [optional]
|
||||||
**personIds** | **List<String>** | | [optional] [default to const []]
|
**personIds** | **List<String>** | | [optional] [default to const []]
|
||||||
|
**previewPath** | **String** | | [optional]
|
||||||
**resizePath** | **String** | | [optional]
|
**resizePath** | **String** | | [optional]
|
||||||
**size** | **num** | | [optional]
|
**size** | **num** | | [optional]
|
||||||
**state** | **String** | | [optional]
|
**state** | **String** | | [optional]
|
||||||
**takenAfter** | [**DateTime**](DateTime.md) | | [optional]
|
**takenAfter** | [**DateTime**](DateTime.md) | | [optional]
|
||||||
**takenBefore** | [**DateTime**](DateTime.md) | | [optional]
|
**takenBefore** | [**DateTime**](DateTime.md) | | [optional]
|
||||||
|
**thumbnailPath** | **String** | | [optional]
|
||||||
**trashedAfter** | [**DateTime**](DateTime.md) | | [optional]
|
**trashedAfter** | [**DateTime**](DateTime.md) | | [optional]
|
||||||
**trashedBefore** | [**DateTime**](DateTime.md) | | [optional]
|
**trashedBefore** | [**DateTime**](DateTime.md) | | [optional]
|
||||||
**type** | [**AssetTypeEnum**](AssetTypeEnum.md) | | [optional]
|
**type** | [**AssetTypeEnum**](AssetTypeEnum.md) | | [optional]
|
||||||
|
2
mobile/openapi/doc/SystemConfigDto.md
generated
2
mobile/openapi/doc/SystemConfigDto.md
generated
@ -9,6 +9,7 @@ import 'package:openapi/api.dart';
|
|||||||
Name | Type | Description | Notes
|
Name | Type | Description | Notes
|
||||||
------------ | ------------- | ------------- | -------------
|
------------ | ------------- | ------------- | -------------
|
||||||
**ffmpeg** | [**SystemConfigFFmpegDto**](SystemConfigFFmpegDto.md) | |
|
**ffmpeg** | [**SystemConfigFFmpegDto**](SystemConfigFFmpegDto.md) | |
|
||||||
|
**image** | [**SystemConfigImageDto**](SystemConfigImageDto.md) | |
|
||||||
**job** | [**SystemConfigJobDto**](SystemConfigJobDto.md) | |
|
**job** | [**SystemConfigJobDto**](SystemConfigJobDto.md) | |
|
||||||
**library_** | [**SystemConfigLibraryDto**](SystemConfigLibraryDto.md) | |
|
**library_** | [**SystemConfigLibraryDto**](SystemConfigLibraryDto.md) | |
|
||||||
**logging** | [**SystemConfigLoggingDto**](SystemConfigLoggingDto.md) | |
|
**logging** | [**SystemConfigLoggingDto**](SystemConfigLoggingDto.md) | |
|
||||||
@ -21,7 +22,6 @@ Name | Type | Description | Notes
|
|||||||
**server** | [**SystemConfigServerDto**](SystemConfigServerDto.md) | |
|
**server** | [**SystemConfigServerDto**](SystemConfigServerDto.md) | |
|
||||||
**storageTemplate** | [**SystemConfigStorageTemplateDto**](SystemConfigStorageTemplateDto.md) | |
|
**storageTemplate** | [**SystemConfigStorageTemplateDto**](SystemConfigStorageTemplateDto.md) | |
|
||||||
**theme** | [**SystemConfigThemeDto**](SystemConfigThemeDto.md) | |
|
**theme** | [**SystemConfigThemeDto**](SystemConfigThemeDto.md) | |
|
||||||
**thumbnail** | [**SystemConfigThumbnailDto**](SystemConfigThumbnailDto.md) | |
|
|
||||||
**trash** | [**SystemConfigTrashDto**](SystemConfigTrashDto.md) | |
|
**trash** | [**SystemConfigTrashDto**](SystemConfigTrashDto.md) | |
|
||||||
**user** | [**SystemConfigUserDto**](SystemConfigUserDto.md) | |
|
**user** | [**SystemConfigUserDto**](SystemConfigUserDto.md) | |
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# openapi.model.SystemConfigThumbnailDto
|
# openapi.model.SystemConfigImageDto
|
||||||
|
|
||||||
## Load the model package
|
## Load the model package
|
||||||
```dart
|
```dart
|
||||||
@ -9,9 +9,11 @@ import 'package:openapi/api.dart';
|
|||||||
Name | Type | Description | Notes
|
Name | Type | Description | Notes
|
||||||
------------ | ------------- | ------------- | -------------
|
------------ | ------------- | ------------- | -------------
|
||||||
**colorspace** | [**Colorspace**](Colorspace.md) | |
|
**colorspace** | [**Colorspace**](Colorspace.md) | |
|
||||||
**jpegSize** | **int** | |
|
**previewFormat** | [**ImageFormat**](ImageFormat.md) | |
|
||||||
|
**previewSize** | **int** | |
|
||||||
**quality** | **int** | |
|
**quality** | **int** | |
|
||||||
**webpSize** | **int** | |
|
**thumbnailFormat** | [**ImageFormat**](ImageFormat.md) | |
|
||||||
|
**thumbnailSize** | **int** | |
|
||||||
|
|
||||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
3
mobile/openapi/lib/api.dart
generated
3
mobile/openapi/lib/api.dart
generated
@ -112,6 +112,7 @@ part 'model/file_checksum_response_dto.dart';
|
|||||||
part 'model/file_report_dto.dart';
|
part 'model/file_report_dto.dart';
|
||||||
part 'model/file_report_fix_dto.dart';
|
part 'model/file_report_fix_dto.dart';
|
||||||
part 'model/file_report_item_dto.dart';
|
part 'model/file_report_item_dto.dart';
|
||||||
|
part 'model/image_format.dart';
|
||||||
part 'model/job_command.dart';
|
part 'model/job_command.dart';
|
||||||
part 'model/job_command_dto.dart';
|
part 'model/job_command_dto.dart';
|
||||||
part 'model/job_counts_dto.dart';
|
part 'model/job_counts_dto.dart';
|
||||||
@ -176,6 +177,7 @@ part 'model/smart_info_response_dto.dart';
|
|||||||
part 'model/smart_search_dto.dart';
|
part 'model/smart_search_dto.dart';
|
||||||
part 'model/system_config_dto.dart';
|
part 'model/system_config_dto.dart';
|
||||||
part 'model/system_config_f_fmpeg_dto.dart';
|
part 'model/system_config_f_fmpeg_dto.dart';
|
||||||
|
part 'model/system_config_image_dto.dart';
|
||||||
part 'model/system_config_job_dto.dart';
|
part 'model/system_config_job_dto.dart';
|
||||||
part 'model/system_config_library_dto.dart';
|
part 'model/system_config_library_dto.dart';
|
||||||
part 'model/system_config_library_scan_dto.dart';
|
part 'model/system_config_library_scan_dto.dart';
|
||||||
@ -191,7 +193,6 @@ part 'model/system_config_server_dto.dart';
|
|||||||
part 'model/system_config_storage_template_dto.dart';
|
part 'model/system_config_storage_template_dto.dart';
|
||||||
part 'model/system_config_template_storage_option_dto.dart';
|
part 'model/system_config_template_storage_option_dto.dart';
|
||||||
part 'model/system_config_theme_dto.dart';
|
part 'model/system_config_theme_dto.dart';
|
||||||
part 'model/system_config_thumbnail_dto.dart';
|
|
||||||
part 'model/system_config_trash_dto.dart';
|
part 'model/system_config_trash_dto.dart';
|
||||||
part 'model/system_config_user_dto.dart';
|
part 'model/system_config_user_dto.dart';
|
||||||
part 'model/tag_response_dto.dart';
|
part 'model/tag_response_dto.dart';
|
||||||
|
20
mobile/openapi/lib/api/asset_api.dart
generated
20
mobile/openapi/lib/api/asset_api.dart
generated
@ -931,6 +931,8 @@ class AssetApi {
|
|||||||
///
|
///
|
||||||
/// * [List<String>] personIds:
|
/// * [List<String>] personIds:
|
||||||
///
|
///
|
||||||
|
/// * [String] previewPath:
|
||||||
|
///
|
||||||
/// * [String] resizePath:
|
/// * [String] resizePath:
|
||||||
///
|
///
|
||||||
/// * [num] size:
|
/// * [num] size:
|
||||||
@ -941,6 +943,8 @@ class AssetApi {
|
|||||||
///
|
///
|
||||||
/// * [DateTime] takenBefore:
|
/// * [DateTime] takenBefore:
|
||||||
///
|
///
|
||||||
|
/// * [String] thumbnailPath:
|
||||||
|
///
|
||||||
/// * [DateTime] trashedAfter:
|
/// * [DateTime] trashedAfter:
|
||||||
///
|
///
|
||||||
/// * [DateTime] trashedBefore:
|
/// * [DateTime] trashedBefore:
|
||||||
@ -962,7 +966,7 @@ class AssetApi {
|
|||||||
/// * [bool] withPeople:
|
/// * [bool] withPeople:
|
||||||
///
|
///
|
||||||
/// * [bool] withStacked:
|
/// * [bool] withStacked:
|
||||||
Future<Response> searchAssetsWithHttpInfo({ String? checksum, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceAssetId, String? deviceId, String? encodedVideoPath, String? id, bool? isArchived, bool? isEncoded, bool? isExternal, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, bool? isReadOnly, bool? isVisible, String? lensModel, String? libraryId, String? make, String? model, AssetOrder? order, String? originalFileName, String? originalPath, num? page, List<String>? personIds, String? resizePath, num? size, String? state, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, String? webpPath, bool? withArchived, bool? withDeleted, bool? withExif, bool? withPeople, bool? withStacked, }) async {
|
Future<Response> searchAssetsWithHttpInfo({ String? checksum, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceAssetId, String? deviceId, String? encodedVideoPath, String? id, bool? isArchived, bool? isEncoded, bool? isExternal, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, bool? isReadOnly, bool? isVisible, String? lensModel, String? libraryId, String? make, String? model, AssetOrder? order, String? originalFileName, String? originalPath, num? page, List<String>? personIds, String? previewPath, String? resizePath, num? size, String? state, DateTime? takenAfter, DateTime? takenBefore, String? thumbnailPath, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, String? webpPath, bool? withArchived, bool? withDeleted, bool? withExif, bool? withPeople, bool? withStacked, }) async {
|
||||||
// ignore: prefer_const_declarations
|
// ignore: prefer_const_declarations
|
||||||
final path = r'/assets';
|
final path = r'/assets';
|
||||||
|
|
||||||
@ -1054,6 +1058,9 @@ class AssetApi {
|
|||||||
if (personIds != null) {
|
if (personIds != null) {
|
||||||
queryParams.addAll(_queryParams('multi', 'personIds', personIds));
|
queryParams.addAll(_queryParams('multi', 'personIds', personIds));
|
||||||
}
|
}
|
||||||
|
if (previewPath != null) {
|
||||||
|
queryParams.addAll(_queryParams('', 'previewPath', previewPath));
|
||||||
|
}
|
||||||
if (resizePath != null) {
|
if (resizePath != null) {
|
||||||
queryParams.addAll(_queryParams('', 'resizePath', resizePath));
|
queryParams.addAll(_queryParams('', 'resizePath', resizePath));
|
||||||
}
|
}
|
||||||
@ -1069,6 +1076,9 @@ class AssetApi {
|
|||||||
if (takenBefore != null) {
|
if (takenBefore != null) {
|
||||||
queryParams.addAll(_queryParams('', 'takenBefore', takenBefore));
|
queryParams.addAll(_queryParams('', 'takenBefore', takenBefore));
|
||||||
}
|
}
|
||||||
|
if (thumbnailPath != null) {
|
||||||
|
queryParams.addAll(_queryParams('', 'thumbnailPath', thumbnailPath));
|
||||||
|
}
|
||||||
if (trashedAfter != null) {
|
if (trashedAfter != null) {
|
||||||
queryParams.addAll(_queryParams('', 'trashedAfter', trashedAfter));
|
queryParams.addAll(_queryParams('', 'trashedAfter', trashedAfter));
|
||||||
}
|
}
|
||||||
@ -1173,6 +1183,8 @@ class AssetApi {
|
|||||||
///
|
///
|
||||||
/// * [List<String>] personIds:
|
/// * [List<String>] personIds:
|
||||||
///
|
///
|
||||||
|
/// * [String] previewPath:
|
||||||
|
///
|
||||||
/// * [String] resizePath:
|
/// * [String] resizePath:
|
||||||
///
|
///
|
||||||
/// * [num] size:
|
/// * [num] size:
|
||||||
@ -1183,6 +1195,8 @@ class AssetApi {
|
|||||||
///
|
///
|
||||||
/// * [DateTime] takenBefore:
|
/// * [DateTime] takenBefore:
|
||||||
///
|
///
|
||||||
|
/// * [String] thumbnailPath:
|
||||||
|
///
|
||||||
/// * [DateTime] trashedAfter:
|
/// * [DateTime] trashedAfter:
|
||||||
///
|
///
|
||||||
/// * [DateTime] trashedBefore:
|
/// * [DateTime] trashedBefore:
|
||||||
@ -1204,8 +1218,8 @@ class AssetApi {
|
|||||||
/// * [bool] withPeople:
|
/// * [bool] withPeople:
|
||||||
///
|
///
|
||||||
/// * [bool] withStacked:
|
/// * [bool] withStacked:
|
||||||
Future<List<AssetResponseDto>?> searchAssets({ String? checksum, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceAssetId, String? deviceId, String? encodedVideoPath, String? id, bool? isArchived, bool? isEncoded, bool? isExternal, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, bool? isReadOnly, bool? isVisible, String? lensModel, String? libraryId, String? make, String? model, AssetOrder? order, String? originalFileName, String? originalPath, num? page, List<String>? personIds, String? resizePath, num? size, String? state, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, String? webpPath, bool? withArchived, bool? withDeleted, bool? withExif, bool? withPeople, bool? withStacked, }) async {
|
Future<List<AssetResponseDto>?> searchAssets({ String? checksum, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceAssetId, String? deviceId, String? encodedVideoPath, String? id, bool? isArchived, bool? isEncoded, bool? isExternal, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, bool? isReadOnly, bool? isVisible, String? lensModel, String? libraryId, String? make, String? model, AssetOrder? order, String? originalFileName, String? originalPath, num? page, List<String>? personIds, String? previewPath, String? resizePath, num? size, String? state, DateTime? takenAfter, DateTime? takenBefore, String? thumbnailPath, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, String? webpPath, bool? withArchived, bool? withDeleted, bool? withExif, bool? withPeople, bool? withStacked, }) async {
|
||||||
final response = await searchAssetsWithHttpInfo( checksum: checksum, city: city, country: country, createdAfter: createdAfter, createdBefore: createdBefore, deviceAssetId: deviceAssetId, deviceId: deviceId, encodedVideoPath: encodedVideoPath, id: id, isArchived: isArchived, isEncoded: isEncoded, isExternal: isExternal, isFavorite: isFavorite, isMotion: isMotion, isNotInAlbum: isNotInAlbum, isOffline: isOffline, isReadOnly: isReadOnly, isVisible: isVisible, lensModel: lensModel, libraryId: libraryId, make: make, model: model, order: order, originalFileName: originalFileName, originalPath: originalPath, page: page, personIds: personIds, resizePath: resizePath, size: size, state: state, takenAfter: takenAfter, takenBefore: takenBefore, trashedAfter: trashedAfter, trashedBefore: trashedBefore, type: type, updatedAfter: updatedAfter, updatedBefore: updatedBefore, webpPath: webpPath, withArchived: withArchived, withDeleted: withDeleted, withExif: withExif, withPeople: withPeople, withStacked: withStacked, );
|
final response = await searchAssetsWithHttpInfo( checksum: checksum, city: city, country: country, createdAfter: createdAfter, createdBefore: createdBefore, deviceAssetId: deviceAssetId, deviceId: deviceId, encodedVideoPath: encodedVideoPath, id: id, isArchived: isArchived, isEncoded: isEncoded, isExternal: isExternal, isFavorite: isFavorite, isMotion: isMotion, isNotInAlbum: isNotInAlbum, isOffline: isOffline, isReadOnly: isReadOnly, isVisible: isVisible, lensModel: lensModel, libraryId: libraryId, make: make, model: model, order: order, originalFileName: originalFileName, originalPath: originalPath, page: page, personIds: personIds, previewPath: previewPath, resizePath: resizePath, size: size, state: state, takenAfter: takenAfter, takenBefore: takenBefore, thumbnailPath: thumbnailPath, trashedAfter: trashedAfter, trashedBefore: trashedBefore, type: type, updatedAfter: updatedAfter, updatedBefore: updatedBefore, webpPath: webpPath, withArchived: withArchived, withDeleted: withDeleted, withExif: withExif, withPeople: withPeople, withStacked: withStacked, );
|
||||||
if (response.statusCode >= HttpStatus.badRequest) {
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
}
|
}
|
||||||
|
6
mobile/openapi/lib/api_client.dart
generated
6
mobile/openapi/lib/api_client.dart
generated
@ -304,6 +304,8 @@ class ApiClient {
|
|||||||
return FileReportFixDto.fromJson(value);
|
return FileReportFixDto.fromJson(value);
|
||||||
case 'FileReportItemDto':
|
case 'FileReportItemDto':
|
||||||
return FileReportItemDto.fromJson(value);
|
return FileReportItemDto.fromJson(value);
|
||||||
|
case 'ImageFormat':
|
||||||
|
return ImageFormatTypeTransformer().decode(value);
|
||||||
case 'JobCommand':
|
case 'JobCommand':
|
||||||
return JobCommandTypeTransformer().decode(value);
|
return JobCommandTypeTransformer().decode(value);
|
||||||
case 'JobCommandDto':
|
case 'JobCommandDto':
|
||||||
@ -432,6 +434,8 @@ class ApiClient {
|
|||||||
return SystemConfigDto.fromJson(value);
|
return SystemConfigDto.fromJson(value);
|
||||||
case 'SystemConfigFFmpegDto':
|
case 'SystemConfigFFmpegDto':
|
||||||
return SystemConfigFFmpegDto.fromJson(value);
|
return SystemConfigFFmpegDto.fromJson(value);
|
||||||
|
case 'SystemConfigImageDto':
|
||||||
|
return SystemConfigImageDto.fromJson(value);
|
||||||
case 'SystemConfigJobDto':
|
case 'SystemConfigJobDto':
|
||||||
return SystemConfigJobDto.fromJson(value);
|
return SystemConfigJobDto.fromJson(value);
|
||||||
case 'SystemConfigLibraryDto':
|
case 'SystemConfigLibraryDto':
|
||||||
@ -462,8 +466,6 @@ class ApiClient {
|
|||||||
return SystemConfigTemplateStorageOptionDto.fromJson(value);
|
return SystemConfigTemplateStorageOptionDto.fromJson(value);
|
||||||
case 'SystemConfigThemeDto':
|
case 'SystemConfigThemeDto':
|
||||||
return SystemConfigThemeDto.fromJson(value);
|
return SystemConfigThemeDto.fromJson(value);
|
||||||
case 'SystemConfigThumbnailDto':
|
|
||||||
return SystemConfigThumbnailDto.fromJson(value);
|
|
||||||
case 'SystemConfigTrashDto':
|
case 'SystemConfigTrashDto':
|
||||||
return SystemConfigTrashDto.fromJson(value);
|
return SystemConfigTrashDto.fromJson(value);
|
||||||
case 'SystemConfigUserDto':
|
case 'SystemConfigUserDto':
|
||||||
|
3
mobile/openapi/lib/api_helper.dart
generated
3
mobile/openapi/lib/api_helper.dart
generated
@ -79,6 +79,9 @@ String parameterToString(dynamic value) {
|
|||||||
if (value is EntityType) {
|
if (value is EntityType) {
|
||||||
return EntityTypeTypeTransformer().encode(value).toString();
|
return EntityTypeTypeTransformer().encode(value).toString();
|
||||||
}
|
}
|
||||||
|
if (value is ImageFormat) {
|
||||||
|
return ImageFormatTypeTransformer().encode(value).toString();
|
||||||
|
}
|
||||||
if (value is JobCommand) {
|
if (value is JobCommand) {
|
||||||
return JobCommandTypeTransformer().encode(value).toString();
|
return JobCommandTypeTransformer().encode(value).toString();
|
||||||
}
|
}
|
||||||
|
85
mobile/openapi/lib/model/image_format.dart
generated
Normal file
85
mobile/openapi/lib/model/image_format.dart
generated
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
|
||||||
|
class ImageFormat {
|
||||||
|
/// Instantiate a new enum with the provided [value].
|
||||||
|
const ImageFormat._(this.value);
|
||||||
|
|
||||||
|
/// The underlying value of this enum member.
|
||||||
|
final String value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => value;
|
||||||
|
|
||||||
|
String toJson() => value;
|
||||||
|
|
||||||
|
static const jpeg = ImageFormat._(r'jpeg');
|
||||||
|
static const webp = ImageFormat._(r'webp');
|
||||||
|
|
||||||
|
/// List of all possible values in this [enum][ImageFormat].
|
||||||
|
static const values = <ImageFormat>[
|
||||||
|
jpeg,
|
||||||
|
webp,
|
||||||
|
];
|
||||||
|
|
||||||
|
static ImageFormat? fromJson(dynamic value) => ImageFormatTypeTransformer().decode(value);
|
||||||
|
|
||||||
|
static List<ImageFormat> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <ImageFormat>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = ImageFormat.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transformation class that can [encode] an instance of [ImageFormat] to String,
|
||||||
|
/// and [decode] dynamic data back to [ImageFormat].
|
||||||
|
class ImageFormatTypeTransformer {
|
||||||
|
factory ImageFormatTypeTransformer() => _instance ??= const ImageFormatTypeTransformer._();
|
||||||
|
|
||||||
|
const ImageFormatTypeTransformer._();
|
||||||
|
|
||||||
|
String encode(ImageFormat data) => data.value;
|
||||||
|
|
||||||
|
/// Decodes a [dynamic value][data] to a ImageFormat.
|
||||||
|
///
|
||||||
|
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||||
|
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||||
|
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||||
|
///
|
||||||
|
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||||
|
/// and users are still using an old app with the old code.
|
||||||
|
ImageFormat? decode(dynamic data, {bool allowNull = true}) {
|
||||||
|
if (data != null) {
|
||||||
|
switch (data) {
|
||||||
|
case r'jpeg': return ImageFormat.jpeg;
|
||||||
|
case r'webp': return ImageFormat.webp;
|
||||||
|
default:
|
||||||
|
if (!allowNull) {
|
||||||
|
throw ArgumentError('Unknown enum value to decode: $data');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Singleton [ImageFormatTypeTransformer] instance.
|
||||||
|
static ImageFormatTypeTransformer? _instance;
|
||||||
|
}
|
||||||
|
|
36
mobile/openapi/lib/model/metadata_search_dto.dart
generated
36
mobile/openapi/lib/model/metadata_search_dto.dart
generated
@ -40,11 +40,13 @@ class MetadataSearchDto {
|
|||||||
this.originalPath,
|
this.originalPath,
|
||||||
this.page,
|
this.page,
|
||||||
this.personIds = const [],
|
this.personIds = const [],
|
||||||
|
this.previewPath,
|
||||||
this.resizePath,
|
this.resizePath,
|
||||||
this.size,
|
this.size,
|
||||||
this.state,
|
this.state,
|
||||||
this.takenAfter,
|
this.takenAfter,
|
||||||
this.takenBefore,
|
this.takenBefore,
|
||||||
|
this.thumbnailPath,
|
||||||
this.trashedAfter,
|
this.trashedAfter,
|
||||||
this.trashedBefore,
|
this.trashedBefore,
|
||||||
this.type,
|
this.type,
|
||||||
@ -268,6 +270,14 @@ class MetadataSearchDto {
|
|||||||
|
|
||||||
List<String> personIds;
|
List<String> personIds;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
|
/// source code must fall back to having a nullable type.
|
||||||
|
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||||
|
///
|
||||||
|
String? previewPath;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
/// does not include a default value (using the "default:" property), however, the generated
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
@ -308,6 +318,14 @@ class MetadataSearchDto {
|
|||||||
///
|
///
|
||||||
DateTime? takenBefore;
|
DateTime? takenBefore;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
|
/// source code must fall back to having a nullable type.
|
||||||
|
/// Consider adding a "default:" property in the specification file to hide this note.
|
||||||
|
///
|
||||||
|
String? thumbnailPath;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
/// does not include a default value (using the "default:" property), however, the generated
|
/// does not include a default value (using the "default:" property), however, the generated
|
||||||
@ -419,11 +437,13 @@ class MetadataSearchDto {
|
|||||||
other.originalPath == originalPath &&
|
other.originalPath == originalPath &&
|
||||||
other.page == page &&
|
other.page == page &&
|
||||||
_deepEquality.equals(other.personIds, personIds) &&
|
_deepEquality.equals(other.personIds, personIds) &&
|
||||||
|
other.previewPath == previewPath &&
|
||||||
other.resizePath == resizePath &&
|
other.resizePath == resizePath &&
|
||||||
other.size == size &&
|
other.size == size &&
|
||||||
other.state == state &&
|
other.state == state &&
|
||||||
other.takenAfter == takenAfter &&
|
other.takenAfter == takenAfter &&
|
||||||
other.takenBefore == takenBefore &&
|
other.takenBefore == takenBefore &&
|
||||||
|
other.thumbnailPath == thumbnailPath &&
|
||||||
other.trashedAfter == trashedAfter &&
|
other.trashedAfter == trashedAfter &&
|
||||||
other.trashedBefore == trashedBefore &&
|
other.trashedBefore == trashedBefore &&
|
||||||
other.type == type &&
|
other.type == type &&
|
||||||
@ -466,11 +486,13 @@ class MetadataSearchDto {
|
|||||||
(originalPath == null ? 0 : originalPath!.hashCode) +
|
(originalPath == null ? 0 : originalPath!.hashCode) +
|
||||||
(page == null ? 0 : page!.hashCode) +
|
(page == null ? 0 : page!.hashCode) +
|
||||||
(personIds.hashCode) +
|
(personIds.hashCode) +
|
||||||
|
(previewPath == null ? 0 : previewPath!.hashCode) +
|
||||||
(resizePath == null ? 0 : resizePath!.hashCode) +
|
(resizePath == null ? 0 : resizePath!.hashCode) +
|
||||||
(size == null ? 0 : size!.hashCode) +
|
(size == null ? 0 : size!.hashCode) +
|
||||||
(state == null ? 0 : state!.hashCode) +
|
(state == null ? 0 : state!.hashCode) +
|
||||||
(takenAfter == null ? 0 : takenAfter!.hashCode) +
|
(takenAfter == null ? 0 : takenAfter!.hashCode) +
|
||||||
(takenBefore == null ? 0 : takenBefore!.hashCode) +
|
(takenBefore == null ? 0 : takenBefore!.hashCode) +
|
||||||
|
(thumbnailPath == null ? 0 : thumbnailPath!.hashCode) +
|
||||||
(trashedAfter == null ? 0 : trashedAfter!.hashCode) +
|
(trashedAfter == null ? 0 : trashedAfter!.hashCode) +
|
||||||
(trashedBefore == null ? 0 : trashedBefore!.hashCode) +
|
(trashedBefore == null ? 0 : trashedBefore!.hashCode) +
|
||||||
(type == null ? 0 : type!.hashCode) +
|
(type == null ? 0 : type!.hashCode) +
|
||||||
@ -484,7 +506,7 @@ class MetadataSearchDto {
|
|||||||
(withStacked == null ? 0 : withStacked!.hashCode);
|
(withStacked == null ? 0 : withStacked!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'MetadataSearchDto[checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceAssetId=$deviceAssetId, deviceId=$deviceId, encodedVideoPath=$encodedVideoPath, id=$id, isArchived=$isArchived, isEncoded=$isEncoded, isExternal=$isExternal, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isReadOnly=$isReadOnly, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, resizePath=$resizePath, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, webpPath=$webpPath, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
|
String toString() => 'MetadataSearchDto[checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceAssetId=$deviceAssetId, deviceId=$deviceId, encodedVideoPath=$encodedVideoPath, id=$id, isArchived=$isArchived, isEncoded=$isEncoded, isExternal=$isExternal, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, isReadOnly=$isReadOnly, isVisible=$isVisible, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, previewPath=$previewPath, resizePath=$resizePath, size=$size, state=$state, takenAfter=$takenAfter, takenBefore=$takenBefore, thumbnailPath=$thumbnailPath, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, webpPath=$webpPath, withArchived=$withArchived, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@ -619,6 +641,11 @@ class MetadataSearchDto {
|
|||||||
// json[r'page'] = null;
|
// json[r'page'] = null;
|
||||||
}
|
}
|
||||||
json[r'personIds'] = this.personIds;
|
json[r'personIds'] = this.personIds;
|
||||||
|
if (this.previewPath != null) {
|
||||||
|
json[r'previewPath'] = this.previewPath;
|
||||||
|
} else {
|
||||||
|
// json[r'previewPath'] = null;
|
||||||
|
}
|
||||||
if (this.resizePath != null) {
|
if (this.resizePath != null) {
|
||||||
json[r'resizePath'] = this.resizePath;
|
json[r'resizePath'] = this.resizePath;
|
||||||
} else {
|
} else {
|
||||||
@ -644,6 +671,11 @@ class MetadataSearchDto {
|
|||||||
} else {
|
} else {
|
||||||
// json[r'takenBefore'] = null;
|
// json[r'takenBefore'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.thumbnailPath != null) {
|
||||||
|
json[r'thumbnailPath'] = this.thumbnailPath;
|
||||||
|
} else {
|
||||||
|
// json[r'thumbnailPath'] = null;
|
||||||
|
}
|
||||||
if (this.trashedAfter != null) {
|
if (this.trashedAfter != null) {
|
||||||
json[r'trashedAfter'] = this.trashedAfter!.toUtc().toIso8601String();
|
json[r'trashedAfter'] = this.trashedAfter!.toUtc().toIso8601String();
|
||||||
} else {
|
} else {
|
||||||
@ -735,11 +767,13 @@ class MetadataSearchDto {
|
|||||||
personIds: json[r'personIds'] is Iterable
|
personIds: json[r'personIds'] is Iterable
|
||||||
? (json[r'personIds'] as Iterable).cast<String>().toList(growable: false)
|
? (json[r'personIds'] as Iterable).cast<String>().toList(growable: false)
|
||||||
: const [],
|
: const [],
|
||||||
|
previewPath: mapValueOfType<String>(json, r'previewPath'),
|
||||||
resizePath: mapValueOfType<String>(json, r'resizePath'),
|
resizePath: mapValueOfType<String>(json, r'resizePath'),
|
||||||
size: num.parse('${json[r'size']}'),
|
size: num.parse('${json[r'size']}'),
|
||||||
state: mapValueOfType<String>(json, r'state'),
|
state: mapValueOfType<String>(json, r'state'),
|
||||||
takenAfter: mapDateTime(json, r'takenAfter', r''),
|
takenAfter: mapDateTime(json, r'takenAfter', r''),
|
||||||
takenBefore: mapDateTime(json, r'takenBefore', r''),
|
takenBefore: mapDateTime(json, r'takenBefore', r''),
|
||||||
|
thumbnailPath: mapValueOfType<String>(json, r'thumbnailPath'),
|
||||||
trashedAfter: mapDateTime(json, r'trashedAfter', r''),
|
trashedAfter: mapDateTime(json, r'trashedAfter', r''),
|
||||||
trashedBefore: mapDateTime(json, r'trashedBefore', r''),
|
trashedBefore: mapDateTime(json, r'trashedBefore', r''),
|
||||||
type: AssetTypeEnum.fromJson(json[r'type']),
|
type: AssetTypeEnum.fromJson(json[r'type']),
|
||||||
|
12
mobile/openapi/lib/model/path_type.dart
generated
12
mobile/openapi/lib/model/path_type.dart
generated
@ -24,8 +24,8 @@ class PathType {
|
|||||||
String toJson() => value;
|
String toJson() => value;
|
||||||
|
|
||||||
static const original = PathType._(r'original');
|
static const original = PathType._(r'original');
|
||||||
static const jpegThumbnail = PathType._(r'jpeg_thumbnail');
|
static const preview = PathType._(r'preview');
|
||||||
static const webpThumbnail = PathType._(r'webp_thumbnail');
|
static const thumbnail = PathType._(r'thumbnail');
|
||||||
static const encodedVideo = PathType._(r'encoded_video');
|
static const encodedVideo = PathType._(r'encoded_video');
|
||||||
static const sidecar = PathType._(r'sidecar');
|
static const sidecar = PathType._(r'sidecar');
|
||||||
static const face = PathType._(r'face');
|
static const face = PathType._(r'face');
|
||||||
@ -34,8 +34,8 @@ class PathType {
|
|||||||
/// List of all possible values in this [enum][PathType].
|
/// List of all possible values in this [enum][PathType].
|
||||||
static const values = <PathType>[
|
static const values = <PathType>[
|
||||||
original,
|
original,
|
||||||
jpegThumbnail,
|
preview,
|
||||||
webpThumbnail,
|
thumbnail,
|
||||||
encodedVideo,
|
encodedVideo,
|
||||||
sidecar,
|
sidecar,
|
||||||
face,
|
face,
|
||||||
@ -79,8 +79,8 @@ class PathTypeTypeTransformer {
|
|||||||
if (data != null) {
|
if (data != null) {
|
||||||
switch (data) {
|
switch (data) {
|
||||||
case r'original': return PathType.original;
|
case r'original': return PathType.original;
|
||||||
case r'jpeg_thumbnail': return PathType.jpegThumbnail;
|
case r'preview': return PathType.preview;
|
||||||
case r'webp_thumbnail': return PathType.webpThumbnail;
|
case r'thumbnail': return PathType.thumbnail;
|
||||||
case r'encoded_video': return PathType.encodedVideo;
|
case r'encoded_video': return PathType.encodedVideo;
|
||||||
case r'sidecar': return PathType.sidecar;
|
case r'sidecar': return PathType.sidecar;
|
||||||
case r'face': return PathType.face;
|
case r'face': return PathType.face;
|
||||||
|
18
mobile/openapi/lib/model/system_config_dto.dart
generated
18
mobile/openapi/lib/model/system_config_dto.dart
generated
@ -14,6 +14,7 @@ class SystemConfigDto {
|
|||||||
/// Returns a new [SystemConfigDto] instance.
|
/// Returns a new [SystemConfigDto] instance.
|
||||||
SystemConfigDto({
|
SystemConfigDto({
|
||||||
required this.ffmpeg,
|
required this.ffmpeg,
|
||||||
|
required this.image,
|
||||||
required this.job,
|
required this.job,
|
||||||
required this.library_,
|
required this.library_,
|
||||||
required this.logging,
|
required this.logging,
|
||||||
@ -26,13 +27,14 @@ class SystemConfigDto {
|
|||||||
required this.server,
|
required this.server,
|
||||||
required this.storageTemplate,
|
required this.storageTemplate,
|
||||||
required this.theme,
|
required this.theme,
|
||||||
required this.thumbnail,
|
|
||||||
required this.trash,
|
required this.trash,
|
||||||
required this.user,
|
required this.user,
|
||||||
});
|
});
|
||||||
|
|
||||||
SystemConfigFFmpegDto ffmpeg;
|
SystemConfigFFmpegDto ffmpeg;
|
||||||
|
|
||||||
|
SystemConfigImageDto image;
|
||||||
|
|
||||||
SystemConfigJobDto job;
|
SystemConfigJobDto job;
|
||||||
|
|
||||||
SystemConfigLibraryDto library_;
|
SystemConfigLibraryDto library_;
|
||||||
@ -57,8 +59,6 @@ class SystemConfigDto {
|
|||||||
|
|
||||||
SystemConfigThemeDto theme;
|
SystemConfigThemeDto theme;
|
||||||
|
|
||||||
SystemConfigThumbnailDto thumbnail;
|
|
||||||
|
|
||||||
SystemConfigTrashDto trash;
|
SystemConfigTrashDto trash;
|
||||||
|
|
||||||
SystemConfigUserDto user;
|
SystemConfigUserDto user;
|
||||||
@ -66,6 +66,7 @@ class SystemConfigDto {
|
|||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is SystemConfigDto &&
|
bool operator ==(Object other) => identical(this, other) || other is SystemConfigDto &&
|
||||||
other.ffmpeg == ffmpeg &&
|
other.ffmpeg == ffmpeg &&
|
||||||
|
other.image == image &&
|
||||||
other.job == job &&
|
other.job == job &&
|
||||||
other.library_ == library_ &&
|
other.library_ == library_ &&
|
||||||
other.logging == logging &&
|
other.logging == logging &&
|
||||||
@ -78,7 +79,6 @@ class SystemConfigDto {
|
|||||||
other.server == server &&
|
other.server == server &&
|
||||||
other.storageTemplate == storageTemplate &&
|
other.storageTemplate == storageTemplate &&
|
||||||
other.theme == theme &&
|
other.theme == theme &&
|
||||||
other.thumbnail == thumbnail &&
|
|
||||||
other.trash == trash &&
|
other.trash == trash &&
|
||||||
other.user == user;
|
other.user == user;
|
||||||
|
|
||||||
@ -86,6 +86,7 @@ class SystemConfigDto {
|
|||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
(ffmpeg.hashCode) +
|
(ffmpeg.hashCode) +
|
||||||
|
(image.hashCode) +
|
||||||
(job.hashCode) +
|
(job.hashCode) +
|
||||||
(library_.hashCode) +
|
(library_.hashCode) +
|
||||||
(logging.hashCode) +
|
(logging.hashCode) +
|
||||||
@ -98,16 +99,16 @@ class SystemConfigDto {
|
|||||||
(server.hashCode) +
|
(server.hashCode) +
|
||||||
(storageTemplate.hashCode) +
|
(storageTemplate.hashCode) +
|
||||||
(theme.hashCode) +
|
(theme.hashCode) +
|
||||||
(thumbnail.hashCode) +
|
|
||||||
(trash.hashCode) +
|
(trash.hashCode) +
|
||||||
(user.hashCode);
|
(user.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'SystemConfigDto[ffmpeg=$ffmpeg, job=$job, library_=$library_, logging=$logging, machineLearning=$machineLearning, map=$map, newVersionCheck=$newVersionCheck, oauth=$oauth, passwordLogin=$passwordLogin, reverseGeocoding=$reverseGeocoding, server=$server, storageTemplate=$storageTemplate, theme=$theme, thumbnail=$thumbnail, trash=$trash, user=$user]';
|
String toString() => 'SystemConfigDto[ffmpeg=$ffmpeg, image=$image, job=$job, library_=$library_, logging=$logging, machineLearning=$machineLearning, map=$map, newVersionCheck=$newVersionCheck, oauth=$oauth, passwordLogin=$passwordLogin, reverseGeocoding=$reverseGeocoding, server=$server, storageTemplate=$storageTemplate, theme=$theme, trash=$trash, user=$user]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
json[r'ffmpeg'] = this.ffmpeg;
|
json[r'ffmpeg'] = this.ffmpeg;
|
||||||
|
json[r'image'] = this.image;
|
||||||
json[r'job'] = this.job;
|
json[r'job'] = this.job;
|
||||||
json[r'library'] = this.library_;
|
json[r'library'] = this.library_;
|
||||||
json[r'logging'] = this.logging;
|
json[r'logging'] = this.logging;
|
||||||
@ -120,7 +121,6 @@ class SystemConfigDto {
|
|||||||
json[r'server'] = this.server;
|
json[r'server'] = this.server;
|
||||||
json[r'storageTemplate'] = this.storageTemplate;
|
json[r'storageTemplate'] = this.storageTemplate;
|
||||||
json[r'theme'] = this.theme;
|
json[r'theme'] = this.theme;
|
||||||
json[r'thumbnail'] = this.thumbnail;
|
|
||||||
json[r'trash'] = this.trash;
|
json[r'trash'] = this.trash;
|
||||||
json[r'user'] = this.user;
|
json[r'user'] = this.user;
|
||||||
return json;
|
return json;
|
||||||
@ -135,6 +135,7 @@ class SystemConfigDto {
|
|||||||
|
|
||||||
return SystemConfigDto(
|
return SystemConfigDto(
|
||||||
ffmpeg: SystemConfigFFmpegDto.fromJson(json[r'ffmpeg'])!,
|
ffmpeg: SystemConfigFFmpegDto.fromJson(json[r'ffmpeg'])!,
|
||||||
|
image: SystemConfigImageDto.fromJson(json[r'image'])!,
|
||||||
job: SystemConfigJobDto.fromJson(json[r'job'])!,
|
job: SystemConfigJobDto.fromJson(json[r'job'])!,
|
||||||
library_: SystemConfigLibraryDto.fromJson(json[r'library'])!,
|
library_: SystemConfigLibraryDto.fromJson(json[r'library'])!,
|
||||||
logging: SystemConfigLoggingDto.fromJson(json[r'logging'])!,
|
logging: SystemConfigLoggingDto.fromJson(json[r'logging'])!,
|
||||||
@ -147,7 +148,6 @@ class SystemConfigDto {
|
|||||||
server: SystemConfigServerDto.fromJson(json[r'server'])!,
|
server: SystemConfigServerDto.fromJson(json[r'server'])!,
|
||||||
storageTemplate: SystemConfigStorageTemplateDto.fromJson(json[r'storageTemplate'])!,
|
storageTemplate: SystemConfigStorageTemplateDto.fromJson(json[r'storageTemplate'])!,
|
||||||
theme: SystemConfigThemeDto.fromJson(json[r'theme'])!,
|
theme: SystemConfigThemeDto.fromJson(json[r'theme'])!,
|
||||||
thumbnail: SystemConfigThumbnailDto.fromJson(json[r'thumbnail'])!,
|
|
||||||
trash: SystemConfigTrashDto.fromJson(json[r'trash'])!,
|
trash: SystemConfigTrashDto.fromJson(json[r'trash'])!,
|
||||||
user: SystemConfigUserDto.fromJson(json[r'user'])!,
|
user: SystemConfigUserDto.fromJson(json[r'user'])!,
|
||||||
);
|
);
|
||||||
@ -198,6 +198,7 @@ class SystemConfigDto {
|
|||||||
/// The list of required keys that must be present in a JSON.
|
/// The list of required keys that must be present in a JSON.
|
||||||
static const requiredKeys = <String>{
|
static const requiredKeys = <String>{
|
||||||
'ffmpeg',
|
'ffmpeg',
|
||||||
|
'image',
|
||||||
'job',
|
'job',
|
||||||
'library',
|
'library',
|
||||||
'logging',
|
'logging',
|
||||||
@ -210,7 +211,6 @@ class SystemConfigDto {
|
|||||||
'server',
|
'server',
|
||||||
'storageTemplate',
|
'storageTemplate',
|
||||||
'theme',
|
'theme',
|
||||||
'thumbnail',
|
|
||||||
'trash',
|
'trash',
|
||||||
'user',
|
'user',
|
||||||
};
|
};
|
||||||
|
138
mobile/openapi/lib/model/system_config_image_dto.dart
generated
Normal file
138
mobile/openapi/lib/model/system_config_image_dto.dart
generated
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class SystemConfigImageDto {
|
||||||
|
/// Returns a new [SystemConfigImageDto] instance.
|
||||||
|
SystemConfigImageDto({
|
||||||
|
required this.colorspace,
|
||||||
|
required this.previewFormat,
|
||||||
|
required this.previewSize,
|
||||||
|
required this.quality,
|
||||||
|
required this.thumbnailFormat,
|
||||||
|
required this.thumbnailSize,
|
||||||
|
});
|
||||||
|
|
||||||
|
Colorspace colorspace;
|
||||||
|
|
||||||
|
ImageFormat previewFormat;
|
||||||
|
|
||||||
|
int previewSize;
|
||||||
|
|
||||||
|
int quality;
|
||||||
|
|
||||||
|
ImageFormat thumbnailFormat;
|
||||||
|
|
||||||
|
int thumbnailSize;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is SystemConfigImageDto &&
|
||||||
|
other.colorspace == colorspace &&
|
||||||
|
other.previewFormat == previewFormat &&
|
||||||
|
other.previewSize == previewSize &&
|
||||||
|
other.quality == quality &&
|
||||||
|
other.thumbnailFormat == thumbnailFormat &&
|
||||||
|
other.thumbnailSize == thumbnailSize;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(colorspace.hashCode) +
|
||||||
|
(previewFormat.hashCode) +
|
||||||
|
(previewSize.hashCode) +
|
||||||
|
(quality.hashCode) +
|
||||||
|
(thumbnailFormat.hashCode) +
|
||||||
|
(thumbnailSize.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'SystemConfigImageDto[colorspace=$colorspace, previewFormat=$previewFormat, previewSize=$previewSize, quality=$quality, thumbnailFormat=$thumbnailFormat, thumbnailSize=$thumbnailSize]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'colorspace'] = this.colorspace;
|
||||||
|
json[r'previewFormat'] = this.previewFormat;
|
||||||
|
json[r'previewSize'] = this.previewSize;
|
||||||
|
json[r'quality'] = this.quality;
|
||||||
|
json[r'thumbnailFormat'] = this.thumbnailFormat;
|
||||||
|
json[r'thumbnailSize'] = this.thumbnailSize;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [SystemConfigImageDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static SystemConfigImageDto? fromJson(dynamic value) {
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return SystemConfigImageDto(
|
||||||
|
colorspace: Colorspace.fromJson(json[r'colorspace'])!,
|
||||||
|
previewFormat: ImageFormat.fromJson(json[r'previewFormat'])!,
|
||||||
|
previewSize: mapValueOfType<int>(json, r'previewSize')!,
|
||||||
|
quality: mapValueOfType<int>(json, r'quality')!,
|
||||||
|
thumbnailFormat: ImageFormat.fromJson(json[r'thumbnailFormat'])!,
|
||||||
|
thumbnailSize: mapValueOfType<int>(json, r'thumbnailSize')!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<SystemConfigImageDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <SystemConfigImageDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = SystemConfigImageDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, SystemConfigImageDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, SystemConfigImageDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = SystemConfigImageDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of SystemConfigImageDto-objects as value to a dart map
|
||||||
|
static Map<String, List<SystemConfigImageDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<SystemConfigImageDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = SystemConfigImageDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'colorspace',
|
||||||
|
'previewFormat',
|
||||||
|
'previewSize',
|
||||||
|
'quality',
|
||||||
|
'thumbnailFormat',
|
||||||
|
'thumbnailSize',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,122 +0,0 @@
|
|||||||
//
|
|
||||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
|
||||||
//
|
|
||||||
// @dart=2.12
|
|
||||||
|
|
||||||
// ignore_for_file: unused_element, unused_import
|
|
||||||
// ignore_for_file: always_put_required_named_parameters_first
|
|
||||||
// ignore_for_file: constant_identifier_names
|
|
||||||
// ignore_for_file: lines_longer_than_80_chars
|
|
||||||
|
|
||||||
part of openapi.api;
|
|
||||||
|
|
||||||
class SystemConfigThumbnailDto {
|
|
||||||
/// Returns a new [SystemConfigThumbnailDto] instance.
|
|
||||||
SystemConfigThumbnailDto({
|
|
||||||
required this.colorspace,
|
|
||||||
required this.jpegSize,
|
|
||||||
required this.quality,
|
|
||||||
required this.webpSize,
|
|
||||||
});
|
|
||||||
|
|
||||||
Colorspace colorspace;
|
|
||||||
|
|
||||||
int jpegSize;
|
|
||||||
|
|
||||||
int quality;
|
|
||||||
|
|
||||||
int webpSize;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) => identical(this, other) || other is SystemConfigThumbnailDto &&
|
|
||||||
other.colorspace == colorspace &&
|
|
||||||
other.jpegSize == jpegSize &&
|
|
||||||
other.quality == quality &&
|
|
||||||
other.webpSize == webpSize;
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode =>
|
|
||||||
// ignore: unnecessary_parenthesis
|
|
||||||
(colorspace.hashCode) +
|
|
||||||
(jpegSize.hashCode) +
|
|
||||||
(quality.hashCode) +
|
|
||||||
(webpSize.hashCode);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => 'SystemConfigThumbnailDto[colorspace=$colorspace, jpegSize=$jpegSize, quality=$quality, webpSize=$webpSize]';
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
final json = <String, dynamic>{};
|
|
||||||
json[r'colorspace'] = this.colorspace;
|
|
||||||
json[r'jpegSize'] = this.jpegSize;
|
|
||||||
json[r'quality'] = this.quality;
|
|
||||||
json[r'webpSize'] = this.webpSize;
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new [SystemConfigThumbnailDto] instance and imports its values from
|
|
||||||
/// [value] if it's a [Map], null otherwise.
|
|
||||||
// ignore: prefer_constructors_over_static_methods
|
|
||||||
static SystemConfigThumbnailDto? fromJson(dynamic value) {
|
|
||||||
if (value is Map) {
|
|
||||||
final json = value.cast<String, dynamic>();
|
|
||||||
|
|
||||||
return SystemConfigThumbnailDto(
|
|
||||||
colorspace: Colorspace.fromJson(json[r'colorspace'])!,
|
|
||||||
jpegSize: mapValueOfType<int>(json, r'jpegSize')!,
|
|
||||||
quality: mapValueOfType<int>(json, r'quality')!,
|
|
||||||
webpSize: mapValueOfType<int>(json, r'webpSize')!,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static List<SystemConfigThumbnailDto> listFromJson(dynamic json, {bool growable = false,}) {
|
|
||||||
final result = <SystemConfigThumbnailDto>[];
|
|
||||||
if (json is List && json.isNotEmpty) {
|
|
||||||
for (final row in json) {
|
|
||||||
final value = SystemConfigThumbnailDto.fromJson(row);
|
|
||||||
if (value != null) {
|
|
||||||
result.add(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.toList(growable: growable);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Map<String, SystemConfigThumbnailDto> mapFromJson(dynamic json) {
|
|
||||||
final map = <String, SystemConfigThumbnailDto>{};
|
|
||||||
if (json is Map && json.isNotEmpty) {
|
|
||||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
|
||||||
for (final entry in json.entries) {
|
|
||||||
final value = SystemConfigThumbnailDto.fromJson(entry.value);
|
|
||||||
if (value != null) {
|
|
||||||
map[entry.key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
// maps a json object with a list of SystemConfigThumbnailDto-objects as value to a dart map
|
|
||||||
static Map<String, List<SystemConfigThumbnailDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
|
||||||
final map = <String, List<SystemConfigThumbnailDto>>{};
|
|
||||||
if (json is Map && json.isNotEmpty) {
|
|
||||||
// ignore: parameter_assignments
|
|
||||||
json = json.cast<String, dynamic>();
|
|
||||||
for (final entry in json.entries) {
|
|
||||||
map[entry.key] = SystemConfigThumbnailDto.listFromJson(entry.value, growable: growable,);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The list of required keys that must be present in a JSON.
|
|
||||||
static const requiredKeys = <String>{
|
|
||||||
'colorspace',
|
|
||||||
'jpegSize',
|
|
||||||
'quality',
|
|
||||||
'webpSize',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
2
mobile/openapi/test/asset_api_test.dart
generated
2
mobile/openapi/test/asset_api_test.dart
generated
@ -100,7 +100,7 @@ void main() {
|
|||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
//Future<List<AssetResponseDto>> searchAssets({ String checksum, String city, String country, DateTime createdAfter, DateTime createdBefore, String deviceAssetId, String deviceId, String encodedVideoPath, String id, bool isArchived, bool isEncoded, bool isExternal, bool isFavorite, bool isMotion, bool isNotInAlbum, bool isOffline, bool isReadOnly, bool isVisible, String lensModel, String libraryId, String make, String model, AssetOrder order, String originalFileName, String originalPath, num page, List<String> personIds, String resizePath, num size, String state, DateTime takenAfter, DateTime takenBefore, DateTime trashedAfter, DateTime trashedBefore, AssetTypeEnum type, DateTime updatedAfter, DateTime updatedBefore, String webpPath, bool withArchived, bool withDeleted, bool withExif, bool withPeople, bool withStacked }) async
|
//Future<List<AssetResponseDto>> searchAssets({ String checksum, String city, String country, DateTime createdAfter, DateTime createdBefore, String deviceAssetId, String deviceId, String encodedVideoPath, String id, bool isArchived, bool isEncoded, bool isExternal, bool isFavorite, bool isMotion, bool isNotInAlbum, bool isOffline, bool isReadOnly, bool isVisible, String lensModel, String libraryId, String make, String model, AssetOrder order, String originalFileName, String originalPath, num page, List<String> personIds, String previewPath, String resizePath, num size, String state, DateTime takenAfter, DateTime takenBefore, String thumbnailPath, DateTime trashedAfter, DateTime trashedBefore, AssetTypeEnum type, DateTime updatedAfter, DateTime updatedBefore, String webpPath, bool withArchived, bool withDeleted, bool withExif, bool withPeople, bool withStacked }) async
|
||||||
test('test searchAssets', () async {
|
test('test searchAssets', () async {
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
21
mobile/openapi/test/image_format_test.dart
generated
Normal file
21
mobile/openapi/test/image_format_test.dart
generated
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.12
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
// tests for ImageFormat
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
group('test ImageFormat', () {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
10
mobile/openapi/test/metadata_search_dto_test.dart
generated
10
mobile/openapi/test/metadata_search_dto_test.dart
generated
@ -151,6 +151,11 @@ void main() {
|
|||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// String previewPath
|
||||||
|
test('to test the property `previewPath`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
// String resizePath
|
// String resizePath
|
||||||
test('to test the property `resizePath`', () async {
|
test('to test the property `resizePath`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
@ -176,6 +181,11 @@ void main() {
|
|||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// String thumbnailPath
|
||||||
|
test('to test the property `thumbnailPath`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
// DateTime trashedAfter
|
// DateTime trashedAfter
|
||||||
test('to test the property `trashedAfter`', () async {
|
test('to test the property `trashedAfter`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
|
10
mobile/openapi/test/system_config_dto_test.dart
generated
10
mobile/openapi/test/system_config_dto_test.dart
generated
@ -21,6 +21,11 @@ void main() {
|
|||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// SystemConfigImageDto image
|
||||||
|
test('to test the property `image`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
// SystemConfigJobDto job
|
// SystemConfigJobDto job
|
||||||
test('to test the property `job`', () async {
|
test('to test the property `job`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
@ -81,11 +86,6 @@ void main() {
|
|||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
// SystemConfigThumbnailDto thumbnail
|
|
||||||
test('to test the property `thumbnail`', () async {
|
|
||||||
// TODO
|
|
||||||
});
|
|
||||||
|
|
||||||
// SystemConfigTrashDto trash
|
// SystemConfigTrashDto trash
|
||||||
test('to test the property `trash`', () async {
|
test('to test the property `trash`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -11,18 +11,23 @@
|
|||||||
import 'package:openapi/api.dart';
|
import 'package:openapi/api.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
// tests for SystemConfigThumbnailDto
|
// tests for SystemConfigImageDto
|
||||||
void main() {
|
void main() {
|
||||||
// final instance = SystemConfigThumbnailDto();
|
// final instance = SystemConfigImageDto();
|
||||||
|
|
||||||
group('test SystemConfigThumbnailDto', () {
|
group('test SystemConfigImageDto', () {
|
||||||
// Colorspace colorspace
|
// Colorspace colorspace
|
||||||
test('to test the property `colorspace`', () async {
|
test('to test the property `colorspace`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
// int jpegSize
|
// ImageFormat previewFormat
|
||||||
test('to test the property `jpegSize`', () async {
|
test('to test the property `previewFormat`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// int previewSize
|
||||||
|
test('to test the property `previewSize`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -31,8 +36,13 @@ void main() {
|
|||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
// int webpSize
|
// ImageFormat thumbnailFormat
|
||||||
test('to test the property `webpSize`', () async {
|
test('to test the property `thumbnailFormat`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// int thumbnailSize
|
||||||
|
test('to test the property `thumbnailSize`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
@ -2101,10 +2101,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "previewPath",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "resizePath",
|
"name": "resizePath",
|
||||||
"required": false,
|
"required": false,
|
||||||
"in": "query",
|
"in": "query",
|
||||||
|
"deprecated": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
@ -2143,6 +2152,14 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "thumbnailPath",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "trashedAfter",
|
"name": "trashedAfter",
|
||||||
"required": false,
|
"required": false,
|
||||||
@ -2191,6 +2208,7 @@
|
|||||||
"name": "webpPath",
|
"name": "webpPath",
|
||||||
"required": false,
|
"required": false,
|
||||||
"in": "query",
|
"in": "query",
|
||||||
|
"deprecated": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
@ -8114,6 +8132,13 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"ImageFormat": {
|
||||||
|
"enum": [
|
||||||
|
"jpeg",
|
||||||
|
"webp"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"JobCommand": {
|
"JobCommand": {
|
||||||
"enum": [
|
"enum": [
|
||||||
"start",
|
"start",
|
||||||
@ -8555,7 +8580,11 @@
|
|||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
|
"previewPath": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"resizePath": {
|
"resizePath": {
|
||||||
|
"deprecated": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"size": {
|
"size": {
|
||||||
@ -8572,6 +8601,9 @@
|
|||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"thumbnailPath": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"trashedAfter": {
|
"trashedAfter": {
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -8592,6 +8624,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"webpPath": {
|
"webpPath": {
|
||||||
|
"deprecated": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"withArchived": {
|
"withArchived": {
|
||||||
@ -8746,8 +8779,8 @@
|
|||||||
"PathType": {
|
"PathType": {
|
||||||
"enum": [
|
"enum": [
|
||||||
"original",
|
"original",
|
||||||
"jpeg_thumbnail",
|
"preview",
|
||||||
"webp_thumbnail",
|
"thumbnail",
|
||||||
"encoded_video",
|
"encoded_video",
|
||||||
"sidecar",
|
"sidecar",
|
||||||
"face",
|
"face",
|
||||||
@ -9743,6 +9776,9 @@
|
|||||||
"ffmpeg": {
|
"ffmpeg": {
|
||||||
"$ref": "#/components/schemas/SystemConfigFFmpegDto"
|
"$ref": "#/components/schemas/SystemConfigFFmpegDto"
|
||||||
},
|
},
|
||||||
|
"image": {
|
||||||
|
"$ref": "#/components/schemas/SystemConfigImageDto"
|
||||||
|
},
|
||||||
"job": {
|
"job": {
|
||||||
"$ref": "#/components/schemas/SystemConfigJobDto"
|
"$ref": "#/components/schemas/SystemConfigJobDto"
|
||||||
},
|
},
|
||||||
@ -9779,9 +9815,6 @@
|
|||||||
"theme": {
|
"theme": {
|
||||||
"$ref": "#/components/schemas/SystemConfigThemeDto"
|
"$ref": "#/components/schemas/SystemConfigThemeDto"
|
||||||
},
|
},
|
||||||
"thumbnail": {
|
|
||||||
"$ref": "#/components/schemas/SystemConfigThumbnailDto"
|
|
||||||
},
|
|
||||||
"trash": {
|
"trash": {
|
||||||
"$ref": "#/components/schemas/SystemConfigTrashDto"
|
"$ref": "#/components/schemas/SystemConfigTrashDto"
|
||||||
},
|
},
|
||||||
@ -9791,6 +9824,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"ffmpeg",
|
"ffmpeg",
|
||||||
|
"image",
|
||||||
"job",
|
"job",
|
||||||
"library",
|
"library",
|
||||||
"logging",
|
"logging",
|
||||||
@ -9803,7 +9837,6 @@
|
|||||||
"server",
|
"server",
|
||||||
"storageTemplate",
|
"storageTemplate",
|
||||||
"theme",
|
"theme",
|
||||||
"thumbnail",
|
|
||||||
"trash",
|
"trash",
|
||||||
"user"
|
"user"
|
||||||
],
|
],
|
||||||
@ -9902,6 +9935,37 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"SystemConfigImageDto": {
|
||||||
|
"properties": {
|
||||||
|
"colorspace": {
|
||||||
|
"$ref": "#/components/schemas/Colorspace"
|
||||||
|
},
|
||||||
|
"previewFormat": {
|
||||||
|
"$ref": "#/components/schemas/ImageFormat"
|
||||||
|
},
|
||||||
|
"previewSize": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"quality": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"thumbnailFormat": {
|
||||||
|
"$ref": "#/components/schemas/ImageFormat"
|
||||||
|
},
|
||||||
|
"thumbnailSize": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"colorspace",
|
||||||
|
"previewFormat",
|
||||||
|
"previewSize",
|
||||||
|
"quality",
|
||||||
|
"thumbnailFormat",
|
||||||
|
"thumbnailSize"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"SystemConfigJobDto": {
|
"SystemConfigJobDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"backgroundTask": {
|
"backgroundTask": {
|
||||||
@ -10251,29 +10315,6 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"SystemConfigThumbnailDto": {
|
|
||||||
"properties": {
|
|
||||||
"colorspace": {
|
|
||||||
"$ref": "#/components/schemas/Colorspace"
|
|
||||||
},
|
|
||||||
"jpegSize": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"quality": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"webpSize": {
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"colorspace",
|
|
||||||
"jpegSize",
|
|
||||||
"quality",
|
|
||||||
"webpSize"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"SystemConfigTrashDto": {
|
"SystemConfigTrashDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"days": {
|
"days": {
|
||||||
|
@ -640,11 +640,13 @@ export type MetadataSearchDto = {
|
|||||||
originalPath?: string;
|
originalPath?: string;
|
||||||
page?: number;
|
page?: number;
|
||||||
personIds?: string[];
|
personIds?: string[];
|
||||||
|
previewPath?: string;
|
||||||
resizePath?: string;
|
resizePath?: string;
|
||||||
size?: number;
|
size?: number;
|
||||||
state?: string;
|
state?: string;
|
||||||
takenAfter?: string;
|
takenAfter?: string;
|
||||||
takenBefore?: string;
|
takenBefore?: string;
|
||||||
|
thumbnailPath?: string;
|
||||||
trashedAfter?: string;
|
trashedAfter?: string;
|
||||||
trashedBefore?: string;
|
trashedBefore?: string;
|
||||||
"type"?: AssetTypeEnum;
|
"type"?: AssetTypeEnum;
|
||||||
@ -827,6 +829,14 @@ export type SystemConfigFFmpegDto = {
|
|||||||
transcode: TranscodePolicy;
|
transcode: TranscodePolicy;
|
||||||
twoPass: boolean;
|
twoPass: boolean;
|
||||||
};
|
};
|
||||||
|
export type SystemConfigImageDto = {
|
||||||
|
colorspace: Colorspace;
|
||||||
|
previewFormat: ImageFormat;
|
||||||
|
previewSize: number;
|
||||||
|
quality: number;
|
||||||
|
thumbnailFormat: ImageFormat;
|
||||||
|
thumbnailSize: number;
|
||||||
|
};
|
||||||
export type JobSettingsDto = {
|
export type JobSettingsDto = {
|
||||||
concurrency: number;
|
concurrency: number;
|
||||||
};
|
};
|
||||||
@ -919,12 +929,6 @@ export type SystemConfigStorageTemplateDto = {
|
|||||||
export type SystemConfigThemeDto = {
|
export type SystemConfigThemeDto = {
|
||||||
customCss: string;
|
customCss: string;
|
||||||
};
|
};
|
||||||
export type SystemConfigThumbnailDto = {
|
|
||||||
colorspace: Colorspace;
|
|
||||||
jpegSize: number;
|
|
||||||
quality: number;
|
|
||||||
webpSize: number;
|
|
||||||
};
|
|
||||||
export type SystemConfigTrashDto = {
|
export type SystemConfigTrashDto = {
|
||||||
days: number;
|
days: number;
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
@ -934,6 +938,7 @@ export type SystemConfigUserDto = {
|
|||||||
};
|
};
|
||||||
export type SystemConfigDto = {
|
export type SystemConfigDto = {
|
||||||
ffmpeg: SystemConfigFFmpegDto;
|
ffmpeg: SystemConfigFFmpegDto;
|
||||||
|
image: SystemConfigImageDto;
|
||||||
job: SystemConfigJobDto;
|
job: SystemConfigJobDto;
|
||||||
library: SystemConfigLibraryDto;
|
library: SystemConfigLibraryDto;
|
||||||
logging: SystemConfigLoggingDto;
|
logging: SystemConfigLoggingDto;
|
||||||
@ -946,7 +951,6 @@ export type SystemConfigDto = {
|
|||||||
server: SystemConfigServerDto;
|
server: SystemConfigServerDto;
|
||||||
storageTemplate: SystemConfigStorageTemplateDto;
|
storageTemplate: SystemConfigStorageTemplateDto;
|
||||||
theme: SystemConfigThemeDto;
|
theme: SystemConfigThemeDto;
|
||||||
thumbnail: SystemConfigThumbnailDto;
|
|
||||||
trash: SystemConfigTrashDto;
|
trash: SystemConfigTrashDto;
|
||||||
user: SystemConfigUserDto;
|
user: SystemConfigUserDto;
|
||||||
};
|
};
|
||||||
@ -1497,7 +1501,7 @@ export function updateAsset({ id, updateAssetDto }: {
|
|||||||
body: updateAssetDto
|
body: updateAssetDto
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
export function searchAssets({ checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, resizePath, size, state, takenAfter, takenBefore, trashedAfter, trashedBefore, $type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked }: {
|
export function searchAssets({ checksum, city, country, createdAfter, createdBefore, deviceAssetId, deviceId, encodedVideoPath, id, isArchived, isEncoded, isExternal, isFavorite, isMotion, isNotInAlbum, isOffline, isReadOnly, isVisible, lensModel, libraryId, make, model, order, originalFileName, originalPath, page, personIds, previewPath, resizePath, size, state, takenAfter, takenBefore, thumbnailPath, trashedAfter, trashedBefore, $type, updatedAfter, updatedBefore, webpPath, withArchived, withDeleted, withExif, withPeople, withStacked }: {
|
||||||
checksum?: string;
|
checksum?: string;
|
||||||
city?: string;
|
city?: string;
|
||||||
country?: string;
|
country?: string;
|
||||||
@ -1525,11 +1529,13 @@ export function searchAssets({ checksum, city, country, createdAfter, createdBef
|
|||||||
originalPath?: string;
|
originalPath?: string;
|
||||||
page?: number;
|
page?: number;
|
||||||
personIds?: string[];
|
personIds?: string[];
|
||||||
|
previewPath?: string;
|
||||||
resizePath?: string;
|
resizePath?: string;
|
||||||
size?: number;
|
size?: number;
|
||||||
state?: string;
|
state?: string;
|
||||||
takenAfter?: string;
|
takenAfter?: string;
|
||||||
takenBefore?: string;
|
takenBefore?: string;
|
||||||
|
thumbnailPath?: string;
|
||||||
trashedAfter?: string;
|
trashedAfter?: string;
|
||||||
trashedBefore?: string;
|
trashedBefore?: string;
|
||||||
$type?: AssetTypeEnum;
|
$type?: AssetTypeEnum;
|
||||||
@ -1573,11 +1579,13 @@ export function searchAssets({ checksum, city, country, createdAfter, createdBef
|
|||||||
originalPath,
|
originalPath,
|
||||||
page,
|
page,
|
||||||
personIds,
|
personIds,
|
||||||
|
previewPath,
|
||||||
resizePath,
|
resizePath,
|
||||||
size,
|
size,
|
||||||
state,
|
state,
|
||||||
takenAfter,
|
takenAfter,
|
||||||
takenBefore,
|
takenBefore,
|
||||||
|
thumbnailPath,
|
||||||
trashedAfter,
|
trashedAfter,
|
||||||
trashedBefore,
|
trashedBefore,
|
||||||
"type": $type,
|
"type": $type,
|
||||||
@ -2802,8 +2810,8 @@ export enum PathEntityType {
|
|||||||
}
|
}
|
||||||
export enum PathType {
|
export enum PathType {
|
||||||
Original = "original",
|
Original = "original",
|
||||||
JpegThumbnail = "jpeg_thumbnail",
|
Preview = "preview",
|
||||||
WebpThumbnail = "webp_thumbnail",
|
Thumbnail = "thumbnail",
|
||||||
EncodedVideo = "encoded_video",
|
EncodedVideo = "encoded_video",
|
||||||
Sidecar = "sidecar",
|
Sidecar = "sidecar",
|
||||||
Face = "face",
|
Face = "face",
|
||||||
@ -2885,6 +2893,14 @@ export enum TranscodePolicy {
|
|||||||
Required = "required",
|
Required = "required",
|
||||||
Disabled = "disabled"
|
Disabled = "disabled"
|
||||||
}
|
}
|
||||||
|
export enum Colorspace {
|
||||||
|
Srgb = "srgb",
|
||||||
|
P3 = "p3"
|
||||||
|
}
|
||||||
|
export enum ImageFormat {
|
||||||
|
Jpeg = "jpeg",
|
||||||
|
Webp = "webp"
|
||||||
|
}
|
||||||
export enum LogLevel {
|
export enum LogLevel {
|
||||||
Verbose = "verbose",
|
Verbose = "verbose",
|
||||||
Debug = "debug",
|
Debug = "debug",
|
||||||
@ -2901,10 +2917,6 @@ export enum ModelType {
|
|||||||
FacialRecognition = "facial-recognition",
|
FacialRecognition = "facial-recognition",
|
||||||
Clip = "clip"
|
Clip = "clip"
|
||||||
}
|
}
|
||||||
export enum Colorspace {
|
|
||||||
Srgb = "srgb",
|
|
||||||
P3 = "p3"
|
|
||||||
}
|
|
||||||
export enum MapTheme {
|
export enum MapTheme {
|
||||||
Light = "light",
|
Light = "light",
|
||||||
Dark = "dark"
|
Dark = "dark"
|
||||||
|
@ -4,6 +4,7 @@ import { SystemConfigCore } from 'src/cores/system-config.core';
|
|||||||
import { AssetEntity } from 'src/entities/asset.entity';
|
import { AssetEntity } from 'src/entities/asset.entity';
|
||||||
import { AssetPathType, PathType, PersonPathType } from 'src/entities/move.entity';
|
import { AssetPathType, PathType, PersonPathType } from 'src/entities/move.entity';
|
||||||
import { PersonEntity } from 'src/entities/person.entity';
|
import { PersonEntity } from 'src/entities/person.entity';
|
||||||
|
import { ImageFormat } from 'src/entities/system-config.entity';
|
||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||||
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
||||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
import { IMoveRepository } from 'src/interfaces/move.interface';
|
||||||
@ -34,7 +35,8 @@ export interface MoveRequest {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type GeneratedAssetPath = AssetPathType.JPEG_THUMBNAIL | AssetPathType.WEBP_THUMBNAIL | AssetPathType.ENCODED_VIDEO;
|
export type GeneratedImageType = AssetPathType.PREVIEW | AssetPathType.THUMBNAIL;
|
||||||
|
export type GeneratedAssetType = GeneratedImageType | AssetPathType.ENCODED_VIDEO;
|
||||||
|
|
||||||
let instance: StorageCore | null;
|
let instance: StorageCore | null;
|
||||||
|
|
||||||
@ -94,12 +96,8 @@ export class StorageCore {
|
|||||||
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, person.ownerId, `${person.id}.jpeg`);
|
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, person.ownerId, `${person.id}.jpeg`);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getLargeThumbnailPath(asset: AssetEntity) {
|
static getImagePath(asset: AssetEntity, type: GeneratedImageType, format: ImageFormat) {
|
||||||
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}.jpeg`);
|
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}-${type}.${format}`);
|
||||||
}
|
|
||||||
|
|
||||||
static getSmallThumbnailPath(asset: AssetEntity) {
|
|
||||||
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}.webp`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static getEncodedVideoPath(asset: AssetEntity) {
|
static getEncodedVideoPath(asset: AssetEntity) {
|
||||||
@ -128,34 +126,23 @@ export class StorageCore {
|
|||||||
return path.startsWith(THUMBNAIL_DIR) || path.startsWith(ENCODED_VIDEO_DIR);
|
return path.startsWith(THUMBNAIL_DIR) || path.startsWith(ENCODED_VIDEO_DIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
async moveAssetFile(asset: AssetEntity, pathType: GeneratedAssetPath) {
|
async moveAssetImage(asset: AssetEntity, pathType: GeneratedImageType, format: ImageFormat) {
|
||||||
const { id: entityId, resizePath, webpPath, encodedVideoPath } = asset;
|
const { id: entityId, previewPath, thumbnailPath } = asset;
|
||||||
switch (pathType) {
|
return this.moveFile({
|
||||||
case AssetPathType.JPEG_THUMBNAIL: {
|
entityId,
|
||||||
return this.moveFile({
|
pathType,
|
||||||
entityId,
|
oldPath: pathType === AssetPathType.PREVIEW ? previewPath : thumbnailPath,
|
||||||
pathType,
|
newPath: StorageCore.getImagePath(asset, AssetPathType.THUMBNAIL, format),
|
||||||
oldPath: resizePath,
|
});
|
||||||
newPath: StorageCore.getLargeThumbnailPath(asset),
|
}
|
||||||
});
|
|
||||||
}
|
async moveAssetVideo(asset: AssetEntity) {
|
||||||
case AssetPathType.WEBP_THUMBNAIL: {
|
return this.moveFile({
|
||||||
return this.moveFile({
|
entityId: asset.id,
|
||||||
entityId,
|
pathType: AssetPathType.ENCODED_VIDEO,
|
||||||
pathType,
|
oldPath: asset.encodedVideoPath,
|
||||||
oldPath: webpPath,
|
newPath: StorageCore.getEncodedVideoPath(asset),
|
||||||
newPath: StorageCore.getSmallThumbnailPath(asset),
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
case AssetPathType.ENCODED_VIDEO: {
|
|
||||||
return this.moveFile({
|
|
||||||
entityId,
|
|
||||||
pathType,
|
|
||||||
oldPath: encodedVideoPath,
|
|
||||||
newPath: StorageCore.getEncodedVideoPath(asset),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async movePersonFile(person: PersonEntity, pathType: PersonPathType) {
|
async movePersonFile(person: PersonEntity, pathType: PersonPathType) {
|
||||||
@ -294,11 +281,11 @@ export class StorageCore {
|
|||||||
case AssetPathType.ORIGINAL: {
|
case AssetPathType.ORIGINAL: {
|
||||||
return this.assetRepository.update({ id, originalPath: newPath });
|
return this.assetRepository.update({ id, originalPath: newPath });
|
||||||
}
|
}
|
||||||
case AssetPathType.JPEG_THUMBNAIL: {
|
case AssetPathType.PREVIEW: {
|
||||||
return this.assetRepository.update({ id, resizePath: newPath });
|
return this.assetRepository.update({ id, previewPath: newPath });
|
||||||
}
|
}
|
||||||
case AssetPathType.WEBP_THUMBNAIL: {
|
case AssetPathType.THUMBNAIL: {
|
||||||
return this.assetRepository.update({ id, webpPath: newPath });
|
return this.assetRepository.update({ id, thumbnailPath: newPath });
|
||||||
}
|
}
|
||||||
case AssetPathType.ENCODED_VIDEO: {
|
case AssetPathType.ENCODED_VIDEO: {
|
||||||
return this.assetRepository.update({ id, encodedVideoPath: newPath });
|
return this.assetRepository.update({ id, encodedVideoPath: newPath });
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
AudioCodec,
|
AudioCodec,
|
||||||
CQMode,
|
CQMode,
|
||||||
Colorspace,
|
Colorspace,
|
||||||
|
ImageFormat,
|
||||||
LogLevel,
|
LogLevel,
|
||||||
SystemConfig,
|
SystemConfig,
|
||||||
SystemConfigEntity,
|
SystemConfigEntity,
|
||||||
@ -112,9 +113,11 @@ export const defaults = Object.freeze<SystemConfig>({
|
|||||||
hashVerificationEnabled: true,
|
hashVerificationEnabled: true,
|
||||||
template: '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
template: '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||||
},
|
},
|
||||||
thumbnail: {
|
image: {
|
||||||
webpSize: 250,
|
thumbnailFormat: ImageFormat.WEBP,
|
||||||
jpegSize: 1440,
|
thumbnailSize: 250,
|
||||||
|
previewFormat: ImageFormat.JPEG,
|
||||||
|
previewSize: 1440,
|
||||||
quality: 80,
|
quality: 80,
|
||||||
colorspace: Colorspace.P3,
|
colorspace: Colorspace.P3,
|
||||||
},
|
},
|
||||||
|
@ -82,7 +82,7 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As
|
|||||||
type: entity.type,
|
type: entity.type,
|
||||||
thumbhash: entity.thumbhash?.toString('base64') ?? null,
|
thumbhash: entity.thumbhash?.toString('base64') ?? null,
|
||||||
localDateTime: entity.localDateTime,
|
localDateTime: entity.localDateTime,
|
||||||
resized: !!entity.resizePath,
|
resized: !!entity.previewPath,
|
||||||
duration: entity.duration ?? '0:00:00.00000',
|
duration: entity.duration ?? '0:00:00.00000',
|
||||||
livePhotoVideoId: entity.livePhotoVideoId,
|
livePhotoVideoId: entity.livePhotoVideoId,
|
||||||
hasMetadata: false,
|
hasMetadata: false,
|
||||||
@ -100,7 +100,7 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As
|
|||||||
type: entity.type,
|
type: entity.type,
|
||||||
originalPath: entity.originalPath,
|
originalPath: entity.originalPath,
|
||||||
originalFileName: entity.originalFileName,
|
originalFileName: entity.originalFileName,
|
||||||
resized: !!entity.resizePath,
|
resized: !!entity.previewPath,
|
||||||
thumbhash: entity.thumbhash?.toString('base64') ?? null,
|
thumbhash: entity.thumbhash?.toString('base64') ?? null,
|
||||||
fileCreatedAt: entity.fileCreatedAt,
|
fileCreatedAt: entity.fileCreatedAt,
|
||||||
fileModifiedAt: entity.fileModifiedAt,
|
fileModifiedAt: entity.fileModifiedAt,
|
||||||
|
@ -163,13 +163,25 @@ export class MetadataSearchDto extends BaseSearchDto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@Optional()
|
@Optional()
|
||||||
|
@ApiProperty({ deprecated: true })
|
||||||
resizePath?: string;
|
resizePath?: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@Optional()
|
@Optional()
|
||||||
|
@ApiProperty({ deprecated: true })
|
||||||
webpPath?: string;
|
webpPath?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@Optional()
|
||||||
|
previewPath?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@Optional()
|
||||||
|
thumbnailPath?: string;
|
||||||
|
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@Optional()
|
@Optional()
|
||||||
|
@ -22,6 +22,7 @@ import {
|
|||||||
AudioCodec,
|
AudioCodec,
|
||||||
CQMode,
|
CQMode,
|
||||||
Colorspace,
|
Colorspace,
|
||||||
|
ImageFormat,
|
||||||
LogLevel,
|
LogLevel,
|
||||||
SystemConfig,
|
SystemConfig,
|
||||||
ToneMapping,
|
ToneMapping,
|
||||||
@ -385,18 +386,26 @@ export class SystemConfigThemeDto {
|
|||||||
customCss!: string;
|
customCss!: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SystemConfigThumbnailDto {
|
class SystemConfigImageDto {
|
||||||
@IsInt()
|
@IsEnum(ImageFormat)
|
||||||
@Min(1)
|
@ApiProperty({ enumName: 'ImageFormat', enum: ImageFormat })
|
||||||
@Type(() => Number)
|
thumbnailFormat!: ImageFormat;
|
||||||
@ApiProperty({ type: 'integer' })
|
|
||||||
webpSize!: number;
|
|
||||||
|
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@Min(1)
|
@Min(1)
|
||||||
@Type(() => Number)
|
@Type(() => Number)
|
||||||
@ApiProperty({ type: 'integer' })
|
@ApiProperty({ type: 'integer' })
|
||||||
jpegSize!: number;
|
thumbnailSize!: number;
|
||||||
|
|
||||||
|
@IsEnum(ImageFormat)
|
||||||
|
@ApiProperty({ enumName: 'ImageFormat', enum: ImageFormat })
|
||||||
|
previewFormat!: ImageFormat;
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
@Min(1)
|
||||||
|
@Type(() => Number)
|
||||||
|
@ApiProperty({ type: 'integer' })
|
||||||
|
previewSize!: number;
|
||||||
|
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@Min(1)
|
@Min(1)
|
||||||
@ -480,10 +489,10 @@ export class SystemConfigDto implements SystemConfig {
|
|||||||
@IsObject()
|
@IsObject()
|
||||||
job!: SystemConfigJobDto;
|
job!: SystemConfigJobDto;
|
||||||
|
|
||||||
@Type(() => SystemConfigThumbnailDto)
|
@Type(() => SystemConfigImageDto)
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
thumbnail!: SystemConfigThumbnailDto;
|
image!: SystemConfigImageDto;
|
||||||
|
|
||||||
@Type(() => SystemConfigTrashDto)
|
@Type(() => SystemConfigTrashDto)
|
||||||
@ValidateNested()
|
@ValidateNested()
|
||||||
|
@ -67,10 +67,10 @@ export class AssetEntity {
|
|||||||
originalPath!: string;
|
originalPath!: string;
|
||||||
|
|
||||||
@Column({ type: 'varchar', nullable: true })
|
@Column({ type: 'varchar', nullable: true })
|
||||||
resizePath!: string | null;
|
previewPath!: string | null;
|
||||||
|
|
||||||
@Column({ type: 'varchar', nullable: true, default: '' })
|
@Column({ type: 'varchar', nullable: true, default: '' })
|
||||||
webpPath!: string | null;
|
thumbnailPath!: string | null;
|
||||||
|
|
||||||
@Column({ type: 'bytea', nullable: true })
|
@Column({ type: 'bytea', nullable: true })
|
||||||
thumbhash!: Buffer | null;
|
thumbhash!: Buffer | null;
|
||||||
|
@ -24,8 +24,8 @@ export class MoveEntity {
|
|||||||
|
|
||||||
export enum AssetPathType {
|
export enum AssetPathType {
|
||||||
ORIGINAL = 'original',
|
ORIGINAL = 'original',
|
||||||
JPEG_THUMBNAIL = 'jpeg_thumbnail',
|
PREVIEW = 'preview',
|
||||||
WEBP_THUMBNAIL = 'webp_thumbnail',
|
THUMBNAIL = 'thumbnail',
|
||||||
ENCODED_VIDEO = 'encoded_video',
|
ENCODED_VIDEO = 'encoded_video',
|
||||||
SIDECAR = 'sidecar',
|
SIDECAR = 'sidecar',
|
||||||
}
|
}
|
||||||
|
@ -165,6 +165,11 @@ export enum Colorspace {
|
|||||||
P3 = 'p3',
|
P3 = 'p3',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ImageFormat {
|
||||||
|
JPEG = 'jpeg',
|
||||||
|
WEBP = 'webp',
|
||||||
|
}
|
||||||
|
|
||||||
export enum LogLevel {
|
export enum LogLevel {
|
||||||
VERBOSE = 'verbose',
|
VERBOSE = 'verbose',
|
||||||
DEBUG = 'debug',
|
DEBUG = 'debug',
|
||||||
@ -249,9 +254,11 @@ export interface SystemConfig {
|
|||||||
hashVerificationEnabled: boolean;
|
hashVerificationEnabled: boolean;
|
||||||
template: string;
|
template: string;
|
||||||
};
|
};
|
||||||
thumbnail: {
|
image: {
|
||||||
webpSize: number;
|
thumbnailFormat: ImageFormat;
|
||||||
jpegSize: number;
|
thumbnailSize: number;
|
||||||
|
previewFormat: ImageFormat;
|
||||||
|
previewSize: number;
|
||||||
quality: number;
|
quality: number;
|
||||||
colorspace: Colorspace;
|
colorspace: Colorspace;
|
||||||
};
|
};
|
||||||
|
@ -33,9 +33,9 @@ export enum JobName {
|
|||||||
|
|
||||||
// thumbnails
|
// thumbnails
|
||||||
QUEUE_GENERATE_THUMBNAILS = 'queue-generate-thumbnails',
|
QUEUE_GENERATE_THUMBNAILS = 'queue-generate-thumbnails',
|
||||||
GENERATE_JPEG_THUMBNAIL = 'generate-jpeg-thumbnail',
|
GENERATE_PREVIEW = 'generate-preview',
|
||||||
GENERATE_WEBP_THUMBNAIL = 'generate-webp-thumbnail',
|
GENERATE_THUMBNAIL = 'generate-thumbnail',
|
||||||
GENERATE_THUMBHASH_THUMBNAIL = 'generate-thumbhash-thumbnail',
|
GENERATE_THUMBHASH = 'generate-thumbhash',
|
||||||
GENERATE_PERSON_THUMBNAIL = 'generate-person-thumbnail',
|
GENERATE_PERSON_THUMBNAIL = 'generate-person-thumbnail',
|
||||||
|
|
||||||
// metadata
|
// metadata
|
||||||
@ -160,9 +160,9 @@ export type JobItem =
|
|||||||
|
|
||||||
// Thumbnails
|
// Thumbnails
|
||||||
| { name: JobName.QUEUE_GENERATE_THUMBNAILS; data: IBaseJob }
|
| { name: JobName.QUEUE_GENERATE_THUMBNAILS; data: IBaseJob }
|
||||||
| { name: JobName.GENERATE_JPEG_THUMBNAIL; data: IEntityJob }
|
| { name: JobName.GENERATE_PREVIEW; data: IEntityJob }
|
||||||
| { name: JobName.GENERATE_WEBP_THUMBNAIL; data: IEntityJob }
|
| { name: JobName.GENERATE_THUMBNAIL; data: IEntityJob }
|
||||||
| { name: JobName.GENERATE_THUMBHASH_THUMBNAIL; data: IEntityJob }
|
| { name: JobName.GENERATE_THUMBHASH; data: IEntityJob }
|
||||||
|
|
||||||
// User
|
// User
|
||||||
| { name: JobName.USER_DELETE_CHECK; data?: IBaseJob }
|
| { name: JobName.USER_DELETE_CHECK; data?: IBaseJob }
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { Writable } from 'node:stream';
|
import { Writable } from 'node:stream';
|
||||||
import { TranscodeTarget, VideoCodec } from 'src/entities/system-config.entity';
|
import { ImageFormat, TranscodeTarget, VideoCodec } from 'src/entities/system-config.entity';
|
||||||
|
|
||||||
export const IMediaRepository = 'IMediaRepository';
|
export const IMediaRepository = 'IMediaRepository';
|
||||||
|
|
||||||
export interface ResizeOptions {
|
export interface ResizeOptions {
|
||||||
size: number;
|
size: number;
|
||||||
format: 'webp' | 'jpeg';
|
format: ImageFormat;
|
||||||
colorspace: string;
|
colorspace: string;
|
||||||
quality: number;
|
quality: number;
|
||||||
}
|
}
|
||||||
|
@ -117,8 +117,8 @@ export interface SearchPathOptions {
|
|||||||
encodedVideoPath?: string;
|
encodedVideoPath?: string;
|
||||||
originalFileName?: string;
|
originalFileName?: string;
|
||||||
originalPath?: string;
|
originalPath?: string;
|
||||||
resizePath?: string;
|
previewPath?: string;
|
||||||
webpPath?: string;
|
thumbnailPath?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SearchExifOptions {
|
export interface SearchExifOptions {
|
||||||
|
51
server/src/migrations/1711257900274-RenameWebpJpegPaths.ts
Normal file
51
server/src/migrations/1711257900274-RenameWebpJpegPaths.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||||
|
|
||||||
|
export class RenameWebpJpegPaths1711257900274 implements MigrationInterface {
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.renameColumn('assets', 'webpPath', 'thumbnailPath');
|
||||||
|
await queryRunner.renameColumn('assets', 'resizePath', 'previewPath');
|
||||||
|
await queryRunner.query(`
|
||||||
|
UPDATE system_config
|
||||||
|
SET key = 'image.previewSize'
|
||||||
|
WHERE key = 'thumbnail.jpegSize'`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`UPDATE system_config
|
||||||
|
SET key = 'image.thumbnailSize'
|
||||||
|
WHERE key = 'thumbnail.webpSize'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`UPDATE system_config
|
||||||
|
SET key = 'image.quality'
|
||||||
|
WHERE key = 'thumbnail.quality'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`UPDATE system_config
|
||||||
|
SET key = 'image.colorspace'
|
||||||
|
WHERE key = 'thumbnail.colorspace'`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.renameColumn('assets', 'thumbnailPath', 'webpPath');
|
||||||
|
await queryRunner.renameColumn('assets', 'previewPath', 'resizePath');
|
||||||
|
await queryRunner.query(`
|
||||||
|
UPDATE system_config
|
||||||
|
SET key = 'thumbnail.jpegSize'
|
||||||
|
WHERE key = 'image.previewSize'`);
|
||||||
|
await queryRunner.query(
|
||||||
|
`UPDATE system_config
|
||||||
|
SET key = 'thumbnail.webpSize'
|
||||||
|
WHERE key = 'image.thumbnailSize'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`UPDATE system_config
|
||||||
|
SET key = 'thumbnail.quality'
|
||||||
|
WHERE key = 'image.quality'`,
|
||||||
|
);
|
||||||
|
await queryRunner.query(
|
||||||
|
`UPDATE system_config
|
||||||
|
SET key = 'thumbnail.colorspace'
|
||||||
|
WHERE key = 'image.colorspace'`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -9,8 +9,8 @@ SELECT
|
|||||||
"entity"."deviceId" AS "entity_deviceId",
|
"entity"."deviceId" AS "entity_deviceId",
|
||||||
"entity"."type" AS "entity_type",
|
"entity"."type" AS "entity_type",
|
||||||
"entity"."originalPath" AS "entity_originalPath",
|
"entity"."originalPath" AS "entity_originalPath",
|
||||||
"entity"."resizePath" AS "entity_resizePath",
|
"entity"."previewPath" AS "entity_previewPath",
|
||||||
"entity"."webpPath" AS "entity_webpPath",
|
"entity"."thumbnailPath" AS "entity_thumbnailPath",
|
||||||
"entity"."thumbhash" AS "entity_thumbhash",
|
"entity"."thumbhash" AS "entity_thumbhash",
|
||||||
"entity"."encodedVideoPath" AS "entity_encodedVideoPath",
|
"entity"."encodedVideoPath" AS "entity_encodedVideoPath",
|
||||||
"entity"."createdAt" AS "entity_createdAt",
|
"entity"."createdAt" AS "entity_createdAt",
|
||||||
@ -67,7 +67,7 @@ WHERE
|
|||||||
"entity"."ownerId" IN ($1)
|
"entity"."ownerId" IN ($1)
|
||||||
AND "entity"."isVisible" = true
|
AND "entity"."isVisible" = true
|
||||||
AND "entity"."isArchived" = false
|
AND "entity"."isArchived" = false
|
||||||
AND "entity"."resizePath" IS NOT NULL
|
AND "entity"."previewPath" IS NOT NULL
|
||||||
AND EXTRACT(
|
AND EXTRACT(
|
||||||
DAY
|
DAY
|
||||||
FROM
|
FROM
|
||||||
@ -92,8 +92,8 @@ SELECT
|
|||||||
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
||||||
"AssetEntity"."type" AS "AssetEntity_type",
|
"AssetEntity"."type" AS "AssetEntity_type",
|
||||||
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
||||||
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
|
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
|
||||||
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
|
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
|
||||||
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
||||||
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
||||||
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
||||||
@ -128,8 +128,8 @@ SELECT
|
|||||||
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
||||||
"AssetEntity"."type" AS "AssetEntity_type",
|
"AssetEntity"."type" AS "AssetEntity_type",
|
||||||
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
||||||
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
|
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
|
||||||
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
|
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
|
||||||
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
||||||
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
||||||
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
||||||
@ -213,8 +213,8 @@ SELECT
|
|||||||
"bd93d5747511a4dad4923546c51365bf1a803774"."deviceId" AS "bd93d5747511a4dad4923546c51365bf1a803774_deviceId",
|
"bd93d5747511a4dad4923546c51365bf1a803774"."deviceId" AS "bd93d5747511a4dad4923546c51365bf1a803774_deviceId",
|
||||||
"bd93d5747511a4dad4923546c51365bf1a803774"."type" AS "bd93d5747511a4dad4923546c51365bf1a803774_type",
|
"bd93d5747511a4dad4923546c51365bf1a803774"."type" AS "bd93d5747511a4dad4923546c51365bf1a803774_type",
|
||||||
"bd93d5747511a4dad4923546c51365bf1a803774"."originalPath" AS "bd93d5747511a4dad4923546c51365bf1a803774_originalPath",
|
"bd93d5747511a4dad4923546c51365bf1a803774"."originalPath" AS "bd93d5747511a4dad4923546c51365bf1a803774_originalPath",
|
||||||
"bd93d5747511a4dad4923546c51365bf1a803774"."resizePath" AS "bd93d5747511a4dad4923546c51365bf1a803774_resizePath",
|
"bd93d5747511a4dad4923546c51365bf1a803774"."previewPath" AS "bd93d5747511a4dad4923546c51365bf1a803774_previewPath",
|
||||||
"bd93d5747511a4dad4923546c51365bf1a803774"."webpPath" AS "bd93d5747511a4dad4923546c51365bf1a803774_webpPath",
|
"bd93d5747511a4dad4923546c51365bf1a803774"."thumbnailPath" AS "bd93d5747511a4dad4923546c51365bf1a803774_thumbnailPath",
|
||||||
"bd93d5747511a4dad4923546c51365bf1a803774"."thumbhash" AS "bd93d5747511a4dad4923546c51365bf1a803774_thumbhash",
|
"bd93d5747511a4dad4923546c51365bf1a803774"."thumbhash" AS "bd93d5747511a4dad4923546c51365bf1a803774_thumbhash",
|
||||||
"bd93d5747511a4dad4923546c51365bf1a803774"."encodedVideoPath" AS "bd93d5747511a4dad4923546c51365bf1a803774_encodedVideoPath",
|
"bd93d5747511a4dad4923546c51365bf1a803774"."encodedVideoPath" AS "bd93d5747511a4dad4923546c51365bf1a803774_encodedVideoPath",
|
||||||
"bd93d5747511a4dad4923546c51365bf1a803774"."createdAt" AS "bd93d5747511a4dad4923546c51365bf1a803774_createdAt",
|
"bd93d5747511a4dad4923546c51365bf1a803774"."createdAt" AS "bd93d5747511a4dad4923546c51365bf1a803774_createdAt",
|
||||||
@ -294,8 +294,8 @@ FROM
|
|||||||
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
||||||
"AssetEntity"."type" AS "AssetEntity_type",
|
"AssetEntity"."type" AS "AssetEntity_type",
|
||||||
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
||||||
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
|
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
|
||||||
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
|
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
|
||||||
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
||||||
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
||||||
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
||||||
@ -391,8 +391,8 @@ SELECT
|
|||||||
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
||||||
"AssetEntity"."type" AS "AssetEntity_type",
|
"AssetEntity"."type" AS "AssetEntity_type",
|
||||||
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
||||||
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
|
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
|
||||||
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
|
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
|
||||||
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
||||||
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
||||||
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
||||||
@ -437,8 +437,8 @@ SELECT
|
|||||||
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
||||||
"AssetEntity"."type" AS "AssetEntity_type",
|
"AssetEntity"."type" AS "AssetEntity_type",
|
||||||
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
||||||
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
|
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
|
||||||
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
|
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
|
||||||
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
||||||
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
||||||
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
||||||
@ -481,8 +481,8 @@ SELECT
|
|||||||
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
||||||
"AssetEntity"."type" AS "AssetEntity_type",
|
"AssetEntity"."type" AS "AssetEntity_type",
|
||||||
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
||||||
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
|
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
|
||||||
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
|
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
|
||||||
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
||||||
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
||||||
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
||||||
@ -570,8 +570,8 @@ SELECT
|
|||||||
"asset"."deviceId" AS "asset_deviceId",
|
"asset"."deviceId" AS "asset_deviceId",
|
||||||
"asset"."type" AS "asset_type",
|
"asset"."type" AS "asset_type",
|
||||||
"asset"."originalPath" AS "asset_originalPath",
|
"asset"."originalPath" AS "asset_originalPath",
|
||||||
"asset"."resizePath" AS "asset_resizePath",
|
"asset"."previewPath" AS "asset_previewPath",
|
||||||
"asset"."webpPath" AS "asset_webpPath",
|
"asset"."thumbnailPath" AS "asset_thumbnailPath",
|
||||||
"asset"."thumbhash" AS "asset_thumbhash",
|
"asset"."thumbhash" AS "asset_thumbhash",
|
||||||
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
||||||
"asset"."createdAt" AS "asset_createdAt",
|
"asset"."createdAt" AS "asset_createdAt",
|
||||||
@ -629,8 +629,8 @@ SELECT
|
|||||||
"stackedAssets"."deviceId" AS "stackedAssets_deviceId",
|
"stackedAssets"."deviceId" AS "stackedAssets_deviceId",
|
||||||
"stackedAssets"."type" AS "stackedAssets_type",
|
"stackedAssets"."type" AS "stackedAssets_type",
|
||||||
"stackedAssets"."originalPath" AS "stackedAssets_originalPath",
|
"stackedAssets"."originalPath" AS "stackedAssets_originalPath",
|
||||||
"stackedAssets"."resizePath" AS "stackedAssets_resizePath",
|
"stackedAssets"."previewPath" AS "stackedAssets_previewPath",
|
||||||
"stackedAssets"."webpPath" AS "stackedAssets_webpPath",
|
"stackedAssets"."thumbnailPath" AS "stackedAssets_thumbnailPath",
|
||||||
"stackedAssets"."thumbhash" AS "stackedAssets_thumbhash",
|
"stackedAssets"."thumbhash" AS "stackedAssets_thumbhash",
|
||||||
"stackedAssets"."encodedVideoPath" AS "stackedAssets_encodedVideoPath",
|
"stackedAssets"."encodedVideoPath" AS "stackedAssets_encodedVideoPath",
|
||||||
"stackedAssets"."createdAt" AS "stackedAssets_createdAt",
|
"stackedAssets"."createdAt" AS "stackedAssets_createdAt",
|
||||||
|
@ -152,8 +152,8 @@ FROM
|
|||||||
"AssetFaceEntity__AssetFaceEntity_asset"."deviceId" AS "AssetFaceEntity__AssetFaceEntity_asset_deviceId",
|
"AssetFaceEntity__AssetFaceEntity_asset"."deviceId" AS "AssetFaceEntity__AssetFaceEntity_asset_deviceId",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."type" AS "AssetFaceEntity__AssetFaceEntity_asset_type",
|
"AssetFaceEntity__AssetFaceEntity_asset"."type" AS "AssetFaceEntity__AssetFaceEntity_asset_type",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."originalPath" AS "AssetFaceEntity__AssetFaceEntity_asset_originalPath",
|
"AssetFaceEntity__AssetFaceEntity_asset"."originalPath" AS "AssetFaceEntity__AssetFaceEntity_asset_originalPath",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."resizePath" AS "AssetFaceEntity__AssetFaceEntity_asset_resizePath",
|
"AssetFaceEntity__AssetFaceEntity_asset"."previewPath" AS "AssetFaceEntity__AssetFaceEntity_asset_previewPath",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."webpPath" AS "AssetFaceEntity__AssetFaceEntity_asset_webpPath",
|
"AssetFaceEntity__AssetFaceEntity_asset"."thumbnailPath" AS "AssetFaceEntity__AssetFaceEntity_asset_thumbnailPath",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."thumbhash" AS "AssetFaceEntity__AssetFaceEntity_asset_thumbhash",
|
"AssetFaceEntity__AssetFaceEntity_asset"."thumbhash" AS "AssetFaceEntity__AssetFaceEntity_asset_thumbhash",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."encodedVideoPath" AS "AssetFaceEntity__AssetFaceEntity_asset_encodedVideoPath",
|
"AssetFaceEntity__AssetFaceEntity_asset"."encodedVideoPath" AS "AssetFaceEntity__AssetFaceEntity_asset_encodedVideoPath",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."createdAt" AS "AssetFaceEntity__AssetFaceEntity_asset_createdAt",
|
"AssetFaceEntity__AssetFaceEntity_asset"."createdAt" AS "AssetFaceEntity__AssetFaceEntity_asset_createdAt",
|
||||||
@ -250,8 +250,8 @@ FROM
|
|||||||
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
"AssetEntity"."deviceId" AS "AssetEntity_deviceId",
|
||||||
"AssetEntity"."type" AS "AssetEntity_type",
|
"AssetEntity"."type" AS "AssetEntity_type",
|
||||||
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
"AssetEntity"."originalPath" AS "AssetEntity_originalPath",
|
||||||
"AssetEntity"."resizePath" AS "AssetEntity_resizePath",
|
"AssetEntity"."previewPath" AS "AssetEntity_previewPath",
|
||||||
"AssetEntity"."webpPath" AS "AssetEntity_webpPath",
|
"AssetEntity"."thumbnailPath" AS "AssetEntity_thumbnailPath",
|
||||||
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
"AssetEntity"."thumbhash" AS "AssetEntity_thumbhash",
|
||||||
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
"AssetEntity"."encodedVideoPath" AS "AssetEntity_encodedVideoPath",
|
||||||
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
"AssetEntity"."createdAt" AS "AssetEntity_createdAt",
|
||||||
@ -380,8 +380,8 @@ SELECT
|
|||||||
"AssetFaceEntity__AssetFaceEntity_asset"."deviceId" AS "AssetFaceEntity__AssetFaceEntity_asset_deviceId",
|
"AssetFaceEntity__AssetFaceEntity_asset"."deviceId" AS "AssetFaceEntity__AssetFaceEntity_asset_deviceId",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."type" AS "AssetFaceEntity__AssetFaceEntity_asset_type",
|
"AssetFaceEntity__AssetFaceEntity_asset"."type" AS "AssetFaceEntity__AssetFaceEntity_asset_type",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."originalPath" AS "AssetFaceEntity__AssetFaceEntity_asset_originalPath",
|
"AssetFaceEntity__AssetFaceEntity_asset"."originalPath" AS "AssetFaceEntity__AssetFaceEntity_asset_originalPath",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."resizePath" AS "AssetFaceEntity__AssetFaceEntity_asset_resizePath",
|
"AssetFaceEntity__AssetFaceEntity_asset"."previewPath" AS "AssetFaceEntity__AssetFaceEntity_asset_previewPath",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."webpPath" AS "AssetFaceEntity__AssetFaceEntity_asset_webpPath",
|
"AssetFaceEntity__AssetFaceEntity_asset"."thumbnailPath" AS "AssetFaceEntity__AssetFaceEntity_asset_thumbnailPath",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."thumbhash" AS "AssetFaceEntity__AssetFaceEntity_asset_thumbhash",
|
"AssetFaceEntity__AssetFaceEntity_asset"."thumbhash" AS "AssetFaceEntity__AssetFaceEntity_asset_thumbhash",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."encodedVideoPath" AS "AssetFaceEntity__AssetFaceEntity_asset_encodedVideoPath",
|
"AssetFaceEntity__AssetFaceEntity_asset"."encodedVideoPath" AS "AssetFaceEntity__AssetFaceEntity_asset_encodedVideoPath",
|
||||||
"AssetFaceEntity__AssetFaceEntity_asset"."createdAt" AS "AssetFaceEntity__AssetFaceEntity_asset_createdAt",
|
"AssetFaceEntity__AssetFaceEntity_asset"."createdAt" AS "AssetFaceEntity__AssetFaceEntity_asset_createdAt",
|
||||||
|
@ -14,8 +14,8 @@ FROM
|
|||||||
"asset"."deviceId" AS "asset_deviceId",
|
"asset"."deviceId" AS "asset_deviceId",
|
||||||
"asset"."type" AS "asset_type",
|
"asset"."type" AS "asset_type",
|
||||||
"asset"."originalPath" AS "asset_originalPath",
|
"asset"."originalPath" AS "asset_originalPath",
|
||||||
"asset"."resizePath" AS "asset_resizePath",
|
"asset"."previewPath" AS "asset_previewPath",
|
||||||
"asset"."webpPath" AS "asset_webpPath",
|
"asset"."thumbnailPath" AS "asset_thumbnailPath",
|
||||||
"asset"."thumbhash" AS "asset_thumbhash",
|
"asset"."thumbhash" AS "asset_thumbhash",
|
||||||
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
||||||
"asset"."createdAt" AS "asset_createdAt",
|
"asset"."createdAt" AS "asset_createdAt",
|
||||||
@ -45,8 +45,8 @@ FROM
|
|||||||
"stackedAssets"."deviceId" AS "stackedAssets_deviceId",
|
"stackedAssets"."deviceId" AS "stackedAssets_deviceId",
|
||||||
"stackedAssets"."type" AS "stackedAssets_type",
|
"stackedAssets"."type" AS "stackedAssets_type",
|
||||||
"stackedAssets"."originalPath" AS "stackedAssets_originalPath",
|
"stackedAssets"."originalPath" AS "stackedAssets_originalPath",
|
||||||
"stackedAssets"."resizePath" AS "stackedAssets_resizePath",
|
"stackedAssets"."previewPath" AS "stackedAssets_previewPath",
|
||||||
"stackedAssets"."webpPath" AS "stackedAssets_webpPath",
|
"stackedAssets"."thumbnailPath" AS "stackedAssets_thumbnailPath",
|
||||||
"stackedAssets"."thumbhash" AS "stackedAssets_thumbhash",
|
"stackedAssets"."thumbhash" AS "stackedAssets_thumbhash",
|
||||||
"stackedAssets"."encodedVideoPath" AS "stackedAssets_encodedVideoPath",
|
"stackedAssets"."encodedVideoPath" AS "stackedAssets_encodedVideoPath",
|
||||||
"stackedAssets"."createdAt" AS "stackedAssets_createdAt",
|
"stackedAssets"."createdAt" AS "stackedAssets_createdAt",
|
||||||
@ -110,8 +110,8 @@ SELECT
|
|||||||
"asset"."deviceId" AS "asset_deviceId",
|
"asset"."deviceId" AS "asset_deviceId",
|
||||||
"asset"."type" AS "asset_type",
|
"asset"."type" AS "asset_type",
|
||||||
"asset"."originalPath" AS "asset_originalPath",
|
"asset"."originalPath" AS "asset_originalPath",
|
||||||
"asset"."resizePath" AS "asset_resizePath",
|
"asset"."previewPath" AS "asset_previewPath",
|
||||||
"asset"."webpPath" AS "asset_webpPath",
|
"asset"."thumbnailPath" AS "asset_thumbnailPath",
|
||||||
"asset"."thumbhash" AS "asset_thumbhash",
|
"asset"."thumbhash" AS "asset_thumbhash",
|
||||||
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
||||||
"asset"."createdAt" AS "asset_createdAt",
|
"asset"."createdAt" AS "asset_createdAt",
|
||||||
@ -141,8 +141,8 @@ SELECT
|
|||||||
"stackedAssets"."deviceId" AS "stackedAssets_deviceId",
|
"stackedAssets"."deviceId" AS "stackedAssets_deviceId",
|
||||||
"stackedAssets"."type" AS "stackedAssets_type",
|
"stackedAssets"."type" AS "stackedAssets_type",
|
||||||
"stackedAssets"."originalPath" AS "stackedAssets_originalPath",
|
"stackedAssets"."originalPath" AS "stackedAssets_originalPath",
|
||||||
"stackedAssets"."resizePath" AS "stackedAssets_resizePath",
|
"stackedAssets"."previewPath" AS "stackedAssets_previewPath",
|
||||||
"stackedAssets"."webpPath" AS "stackedAssets_webpPath",
|
"stackedAssets"."thumbnailPath" AS "stackedAssets_thumbnailPath",
|
||||||
"stackedAssets"."thumbhash" AS "stackedAssets_thumbhash",
|
"stackedAssets"."thumbhash" AS "stackedAssets_thumbhash",
|
||||||
"stackedAssets"."encodedVideoPath" AS "stackedAssets_encodedVideoPath",
|
"stackedAssets"."encodedVideoPath" AS "stackedAssets_encodedVideoPath",
|
||||||
"stackedAssets"."createdAt" AS "stackedAssets_createdAt",
|
"stackedAssets"."createdAt" AS "stackedAssets_createdAt",
|
||||||
@ -320,8 +320,8 @@ SELECT
|
|||||||
"asset"."deviceId" AS "asset_deviceId",
|
"asset"."deviceId" AS "asset_deviceId",
|
||||||
"asset"."type" AS "asset_type",
|
"asset"."type" AS "asset_type",
|
||||||
"asset"."originalPath" AS "asset_originalPath",
|
"asset"."originalPath" AS "asset_originalPath",
|
||||||
"asset"."resizePath" AS "asset_resizePath",
|
"asset"."previewPath" AS "asset_previewPath",
|
||||||
"asset"."webpPath" AS "asset_webpPath",
|
"asset"."thumbnailPath" AS "asset_thumbnailPath",
|
||||||
"asset"."thumbhash" AS "asset_thumbhash",
|
"asset"."thumbhash" AS "asset_thumbhash",
|
||||||
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
"asset"."encodedVideoPath" AS "asset_encodedVideoPath",
|
||||||
"asset"."createdAt" AS "asset_createdAt",
|
"asset"."createdAt" AS "asset_createdAt",
|
||||||
|
@ -28,8 +28,8 @@ FROM
|
|||||||
"SharedLinkEntity__SharedLinkEntity_assets"."deviceId" AS "SharedLinkEntity__SharedLinkEntity_assets_deviceId",
|
"SharedLinkEntity__SharedLinkEntity_assets"."deviceId" AS "SharedLinkEntity__SharedLinkEntity_assets_deviceId",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."type" AS "SharedLinkEntity__SharedLinkEntity_assets_type",
|
"SharedLinkEntity__SharedLinkEntity_assets"."type" AS "SharedLinkEntity__SharedLinkEntity_assets_type",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."originalPath" AS "SharedLinkEntity__SharedLinkEntity_assets_originalPath",
|
"SharedLinkEntity__SharedLinkEntity_assets"."originalPath" AS "SharedLinkEntity__SharedLinkEntity_assets_originalPath",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."resizePath" AS "SharedLinkEntity__SharedLinkEntity_assets_resizePath",
|
"SharedLinkEntity__SharedLinkEntity_assets"."previewPath" AS "SharedLinkEntity__SharedLinkEntity_assets_previewPath",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."webpPath" AS "SharedLinkEntity__SharedLinkEntity_assets_webpPath",
|
"SharedLinkEntity__SharedLinkEntity_assets"."thumbnailPath" AS "SharedLinkEntity__SharedLinkEntity_assets_thumbnailPath",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."thumbhash" AS "SharedLinkEntity__SharedLinkEntity_assets_thumbhash",
|
"SharedLinkEntity__SharedLinkEntity_assets"."thumbhash" AS "SharedLinkEntity__SharedLinkEntity_assets_thumbhash",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."encodedVideoPath" AS "SharedLinkEntity__SharedLinkEntity_assets_encodedVideoPath",
|
"SharedLinkEntity__SharedLinkEntity_assets"."encodedVideoPath" AS "SharedLinkEntity__SharedLinkEntity_assets_encodedVideoPath",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."createdAt" AS "SharedLinkEntity__SharedLinkEntity_assets_createdAt",
|
"SharedLinkEntity__SharedLinkEntity_assets"."createdAt" AS "SharedLinkEntity__SharedLinkEntity_assets_createdAt",
|
||||||
@ -95,8 +95,8 @@ FROM
|
|||||||
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."deviceId" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_deviceId",
|
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."deviceId" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_deviceId",
|
||||||
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."type" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_type",
|
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."type" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_type",
|
||||||
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."originalPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_originalPath",
|
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."originalPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_originalPath",
|
||||||
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."resizePath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_resizePath",
|
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."previewPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_previewPath",
|
||||||
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."webpPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_webpPath",
|
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."thumbnailPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_thumbnailPath",
|
||||||
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."thumbhash" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_thumbhash",
|
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."thumbhash" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_thumbhash",
|
||||||
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."encodedVideoPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_encodedVideoPath",
|
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."encodedVideoPath" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_encodedVideoPath",
|
||||||
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."createdAt" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_createdAt",
|
"4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6"."createdAt" AS "4a35f463ae8c5544ede95c4b6d9ce8c686b6bfe6_createdAt",
|
||||||
@ -218,8 +218,8 @@ SELECT
|
|||||||
"SharedLinkEntity__SharedLinkEntity_assets"."deviceId" AS "SharedLinkEntity__SharedLinkEntity_assets_deviceId",
|
"SharedLinkEntity__SharedLinkEntity_assets"."deviceId" AS "SharedLinkEntity__SharedLinkEntity_assets_deviceId",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."type" AS "SharedLinkEntity__SharedLinkEntity_assets_type",
|
"SharedLinkEntity__SharedLinkEntity_assets"."type" AS "SharedLinkEntity__SharedLinkEntity_assets_type",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."originalPath" AS "SharedLinkEntity__SharedLinkEntity_assets_originalPath",
|
"SharedLinkEntity__SharedLinkEntity_assets"."originalPath" AS "SharedLinkEntity__SharedLinkEntity_assets_originalPath",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."resizePath" AS "SharedLinkEntity__SharedLinkEntity_assets_resizePath",
|
"SharedLinkEntity__SharedLinkEntity_assets"."previewPath" AS "SharedLinkEntity__SharedLinkEntity_assets_previewPath",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."webpPath" AS "SharedLinkEntity__SharedLinkEntity_assets_webpPath",
|
"SharedLinkEntity__SharedLinkEntity_assets"."thumbnailPath" AS "SharedLinkEntity__SharedLinkEntity_assets_thumbnailPath",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."thumbhash" AS "SharedLinkEntity__SharedLinkEntity_assets_thumbhash",
|
"SharedLinkEntity__SharedLinkEntity_assets"."thumbhash" AS "SharedLinkEntity__SharedLinkEntity_assets_thumbhash",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."encodedVideoPath" AS "SharedLinkEntity__SharedLinkEntity_assets_encodedVideoPath",
|
"SharedLinkEntity__SharedLinkEntity_assets"."encodedVideoPath" AS "SharedLinkEntity__SharedLinkEntity_assets_encodedVideoPath",
|
||||||
"SharedLinkEntity__SharedLinkEntity_assets"."createdAt" AS "SharedLinkEntity__SharedLinkEntity_assets_createdAt",
|
"SharedLinkEntity__SharedLinkEntity_assets"."createdAt" AS "SharedLinkEntity__SharedLinkEntity_assets_createdAt",
|
||||||
|
@ -66,7 +66,7 @@ export class AssetRepositoryV1 implements IAssetRepositoryV1 {
|
|||||||
getDetectedObjectsByUserId(userId: string): Promise<CuratedObjectsResponseDto[]> {
|
getDetectedObjectsByUserId(userId: string): Promise<CuratedObjectsResponseDto[]> {
|
||||||
return this.assetRepository.query(
|
return this.assetRepository.query(
|
||||||
`
|
`
|
||||||
SELECT DISTINCT ON (unnest(si.objects)) a.id, unnest(si.objects) as "object", a."resizePath", a."deviceAssetId", a."deviceId"
|
SELECT DISTINCT ON (unnest(si.objects)) a.id, unnest(si.objects) as "object", a."previewPath" AS "resizePath", a."deviceAssetId", a."deviceId"
|
||||||
FROM assets a
|
FROM assets a
|
||||||
LEFT JOIN smart_info si ON a.id = si."assetId"
|
LEFT JOIN smart_info si ON a.id = si."assetId"
|
||||||
WHERE a."ownerId" = $1
|
WHERE a."ownerId" = $1
|
||||||
@ -80,7 +80,7 @@ export class AssetRepositoryV1 implements IAssetRepositoryV1 {
|
|||||||
getLocationsByUserId(userId: string): Promise<CuratedLocationsResponseDto[]> {
|
getLocationsByUserId(userId: string): Promise<CuratedLocationsResponseDto[]> {
|
||||||
return this.assetRepository.query(
|
return this.assetRepository.query(
|
||||||
`
|
`
|
||||||
SELECT DISTINCT ON (e.city) a.id, e.city, a."resizePath", a."deviceAssetId", a."deviceId"
|
SELECT DISTINCT ON (e.city) a.id, e.city, a."previewPath" AS "resizePath", a."deviceAssetId", a."deviceId"
|
||||||
FROM assets a
|
FROM assets a
|
||||||
LEFT JOIN exif e ON a.id = e."assetId"
|
LEFT JOIN exif e ON a.id = e."assetId"
|
||||||
WHERE a."ownerId" = $1
|
WHERE a."ownerId" = $1
|
||||||
|
@ -83,7 +83,7 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
`entity.ownerId IN (:...ownerIds)
|
`entity.ownerId IN (:...ownerIds)
|
||||||
AND entity.isVisible = true
|
AND entity.isVisible = true
|
||||||
AND entity.isArchived = false
|
AND entity.isArchived = false
|
||||||
AND entity.resizePath IS NOT NULL
|
AND entity.previewPath IS NOT NULL
|
||||||
AND EXTRACT(DAY FROM entity.localDateTime AT TIME ZONE 'UTC') = :day
|
AND EXTRACT(DAY FROM entity.localDateTime AT TIME ZONE 'UTC') = :day
|
||||||
AND EXTRACT(MONTH FROM entity.localDateTime AT TIME ZONE 'UTC') = :month`,
|
AND EXTRACT(MONTH FROM entity.localDateTime AT TIME ZONE 'UTC') = :month`,
|
||||||
{
|
{
|
||||||
@ -302,10 +302,10 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
switch (property) {
|
switch (property) {
|
||||||
case WithoutProperty.THUMBNAIL: {
|
case WithoutProperty.THUMBNAIL: {
|
||||||
where = [
|
where = [
|
||||||
{ resizePath: IsNull(), isVisible: true },
|
{ previewPath: IsNull(), isVisible: true },
|
||||||
{ resizePath: '', isVisible: true },
|
{ previewPath: '', isVisible: true },
|
||||||
{ webpPath: IsNull(), isVisible: true },
|
{ thumbnailPath: IsNull(), isVisible: true },
|
||||||
{ webpPath: '', isVisible: true },
|
{ thumbnailPath: '', isVisible: true },
|
||||||
{ thumbhash: IsNull(), isVisible: true },
|
{ thumbhash: IsNull(), isVisible: true },
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
@ -339,7 +339,7 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
};
|
};
|
||||||
where = {
|
where = {
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
resizePath: Not(IsNull()),
|
previewPath: Not(IsNull()),
|
||||||
smartSearch: {
|
smartSearch: {
|
||||||
embedding: IsNull(),
|
embedding: IsNull(),
|
||||||
},
|
},
|
||||||
@ -352,7 +352,7 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
smartInfo: true,
|
smartInfo: true,
|
||||||
};
|
};
|
||||||
where = {
|
where = {
|
||||||
resizePath: Not(IsNull()),
|
previewPath: Not(IsNull()),
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
smartInfo: {
|
smartInfo: {
|
||||||
tags: IsNull(),
|
tags: IsNull(),
|
||||||
@ -367,7 +367,7 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
jobStatus: true,
|
jobStatus: true,
|
||||||
};
|
};
|
||||||
where = {
|
where = {
|
||||||
resizePath: Not(IsNull()),
|
previewPath: Not(IsNull()),
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
faces: {
|
faces: {
|
||||||
assetId: IsNull(),
|
assetId: IsNull(),
|
||||||
@ -385,7 +385,7 @@ export class AssetRepository implements IAssetRepository {
|
|||||||
faces: true,
|
faces: true,
|
||||||
};
|
};
|
||||||
where = {
|
where = {
|
||||||
resizePath: Not(IsNull()),
|
previewPath: Not(IsNull()),
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
faces: {
|
faces: {
|
||||||
assetId: Not(IsNull()),
|
assetId: Not(IsNull()),
|
||||||
|
@ -35,9 +35,9 @@ export const JOBS_TO_QUEUE: Record<JobName, QueueName> = {
|
|||||||
|
|
||||||
// thumbnails
|
// thumbnails
|
||||||
[JobName.QUEUE_GENERATE_THUMBNAILS]: QueueName.THUMBNAIL_GENERATION,
|
[JobName.QUEUE_GENERATE_THUMBNAILS]: QueueName.THUMBNAIL_GENERATION,
|
||||||
[JobName.GENERATE_JPEG_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
[JobName.GENERATE_PREVIEW]: QueueName.THUMBNAIL_GENERATION,
|
||||||
[JobName.GENERATE_WEBP_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
[JobName.GENERATE_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
||||||
[JobName.GENERATE_THUMBHASH_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
[JobName.GENERATE_THUMBHASH]: QueueName.THUMBNAIL_GENERATION,
|
||||||
[JobName.GENERATE_PERSON_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
[JobName.GENERATE_PERSON_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
||||||
|
|
||||||
// metadata
|
// metadata
|
||||||
|
@ -44,13 +44,13 @@ const _getAsset_1 = () => {
|
|||||||
asset_1.deviceId = 'device_id_1';
|
asset_1.deviceId = 'device_id_1';
|
||||||
asset_1.type = AssetType.VIDEO;
|
asset_1.type = AssetType.VIDEO;
|
||||||
asset_1.originalPath = 'fake_path/asset_1.jpeg';
|
asset_1.originalPath = 'fake_path/asset_1.jpeg';
|
||||||
asset_1.resizePath = '';
|
asset_1.previewPath = '';
|
||||||
asset_1.fileModifiedAt = new Date('2022-06-19T23:41:36.910Z');
|
asset_1.fileModifiedAt = new Date('2022-06-19T23:41:36.910Z');
|
||||||
asset_1.fileCreatedAt = new Date('2022-06-19T23:41:36.910Z');
|
asset_1.fileCreatedAt = new Date('2022-06-19T23:41:36.910Z');
|
||||||
asset_1.updatedAt = new Date('2022-06-19T23:41:36.910Z');
|
asset_1.updatedAt = new Date('2022-06-19T23:41:36.910Z');
|
||||||
asset_1.isFavorite = false;
|
asset_1.isFavorite = false;
|
||||||
asset_1.isArchived = false;
|
asset_1.isArchived = false;
|
||||||
asset_1.webpPath = '';
|
asset_1.thumbnailPath = '';
|
||||||
asset_1.encodedVideoPath = '';
|
asset_1.encodedVideoPath = '';
|
||||||
asset_1.duration = '0:00:00.000000';
|
asset_1.duration = '0:00:00.000000';
|
||||||
asset_1.exifInfo = new ExifEntity();
|
asset_1.exifInfo = new ExifEntity();
|
||||||
|
@ -247,16 +247,16 @@ export class AssetServiceV1 {
|
|||||||
private getThumbnailPath(asset: AssetEntity, format: GetAssetThumbnailFormatEnum) {
|
private getThumbnailPath(asset: AssetEntity, format: GetAssetThumbnailFormatEnum) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case GetAssetThumbnailFormatEnum.WEBP: {
|
case GetAssetThumbnailFormatEnum.WEBP: {
|
||||||
if (asset.webpPath) {
|
if (asset.thumbnailPath) {
|
||||||
return asset.webpPath;
|
return asset.thumbnailPath;
|
||||||
}
|
}
|
||||||
this.logger.warn(`WebP thumbnail requested but not found for asset ${asset.id}, falling back to JPEG`);
|
this.logger.warn(`WebP thumbnail requested but not found for asset ${asset.id}, falling back to JPEG`);
|
||||||
}
|
}
|
||||||
case GetAssetThumbnailFormatEnum.JPEG: {
|
case GetAssetThumbnailFormatEnum.JPEG: {
|
||||||
if (!asset.resizePath) {
|
if (!asset.previewPath) {
|
||||||
throw new NotFoundException(`No thumbnail found for asset ${asset.id}`);
|
throw new NotFoundException(`No thumbnail found for asset ${asset.id}`);
|
||||||
}
|
}
|
||||||
return asset.resizePath;
|
return asset.previewPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,12 +268,12 @@ export class AssetServiceV1 {
|
|||||||
* Serve file viewer on the web
|
* Serve file viewer on the web
|
||||||
*/
|
*/
|
||||||
if (dto.isWeb && mimeType != 'image/gif') {
|
if (dto.isWeb && mimeType != 'image/gif') {
|
||||||
if (!asset.resizePath) {
|
if (!asset.previewPath) {
|
||||||
this.logger.error('Error serving IMAGE asset for web');
|
this.logger.error('Error serving IMAGE asset for web');
|
||||||
throw new InternalServerErrorException(`Failed to serve image asset for web`, 'ServeFile');
|
throw new InternalServerErrorException(`Failed to serve image asset for web`, 'ServeFile');
|
||||||
}
|
}
|
||||||
|
|
||||||
return asset.resizePath;
|
return asset.previewPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -283,15 +283,15 @@ export class AssetServiceV1 {
|
|||||||
return asset.originalPath;
|
return asset.originalPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asset.webpPath && asset.webpPath.length > 0) {
|
if (asset.thumbnailPath && asset.thumbnailPath.length > 0) {
|
||||||
return asset.webpPath;
|
return asset.thumbnailPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!asset.resizePath) {
|
if (!asset.previewPath) {
|
||||||
throw new Error('resizePath not set');
|
throw new Error('previewPath not set');
|
||||||
}
|
}
|
||||||
|
|
||||||
return asset.resizePath;
|
return asset.previewPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getLibraryId(auth: AuthDto, libraryId?: string) {
|
private async getLibraryId(auth: AuthDto, libraryId?: string) {
|
||||||
|
@ -661,8 +661,8 @@ describe(AssetService.name, () => {
|
|||||||
name: JobName.DELETE_FILES,
|
name: JobName.DELETE_FILES,
|
||||||
data: {
|
data: {
|
||||||
files: [
|
files: [
|
||||||
assetWithFace.webpPath,
|
assetWithFace.thumbnailPath,
|
||||||
assetWithFace.resizePath,
|
assetWithFace.previewPath,
|
||||||
assetWithFace.encodedVideoPath,
|
assetWithFace.encodedVideoPath,
|
||||||
assetWithFace.sidecarPath,
|
assetWithFace.sidecarPath,
|
||||||
assetWithFace.originalPath,
|
assetWithFace.originalPath,
|
||||||
@ -745,8 +745,8 @@ describe(AssetService.name, () => {
|
|||||||
name: JobName.DELETE_FILES,
|
name: JobName.DELETE_FILES,
|
||||||
data: {
|
data: {
|
||||||
files: [
|
files: [
|
||||||
assetStub.external.webpPath,
|
assetStub.external.thumbnailPath,
|
||||||
assetStub.external.resizePath,
|
assetStub.external.previewPath,
|
||||||
assetStub.external.encodedVideoPath,
|
assetStub.external.encodedVideoPath,
|
||||||
assetStub.external.sidecarPath,
|
assetStub.external.sidecarPath,
|
||||||
],
|
],
|
||||||
@ -828,9 +828,7 @@ describe(AssetService.name, () => {
|
|||||||
it('should run the refresh thumbnails job', async () => {
|
it('should run the refresh thumbnails job', async () => {
|
||||||
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset-1']));
|
accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset-1']));
|
||||||
await sut.run(authStub.admin, { assetIds: ['asset-1'], name: AssetJobName.REGENERATE_THUMBNAIL }),
|
await sut.run(authStub.admin, { assetIds: ['asset-1'], name: AssetJobName.REGENERATE_THUMBNAIL }),
|
||||||
expect(jobMock.queueAll).toHaveBeenCalledWith([
|
expect(jobMock.queueAll).toHaveBeenCalledWith([{ name: JobName.GENERATE_PREVIEW, data: { id: 'asset-1' } }]);
|
||||||
{ name: JobName.GENERATE_JPEG_THUMBNAIL, data: { id: 'asset-1' } },
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should run the transcode video', async () => {
|
it('should run the transcode video', async () => {
|
||||||
|
@ -399,7 +399,7 @@ export class AssetService {
|
|||||||
await this.jobRepository.queue({ name: JobName.ASSET_DELETION, data: { id: asset.livePhotoVideoId } });
|
await this.jobRepository.queue({ name: JobName.ASSET_DELETION, data: { id: asset.livePhotoVideoId } });
|
||||||
}
|
}
|
||||||
|
|
||||||
const files = [asset.webpPath, asset.resizePath, asset.encodedVideoPath, asset.sidecarPath];
|
const files = [asset.thumbnailPath, asset.previewPath, asset.encodedVideoPath, asset.sidecarPath];
|
||||||
if (!fromExternal) {
|
if (!fromExternal) {
|
||||||
files.push(asset.originalPath);
|
files.push(asset.originalPath);
|
||||||
}
|
}
|
||||||
@ -472,7 +472,7 @@ export class AssetService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case AssetJobName.REGENERATE_THUMBNAIL: {
|
case AssetJobName.REGENERATE_THUMBNAIL: {
|
||||||
jobs.push({ name: JobName.GENERATE_JPEG_THUMBNAIL, data: { id } });
|
jobs.push({ name: JobName.GENERATE_PREVIEW, data: { id } });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,13 +95,13 @@ export class AuditService {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AssetPathType.JPEG_THUMBNAIL: {
|
case AssetPathType.PREVIEW: {
|
||||||
await this.assetRepository.update({ id, resizePath: pathValue });
|
await this.assetRepository.update({ id, previewPath: pathValue });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AssetPathType.WEBP_THUMBNAIL: {
|
case AssetPathType.THUMBNAIL: {
|
||||||
await this.assetRepository.update({ id, webpPath: pathValue });
|
await this.assetRepository.update({ id, thumbnailPath: pathValue });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,8 +174,8 @@ export class AuditService {
|
|||||||
const orphans: FileReportItemDto[] = [];
|
const orphans: FileReportItemDto[] = [];
|
||||||
for await (const assets of pagination) {
|
for await (const assets of pagination) {
|
||||||
assetCount += assets.length;
|
assetCount += assets.length;
|
||||||
for (const { id, originalPath, resizePath, encodedVideoPath, webpPath, isExternal, checksum } of assets) {
|
for (const { id, originalPath, previewPath, encodedVideoPath, thumbnailPath, isExternal, checksum } of assets) {
|
||||||
for (const file of [originalPath, resizePath, encodedVideoPath, webpPath]) {
|
for (const file of [originalPath, previewPath, encodedVideoPath, thumbnailPath]) {
|
||||||
track(file);
|
track(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,14 +191,14 @@ export class AuditService {
|
|||||||
) {
|
) {
|
||||||
orphans.push({ ...entity, pathType: AssetPathType.ORIGINAL, pathValue: originalPath });
|
orphans.push({ ...entity, pathType: AssetPathType.ORIGINAL, pathValue: originalPath });
|
||||||
}
|
}
|
||||||
if (resizePath && !hasFile(thumbFiles, resizePath)) {
|
if (previewPath && !hasFile(thumbFiles, previewPath)) {
|
||||||
orphans.push({ ...entity, pathType: AssetPathType.JPEG_THUMBNAIL, pathValue: resizePath });
|
orphans.push({ ...entity, pathType: AssetPathType.PREVIEW, pathValue: previewPath });
|
||||||
}
|
}
|
||||||
if (webpPath && !hasFile(thumbFiles, webpPath)) {
|
if (thumbnailPath && !hasFile(thumbFiles, thumbnailPath)) {
|
||||||
orphans.push({ ...entity, pathType: AssetPathType.WEBP_THUMBNAIL, pathValue: webpPath });
|
orphans.push({ ...entity, pathType: AssetPathType.THUMBNAIL, pathValue: thumbnailPath });
|
||||||
}
|
}
|
||||||
if (encodedVideoPath && !hasFile(videoFiles, encodedVideoPath)) {
|
if (encodedVideoPath && !hasFile(videoFiles, encodedVideoPath)) {
|
||||||
orphans.push({ ...entity, pathType: AssetPathType.WEBP_THUMBNAIL, pathValue: encodedVideoPath });
|
orphans.push({ ...entity, pathType: AssetPathType.THUMBNAIL, pathValue: encodedVideoPath });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,7 +279,7 @@ describe(JobService.name, () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: { name: JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE, data: { id: 'asset-1', source: 'upload' } },
|
item: { name: JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE, data: { id: 'asset-1', source: 'upload' } },
|
||||||
jobs: [JobName.GENERATE_JPEG_THUMBNAIL],
|
jobs: [JobName.GENERATE_PREVIEW],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: { name: JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE, data: { id: 'asset-1' } },
|
item: { name: JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE, data: { id: 'asset-1' } },
|
||||||
@ -290,24 +290,24 @@ describe(JobService.name, () => {
|
|||||||
jobs: [],
|
jobs: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: { name: JobName.GENERATE_JPEG_THUMBNAIL, data: { id: 'asset-1' } },
|
item: { name: JobName.GENERATE_PREVIEW, data: { id: 'asset-1' } },
|
||||||
jobs: [JobName.GENERATE_WEBP_THUMBNAIL, JobName.GENERATE_THUMBHASH_THUMBNAIL],
|
jobs: [JobName.GENERATE_THUMBNAIL, JobName.GENERATE_THUMBHASH],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: { name: JobName.GENERATE_JPEG_THUMBNAIL, data: { id: 'asset-1', source: 'upload' } },
|
item: { name: JobName.GENERATE_PREVIEW, data: { id: 'asset-1', source: 'upload' } },
|
||||||
jobs: [
|
jobs: [
|
||||||
JobName.GENERATE_WEBP_THUMBNAIL,
|
JobName.GENERATE_THUMBNAIL,
|
||||||
JobName.GENERATE_THUMBHASH_THUMBNAIL,
|
JobName.GENERATE_THUMBHASH,
|
||||||
JobName.SMART_SEARCH,
|
JobName.SMART_SEARCH,
|
||||||
JobName.FACE_DETECTION,
|
JobName.FACE_DETECTION,
|
||||||
JobName.VIDEO_CONVERSION,
|
JobName.VIDEO_CONVERSION,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
item: { name: JobName.GENERATE_JPEG_THUMBNAIL, data: { id: 'asset-live-image', source: 'upload' } },
|
item: { name: JobName.GENERATE_PREVIEW, data: { id: 'asset-live-image', source: 'upload' } },
|
||||||
jobs: [
|
jobs: [
|
||||||
JobName.GENERATE_WEBP_THUMBNAIL,
|
JobName.GENERATE_THUMBNAIL,
|
||||||
JobName.GENERATE_THUMBHASH_THUMBNAIL,
|
JobName.GENERATE_THUMBHASH,
|
||||||
JobName.SMART_SEARCH,
|
JobName.SMART_SEARCH,
|
||||||
JobName.FACE_DETECTION,
|
JobName.FACE_DETECTION,
|
||||||
JobName.VIDEO_CONVERSION,
|
JobName.VIDEO_CONVERSION,
|
||||||
@ -329,7 +329,7 @@ describe(JobService.name, () => {
|
|||||||
|
|
||||||
for (const { item, jobs } of tests) {
|
for (const { item, jobs } of tests) {
|
||||||
it(`should queue ${jobs.length} jobs when a ${item.name} job finishes successfully`, async () => {
|
it(`should queue ${jobs.length} jobs when a ${item.name} job finishes successfully`, async () => {
|
||||||
if (item.name === JobName.GENERATE_JPEG_THUMBNAIL && item.data.source === 'upload') {
|
if (item.name === JobName.GENERATE_PREVIEW && item.data.source === 'upload') {
|
||||||
if (item.data.id === 'asset-live-image') {
|
if (item.data.id === 'asset-live-image') {
|
||||||
assetMock.getByIds.mockResolvedValue([assetStub.livePhotoStillAsset]);
|
assetMock.getByIds.mockResolvedValue([assetStub.livePhotoStillAsset]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -245,7 +245,7 @@ export class JobService {
|
|||||||
|
|
||||||
case JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE: {
|
case JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE: {
|
||||||
if (item.data.source === 'upload') {
|
if (item.data.source === 'upload') {
|
||||||
await this.jobRepository.queue({ name: JobName.GENERATE_JPEG_THUMBNAIL, data: item.data });
|
await this.jobRepository.queue({ name: JobName.GENERATE_PREVIEW, data: item.data });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -259,10 +259,10 @@ export class JobService {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case JobName.GENERATE_JPEG_THUMBNAIL: {
|
case JobName.GENERATE_PREVIEW: {
|
||||||
const jobs: JobItem[] = [
|
const jobs: JobItem[] = [
|
||||||
{ name: JobName.GENERATE_WEBP_THUMBNAIL, data: item.data },
|
{ name: JobName.GENERATE_THUMBNAIL, data: item.data },
|
||||||
{ name: JobName.GENERATE_THUMBHASH_THUMBNAIL, data: item.data },
|
{ name: JobName.GENERATE_THUMBHASH, data: item.data },
|
||||||
];
|
];
|
||||||
|
|
||||||
if (item.data.source === 'upload') {
|
if (item.data.source === 'upload') {
|
||||||
@ -282,7 +282,7 @@ export class JobService {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case JobName.GENERATE_WEBP_THUMBNAIL: {
|
case JobName.GENERATE_THUMBNAIL: {
|
||||||
if (item.data.source !== 'upload') {
|
if (item.data.source !== 'upload') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import { ExifEntity } from 'src/entities/exif.entity';
|
|||||||
import {
|
import {
|
||||||
AudioCodec,
|
AudioCodec,
|
||||||
Colorspace,
|
Colorspace,
|
||||||
|
ImageFormat,
|
||||||
SystemConfigKey,
|
SystemConfigKey,
|
||||||
ToneMapping,
|
ToneMapping,
|
||||||
TranscodeHWAccel,
|
TranscodeHWAccel,
|
||||||
@ -78,7 +79,7 @@ describe(MediaService.name, () => {
|
|||||||
expect(assetMock.getWithout).not.toHaveBeenCalled();
|
expect(assetMock.getWithout).not.toHaveBeenCalled();
|
||||||
expect(jobMock.queueAll).toHaveBeenCalledWith([
|
expect(jobMock.queueAll).toHaveBeenCalledWith([
|
||||||
{
|
{
|
||||||
name: JobName.GENERATE_JPEG_THUMBNAIL,
|
name: JobName.GENERATE_PREVIEW,
|
||||||
data: { id: assetStub.image.id },
|
data: { id: assetStub.image.id },
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@ -136,7 +137,7 @@ describe(MediaService.name, () => {
|
|||||||
expect(assetMock.getWithout).toHaveBeenCalledWith({ skip: 0, take: 1000 }, WithoutProperty.THUMBNAIL);
|
expect(assetMock.getWithout).toHaveBeenCalledWith({ skip: 0, take: 1000 }, WithoutProperty.THUMBNAIL);
|
||||||
expect(jobMock.queueAll).toHaveBeenCalledWith([
|
expect(jobMock.queueAll).toHaveBeenCalledWith([
|
||||||
{
|
{
|
||||||
name: JobName.GENERATE_JPEG_THUMBNAIL,
|
name: JobName.GENERATE_PREVIEW,
|
||||||
data: { id: assetStub.image.id },
|
data: { id: assetStub.image.id },
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@ -160,7 +161,7 @@ describe(MediaService.name, () => {
|
|||||||
expect(assetMock.getWithout).toHaveBeenCalledWith({ skip: 0, take: 1000 }, WithoutProperty.THUMBNAIL);
|
expect(assetMock.getWithout).toHaveBeenCalledWith({ skip: 0, take: 1000 }, WithoutProperty.THUMBNAIL);
|
||||||
expect(jobMock.queueAll).toHaveBeenCalledWith([
|
expect(jobMock.queueAll).toHaveBeenCalledWith([
|
||||||
{
|
{
|
||||||
name: JobName.GENERATE_WEBP_THUMBNAIL,
|
name: JobName.GENERATE_THUMBNAIL,
|
||||||
data: { id: assetStub.image.id },
|
data: { id: assetStub.image.id },
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@ -184,7 +185,7 @@ describe(MediaService.name, () => {
|
|||||||
expect(assetMock.getWithout).toHaveBeenCalledWith({ skip: 0, take: 1000 }, WithoutProperty.THUMBNAIL);
|
expect(assetMock.getWithout).toHaveBeenCalledWith({ skip: 0, take: 1000 }, WithoutProperty.THUMBNAIL);
|
||||||
expect(jobMock.queueAll).toHaveBeenCalledWith([
|
expect(jobMock.queueAll).toHaveBeenCalledWith([
|
||||||
{
|
{
|
||||||
name: JobName.GENERATE_THUMBHASH_THUMBNAIL,
|
name: JobName.GENERATE_THUMBHASH,
|
||||||
data: { id: assetStub.image.id },
|
data: { id: assetStub.image.id },
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@ -193,10 +194,10 @@ describe(MediaService.name, () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('handleGenerateJpegThumbnail', () => {
|
describe('handleGeneratePreview', () => {
|
||||||
it('should skip thumbnail generation if asset not found', async () => {
|
it('should skip thumbnail generation if asset not found', async () => {
|
||||||
assetMock.getByIds.mockResolvedValue([]);
|
assetMock.getByIds.mockResolvedValue([]);
|
||||||
await sut.handleGenerateJpegThumbnail({ id: assetStub.image.id });
|
await sut.handleGeneratePreview({ id: assetStub.image.id });
|
||||||
expect(mediaMock.resize).not.toHaveBeenCalled();
|
expect(mediaMock.resize).not.toHaveBeenCalled();
|
||||||
expect(assetMock.update).not.toHaveBeenCalledWith();
|
expect(assetMock.update).not.toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
@ -204,25 +205,29 @@ describe(MediaService.name, () => {
|
|||||||
it('should skip video thumbnail generation if no video stream', async () => {
|
it('should skip video thumbnail generation if no video stream', async () => {
|
||||||
mediaMock.probe.mockResolvedValue(probeStub.noVideoStreams);
|
mediaMock.probe.mockResolvedValue(probeStub.noVideoStreams);
|
||||||
assetMock.getByIds.mockResolvedValue([assetStub.video]);
|
assetMock.getByIds.mockResolvedValue([assetStub.video]);
|
||||||
await sut.handleGenerateJpegThumbnail({ id: assetStub.image.id });
|
await sut.handleGeneratePreview({ id: assetStub.image.id });
|
||||||
expect(mediaMock.resize).not.toHaveBeenCalled();
|
expect(mediaMock.resize).not.toHaveBeenCalled();
|
||||||
expect(assetMock.update).not.toHaveBeenCalledWith();
|
expect(assetMock.update).not.toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate a thumbnail for an image', async () => {
|
it('should generate a thumbnail for an image', async () => {
|
||||||
assetMock.getByIds.mockResolvedValue([assetStub.image]);
|
assetMock.getByIds.mockResolvedValue([assetStub.image]);
|
||||||
await sut.handleGenerateJpegThumbnail({ id: assetStub.image.id });
|
await sut.handleGeneratePreview({ id: assetStub.image.id });
|
||||||
|
|
||||||
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
||||||
expect(mediaMock.resize).toHaveBeenCalledWith('/original/path.jpg', 'upload/thumbs/user-id/as/se/asset-id.jpeg', {
|
expect(mediaMock.resize).toHaveBeenCalledWith(
|
||||||
size: 1440,
|
'/original/path.jpg',
|
||||||
format: 'jpeg',
|
'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
quality: 80,
|
{
|
||||||
colorspace: Colorspace.SRGB,
|
size: 1440,
|
||||||
});
|
format: ImageFormat.JPEG,
|
||||||
|
quality: 80,
|
||||||
|
colorspace: Colorspace.SRGB,
|
||||||
|
},
|
||||||
|
);
|
||||||
expect(assetMock.update).toHaveBeenCalledWith({
|
expect(assetMock.update).toHaveBeenCalledWith({
|
||||||
id: 'asset-id',
|
id: 'asset-id',
|
||||||
resizePath: 'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
previewPath: 'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -230,30 +235,34 @@ describe(MediaService.name, () => {
|
|||||||
assetMock.getByIds.mockResolvedValue([
|
assetMock.getByIds.mockResolvedValue([
|
||||||
{ ...assetStub.image, exifInfo: { profileDescription: 'Adobe RGB', bitsPerSample: 14 } as ExifEntity },
|
{ ...assetStub.image, exifInfo: { profileDescription: 'Adobe RGB', bitsPerSample: 14 } as ExifEntity },
|
||||||
]);
|
]);
|
||||||
await sut.handleGenerateJpegThumbnail({ id: assetStub.image.id });
|
await sut.handleGeneratePreview({ id: assetStub.image.id });
|
||||||
|
|
||||||
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
||||||
expect(mediaMock.resize).toHaveBeenCalledWith('/original/path.jpg', 'upload/thumbs/user-id/as/se/asset-id.jpeg', {
|
expect(mediaMock.resize).toHaveBeenCalledWith(
|
||||||
size: 1440,
|
'/original/path.jpg',
|
||||||
format: 'jpeg',
|
'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
quality: 80,
|
{
|
||||||
colorspace: Colorspace.P3,
|
size: 1440,
|
||||||
});
|
format: ImageFormat.JPEG,
|
||||||
|
quality: 80,
|
||||||
|
colorspace: Colorspace.P3,
|
||||||
|
},
|
||||||
|
);
|
||||||
expect(assetMock.update).toHaveBeenCalledWith({
|
expect(assetMock.update).toHaveBeenCalledWith({
|
||||||
id: 'asset-id',
|
id: 'asset-id',
|
||||||
resizePath: 'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
previewPath: 'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate a thumbnail for a video', async () => {
|
it('should generate a thumbnail for a video', async () => {
|
||||||
mediaMock.probe.mockResolvedValue(probeStub.videoStream2160p);
|
mediaMock.probe.mockResolvedValue(probeStub.videoStream2160p);
|
||||||
assetMock.getByIds.mockResolvedValue([assetStub.video]);
|
assetMock.getByIds.mockResolvedValue([assetStub.video]);
|
||||||
await sut.handleGenerateJpegThumbnail({ id: assetStub.video.id });
|
await sut.handleGeneratePreview({ id: assetStub.video.id });
|
||||||
|
|
||||||
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
||||||
expect(mediaMock.transcode).toHaveBeenCalledWith(
|
expect(mediaMock.transcode).toHaveBeenCalledWith(
|
||||||
'/original/path.ext',
|
'/original/path.ext',
|
||||||
'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
{
|
{
|
||||||
inputOptions: ['-ss 00:00:00', '-sws_flags accurate_rnd+bitexact+full_chroma_int'],
|
inputOptions: ['-ss 00:00:00', '-sws_flags accurate_rnd+bitexact+full_chroma_int'],
|
||||||
outputOptions: [
|
outputOptions: [
|
||||||
@ -266,19 +275,19 @@ describe(MediaService.name, () => {
|
|||||||
);
|
);
|
||||||
expect(assetMock.update).toHaveBeenCalledWith({
|
expect(assetMock.update).toHaveBeenCalledWith({
|
||||||
id: 'asset-id',
|
id: 'asset-id',
|
||||||
resizePath: 'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
previewPath: 'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should tonemap thumbnail for hdr video', async () => {
|
it('should tonemap thumbnail for hdr video', async () => {
|
||||||
mediaMock.probe.mockResolvedValue(probeStub.videoStreamHDR);
|
mediaMock.probe.mockResolvedValue(probeStub.videoStreamHDR);
|
||||||
assetMock.getByIds.mockResolvedValue([assetStub.video]);
|
assetMock.getByIds.mockResolvedValue([assetStub.video]);
|
||||||
await sut.handleGenerateJpegThumbnail({ id: assetStub.video.id });
|
await sut.handleGeneratePreview({ id: assetStub.video.id });
|
||||||
|
|
||||||
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
||||||
expect(mediaMock.transcode).toHaveBeenCalledWith(
|
expect(mediaMock.transcode).toHaveBeenCalledWith(
|
||||||
'/original/path.ext',
|
'/original/path.ext',
|
||||||
'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
{
|
{
|
||||||
inputOptions: ['-ss 00:00:00', '-sws_flags accurate_rnd+bitexact+full_chroma_int'],
|
inputOptions: ['-ss 00:00:00', '-sws_flags accurate_rnd+bitexact+full_chroma_int'],
|
||||||
outputOptions: [
|
outputOptions: [
|
||||||
@ -291,7 +300,7 @@ describe(MediaService.name, () => {
|
|||||||
);
|
);
|
||||||
expect(assetMock.update).toHaveBeenCalledWith({
|
expect(assetMock.update).toHaveBeenCalledWith({
|
||||||
id: 'asset-id',
|
id: 'asset-id',
|
||||||
resizePath: 'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
previewPath: 'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -302,11 +311,11 @@ describe(MediaService.name, () => {
|
|||||||
{ key: SystemConfigKey.FFMPEG_MAX_BITRATE, value: '5000k' },
|
{ key: SystemConfigKey.FFMPEG_MAX_BITRATE, value: '5000k' },
|
||||||
]);
|
]);
|
||||||
assetMock.getByIds.mockResolvedValue([assetStub.video]);
|
assetMock.getByIds.mockResolvedValue([assetStub.video]);
|
||||||
await sut.handleGenerateJpegThumbnail({ id: assetStub.video.id });
|
await sut.handleGeneratePreview({ id: assetStub.video.id });
|
||||||
|
|
||||||
expect(mediaMock.transcode).toHaveBeenCalledWith(
|
expect(mediaMock.transcode).toHaveBeenCalledWith(
|
||||||
'/original/path.ext',
|
'/original/path.ext',
|
||||||
'upload/thumbs/user-id/as/se/asset-id.jpeg',
|
'upload/thumbs/user-id/as/se/asset-id-preview.jpeg',
|
||||||
{
|
{
|
||||||
inputOptions: ['-ss 00:00:00', '-sws_flags accurate_rnd+bitexact+full_chroma_int'],
|
inputOptions: ['-ss 00:00:00', '-sws_flags accurate_rnd+bitexact+full_chroma_int'],
|
||||||
outputOptions: [
|
outputOptions: [
|
||||||
@ -321,31 +330,35 @@ describe(MediaService.name, () => {
|
|||||||
|
|
||||||
it('should run successfully', async () => {
|
it('should run successfully', async () => {
|
||||||
assetMock.getByIds.mockResolvedValue([assetStub.image]);
|
assetMock.getByIds.mockResolvedValue([assetStub.image]);
|
||||||
await sut.handleGenerateJpegThumbnail({ id: assetStub.image.id });
|
await sut.handleGeneratePreview({ id: assetStub.image.id });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('handleGenerateWebpThumbnail', () => {
|
describe('handleGenerateThumbnail', () => {
|
||||||
it('should skip thumbnail generation if asset not found', async () => {
|
it('should skip thumbnail generation if asset not found', async () => {
|
||||||
assetMock.getByIds.mockResolvedValue([]);
|
assetMock.getByIds.mockResolvedValue([]);
|
||||||
await sut.handleGenerateWebpThumbnail({ id: assetStub.image.id });
|
await sut.handleGenerateThumbnail({ id: assetStub.image.id });
|
||||||
expect(mediaMock.resize).not.toHaveBeenCalled();
|
expect(mediaMock.resize).not.toHaveBeenCalled();
|
||||||
expect(assetMock.update).not.toHaveBeenCalledWith();
|
expect(assetMock.update).not.toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate a thumbnail', async () => {
|
it('should generate a thumbnail', async () => {
|
||||||
assetMock.getByIds.mockResolvedValue([assetStub.image]);
|
assetMock.getByIds.mockResolvedValue([assetStub.image]);
|
||||||
await sut.handleGenerateWebpThumbnail({ id: assetStub.image.id });
|
await sut.handleGenerateThumbnail({ id: assetStub.image.id });
|
||||||
|
|
||||||
expect(mediaMock.resize).toHaveBeenCalledWith('/original/path.jpg', 'upload/thumbs/user-id/as/se/asset-id.webp', {
|
expect(mediaMock.resize).toHaveBeenCalledWith(
|
||||||
format: 'webp',
|
'/original/path.jpg',
|
||||||
size: 250,
|
'upload/thumbs/user-id/as/se/asset-id-thumbnail.webp',
|
||||||
quality: 80,
|
{
|
||||||
colorspace: Colorspace.SRGB,
|
format: ImageFormat.WEBP,
|
||||||
});
|
size: 250,
|
||||||
|
quality: 80,
|
||||||
|
colorspace: Colorspace.SRGB,
|
||||||
|
},
|
||||||
|
);
|
||||||
expect(assetMock.update).toHaveBeenCalledWith({
|
expect(assetMock.update).toHaveBeenCalledWith({
|
||||||
id: 'asset-id',
|
id: 'asset-id',
|
||||||
webpPath: 'upload/thumbs/user-id/as/se/asset-id.webp',
|
thumbnailPath: 'upload/thumbs/user-id/as/se/asset-id-thumbnail.webp',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -354,31 +367,35 @@ describe(MediaService.name, () => {
|
|||||||
assetMock.getByIds.mockResolvedValue([
|
assetMock.getByIds.mockResolvedValue([
|
||||||
{ ...assetStub.image, exifInfo: { profileDescription: 'Adobe RGB', bitsPerSample: 14 } as ExifEntity },
|
{ ...assetStub.image, exifInfo: { profileDescription: 'Adobe RGB', bitsPerSample: 14 } as ExifEntity },
|
||||||
]);
|
]);
|
||||||
await sut.handleGenerateWebpThumbnail({ id: assetStub.image.id });
|
await sut.handleGenerateThumbnail({ id: assetStub.image.id });
|
||||||
|
|
||||||
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/thumbs/user-id/as/se');
|
||||||
expect(mediaMock.resize).toHaveBeenCalledWith('/original/path.jpg', 'upload/thumbs/user-id/as/se/asset-id.webp', {
|
expect(mediaMock.resize).toHaveBeenCalledWith(
|
||||||
format: 'webp',
|
'/original/path.jpg',
|
||||||
size: 250,
|
'upload/thumbs/user-id/as/se/asset-id-thumbnail.webp',
|
||||||
quality: 80,
|
{
|
||||||
colorspace: Colorspace.P3,
|
format: ImageFormat.WEBP,
|
||||||
});
|
size: 250,
|
||||||
|
quality: 80,
|
||||||
|
colorspace: Colorspace.P3,
|
||||||
|
},
|
||||||
|
);
|
||||||
expect(assetMock.update).toHaveBeenCalledWith({
|
expect(assetMock.update).toHaveBeenCalledWith({
|
||||||
id: 'asset-id',
|
id: 'asset-id',
|
||||||
webpPath: 'upload/thumbs/user-id/as/se/asset-id.webp',
|
thumbnailPath: 'upload/thumbs/user-id/as/se/asset-id-thumbnail.webp',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('handleGenerateThumbhashThumbnail', () => {
|
describe('handleGenerateThumbhashThumbnail', () => {
|
||||||
it('should skip thumbhash generation if asset not found', async () => {
|
it('should skip thumbhash generation if asset not found', async () => {
|
||||||
assetMock.getByIds.mockResolvedValue([]);
|
assetMock.getByIds.mockResolvedValue([]);
|
||||||
await sut.handleGenerateThumbhashThumbnail({ id: assetStub.image.id });
|
await sut.handleGenerateThumbhash({ id: assetStub.image.id });
|
||||||
expect(mediaMock.generateThumbhash).not.toHaveBeenCalled();
|
expect(mediaMock.generateThumbhash).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should skip thumbhash generation if resize path is missing', async () => {
|
it('should skip thumbhash generation if resize path is missing', async () => {
|
||||||
assetMock.getByIds.mockResolvedValue([assetStub.noResizePath]);
|
assetMock.getByIds.mockResolvedValue([assetStub.noResizePath]);
|
||||||
await sut.handleGenerateThumbhashThumbnail({ id: assetStub.noResizePath.id });
|
await sut.handleGenerateThumbhash({ id: assetStub.noResizePath.id });
|
||||||
expect(mediaMock.generateThumbhash).not.toHaveBeenCalled();
|
expect(mediaMock.generateThumbhash).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -387,7 +404,7 @@ describe(MediaService.name, () => {
|
|||||||
assetMock.getByIds.mockResolvedValue([assetStub.image]);
|
assetMock.getByIds.mockResolvedValue([assetStub.image]);
|
||||||
mediaMock.generateThumbhash.mockResolvedValue(thumbhashBuffer);
|
mediaMock.generateThumbhash.mockResolvedValue(thumbhashBuffer);
|
||||||
|
|
||||||
await sut.handleGenerateThumbhashThumbnail({ id: assetStub.image.id });
|
await sut.handleGenerateThumbhash({ id: assetStub.image.id });
|
||||||
|
|
||||||
expect(mediaMock.generateThumbhash).toHaveBeenCalledWith('/uploads/user-id/thumbs/path.jpg');
|
expect(mediaMock.generateThumbhash).toHaveBeenCalledWith('/uploads/user-id/thumbs/path.jpg');
|
||||||
expect(assetMock.update).toHaveBeenCalledWith({ id: 'asset-id', thumbhash: thumbhashBuffer });
|
expect(assetMock.update).toHaveBeenCalledWith({ id: 'asset-id', thumbhash: thumbhashBuffer });
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Inject, Injectable, UnsupportedMediaTypeException } from '@nestjs/common';
|
import { Inject, Injectable, UnsupportedMediaTypeException } from '@nestjs/common';
|
||||||
import { StorageCore, StorageFolder } from 'src/cores/storage.core';
|
import { GeneratedImageType, StorageCore, StorageFolder } from 'src/cores/storage.core';
|
||||||
import { SystemConfigCore } from 'src/cores/system-config.core';
|
import { SystemConfigCore } from 'src/cores/system-config.core';
|
||||||
import { SystemConfigFFmpegDto } from 'src/dtos/system-config.dto';
|
import { SystemConfigFFmpegDto } from 'src/dtos/system-config.dto';
|
||||||
import { AssetEntity, AssetType } from 'src/entities/asset.entity';
|
import { AssetEntity, AssetType } from 'src/entities/asset.entity';
|
||||||
@ -7,6 +7,7 @@ import { AssetPathType } from 'src/entities/move.entity';
|
|||||||
import {
|
import {
|
||||||
AudioCodec,
|
AudioCodec,
|
||||||
Colorspace,
|
Colorspace,
|
||||||
|
ImageFormat,
|
||||||
TranscodeHWAccel,
|
TranscodeHWAccel,
|
||||||
TranscodePolicy,
|
TranscodePolicy,
|
||||||
TranscodeTarget,
|
TranscodeTarget,
|
||||||
@ -81,15 +82,15 @@ export class MediaService {
|
|||||||
const jobs: JobItem[] = [];
|
const jobs: JobItem[] = [];
|
||||||
|
|
||||||
for (const asset of assets) {
|
for (const asset of assets) {
|
||||||
if (!asset.resizePath || force) {
|
if (!asset.previewPath || force) {
|
||||||
jobs.push({ name: JobName.GENERATE_JPEG_THUMBNAIL, data: { id: asset.id } });
|
jobs.push({ name: JobName.GENERATE_PREVIEW, data: { id: asset.id } });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!asset.webpPath) {
|
if (!asset.thumbnailPath) {
|
||||||
jobs.push({ name: JobName.GENERATE_WEBP_THUMBNAIL, data: { id: asset.id } });
|
jobs.push({ name: JobName.GENERATE_THUMBNAIL, data: { id: asset.id } });
|
||||||
}
|
}
|
||||||
if (!asset.thumbhash) {
|
if (!asset.thumbhash) {
|
||||||
jobs.push({ name: JobName.GENERATE_THUMBHASH_THUMBNAIL, data: { id: asset.id } });
|
jobs.push({ name: JobName.GENERATE_THUMBHASH, data: { id: asset.id } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,41 +153,41 @@ export class MediaService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async handleAssetMigration({ id }: IEntityJob): Promise<JobStatus> {
|
async handleAssetMigration({ id }: IEntityJob): Promise<JobStatus> {
|
||||||
|
const { image } = await this.configCore.getConfig();
|
||||||
const [asset] = await this.assetRepository.getByIds([id]);
|
const [asset] = await this.assetRepository.getByIds([id]);
|
||||||
if (!asset) {
|
if (!asset) {
|
||||||
return JobStatus.FAILED;
|
return JobStatus.FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.storageCore.moveAssetFile(asset, AssetPathType.JPEG_THUMBNAIL);
|
await this.storageCore.moveAssetImage(asset, AssetPathType.PREVIEW, image.previewFormat);
|
||||||
await this.storageCore.moveAssetFile(asset, AssetPathType.WEBP_THUMBNAIL);
|
await this.storageCore.moveAssetImage(asset, AssetPathType.THUMBNAIL, image.thumbnailFormat);
|
||||||
await this.storageCore.moveAssetFile(asset, AssetPathType.ENCODED_VIDEO);
|
await this.storageCore.moveAssetVideo(asset);
|
||||||
|
|
||||||
return JobStatus.SUCCESS;
|
return JobStatus.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleGenerateJpegThumbnail({ id }: IEntityJob): Promise<JobStatus> {
|
async handleGeneratePreview({ id }: IEntityJob): Promise<JobStatus> {
|
||||||
const [asset] = await this.assetRepository.getByIds([id], { exifInfo: true });
|
const [asset] = await this.assetRepository.getByIds([id], { exifInfo: true });
|
||||||
if (!asset) {
|
if (!asset) {
|
||||||
return JobStatus.FAILED;
|
return JobStatus.FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resizePath = await this.generateThumbnail(asset, 'jpeg');
|
const previewPath = await this.generateThumbnail(asset, AssetPathType.PREVIEW, ImageFormat.JPEG);
|
||||||
await this.assetRepository.update({ id: asset.id, resizePath });
|
await this.assetRepository.update({ id: asset.id, previewPath });
|
||||||
return JobStatus.SUCCESS;
|
return JobStatus.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async generateThumbnail(asset: AssetEntity, format: 'jpeg' | 'webp') {
|
private async generateThumbnail(asset: AssetEntity, type: GeneratedImageType, format: ImageFormat) {
|
||||||
const { thumbnail, ffmpeg } = await this.configCore.getConfig();
|
const { image, ffmpeg } = await this.configCore.getConfig();
|
||||||
const size = format === 'jpeg' ? thumbnail.jpegSize : thumbnail.webpSize;
|
const size = type === AssetPathType.PREVIEW ? image.previewSize : image.thumbnailSize;
|
||||||
const path =
|
const path = StorageCore.getImagePath(asset, type, format);
|
||||||
format === 'jpeg' ? StorageCore.getLargeThumbnailPath(asset) : StorageCore.getSmallThumbnailPath(asset);
|
|
||||||
this.storageCore.ensureFolders(path);
|
this.storageCore.ensureFolders(path);
|
||||||
|
|
||||||
switch (asset.type) {
|
switch (asset.type) {
|
||||||
case AssetType.IMAGE: {
|
case AssetType.IMAGE: {
|
||||||
const colorspace = this.isSRGB(asset) ? Colorspace.SRGB : thumbnail.colorspace;
|
const colorspace = this.isSRGB(asset) ? Colorspace.SRGB : image.colorspace;
|
||||||
const thumbnailOptions = { format, size, colorspace, quality: thumbnail.quality };
|
const imageOptions = { format, size, colorspace, quality: image.quality };
|
||||||
await this.mediaRepository.resize(asset.originalPath, path, thumbnailOptions);
|
await this.mediaRepository.resize(asset.originalPath, path, imageOptions);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,24 +215,24 @@ export class MediaService {
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleGenerateWebpThumbnail({ id }: IEntityJob): Promise<JobStatus> {
|
async handleGenerateThumbnail({ id }: IEntityJob): Promise<JobStatus> {
|
||||||
const [asset] = await this.assetRepository.getByIds([id], { exifInfo: true });
|
const [asset] = await this.assetRepository.getByIds([id], { exifInfo: true });
|
||||||
if (!asset) {
|
if (!asset) {
|
||||||
return JobStatus.FAILED;
|
return JobStatus.FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
const webpPath = await this.generateThumbnail(asset, 'webp');
|
const thumbnailPath = await this.generateThumbnail(asset, AssetPathType.THUMBNAIL, ImageFormat.WEBP);
|
||||||
await this.assetRepository.update({ id: asset.id, webpPath });
|
await this.assetRepository.update({ id: asset.id, thumbnailPath });
|
||||||
return JobStatus.SUCCESS;
|
return JobStatus.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleGenerateThumbhashThumbnail({ id }: IEntityJob): Promise<JobStatus> {
|
async handleGenerateThumbhash({ id }: IEntityJob): Promise<JobStatus> {
|
||||||
const [asset] = await this.assetRepository.getByIds([id]);
|
const [asset] = await this.assetRepository.getByIds([id]);
|
||||||
if (!asset?.resizePath) {
|
if (!asset?.previewPath) {
|
||||||
return JobStatus.FAILED;
|
return JobStatus.FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
const thumbhash = await this.mediaRepository.generateThumbhash(asset.resizePath);
|
const thumbhash = await this.mediaRepository.generateThumbhash(asset.previewPath);
|
||||||
await this.assetRepository.update({ id: asset.id, thumbhash });
|
await this.assetRepository.update({ id: asset.id, thumbhash });
|
||||||
|
|
||||||
return JobStatus.SUCCESS;
|
return JobStatus.SUCCESS;
|
||||||
|
@ -53,9 +53,9 @@ export class MicroservicesService {
|
|||||||
[JobName.MIGRATE_ASSET]: (data) => this.mediaService.handleAssetMigration(data),
|
[JobName.MIGRATE_ASSET]: (data) => this.mediaService.handleAssetMigration(data),
|
||||||
[JobName.MIGRATE_PERSON]: (data) => this.personService.handlePersonMigration(data),
|
[JobName.MIGRATE_PERSON]: (data) => this.personService.handlePersonMigration(data),
|
||||||
[JobName.QUEUE_GENERATE_THUMBNAILS]: (data) => this.mediaService.handleQueueGenerateThumbnails(data),
|
[JobName.QUEUE_GENERATE_THUMBNAILS]: (data) => this.mediaService.handleQueueGenerateThumbnails(data),
|
||||||
[JobName.GENERATE_JPEG_THUMBNAIL]: (data) => this.mediaService.handleGenerateJpegThumbnail(data),
|
[JobName.GENERATE_PREVIEW]: (data) => this.mediaService.handleGeneratePreview(data),
|
||||||
[JobName.GENERATE_WEBP_THUMBNAIL]: (data) => this.mediaService.handleGenerateWebpThumbnail(data),
|
[JobName.GENERATE_THUMBNAIL]: (data) => this.mediaService.handleGenerateThumbnail(data),
|
||||||
[JobName.GENERATE_THUMBHASH_THUMBNAIL]: (data) => this.mediaService.handleGenerateThumbhashThumbnail(data),
|
[JobName.GENERATE_THUMBHASH]: (data) => this.mediaService.handleGenerateThumbhash(data),
|
||||||
[JobName.QUEUE_VIDEO_CONVERSION]: (data) => this.mediaService.handleQueueVideoConversion(data),
|
[JobName.QUEUE_VIDEO_CONVERSION]: (data) => this.mediaService.handleQueueVideoConversion(data),
|
||||||
[JobName.VIDEO_CONVERSION]: (data) => this.mediaService.handleVideoConversion(data),
|
[JobName.VIDEO_CONVERSION]: (data) => this.mediaService.handleVideoConversion(data),
|
||||||
[JobName.QUEUE_METADATA_EXTRACTION]: (data) => this.metadataService.handleQueueMetadataExtraction(data),
|
[JobName.QUEUE_METADATA_EXTRACTION]: (data) => this.metadataService.handleQueueMetadataExtraction(data),
|
||||||
|
@ -645,7 +645,7 @@ describe(PersonService.name, () => {
|
|||||||
expect(machineLearningMock.detectFaces).toHaveBeenCalledWith(
|
expect(machineLearningMock.detectFaces).toHaveBeenCalledWith(
|
||||||
'http://immich-machine-learning:3003',
|
'http://immich-machine-learning:3003',
|
||||||
{
|
{
|
||||||
imagePath: assetStub.image.resizePath,
|
imagePath: assetStub.image.previewPath,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -23,6 +23,7 @@ import {
|
|||||||
} from 'src/dtos/person.dto';
|
} from 'src/dtos/person.dto';
|
||||||
import { PersonPathType } from 'src/entities/move.entity';
|
import { PersonPathType } from 'src/entities/move.entity';
|
||||||
import { PersonEntity } from 'src/entities/person.entity';
|
import { PersonEntity } from 'src/entities/person.entity';
|
||||||
|
import { ImageFormat } from 'src/entities/system-config.entity';
|
||||||
import { IAccessRepository } from 'src/interfaces/access.interface';
|
import { IAccessRepository } from 'src/interfaces/access.interface';
|
||||||
import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.interface';
|
import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.interface';
|
||||||
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
||||||
@ -315,17 +316,17 @@ export class PersonService {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const [asset] = await this.assetRepository.getByIds([id], relations);
|
const [asset] = await this.assetRepository.getByIds([id], relations);
|
||||||
if (!asset || !asset.resizePath || asset.faces?.length > 0) {
|
if (!asset || !asset.previewPath || asset.faces?.length > 0) {
|
||||||
return JobStatus.FAILED;
|
return JobStatus.FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
const faces = await this.machineLearningRepository.detectFaces(
|
const faces = await this.machineLearningRepository.detectFaces(
|
||||||
machineLearning.url,
|
machineLearning.url,
|
||||||
{ imagePath: asset.resizePath },
|
{ imagePath: asset.previewPath },
|
||||||
machineLearning.facialRecognition,
|
machineLearning.facialRecognition,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.logger.debug(`${faces.length} faces detected in ${asset.resizePath}`);
|
this.logger.debug(`${faces.length} faces detected in ${asset.previewPath}`);
|
||||||
this.logger.verbose(faces.map((face) => ({ ...face, embedding: `vector(${face.embedding.length})` })));
|
this.logger.verbose(faces.map((face) => ({ ...face, embedding: `vector(${face.embedding.length})` })));
|
||||||
|
|
||||||
if (faces.length > 0) {
|
if (faces.length > 0) {
|
||||||
@ -470,7 +471,7 @@ export class PersonService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async handleGeneratePersonThumbnail(data: IEntityJob): Promise<JobStatus> {
|
async handleGeneratePersonThumbnail(data: IEntityJob): Promise<JobStatus> {
|
||||||
const { machineLearning, thumbnail } = await this.configCore.getConfig();
|
const { machineLearning, image } = await this.configCore.getConfig();
|
||||||
if (!machineLearning.enabled || !machineLearning.facialRecognition.enabled) {
|
if (!machineLearning.enabled || !machineLearning.facialRecognition.enabled) {
|
||||||
return JobStatus.SKIPPED;
|
return JobStatus.SKIPPED;
|
||||||
}
|
}
|
||||||
@ -496,7 +497,7 @@ export class PersonService {
|
|||||||
} = face;
|
} = face;
|
||||||
|
|
||||||
const [asset] = await this.assetRepository.getByIds([assetId]);
|
const [asset] = await this.assetRepository.getByIds([assetId]);
|
||||||
if (!asset?.resizePath) {
|
if (!asset?.previewPath) {
|
||||||
return JobStatus.FAILED;
|
return JobStatus.FAILED;
|
||||||
}
|
}
|
||||||
this.logger.verbose(`Cropping face for person: ${person.id}`);
|
this.logger.verbose(`Cropping face for person: ${person.id}`);
|
||||||
@ -527,12 +528,12 @@ export class PersonService {
|
|||||||
height: newHalfSize * 2,
|
height: newHalfSize * 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
const croppedOutput = await this.mediaRepository.crop(asset.resizePath, cropOptions);
|
const croppedOutput = await this.mediaRepository.crop(asset.previewPath, cropOptions);
|
||||||
const thumbnailOptions = {
|
const thumbnailOptions = {
|
||||||
format: 'jpeg',
|
format: ImageFormat.JPEG,
|
||||||
size: FACE_THUMBNAIL_SIZE,
|
size: FACE_THUMBNAIL_SIZE,
|
||||||
colorspace: thumbnail.colorspace,
|
colorspace: image.colorspace,
|
||||||
quality: thumbnail.quality,
|
quality: image.quality,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
await this.mediaRepository.resize(croppedOutput, thumbnailPath, thumbnailOptions);
|
await this.mediaRepository.resize(croppedOutput, thumbnailPath, thumbnailOptions);
|
||||||
|
@ -76,6 +76,9 @@ export class SearchService {
|
|||||||
checksum = Buffer.from(dto.checksum, encoding);
|
checksum = Buffer.from(dto.checksum, encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dto.previewPath ??= dto.resizePath;
|
||||||
|
dto.thumbnailPath ??= dto.webpPath;
|
||||||
|
|
||||||
const page = dto.page ?? 1;
|
const page = dto.page ?? 1;
|
||||||
const size = dto.size || 250;
|
const size = dto.size || 250;
|
||||||
const enumToOrder = { [AssetOrder.ASC]: 'ASC', [AssetOrder.DESC]: 'DESC' } as const;
|
const enumToOrder = { [AssetOrder.ASC]: 'ASC', [AssetOrder.DESC]: 'DESC' } as const;
|
||||||
|
@ -18,7 +18,7 @@ import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.r
|
|||||||
|
|
||||||
const asset = {
|
const asset = {
|
||||||
id: 'asset-1',
|
id: 'asset-1',
|
||||||
resizePath: 'path/to/resize.ext',
|
previewPath: 'path/to/resize.ext',
|
||||||
} as AssetEntity;
|
} as AssetEntity;
|
||||||
|
|
||||||
describe(SmartInfoService.name, () => {
|
describe(SmartInfoService.name, () => {
|
||||||
@ -94,7 +94,7 @@ describe(SmartInfoService.name, () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should skip assets without a resize path', async () => {
|
it('should skip assets without a resize path', async () => {
|
||||||
const asset = { resizePath: '' } as AssetEntity;
|
const asset = { previewPath: '' } as AssetEntity;
|
||||||
assetMock.getByIds.mockResolvedValue([asset]);
|
assetMock.getByIds.mockResolvedValue([asset]);
|
||||||
|
|
||||||
await sut.handleEncodeClip({ id: asset.id });
|
await sut.handleEncodeClip({ id: asset.id });
|
||||||
|
@ -83,13 +83,13 @@ export class SmartInfoService {
|
|||||||
return JobStatus.FAILED;
|
return JobStatus.FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!asset.resizePath) {
|
if (!asset.previewPath) {
|
||||||
return JobStatus.FAILED;
|
return JobStatus.FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
const clipEmbedding = await this.machineLearning.encodeImage(
|
const clipEmbedding = await this.machineLearning.encodeImage(
|
||||||
machineLearning.url,
|
machineLearning.url,
|
||||||
{ imagePath: asset.resizePath },
|
{ imagePath: asset.previewPath },
|
||||||
machineLearning.clip,
|
machineLearning.clip,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
AudioCodec,
|
AudioCodec,
|
||||||
CQMode,
|
CQMode,
|
||||||
Colorspace,
|
Colorspace,
|
||||||
|
ImageFormat,
|
||||||
LogLevel,
|
LogLevel,
|
||||||
SystemConfig,
|
SystemConfig,
|
||||||
SystemConfigEntity,
|
SystemConfigEntity,
|
||||||
@ -119,9 +120,11 @@ const updatedConfig = Object.freeze<SystemConfig>({
|
|||||||
hashVerificationEnabled: true,
|
hashVerificationEnabled: true,
|
||||||
template: '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
template: '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||||
},
|
},
|
||||||
thumbnail: {
|
image: {
|
||||||
webpSize: 250,
|
thumbnailFormat: ImageFormat.WEBP,
|
||||||
jpegSize: 1440,
|
thumbnailSize: 250,
|
||||||
|
previewFormat: ImageFormat.JPEG,
|
||||||
|
previewSize: 1440,
|
||||||
quality: 80,
|
quality: 80,
|
||||||
colorspace: Colorspace.P3,
|
colorspace: Colorspace.P3,
|
||||||
},
|
},
|
||||||
|
@ -58,7 +58,7 @@ export function searchAssetBuilder(
|
|||||||
builder.andWhere(`${builder.alias}.ownerId IN (:...userIds)`, { userIds: options.userIds });
|
builder.andWhere(`${builder.alias}.ownerId IN (:...userIds)`, { userIds: options.userIds });
|
||||||
}
|
}
|
||||||
|
|
||||||
const path = _.pick(options, ['encodedVideoPath', 'originalPath', 'resizePath', 'webpPath']);
|
const path = _.pick(options, ['encodedVideoPath', 'originalPath', 'previewPath', 'thumbnailPath']);
|
||||||
builder.andWhere(_.omitBy(path, _.isUndefined));
|
builder.andWhere(_.omitBy(path, _.isUndefined));
|
||||||
|
|
||||||
if (options.originalFileName) {
|
if (options.originalFileName) {
|
||||||
|
68
server/test/fixtures/asset.stub.ts
vendored
68
server/test/fixtures/asset.stub.ts
vendored
@ -26,10 +26,10 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: 'upload/library/IMG_123.jpg',
|
originalPath: 'upload/library/IMG_123.jpg',
|
||||||
resizePath: null,
|
previewPath: null,
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: '/uploads/user-id/webp/path.ext',
|
thumbnailPath: '/uploads/user-id/webp/path.ext',
|
||||||
thumbhash: Buffer.from('blablabla', 'base64'),
|
thumbhash: Buffer.from('blablabla', 'base64'),
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -62,10 +62,10 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: 'upload/library/IMG_456.jpg',
|
originalPath: 'upload/library/IMG_456.jpg',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.ext',
|
previewPath: '/uploads/user-id/thumbs/path.ext',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: null,
|
thumbnailPath: null,
|
||||||
thumbhash: Buffer.from('blablabla', 'base64'),
|
thumbhash: Buffer.from('blablabla', 'base64'),
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -102,10 +102,10 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/original/path.ext',
|
originalPath: '/original/path.ext',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.ext',
|
previewPath: '/uploads/user-id/thumbs/path.ext',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: '/uploads/user-id/webp/path.ext',
|
thumbnailPath: '/uploads/user-id/webp/path.ext',
|
||||||
thumbhash: null,
|
thumbhash: null,
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -139,10 +139,10 @@ export const assetStub = {
|
|||||||
ownerId: 'admin-id',
|
ownerId: 'admin-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/original/path.jpg',
|
originalPath: '/original/path.jpg',
|
||||||
resizePath: '/uploads/admin-id/thumbs/path.jpg',
|
previewPath: '/uploads/admin-id/thumbs/path.jpg',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: '/uploads/admin-id/webp/path.ext',
|
thumbnailPath: '/uploads/admin-id/webp/path.ext',
|
||||||
thumbhash: Buffer.from('blablabla', 'base64'),
|
thumbhash: Buffer.from('blablabla', 'base64'),
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -184,10 +184,10 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/original/path.jpg',
|
originalPath: '/original/path.jpg',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.jpg',
|
previewPath: '/uploads/user-id/thumbs/path.jpg',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: '/uploads/user-id/webp/path.ext',
|
thumbnailPath: '/uploads/user-id/webp/path.ext',
|
||||||
thumbhash: Buffer.from('blablabla', 'base64'),
|
thumbhash: Buffer.from('blablabla', 'base64'),
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -224,10 +224,10 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/data/user1/photo.jpg',
|
originalPath: '/data/user1/photo.jpg',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.jpg',
|
previewPath: '/uploads/user-id/thumbs/path.jpg',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: '/uploads/user-id/webp/path.ext',
|
thumbnailPath: '/uploads/user-id/webp/path.ext',
|
||||||
thumbhash: Buffer.from('blablabla', 'base64'),
|
thumbhash: Buffer.from('blablabla', 'base64'),
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -264,10 +264,10 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/original/path.jpg',
|
originalPath: '/original/path.jpg',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.jpg',
|
previewPath: '/uploads/user-id/thumbs/path.jpg',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: '/uploads/user-id/webp/path.ext',
|
thumbnailPath: '/uploads/user-id/webp/path.ext',
|
||||||
thumbhash: Buffer.from('blablabla', 'base64'),
|
thumbhash: Buffer.from('blablabla', 'base64'),
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -304,10 +304,10 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/original/path.ext',
|
originalPath: '/original/path.ext',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.ext',
|
previewPath: '/uploads/user-id/thumbs/path.ext',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: '/uploads/user-id/webp/path.ext',
|
thumbnailPath: '/uploads/user-id/webp/path.ext',
|
||||||
thumbhash: Buffer.from('blablabla', 'base64'),
|
thumbhash: Buffer.from('blablabla', 'base64'),
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -344,10 +344,10 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/original/path.ext',
|
originalPath: '/original/path.ext',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.ext',
|
previewPath: '/uploads/user-id/thumbs/path.ext',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: '/uploads/user-id/webp/path.ext',
|
thumbnailPath: '/uploads/user-id/webp/path.ext',
|
||||||
thumbhash: Buffer.from('blablabla', 'base64'),
|
thumbhash: Buffer.from('blablabla', 'base64'),
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2015-02-23T05:06:29.716Z'),
|
createdAt: new Date('2015-02-23T05:06:29.716Z'),
|
||||||
@ -385,10 +385,10 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/original/path.ext',
|
originalPath: '/original/path.ext',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.ext',
|
previewPath: '/uploads/user-id/thumbs/path.ext',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.VIDEO,
|
type: AssetType.VIDEO,
|
||||||
webpPath: null,
|
thumbnailPath: null,
|
||||||
thumbhash: null,
|
thumbhash: null,
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -456,10 +456,10 @@ export const assetStub = {
|
|||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
originalPath: '/original/path.ext',
|
originalPath: '/original/path.ext',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.ext',
|
previewPath: '/uploads/user-id/thumbs/path.ext',
|
||||||
sidecarPath: null,
|
sidecarPath: null,
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: null,
|
thumbnailPath: null,
|
||||||
thumbhash: null,
|
thumbhash: null,
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-22T05:06:29.716Z'),
|
createdAt: new Date('2023-02-22T05:06:29.716Z'),
|
||||||
@ -499,11 +499,11 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/original/path.ext',
|
originalPath: '/original/path.ext',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.ext',
|
previewPath: '/uploads/user-id/thumbs/path.ext',
|
||||||
thumbhash: null,
|
thumbhash: null,
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: null,
|
thumbnailPath: null,
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -535,11 +535,11 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/original/path.ext',
|
originalPath: '/original/path.ext',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.ext',
|
previewPath: '/uploads/user-id/thumbs/path.ext',
|
||||||
thumbhash: null,
|
thumbhash: null,
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: null,
|
thumbnailPath: null,
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -572,11 +572,11 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/original/path.ext',
|
originalPath: '/original/path.ext',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.ext',
|
previewPath: '/uploads/user-id/thumbs/path.ext',
|
||||||
thumbhash: null,
|
thumbhash: null,
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: null,
|
thumbnailPath: null,
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -610,10 +610,10 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/original/path.ext',
|
originalPath: '/original/path.ext',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.ext',
|
previewPath: '/uploads/user-id/thumbs/path.ext',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.VIDEO,
|
type: AssetType.VIDEO,
|
||||||
webpPath: null,
|
thumbnailPath: null,
|
||||||
thumbhash: null,
|
thumbhash: null,
|
||||||
encodedVideoPath: '/encoded/video/path.mp4',
|
encodedVideoPath: '/encoded/video/path.mp4',
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -648,10 +648,10 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/data/user1/photo.jpg',
|
originalPath: '/data/user1/photo.jpg',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.jpg',
|
previewPath: '/uploads/user-id/thumbs/path.jpg',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: '/uploads/user-id/webp/path.ext',
|
thumbnailPath: '/uploads/user-id/webp/path.ext',
|
||||||
thumbhash: Buffer.from('blablabla', 'base64'),
|
thumbhash: Buffer.from('blablabla', 'base64'),
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
@ -687,10 +687,10 @@ export const assetStub = {
|
|||||||
ownerId: 'user-id',
|
ownerId: 'user-id',
|
||||||
deviceId: 'device-id',
|
deviceId: 'device-id',
|
||||||
originalPath: '/data/user1/photo.jpg',
|
originalPath: '/data/user1/photo.jpg',
|
||||||
resizePath: '/uploads/user-id/thumbs/path.jpg',
|
previewPath: '/uploads/user-id/thumbs/path.jpg',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
type: AssetType.IMAGE,
|
type: AssetType.IMAGE,
|
||||||
webpPath: '/uploads/user-id/webp/path.ext',
|
thumbnailPath: '/uploads/user-id/webp/path.ext',
|
||||||
thumbhash: Buffer.from('blablabla', 'base64'),
|
thumbhash: Buffer.from('blablabla', 'base64'),
|
||||||
encodedVideoPath: null,
|
encodedVideoPath: null,
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
|
4
server/test/fixtures/shared-link.stub.ts
vendored
4
server/test/fixtures/shared-link.stub.ts
vendored
@ -199,7 +199,7 @@ export const sharedLinkStub = {
|
|||||||
deviceId: 'device_id_1',
|
deviceId: 'device_id_1',
|
||||||
type: AssetType.VIDEO,
|
type: AssetType.VIDEO,
|
||||||
originalPath: 'fake_path/jpeg',
|
originalPath: 'fake_path/jpeg',
|
||||||
resizePath: '',
|
previewPath: '',
|
||||||
checksum: Buffer.from('file hash', 'utf8'),
|
checksum: Buffer.from('file hash', 'utf8'),
|
||||||
fileModifiedAt: today,
|
fileModifiedAt: today,
|
||||||
fileCreatedAt: today,
|
fileCreatedAt: today,
|
||||||
@ -219,7 +219,7 @@ export const sharedLinkStub = {
|
|||||||
objects: ['a', 'b', 'c'],
|
objects: ['a', 'b', 'c'],
|
||||||
asset: null as any,
|
asset: null as any,
|
||||||
},
|
},
|
||||||
webpPath: '',
|
thumbnailPath: '',
|
||||||
thumbhash: null,
|
thumbhash: null,
|
||||||
encodedVideoPath: '',
|
encodedVideoPath: '',
|
||||||
duration: null,
|
duration: null,
|
||||||
|
@ -25,10 +25,10 @@
|
|||||||
<form autocomplete="off" on:submit|preventDefault>
|
<form autocomplete="off" on:submit|preventDefault>
|
||||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||||
<SettingSelect
|
<SettingSelect
|
||||||
label="SMALL THUMBNAIL RESOLUTION"
|
label="THUMBNAIL RESOLUTION"
|
||||||
desc="Used when viewing groups of photos (main timeline, album view, etc.). Higher resolutions can preserve more detail but take longer to encode, have larger file sizes, and can reduce app responsiveness."
|
desc="Used when viewing groups of photos (main timeline, album view, etc.). Higher resolutions can preserve more detail but take longer to encode, have larger file sizes, and can reduce app responsiveness."
|
||||||
number
|
number
|
||||||
bind:value={config.thumbnail.webpSize}
|
bind:value={config.image.thumbnailSize}
|
||||||
options={[
|
options={[
|
||||||
{ value: 1080, text: '1080p' },
|
{ value: 1080, text: '1080p' },
|
||||||
{ value: 720, text: '720p' },
|
{ value: 720, text: '720p' },
|
||||||
@ -37,15 +37,15 @@
|
|||||||
{ value: 200, text: '200p' },
|
{ value: 200, text: '200p' },
|
||||||
]}
|
]}
|
||||||
name="resolution"
|
name="resolution"
|
||||||
isEdited={config.thumbnail.webpSize !== savedConfig.thumbnail.webpSize}
|
isEdited={config.image.thumbnailSize !== savedConfig.image.thumbnailSize}
|
||||||
{disabled}
|
{disabled}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SettingSelect
|
<SettingSelect
|
||||||
label="LARGE THUMBNAIL RESOLUTION"
|
label="PREVIEW RESOLUTION"
|
||||||
desc="Used when viewing a single photo and for machine learning. Higher resolutions can preserve more detail but take longer to encode, have larger file sizes, and can reduce app responsiveness."
|
desc="Used when viewing a single photo and for machine learning. Higher resolutions can preserve more detail but take longer to encode, have larger file sizes, and can reduce app responsiveness."
|
||||||
number
|
number
|
||||||
bind:value={config.thumbnail.jpegSize}
|
bind:value={config.image.previewSize}
|
||||||
options={[
|
options={[
|
||||||
{ value: 2160, text: '4K' },
|
{ value: 2160, text: '4K' },
|
||||||
{ value: 1440, text: '1440p' },
|
{ value: 1440, text: '1440p' },
|
||||||
@ -53,31 +53,31 @@
|
|||||||
{ value: 720, text: '720p' },
|
{ value: 720, text: '720p' },
|
||||||
]}
|
]}
|
||||||
name="resolution"
|
name="resolution"
|
||||||
isEdited={config.thumbnail.jpegSize !== savedConfig.thumbnail.jpegSize}
|
isEdited={config.image.previewSize !== savedConfig.image.previewSize}
|
||||||
{disabled}
|
{disabled}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SettingInputField
|
<SettingInputField
|
||||||
inputType={SettingInputFieldType.NUMBER}
|
inputType={SettingInputFieldType.NUMBER}
|
||||||
label="QUALITY"
|
label="QUALITY"
|
||||||
desc="Thumbnail quality from 1-100. Higher is better for quality but produces larger files."
|
desc="Image quality from 1-100. Higher is better for quality but produces larger files."
|
||||||
bind:value={config.thumbnail.quality}
|
bind:value={config.image.quality}
|
||||||
isEdited={config.thumbnail.quality !== savedConfig.thumbnail.quality}
|
isEdited={config.image.quality !== savedConfig.image.quality}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SettingSwitch
|
<SettingSwitch
|
||||||
title="PREFER WIDE GAMUT"
|
title="PREFER WIDE GAMUT"
|
||||||
subtitle="Use Display P3 for thumbnails. This better preserves the vibrance of images with wide colorspaces, but images may appear differently on old devices with an old browser version. sRGB images are kept as sRGB to avoid color shifts."
|
subtitle="Use Display P3 for thumbnails. This better preserves the vibrance of images with wide colorspaces, but images may appear differently on old devices with an old browser version. sRGB images are kept as sRGB to avoid color shifts."
|
||||||
checked={config.thumbnail.colorspace === Colorspace.P3}
|
checked={config.image.colorspace === Colorspace.P3}
|
||||||
on:toggle={(e) => (config.thumbnail.colorspace = e.detail ? Colorspace.P3 : Colorspace.Srgb)}
|
on:toggle={(e) => (config.image.colorspace = e.detail ? Colorspace.P3 : Colorspace.Srgb)}
|
||||||
isEdited={config.thumbnail.colorspace !== savedConfig.thumbnail.colorspace}
|
isEdited={config.image.colorspace !== savedConfig.image.colorspace}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ml-4">
|
<div class="ml-4">
|
||||||
<SettingButtonsRow
|
<SettingButtonsRow
|
||||||
on:reset={({ detail }) => dispatch('reset', { ...detail, configKeys: ['thumbnail'] })}
|
on:reset={({ detail }) => dispatch('reset', { ...detail, configKeys: ['image'] })}
|
||||||
on:save={() => dispatch('save', { thumbnail: config.thumbnail })}
|
on:save={() => dispatch('save', { image: config.image })}
|
||||||
showResetToDefault={!isEqual(savedConfig, defaultConfig)}
|
showResetToDefault={!isEqual(savedConfig, defaultConfig)}
|
||||||
{disabled}
|
{disabled}
|
||||||
/>
|
/>
|
@ -13,7 +13,7 @@
|
|||||||
import SettingAccordion from '$lib/components/shared-components/settings/setting-accordion.svelte';
|
import SettingAccordion from '$lib/components/shared-components/settings/setting-accordion.svelte';
|
||||||
import StorageTemplateSettings from '$lib/components/admin-page/settings/storage-template/storage-template-settings.svelte';
|
import StorageTemplateSettings from '$lib/components/admin-page/settings/storage-template/storage-template-settings.svelte';
|
||||||
import ThemeSettings from '$lib/components/admin-page/settings/theme/theme-settings.svelte';
|
import ThemeSettings from '$lib/components/admin-page/settings/theme/theme-settings.svelte';
|
||||||
import ThumbnailSettings from '$lib/components/admin-page/settings/thumbnail/thumbnail-settings.svelte';
|
import ImageSettings from '$lib/components/admin-page/settings/image/image-settings.svelte';
|
||||||
import TrashSettings from '$lib/components/admin-page/settings/trash-settings/trash-settings.svelte';
|
import TrashSettings from '$lib/components/admin-page/settings/trash-settings/trash-settings.svelte';
|
||||||
import UserSettings from '$lib/components/admin-page/settings/user-settings/user-settings.svelte';
|
import UserSettings from '$lib/components/admin-page/settings/user-settings/user-settings.svelte';
|
||||||
import LinkButton from '$lib/components/elements/buttons/link-button.svelte';
|
import LinkButton from '$lib/components/elements/buttons/link-button.svelte';
|
||||||
@ -43,7 +43,7 @@
|
|||||||
| typeof ServerSettings
|
| typeof ServerSettings
|
||||||
| typeof StorageTemplateSettings
|
| typeof StorageTemplateSettings
|
||||||
| typeof ThemeSettings
|
| typeof ThemeSettings
|
||||||
| typeof ThumbnailSettings
|
| typeof ImageSettings
|
||||||
| typeof TrashSettings
|
| typeof TrashSettings
|
||||||
| typeof NewVersionCheckSettings
|
| typeof NewVersionCheckSettings
|
||||||
| typeof FFmpegSettings
|
| typeof FFmpegSettings
|
||||||
@ -64,6 +64,12 @@
|
|||||||
subtitle: string;
|
subtitle: string;
|
||||||
key: string;
|
key: string;
|
||||||
}> = [
|
}> = [
|
||||||
|
{
|
||||||
|
item: ImageSettings,
|
||||||
|
title: 'Image Settings',
|
||||||
|
subtitle: 'Manage the quality and resolution of generated images',
|
||||||
|
key: 'image',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
item: JobSettings,
|
item: JobSettings,
|
||||||
title: 'Job Settings',
|
title: 'Job Settings',
|
||||||
@ -124,12 +130,6 @@
|
|||||||
subtitle: 'Manage customization of the Immich web interface',
|
subtitle: 'Manage customization of the Immich web interface',
|
||||||
key: 'theme',
|
key: 'theme',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
item: ThumbnailSettings,
|
|
||||||
title: 'Thumbnail Settings',
|
|
||||||
subtitle: 'Manage the resolution of thumbnail sizes',
|
|
||||||
key: 'thumbnail',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
item: TrashSettings,
|
item: TrashSettings,
|
||||||
title: 'Trash Settings',
|
title: 'Trash Settings',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user