update api

This commit is contained in:
mertalev 2025-06-16 13:23:00 -04:00
parent 1c53e65641
commit dd7c06f937
No known key found for this signature in database
GPG key ID: DF6ABC77AAD98C95
22 changed files with 177 additions and 863 deletions

View file

@ -194,7 +194,6 @@ Class | Method | HTTP request | Description
*SearchApi* | [**searchAssetStatistics**](doc//SearchApi.md#searchassetstatistics) | **POST** /search/statistics | *SearchApi* | [**searchAssetStatistics**](doc//SearchApi.md#searchassetstatistics) | **POST** /search/statistics |
*SearchApi* | [**searchAssets**](doc//SearchApi.md#searchassets) | **POST** /search/metadata | *SearchApi* | [**searchAssets**](doc//SearchApi.md#searchassets) | **POST** /search/metadata |
*SearchApi* | [**searchLargeAssets**](doc//SearchApi.md#searchlargeassets) | **POST** /search/large-assets | *SearchApi* | [**searchLargeAssets**](doc//SearchApi.md#searchlargeassets) | **POST** /search/large-assets |
*SearchApi* | [**searchOcr**](doc//SearchApi.md#searchocr) | **POST** /search/ocr |
*SearchApi* | [**searchPerson**](doc//SearchApi.md#searchperson) | **GET** /search/person | *SearchApi* | [**searchPerson**](doc//SearchApi.md#searchperson) | **GET** /search/person |
*SearchApi* | [**searchPlaces**](doc//SearchApi.md#searchplaces) | **GET** /search/places | *SearchApi* | [**searchPlaces**](doc//SearchApi.md#searchplaces) | **GET** /search/places |
*SearchApi* | [**searchRandom**](doc//SearchApi.md#searchrandom) | **POST** /search/random | *SearchApi* | [**searchRandom**](doc//SearchApi.md#searchrandom) | **POST** /search/random |
@ -417,7 +416,6 @@ Class | Method | HTTP request | Description
- [OAuthConfigDto](doc//OAuthConfigDto.md) - [OAuthConfigDto](doc//OAuthConfigDto.md)
- [OAuthTokenEndpointAuthMethod](doc//OAuthTokenEndpointAuthMethod.md) - [OAuthTokenEndpointAuthMethod](doc//OAuthTokenEndpointAuthMethod.md)
- [OcrConfig](doc//OcrConfig.md) - [OcrConfig](doc//OcrConfig.md)
- [OcrSearchDto](doc//OcrSearchDto.md)
- [OnThisDayDto](doc//OnThisDayDto.md) - [OnThisDayDto](doc//OnThisDayDto.md)
- [OnboardingDto](doc//OnboardingDto.md) - [OnboardingDto](doc//OnboardingDto.md)
- [OnboardingResponseDto](doc//OnboardingResponseDto.md) - [OnboardingResponseDto](doc//OnboardingResponseDto.md)

View file

@ -188,7 +188,6 @@ part 'model/o_auth_callback_dto.dart';
part 'model/o_auth_config_dto.dart'; part 'model/o_auth_config_dto.dart';
part 'model/o_auth_token_endpoint_auth_method.dart'; part 'model/o_auth_token_endpoint_auth_method.dart';
part 'model/ocr_config.dart'; part 'model/ocr_config.dart';
part 'model/ocr_search_dto.dart';
part 'model/on_this_day_dto.dart'; part 'model/on_this_day_dto.dart';
part 'model/onboarding_dto.dart'; part 'model/onboarding_dto.dart';
part 'model/onboarding_response_dto.dart'; part 'model/onboarding_response_dto.dart';

View file

@ -346,6 +346,8 @@ class SearchApi {
/// ///
/// * [String] model: /// * [String] model:
/// ///
/// * [String] ocr:
///
/// * [List<String>] personIds: /// * [List<String>] personIds:
/// ///
/// * [num] rating: /// * [num] rating:
@ -375,7 +377,7 @@ class SearchApi {
/// * [bool] withDeleted: /// * [bool] withDeleted:
/// ///
/// * [bool] withExif: /// * [bool] withExif:
Future<Response> searchLargeAssetsWithHttpInfo({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async { Future<Response> searchLargeAssetsWithHttpInfo({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, String? ocr, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/search/large-assets'; final apiPath = r'/search/large-assets';
@ -434,6 +436,9 @@ class SearchApi {
if (model != null) { if (model != null) {
queryParams.addAll(_queryParams('', 'model', model)); queryParams.addAll(_queryParams('', 'model', model));
} }
if (ocr != null) {
queryParams.addAll(_queryParams('', 'ocr', ocr));
}
if (personIds != null) { if (personIds != null) {
queryParams.addAll(_queryParams('multi', 'personIds', personIds)); queryParams.addAll(_queryParams('multi', 'personIds', personIds));
} }
@ -530,6 +535,8 @@ class SearchApi {
/// ///
/// * [String] model: /// * [String] model:
/// ///
/// * [String] ocr:
///
/// * [List<String>] personIds: /// * [List<String>] personIds:
/// ///
/// * [num] rating: /// * [num] rating:
@ -559,8 +566,8 @@ class SearchApi {
/// * [bool] withDeleted: /// * [bool] withDeleted:
/// ///
/// * [bool] withExif: /// * [bool] withExif:
Future<List<AssetResponseDto>?> searchLargeAssets({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async { Future<List<AssetResponseDto>?> searchLargeAssets({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, String? ocr, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async {
final response = await searchLargeAssetsWithHttpInfo( albumIds: albumIds, city: city, country: country, createdAfter: createdAfter, createdBefore: createdBefore, deviceId: deviceId, isEncoded: isEncoded, isFavorite: isFavorite, isMotion: isMotion, isNotInAlbum: isNotInAlbum, isOffline: isOffline, lensModel: lensModel, libraryId: libraryId, make: make, minFileSize: minFileSize, model: model, personIds: personIds, rating: rating, size: size, state: state, tagIds: tagIds, takenAfter: takenAfter, takenBefore: takenBefore, trashedAfter: trashedAfter, trashedBefore: trashedBefore, type: type, updatedAfter: updatedAfter, updatedBefore: updatedBefore, visibility: visibility, withDeleted: withDeleted, withExif: withExif, ); final response = await searchLargeAssetsWithHttpInfo( albumIds: albumIds, city: city, country: country, createdAfter: createdAfter, createdBefore: createdBefore, deviceId: deviceId, isEncoded: isEncoded, isFavorite: isFavorite, isMotion: isMotion, isNotInAlbum: isNotInAlbum, isOffline: isOffline, lensModel: lensModel, libraryId: libraryId, make: make, minFileSize: minFileSize, model: model, ocr: ocr, personIds: personIds, rating: rating, size: size, state: state, tagIds: tagIds, takenAfter: takenAfter, takenBefore: takenBefore, trashedAfter: trashedAfter, trashedBefore: trashedBefore, type: type, updatedAfter: updatedAfter, updatedBefore: updatedBefore, visibility: visibility, withDeleted: withDeleted, withExif: withExif, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response)); throw ApiException(response.statusCode, await _decodeBodyBytes(response));
} }
@ -577,53 +584,6 @@ class SearchApi {
return null; return null;
} }
/// Performs an HTTP 'POST /search/ocr' operation and returns the [Response].
/// Parameters:
///
/// * [OcrSearchDto] ocrSearchDto (required):
Future<Response> searchOcrWithHttpInfo(OcrSearchDto ocrSearchDto,) async {
// ignore: prefer_const_declarations
final apiPath = r'/search/ocr';
// ignore: prefer_final_locals
Object? postBody = ocrSearchDto;
final queryParams = <QueryParam>[];
final headerParams = <String, String>{};
final formParams = <String, String>{};
const contentTypes = <String>['application/json'];
return apiClient.invokeAPI(
apiPath,
'POST',
queryParams,
postBody,
headerParams,
formParams,
contentTypes.isEmpty ? null : contentTypes.first,
);
}
/// Parameters:
///
/// * [OcrSearchDto] ocrSearchDto (required):
Future<SearchResponseDto?> searchOcr(OcrSearchDto ocrSearchDto,) async {
final response = await searchOcrWithHttpInfo(ocrSearchDto,);
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}
// When a remote server returns no body with a status of 204, we shall not decode it.
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'SearchResponseDto',) as SearchResponseDto;
}
return null;
}
/// This endpoint requires the `person.read` permission. /// This endpoint requires the `person.read` permission.
/// ///
/// Note: This method returns the HTTP [Response]. /// Note: This method returns the HTTP [Response].

View file

@ -430,8 +430,6 @@ class ApiClient {
return OAuthTokenEndpointAuthMethodTypeTransformer().decode(value); return OAuthTokenEndpointAuthMethodTypeTransformer().decode(value);
case 'OcrConfig': case 'OcrConfig':
return OcrConfig.fromJson(value); return OcrConfig.fromJson(value);
case 'OcrSearchDto':
return OcrSearchDto.fromJson(value);
case 'OnThisDayDto': case 'OnThisDayDto':
return OnThisDayDto.fromJson(value); return OnThisDayDto.fromJson(value);
case 'OnboardingDto': case 'OnboardingDto':

View file

@ -33,6 +33,7 @@ class MetadataSearchDto {
this.libraryId, this.libraryId,
this.make, this.make,
this.model, this.model,
this.ocr,
this.order = AssetOrder.desc, this.order = AssetOrder.desc,
this.originalFileName, this.originalFileName,
this.originalPath, this.originalPath,
@ -182,6 +183,14 @@ class MetadataSearchDto {
String? model; String? model;
///
/// 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? ocr;
AssetOrder order; AssetOrder order;
/// ///
@ -369,6 +378,7 @@ class MetadataSearchDto {
other.libraryId == libraryId && other.libraryId == libraryId &&
other.make == make && other.make == make &&
other.model == model && other.model == model &&
other.ocr == ocr &&
other.order == order && other.order == order &&
other.originalFileName == originalFileName && other.originalFileName == originalFileName &&
other.originalPath == originalPath && other.originalPath == originalPath &&
@ -416,6 +426,7 @@ class MetadataSearchDto {
(libraryId == null ? 0 : libraryId!.hashCode) + (libraryId == null ? 0 : libraryId!.hashCode) +
(make == null ? 0 : make!.hashCode) + (make == null ? 0 : make!.hashCode) +
(model == null ? 0 : model!.hashCode) + (model == null ? 0 : model!.hashCode) +
(ocr == null ? 0 : ocr!.hashCode) +
(order.hashCode) + (order.hashCode) +
(originalFileName == null ? 0 : originalFileName!.hashCode) + (originalFileName == null ? 0 : originalFileName!.hashCode) +
(originalPath == null ? 0 : originalPath!.hashCode) + (originalPath == null ? 0 : originalPath!.hashCode) +
@ -441,7 +452,7 @@ class MetadataSearchDto {
(withStacked == null ? 0 : withStacked!.hashCode); (withStacked == null ? 0 : withStacked!.hashCode);
@override @override
String toString() => 'MetadataSearchDto[albumIds=$albumIds, checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, description=$description, deviceAssetId=$deviceAssetId, deviceId=$deviceId, encodedVideoPath=$encodedVideoPath, id=$id, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, previewPath=$previewPath, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, thumbnailPath=$thumbnailPath, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]'; String toString() => 'MetadataSearchDto[albumIds=$albumIds, checksum=$checksum, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, description=$description, deviceAssetId=$deviceAssetId, deviceId=$deviceId, encodedVideoPath=$encodedVideoPath, id=$id, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, order=$order, originalFileName=$originalFileName, originalPath=$originalPath, page=$page, personIds=$personIds, previewPath=$previewPath, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, thumbnailPath=$thumbnailPath, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@ -540,6 +551,11 @@ class MetadataSearchDto {
json[r'model'] = this.model; json[r'model'] = this.model;
} else { } else {
// json[r'model'] = null; // json[r'model'] = null;
}
if (this.ocr != null) {
json[r'ocr'] = this.ocr;
} else {
// json[r'ocr'] = null;
} }
json[r'order'] = this.order; json[r'order'] = this.order;
if (this.originalFileName != null) { if (this.originalFileName != null) {
@ -682,6 +698,7 @@ class MetadataSearchDto {
libraryId: mapValueOfType<String>(json, r'libraryId'), libraryId: mapValueOfType<String>(json, r'libraryId'),
make: mapValueOfType<String>(json, r'make'), make: mapValueOfType<String>(json, r'make'),
model: mapValueOfType<String>(json, r'model'), model: mapValueOfType<String>(json, r'model'),
ocr: mapValueOfType<String>(json, r'ocr'),
order: AssetOrder.fromJson(json[r'order']) ?? AssetOrder.desc, order: AssetOrder.fromJson(json[r'order']) ?? AssetOrder.desc,
originalFileName: mapValueOfType<String>(json, r'originalFileName'), originalFileName: mapValueOfType<String>(json, r'originalFileName'),
originalPath: mapValueOfType<String>(json, r'originalPath'), originalPath: mapValueOfType<String>(json, r'originalPath'),

View file

@ -14,38 +14,53 @@ class OcrConfig {
/// Returns a new [OcrConfig] instance. /// Returns a new [OcrConfig] instance.
OcrConfig({ OcrConfig({
required this.enabled, required this.enabled,
required this.minScore, required this.maxResolution,
required this.minDetectionScore,
required this.minRecognitionScore,
required this.modelName, required this.modelName,
}); });
bool enabled; bool enabled;
/// Minimum value: 1
int maxResolution;
/// Minimum value: 0.1 /// Minimum value: 0.1
/// Maximum value: 1 /// Maximum value: 1
double minScore; double minDetectionScore;
/// Minimum value: 0.1
/// Maximum value: 1
double minRecognitionScore;
String modelName; String modelName;
@override @override
bool operator ==(Object other) => identical(this, other) || other is OcrConfig && bool operator ==(Object other) => identical(this, other) || other is OcrConfig &&
other.enabled == enabled && other.enabled == enabled &&
other.minScore == minScore && other.maxResolution == maxResolution &&
other.minDetectionScore == minDetectionScore &&
other.minRecognitionScore == minRecognitionScore &&
other.modelName == modelName; other.modelName == modelName;
@override @override
int get hashCode => int get hashCode =>
// ignore: unnecessary_parenthesis // ignore: unnecessary_parenthesis
(enabled.hashCode) + (enabled.hashCode) +
(minScore.hashCode) + (maxResolution.hashCode) +
(minDetectionScore.hashCode) +
(minRecognitionScore.hashCode) +
(modelName.hashCode); (modelName.hashCode);
@override @override
String toString() => 'OcrConfig[enabled=$enabled, minScore=$minScore, modelName=$modelName]'; String toString() => 'OcrConfig[enabled=$enabled, maxResolution=$maxResolution, minDetectionScore=$minDetectionScore, minRecognitionScore=$minRecognitionScore, modelName=$modelName]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
json[r'enabled'] = this.enabled; json[r'enabled'] = this.enabled;
json[r'minScore'] = this.minScore; json[r'maxResolution'] = this.maxResolution;
json[r'minDetectionScore'] = this.minDetectionScore;
json[r'minRecognitionScore'] = this.minRecognitionScore;
json[r'modelName'] = this.modelName; json[r'modelName'] = this.modelName;
return json; return json;
} }
@ -60,7 +75,9 @@ class OcrConfig {
return OcrConfig( return OcrConfig(
enabled: mapValueOfType<bool>(json, r'enabled')!, enabled: mapValueOfType<bool>(json, r'enabled')!,
minScore: (mapValueOfType<num>(json, r'minScore')!).toDouble(), maxResolution: mapValueOfType<int>(json, r'maxResolution')!,
minDetectionScore: (mapValueOfType<num>(json, r'minDetectionScore')!).toDouble(),
minRecognitionScore: (mapValueOfType<num>(json, r'minRecognitionScore')!).toDouble(),
modelName: mapValueOfType<String>(json, r'modelName')!, modelName: mapValueOfType<String>(json, r'modelName')!,
); );
} }
@ -110,7 +127,9 @@ class OcrConfig {
/// 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>{
'enabled', 'enabled',
'minScore', 'maxResolution',
'minDetectionScore',
'minRecognitionScore',
'modelName', 'modelName',
}; };
} }

View file

@ -1,522 +0,0 @@
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.18
// 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 OcrSearchDto {
/// Returns a new [OcrSearchDto] instance.
OcrSearchDto({
this.albumIds = const [],
this.city,
this.country,
this.createdAfter,
this.createdBefore,
this.deviceId,
this.isEncoded,
this.isFavorite,
this.isMotion,
this.isNotInAlbum,
this.isOffline,
this.lensModel,
this.libraryId,
this.make,
this.model,
required this.ocr,
this.page,
this.personIds = const [],
this.rating,
this.state,
this.tagIds = const [],
this.takenAfter,
this.takenBefore,
this.trashedAfter,
this.trashedBefore,
this.type,
this.updatedAfter,
this.updatedBefore,
this.visibility,
});
List<String> albumIds;
String? city;
String? country;
///
/// 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.
///
DateTime? createdAfter;
///
/// 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.
///
DateTime? createdBefore;
///
/// 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? deviceId;
///
/// 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.
///
bool? isEncoded;
///
/// 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.
///
bool? isFavorite;
///
/// 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.
///
bool? isMotion;
///
/// 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.
///
bool? isNotInAlbum;
///
/// 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.
///
bool? isOffline;
String? lensModel;
String? libraryId;
///
/// 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? make;
String? model;
String ocr;
/// Minimum value: 1
///
/// 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.
///
num? page;
List<String> personIds;
/// Minimum value: -1
/// Maximum value: 5
///
/// 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.
///
num? rating;
String? state;
List<String>? tagIds;
///
/// 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.
///
DateTime? takenAfter;
///
/// 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.
///
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.
///
DateTime? trashedAfter;
///
/// 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.
///
DateTime? trashedBefore;
///
/// 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.
///
AssetTypeEnum? type;
///
/// 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.
///
DateTime? updatedAfter;
///
/// 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.
///
DateTime? updatedBefore;
///
/// 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.
///
AssetVisibility? visibility;
@override
bool operator ==(Object other) => identical(this, other) || other is OcrSearchDto &&
_deepEquality.equals(other.albumIds, albumIds) &&
other.city == city &&
other.country == country &&
other.createdAfter == createdAfter &&
other.createdBefore == createdBefore &&
other.deviceId == deviceId &&
other.isEncoded == isEncoded &&
other.isFavorite == isFavorite &&
other.isMotion == isMotion &&
other.isNotInAlbum == isNotInAlbum &&
other.isOffline == isOffline &&
other.lensModel == lensModel &&
other.libraryId == libraryId &&
other.make == make &&
other.model == model &&
other.ocr == ocr &&
other.page == page &&
_deepEquality.equals(other.personIds, personIds) &&
other.rating == rating &&
other.state == state &&
_deepEquality.equals(other.tagIds, tagIds) &&
other.takenAfter == takenAfter &&
other.takenBefore == takenBefore &&
other.trashedAfter == trashedAfter &&
other.trashedBefore == trashedBefore &&
other.type == type &&
other.updatedAfter == updatedAfter &&
other.updatedBefore == updatedBefore &&
other.visibility == visibility;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(albumIds.hashCode) +
(city == null ? 0 : city!.hashCode) +
(country == null ? 0 : country!.hashCode) +
(createdAfter == null ? 0 : createdAfter!.hashCode) +
(createdBefore == null ? 0 : createdBefore!.hashCode) +
(deviceId == null ? 0 : deviceId!.hashCode) +
(isEncoded == null ? 0 : isEncoded!.hashCode) +
(isFavorite == null ? 0 : isFavorite!.hashCode) +
(isMotion == null ? 0 : isMotion!.hashCode) +
(isNotInAlbum == null ? 0 : isNotInAlbum!.hashCode) +
(isOffline == null ? 0 : isOffline!.hashCode) +
(lensModel == null ? 0 : lensModel!.hashCode) +
(libraryId == null ? 0 : libraryId!.hashCode) +
(make == null ? 0 : make!.hashCode) +
(model == null ? 0 : model!.hashCode) +
(ocr.hashCode) +
(page == null ? 0 : page!.hashCode) +
(personIds.hashCode) +
(rating == null ? 0 : rating!.hashCode) +
(state == null ? 0 : state!.hashCode) +
(tagIds == null ? 0 : tagIds!.hashCode) +
(takenAfter == null ? 0 : takenAfter!.hashCode) +
(takenBefore == null ? 0 : takenBefore!.hashCode) +
(trashedAfter == null ? 0 : trashedAfter!.hashCode) +
(trashedBefore == null ? 0 : trashedBefore!.hashCode) +
(type == null ? 0 : type!.hashCode) +
(updatedAfter == null ? 0 : updatedAfter!.hashCode) +
(updatedBefore == null ? 0 : updatedBefore!.hashCode) +
(visibility == null ? 0 : visibility!.hashCode);
@override
String toString() => 'OcrSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, page=$page, personIds=$personIds, rating=$rating, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'albumIds'] = this.albumIds;
if (this.city != null) {
json[r'city'] = this.city;
} else {
// json[r'city'] = null;
}
if (this.country != null) {
json[r'country'] = this.country;
} else {
// json[r'country'] = null;
}
if (this.createdAfter != null) {
json[r'createdAfter'] = this.createdAfter!.toUtc().toIso8601String();
} else {
// json[r'createdAfter'] = null;
}
if (this.createdBefore != null) {
json[r'createdBefore'] = this.createdBefore!.toUtc().toIso8601String();
} else {
// json[r'createdBefore'] = null;
}
if (this.deviceId != null) {
json[r'deviceId'] = this.deviceId;
} else {
// json[r'deviceId'] = null;
}
if (this.isEncoded != null) {
json[r'isEncoded'] = this.isEncoded;
} else {
// json[r'isEncoded'] = null;
}
if (this.isFavorite != null) {
json[r'isFavorite'] = this.isFavorite;
} else {
// json[r'isFavorite'] = null;
}
if (this.isMotion != null) {
json[r'isMotion'] = this.isMotion;
} else {
// json[r'isMotion'] = null;
}
if (this.isNotInAlbum != null) {
json[r'isNotInAlbum'] = this.isNotInAlbum;
} else {
// json[r'isNotInAlbum'] = null;
}
if (this.isOffline != null) {
json[r'isOffline'] = this.isOffline;
} else {
// json[r'isOffline'] = null;
}
if (this.lensModel != null) {
json[r'lensModel'] = this.lensModel;
} else {
// json[r'lensModel'] = null;
}
if (this.libraryId != null) {
json[r'libraryId'] = this.libraryId;
} else {
// json[r'libraryId'] = null;
}
if (this.make != null) {
json[r'make'] = this.make;
} else {
// json[r'make'] = null;
}
if (this.model != null) {
json[r'model'] = this.model;
} else {
// json[r'model'] = null;
}
json[r'ocr'] = this.ocr;
if (this.page != null) {
json[r'page'] = this.page;
} else {
// json[r'page'] = null;
}
json[r'personIds'] = this.personIds;
if (this.rating != null) {
json[r'rating'] = this.rating;
} else {
// json[r'rating'] = null;
}
if (this.state != null) {
json[r'state'] = this.state;
} else {
// json[r'state'] = null;
}
if (this.tagIds != null) {
json[r'tagIds'] = this.tagIds;
} else {
// json[r'tagIds'] = null;
}
if (this.takenAfter != null) {
json[r'takenAfter'] = this.takenAfter!.toUtc().toIso8601String();
} else {
// json[r'takenAfter'] = null;
}
if (this.takenBefore != null) {
json[r'takenBefore'] = this.takenBefore!.toUtc().toIso8601String();
} else {
// json[r'takenBefore'] = null;
}
if (this.trashedAfter != null) {
json[r'trashedAfter'] = this.trashedAfter!.toUtc().toIso8601String();
} else {
// json[r'trashedAfter'] = null;
}
if (this.trashedBefore != null) {
json[r'trashedBefore'] = this.trashedBefore!.toUtc().toIso8601String();
} else {
// json[r'trashedBefore'] = null;
}
if (this.type != null) {
json[r'type'] = this.type;
} else {
// json[r'type'] = null;
}
if (this.updatedAfter != null) {
json[r'updatedAfter'] = this.updatedAfter!.toUtc().toIso8601String();
} else {
// json[r'updatedAfter'] = null;
}
if (this.updatedBefore != null) {
json[r'updatedBefore'] = this.updatedBefore!.toUtc().toIso8601String();
} else {
// json[r'updatedBefore'] = null;
}
if (this.visibility != null) {
json[r'visibility'] = this.visibility;
} else {
// json[r'visibility'] = null;
}
return json;
}
/// Returns a new [OcrSearchDto] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static OcrSearchDto? fromJson(dynamic value) {
upgradeDto(value, "OcrSearchDto");
if (value is Map) {
final json = value.cast<String, dynamic>();
return OcrSearchDto(
albumIds: json[r'albumIds'] is Iterable
? (json[r'albumIds'] as Iterable).cast<String>().toList(growable: false)
: const [],
city: mapValueOfType<String>(json, r'city'),
country: mapValueOfType<String>(json, r'country'),
createdAfter: mapDateTime(json, r'createdAfter', r''),
createdBefore: mapDateTime(json, r'createdBefore', r''),
deviceId: mapValueOfType<String>(json, r'deviceId'),
isEncoded: mapValueOfType<bool>(json, r'isEncoded'),
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
isMotion: mapValueOfType<bool>(json, r'isMotion'),
isNotInAlbum: mapValueOfType<bool>(json, r'isNotInAlbum'),
isOffline: mapValueOfType<bool>(json, r'isOffline'),
lensModel: mapValueOfType<String>(json, r'lensModel'),
libraryId: mapValueOfType<String>(json, r'libraryId'),
make: mapValueOfType<String>(json, r'make'),
model: mapValueOfType<String>(json, r'model'),
ocr: mapValueOfType<String>(json, r'ocr')!,
page: num.parse('${json[r'page']}'),
personIds: json[r'personIds'] is Iterable
? (json[r'personIds'] as Iterable).cast<String>().toList(growable: false)
: const [],
rating: num.parse('${json[r'rating']}'),
state: mapValueOfType<String>(json, r'state'),
tagIds: json[r'tagIds'] is Iterable
? (json[r'tagIds'] as Iterable).cast<String>().toList(growable: false)
: const [],
takenAfter: mapDateTime(json, r'takenAfter', r''),
takenBefore: mapDateTime(json, r'takenBefore', r''),
trashedAfter: mapDateTime(json, r'trashedAfter', r''),
trashedBefore: mapDateTime(json, r'trashedBefore', r''),
type: AssetTypeEnum.fromJson(json[r'type']),
updatedAfter: mapDateTime(json, r'updatedAfter', r''),
updatedBefore: mapDateTime(json, r'updatedBefore', r''),
visibility: AssetVisibility.fromJson(json[r'visibility']),
);
}
return null;
}
static List<OcrSearchDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <OcrSearchDto>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = OcrSearchDto.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, OcrSearchDto> mapFromJson(dynamic json) {
final map = <String, OcrSearchDto>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = OcrSearchDto.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of OcrSearchDto-objects as value to a dart map
static Map<String, List<OcrSearchDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<OcrSearchDto>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = OcrSearchDto.listFromJson(entry.value, growable: growable,);
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{
'ocr',
};
}

View file

@ -28,6 +28,7 @@ class RandomSearchDto {
this.libraryId, this.libraryId,
this.make, this.make,
this.model, this.model,
this.ocr,
this.personIds = const [], this.personIds = const [],
this.rating, this.rating,
this.size, this.size,
@ -131,6 +132,14 @@ class RandomSearchDto {
String? model; String? model;
///
/// 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? ocr;
List<String> personIds; List<String> personIds;
/// Minimum value: -1 /// Minimum value: -1
@ -270,6 +279,7 @@ class RandomSearchDto {
other.libraryId == libraryId && other.libraryId == libraryId &&
other.make == make && other.make == make &&
other.model == model && other.model == model &&
other.ocr == ocr &&
_deepEquality.equals(other.personIds, personIds) && _deepEquality.equals(other.personIds, personIds) &&
other.rating == rating && other.rating == rating &&
other.size == size && other.size == size &&
@ -306,6 +316,7 @@ class RandomSearchDto {
(libraryId == null ? 0 : libraryId!.hashCode) + (libraryId == null ? 0 : libraryId!.hashCode) +
(make == null ? 0 : make!.hashCode) + (make == null ? 0 : make!.hashCode) +
(model == null ? 0 : model!.hashCode) + (model == null ? 0 : model!.hashCode) +
(ocr == null ? 0 : ocr!.hashCode) +
(personIds.hashCode) + (personIds.hashCode) +
(rating == null ? 0 : rating!.hashCode) + (rating == null ? 0 : rating!.hashCode) +
(size == null ? 0 : size!.hashCode) + (size == null ? 0 : size!.hashCode) +
@ -325,7 +336,7 @@ class RandomSearchDto {
(withStacked == null ? 0 : withStacked!.hashCode); (withStacked == null ? 0 : withStacked!.hashCode);
@override @override
String toString() => 'RandomSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, personIds=$personIds, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]'; String toString() => 'RandomSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, personIds=$personIds, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif, withPeople=$withPeople, withStacked=$withStacked]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@ -399,6 +410,11 @@ class RandomSearchDto {
json[r'model'] = this.model; json[r'model'] = this.model;
} else { } else {
// json[r'model'] = null; // json[r'model'] = null;
}
if (this.ocr != null) {
json[r'ocr'] = this.ocr;
} else {
// json[r'ocr'] = null;
} }
json[r'personIds'] = this.personIds; json[r'personIds'] = this.personIds;
if (this.rating != null) { if (this.rating != null) {
@ -510,6 +526,7 @@ class RandomSearchDto {
libraryId: mapValueOfType<String>(json, r'libraryId'), libraryId: mapValueOfType<String>(json, r'libraryId'),
make: mapValueOfType<String>(json, r'make'), make: mapValueOfType<String>(json, r'make'),
model: mapValueOfType<String>(json, r'model'), model: mapValueOfType<String>(json, r'model'),
ocr: mapValueOfType<String>(json, r'ocr'),
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 [],

View file

@ -29,6 +29,7 @@ class SmartSearchDto {
this.libraryId, this.libraryId,
this.make, this.make,
this.model, this.model,
this.ocr,
this.page, this.page,
this.personIds = const [], this.personIds = const [],
this.query, this.query,
@ -141,6 +142,14 @@ class SmartSearchDto {
String? model; String? model;
///
/// 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? ocr;
/// Minimum value: 1 /// Minimum value: 1
/// ///
/// 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
@ -290,6 +299,7 @@ class SmartSearchDto {
other.libraryId == libraryId && other.libraryId == libraryId &&
other.make == make && other.make == make &&
other.model == model && other.model == model &&
other.ocr == ocr &&
other.page == page && other.page == page &&
_deepEquality.equals(other.personIds, personIds) && _deepEquality.equals(other.personIds, personIds) &&
other.query == query && other.query == query &&
@ -328,6 +338,7 @@ class SmartSearchDto {
(libraryId == null ? 0 : libraryId!.hashCode) + (libraryId == null ? 0 : libraryId!.hashCode) +
(make == null ? 0 : make!.hashCode) + (make == null ? 0 : make!.hashCode) +
(model == null ? 0 : model!.hashCode) + (model == null ? 0 : model!.hashCode) +
(ocr == null ? 0 : ocr!.hashCode) +
(page == null ? 0 : page!.hashCode) + (page == null ? 0 : page!.hashCode) +
(personIds.hashCode) + (personIds.hashCode) +
(query == null ? 0 : query!.hashCode) + (query == null ? 0 : query!.hashCode) +
@ -348,7 +359,7 @@ class SmartSearchDto {
(withExif == null ? 0 : withExif!.hashCode); (withExif == null ? 0 : withExif!.hashCode);
@override @override
String toString() => 'SmartSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, language=$language, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, page=$page, personIds=$personIds, query=$query, queryAssetId=$queryAssetId, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif]'; String toString() => 'SmartSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, language=$language, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, page=$page, personIds=$personIds, query=$query, queryAssetId=$queryAssetId, rating=$rating, size=$size, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility, withDeleted=$withDeleted, withExif=$withExif]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@ -428,6 +439,11 @@ class SmartSearchDto {
} else { } else {
// json[r'model'] = null; // json[r'model'] = null;
} }
if (this.ocr != null) {
json[r'ocr'] = this.ocr;
} else {
// json[r'ocr'] = null;
}
if (this.page != null) { if (this.page != null) {
json[r'page'] = this.page; json[r'page'] = this.page;
} else { } else {
@ -544,6 +560,7 @@ class SmartSearchDto {
libraryId: mapValueOfType<String>(json, r'libraryId'), libraryId: mapValueOfType<String>(json, r'libraryId'),
make: mapValueOfType<String>(json, r'make'), make: mapValueOfType<String>(json, r'make'),
model: mapValueOfType<String>(json, r'model'), model: mapValueOfType<String>(json, r'model'),
ocr: mapValueOfType<String>(json, r'ocr'),
page: num.parse('${json[r'page']}'), page: num.parse('${json[r'page']}'),
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)

View file

@ -29,6 +29,7 @@ class StatisticsSearchDto {
this.libraryId, this.libraryId,
this.make, this.make,
this.model, this.model,
this.ocr,
this.personIds = const [], this.personIds = const [],
this.rating, this.rating,
this.state, this.state,
@ -135,6 +136,14 @@ class StatisticsSearchDto {
String? model; String? model;
///
/// 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? ocr;
List<String> personIds; List<String> personIds;
/// Minimum value: -1 /// Minimum value: -1
@ -233,6 +242,7 @@ class StatisticsSearchDto {
other.libraryId == libraryId && other.libraryId == libraryId &&
other.make == make && other.make == make &&
other.model == model && other.model == model &&
other.ocr == ocr &&
_deepEquality.equals(other.personIds, personIds) && _deepEquality.equals(other.personIds, personIds) &&
other.rating == rating && other.rating == rating &&
other.state == state && other.state == state &&
@ -265,6 +275,7 @@ class StatisticsSearchDto {
(libraryId == null ? 0 : libraryId!.hashCode) + (libraryId == null ? 0 : libraryId!.hashCode) +
(make == null ? 0 : make!.hashCode) + (make == null ? 0 : make!.hashCode) +
(model == null ? 0 : model!.hashCode) + (model == null ? 0 : model!.hashCode) +
(ocr == null ? 0 : ocr!.hashCode) +
(personIds.hashCode) + (personIds.hashCode) +
(rating == null ? 0 : rating!.hashCode) + (rating == null ? 0 : rating!.hashCode) +
(state == null ? 0 : state!.hashCode) + (state == null ? 0 : state!.hashCode) +
@ -279,7 +290,7 @@ class StatisticsSearchDto {
(visibility == null ? 0 : visibility!.hashCode); (visibility == null ? 0 : visibility!.hashCode);
@override @override
String toString() => 'StatisticsSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, description=$description, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, personIds=$personIds, rating=$rating, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility]'; String toString() => 'StatisticsSearchDto[albumIds=$albumIds, city=$city, country=$country, createdAfter=$createdAfter, createdBefore=$createdBefore, description=$description, deviceId=$deviceId, isEncoded=$isEncoded, isFavorite=$isFavorite, isMotion=$isMotion, isNotInAlbum=$isNotInAlbum, isOffline=$isOffline, lensModel=$lensModel, libraryId=$libraryId, make=$make, model=$model, ocr=$ocr, personIds=$personIds, rating=$rating, state=$state, tagIds=$tagIds, takenAfter=$takenAfter, takenBefore=$takenBefore, trashedAfter=$trashedAfter, trashedBefore=$trashedBefore, type=$type, updatedAfter=$updatedAfter, updatedBefore=$updatedBefore, visibility=$visibility]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@ -358,6 +369,11 @@ class StatisticsSearchDto {
json[r'model'] = this.model; json[r'model'] = this.model;
} else { } else {
// json[r'model'] = null; // json[r'model'] = null;
}
if (this.ocr != null) {
json[r'ocr'] = this.ocr;
} else {
// json[r'ocr'] = null;
} }
json[r'personIds'] = this.personIds; json[r'personIds'] = this.personIds;
if (this.rating != null) { if (this.rating != null) {
@ -445,6 +461,7 @@ class StatisticsSearchDto {
libraryId: mapValueOfType<String>(json, r'libraryId'), libraryId: mapValueOfType<String>(json, r'libraryId'),
make: mapValueOfType<String>(json, r'make'), make: mapValueOfType<String>(json, r'make'),
model: mapValueOfType<String>(json, r'model'), model: mapValueOfType<String>(json, r'model'),
ocr: mapValueOfType<String>(json, r'ocr'),
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 [],

View file

@ -5933,6 +5933,14 @@
"type": "string" "type": "string"
} }
}, },
{
"name": "ocr",
"required": false,
"in": "query",
"schema": {
"type": "string"
}
},
{ {
"name": "personIds", "name": "personIds",
"required": false, "required": false,
@ -6151,48 +6159,6 @@
"description": "This endpoint requires the `asset.read` permission." "description": "This endpoint requires the `asset.read` permission."
} }
}, },
"/search/ocr": {
"post": {
"operationId": "searchOcr",
"parameters": [],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OcrSearchDto"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SearchResponseDto"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Search"
]
}
},
"/search/person": { "/search/person": {
"get": { "get": {
"operationId": "searchPerson", "operationId": "searchPerson",
@ -12604,6 +12570,9 @@
"nullable": true, "nullable": true,
"type": "string" "type": "string"
}, },
"ocr": {
"type": "string"
},
"order": { "order": {
"allOf": [ "allOf": [
{ {
@ -12918,176 +12887,32 @@
"enabled": { "enabled": {
"type": "boolean" "type": "boolean"
}, },
"minDetectionBoxScore": { "maxResolution": {
"format": "double", "minimum": 1,
"maximum": 1, "type": "integer"
"minimum": 0,
"type": "number"
}, },
"minDetectionScore": { "minDetectionScore": {
"format": "double", "format": "double",
"maximum": 1, "maximum": 1,
"minimum": 0, "minimum": 0.1,
"type": "number" "type": "number"
}, },
"minRecognitionScore": { "minRecognitionScore": {
"format": "double", "format": "double",
"maximum": 1, "maximum": 1,
"minimum": 0, "minimum": 0.1,
"type": "number" "type": "number"
}, },
"modelName": { "modelName": {
"type": "string" "type": "string"
},
"orientationClassifyEnabled": {
"type": "boolean"
},
"unwarpingEnabled": {
"type": "boolean"
} }
}, },
"required": [ "required": [
"enabled", "enabled",
"minDetectionBoxScore", "maxResolution",
"minDetectionScore", "minDetectionScore",
"minRecognitionScore", "minRecognitionScore",
"modelName", "modelName"
"orientationClassifyEnabled",
"unwarpingEnabled"
],
"type": "object"
},
"OcrSearchDto": {
"properties": {
"albumIds": {
"items": {
"format": "uuid",
"type": "string"
},
"type": "array"
},
"city": {
"nullable": true,
"type": "string"
},
"country": {
"nullable": true,
"type": "string"
},
"createdAfter": {
"format": "date-time",
"type": "string"
},
"createdBefore": {
"format": "date-time",
"type": "string"
},
"deviceId": {
"type": "string"
},
"isEncoded": {
"type": "boolean"
},
"isFavorite": {
"type": "boolean"
},
"isMotion": {
"type": "boolean"
},
"isNotInAlbum": {
"type": "boolean"
},
"isOffline": {
"type": "boolean"
},
"lensModel": {
"nullable": true,
"type": "string"
},
"libraryId": {
"format": "uuid",
"nullable": true,
"type": "string"
},
"make": {
"type": "string"
},
"model": {
"nullable": true,
"type": "string"
},
"ocr": {
"type": "string"
},
"page": {
"minimum": 1,
"type": "number"
},
"personIds": {
"items": {
"format": "uuid",
"type": "string"
},
"type": "array"
},
"rating": {
"maximum": 5,
"minimum": -1,
"type": "number"
},
"state": {
"nullable": true,
"type": "string"
},
"tagIds": {
"items": {
"format": "uuid",
"type": "string"
},
"nullable": true,
"type": "array"
},
"takenAfter": {
"format": "date-time",
"type": "string"
},
"takenBefore": {
"format": "date-time",
"type": "string"
},
"trashedAfter": {
"format": "date-time",
"type": "string"
},
"trashedBefore": {
"format": "date-time",
"type": "string"
},
"type": {
"allOf": [
{
"$ref": "#/components/schemas/AssetTypeEnum"
}
]
},
"updatedAfter": {
"format": "date-time",
"type": "string"
},
"updatedBefore": {
"format": "date-time",
"type": "string"
},
"visibility": {
"allOf": [
{
"$ref": "#/components/schemas/AssetVisibility"
}
]
}
},
"required": [
"ocr"
], ],
"type": "object" "type": "object"
}, },
@ -13760,6 +13585,9 @@
"nullable": true, "nullable": true,
"type": "string" "type": "string"
}, },
"ocr": {
"type": "string"
},
"personIds": { "personIds": {
"items": { "items": {
"format": "uuid", "format": "uuid",
@ -14856,6 +14684,9 @@
"nullable": true, "nullable": true,
"type": "string" "type": "string"
}, },
"ocr": {
"type": "string"
},
"page": { "page": {
"minimum": 1, "minimum": 1,
"type": "number" "type": "number"
@ -15061,6 +14892,9 @@
"nullable": true, "nullable": true,
"type": "string" "type": "string"
}, },
"ocr": {
"type": "string"
},
"personIds": { "personIds": {
"items": { "items": {
"format": "uuid", "format": "uuid",

View file

@ -909,6 +909,7 @@ export type MetadataSearchDto = {
libraryId?: string | null; libraryId?: string | null;
make?: string; make?: string;
model?: string | null; model?: string | null;
ocr?: string;
order?: AssetOrder; order?: AssetOrder;
originalFileName?: string; originalFileName?: string;
originalPath?: string; originalPath?: string;
@ -958,37 +959,6 @@ export type SearchResponseDto = {
albums: SearchAlbumResponseDto; albums: SearchAlbumResponseDto;
assets: SearchAssetResponseDto; assets: SearchAssetResponseDto;
}; };
export type OcrSearchDto = {
albumIds?: string[];
city?: string | null;
country?: string | null;
createdAfter?: string;
createdBefore?: string;
deviceId?: string;
isEncoded?: boolean;
isFavorite?: boolean;
isMotion?: boolean;
isNotInAlbum?: boolean;
isOffline?: boolean;
lensModel?: string | null;
libraryId?: string | null;
make?: string;
model?: string | null;
ocr: string;
page?: number;
personIds?: string[];
rating?: number;
state?: string | null;
tagIds?: string[] | null;
takenAfter?: string;
takenBefore?: string;
trashedAfter?: string;
trashedBefore?: string;
"type"?: AssetTypeEnum;
updatedAfter?: string;
updatedBefore?: string;
visibility?: AssetVisibility;
};
export type PlacesResponseDto = { export type PlacesResponseDto = {
admin1name?: string; admin1name?: string;
admin2name?: string; admin2name?: string;
@ -1012,6 +982,7 @@ export type RandomSearchDto = {
libraryId?: string | null; libraryId?: string | null;
make?: string; make?: string;
model?: string | null; model?: string | null;
ocr?: string;
personIds?: string[]; personIds?: string[];
rating?: number; rating?: number;
size?: number; size?: number;
@ -1047,6 +1018,7 @@ export type SmartSearchDto = {
libraryId?: string | null; libraryId?: string | null;
make?: string; make?: string;
model?: string | null; model?: string | null;
ocr?: string;
page?: number; page?: number;
personIds?: string[]; personIds?: string[];
query?: string; query?: string;
@ -1083,6 +1055,7 @@ export type StatisticsSearchDto = {
libraryId?: string | null; libraryId?: string | null;
make?: string; make?: string;
model?: string | null; model?: string | null;
ocr?: string;
personIds?: string[]; personIds?: string[];
rating?: number; rating?: number;
state?: string | null; state?: string | null;
@ -1434,7 +1407,9 @@ export type FacialRecognitionConfig = {
}; };
export type OcrConfig = { export type OcrConfig = {
enabled: boolean; enabled: boolean;
minScore: number; maxResolution: number;
minDetectionScore: number;
minRecognitionScore: number;
modelName: string; modelName: string;
}; };
export type SystemConfigMachineLearningDto = { export type SystemConfigMachineLearningDto = {
@ -3409,7 +3384,7 @@ export function getExploreData(opts?: Oazapfts.RequestOpts) {
/** /**
* This endpoint requires the `asset.read` permission. * This endpoint requires the `asset.read` permission.
*/ */
export function searchLargeAssets({ albumIds, city, country, createdAfter, createdBefore, deviceId, isEncoded, isFavorite, isMotion, isNotInAlbum, isOffline, lensModel, libraryId, make, minFileSize, model, personIds, rating, size, state, tagIds, takenAfter, takenBefore, trashedAfter, trashedBefore, $type, updatedAfter, updatedBefore, visibility, withDeleted, withExif }: { export function searchLargeAssets({ albumIds, city, country, createdAfter, createdBefore, deviceId, isEncoded, isFavorite, isMotion, isNotInAlbum, isOffline, lensModel, libraryId, make, minFileSize, model, ocr, personIds, rating, size, state, tagIds, takenAfter, takenBefore, trashedAfter, trashedBefore, $type, updatedAfter, updatedBefore, visibility, withDeleted, withExif }: {
albumIds?: string[]; albumIds?: string[];
city?: string | null; city?: string | null;
country?: string | null; country?: string | null;
@ -3426,6 +3401,7 @@ export function searchLargeAssets({ albumIds, city, country, createdAfter, creat
make?: string; make?: string;
minFileSize?: number; minFileSize?: number;
model?: string | null; model?: string | null;
ocr?: string;
personIds?: string[]; personIds?: string[];
rating?: number; rating?: number;
size?: number; size?: number;
@ -3462,6 +3438,7 @@ export function searchLargeAssets({ albumIds, city, country, createdAfter, creat
make, make,
minFileSize, minFileSize,
model, model,
ocr,
personIds, personIds,
rating, rating,
size, size,
@ -3497,18 +3474,6 @@ export function searchAssets({ metadataSearchDto }: {
body: metadataSearchDto body: metadataSearchDto
}))); })));
} }
export function searchOcr({ ocrSearchDto }: {
ocrSearchDto: OcrSearchDto;
}, opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
data: SearchResponseDto;
}>("/search/ocr", oazapfts.json({
...opts,
method: "POST",
body: ocrSearchDto
})));
}
/** /**
* This endpoint requires the `person.read` permission. * This endpoint requires the `person.read` permission.
*/ */

View file

@ -253,8 +253,8 @@ export const defaults = Object.freeze<SystemConfig>({
ocr: { ocr: {
enabled: true, enabled: true,
modelName: 'PP-OCRv5_server', modelName: 'PP-OCRv5_server',
minDetectionScore: 0.3, minDetectionScore: 0.5,
minRecognitionScore: 0.0, minRecognitionScore: 0.5,
maxResolution: 1440, maxResolution: 1440,
}, },
}, },

View file

@ -101,6 +101,11 @@ class BaseSearchDto {
@Max(5) @Max(5)
@Min(-1) @Min(-1)
rating?: number; rating?: number;
@IsString()
@IsNotEmpty()
@Optional()
ocr?: string;
} }
class BaseSearchWithResultsDto extends BaseSearchDto { class BaseSearchWithResultsDto extends BaseSearchDto {
@ -218,18 +223,6 @@ export class SmartSearchDto extends BaseSearchWithResultsDto {
page?: number; page?: number;
} }
export class OcrSearchDto extends BaseSearchDto {
@IsString()
@IsNotEmpty()
ocr!: string;
@IsInt()
@Min(1)
@Type(() => Number)
@Optional()
page?: number;
}
export class SearchPlacesDto { export class SearchPlacesDto {
@IsString() @IsString()
@IsNotEmpty() @IsNotEmpty()

View file

@ -196,9 +196,9 @@ export class AssetJobRepository {
@GenerateSql({ params: [DummyValue.UUID] }) @GenerateSql({ params: [DummyValue.UUID] })
getForOcr(id: string) { getForOcr(id: string) {
return this.db return this.db
.selectFrom('assets') .selectFrom('asset')
.select((eb) => ['assets.visibility', withFile(eb, AssetFileType.PREVIEW).as('previewFile')]) .select((eb) => ['asset.visibility', withFile(eb, AssetFileType.Preview).as('previewFile')])
.where('assets.id', '=', id) .where('asset.id', '=', id)
.executeTakeFirst(); .executeTakeFirst();
} }
@ -361,15 +361,15 @@ export class AssetJobRepository {
@GenerateSql({ params: [], stream: true }) @GenerateSql({ params: [], stream: true })
streamForOcrJob(force?: boolean) { streamForOcrJob(force?: boolean) {
return this.db return this.db
.selectFrom('assets') .selectFrom('asset')
.select(['assets.id']) .select(['asset.id'])
.$if(!force, (qb) => .$if(!force, (qb) =>
qb qb
.innerJoin('asset_job_status', 'asset_job_status.assetId', 'assets.id') .innerJoin('asset_job_status', 'asset_job_status.assetId', 'asset.id')
.where('asset_job_status.ocrAt', 'is', null), .where('asset_job_status.ocrAt', 'is', null),
) )
.where('assets.deletedAt', 'is', null) .where('asset.deletedAt', 'is', null)
.where('assets.visibility', '!=', AssetVisibility.HIDDEN) .where('asset.visibility', '!=', AssetVisibility.Hidden)
.stream(); .stream();
} }

View file

@ -1,8 +1,9 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { Insertable, Kysely, sql } from 'kysely'; import { Insertable, Kysely, sql } from 'kysely';
import { InjectKysely } from 'nestjs-kysely'; import { InjectKysely } from 'nestjs-kysely';
import { AssetOcr, DB } from 'src/db';
import { DummyValue, GenerateSql } from 'src/decorators'; import { DummyValue, GenerateSql } from 'src/decorators';
import { DB } from 'src/schema';
import { AssetOcrTable } from 'src/schema/tables/asset-ocr.table';
@Injectable() @Injectable()
export class OcrRepository { export class OcrRepository {
@ -46,7 +47,7 @@ export class OcrRepository {
], ],
], ],
}) })
upsert(assetId: string, ocrDataList: Insertable<AssetOcr>[]) { upsert(assetId: string, ocrDataList: Insertable<AssetOcrTable>[]) {
let query = this.db.with('deleted_ocr', (db) => db.deleteFrom('asset_ocr').where('assetId', '=', assetId)); let query = this.db.with('deleted_ocr', (db) => db.deleteFrom('asset_ocr').where('assetId', '=', assetId));
if (ocrDataList.length > 0) { if (ocrDataList.length > 0) {
const searchText = ocrDataList.map((item) => item.text.trim()).join(' '); const searchText = ocrDataList.map((item) => item.text.trim()).join(' ');

View file

@ -178,6 +178,8 @@ export interface DB {
asset_metadata: AssetMetadataTable; asset_metadata: AssetMetadataTable;
asset_metadata_audit: AssetMetadataAuditTable; asset_metadata_audit: AssetMetadataAuditTable;
asset_job_status: AssetJobStatusTable; asset_job_status: AssetJobStatusTable;
asset_ocr: AssetOcrTable;
ocr_search: OcrSearchTable;
audit: AuditTable; audit: AuditTable;

View file

@ -1,10 +1,10 @@
import { AssetTable } from 'src/schema/tables/asset.table'; import { AssetTable } from 'src/schema/tables/asset.table';
import { Column, ForeignKeyColumn, PrimaryGeneratedColumn, Table } from 'src/sql-tools'; import { Column, ForeignKeyColumn, Generated, PrimaryGeneratedColumn, Table } from 'src/sql-tools';
@Table('asset_ocr') @Table('asset_ocr')
export class AssetOcrTable { export class AssetOcrTable {
@PrimaryGeneratedColumn() @PrimaryGeneratedColumn()
id!: string; id!: Generated<string>;
@ForeignKeyColumn(() => AssetTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' }) @ForeignKeyColumn(() => AssetTable, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
assetId!: string; assetId!: string;

View file

@ -308,7 +308,6 @@ export class JobService extends BaseService {
if (config.nightlyTasks.clusterNewFaces) { if (config.nightlyTasks.clusterNewFaces) {
jobs.push({ name: JobName.FacialRecognitionQueueAll, data: { force: false, nightly: true } }); jobs.push({ name: JobName.FacialRecognitionQueueAll, data: { force: false, nightly: true } });
{ name: JobName.QUEUE_OCR, data: { force: false, nightly: true } },
} }
await this.jobRepository.queueAll(jobs); await this.jobRepository.queueAll(jobs);

View file

@ -13,7 +13,7 @@ export class OcrService extends BaseService {
async handleQueueOcr({ force, nightly }: JobOf<JobName.QUEUE_OCR>): Promise<JobStatus> { async handleQueueOcr({ force, nightly }: JobOf<JobName.QUEUE_OCR>): Promise<JobStatus> {
const { machineLearning } = await this.getConfig({ withCache: false }); const { machineLearning } = await this.getConfig({ withCache: false });
if (!isOcrEnabled(machineLearning)) { if (!isOcrEnabled(machineLearning)) {
return JobStatus.SKIPPED; return JobStatus.Skipped;
} }
if (force) { if (force) {
@ -33,23 +33,23 @@ export class OcrService extends BaseService {
} }
await this.jobRepository.queueAll(jobs); await this.jobRepository.queueAll(jobs);
return JobStatus.SUCCESS; return JobStatus.Success;
} }
@OnJob({ name: JobName.OCR, queue: QueueName.OCR }) @OnJob({ name: JobName.OCR, queue: QueueName.OCR })
async handleOcr({ id }: JobOf<JobName.OCR>): Promise<JobStatus> { async handleOcr({ id }: JobOf<JobName.OCR>): Promise<JobStatus> {
const { machineLearning } = await this.getConfig({ withCache: true }); const { machineLearning } = await this.getConfig({ withCache: true });
if (!isOcrEnabled(machineLearning)) { if (!isOcrEnabled(machineLearning)) {
return JobStatus.SKIPPED; return JobStatus.Skipped;
} }
const asset = await this.assetJobRepository.getForOcr(id); const asset = await this.assetJobRepository.getForOcr(id);
if (!asset || !asset.previewFile) { if (!asset || !asset.previewFile) {
return JobStatus.FAILED; return JobStatus.Failed;
} }
if (asset.visibility === AssetVisibility.HIDDEN) { if (asset.visibility === AssetVisibility.Hidden) {
return JobStatus.SKIPPED; return JobStatus.Skipped;
} }
const ocrResults = await this.machineLearningRepository.ocr( const ocrResults = await this.machineLearningRepository.ocr(
@ -63,7 +63,7 @@ export class OcrService extends BaseService {
await this.assetRepository.upsertJobStatus({ assetId: id, ocrAt: new Date() }); await this.assetRepository.upsertJobStatus({ assetId: id, ocrAt: new Date() });
this.logger.debug(`Processed ${ocrResults.text.length} OCR result(s) for ${id}`); this.logger.debug(`Processed ${ocrResults.text.length} OCR result(s) for ${id}`);
return JobStatus.SUCCESS; return JobStatus.Success;
} }
parseOcrResults(id: string, ocrResults: OCR) { parseOcrResults(id: string, ocrResults: OCR) {

View file

@ -390,7 +390,7 @@ export function searchAssetBuilder(kysely: Kysely<DB>, options: AssetSearchBuild
) )
.$if(!!options.ocr, (qb) => .$if(!!options.ocr, (qb) =>
qb qb
.innerJoin('ocr_search', 'assets.id', 'ocr_search.assetId') .innerJoin('ocr_search', 'asset.id', 'ocr_search.assetId')
.where(() => sql`f_unaccent(ocr_search.text) %>> f_unaccent(${options.ocr!})`), .where(() => sql`f_unaccent(ocr_search.text) %>> f_unaccent(${options.ocr!})`),
) )
.$if(!!options.type, (qb) => qb.where('asset.type', '=', options.type!)) .$if(!!options.type, (qb) => qb.where('asset.type', '=', options.type!))

View file

@ -39,7 +39,7 @@
searchStore.isSearchEnabled = false; searchStore.isSearchEnabled = false;
}); });
const handleSearch = async (payload: SmartSearchDto | MetadataSearchDto | OcrSearchDto) => { const handleSearch = async (payload: SmartSearchDto | MetadataSearchDto) => {
const params = getMetadataSearchQuery(payload); const params = getMetadataSearchQuery(payload);
closeDropdown(); closeDropdown();