chore: remove all deprecated endpoints/properties from server and mobile app (#9724)

* chore: remove deprecated title property from MemoryLaneResponseDto

* chore: remove deprecated webpPath and resizePath from MetadataSearchDto

* chore: remove deprecated sharedUserIds property from Album AddUsersDto

* chore: remove deprecated sharedUsers property from AlbumResponseDto

* chore: remove deprecated sharedWithUserIds property from CreateAlbumDto

* chore: remove deprecated isExternal and isReadOnly properties from AssetResponseDto

* chore: remove deprecated /server-info endpoint

* chore: bloody linters
This commit is contained in:
Zack Pollard 2024-05-24 15:37:01 +01:00 committed by GitHub
parent 1f5d82e9d9
commit 39d2c4f37b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 56 additions and 221 deletions

View file

@ -383,7 +383,6 @@ describe('/albums', () => {
description: '',
albumThumbnailAssetId: null,
shared: false,
sharedUsers: [],
albumUsers: [],
hasSharedLink: false,
assets: [],
@ -611,7 +610,11 @@ describe('/albums', () => {
expect(status).toBe(200);
expect(body).toEqual(
expect.objectContaining({
sharedUsers: [expect.objectContaining({ id: user2.userId })],
albumUsers: [
expect.objectContaining({
user: expect.objectContaining({ id: user2.userId }),
}),
],
}),
);
});

View file

@ -15,16 +15,16 @@ describe('/server-info', () => {
nonAdmin = await utils.userSetup(admin.accessToken, createUserDto.user1);
});
describe('GET /server-info', () => {
describe('GET /server-info/storage', () => {
it('should require authentication', async () => {
const { status, body } = await request(app).get('/server-info');
const { status, body } = await request(app).get('/server-info/storage');
expect(status).toBe(401);
expect(body).toEqual(errorDto.unauthorized);
});
it('should return the disk information', async () => {
const { status, body } = await request(app)
.get('/server-info')
.get('/server-info/storage')
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(200);
expect(body).toEqual({

View file

@ -145,9 +145,10 @@ class Album {
.remoteIdEqualTo(dto.albumThumbnailAssetId)
.findFirst();
}
if (dto.sharedUsers.isNotEmpty) {
final users = await db.users
.getAllById(dto.sharedUsers.map((e) => e.id).toList(growable: false));
if (dto.albumUsers.isNotEmpty) {
final users = await db.users.getAllById(
dto.albumUsers.map((e) => e.user.id).toList(growable: false),
);
a.sharedUsers.addAll(users.cast());
}
if (dto.assets.isNotEmpty) {

View file

@ -180,7 +180,14 @@ class AlbumService {
CreateAlbumDto(
albumName: albumName,
assetIds: assets.map((asset) => asset.remoteId!).toList(),
sharedWithUserIds: sharedUsers.map((e) => e.id).toList(),
albumUsers: sharedUsers
.map(
(e) => AlbumUserCreateDto(
userId: e.id,
role: AlbumUserRole.editor,
),
)
.toList(),
),
);
if (remote != null) {

View file

@ -8,6 +8,8 @@ import 'package:isar/isar.dart';
import 'package:logging/logging.dart';
import 'package:openapi/api.dart';
import '../utils/string_helper.dart';
final memoryServiceProvider = StateProvider<MemoryService>((ref) {
return MemoryService(
ref.watch(apiServiceProvider),
@ -36,13 +38,13 @@ class MemoryService {
}
List<Memory> memories = [];
for (final MemoryLaneResponseDto(:title, :assets) in data) {
for (final MemoryLaneResponseDto(:yearsAgo, :assets) in data) {
final dbAssets =
await _db.assets.getAllByRemoteId(assets.map((e) => e.id));
if (dbAssets.isNotEmpty) {
memories.add(
Memory(
title: title,
title: '$yearsAgo year${s(yearsAgo)} ago',
assets: dbAssets,
),
);

View file

@ -362,15 +362,15 @@ class SyncService {
// update shared users
final List<User> sharedUsers = album.sharedUsers.toList(growable: false);
sharedUsers.sort((a, b) => a.id.compareTo(b.id));
dto.sharedUsers.sort((a, b) => a.id.compareTo(b.id));
dto.albumUsers.sort((a, b) => a.user.id.compareTo(b.user.id));
final List<String> userIdsToAdd = [];
final List<User> usersToUnlink = [];
diffSortedListsSync(
dto.sharedUsers,
dto.albumUsers,
sharedUsers,
compare: (UserResponseDto a, User b) => a.id.compareTo(b.id),
compare: (AlbumUserResponseDto a, User b) => a.user.id.compareTo(b.id),
both: (a, b) => false,
onlyFirst: (UserResponseDto a) => userIdsToAdd.add(a.id),
onlyFirst: (AlbumUserResponseDto a) => userIdsToAdd.add(a.user.id),
onlySecond: (User a) => usersToUnlink.add(a),
);
@ -905,7 +905,7 @@ bool _hasAlbumResponseDtoChanged(AlbumResponseDto dto, Album a) {
dto.albumName != a.name ||
dto.albumThumbnailAssetId != a.thumbnail.value?.remoteId ||
dto.shared != a.shared ||
dto.sharedUsers.length != a.sharedUsers.length ||
dto.albumUsers.length != a.sharedUsers.length ||
!dto.updatedAt.isAtSameMomentAs(a.modifiedAt) ||
!isAtSameMomentAs(dto.startDate, a.startDate) ||
!isAtSameMomentAs(dto.endDate, a.endDate) ||

View file

@ -3,3 +3,5 @@ extension StringExtension on String {
return "${this[0].toUpperCase()}${substring(1).toLowerCase()}";
}
}
String s(num count) => (count == 1 ? '' : 's');

BIN
mobile/openapi/README.md generated

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -4399,44 +4399,6 @@
]
}
},
"/server-info": {
"get": {
"deprecated": true,
"description": "This property was deprecated in v1.106.0",
"operationId": "getServerInfo",
"parameters": [],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ServerStorageResponseDto"
}
}
},
"description": ""
}
},
"security": [
{
"bearer": []
},
{
"cookie": []
},
{
"api_key": []
}
],
"tags": [
"Server Info",
"Deprecated"
],
"x-immich-lifecycle": {
"deprecatedAt": "v1.106.0"
}
}
},
"/server-info/config": {
"get": {
"operationId": "getServerConfig",
@ -6738,15 +6700,6 @@
"$ref": "#/components/schemas/AlbumUserAddDto"
},
"type": "array"
},
"sharedUserIds": {
"deprecated": true,
"description": "This property was deprecated in v1.102.0",
"items": {
"format": "uuid",
"type": "string"
},
"type": "array"
}
},
"required": [
@ -6844,14 +6797,6 @@
"shared": {
"type": "boolean"
},
"sharedUsers": {
"deprecated": true,
"description": "This property was deprecated in v1.102.0",
"items": {
"$ref": "#/components/schemas/UserResponseDto"
},
"type": "array"
},
"startDate": {
"format": "date-time",
"type": "string"
@ -6875,7 +6820,6 @@
"owner",
"ownerId",
"shared",
"sharedUsers",
"updatedAt"
],
"type": "object"
@ -7495,22 +7439,12 @@
"isArchived": {
"type": "boolean"
},
"isExternal": {
"deprecated": true,
"description": "This property was deprecated in v1.104.0",
"type": "boolean"
},
"isFavorite": {
"type": "boolean"
},
"isOffline": {
"type": "boolean"
},
"isReadOnly": {
"deprecated": true,
"description": "This property was deprecated in v1.104.0",
"type": "boolean"
},
"isTrashed": {
"type": "boolean"
},
@ -7801,7 +7735,6 @@
"type": "string"
},
"albumUsers": {
"description": "This property was added in v1.104.0",
"items": {
"$ref": "#/components/schemas/AlbumUserCreateDto"
},
@ -7816,15 +7749,6 @@
},
"description": {
"type": "string"
},
"sharedWithUserIds": {
"deprecated": true,
"description": "This property was deprecated in v1.104.0",
"items": {
"format": "uuid",
"type": "string"
},
"type": "array"
}
},
"required": [
@ -8672,18 +8596,12 @@
},
"type": "array"
},
"title": {
"deprecated": true,
"description": "This property was deprecated in v1.100.0",
"type": "string"
},
"yearsAgo": {
"type": "integer"
}
},
"required": [
"assets",
"title",
"yearsAgo"
],
"type": "object"
@ -8874,11 +8792,6 @@
"previewPath": {
"type": "string"
},
"resizePath": {
"deprecated": true,
"description": "This property was deprecated in v1.100.0",
"type": "string"
},
"size": {
"maximum": 1000,
"minimum": 1,
@ -8917,11 +8830,6 @@
"format": "date-time",
"type": "string"
},
"webpPath": {
"deprecated": true,
"description": "This property was deprecated in v1.100.0",
"type": "string"
},
"withArchived": {
"default": false,
"type": "boolean"

View file

@ -123,12 +123,8 @@ export type AssetResponseDto = {
hasMetadata: boolean;
id: string;
isArchived: boolean;
/** This property was deprecated in v1.104.0 */
isExternal?: boolean;
isFavorite: boolean;
isOffline: boolean;
/** This property was deprecated in v1.104.0 */
isReadOnly?: boolean;
isTrashed: boolean;
/** This property was deprecated in v1.106.0 */
libraryId?: string | null;
@ -166,8 +162,6 @@ export type AlbumResponseDto = {
owner: UserResponseDto;
ownerId: string;
shared: boolean;
/** This property was deprecated in v1.102.0 */
sharedUsers: UserResponseDto[];
startDate?: string;
updatedAt: string;
};
@ -177,12 +171,9 @@ export type AlbumUserCreateDto = {
};
export type CreateAlbumDto = {
albumName: string;
/** This property was added in v1.104.0 */
albumUsers?: AlbumUserCreateDto[];
assetIds?: string[];
description?: string;
/** This property was deprecated in v1.104.0 */
sharedWithUserIds?: string[];
};
export type AlbumCountResponseDto = {
notShared: number;
@ -213,8 +204,6 @@ export type AlbumUserAddDto = {
};
export type AddUsersDto = {
albumUsers: AlbumUserAddDto[];
/** This property was deprecated in v1.102.0 */
sharedUserIds?: string[];
};
export type ApiKeyResponseDto = {
createdAt: string;
@ -285,8 +274,6 @@ export type MapMarkerResponseDto = {
};
export type MemoryLaneResponseDto = {
assets: AssetResponseDto[];
/** This property was deprecated in v1.100.0 */
title: string;
yearsAgo: number;
};
export type UpdateStackParentDto = {
@ -660,8 +647,6 @@ export type MetadataSearchDto = {
page?: number;
personIds?: string[];
previewPath?: string;
/** This property was deprecated in v1.100.0 */
resizePath?: string;
size?: number;
state?: string;
takenAfter?: string;
@ -672,8 +657,6 @@ export type MetadataSearchDto = {
"type"?: AssetTypeEnum;
updatedAfter?: string;
updatedBefore?: string;
/** This property was deprecated in v1.100.0 */
webpPath?: string;
withArchived?: boolean;
withDeleted?: boolean;
withExif?: boolean;
@ -745,15 +728,6 @@ export type SmartSearchDto = {
withDeleted?: boolean;
withExif?: boolean;
};
export type ServerStorageResponseDto = {
diskAvailable: string;
diskAvailableRaw: number;
diskSize: string;
diskSizeRaw: number;
diskUsagePercentage: number;
diskUse: string;
diskUseRaw: number;
};
export type ServerConfigDto = {
externalDomain: string;
isInitialized: boolean;
@ -801,6 +775,15 @@ export type ServerStatsResponseDto = {
usageByUser: UsageByUserDto[];
videos: number;
};
export type ServerStorageResponseDto = {
diskAvailable: string;
diskAvailableRaw: number;
diskSize: string;
diskSizeRaw: number;
diskUsagePercentage: number;
diskUse: string;
diskUseRaw: number;
};
export type ServerThemeDto = {
customCss: string;
};
@ -2277,17 +2260,6 @@ export function getSearchSuggestions({ country, make, model, state, $type }: {
...opts
}));
}
/**
* This property was deprecated in v1.106.0
*/
export function getServerInfo(opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
data: ServerStorageResponseDto;
}>("/server-info", {
...opts
}));
}
export function getServerConfig(opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;

View file

@ -1,6 +1,5 @@
import { Controller, Get } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { EndpointLifecycle } from 'src/decorators';
import {
ServerConfigDto,
ServerFeaturesDto,
@ -23,13 +22,6 @@ export class ServerInfoController {
private versionService: VersionService,
) {}
@Get()
@EndpointLifecycle({ deprecatedAt: 'v1.106.0' })
@Authenticated()
getServerInfo(): Promise<ServerStorageResponseDto> {
return this.service.getStorage();
}
@Get('storage')
@Authenticated()
getStorage(): Promise<ServerStorageResponseDto> {

View file

@ -2,7 +2,6 @@ import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { ArrayNotEmpty, IsArray, IsEnum, IsString, ValidateNested } from 'class-validator';
import _ from 'lodash';
import { PropertyLifecycle } from 'src/decorators';
import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import { UserResponseDto, mapUser } from 'src/dtos/user.dto';
@ -25,10 +24,6 @@ export class AlbumUserAddDto {
}
export class AddUsersDto {
@ValidateUUID({ each: true, optional: true })
@PropertyLifecycle({ deprecatedAt: 'v1.102.0' })
sharedUserIds?: string[];
@ArrayNotEmpty()
albumUsers!: AlbumUserAddDto[];
}
@ -55,13 +50,8 @@ export class CreateAlbumDto {
@IsArray()
@ValidateNested({ each: true })
@Type(() => AlbumUserCreateDto)
@PropertyLifecycle({ addedAt: 'v1.104.0' })
albumUsers?: AlbumUserCreateDto[];
@ValidateUUID({ optional: true, each: true })
@PropertyLifecycle({ deprecatedAt: 'v1.104.0' })
sharedWithUserIds?: string[];
@ValidateUUID({ optional: true, each: true })
assetIds?: string[];
}
@ -137,8 +127,6 @@ export class AlbumResponseDto {
updatedAt!: Date;
albumThumbnailAssetId!: string | null;
shared!: boolean;
@PropertyLifecycle({ deprecatedAt: 'v1.102.0' })
sharedUsers!: UserResponseDto[];
albumUsers!: AlbumUserResponseDto[];
hasSharedLink!: boolean;
assets!: AssetResponseDto[];
@ -192,7 +180,6 @@ export const mapAlbum = (entity: AlbumEntity, withAssets: boolean, auth?: AuthDt
id: entity.id,
ownerId: entity.ownerId,
owner: mapUser(entity.owner),
sharedUsers,
albumUsers: albumUsersSorted,
shared: hasSharedUser || hasSharedLink,
hasSharedLink,

View file

@ -37,10 +37,6 @@ export class AssetResponseDto extends SanitizedAssetResponseDto {
isArchived!: boolean;
isTrashed!: boolean;
isOffline!: boolean;
@PropertyLifecycle({ deprecatedAt: 'v1.104.0' })
isExternal?: boolean;
@PropertyLifecycle({ deprecatedAt: 'v1.104.0' })
isReadOnly?: boolean;
exifInfo?: ExifResponseDto;
smartInfo?: SmartInfoResponseDto;
tags?: TagResponseDto[];
@ -129,17 +125,12 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As
: undefined,
stackCount: entity.stack?.assets?.length ?? null,
isOffline: entity.isOffline,
isExternal: false,
isReadOnly: false,
hasMetadata: true,
duplicateId: entity.duplicateId,
};
}
export class MemoryLaneResponseDto {
@PropertyLifecycle({ deprecatedAt: 'v1.100.0' })
title!: string;
@ApiProperty({ type: 'integer' })
yearsAgo!: number;

View file

@ -1,7 +1,6 @@
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { IsEnum, IsInt, IsNotEmpty, IsString, Max, Min } from 'class-validator';
import { PropertyLifecycle } from 'src/decorators';
import { AlbumResponseDto } from 'src/dtos/album.dto';
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
import { AssetOrder } from 'src/entities/album.entity';
@ -155,18 +154,6 @@ export class MetadataSearchDto extends BaseSearchDto {
@Optional()
originalPath?: string;
@IsString()
@IsNotEmpty()
@Optional()
@PropertyLifecycle({ deprecatedAt: 'v1.100.0' })
resizePath?: string;
@IsString()
@IsNotEmpty()
@Optional()
@PropertyLifecycle({ deprecatedAt: 'v1.100.0' })
webpPath?: string;
@IsString()
@IsNotEmpty()
@Optional()

View file

@ -185,7 +185,7 @@ describe(AlbumService.name, () => {
await sut.create(authStub.admin, {
albumName: 'Empty album',
sharedWithUserIds: ['user-id'],
albumUsers: [{ userId: 'user-id', role: AlbumUserRole.EDITOR }],
description: '',
assetIds: ['123'],
});
@ -208,7 +208,7 @@ describe(AlbumService.name, () => {
await expect(
sut.create(authStub.admin, {
albumName: 'Empty album',
sharedWithUserIds: ['user-3'],
albumUsers: [{ userId: 'user-3', role: AlbumUserRole.EDITOR }],
}),
).rejects.toBeInstanceOf(BadRequestException);
expect(userMock.get).toHaveBeenCalledWith('user-3', {});

View file

@ -14,7 +14,7 @@ import {
} from 'src/dtos/album.dto';
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
import { AuthDto } from 'src/dtos/auth.dto';
import { AlbumUserEntity, AlbumUserRole } from 'src/entities/album-user.entity';
import { AlbumUserEntity } from 'src/entities/album-user.entity';
import { AlbumEntity } from 'src/entities/album.entity';
import { AssetEntity } from 'src/entities/asset.entity';
import { IAccessRepository } from 'src/interfaces/access.interface';
@ -115,9 +115,6 @@ export class AlbumService {
async create(auth: AuthDto, dto: CreateAlbumDto): Promise<AlbumResponseDto> {
const albumUsers = dto.albumUsers || [];
for (const userId of dto.sharedWithUserIds || []) {
albumUsers.push({ userId, role: AlbumUserRole.EDITOR });
}
for (const { userId } of albumUsers) {
const exists = await this.userRepository.get(userId, {});
@ -216,15 +213,7 @@ export class AlbumService {
return results;
}
async addUsers(auth: AuthDto, id: string, { albumUsers, sharedUserIds }: AddUsersDto): Promise<AlbumResponseDto> {
// Remove once deprecated sharedUserIds is removed
if (!albumUsers) {
if (!sharedUserIds) {
throw new BadRequestException('No users provided');
}
albumUsers = sharedUserIds.map((userId) => ({ userId, role: AlbumUserRole.EDITOR }));
}
async addUsers(auth: AuthDto, id: string, { albumUsers }: AddUsersDto): Promise<AlbumResponseDto> {
await this.access.requirePermission(auth, Permission.ALBUM_SHARE, id);
const album = await this.findOrFail(id, { withAssets: false });

View file

@ -78,9 +78,6 @@ export class SearchService {
checksum = Buffer.from(dto.checksum, encoding);
}
dto.previewPath ??= dto.resizePath;
dto.thumbnailPath ??= dto.webpPath;
const page = dto.page ?? 1;
const size = dto.size || 250;
const enumToOrder = { [AssetOrder.ASC]: 'ASC', [AssetOrder.DESC]: 'DESC' } as const;

View file

@ -57,7 +57,6 @@ const assetResponse: AssetResponseDto = {
resized: false,
thumbhash: null,
fileModifiedAt: today,
isExternal: false,
isOffline: false,
fileCreatedAt: today,
localDateTime: today,
@ -100,7 +99,6 @@ const albumResponse: AlbumResponseDto = {
id: 'album-123',
ownerId: 'admin_id',
owner: mapUser(userStub.admin),
sharedUsers: [],
albumUsers: [],
shared: false,
hasSharedLink: false,

View file

@ -88,7 +88,7 @@
<div class="w-full">{user.name}</div>
<div>Owner</div>
</div>
{#each album.sharedUsers as user (user.id)}
{#each album.albumUsers as { user } (user.id)}
<div class="flex items-center gap-2 py-2">
<div>
<UserAvatar {user} size="md" />

View file

@ -42,8 +42,8 @@
users = data.filter((user) => !(user.deletedAt || user.id === album.ownerId));
// Remove the existed shared users from the album
for (const sharedUser of album.sharedUsers) {
users = users.filter((user) => user.id !== sharedUser.id);
for (const sharedUser of album.albumUsers) {
users = users.filter((user) => user.id !== sharedUser.user.id);
}
});

View file

@ -571,7 +571,7 @@
</div>
{/if}
{#if currentAlbum && currentAlbum.sharedUsers.length > 0 && asset.owner}
{#if currentAlbum && currentAlbum.albumUsers.length > 0 && asset.owner}
<section class="px-6 dark:text-immich-dark-fg mt-4">
<p class="text-sm">SHARED BY</p>
<div class="flex gap-4 pt-4">

View file

@ -136,7 +136,7 @@
assetGridWidth = isShowActivity ? globalWidth - (globalWidth < 768 ? 360 : 460) : globalWidth;
}
$: showActivityStatus =
album.sharedUsers.length > 0 && !$showAssetViewer && (album.isActivityEnabled || $numberOfComments > 0);
album.albumUsers.length > 0 && !$showAssetViewer && (album.isActivityEnabled || $numberOfComments > 0);
$: isEditor =
album.albumUsers.find(({ user: { id } }) => id === $user.id)?.role === AlbumUserRole.Editor ||
@ -158,7 +158,7 @@
backUrl = url || AppRoute.ALBUMS;
if (backUrl === AppRoute.SHARING && album.sharedUsers.length === 0 && !album.hasSharedLink) {
if (backUrl === AppRoute.SHARING && album.albumUsers.length === 0 && !album.hasSharedLink) {
isCreatingSharedAlbum = true;
}
});
@ -229,7 +229,7 @@
isShowActivity = !isShowActivity;
};
$: if (album.sharedUsers.length > 0) {
$: if (album.albumUsers.length > 0) {
handlePromiseError(getFavorite());
handlePromiseError(getNumberOfComments());
}
@ -342,7 +342,7 @@
try {
await refreshAlbum();
viewMode = album.sharedUsers.length > 0 ? ViewMode.VIEW_USERS : ViewMode.VIEW;
viewMode = album.albumUsers.length > 0 ? ViewMode.VIEW_USERS : ViewMode.VIEW;
} catch (error) {
handleError(error, 'Error deleting shared user');
}
@ -482,7 +482,7 @@
{/if}
{/if}
{#if isCreatingSharedAlbum && album.sharedUsers.length === 0}
{#if isCreatingSharedAlbum && album.albumUsers.length === 0}
<Button
size="sm"
rounded="lg"
@ -546,7 +546,7 @@
{album}
{assetStore}
{assetInteractionStore}
isShared={album.sharedUsers.length > 0}
isShared={album.albumUsers.length > 0}
isSelectionMode={viewMode === ViewMode.SELECT_THUMBNAIL}
singleSelect={viewMode === ViewMode.SELECT_THUMBNAIL}
showArchiveIcon
@ -563,7 +563,7 @@
{/if}
<!-- ALBUM SHARING -->
{#if album.sharedUsers.length > 0 || (album.hasSharedLink && isOwned)}
{#if album.albumUsers.length > 0 || (album.hasSharedLink && isOwned)}
<div class="my-3 flex gap-x-1">
<!-- link -->
{#if album.hasSharedLink && isOwned}
@ -649,7 +649,7 @@
{/key}
</main>
</div>
{#if album.sharedUsers.length > 0 && album && isShowActivity && $user && !$showAssetViewer}
{#if album.albumUsers.length > 0 && album && isShowActivity && $user && !$showAssetViewer}
<div class="flex">
<div
transition:fly={{ duration: 150 }}

View file

@ -15,7 +15,6 @@ export const albumFactory = Sync.makeFactory<AlbumResponseDto>({
ownerId: Sync.each(() => faker.string.uuid()),
owner: userFactory.build(),
shared: false,
sharedUsers: [],
albumUsers: [],
hasSharedLink: false,
isActivityEnabled: true,