feat: remove asset from memory
This commit is contained in:
parent
1890c0ab6b
commit
b9c0a3c641
19 changed files with 222 additions and 5 deletions
12
cli/src/api/open-api/api.ts
generated
12
cli/src/api/open-api/api.ts
generated
|
@ -399,6 +399,12 @@ export interface AssetBulkUpdateDto {
|
||||||
* @memberof AssetBulkUpdateDto
|
* @memberof AssetBulkUpdateDto
|
||||||
*/
|
*/
|
||||||
'isFavorite'?: boolean;
|
'isFavorite'?: boolean;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
* @memberof AssetBulkUpdateDto
|
||||||
|
*/
|
||||||
|
'isShownInMemory'?: boolean;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -682,6 +688,12 @@ export interface AssetResponseDto {
|
||||||
* @memberof AssetResponseDto
|
* @memberof AssetResponseDto
|
||||||
*/
|
*/
|
||||||
'isReadOnly': boolean;
|
'isReadOnly': boolean;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
* @memberof AssetResponseDto
|
||||||
|
*/
|
||||||
|
'isShownInMemory': boolean;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
|
|
1
mobile/openapi/doc/AssetBulkUpdateDto.md
generated
1
mobile/openapi/doc/AssetBulkUpdateDto.md
generated
|
@ -11,6 +11,7 @@ Name | Type | Description | Notes
|
||||||
**ids** | **List<String>** | | [default to const []]
|
**ids** | **List<String>** | | [default to const []]
|
||||||
**isArchived** | **bool** | | [optional]
|
**isArchived** | **bool** | | [optional]
|
||||||
**isFavorite** | **bool** | | [optional]
|
**isFavorite** | **bool** | | [optional]
|
||||||
|
**isShownInMemory** | **bool** | | [optional]
|
||||||
|
|
||||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
1
mobile/openapi/doc/AssetResponseDto.md
generated
1
mobile/openapi/doc/AssetResponseDto.md
generated
|
@ -22,6 +22,7 @@ Name | Type | Description | Notes
|
||||||
**isFavorite** | **bool** | |
|
**isFavorite** | **bool** | |
|
||||||
**isOffline** | **bool** | |
|
**isOffline** | **bool** | |
|
||||||
**isReadOnly** | **bool** | |
|
**isReadOnly** | **bool** | |
|
||||||
|
**isShownInMemory** | **bool** | |
|
||||||
**isTrashed** | **bool** | |
|
**isTrashed** | **bool** | |
|
||||||
**libraryId** | **String** | |
|
**libraryId** | **String** | |
|
||||||
**livePhotoVideoId** | **String** | | [optional]
|
**livePhotoVideoId** | **String** | | [optional]
|
||||||
|
|
23
mobile/openapi/lib/model/asset_bulk_update_dto.dart
generated
23
mobile/openapi/lib/model/asset_bulk_update_dto.dart
generated
|
@ -16,6 +16,7 @@ class AssetBulkUpdateDto {
|
||||||
this.ids = const [],
|
this.ids = const [],
|
||||||
this.isArchived,
|
this.isArchived,
|
||||||
this.isFavorite,
|
this.isFavorite,
|
||||||
|
this.isShownInMemory,
|
||||||
});
|
});
|
||||||
|
|
||||||
List<String> ids;
|
List<String> ids;
|
||||||
|
@ -36,21 +37,31 @@ class AssetBulkUpdateDto {
|
||||||
///
|
///
|
||||||
bool? isFavorite;
|
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? isShownInMemory;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is AssetBulkUpdateDto &&
|
bool operator ==(Object other) => identical(this, other) || other is AssetBulkUpdateDto &&
|
||||||
other.ids == ids &&
|
other.ids == ids &&
|
||||||
other.isArchived == isArchived &&
|
other.isArchived == isArchived &&
|
||||||
other.isFavorite == isFavorite;
|
other.isFavorite == isFavorite &&
|
||||||
|
other.isShownInMemory == isShownInMemory;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
(ids.hashCode) +
|
(ids.hashCode) +
|
||||||
(isArchived == null ? 0 : isArchived!.hashCode) +
|
(isArchived == null ? 0 : isArchived!.hashCode) +
|
||||||
(isFavorite == null ? 0 : isFavorite!.hashCode);
|
(isFavorite == null ? 0 : isFavorite!.hashCode) +
|
||||||
|
(isShownInMemory == null ? 0 : isShownInMemory!.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'AssetBulkUpdateDto[ids=$ids, isArchived=$isArchived, isFavorite=$isFavorite]';
|
String toString() => 'AssetBulkUpdateDto[ids=$ids, isArchived=$isArchived, isFavorite=$isFavorite, isShownInMemory=$isShownInMemory]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
|
@ -65,6 +76,11 @@ class AssetBulkUpdateDto {
|
||||||
} else {
|
} else {
|
||||||
// json[r'isFavorite'] = null;
|
// json[r'isFavorite'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.isShownInMemory != null) {
|
||||||
|
json[r'isShownInMemory'] = this.isShownInMemory;
|
||||||
|
} else {
|
||||||
|
// json[r'isShownInMemory'] = null;
|
||||||
|
}
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +97,7 @@ class AssetBulkUpdateDto {
|
||||||
: const [],
|
: const [],
|
||||||
isArchived: mapValueOfType<bool>(json, r'isArchived'),
|
isArchived: mapValueOfType<bool>(json, r'isArchived'),
|
||||||
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
|
||||||
|
isShownInMemory: mapValueOfType<bool>(json, r'isShownInMemory'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
10
mobile/openapi/lib/model/asset_response_dto.dart
generated
10
mobile/openapi/lib/model/asset_response_dto.dart
generated
|
@ -27,6 +27,7 @@ class AssetResponseDto {
|
||||||
required this.isFavorite,
|
required this.isFavorite,
|
||||||
required this.isOffline,
|
required this.isOffline,
|
||||||
required this.isReadOnly,
|
required this.isReadOnly,
|
||||||
|
required this.isShownInMemory,
|
||||||
required this.isTrashed,
|
required this.isTrashed,
|
||||||
required this.libraryId,
|
required this.libraryId,
|
||||||
this.livePhotoVideoId,
|
this.livePhotoVideoId,
|
||||||
|
@ -79,6 +80,8 @@ class AssetResponseDto {
|
||||||
|
|
||||||
bool isReadOnly;
|
bool isReadOnly;
|
||||||
|
|
||||||
|
bool isShownInMemory;
|
||||||
|
|
||||||
bool isTrashed;
|
bool isTrashed;
|
||||||
|
|
||||||
String libraryId;
|
String libraryId;
|
||||||
|
@ -137,6 +140,7 @@ class AssetResponseDto {
|
||||||
other.isFavorite == isFavorite &&
|
other.isFavorite == isFavorite &&
|
||||||
other.isOffline == isOffline &&
|
other.isOffline == isOffline &&
|
||||||
other.isReadOnly == isReadOnly &&
|
other.isReadOnly == isReadOnly &&
|
||||||
|
other.isShownInMemory == isShownInMemory &&
|
||||||
other.isTrashed == isTrashed &&
|
other.isTrashed == isTrashed &&
|
||||||
other.libraryId == libraryId &&
|
other.libraryId == libraryId &&
|
||||||
other.livePhotoVideoId == livePhotoVideoId &&
|
other.livePhotoVideoId == livePhotoVideoId &&
|
||||||
|
@ -170,6 +174,7 @@ class AssetResponseDto {
|
||||||
(isFavorite.hashCode) +
|
(isFavorite.hashCode) +
|
||||||
(isOffline.hashCode) +
|
(isOffline.hashCode) +
|
||||||
(isReadOnly.hashCode) +
|
(isReadOnly.hashCode) +
|
||||||
|
(isShownInMemory.hashCode) +
|
||||||
(isTrashed.hashCode) +
|
(isTrashed.hashCode) +
|
||||||
(libraryId.hashCode) +
|
(libraryId.hashCode) +
|
||||||
(livePhotoVideoId == null ? 0 : livePhotoVideoId!.hashCode) +
|
(livePhotoVideoId == null ? 0 : livePhotoVideoId!.hashCode) +
|
||||||
|
@ -187,7 +192,7 @@ class AssetResponseDto {
|
||||||
(updatedAt.hashCode);
|
(updatedAt.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'AssetResponseDto[checksum=$checksum, deviceAssetId=$deviceAssetId, deviceId=$deviceId, duration=$duration, exifInfo=$exifInfo, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, hasMetadata=$hasMetadata, id=$id, isArchived=$isArchived, isExternal=$isExternal, isFavorite=$isFavorite, isOffline=$isOffline, isReadOnly=$isReadOnly, isTrashed=$isTrashed, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, originalPath=$originalPath, owner=$owner, ownerId=$ownerId, people=$people, resized=$resized, smartInfo=$smartInfo, tags=$tags, thumbhash=$thumbhash, type=$type, updatedAt=$updatedAt]';
|
String toString() => 'AssetResponseDto[checksum=$checksum, deviceAssetId=$deviceAssetId, deviceId=$deviceId, duration=$duration, exifInfo=$exifInfo, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, hasMetadata=$hasMetadata, id=$id, isArchived=$isArchived, isExternal=$isExternal, isFavorite=$isFavorite, isOffline=$isOffline, isReadOnly=$isReadOnly, isShownInMemory=$isShownInMemory, isTrashed=$isTrashed, libraryId=$libraryId, livePhotoVideoId=$livePhotoVideoId, localDateTime=$localDateTime, originalFileName=$originalFileName, originalPath=$originalPath, owner=$owner, ownerId=$ownerId, people=$people, resized=$resized, smartInfo=$smartInfo, tags=$tags, thumbhash=$thumbhash, type=$type, updatedAt=$updatedAt]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
|
@ -209,6 +214,7 @@ class AssetResponseDto {
|
||||||
json[r'isFavorite'] = this.isFavorite;
|
json[r'isFavorite'] = this.isFavorite;
|
||||||
json[r'isOffline'] = this.isOffline;
|
json[r'isOffline'] = this.isOffline;
|
||||||
json[r'isReadOnly'] = this.isReadOnly;
|
json[r'isReadOnly'] = this.isReadOnly;
|
||||||
|
json[r'isShownInMemory'] = this.isShownInMemory;
|
||||||
json[r'isTrashed'] = this.isTrashed;
|
json[r'isTrashed'] = this.isTrashed;
|
||||||
json[r'libraryId'] = this.libraryId;
|
json[r'libraryId'] = this.libraryId;
|
||||||
if (this.livePhotoVideoId != null) {
|
if (this.livePhotoVideoId != null) {
|
||||||
|
@ -265,6 +271,7 @@ class AssetResponseDto {
|
||||||
isFavorite: mapValueOfType<bool>(json, r'isFavorite')!,
|
isFavorite: mapValueOfType<bool>(json, r'isFavorite')!,
|
||||||
isOffline: mapValueOfType<bool>(json, r'isOffline')!,
|
isOffline: mapValueOfType<bool>(json, r'isOffline')!,
|
||||||
isReadOnly: mapValueOfType<bool>(json, r'isReadOnly')!,
|
isReadOnly: mapValueOfType<bool>(json, r'isReadOnly')!,
|
||||||
|
isShownInMemory: mapValueOfType<bool>(json, r'isShownInMemory')!,
|
||||||
isTrashed: mapValueOfType<bool>(json, r'isTrashed')!,
|
isTrashed: mapValueOfType<bool>(json, r'isTrashed')!,
|
||||||
libraryId: mapValueOfType<String>(json, r'libraryId')!,
|
libraryId: mapValueOfType<String>(json, r'libraryId')!,
|
||||||
livePhotoVideoId: mapValueOfType<String>(json, r'livePhotoVideoId'),
|
livePhotoVideoId: mapValueOfType<String>(json, r'livePhotoVideoId'),
|
||||||
|
@ -340,6 +347,7 @@ class AssetResponseDto {
|
||||||
'isFavorite',
|
'isFavorite',
|
||||||
'isOffline',
|
'isOffline',
|
||||||
'isReadOnly',
|
'isReadOnly',
|
||||||
|
'isShownInMemory',
|
||||||
'isTrashed',
|
'isTrashed',
|
||||||
'libraryId',
|
'libraryId',
|
||||||
'localDateTime',
|
'localDateTime',
|
||||||
|
|
|
@ -31,6 +31,11 @@ void main() {
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// bool isShownInMemory
|
||||||
|
test('to test the property `isShownInMemory`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
5
mobile/openapi/test/asset_response_dto_test.dart
generated
5
mobile/openapi/test/asset_response_dto_test.dart
generated
|
@ -87,6 +87,11 @@ void main() {
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// bool isShownInMemory
|
||||||
|
test('to test the property `isShownInMemory`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
// bool isTrashed
|
// bool isTrashed
|
||||||
test('to test the property `isTrashed`', () async {
|
test('to test the property `isTrashed`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
|
|
|
@ -5696,6 +5696,9 @@
|
||||||
},
|
},
|
||||||
"isFavorite": {
|
"isFavorite": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isShownInMemory": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
@ -5903,6 +5906,9 @@
|
||||||
"isReadOnly": {
|
"isReadOnly": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"isShownInMemory": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"isTrashed": {
|
"isTrashed": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
@ -5971,6 +5977,7 @@
|
||||||
"fileCreatedAt",
|
"fileCreatedAt",
|
||||||
"fileModifiedAt",
|
"fileModifiedAt",
|
||||||
"updatedAt",
|
"updatedAt",
|
||||||
|
"isShownInMemory",
|
||||||
"isFavorite",
|
"isFavorite",
|
||||||
"isArchived",
|
"isArchived",
|
||||||
"isTrashed",
|
"isTrashed",
|
||||||
|
|
|
@ -165,7 +165,7 @@ export class AssetService {
|
||||||
const assets = await this.assetRepository.getByDayOfYear(authUser.id, dto);
|
const assets = await this.assetRepository.getByDayOfYear(authUser.id, dto);
|
||||||
|
|
||||||
return _.chain(assets)
|
return _.chain(assets)
|
||||||
.filter((asset) => asset.localDateTime.getFullYear() < currentYear)
|
.filter((asset) => asset.localDateTime.getFullYear() < currentYear && asset.isShownInMemory)
|
||||||
.map((asset) => {
|
.map((asset) => {
|
||||||
const years = currentYear - asset.localDateTime.getFullYear();
|
const years = currentYear - asset.localDateTime.getFullYear();
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,10 @@ export class AssetBulkUpdateDto extends BulkIdsDto {
|
||||||
@Optional()
|
@Optional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
|
|
||||||
|
@Optional()
|
||||||
|
@IsBoolean()
|
||||||
|
isShownInMemory?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UpdateAssetDto {
|
export class UpdateAssetDto {
|
||||||
|
|
|
@ -30,6 +30,7 @@ export class AssetResponseDto extends SanitizedAssetResponseDto {
|
||||||
fileCreatedAt!: Date;
|
fileCreatedAt!: Date;
|
||||||
fileModifiedAt!: Date;
|
fileModifiedAt!: Date;
|
||||||
updatedAt!: Date;
|
updatedAt!: Date;
|
||||||
|
isShownInMemory!: boolean;
|
||||||
isFavorite!: boolean;
|
isFavorite!: boolean;
|
||||||
isArchived!: boolean;
|
isArchived!: boolean;
|
||||||
isTrashed!: boolean;
|
isTrashed!: boolean;
|
||||||
|
@ -77,6 +78,7 @@ export function mapAsset(entity: AssetEntity, stripMetadata = false): AssetRespo
|
||||||
fileModifiedAt: entity.fileModifiedAt,
|
fileModifiedAt: entity.fileModifiedAt,
|
||||||
localDateTime: entity.localDateTime,
|
localDateTime: entity.localDateTime,
|
||||||
updatedAt: entity.updatedAt,
|
updatedAt: entity.updatedAt,
|
||||||
|
isShownInMemory: entity.isShownInMemory,
|
||||||
isFavorite: entity.isFavorite,
|
isFavorite: entity.isFavorite,
|
||||||
isArchived: entity.isArchived,
|
isArchived: entity.isArchived,
|
||||||
isTrashed: !!entity.deletedAt,
|
isTrashed: !!entity.deletedAt,
|
||||||
|
|
|
@ -106,6 +106,9 @@ export class AssetEntity {
|
||||||
@Column({ type: 'boolean', default: false })
|
@Column({ type: 'boolean', default: false })
|
||||||
isOffline!: boolean;
|
isOffline!: boolean;
|
||||||
|
|
||||||
|
@Column({ type: 'boolean', default: true })
|
||||||
|
isShownInMemory!: boolean;
|
||||||
|
|
||||||
@Column({ type: 'bytea' })
|
@Column({ type: 'bytea' })
|
||||||
@Index()
|
@Index()
|
||||||
checksum!: Buffer; // sha1 checksum
|
checksum!: Buffer; // sha1 checksum
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class RemoveFromMemory1697484859613 implements MigrationInterface {
|
||||||
|
name = 'RemoveFromMemory1697484859613'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "assets" RENAME COLUMN "isSkipMotion" TO "isShownInMemory"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_faces" DROP CONSTRAINT "PK_6df76ab2eb6f5b57b7c2f1fc684"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_faces" DROP COLUMN "id"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_faces" ADD CONSTRAINT "PK_bf339a24070dac7e71304ec530a" PRIMARY KEY ("assetId", "personId")`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_faces" DROP CONSTRAINT "FK_95ad7106dd7b484275443f580f9"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_faces" ALTER COLUMN "personId" SET NOT NULL`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "assets" ALTER COLUMN "isShownInMemory" SET DEFAULT true`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_faces" ADD CONSTRAINT "FK_95ad7106dd7b484275443f580f9" FOREIGN KEY ("personId") REFERENCES "person"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_faces" DROP CONSTRAINT "FK_95ad7106dd7b484275443f580f9"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "assets" ALTER COLUMN "isShownInMemory" SET DEFAULT false`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_faces" ALTER COLUMN "personId" DROP NOT NULL`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_faces" ADD CONSTRAINT "FK_95ad7106dd7b484275443f580f9" FOREIGN KEY ("personId") REFERENCES "person"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_faces" DROP CONSTRAINT "PK_bf339a24070dac7e71304ec530a"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_faces" ADD "id" uuid NOT NULL DEFAULT uuid_generate_v4()`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "asset_faces" ADD CONSTRAINT "PK_6df76ab2eb6f5b57b7c2f1fc684" PRIMARY KEY ("id")`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "assets" RENAME COLUMN "isShownInMemory" TO "isSkipMotion"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
server/test/fixtures/asset.stub.ts
vendored
12
server/test/fixtures/asset.stub.ts
vendored
|
@ -24,6 +24,7 @@ export const assetStub = {
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
|
isShownInMemory: true,
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
duration: null,
|
duration: null,
|
||||||
|
@ -59,6 +60,7 @@ export const assetStub = {
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
|
isShownInMemory: true,
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
duration: null,
|
duration: null,
|
||||||
|
@ -98,6 +100,7 @@ export const assetStub = {
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
|
isShownInMemory: true,
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
|
@ -134,6 +137,7 @@ export const assetStub = {
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
|
isShownInMemory: true,
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
|
@ -173,6 +177,7 @@ export const assetStub = {
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
|
isShownInMemory: true,
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
|
@ -212,6 +217,7 @@ export const assetStub = {
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
|
isShownInMemory: true,
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
|
@ -251,6 +257,7 @@ export const assetStub = {
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
|
isShownInMemory: true,
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
|
@ -291,6 +298,7 @@ export const assetStub = {
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
deletedAt: null,
|
deletedAt: null,
|
||||||
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
|
isShownInMemory: true,
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
|
@ -329,6 +337,7 @@ export const assetStub = {
|
||||||
createdAt: new Date('2015-02-23T05:06:29.716Z'),
|
createdAt: new Date('2015-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2015-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2015-02-23T05:06:29.716Z'),
|
||||||
localDateTime: new Date('2015-02-23T05:06:29.716Z'),
|
localDateTime: new Date('2015-02-23T05:06:29.716Z'),
|
||||||
|
isShownInMemory: true,
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isExternal: false,
|
isExternal: false,
|
||||||
|
@ -369,6 +378,7 @@ export const assetStub = {
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
|
isShownInMemory: true,
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
|
@ -439,6 +449,7 @@ export const assetStub = {
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
|
isShownInMemory: true,
|
||||||
isFavorite: false,
|
isFavorite: false,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
|
@ -479,6 +490,7 @@ export const assetStub = {
|
||||||
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
createdAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
updatedAt: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
localDateTime: new Date('2023-02-23T05:06:29.716Z'),
|
||||||
|
isShownInMemory: true,
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
|
|
2
server/test/fixtures/shared-link.stub.ts
vendored
2
server/test/fixtures/shared-link.stub.ts
vendored
|
@ -51,6 +51,7 @@ const assetResponse: AssetResponseDto = {
|
||||||
resized: false,
|
resized: false,
|
||||||
thumbhash: null,
|
thumbhash: null,
|
||||||
fileModifiedAt: today,
|
fileModifiedAt: today,
|
||||||
|
isShownInMemory: true,
|
||||||
isExternal: false,
|
isExternal: false,
|
||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
isOffline: false,
|
isOffline: false,
|
||||||
|
@ -191,6 +192,7 @@ export const sharedLinkStub = {
|
||||||
localDateTime: today,
|
localDateTime: today,
|
||||||
createdAt: today,
|
createdAt: today,
|
||||||
updatedAt: today,
|
updatedAt: today,
|
||||||
|
isShownInMemory: true,
|
||||||
isFavorite: false,
|
isFavorite: false,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
isExternal: false,
|
isExternal: false,
|
||||||
|
|
12
web/src/api/open-api/api.ts
generated
12
web/src/api/open-api/api.ts
generated
|
@ -399,6 +399,12 @@ export interface AssetBulkUpdateDto {
|
||||||
* @memberof AssetBulkUpdateDto
|
* @memberof AssetBulkUpdateDto
|
||||||
*/
|
*/
|
||||||
'isFavorite'?: boolean;
|
'isFavorite'?: boolean;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
* @memberof AssetBulkUpdateDto
|
||||||
|
*/
|
||||||
|
'isShownInMemory'?: boolean;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -682,6 +688,12 @@ export interface AssetResponseDto {
|
||||||
* @memberof AssetResponseDto
|
* @memberof AssetResponseDto
|
||||||
*/
|
*/
|
||||||
'isReadOnly': boolean;
|
'isReadOnly': boolean;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
* @memberof AssetResponseDto
|
||||||
|
*/
|
||||||
|
'isShownInMemory': boolean;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
asProfileImage: void;
|
asProfileImage: void;
|
||||||
runJob: AssetJobName;
|
runJob: AssetJobName;
|
||||||
playSlideShow: void;
|
playSlideShow: void;
|
||||||
|
enableMemories: void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
let contextMenuPosition = { x: 0, y: 0 };
|
let contextMenuPosition = { x: 0, y: 0 };
|
||||||
|
@ -185,6 +186,9 @@
|
||||||
text={api.getAssetJobName(AssetJobName.TranscodeVideo)}
|
text={api.getAssetJobName(AssetJobName.TranscodeVideo)}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if !asset.isShownInMemory}
|
||||||
|
<MenuOption on:click={() => dispatch('enableMemories')} text="Show in memories" />
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -346,6 +346,20 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEnableMemories = async () => {
|
||||||
|
try {
|
||||||
|
await api.assetApi.updateAssets({ assetBulkUpdateDto: { ids: [asset.id], isShownInMemory: true } });
|
||||||
|
|
||||||
|
notificationController.show({
|
||||||
|
message: `Asset can be shown in memories`,
|
||||||
|
type: NotificationType.Info,
|
||||||
|
});
|
||||||
|
asset.isShownInMemory = true;
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, "Can't remove asset from memory");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleStopSlideshow = async () => {
|
const handleStopSlideshow = async () => {
|
||||||
try {
|
try {
|
||||||
await document.exitFullscreen();
|
await document.exitFullscreen();
|
||||||
|
@ -408,6 +422,7 @@
|
||||||
on:asProfileImage={() => (isShowProfileImageCrop = true)}
|
on:asProfileImage={() => (isShowProfileImageCrop = true)}
|
||||||
on:runJob={({ detail: job }) => handleRunJob(job)}
|
on:runJob={({ detail: job }) => handleRunJob(job)}
|
||||||
on:playSlideShow={handlePlaySlideshow}
|
on:playSlideShow={handlePlaySlideshow}
|
||||||
|
on:enableMemories={handleEnableMemories}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -20,6 +20,12 @@
|
||||||
import IntersectionObserver from '$lib/components/asset-viewer/intersection-observer.svelte';
|
import IntersectionObserver from '$lib/components/asset-viewer/intersection-observer.svelte';
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
import { tweened } from 'svelte/motion';
|
import { tweened } from 'svelte/motion';
|
||||||
|
import ContextMenu from '../shared-components/context-menu/context-menu.svelte';
|
||||||
|
import MenuOption from '../shared-components/context-menu/menu-option.svelte';
|
||||||
|
import DotsVertical from 'svelte-material-icons/DotsVertical.svelte';
|
||||||
|
import { clickOutside } from '$lib/utils/click-outside';
|
||||||
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
|
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||||
|
|
||||||
const parseIndex = (s: string | null, max: number | null) => Math.max(Math.min(parseInt(s ?? '') || 0, max ?? 0), 0);
|
const parseIndex = (s: string | null, max: number | null) => Math.max(Math.min(parseInt(s ?? '') || 0, max ?? 0), 0);
|
||||||
|
|
||||||
|
@ -58,6 +64,69 @@
|
||||||
|
|
||||||
let paused = false;
|
let paused = false;
|
||||||
|
|
||||||
|
let isShowAssetOptions = false;
|
||||||
|
let contextMenuPosition = { x: 0, y: 0 };
|
||||||
|
|
||||||
|
const updateMemoryStoreAsset = () => {
|
||||||
|
if ($memoryStore && $memoryStore[memoryIndex].assets[assetIndex]) {
|
||||||
|
memoryStore.update((memoryStore) => {
|
||||||
|
const updatedMemoryStore = [...memoryStore];
|
||||||
|
|
||||||
|
if (memoryIndex >= 0 && memoryIndex < updatedMemoryStore.length) {
|
||||||
|
const memoryItem = updatedMemoryStore[memoryIndex];
|
||||||
|
|
||||||
|
if (assetIndex >= 0 && memoryItem.assets.length > 1) {
|
||||||
|
memoryItem.assets.splice(assetIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return updatedMemoryStore; // Return the updated memoryStore
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateMemoryStoreMemory = () => {
|
||||||
|
if ($memoryStore && $memoryStore[memoryIndex].assets[assetIndex]) {
|
||||||
|
memoryStore.update((memoryStore) => {
|
||||||
|
const updatedMemoryStore = [...memoryStore];
|
||||||
|
updatedMemoryStore.splice(memoryIndex, 1);
|
||||||
|
|
||||||
|
return updatedMemoryStore; // Return the updated memoryStore
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeFromMemory = async () => {
|
||||||
|
try {
|
||||||
|
await api.assetApi.updateAssets({ assetBulkUpdateDto: { ids: [currentAsset.id], isShownInMemory: false } });
|
||||||
|
|
||||||
|
notificationController.show({
|
||||||
|
message: `Removed asset from memory`,
|
||||||
|
type: NotificationType.Info,
|
||||||
|
});
|
||||||
|
if (currentMemory?.assets.length === 1) {
|
||||||
|
if ($memoryStore?.length === 1) {
|
||||||
|
goto(AppRoute.PHOTOS);
|
||||||
|
} else {
|
||||||
|
if ($memoryStore?.length === memoryIndex + 1) {
|
||||||
|
toPreviousMemory();
|
||||||
|
} else {
|
||||||
|
toNextMemory();
|
||||||
|
}
|
||||||
|
updateMemoryStoreAsset();
|
||||||
|
updateMemoryStoreMemory();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updateMemoryStoreAsset();
|
||||||
|
}
|
||||||
|
isShowAssetOptions = false;
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, "Can't remove asset from memory");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleRemoveFromMemory = () => {
|
||||||
|
isShowAssetOptions = !isShowAssetOptions;
|
||||||
|
};
|
||||||
|
|
||||||
// Play or pause progress when the paused state changes.
|
// Play or pause progress when the paused state changes.
|
||||||
$: paused ? pause() : play();
|
$: paused ? pause() : play();
|
||||||
|
|
||||||
|
@ -222,6 +291,16 @@
|
||||||
{currentAsset.exifInfo?.country || ''}
|
{currentAsset.exifInfo?.country || ''}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="absolute right-8 top-4 text-sm font-medium text-white">
|
||||||
|
<div use:clickOutside on:outclick={() => (isShowAssetOptions = false)}>
|
||||||
|
<CircleIconButton isOpacity={true} logo={DotsVertical} on:click={handleRemoveFromMemory} title="More" />
|
||||||
|
{#if isShowAssetOptions}
|
||||||
|
<ContextMenu {...contextMenuPosition} direction="left">
|
||||||
|
<MenuOption on:click={removeFromMemory} text="Remove from memories" />
|
||||||
|
</ContextMenu>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue