mirror of
https://github.com/immich-app/immich.git
synced 2025-05-24 01:12:58 -04:00
chore: remove old memory lane implementation (#18000)
This commit is contained in:
parent
1fde02ee1e
commit
b845184c80
2
mobile/openapi/README.md
generated
2
mobile/openapi/README.md
generated
@ -100,7 +100,6 @@ Class | Method | HTTP request | Description
|
||||
*AssetsApi* | [**getAllUserAssetsByDeviceId**](doc//AssetsApi.md#getalluserassetsbydeviceid) | **GET** /assets/device/{deviceId} | getAllUserAssetsByDeviceId
|
||||
*AssetsApi* | [**getAssetInfo**](doc//AssetsApi.md#getassetinfo) | **GET** /assets/{id} |
|
||||
*AssetsApi* | [**getAssetStatistics**](doc//AssetsApi.md#getassetstatistics) | **GET** /assets/statistics |
|
||||
*AssetsApi* | [**getMemoryLane**](doc//AssetsApi.md#getmemorylane) | **GET** /assets/memory-lane |
|
||||
*AssetsApi* | [**getRandom**](doc//AssetsApi.md#getrandom) | **GET** /assets/random |
|
||||
*AssetsApi* | [**playAssetVideo**](doc//AssetsApi.md#playassetvideo) | **GET** /assets/{id}/video/playback |
|
||||
*AssetsApi* | [**replaceAsset**](doc//AssetsApi.md#replaceasset) | **PUT** /assets/{id}/original | replaceAsset
|
||||
@ -353,7 +352,6 @@ Class | Method | HTTP request | Description
|
||||
- [MemoriesResponse](doc//MemoriesResponse.md)
|
||||
- [MemoriesUpdate](doc//MemoriesUpdate.md)
|
||||
- [MemoryCreateDto](doc//MemoryCreateDto.md)
|
||||
- [MemoryLaneResponseDto](doc//MemoryLaneResponseDto.md)
|
||||
- [MemoryResponseDto](doc//MemoryResponseDto.md)
|
||||
- [MemoryType](doc//MemoryType.md)
|
||||
- [MemoryUpdateDto](doc//MemoryUpdateDto.md)
|
||||
|
1
mobile/openapi/lib/api.dart
generated
1
mobile/openapi/lib/api.dart
generated
@ -156,7 +156,6 @@ part 'model/map_reverse_geocode_response_dto.dart';
|
||||
part 'model/memories_response.dart';
|
||||
part 'model/memories_update.dart';
|
||||
part 'model/memory_create_dto.dart';
|
||||
part 'model/memory_lane_response_dto.dart';
|
||||
part 'model/memory_response_dto.dart';
|
||||
part 'model/memory_type.dart';
|
||||
part 'model/memory_update_dto.dart';
|
||||
|
57
mobile/openapi/lib/api/assets_api.dart
generated
57
mobile/openapi/lib/api/assets_api.dart
generated
@ -404,63 +404,6 @@ class AssetsApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'GET /assets/memory-lane' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [int] day (required):
|
||||
///
|
||||
/// * [int] month (required):
|
||||
Future<Response> getMemoryLaneWithHttpInfo(int day, int month,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final apiPath = r'/assets/memory-lane';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
queryParams.addAll(_queryParams('', 'day', day));
|
||||
queryParams.addAll(_queryParams('', 'month', month));
|
||||
|
||||
const contentTypes = <String>[];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
apiPath,
|
||||
'GET',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [int] day (required):
|
||||
///
|
||||
/// * [int] month (required):
|
||||
Future<List<MemoryLaneResponseDto>?> getMemoryLane(int day, int month,) async {
|
||||
final response = await getMemoryLaneWithHttpInfo(day, month,);
|
||||
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) {
|
||||
final responseBody = await _decodeBodyBytes(response);
|
||||
return (await apiClient.deserializeAsync(responseBody, 'List<MemoryLaneResponseDto>') as List)
|
||||
.cast<MemoryLaneResponseDto>()
|
||||
.toList(growable: false);
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// This property was deprecated in v1.116.0
|
||||
///
|
||||
/// Note: This method returns the HTTP [Response].
|
||||
|
2
mobile/openapi/lib/api_client.dart
generated
2
mobile/openapi/lib/api_client.dart
generated
@ -368,8 +368,6 @@ class ApiClient {
|
||||
return MemoriesUpdate.fromJson(value);
|
||||
case 'MemoryCreateDto':
|
||||
return MemoryCreateDto.fromJson(value);
|
||||
case 'MemoryLaneResponseDto':
|
||||
return MemoryLaneResponseDto.fromJson(value);
|
||||
case 'MemoryResponseDto':
|
||||
return MemoryResponseDto.fromJson(value);
|
||||
case 'MemoryType':
|
||||
|
107
mobile/openapi/lib/model/memory_lane_response_dto.dart
generated
107
mobile/openapi/lib/model/memory_lane_response_dto.dart
generated
@ -1,107 +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 MemoryLaneResponseDto {
|
||||
/// Returns a new [MemoryLaneResponseDto] instance.
|
||||
MemoryLaneResponseDto({
|
||||
this.assets = const [],
|
||||
required this.yearsAgo,
|
||||
});
|
||||
|
||||
List<AssetResponseDto> assets;
|
||||
|
||||
int yearsAgo;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is MemoryLaneResponseDto &&
|
||||
_deepEquality.equals(other.assets, assets) &&
|
||||
other.yearsAgo == yearsAgo;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(assets.hashCode) +
|
||||
(yearsAgo.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'MemoryLaneResponseDto[assets=$assets, yearsAgo=$yearsAgo]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'assets'] = this.assets;
|
||||
json[r'yearsAgo'] = this.yearsAgo;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [MemoryLaneResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static MemoryLaneResponseDto? fromJson(dynamic value) {
|
||||
upgradeDto(value, "MemoryLaneResponseDto");
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return MemoryLaneResponseDto(
|
||||
assets: AssetResponseDto.listFromJson(json[r'assets']),
|
||||
yearsAgo: mapValueOfType<int>(json, r'yearsAgo')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<MemoryLaneResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <MemoryLaneResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = MemoryLaneResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, MemoryLaneResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, MemoryLaneResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = MemoryLaneResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of MemoryLaneResponseDto-objects as value to a dart map
|
||||
static Map<String, List<MemoryLaneResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<MemoryLaneResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = MemoryLaneResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'assets',
|
||||
'yearsAgo',
|
||||
};
|
||||
}
|
||||
|
@ -1726,62 +1726,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/assets/memory-lane": {
|
||||
"get": {
|
||||
"operationId": "getMemoryLane",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "day",
|
||||
"required": true,
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"minimum": 1,
|
||||
"maximum": 31,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "month",
|
||||
"required": true,
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"minimum": 1,
|
||||
"maximum": 12,
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/MemoryLaneResponseDto"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Assets"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/assets/random": {
|
||||
"get": {
|
||||
"deprecated": true,
|
||||
@ -10117,24 +10061,6 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MemoryLaneResponseDto": {
|
||||
"properties": {
|
||||
"assets": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/AssetResponseDto"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"yearsAgo": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"assets",
|
||||
"yearsAgo"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"MemoryResponseDto": {
|
||||
"properties": {
|
||||
"assets": {
|
||||
|
@ -462,10 +462,6 @@ export type AssetJobsDto = {
|
||||
assetIds: string[];
|
||||
name: AssetJobName;
|
||||
};
|
||||
export type MemoryLaneResponseDto = {
|
||||
assets: AssetResponseDto[];
|
||||
yearsAgo: number;
|
||||
};
|
||||
export type AssetStatsResponseDto = {
|
||||
images: number;
|
||||
total: number;
|
||||
@ -1866,20 +1862,6 @@ export function runAssetJobs({ assetJobsDto }: {
|
||||
body: assetJobsDto
|
||||
})));
|
||||
}
|
||||
export function getMemoryLane({ day, month }: {
|
||||
day: number;
|
||||
month: number;
|
||||
}, opts?: Oazapfts.RequestOpts) {
|
||||
return oazapfts.ok(oazapfts.fetchJson<{
|
||||
status: 200;
|
||||
data: MemoryLaneResponseDto[];
|
||||
}>(`/assets/memory-lane${QS.query(QS.explode({
|
||||
day,
|
||||
month
|
||||
}))}`, {
|
||||
...opts
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* This property was deprecated in v1.116.0
|
||||
*/
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common';
|
||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { EndpointLifecycle } from 'src/decorators';
|
||||
import { AssetResponseDto, MemoryLaneResponseDto } from 'src/dtos/asset-response.dto';
|
||||
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
|
||||
import {
|
||||
AssetBulkDeleteDto,
|
||||
AssetBulkUpdateDto,
|
||||
@ -13,7 +13,6 @@ import {
|
||||
UpdateAssetDto,
|
||||
} from 'src/dtos/asset.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { MemoryLaneDto } from 'src/dtos/search.dto';
|
||||
import { RouteKey } from 'src/enum';
|
||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||
import { AssetService } from 'src/services/asset.service';
|
||||
@ -24,12 +23,6 @@ import { UUIDParamDto } from 'src/validation';
|
||||
export class AssetController {
|
||||
constructor(private service: AssetService) {}
|
||||
|
||||
@Get('memory-lane')
|
||||
@Authenticated()
|
||||
getMemoryLane(@Auth() auth: AuthDto, @Query() dto: MemoryLaneDto): Promise<MemoryLaneResponseDto[]> {
|
||||
return this.service.getMemoryLane(auth, dto);
|
||||
}
|
||||
|
||||
@Get('random')
|
||||
@Authenticated()
|
||||
@EndpointLifecycle({ deprecatedAt: 'v1.116.0' })
|
||||
|
@ -199,10 +199,3 @@ export function mapAsset(entity: MapAsset, options: AssetMapOptions = {}): Asset
|
||||
resized: true,
|
||||
};
|
||||
}
|
||||
|
||||
export class MemoryLaneResponseDto {
|
||||
@ApiProperty({ type: 'integer' })
|
||||
yearsAgo!: number;
|
||||
|
||||
assets!: AssetResponseDto[];
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
import { DateTime } from 'luxon';
|
||||
import { MapAsset, mapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { MapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { AssetJobName, AssetStatsResponseDto } from 'src/dtos/asset.dto';
|
||||
import { AssetStatus, AssetType, JobName, JobStatus } from 'src/enum';
|
||||
import { AssetStats } from 'src/repositories/asset.repository';
|
||||
@ -11,7 +11,6 @@ import { faceStub } from 'test/fixtures/face.stub';
|
||||
import { userStub } from 'test/fixtures/user.stub';
|
||||
import { factory } from 'test/small.factory';
|
||||
import { makeStream, newTestService, ServiceMocks } from 'test/utils';
|
||||
import { vitest } from 'vitest';
|
||||
|
||||
const stats: AssetStats = {
|
||||
[AssetType.IMAGE]: 10,
|
||||
@ -44,62 +43,6 @@ describe(AssetService.name, () => {
|
||||
mockGetById([assetStub.livePhotoStillAsset, assetStub.livePhotoMotionAsset]);
|
||||
});
|
||||
|
||||
describe('getMemoryLane', () => {
|
||||
beforeAll(() => {
|
||||
vitest.useFakeTimers();
|
||||
vitest.setSystemTime(new Date('2024-01-15'));
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
vitest.useRealTimers();
|
||||
});
|
||||
|
||||
it('should group the assets correctly', async () => {
|
||||
const image1 = { ...assetStub.image, localDateTime: new Date(2023, 1, 15, 0, 0, 0) };
|
||||
const image2 = { ...assetStub.image, localDateTime: new Date(2023, 1, 15, 1, 0, 0) };
|
||||
const image3 = { ...assetStub.image, localDateTime: new Date(2015, 1, 15) };
|
||||
const image4 = { ...assetStub.image, localDateTime: new Date(2009, 1, 15) };
|
||||
|
||||
mocks.partner.getAll.mockResolvedValue([]);
|
||||
mocks.asset.getByDayOfYear.mockResolvedValue([
|
||||
{
|
||||
year: 2023,
|
||||
assets: [image1, image2],
|
||||
},
|
||||
{
|
||||
year: 2015,
|
||||
assets: [image3],
|
||||
},
|
||||
{
|
||||
year: 2009,
|
||||
assets: [image4],
|
||||
},
|
||||
] as any);
|
||||
|
||||
await expect(sut.getMemoryLane(authStub.admin, { day: 15, month: 1 })).resolves.toEqual([
|
||||
{ yearsAgo: 1, title: '1 year ago', assets: [mapAsset(image1), mapAsset(image2)] },
|
||||
{ yearsAgo: 9, title: '9 years ago', assets: [mapAsset(image3)] },
|
||||
{ yearsAgo: 15, title: '15 years ago', assets: [mapAsset(image4)] },
|
||||
]);
|
||||
|
||||
expect(mocks.asset.getByDayOfYear.mock.calls).toEqual([[[authStub.admin.user.id], { day: 15, month: 1 }]]);
|
||||
});
|
||||
|
||||
it('should get memories with partners with inTimeline enabled', async () => {
|
||||
const partner = factory.partner();
|
||||
const auth = factory.auth({ user: { id: partner.sharedWithId } });
|
||||
|
||||
mocks.partner.getAll.mockResolvedValue([partner]);
|
||||
mocks.asset.getByDayOfYear.mockResolvedValue([]);
|
||||
|
||||
await sut.getMemoryLane(auth, { day: 15, month: 1 });
|
||||
|
||||
expect(mocks.asset.getByDayOfYear.mock.calls).toEqual([
|
||||
[[auth.user.id, partner.sharedById], { day: 15, month: 1 }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getStatistics', () => {
|
||||
it('should get the statistics for a user, excluding archived assets', async () => {
|
||||
mocks.asset.getStatistics.mockResolvedValue(stats);
|
||||
|
@ -3,13 +3,7 @@ import _ from 'lodash';
|
||||
import { DateTime, Duration } from 'luxon';
|
||||
import { JOBS_ASSET_PAGINATION_SIZE } from 'src/constants';
|
||||
import { OnJob } from 'src/decorators';
|
||||
import {
|
||||
AssetResponseDto,
|
||||
MapAsset,
|
||||
MemoryLaneResponseDto,
|
||||
SanitizedAssetResponseDto,
|
||||
mapAsset,
|
||||
} from 'src/dtos/asset-response.dto';
|
||||
import { AssetResponseDto, MapAsset, SanitizedAssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
|
||||
import {
|
||||
AssetBulkDeleteDto,
|
||||
AssetBulkUpdateDto,
|
||||
@ -20,7 +14,6 @@ import {
|
||||
mapStats,
|
||||
} from 'src/dtos/asset.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { MemoryLaneDto } from 'src/dtos/search.dto';
|
||||
import { AssetStatus, JobName, JobStatus, Permission, QueueName } from 'src/enum';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { ISidecarWriteJob, JobItem, JobOf } from 'src/types';
|
||||
@ -28,26 +21,6 @@ import { getAssetFiles, getMyPartnerIds, onAfterUnlink, onBeforeLink, onBeforeUn
|
||||
|
||||
@Injectable()
|
||||
export class AssetService extends BaseService {
|
||||
async getMemoryLane(auth: AuthDto, dto: MemoryLaneDto): Promise<MemoryLaneResponseDto[]> {
|
||||
const partnerIds = await getMyPartnerIds({
|
||||
userId: auth.user.id,
|
||||
repository: this.partnerRepository,
|
||||
timelineEnabled: true,
|
||||
});
|
||||
const userIds = [auth.user.id, ...partnerIds];
|
||||
|
||||
const groups = await this.assetRepository.getByDayOfYear(userIds, dto);
|
||||
return groups.map(({ year, assets }) => {
|
||||
const yearsAgo = DateTime.utc().year - year;
|
||||
return {
|
||||
yearsAgo,
|
||||
// TODO move this to clients
|
||||
title: `${yearsAgo} year${yearsAgo > 1 ? 's' : ''} ago`,
|
||||
assets: assets.map((asset) => mapAsset(asset, { auth })),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async getStatistics(auth: AuthDto, dto: AssetStatsDto) {
|
||||
const stats = await this.assetRepository.getStatistics(auth.user.id, dto);
|
||||
return mapStats(stats);
|
||||
|
Loading…
x
Reference in New Issue
Block a user