1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-25 10:43:13 +02:00

feat(web/server): Search by panorama photos (#3470)

* Add panorama filter

* Add generated api changes

* Fix naming
This commit is contained in:
PyKen 2023-07-31 10:31:57 +09:00 committed by GitHub
parent bc3f95c57c
commit 51cfe10c28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 63 additions and 12 deletions

View File

@ -9489,6 +9489,7 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio
* @param {string} [exifInfoCountry] * @param {string} [exifInfoCountry]
* @param {string} [exifInfoMake] * @param {string} [exifInfoMake]
* @param {string} [exifInfoModel] * @param {string} [exifInfoModel]
* @param {string} [exifInfoProjectionType]
* @param {Array<string>} [smartInfoObjects] * @param {Array<string>} [smartInfoObjects]
* @param {Array<string>} [smartInfoTags] * @param {Array<string>} [smartInfoTags]
* @param {boolean} [recent] * @param {boolean} [recent]
@ -9496,7 +9497,7 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @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<string>, smartInfoTags?: Array<string>, recent?: boolean, motion?: boolean, options: AxiosRequestConfig = {}): Promise<RequestArgs> => { 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<string>, smartInfoTags?: Array<string>, recent?: boolean, motion?: boolean, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/search`; const localVarPath = `/search`;
// use dummy base URL string because the URL constructor only accepts absolute URLs. // use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -9562,6 +9563,10 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio
localVarQueryParameter['exifInfo.model'] = exifInfoModel; localVarQueryParameter['exifInfo.model'] = exifInfoModel;
} }
if (exifInfoProjectionType !== undefined) {
localVarQueryParameter['exifInfo.projectionType'] = exifInfoProjectionType;
}
if (smartInfoObjects) { if (smartInfoObjects) {
localVarQueryParameter['smartInfo.objects'] = smartInfoObjects; localVarQueryParameter['smartInfo.objects'] = smartInfoObjects;
} }
@ -9630,6 +9635,7 @@ export const SearchApiFp = function(configuration?: Configuration) {
* @param {string} [exifInfoCountry] * @param {string} [exifInfoCountry]
* @param {string} [exifInfoMake] * @param {string} [exifInfoMake]
* @param {string} [exifInfoModel] * @param {string} [exifInfoModel]
* @param {string} [exifInfoProjectionType]
* @param {Array<string>} [smartInfoObjects] * @param {Array<string>} [smartInfoObjects]
* @param {Array<string>} [smartInfoTags] * @param {Array<string>} [smartInfoTags]
* @param {boolean} [recent] * @param {boolean} [recent]
@ -9637,8 +9643,8 @@ export const SearchApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @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<string>, smartInfoTags?: Array<string>, recent?: boolean, motion?: boolean, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SearchResponseDto>> { 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<string>, smartInfoTags?: Array<string>, recent?: boolean, motion?: boolean, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SearchResponseDto>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.search(q, query, clip, type, isFavorite, isArchived, exifInfoCity, exifInfoState, exifInfoCountry, exifInfoMake, exifInfoModel, smartInfoObjects, smartInfoTags, recent, motion, options); 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); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
}, },
} }
@ -9674,7 +9680,7 @@ export const SearchApiFactory = function (configuration?: Configuration, basePat
* @throws {RequiredError} * @throws {RequiredError}
*/ */
search(requestParameters: SearchApiSearchRequest = {}, options?: AxiosRequestConfig): AxiosPromise<SearchResponseDto> { search(requestParameters: SearchApiSearchRequest = {}, options?: AxiosRequestConfig): AxiosPromise<SearchResponseDto> {
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 readonly exifInfoModel?: string
/**
*
* @type {string}
* @memberof SearchApiSearch
*/
readonly exifInfoProjectionType?: string
/** /**
* *
* @type {Array<string>} * @type {Array<string>}
@ -9826,7 +9839,7 @@ export class SearchApi extends BaseAPI {
* @memberof SearchApi * @memberof SearchApi
*/ */
public search(requestParameters: SearchApiSearchRequest = {}, options?: AxiosRequestConfig) { 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));
} }
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -2924,6 +2924,14 @@
"type": "string" "type": "string"
} }
}, },
{
"name": "exifInfo.projectionType",
"required": false,
"in": "query",
"schema": {
"type": "string"
}
},
{ {
"name": "smartInfo.objects", "name": "smartInfo.objects",
"required": false, "required": false,

View File

@ -58,6 +58,11 @@ export class SearchDto {
@IsOptional() @IsOptional()
'exifInfo.model'?: string; 'exifInfo.model'?: string;
@IsString()
@IsNotEmpty()
@IsOptional()
'exifInfo.projectionType'?: string;
@IsString({ each: true }) @IsString({ each: true })
@IsArray() @IsArray()
@IsOptional() @IsOptional()

View File

@ -1,6 +1,6 @@
import { CollectionCreateSchema } from 'typesense/lib/Typesense/Collections'; import { CollectionCreateSchema } from 'typesense/lib/Typesense/Collections';
export const assetSchemaVersion = 7; export const assetSchemaVersion = 8;
export const assetSchema: CollectionCreateSchema = { export const assetSchema: CollectionCreateSchema = {
name: `assets-v${assetSchemaVersion}`, name: `assets-v${assetSchemaVersion}`,
fields: [ fields: [
@ -23,6 +23,7 @@ export const assetSchema: CollectionCreateSchema = {
{ name: 'exifInfo.make', type: 'string', facet: true, optional: true }, { name: 'exifInfo.make', type: 'string', facet: true, optional: true },
{ name: 'exifInfo.model', type: 'string', facet: true, optional: true }, { name: 'exifInfo.model', type: 'string', facet: true, optional: true },
{ name: 'exifInfo.orientation', type: 'string', optional: true }, { name: 'exifInfo.orientation', type: 'string', optional: true },
{ name: 'exifInfo.projectionType', type: 'string', facet: true, optional: true },
// smart info // smart info
{ name: 'smartInfo.objects', type: 'string[]', facet: true, optional: true }, { name: 'smartInfo.objects', type: 'string[]', facet: true, optional: true },

View File

@ -9535,6 +9535,7 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio
* @param {string} [exifInfoCountry] * @param {string} [exifInfoCountry]
* @param {string} [exifInfoMake] * @param {string} [exifInfoMake]
* @param {string} [exifInfoModel] * @param {string} [exifInfoModel]
* @param {string} [exifInfoProjectionType]
* @param {Array<string>} [smartInfoObjects] * @param {Array<string>} [smartInfoObjects]
* @param {Array<string>} [smartInfoTags] * @param {Array<string>} [smartInfoTags]
* @param {boolean} [recent] * @param {boolean} [recent]
@ -9542,7 +9543,7 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @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<string>, smartInfoTags?: Array<string>, recent?: boolean, motion?: boolean, options: AxiosRequestConfig = {}): Promise<RequestArgs> => { 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<string>, smartInfoTags?: Array<string>, recent?: boolean, motion?: boolean, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/search`; const localVarPath = `/search`;
// use dummy base URL string because the URL constructor only accepts absolute URLs. // use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -9608,6 +9609,10 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio
localVarQueryParameter['exifInfo.model'] = exifInfoModel; localVarQueryParameter['exifInfo.model'] = exifInfoModel;
} }
if (exifInfoProjectionType !== undefined) {
localVarQueryParameter['exifInfo.projectionType'] = exifInfoProjectionType;
}
if (smartInfoObjects) { if (smartInfoObjects) {
localVarQueryParameter['smartInfo.objects'] = smartInfoObjects; localVarQueryParameter['smartInfo.objects'] = smartInfoObjects;
} }
@ -9676,6 +9681,7 @@ export const SearchApiFp = function(configuration?: Configuration) {
* @param {string} [exifInfoCountry] * @param {string} [exifInfoCountry]
* @param {string} [exifInfoMake] * @param {string} [exifInfoMake]
* @param {string} [exifInfoModel] * @param {string} [exifInfoModel]
* @param {string} [exifInfoProjectionType]
* @param {Array<string>} [smartInfoObjects] * @param {Array<string>} [smartInfoObjects]
* @param {Array<string>} [smartInfoTags] * @param {Array<string>} [smartInfoTags]
* @param {boolean} [recent] * @param {boolean} [recent]
@ -9683,8 +9689,8 @@ export const SearchApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @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<string>, smartInfoTags?: Array<string>, recent?: boolean, motion?: boolean, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SearchResponseDto>> { 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<string>, smartInfoTags?: Array<string>, recent?: boolean, motion?: boolean, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SearchResponseDto>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.search(q, query, clip, type, isFavorite, isArchived, exifInfoCity, exifInfoState, exifInfoCountry, exifInfoMake, exifInfoModel, smartInfoObjects, smartInfoTags, recent, motion, options); 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); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
}, },
} }
@ -9726,6 +9732,7 @@ export const SearchApiFactory = function (configuration?: Configuration, basePat
* @param {string} [exifInfoCountry] * @param {string} [exifInfoCountry]
* @param {string} [exifInfoMake] * @param {string} [exifInfoMake]
* @param {string} [exifInfoModel] * @param {string} [exifInfoModel]
* @param {string} [exifInfoProjectionType]
* @param {Array<string>} [smartInfoObjects] * @param {Array<string>} [smartInfoObjects]
* @param {Array<string>} [smartInfoTags] * @param {Array<string>} [smartInfoTags]
* @param {boolean} [recent] * @param {boolean} [recent]
@ -9733,8 +9740,8 @@ export const SearchApiFactory = function (configuration?: Configuration, basePat
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @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<string>, smartInfoTags?: Array<string>, recent?: boolean, motion?: boolean, options?: any): AxiosPromise<SearchResponseDto> { 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<string>, smartInfoTags?: Array<string>, recent?: boolean, motion?: boolean, options?: any): AxiosPromise<SearchResponseDto> {
return localVarFp.search(q, query, clip, type, isFavorite, isArchived, exifInfoCity, exifInfoState, exifInfoCountry, exifInfoMake, exifInfoModel, smartInfoObjects, smartInfoTags, recent, motion, options).then((request) => request(axios, basePath)); 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 readonly exifInfoModel?: string
/**
*
* @type {string}
* @memberof SearchApiSearch
*/
readonly exifInfoProjectionType?: string
/** /**
* *
* @type {Array<string>} * @type {Array<string>}
@ -9886,7 +9900,7 @@ export class SearchApi extends BaseAPI {
* @memberof SearchApi * @memberof SearchApi
*/ */
public search(requestParameters: SearchApiSearchRequest = {}, options?: AxiosRequestConfig) { 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));
} }
} }

View File

@ -8,6 +8,7 @@
import HeartMultipleOutline from 'svelte-material-icons/HeartMultipleOutline.svelte'; import HeartMultipleOutline from 'svelte-material-icons/HeartMultipleOutline.svelte';
import MotionPlayOutline from 'svelte-material-icons/MotionPlayOutline.svelte'; import MotionPlayOutline from 'svelte-material-icons/MotionPlayOutline.svelte';
import PlayCircleOutline from 'svelte-material-icons/PlayCircleOutline.svelte'; import PlayCircleOutline from 'svelte-material-icons/PlayCircleOutline.svelte';
import Rotate360Icon from 'svelte-material-icons/Rotate360.svelte';
import type { PageData } from './$types'; import type { PageData } from './$types';
export let data: PageData; export let data: PageData;
@ -149,6 +150,15 @@
<span>Motion photos</span> <span>Motion photos</span>
</a> </a>
</div> </div>
<div>
<a
href="/search?exifInfo.projectionType=EQUIRECTANGULAR"
class="flex w-full items-center gap-2 text-sm font-medium hover:text-immich-primary dark:hover:text-immich-dark-primary"
>
<Rotate360Icon size={24} />
<span>Panorama photos</span>
</a>
</div>
</div> </div>
</div> </div>
</div> </div>