diff --git a/cli/src/api/open-api/api.ts b/cli/src/api/open-api/api.ts index 5bcfe0f078..798d388d7b 100644 --- a/cli/src/api/open-api/api.ts +++ b/cli/src/api/open-api/api.ts @@ -2570,6 +2570,20 @@ export interface QueueStatusDto { */ 'isPaused': boolean; } +/** + * + * @export + * @enum {string} + */ + +export const ReactionLevel = { + Album: 'album', + Asset: 'asset' +} as const; + +export type ReactionLevel = typeof ReactionLevel[keyof typeof ReactionLevel]; + + /** * * @export @@ -5065,11 +5079,12 @@ export const ActivityApiAxiosParamCreator = function (configuration?: Configurat * @param {string} albumId * @param {string} [assetId] * @param {ReactionType} [type] + * @param {ReactionLevel} [level] * @param {string} [userId] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getActivities: async (albumId: string, assetId?: string, type?: ReactionType, userId?: string, options: AxiosRequestConfig = {}): Promise => { + getActivities: async (albumId: string, assetId?: string, type?: ReactionType, level?: ReactionLevel, userId?: string, options: AxiosRequestConfig = {}): Promise => { // verify required parameter 'albumId' is not null or undefined assertParamExists('getActivities', 'albumId', albumId) const localVarPath = `/activity`; @@ -5105,6 +5120,10 @@ export const ActivityApiAxiosParamCreator = function (configuration?: Configurat localVarQueryParameter['type'] = type; } + if (level !== undefined) { + localVarQueryParameter['level'] = level; + } + if (userId !== undefined) { localVarQueryParameter['userId'] = userId; } @@ -5205,12 +5224,13 @@ export const ActivityApiFp = function(configuration?: Configuration) { * @param {string} albumId * @param {string} [assetId] * @param {ReactionType} [type] + * @param {ReactionLevel} [level] * @param {string} [userId] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getActivities(albumId: string, assetId?: string, type?: ReactionType, userId?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getActivities(albumId, assetId, type, userId, options); + async getActivities(albumId: string, assetId?: string, type?: ReactionType, level?: ReactionLevel, userId?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getActivities(albumId, assetId, type, level, userId, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** @@ -5259,7 +5279,7 @@ export const ActivityApiFactory = function (configuration?: Configuration, baseP * @throws {RequiredError} */ getActivities(requestParameters: ActivityApiGetActivitiesRequest, options?: AxiosRequestConfig): AxiosPromise> { - return localVarFp.getActivities(requestParameters.albumId, requestParameters.assetId, requestParameters.type, requestParameters.userId, options).then((request) => request(axios, basePath)); + return localVarFp.getActivities(requestParameters.albumId, requestParameters.assetId, requestParameters.type, requestParameters.level, requestParameters.userId, options).then((request) => request(axios, basePath)); }, /** * @@ -5328,6 +5348,13 @@ export interface ActivityApiGetActivitiesRequest { */ readonly type?: ReactionType + /** + * + * @type {ReactionLevel} + * @memberof ActivityApiGetActivities + */ + readonly level?: ReactionLevel + /** * * @type {string} @@ -5394,7 +5421,7 @@ export class ActivityApi extends BaseAPI { * @memberof ActivityApi */ public getActivities(requestParameters: ActivityApiGetActivitiesRequest, options?: AxiosRequestConfig) { - return ActivityApiFp(this.configuration).getActivities(requestParameters.albumId, requestParameters.assetId, requestParameters.type, requestParameters.userId, options).then((request) => request(this.axios, this.basePath)); + return ActivityApiFp(this.configuration).getActivities(requestParameters.albumId, requestParameters.assetId, requestParameters.type, requestParameters.level, requestParameters.userId, options).then((request) => request(this.axios, this.basePath)); } /** diff --git a/mobile/openapi/.openapi-generator/FILES b/mobile/openapi/.openapi-generator/FILES index 18dc395b57..57854e1b79 100644 --- a/mobile/openapi/.openapi-generator/FILES +++ b/mobile/openapi/.openapi-generator/FILES @@ -101,6 +101,7 @@ doc/PersonResponseDto.md doc/PersonStatisticsResponseDto.md doc/PersonUpdateDto.md doc/QueueStatusDto.md +doc/ReactionLevel.md doc/ReactionType.md doc/RecognitionConfig.md doc/ScanLibraryDto.md @@ -281,6 +282,7 @@ lib/model/person_response_dto.dart lib/model/person_statistics_response_dto.dart lib/model/person_update_dto.dart lib/model/queue_status_dto.dart +lib/model/reaction_level.dart lib/model/reaction_type.dart lib/model/recognition_config.dart lib/model/scan_library_dto.dart @@ -440,6 +442,7 @@ test/person_response_dto_test.dart test/person_statistics_response_dto_test.dart test/person_update_dto_test.dart test/queue_status_dto_test.dart +test/reaction_level_test.dart test/reaction_type_test.dart test/recognition_config_test.dart test/scan_library_dto_test.dart diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index d62d95cb50..0bc2cc1e33 100644 --- a/mobile/openapi/README.md +++ b/mobile/openapi/README.md @@ -292,6 +292,7 @@ Class | Method | HTTP request | Description - [PersonStatisticsResponseDto](doc//PersonStatisticsResponseDto.md) - [PersonUpdateDto](doc//PersonUpdateDto.md) - [QueueStatusDto](doc//QueueStatusDto.md) + - [ReactionLevel](doc//ReactionLevel.md) - [ReactionType](doc//ReactionType.md) - [RecognitionConfig](doc//RecognitionConfig.md) - [ScanLibraryDto](doc//ScanLibraryDto.md) diff --git a/mobile/openapi/doc/ActivityApi.md b/mobile/openapi/doc/ActivityApi.md index 1af3f1f496..6221ef5e4f 100644 --- a/mobile/openapi/doc/ActivityApi.md +++ b/mobile/openapi/doc/ActivityApi.md @@ -125,7 +125,7 @@ void (empty response body) [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) # **getActivities** -> List getActivities(albumId, assetId, type, userId) +> List getActivities(albumId, assetId, type, level, userId) @@ -151,10 +151,11 @@ final api_instance = ActivityApi(); final albumId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String | final assetId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String | final type = ; // ReactionType | +final level = ; // ReactionLevel | final userId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String | try { - final result = api_instance.getActivities(albumId, assetId, type, userId); + final result = api_instance.getActivities(albumId, assetId, type, level, userId); print(result); } catch (e) { print('Exception when calling ActivityApi->getActivities: $e\n'); @@ -168,6 +169,7 @@ Name | Type | Description | Notes **albumId** | **String**| | **assetId** | **String**| | [optional] **type** | [**ReactionType**](.md)| | [optional] + **level** | [**ReactionLevel**](.md)| | [optional] **userId** | **String**| | [optional] ### Return type diff --git a/mobile/openapi/doc/ReactionLevel.md b/mobile/openapi/doc/ReactionLevel.md new file mode 100644 index 0000000000..a53955cb0a --- /dev/null +++ b/mobile/openapi/doc/ReactionLevel.md @@ -0,0 +1,14 @@ +# openapi.model.ReactionLevel + +## Load the model package +```dart +import 'package:openapi/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/mobile/openapi/lib/api.dart b/mobile/openapi/lib/api.dart index 4d6bd8c411..7e4ed3a7b0 100644 --- a/mobile/openapi/lib/api.dart +++ b/mobile/openapi/lib/api.dart @@ -133,6 +133,7 @@ part 'model/person_response_dto.dart'; part 'model/person_statistics_response_dto.dart'; part 'model/person_update_dto.dart'; part 'model/queue_status_dto.dart'; +part 'model/reaction_level.dart'; part 'model/reaction_type.dart'; part 'model/recognition_config.dart'; part 'model/scan_library_dto.dart'; diff --git a/mobile/openapi/lib/api/activity_api.dart b/mobile/openapi/lib/api/activity_api.dart index 458538a5d2..8e2354e201 100644 --- a/mobile/openapi/lib/api/activity_api.dart +++ b/mobile/openapi/lib/api/activity_api.dart @@ -112,8 +112,10 @@ class ActivityApi { /// /// * [ReactionType] type: /// + /// * [ReactionLevel] level: + /// /// * [String] userId: - Future getActivitiesWithHttpInfo(String albumId, { String? assetId, ReactionType? type, String? userId, }) async { + Future getActivitiesWithHttpInfo(String albumId, { String? assetId, ReactionType? type, ReactionLevel? level, String? userId, }) async { // ignore: prefer_const_declarations final path = r'/activity'; @@ -131,6 +133,9 @@ class ActivityApi { if (type != null) { queryParams.addAll(_queryParams('', 'type', type)); } + if (level != null) { + queryParams.addAll(_queryParams('', 'level', level)); + } if (userId != null) { queryParams.addAll(_queryParams('', 'userId', userId)); } @@ -157,9 +162,11 @@ class ActivityApi { /// /// * [ReactionType] type: /// + /// * [ReactionLevel] level: + /// /// * [String] userId: - Future?> getActivities(String albumId, { String? assetId, ReactionType? type, String? userId, }) async { - final response = await getActivitiesWithHttpInfo(albumId, assetId: assetId, type: type, userId: userId, ); + Future?> getActivities(String albumId, { String? assetId, ReactionType? type, ReactionLevel? level, String? userId, }) async { + final response = await getActivitiesWithHttpInfo(albumId, assetId: assetId, type: type, level: level, userId: userId, ); if (response.statusCode >= HttpStatus.badRequest) { throw ApiException(response.statusCode, await _decodeBodyBytes(response)); } diff --git a/mobile/openapi/lib/api_client.dart b/mobile/openapi/lib/api_client.dart index e3b881ccdc..dfdd5b4efe 100644 --- a/mobile/openapi/lib/api_client.dart +++ b/mobile/openapi/lib/api_client.dart @@ -355,6 +355,8 @@ class ApiClient { return PersonUpdateDto.fromJson(value); case 'QueueStatusDto': return QueueStatusDto.fromJson(value); + case 'ReactionLevel': + return ReactionLevelTypeTransformer().decode(value); case 'ReactionType': return ReactionTypeTypeTransformer().decode(value); case 'RecognitionConfig': diff --git a/mobile/openapi/lib/api_helper.dart b/mobile/openapi/lib/api_helper.dart index 632069e8c7..f391314482 100644 --- a/mobile/openapi/lib/api_helper.dart +++ b/mobile/openapi/lib/api_helper.dart @@ -100,6 +100,9 @@ String parameterToString(dynamic value) { if (value is PathType) { return PathTypeTypeTransformer().encode(value).toString(); } + if (value is ReactionLevel) { + return ReactionLevelTypeTransformer().encode(value).toString(); + } if (value is ReactionType) { return ReactionTypeTypeTransformer().encode(value).toString(); } diff --git a/mobile/openapi/lib/model/reaction_level.dart b/mobile/openapi/lib/model/reaction_level.dart new file mode 100644 index 0000000000..5c8b8e62b1 --- /dev/null +++ b/mobile/openapi/lib/model/reaction_level.dart @@ -0,0 +1,85 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + + +class ReactionLevel { + /// Instantiate a new enum with the provided [value]. + const ReactionLevel._(this.value); + + /// The underlying value of this enum member. + final String value; + + @override + String toString() => value; + + String toJson() => value; + + static const album = ReactionLevel._(r'album'); + static const asset = ReactionLevel._(r'asset'); + + /// List of all possible values in this [enum][ReactionLevel]. + static const values = [ + album, + asset, + ]; + + static ReactionLevel? fromJson(dynamic value) => ReactionLevelTypeTransformer().decode(value); + + static List? listFromJson(dynamic json, {bool growable = false,}) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = ReactionLevel.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } +} + +/// Transformation class that can [encode] an instance of [ReactionLevel] to String, +/// and [decode] dynamic data back to [ReactionLevel]. +class ReactionLevelTypeTransformer { + factory ReactionLevelTypeTransformer() => _instance ??= const ReactionLevelTypeTransformer._(); + + const ReactionLevelTypeTransformer._(); + + String encode(ReactionLevel data) => data.value; + + /// Decodes a [dynamic value][data] to a ReactionLevel. + /// + /// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully, + /// then null is returned. However, if [allowNull] is false and the [dynamic value][data] + /// cannot be decoded successfully, then an [UnimplementedError] is thrown. + /// + /// The [allowNull] is very handy when an API changes and a new enum value is added or removed, + /// and users are still using an old app with the old code. + ReactionLevel? decode(dynamic data, {bool allowNull = true}) { + if (data != null) { + switch (data) { + case r'album': return ReactionLevel.album; + case r'asset': return ReactionLevel.asset; + default: + if (!allowNull) { + throw ArgumentError('Unknown enum value to decode: $data'); + } + } + } + return null; + } + + /// Singleton [ReactionLevelTypeTransformer] instance. + static ReactionLevelTypeTransformer? _instance; +} + diff --git a/mobile/openapi/test/activity_api_test.dart b/mobile/openapi/test/activity_api_test.dart index 9b6fe1a6ca..7353c6ea35 100644 --- a/mobile/openapi/test/activity_api_test.dart +++ b/mobile/openapi/test/activity_api_test.dart @@ -27,7 +27,7 @@ void main() { // TODO }); - //Future> getActivities(String albumId, { String assetId, ReactionType type, String userId }) async + //Future> getActivities(String albumId, { String assetId, ReactionType type, ReactionLevel level, String userId }) async test('test getActivities', () async { // TODO }); diff --git a/mobile/openapi/test/reaction_level_test.dart b/mobile/openapi/test/reaction_level_test.dart new file mode 100644 index 0000000000..6fcba58b1a --- /dev/null +++ b/mobile/openapi/test/reaction_level_test.dart @@ -0,0 +1,21 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.12 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +import 'package:openapi/api.dart'; +import 'package:test/test.dart'; + +// tests for ReactionLevel +void main() { + + group('test ReactionLevel', () { + + }); + +} diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json index 53d1e962e9..193586cbd4 100644 --- a/server/immich-openapi-specs.json +++ b/server/immich-openapi-specs.json @@ -31,6 +31,14 @@ "$ref": "#/components/schemas/ReactionType" } }, + { + "name": "level", + "required": false, + "in": "query", + "schema": { + "$ref": "#/components/schemas/ReactionLevel" + } + }, { "name": "userId", "required": false, @@ -7728,6 +7736,13 @@ ], "type": "object" }, + "ReactionLevel": { + "enum": [ + "album", + "asset" + ], + "type": "string" + }, "ReactionType": { "enum": [ "comment", diff --git a/server/src/domain/activity/activity.dto.ts b/server/src/domain/activity/activity.dto.ts index e1a163b814..a5a5bd3dfd 100644 --- a/server/src/domain/activity/activity.dto.ts +++ b/server/src/domain/activity/activity.dto.ts @@ -9,6 +9,11 @@ export enum ReactionType { LIKE = 'like', } +export enum ReactionLevel { + ALBUM = 'album', + ASSET = 'asset', +} + export type MaybeDuplicate = { duplicate: boolean; value: T }; export class ActivityResponseDto { @@ -39,6 +44,11 @@ export class ActivitySearchDto extends ActivityDto { @ApiProperty({ enumName: 'ReactionType', enum: ReactionType }) type?: ReactionType; + @IsEnum(ReactionLevel) + @Optional() + @ApiProperty({ enumName: 'ReactionLevel', enum: ReactionLevel }) + level?: ReactionLevel; + @ValidateUUID({ optional: true }) userId?: string; } diff --git a/server/src/domain/activity/activity.service.ts b/server/src/domain/activity/activity.service.ts index 44362f3fc0..8b601558df 100644 --- a/server/src/domain/activity/activity.service.ts +++ b/server/src/domain/activity/activity.service.ts @@ -10,6 +10,7 @@ import { ActivitySearchDto, ActivityStatisticsResponseDto, MaybeDuplicate, + ReactionLevel, ReactionType, mapActivity, } from './activity.dto'; @@ -30,7 +31,7 @@ export class ActivityService { const activities = await this.repository.search({ userId: dto.userId, albumId: dto.albumId, - assetId: dto.assetId, + assetId: dto.level === ReactionLevel.ALBUM ? null : dto.assetId, isLiked: dto.type && dto.type === ReactionType.LIKE, }); @@ -54,11 +55,12 @@ export class ActivityService { let activity: ActivityEntity | null = null; let duplicate = false; - if (dto.type === 'like') { + if (dto.type === ReactionType.LIKE) { delete dto.comment; [activity] = await this.repository.search({ ...common, - isGlobal: !dto.assetId, + // `null` will search for an album like + assetId: dto.assetId ?? null, isLiked: true, }); duplicate = !!activity; diff --git a/server/src/infra/repositories/activity.repository.ts b/server/src/infra/repositories/activity.repository.ts index 138d963815..25fd5fa7ac 100644 --- a/server/src/infra/repositories/activity.repository.ts +++ b/server/src/infra/repositories/activity.repository.ts @@ -6,10 +6,9 @@ import { ActivityEntity } from '../entities/activity.entity'; export interface ActivitySearch { albumId?: string; - assetId?: string; + assetId?: string | null; userId?: string; isLiked?: boolean; - isGlobal?: boolean; } @Injectable() @@ -17,11 +16,11 @@ export class ActivityRepository implements IActivityRepository { constructor(@InjectRepository(ActivityEntity) private repository: Repository) {} search(options: ActivitySearch): Promise { - const { userId, assetId, albumId, isLiked, isGlobal } = options; + const { userId, assetId, albumId, isLiked } = options; return this.repository.find({ where: { userId, - assetId: isGlobal ? IsNull() : assetId, + assetId: assetId === null ? IsNull() : assetId, albumId, isLiked, }, diff --git a/server/test/e2e/activity.e2e-spec.ts b/server/test/e2e/activity.e2e-spec.ts index 5cc86fc6aa..0bb8aa2c9a 100644 --- a/server/test/e2e/activity.e2e-spec.ts +++ b/server/test/e2e/activity.e2e-spec.ts @@ -247,6 +247,20 @@ describe(`${ActivityController.name} (e2e)`, () => { expect(body).toEqual(reaction); }); + it('should not confuse an album like with an asset like', async () => { + const reaction = await api.activityApi.create(server, admin.accessToken, { + albumId: album.id, + assetId: asset.id, + type: ReactionType.LIKE, + }); + const { status, body } = await request(server) + .post('/activity') + .set('Authorization', `Bearer ${admin.accessToken}`) + .send({ albumId: album.id, type: 'like' }); + expect(status).toEqual(201); + expect(body.id).not.toEqual(reaction.id); + }); + it('should add a comment to an asset', async () => { const { status, body } = await request(server) .post('/activity') diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts index 5bcfe0f078..798d388d7b 100644 --- a/web/src/api/open-api/api.ts +++ b/web/src/api/open-api/api.ts @@ -2570,6 +2570,20 @@ export interface QueueStatusDto { */ 'isPaused': boolean; } +/** + * + * @export + * @enum {string} + */ + +export const ReactionLevel = { + Album: 'album', + Asset: 'asset' +} as const; + +export type ReactionLevel = typeof ReactionLevel[keyof typeof ReactionLevel]; + + /** * * @export @@ -5065,11 +5079,12 @@ export const ActivityApiAxiosParamCreator = function (configuration?: Configurat * @param {string} albumId * @param {string} [assetId] * @param {ReactionType} [type] + * @param {ReactionLevel} [level] * @param {string} [userId] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getActivities: async (albumId: string, assetId?: string, type?: ReactionType, userId?: string, options: AxiosRequestConfig = {}): Promise => { + getActivities: async (albumId: string, assetId?: string, type?: ReactionType, level?: ReactionLevel, userId?: string, options: AxiosRequestConfig = {}): Promise => { // verify required parameter 'albumId' is not null or undefined assertParamExists('getActivities', 'albumId', albumId) const localVarPath = `/activity`; @@ -5105,6 +5120,10 @@ export const ActivityApiAxiosParamCreator = function (configuration?: Configurat localVarQueryParameter['type'] = type; } + if (level !== undefined) { + localVarQueryParameter['level'] = level; + } + if (userId !== undefined) { localVarQueryParameter['userId'] = userId; } @@ -5205,12 +5224,13 @@ export const ActivityApiFp = function(configuration?: Configuration) { * @param {string} albumId * @param {string} [assetId] * @param {ReactionType} [type] + * @param {ReactionLevel} [level] * @param {string} [userId] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getActivities(albumId: string, assetId?: string, type?: ReactionType, userId?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getActivities(albumId, assetId, type, userId, options); + async getActivities(albumId: string, assetId?: string, type?: ReactionType, level?: ReactionLevel, userId?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getActivities(albumId, assetId, type, level, userId, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** @@ -5259,7 +5279,7 @@ export const ActivityApiFactory = function (configuration?: Configuration, baseP * @throws {RequiredError} */ getActivities(requestParameters: ActivityApiGetActivitiesRequest, options?: AxiosRequestConfig): AxiosPromise> { - return localVarFp.getActivities(requestParameters.albumId, requestParameters.assetId, requestParameters.type, requestParameters.userId, options).then((request) => request(axios, basePath)); + return localVarFp.getActivities(requestParameters.albumId, requestParameters.assetId, requestParameters.type, requestParameters.level, requestParameters.userId, options).then((request) => request(axios, basePath)); }, /** * @@ -5328,6 +5348,13 @@ export interface ActivityApiGetActivitiesRequest { */ readonly type?: ReactionType + /** + * + * @type {ReactionLevel} + * @memberof ActivityApiGetActivities + */ + readonly level?: ReactionLevel + /** * * @type {string} @@ -5394,7 +5421,7 @@ export class ActivityApi extends BaseAPI { * @memberof ActivityApi */ public getActivities(requestParameters: ActivityApiGetActivitiesRequest, options?: AxiosRequestConfig) { - return ActivityApiFp(this.configuration).getActivities(requestParameters.albumId, requestParameters.assetId, requestParameters.type, requestParameters.userId, options).then((request) => request(this.axios, this.basePath)); + return ActivityApiFp(this.configuration).getActivities(requestParameters.albumId, requestParameters.assetId, requestParameters.type, requestParameters.level, requestParameters.userId, options).then((request) => request(this.axios, this.basePath)); } /** diff --git a/web/src/lib/components/asset-viewer/activity-viewer.svelte b/web/src/lib/components/asset-viewer/activity-viewer.svelte index dfe285b3eb..f8663ecebc 100644 --- a/web/src/lib/components/asset-viewer/activity-viewer.svelte +++ b/web/src/lib/components/asset-viewer/activity-viewer.svelte @@ -39,6 +39,7 @@ export let assetType: AssetTypeEnum | undefined = undefined; export let albumOwnerId: string; export let disabled: boolean; + export let isLiked: ActivityResponseDto | null; let textArea: HTMLTextAreaElement; let innerHeight: number; @@ -105,7 +106,7 @@ reactions.splice(index, 1); showDeleteReaction.splice(index, 1); reactions = reactions; - if (reaction.type === 'like' && reaction.user.id === user.id) { + if (isLiked && reaction.type === 'like' && reaction.id == isLiked.id) { dispatch('deleteLike'); } else { dispatch('deleteComment'); diff --git a/web/src/lib/components/asset-viewer/asset-viewer.svelte b/web/src/lib/components/asset-viewer/asset-viewer.svelte index 86a86c9aec..0194596f6a 100644 --- a/web/src/lib/components/asset-viewer/asset-viewer.svelte +++ b/web/src/lib/components/asset-viewer/asset-viewer.svelte @@ -756,6 +756,7 @@ albumOwnerId={album.ownerId} albumId={album.id} assetId={asset.id} + {isLiked} bind:reactions on:addComment={handleAddComment} on:deleteComment={handleRemoveComment} diff --git a/web/src/routes/(user)/albums/[albumId]/+page.svelte b/web/src/routes/(user)/albums/[albumId]/+page.svelte index 5525156bf5..09eb66e95f 100644 --- a/web/src/routes/(user)/albums/[albumId]/+page.svelte +++ b/web/src/routes/(user)/albums/[albumId]/+page.svelte @@ -35,7 +35,7 @@ import { downloadArchive } from '$lib/utils/asset-utils'; import { openFileUploadDialog } from '$lib/utils/file-uploader'; import { handleError } from '$lib/utils/handle-error'; - import { ActivityResponseDto, ReactionType, UserResponseDto, api } from '@api'; + import { ActivityResponseDto, ReactionLevel, ReactionType, UserResponseDto, api } from '@api'; import Icon from '$lib/components/elements/icon.svelte'; import type { PageData } from './$types'; import { clickOutside } from '$lib/utils/click-outside'; @@ -167,7 +167,6 @@ const { data } = await api.activityApi.createActivity({ activityCreateDto: { albumId: album.id, type: ReactionType.Like }, }); - isLiked = data; reactions = [...reactions, isLiked]; } @@ -183,6 +182,7 @@ userId: user.id, albumId: album.id, type: ReactionType.Like, + level: ReactionLevel.Album, }); if (data.length > 0) { isLiked = data[0]; @@ -687,6 +687,7 @@ disabled={!album.isActivityEnabled} albumOwnerId={album.ownerId} albumId={album.id} + {isLiked} bind:reactions on:addComment={() => updateNumberOfComments(1)} on:deleteComment={() => updateNumberOfComments(-1)}