immich/mobile/lib/utils/openapi_patching.dart
Ben Beckford 351be95769
feat: memories view (#28675)
* wip web memories view

* paginate searchMemories

* improve memories ui

* feat(mobile): memories view

* improve memories web ui

* fix(web): avoid unnecessary memory refreshes

* refactor(web): move timline memory manager filter

* fix(web): memories infinitely loading on 0 results

* fix(web): memories resetting

* feat(web): animated memory previews

* feat(web): memory page dark styling

* chore(mobile): fix failing memory lane tests

* chore(mobile): remove old import

* chore(e2e): fix failing memory lane tests

* chore(server): revert searchMemories changes

* chore(server): lint

* chore(mobile): fix bad merge

* chore(e2e): fix memory ui tests

* chore(web): rename /memory to /memories

* chore(mobile): linting

* chore(web): linting

* fix(web): prevent duplicate memory page loading

* fix(web): lint

* fix(web): memories page improvements

* chore(mobile): lint

* fix(mobile): fix translations

* fix(mobile): build errors

* fix(web): prevent memories from infinitely loading

* chore(e2e)): fix failng memory viewer test

* chore(web): clean up types in memory manager

* chore(web): lint

* feat: update list and detail memory page layouts

* onlyFavorites through drift

* rename to get all

* mobile: use widgetWhen in memory list page

* remove redundant check

* fix: e2e

---------

Co-authored-by: Timon <mail@timonrieger.de>
Co-authored-by: Jason Rasmussen <jason@rasm.me>
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-08-24 19:16:33 -05:00

75 lines
2.6 KiB
Dart

import 'package:flutter/foundation.dart';
import 'package:openapi/api.dart';
abstract interface class _Dynamic {
Object? resolve();
}
class _CurrentTimestamp implements _Dynamic {
const _CurrentTimestamp();
@override
Object? resolve() => DateTime.now().toIso8601String();
}
const _now = _CurrentTimestamp();
@visibleForTesting
final Map<String, Map<String, Object?>> openApiPatches = {
'UserPreferencesResponseDto': {
'download.includeEmbeddedVideos': false,
'folders': FoldersResponse(enabled: false, sidebarWeb: false).toJson(),
'memories': MemoriesResponse(enabled: true, duration: 5, sidebarWeb: false).toJson(),
'ratings': RatingsResponse(enabled: false).toJson(),
'people': PeopleResponse(enabled: true, sidebarWeb: false).toJson(),
'tags': TagsResponse(enabled: false, sidebarWeb: false).toJson(),
'sharedLinks': SharedLinksResponse(enabled: true, sidebarWeb: false).toJson(),
'cast': CastResponse(gCastEnabled: false).toJson(),
'albums': {'defaultAssetOrder': 'desc'},
'recentlyAdded': RecentlyAddedResponse(sidebarWeb: false).toJson(),
},
'ServerConfigDto': {
'mapLightStyleUrl': 'https://tiles.immich.cloud/v1/style/light.json',
'mapDarkStyleUrl': 'https://tiles.immich.cloud/v1/style/dark.json',
'minFaces': 3,
},
'UserResponseDto': {'profileChangedAt': _now},
'AssetResponseDto': {'visibility': 'timeline', 'createdAt': _now, 'isEdited': false},
'UserAdminResponseDto': {'profileChangedAt': _now, 'clusterGroupId': ''},
'LoginResponseDto': {'isOnboarded': false},
'SyncUserV1': {'profileChangedAt': _now, 'hasProfileImage': false},
'SyncAssetV1': {'isEdited': false},
'ServerFeaturesDto': {'ocr': false, 'realtimeTranscoding': false},
'MemoriesResponse': {'duration': 5, 'sidebarWeb': false},
'WorkflowResponseDto': {'logging': false},
};
void upgradeDto(dynamic value, String targetType) {
if (value is! Map) {
return;
}
final fields = openApiPatches[targetType];
if (fields == null) {
return;
}
fields.forEach((key, defaultValue) {
addDefault(value, key, defaultValue is _Dynamic ? defaultValue.resolve() : defaultValue);
});
}
void addDefault(dynamic value, String keys, dynamic defaultValue) {
// Loop through the keys and assign the default value if the key is not present
final List<String> keyList = keys.split('.');
dynamic current = value;
for (int i = 0; i < keyList.length - 1; i++) {
if (current[keyList[i]] == null) {
current[keyList[i]] = {};
}
current = current[keyList[i]];
}
if (current[keyList.last] == null) {
current[keyList.last] = defaultValue;
}
}