From 51cfe10c287e9bead16181d0ef0184f6407fcbb5 Mon Sep 17 00:00:00 2001 From: PyKen Date: Mon, 31 Jul 2023 10:31:57 +0900 Subject: [PATCH] feat(web/server): Search by panorama photos (#3470) * Add panorama filter * Add generated api changes * Fix naming --- cli/src/api/open-api/api.ts | 23 ++++++++++++---- mobile/openapi/doc/SearchApi.md | 6 +++-- mobile/openapi/lib/api/search_api.dart | 13 +++++++--- mobile/openapi/test/search_api_test.dart | 2 +- server/immich-openapi-specs.json | 8 ++++++ server/src/domain/search/dto/search.dto.ts | 5 ++++ .../infra/typesense-schemas/asset.schema.ts | 3 ++- web/src/api/open-api/api.ts | 26 ++++++++++++++----- web/src/routes/(user)/explore/+page.svelte | 10 +++++++ 9 files changed, 78 insertions(+), 18 deletions(-) diff --git a/cli/src/api/open-api/api.ts b/cli/src/api/open-api/api.ts index 384e33ca95e7027def3055204aca191a49a117fd..6e237d864075d9858b231d3e7dce7822a5ea6fb2 100644 --- a/cli/src/api/open-api/api.ts +++ b/cli/src/api/open-api/api.ts @@ -9489,6 +9489,7 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio * @param {string} [exifInfoCountry] * @param {string} [exifInfoMake] * @param {string} [exifInfoModel] + * @param {string} [exifInfoProjectionType] * @param {Array} [smartInfoObjects] * @param {Array} [smartInfoTags] * @param {boolean} [recent] @@ -9496,7 +9497,7 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio * @param {*} [options] Override http request option. * @throws {RequiredError} */ - search: async (q?: string, query?: string, clip?: boolean, type?: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'OTHER', isFavorite?: boolean, isArchived?: boolean, exifInfoCity?: string, exifInfoState?: string, exifInfoCountry?: string, exifInfoMake?: string, exifInfoModel?: string, smartInfoObjects?: Array, smartInfoTags?: Array, recent?: boolean, motion?: boolean, options: AxiosRequestConfig = {}): Promise => { + search: async (q?: string, query?: string, clip?: boolean, type?: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'OTHER', isFavorite?: boolean, isArchived?: boolean, exifInfoCity?: string, exifInfoState?: string, exifInfoCountry?: string, exifInfoMake?: string, exifInfoModel?: string, exifInfoProjectionType?: string, smartInfoObjects?: Array, smartInfoTags?: Array, recent?: boolean, motion?: boolean, options: AxiosRequestConfig = {}): Promise => { const localVarPath = `/search`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -9562,6 +9563,10 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio localVarQueryParameter['exifInfo.model'] = exifInfoModel; } + if (exifInfoProjectionType !== undefined) { + localVarQueryParameter['exifInfo.projectionType'] = exifInfoProjectionType; + } + if (smartInfoObjects) { localVarQueryParameter['smartInfo.objects'] = smartInfoObjects; } @@ -9630,6 +9635,7 @@ export const SearchApiFp = function(configuration?: Configuration) { * @param {string} [exifInfoCountry] * @param {string} [exifInfoMake] * @param {string} [exifInfoModel] + * @param {string} [exifInfoProjectionType] * @param {Array} [smartInfoObjects] * @param {Array} [smartInfoTags] * @param {boolean} [recent] @@ -9637,8 +9643,8 @@ export const SearchApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async search(q?: string, query?: string, clip?: boolean, type?: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'OTHER', isFavorite?: boolean, isArchived?: boolean, exifInfoCity?: string, exifInfoState?: string, exifInfoCountry?: string, exifInfoMake?: string, exifInfoModel?: string, smartInfoObjects?: Array, smartInfoTags?: Array, recent?: boolean, motion?: boolean, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.search(q, query, clip, type, isFavorite, isArchived, exifInfoCity, exifInfoState, exifInfoCountry, exifInfoMake, exifInfoModel, smartInfoObjects, smartInfoTags, recent, motion, options); + async search(q?: string, query?: string, clip?: boolean, type?: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'OTHER', isFavorite?: boolean, isArchived?: boolean, exifInfoCity?: string, exifInfoState?: string, exifInfoCountry?: string, exifInfoMake?: string, exifInfoModel?: string, exifInfoProjectionType?: string, smartInfoObjects?: Array, smartInfoTags?: Array, recent?: boolean, motion?: boolean, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.search(q, query, clip, type, isFavorite, isArchived, exifInfoCity, exifInfoState, exifInfoCountry, exifInfoMake, exifInfoModel, exifInfoProjectionType, smartInfoObjects, smartInfoTags, recent, motion, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, } @@ -9674,7 +9680,7 @@ export const SearchApiFactory = function (configuration?: Configuration, basePat * @throws {RequiredError} */ search(requestParameters: SearchApiSearchRequest = {}, options?: AxiosRequestConfig): AxiosPromise { - return localVarFp.search(requestParameters.q, requestParameters.query, requestParameters.clip, requestParameters.type, requestParameters.isFavorite, requestParameters.isArchived, requestParameters.exifInfoCity, requestParameters.exifInfoState, requestParameters.exifInfoCountry, requestParameters.exifInfoMake, requestParameters.exifInfoModel, requestParameters.smartInfoObjects, requestParameters.smartInfoTags, requestParameters.recent, requestParameters.motion, options).then((request) => request(axios, basePath)); + return localVarFp.search(requestParameters.q, requestParameters.query, requestParameters.clip, requestParameters.type, requestParameters.isFavorite, requestParameters.isArchived, requestParameters.exifInfoCity, requestParameters.exifInfoState, requestParameters.exifInfoCountry, requestParameters.exifInfoMake, requestParameters.exifInfoModel, requestParameters.exifInfoProjectionType, requestParameters.smartInfoObjects, requestParameters.smartInfoTags, requestParameters.recent, requestParameters.motion, options).then((request) => request(axios, basePath)); }, }; }; @@ -9762,6 +9768,13 @@ export interface SearchApiSearchRequest { */ readonly exifInfoModel?: string + /** + * + * @type {string} + * @memberof SearchApiSearch + */ + readonly exifInfoProjectionType?: string + /** * * @type {Array} @@ -9826,7 +9839,7 @@ export class SearchApi extends BaseAPI { * @memberof SearchApi */ public search(requestParameters: SearchApiSearchRequest = {}, options?: AxiosRequestConfig) { - return SearchApiFp(this.configuration).search(requestParameters.q, requestParameters.query, requestParameters.clip, requestParameters.type, requestParameters.isFavorite, requestParameters.isArchived, requestParameters.exifInfoCity, requestParameters.exifInfoState, requestParameters.exifInfoCountry, requestParameters.exifInfoMake, requestParameters.exifInfoModel, requestParameters.smartInfoObjects, requestParameters.smartInfoTags, requestParameters.recent, requestParameters.motion, options).then((request) => request(this.axios, this.basePath)); + return SearchApiFp(this.configuration).search(requestParameters.q, requestParameters.query, requestParameters.clip, requestParameters.type, requestParameters.isFavorite, requestParameters.isArchived, requestParameters.exifInfoCity, requestParameters.exifInfoState, requestParameters.exifInfoCountry, requestParameters.exifInfoMake, requestParameters.exifInfoModel, requestParameters.exifInfoProjectionType, requestParameters.smartInfoObjects, requestParameters.smartInfoTags, requestParameters.recent, requestParameters.motion, options).then((request) => request(this.axios, this.basePath)); } } diff --git a/mobile/openapi/doc/SearchApi.md b/mobile/openapi/doc/SearchApi.md index 2ada86a47058fb9174ca06e5d4f1ee659ea1cc10..74840a73cda5b4e0c245fd509706e8cbd5a5f662 100644 --- a/mobile/openapi/doc/SearchApi.md +++ b/mobile/openapi/doc/SearchApi.md @@ -117,7 +117,7 @@ This endpoint does not need any parameter. [[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) # **search** -> SearchResponseDto search(q, query, clip, type, isFavorite, isArchived, exifInfoPeriodCity, exifInfoPeriodState, exifInfoPeriodCountry, exifInfoPeriodMake, exifInfoPeriodModel, smartInfoPeriodObjects, smartInfoPeriodTags, recent, motion) +> SearchResponseDto search(q, query, clip, type, isFavorite, isArchived, exifInfoPeriodCity, exifInfoPeriodState, exifInfoPeriodCountry, exifInfoPeriodMake, exifInfoPeriodModel, exifInfoPeriodProjectionType, smartInfoPeriodObjects, smartInfoPeriodTags, recent, motion) @@ -151,13 +151,14 @@ final exifInfoPeriodState = exifInfoPeriodState_example; // String | final exifInfoPeriodCountry = exifInfoPeriodCountry_example; // String | final exifInfoPeriodMake = exifInfoPeriodMake_example; // String | final exifInfoPeriodModel = exifInfoPeriodModel_example; // String | +final exifInfoPeriodProjectionType = exifInfoPeriodProjectionType_example; // String | final smartInfoPeriodObjects = []; // List | final smartInfoPeriodTags = []; // List | final recent = true; // bool | final motion = true; // bool | try { - final result = api_instance.search(q, query, clip, type, isFavorite, isArchived, exifInfoPeriodCity, exifInfoPeriodState, exifInfoPeriodCountry, exifInfoPeriodMake, exifInfoPeriodModel, smartInfoPeriodObjects, smartInfoPeriodTags, recent, motion); + final result = api_instance.search(q, query, clip, type, isFavorite, isArchived, exifInfoPeriodCity, exifInfoPeriodState, exifInfoPeriodCountry, exifInfoPeriodMake, exifInfoPeriodModel, exifInfoPeriodProjectionType, smartInfoPeriodObjects, smartInfoPeriodTags, recent, motion); print(result); } catch (e) { print('Exception when calling SearchApi->search: $e\n'); @@ -179,6 +180,7 @@ Name | Type | Description | Notes **exifInfoPeriodCountry** | **String**| | [optional] **exifInfoPeriodMake** | **String**| | [optional] **exifInfoPeriodModel** | **String**| | [optional] + **exifInfoPeriodProjectionType** | **String**| | [optional] **smartInfoPeriodObjects** | [**List**](String.md)| | [optional] [default to const []] **smartInfoPeriodTags** | [**List**](String.md)| | [optional] [default to const []] **recent** | **bool**| | [optional] diff --git a/mobile/openapi/lib/api/search_api.dart b/mobile/openapi/lib/api/search_api.dart index 9df6c79d07e2a58653bd05eec86bf10d72b0e6e4..8178395e077478f806a303487d57c8c2d14e8ba2 100644 --- a/mobile/openapi/lib/api/search_api.dart +++ b/mobile/openapi/lib/api/search_api.dart @@ -126,6 +126,8 @@ class SearchApi { /// /// * [String] exifInfoPeriodModel: /// + /// * [String] exifInfoPeriodProjectionType: + /// /// * [List] smartInfoPeriodObjects: /// /// * [List] smartInfoPeriodTags: @@ -133,7 +135,7 @@ class SearchApi { /// * [bool] recent: /// /// * [bool] motion: - Future searchWithHttpInfo({ String? q, String? query, bool? clip, String? type, bool? isFavorite, bool? isArchived, String? exifInfoPeriodCity, String? exifInfoPeriodState, String? exifInfoPeriodCountry, String? exifInfoPeriodMake, String? exifInfoPeriodModel, List? smartInfoPeriodObjects, List? smartInfoPeriodTags, bool? recent, bool? motion, }) async { + Future searchWithHttpInfo({ String? q, String? query, bool? clip, String? type, bool? isFavorite, bool? isArchived, String? exifInfoPeriodCity, String? exifInfoPeriodState, String? exifInfoPeriodCountry, String? exifInfoPeriodMake, String? exifInfoPeriodModel, String? exifInfoPeriodProjectionType, List? smartInfoPeriodObjects, List? smartInfoPeriodTags, bool? recent, bool? motion, }) async { // ignore: prefer_const_declarations final path = r'/search'; @@ -177,6 +179,9 @@ class SearchApi { if (exifInfoPeriodModel != null) { queryParams.addAll(_queryParams('', 'exifInfo.model', exifInfoPeriodModel)); } + if (exifInfoPeriodProjectionType != null) { + queryParams.addAll(_queryParams('', 'exifInfo.projectionType', exifInfoPeriodProjectionType)); + } if (smartInfoPeriodObjects != null) { queryParams.addAll(_queryParams('multi', 'smartInfo.objects', smartInfoPeriodObjects)); } @@ -228,6 +233,8 @@ class SearchApi { /// /// * [String] exifInfoPeriodModel: /// + /// * [String] exifInfoPeriodProjectionType: + /// /// * [List] smartInfoPeriodObjects: /// /// * [List] smartInfoPeriodTags: @@ -235,8 +242,8 @@ class SearchApi { /// * [bool] recent: /// /// * [bool] motion: - Future search({ String? q, String? query, bool? clip, String? type, bool? isFavorite, bool? isArchived, String? exifInfoPeriodCity, String? exifInfoPeriodState, String? exifInfoPeriodCountry, String? exifInfoPeriodMake, String? exifInfoPeriodModel, List? smartInfoPeriodObjects, List? smartInfoPeriodTags, bool? recent, bool? motion, }) async { - final response = await searchWithHttpInfo( q: q, query: query, clip: clip, type: type, isFavorite: isFavorite, isArchived: isArchived, exifInfoPeriodCity: exifInfoPeriodCity, exifInfoPeriodState: exifInfoPeriodState, exifInfoPeriodCountry: exifInfoPeriodCountry, exifInfoPeriodMake: exifInfoPeriodMake, exifInfoPeriodModel: exifInfoPeriodModel, smartInfoPeriodObjects: smartInfoPeriodObjects, smartInfoPeriodTags: smartInfoPeriodTags, recent: recent, motion: motion, ); + Future search({ String? q, String? query, bool? clip, String? type, bool? isFavorite, bool? isArchived, String? exifInfoPeriodCity, String? exifInfoPeriodState, String? exifInfoPeriodCountry, String? exifInfoPeriodMake, String? exifInfoPeriodModel, String? exifInfoPeriodProjectionType, List? smartInfoPeriodObjects, List? smartInfoPeriodTags, bool? recent, bool? motion, }) async { + final response = await searchWithHttpInfo( q: q, query: query, clip: clip, type: type, isFavorite: isFavorite, isArchived: isArchived, exifInfoPeriodCity: exifInfoPeriodCity, exifInfoPeriodState: exifInfoPeriodState, exifInfoPeriodCountry: exifInfoPeriodCountry, exifInfoPeriodMake: exifInfoPeriodMake, exifInfoPeriodModel: exifInfoPeriodModel, exifInfoPeriodProjectionType: exifInfoPeriodProjectionType, smartInfoPeriodObjects: smartInfoPeriodObjects, smartInfoPeriodTags: smartInfoPeriodTags, recent: recent, motion: motion, ); if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, await _decodeBodyBytes(response)); } diff --git a/mobile/openapi/test/search_api_test.dart b/mobile/openapi/test/search_api_test.dart index a65075d1eb7caeae4afc80c77bcb18ad8fdde58f..a6bbacfa2a9bde4621ef5743abc56a66beca7070 100644 --- a/mobile/openapi/test/search_api_test.dart +++ b/mobile/openapi/test/search_api_test.dart @@ -27,7 +27,7 @@ void main() { // TODO }); - //Future search({ String q, String query, bool clip, String type, bool isFavorite, bool isArchived, String exifInfoPeriodCity, String exifInfoPeriodState, String exifInfoPeriodCountry, String exifInfoPeriodMake, String exifInfoPeriodModel, List smartInfoPeriodObjects, List smartInfoPeriodTags, bool recent, bool motion }) async + //Future search({ String q, String query, bool clip, String type, bool isFavorite, bool isArchived, String exifInfoPeriodCity, String exifInfoPeriodState, String exifInfoPeriodCountry, String exifInfoPeriodMake, String exifInfoPeriodModel, String exifInfoPeriodProjectionType, List smartInfoPeriodObjects, List smartInfoPeriodTags, bool recent, bool motion }) async test('test search', () async { // TODO }); diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json index 1fc155c54a297464571813333cb725aedeb21a92..56e96bd116e59badbdd4873e5e5f3878f4f608d4 100644 --- a/server/immich-openapi-specs.json +++ b/server/immich-openapi-specs.json @@ -2924,6 +2924,14 @@ "type": "string" } }, + { + "name": "exifInfo.projectionType", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, { "name": "smartInfo.objects", "required": false, diff --git a/server/src/domain/search/dto/search.dto.ts b/server/src/domain/search/dto/search.dto.ts index 27eeb52725f5ae0e037a7d992c713a18e23ca1e2..bb38a383b26a6f8ce6f896a86590ab7ee044e6b7 100644 --- a/server/src/domain/search/dto/search.dto.ts +++ b/server/src/domain/search/dto/search.dto.ts @@ -58,6 +58,11 @@ export class SearchDto { @IsOptional() 'exifInfo.model'?: string; + @IsString() + @IsNotEmpty() + @IsOptional() + 'exifInfo.projectionType'?: string; + @IsString({ each: true }) @IsArray() @IsOptional() diff --git a/server/src/infra/typesense-schemas/asset.schema.ts b/server/src/infra/typesense-schemas/asset.schema.ts index 5d31e67b2b4abc55f0a3525079cb09799d92bf13..53729c0772fe1fdbc104b2d0685552907a37726c 100644 --- a/server/src/infra/typesense-schemas/asset.schema.ts +++ b/server/src/infra/typesense-schemas/asset.schema.ts @@ -1,6 +1,6 @@ import { CollectionCreateSchema } from 'typesense/lib/Typesense/Collections'; -export const assetSchemaVersion = 7; +export const assetSchemaVersion = 8; export const assetSchema: CollectionCreateSchema = { name: `assets-v${assetSchemaVersion}`, fields: [ @@ -23,6 +23,7 @@ export const assetSchema: CollectionCreateSchema = { { name: 'exifInfo.make', type: 'string', facet: true, optional: true }, { name: 'exifInfo.model', type: 'string', facet: true, optional: true }, { name: 'exifInfo.orientation', type: 'string', optional: true }, + { name: 'exifInfo.projectionType', type: 'string', facet: true, optional: true }, // smart info { name: 'smartInfo.objects', type: 'string[]', facet: true, optional: true }, diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts index 02d3b4140443263defd3c91ebe88320b2af694a5..e42b66ccbfa8b44b3c8ec671986d65b95feb33fe 100644 --- a/web/src/api/open-api/api.ts +++ b/web/src/api/open-api/api.ts @@ -9535,6 +9535,7 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio * @param {string} [exifInfoCountry] * @param {string} [exifInfoMake] * @param {string} [exifInfoModel] + * @param {string} [exifInfoProjectionType] * @param {Array} [smartInfoObjects] * @param {Array} [smartInfoTags] * @param {boolean} [recent] @@ -9542,7 +9543,7 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio * @param {*} [options] Override http request option. * @throws {RequiredError} */ - search: async (q?: string, query?: string, clip?: boolean, type?: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'OTHER', isFavorite?: boolean, isArchived?: boolean, exifInfoCity?: string, exifInfoState?: string, exifInfoCountry?: string, exifInfoMake?: string, exifInfoModel?: string, smartInfoObjects?: Array, smartInfoTags?: Array, recent?: boolean, motion?: boolean, options: AxiosRequestConfig = {}): Promise => { + search: async (q?: string, query?: string, clip?: boolean, type?: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'OTHER', isFavorite?: boolean, isArchived?: boolean, exifInfoCity?: string, exifInfoState?: string, exifInfoCountry?: string, exifInfoMake?: string, exifInfoModel?: string, exifInfoProjectionType?: string, smartInfoObjects?: Array, smartInfoTags?: Array, recent?: boolean, motion?: boolean, options: AxiosRequestConfig = {}): Promise => { const localVarPath = `/search`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -9608,6 +9609,10 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio localVarQueryParameter['exifInfo.model'] = exifInfoModel; } + if (exifInfoProjectionType !== undefined) { + localVarQueryParameter['exifInfo.projectionType'] = exifInfoProjectionType; + } + if (smartInfoObjects) { localVarQueryParameter['smartInfo.objects'] = smartInfoObjects; } @@ -9676,6 +9681,7 @@ export const SearchApiFp = function(configuration?: Configuration) { * @param {string} [exifInfoCountry] * @param {string} [exifInfoMake] * @param {string} [exifInfoModel] + * @param {string} [exifInfoProjectionType] * @param {Array} [smartInfoObjects] * @param {Array} [smartInfoTags] * @param {boolean} [recent] @@ -9683,8 +9689,8 @@ export const SearchApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async search(q?: string, query?: string, clip?: boolean, type?: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'OTHER', isFavorite?: boolean, isArchived?: boolean, exifInfoCity?: string, exifInfoState?: string, exifInfoCountry?: string, exifInfoMake?: string, exifInfoModel?: string, smartInfoObjects?: Array, smartInfoTags?: Array, recent?: boolean, motion?: boolean, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.search(q, query, clip, type, isFavorite, isArchived, exifInfoCity, exifInfoState, exifInfoCountry, exifInfoMake, exifInfoModel, smartInfoObjects, smartInfoTags, recent, motion, options); + async search(q?: string, query?: string, clip?: boolean, type?: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'OTHER', isFavorite?: boolean, isArchived?: boolean, exifInfoCity?: string, exifInfoState?: string, exifInfoCountry?: string, exifInfoMake?: string, exifInfoModel?: string, exifInfoProjectionType?: string, smartInfoObjects?: Array, smartInfoTags?: Array, recent?: boolean, motion?: boolean, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.search(q, query, clip, type, isFavorite, isArchived, exifInfoCity, exifInfoState, exifInfoCountry, exifInfoMake, exifInfoModel, exifInfoProjectionType, smartInfoObjects, smartInfoTags, recent, motion, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, } @@ -9726,6 +9732,7 @@ export const SearchApiFactory = function (configuration?: Configuration, basePat * @param {string} [exifInfoCountry] * @param {string} [exifInfoMake] * @param {string} [exifInfoModel] + * @param {string} [exifInfoProjectionType] * @param {Array} [smartInfoObjects] * @param {Array} [smartInfoTags] * @param {boolean} [recent] @@ -9733,8 +9740,8 @@ export const SearchApiFactory = function (configuration?: Configuration, basePat * @param {*} [options] Override http request option. * @throws {RequiredError} */ - search(q?: string, query?: string, clip?: boolean, type?: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'OTHER', isFavorite?: boolean, isArchived?: boolean, exifInfoCity?: string, exifInfoState?: string, exifInfoCountry?: string, exifInfoMake?: string, exifInfoModel?: string, smartInfoObjects?: Array, smartInfoTags?: Array, recent?: boolean, motion?: boolean, options?: any): AxiosPromise { - return localVarFp.search(q, query, clip, type, isFavorite, isArchived, exifInfoCity, exifInfoState, exifInfoCountry, exifInfoMake, exifInfoModel, smartInfoObjects, smartInfoTags, recent, motion, options).then((request) => request(axios, basePath)); + search(q?: string, query?: string, clip?: boolean, type?: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'OTHER', isFavorite?: boolean, isArchived?: boolean, exifInfoCity?: string, exifInfoState?: string, exifInfoCountry?: string, exifInfoMake?: string, exifInfoModel?: string, exifInfoProjectionType?: string, smartInfoObjects?: Array, smartInfoTags?: Array, recent?: boolean, motion?: boolean, options?: any): AxiosPromise { + return localVarFp.search(q, query, clip, type, isFavorite, isArchived, exifInfoCity, exifInfoState, exifInfoCountry, exifInfoMake, exifInfoModel, exifInfoProjectionType, smartInfoObjects, smartInfoTags, recent, motion, options).then((request) => request(axios, basePath)); }, }; }; @@ -9822,6 +9829,13 @@ export interface SearchApiSearchRequest { */ readonly exifInfoModel?: string + /** + * + * @type {string} + * @memberof SearchApiSearch + */ + readonly exifInfoProjectionType?: string + /** * * @type {Array} @@ -9886,7 +9900,7 @@ export class SearchApi extends BaseAPI { * @memberof SearchApi */ public search(requestParameters: SearchApiSearchRequest = {}, options?: AxiosRequestConfig) { - return SearchApiFp(this.configuration).search(requestParameters.q, requestParameters.query, requestParameters.clip, requestParameters.type, requestParameters.isFavorite, requestParameters.isArchived, requestParameters.exifInfoCity, requestParameters.exifInfoState, requestParameters.exifInfoCountry, requestParameters.exifInfoMake, requestParameters.exifInfoModel, requestParameters.smartInfoObjects, requestParameters.smartInfoTags, requestParameters.recent, requestParameters.motion, options).then((request) => request(this.axios, this.basePath)); + return SearchApiFp(this.configuration).search(requestParameters.q, requestParameters.query, requestParameters.clip, requestParameters.type, requestParameters.isFavorite, requestParameters.isArchived, requestParameters.exifInfoCity, requestParameters.exifInfoState, requestParameters.exifInfoCountry, requestParameters.exifInfoMake, requestParameters.exifInfoModel, requestParameters.exifInfoProjectionType, requestParameters.smartInfoObjects, requestParameters.smartInfoTags, requestParameters.recent, requestParameters.motion, options).then((request) => request(this.axios, this.basePath)); } } diff --git a/web/src/routes/(user)/explore/+page.svelte b/web/src/routes/(user)/explore/+page.svelte index 3972bbb41f298e91bcf13e4881b726a979fe6585..cdedb2d10ea32c4ab49f9d564bad4bc76890b1cd 100644 --- a/web/src/routes/(user)/explore/+page.svelte +++ b/web/src/routes/(user)/explore/+page.svelte @@ -8,6 +8,7 @@ import HeartMultipleOutline from 'svelte-material-icons/HeartMultipleOutline.svelte'; import MotionPlayOutline from 'svelte-material-icons/MotionPlayOutline.svelte'; import PlayCircleOutline from 'svelte-material-icons/PlayCircleOutline.svelte'; + import Rotate360Icon from 'svelte-material-icons/Rotate360.svelte'; import type { PageData } from './$types'; export let data: PageData; @@ -149,6 +150,15 @@ Motion photos +