Compare commits

..

24 Commits

Author SHA1 Message Date
Thomas Way 1fb1eccc46 simplify asset details 2026-02-06 00:55:13 +00:00
Thomas Way 1481e416f8 remove files 2026-02-06 00:51:22 +00:00
Thomas Way b41e860b43 use dynamic image details 2026-02-06 00:50:02 +00:00
Thomas Way fbdf2a8aab cleanup 2026-02-06 00:13:34 +00:00
Thomas Way 15c9ee2dd9 fully working 2026-02-06 00:03:13 +00:00
Thomas Way 44284fd7d9 nearly feature complete, bar dragging down 2026-02-05 22:02:33 +00:00
Thomas Way 53c5ff1cd7 remove bottom sheet 2026-02-05 17:14:59 +00:00
Thomas Way 59af9e087b with image and controls 2026-02-05 16:49:37 +00:00
Thomas Way 6e91e2e202 scroll physics, asset details 2026-02-05 15:37:07 +00:00
Thomas Way bf6ed541dd abc 2026-02-04 17:54:12 +00:00
Thomas 855817514c fix(mobile): hide latest version if disabled (#25691)
* fix(mobile): hide latest version if disabled

If the version check feature is disabled, the server will currently send
stale data to the client. In addition to no longer sending stale data,
the client should also not show the latest version if the feature is
disabled.

This complements the server PR #25688.

* lint

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
2026-01-30 16:17:03 +00:00
Thomas d5ad35ea52 chore(mobile): remove references to fvm, add mise docs, use java 21 (#25703) 2026-01-29 23:03:56 -06:00
shenlong e63213d774 fix(mobile): do not autocorrect on endpoint input (#25696)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2026-01-29 23:03:26 -06:00
Jason Rasmussen 0be1ffade6 fix: no notification if release check is disabled (#25688) 2026-01-29 18:31:11 -05:00
Brandon Wees 1a04caee29 fix: reset and unsaved change states in editor (#25588) 2026-01-29 15:18:30 -06:00
renovate[bot] 3ace578fc0 chore(deps): update dependency opentofu to v1.11.4 (#24609)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-29 12:14:44 -05:00
Jason Rasmussen 25c573bc7a chore: remove random code snippet (#25677) 2026-01-29 16:11:25 +00:00
renovate[bot] 10bb83cf75 chore(deps): update dependency terragrunt to v0.98.0 (#24328)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-29 08:55:42 -05:00
Jason Rasmussen 10b53b525d refactor: event manager (#25565) 2026-01-29 08:52:18 -05:00
Timon 8db61d341f docs(openapi): add descriptions to OpenAPI specification (#25185)
* faces

* add openapi descriptions

* remove dto descriptions

* gen openapi

* dtos

* fix dtos

* fix more

* fix build

* more

* complete dtos

* descriptions on rebase

* gen rebase

* revert correct integer type conversion

* gen after revert

* revert correct nullables

* regen after revert

* actually incorrect adding default here

* revert correct number type conversion

* regen after revert

* revert nullable usage

* regen fully

* readd some comments

* one more

* one more

* use enum

* add missing

* add missing controllers

* add missing dtos

* complete it

* more

* describe global key and slug

* add remaining body and param descriptions

* lint and format

* cleanup

* response and schema descriptions

* test patch according to suggestion

* revert added api response objects

* revert added api body objects

* revert added api param object

* revert added api query objects

* revert reorganized http code objects

* revert reorganize ApiOkResponse objects

* revert added api response objects (2)

* revert added api tag object

* revert added api schema objects

* migrate missing asset.dto.ts

* regenerate openapi builds

* delete generated mustache files

* remove descriptions from properties that are schemas

* lint

* revert nullable type changes

* revert int/num type changes

* remove explicit default

* readd comment

* lint

* pr fixes

* last bits and pieces

* lint and format

* chore: remove rejected patches

* fix: deleting asset from asset-viewer on search results (#25596)

* fix: escape handling in search asset viewer (#25621)

* fix: correctly show owner in album options modal (#25618)

* fix: validation issues

* fix: validation issues

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
Co-authored-by: Min Idzelis <min123@gmail.com>
Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Co-authored-by: Paul Makles <me@insrt.uk>
2026-01-29 08:49:15 -05:00
github-actions eadb2f89af chore: version v2.5.2 2026-01-28 22:05:10 +00:00
Marius f2f11b1924 fix(mobile): tall image scrolling (#25649)
Add cross-axis gesture detection in PhotoView so vertical scrolling works on tall images that don't fill the screen width (have black bars)
2026-01-28 17:03:11 -05:00
Jason Rasmussen 141be5cbc9 fix: memory generation (#25650) 2026-01-28 15:51:24 -06:00
Jason Rasmussen e81faa1dbf fix: memory lane (#25652) 2026-01-28 15:51:13 -06:00
444 changed files with 6226 additions and 1257 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.5.1", "version": "2.5.2",
"description": "Command Line Interface (CLI) for Immich", "description": "Command Line Interface (CLI) for Immich",
"type": "module", "type": "module",
"exports": "./dist/index.js", "exports": "./dist/index.js",
+2 -2
View File
@@ -1,6 +1,6 @@
[tools] [tools]
terragrunt = "0.93.10" terragrunt = "0.98.0"
opentofu = "1.10.7" opentofu = "1.11.4"
[tasks."tg:fmt"] [tasks."tg:fmt"]
run = "terragrunt hclfmt" run = "terragrunt hclfmt"
+2 -2
View File
@@ -1,7 +1,7 @@
[ [
{ {
"label": "v2.5.1", "label": "v2.5.2",
"url": "https://docs.v2.5.1.archive.immich.app" "url": "https://docs.v2.5.2.archive.immich.app"
}, },
{ {
"label": "v2.4.1", "label": "v2.4.1",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "immich-e2e", "name": "immich-e2e",
"version": "2.5.1", "version": "2.5.2",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "immich-i18n", "name": "immich-i18n",
"version": "2.5.1", "version": "2.5.2",
"private": true, "private": true,
"scripts": { "scripts": {
"format": "prettier --check .", "format": "prettier --check .",
+1 -1
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "immich-ml" name = "immich-ml"
version = "2.5.1" version = "2.5.2"
description = "" description = ""
authors = [{ name = "Hau Tran", email = "alex.tran1502@gmail.com" }] authors = [{ name = "Hau Tran", email = "alex.tran1502@gmail.com" }]
requires-python = ">=3.11,<4.0" requires-python = ">=3.11,<4.0"
+1 -1
View File
@@ -919,7 +919,7 @@ wheels = [
[[package]] [[package]]
name = "immich-ml" name = "immich-ml"
version = "2.4.1" version = "2.5.2"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "aiocache" }, { name = "aiocache" },
+3 -3
View File
@@ -17,9 +17,9 @@ config_roots = [
node = "24.13.0" node = "24.13.0"
flutter = "3.35.7" flutter = "3.35.7"
pnpm = "10.28.0" pnpm = "10.28.0"
terragrunt = "0.93.10" terragrunt = "0.98.0"
opentofu = "1.10.7" opentofu = "1.11.4"
java = "25.0.1" java = "21.0.2"
[tools."github:CQLabs/homebrew-dcm"] [tools."github:CQLabs/homebrew-dcm"]
version = "1.30.0" version = "1.30.0"
-3
View File
@@ -1,3 +0,0 @@
{
"flutter": "3.35.7"
}
-3
View File
@@ -55,8 +55,5 @@ default.isar
default.isar.lock default.isar.lock
libisar.so libisar.so
# FVM Version
.fvm/
# Translation file # Translation file
lib/generated/ lib/generated/
+3 -1
View File
@@ -2,7 +2,9 @@
"dart.flutterSdkPath": ".fvm/versions/3.35.7", "dart.flutterSdkPath": ".fvm/versions/3.35.7",
"dart.lineLength": 120, "dart.lineLength": 120,
"[dart]": { "[dart]": {
"editor.rulers": [120] "editor.rulers": [
120
]
}, },
"search.exclude": { "search.exclude": {
"**/.fvm": true "**/.fvm": true
+6 -4
View File
@@ -4,10 +4,12 @@ The Immich mobile app is a Flutter-based solution leveraging the Isar Database f
## Setup ## Setup
1. Setup Flutter toolchain using FVM. 1. [Install mise](https://mise.jdx.dev/installing-mise.html).
2. Run `flutter pub get` to install the dependencies. 2. Change to the immich directory and trust the mise config with `mise trust`.
3. Run `make translation` to generate the translation file. 3. Install tools with mise: `mise install`.
4. Run `fvm flutter run` to start the app. 4. Run `flutter pub get` to install the dependencies.
5. Run `make translation` to generate the translation file.
6. Run `flutter run` to start the app.
## Translation ## Translation
+2 -2
View File
@@ -35,8 +35,8 @@ platform :android do
task: 'bundle', task: 'bundle',
build_type: 'Release', build_type: 'Release',
properties: { properties: {
"android.injected.version.code" => 3032, "android.injected.version.code" => 3033,
"android.injected.version.name" => "2.5.1", "android.injected.version.name" => "2.5.2",
} }
) )
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab') upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
+1 -1
View File
@@ -80,7 +80,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2.5.1</string> <string>2.5.2</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>
+2 -2
View File
@@ -16,9 +16,9 @@ class ScrollToDateEvent extends Event {
} }
// Asset Viewer Events // Asset Viewer Events
class ViewerOpenBottomSheetEvent extends Event { class ViewerShowDetailsEvent extends Event {
final bool activitiesMode; final bool activitiesMode;
const ViewerOpenBottomSheetEvent({this.activitiesMode = false}); const ViewerShowDetailsEvent({this.activitiesMode = false});
} }
class ViewerReloadAssetEvent extends Event { class ViewerReloadAssetEvent extends Event {
@@ -144,13 +144,16 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository {
bool keepFavorites = true, bool keepFavorites = true,
Set<String> keepAlbumIds = const {}, Set<String> keepAlbumIds = const {},
}) async { }) async {
final iosSharedAlbumIds = _db.localAlbumEntity.selectOnly()
..addColumns([_db.localAlbumEntity.id])
..where(_db.localAlbumEntity.isIosSharedAlbum.equals(true));
final iosSharedAlbumAssets = _db.localAlbumAssetEntity.selectOnly() final iosSharedAlbumAssets = _db.localAlbumAssetEntity.selectOnly()
..addColumns([_db.localAlbumAssetEntity.assetId]) ..addColumns([_db.localAlbumAssetEntity.assetId])
..where(_db.localAlbumAssetEntity.albumId.isInQuery(iosSharedAlbumIds)); ..join([
innerJoin(
_db.localAlbumEntity,
_db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id),
useColumns: false,
),
])
..where(_db.localAlbumEntity.isIosSharedAlbum.equals(true));
final query = _db.localAssetEntity.select().join([ final query = _db.localAssetEntity.select().join([
innerJoin(_db.remoteAssetEntity, _db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum)), innerJoin(_db.remoteAssetEntity, _db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum)),
@@ -20,7 +20,7 @@ enum VersionStatus {
class ServerInfo { class ServerInfo {
final ServerVersion serverVersion; final ServerVersion serverVersion;
final ServerVersion latestVersion; final ServerVersion? latestVersion;
final ServerFeatures serverFeatures; final ServerFeatures serverFeatures;
final ServerConfig serverConfig; final ServerConfig serverConfig;
final ServerDiskInfo serverDiskInfo; final ServerDiskInfo serverDiskInfo;
@@ -1,5 +1,4 @@
import 'dart:async'; import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
@@ -18,7 +17,6 @@ import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_sheet/she
import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_sheet/sheet_people_details.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_sheet/sheet_people_details.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/rating_bar.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/rating_bar.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/sheet_tile.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/sheet_tile.widget.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart';
@@ -32,36 +30,10 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart';
const _kSeparator = ''; const _kSeparator = '';
class AssetDetailBottomSheet extends ConsumerWidget { class AssetDetails extends ConsumerWidget {
final DraggableScrollableController? controller; final double minHeight;
final double initialChildSize;
const AssetDetailBottomSheet({this.controller, this.initialChildSize = 0.35, super.key}); const AssetDetails({required this.minHeight, super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final asset = ref.watch(currentAssetNotifier);
if (asset == null) {
return const SizedBox.shrink();
}
return BaseBottomSheet(
actions: [],
slivers: const [_AssetDetailBottomSheet()],
controller: controller,
initialChildSize: initialChildSize,
minChildSize: 0.1,
maxChildSize: 0.88,
expand: false,
shouldCloseOnMinExtent: false,
resizeOnScroll: false,
backgroundColor: context.isDarkTheme ? context.colorScheme.surface : Colors.white,
);
}
}
class _AssetDetailBottomSheet extends ConsumerWidget {
const _AssetDetailBottomSheet();
String _getDateTime(BuildContext ctx, BaseAsset asset, ExifInfo? exifInfo) { String _getDateTime(BuildContext ctx, BaseAsset asset, ExifInfo? exifInfo) {
DateTime dateTime = asset.createdAt.toLocal(); DateTime dateTime = asset.createdAt.toLocal();
@@ -199,7 +171,7 @@ class _AssetDetailBottomSheet extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final asset = ref.watch(currentAssetNotifier); final asset = ref.watch(currentAssetNotifier);
if (asset == null) { if (asset == null) {
return const SliverToBoxAdapter(child: SizedBox.shrink()); return const SizedBox.shrink();
} }
final exifInfo = ref.watch(currentAssetExifProvider).valueOrNull; final exifInfo = ref.watch(currentAssetExifProvider).valueOrNull;
@@ -247,8 +219,26 @@ class _AssetDetailBottomSheet extends ConsumerWidget {
} }
} }
return SliverList.list( return Container(
constraints: BoxConstraints(minHeight: minHeight),
decoration: BoxDecoration(
color: context.isDarkTheme ? context.colorScheme.surface : Colors.white,
borderRadius: const BorderRadius.vertical(top: Radius.circular(20)),
),
child: Column(
children: [ children: [
const SizedBox(height: 16),
Center(
child: Container(
width: 32,
height: 4,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(2),
color: context.colorScheme.onSurfaceVariant,
),
),
),
const SizedBox(height: 16),
// Asset Date and Time // Asset Date and Time
SheetTile( SheetTile(
title: _getDateTime(context, asset, exifInfo), title: _getDateTime(context, asset, exifInfo),
@@ -322,6 +312,7 @@ class _AssetDetailBottomSheet extends ConsumerWidget {
// padding at the bottom to avoid cut-off // padding at the bottom to avoid cut-off
const SizedBox(height: 60), const SizedBox(height: 60),
], ],
),
); );
} }
} }
@@ -407,3 +398,4 @@ class _SheetAssetDescriptionState extends ConsumerState<_SheetAssetDescription>
); );
} }
} }
@@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:math' as math;
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
@@ -14,12 +15,11 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/extensions/platform_extensions.dart';
import 'package:immich_mobile/extensions/scroll_extensions.dart'; import 'package:immich_mobile/extensions/scroll_extensions.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/download_status_floating_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/download_status_floating_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/activities_bottom_sheet.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_details.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.provider.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.provider.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_bar.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_bar.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_sheet.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/top_app_bar.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/top_app_bar.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/video_viewer.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/video_viewer.widget.dart';
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart'; import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
@@ -30,7 +30,6 @@ import 'package:immich_mobile/providers/asset_viewer/video_player_value_provider
import 'package:immich_mobile/providers/cast.provider.dart'; import 'package:immich_mobile/providers/cast.provider.dart';
import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart';
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart'; import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart';
import 'package:immich_mobile/widgets/photo_view/photo_view.dart'; import 'package:immich_mobile/widgets/photo_view/photo_view.dart';
@@ -100,27 +99,24 @@ class AssetViewer extends ConsumerStatefulWidget {
} }
} }
const double _kBottomSheetMinimumExtent = 0.4; enum _DragMode { undecided, dismiss, scroll }
const double _kBottomSheetSnapExtent = 0.67;
class _AssetViewerState extends ConsumerState<AssetViewer> { class _AssetViewerState extends ConsumerState<AssetViewer> with TickerProviderStateMixin {
static final _dummyListener = ImageStreamListener((image, _) => image.dispose()); static final _dummyListener = ImageStreamListener((image, _) => image.dispose());
late PageController pageController; late PageController pageController;
late DraggableScrollableController bottomSheetController;
PersistentBottomSheetController? sheetCloseController;
// PhotoViewGallery takes care of disposing it's controllers // PhotoViewGallery takes care of disposing it's controllers
PhotoViewControllerBase? viewController; PhotoViewControllerBase? viewController;
StreamSubscription? reloadSubscription; StreamSubscription? reloadSubscription;
StreamSubscription? _scaleBoundarySub;
late final int heroOffset; late final int heroOffset;
late PhotoViewControllerValue initialPhotoViewState; late PhotoViewControllerValue initialPhotoViewState;
bool? hasDraggedDown;
bool isSnapping = false;
bool blockGestures = false; bool blockGestures = false;
bool dragInProgress = false; bool dragInProgress = false;
bool shouldPopOnDrag = false; bool shouldPopOnDrag = false;
_DragMode _dragMode = _DragMode.undecided;
Offset _dragStartGlobalPosition = Offset.zero;
bool assetReloadRequested = false; bool assetReloadRequested = false;
double previousExtent = _kBottomSheetMinimumExtent;
Offset dragDownPosition = Offset.zero; Offset dragDownPosition = Offset.zero;
int totalAssets = 0; int totalAssets = 0;
int stackIndex = 0; int stackIndex = 0;
@@ -135,13 +131,19 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
KeepAliveLink? _stackChildrenKeepAlive; KeepAliveLink? _stackChildrenKeepAlive;
final ScrollController _scrollController = ScrollController();
late final AnimationController _ballisticAnimController;
double _assetDetailsOpacity = 0.0;
double _currentSnapOffset = 0.0;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
assert(ref.read(currentAssetNotifier) != null, "Current asset should not be null when opening the AssetViewer"); assert(ref.read(currentAssetNotifier) != null, "Current asset should not be null when opening the AssetViewer");
pageController = PageController(initialPage: widget.initialIndex); pageController = PageController(initialPage: widget.initialIndex);
_scrollController.addListener(_onScroll);
_ballisticAnimController = AnimationController.unbounded(vsync: this)..addListener(_onBallisticTick);
totalAssets = ref.read(timelineServiceProvider).totalAssets; totalAssets = ref.read(timelineServiceProvider).totalAssets;
bottomSheetController = DraggableScrollableController();
WidgetsBinding.instance.addPostFrameCallback(_onAssetInit); WidgetsBinding.instance.addPostFrameCallback(_onAssetInit);
reloadSubscription = EventStream.shared.listen(_onEvent); reloadSubscription = EventStream.shared.listen(_onEvent);
heroOffset = widget.heroOffset ?? TabsRouterScope.of(context)?.controller.activeIndex ?? 0; heroOffset = widget.heroOffset ?? TabsRouterScope.of(context)?.controller.activeIndex ?? 0;
@@ -156,12 +158,129 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
} }
} }
void _onScroll() {
final newOpacity = _scrollController.offset > 5 ? 1.0 : 0.0;
if (newOpacity != _assetDetailsOpacity) {
setState(() {
_assetDetailsOpacity = newOpacity;
});
if (_assetDetailsOpacity == 0) {
ref.read(assetViewerProvider.notifier).setControls(true);
} else {
ref.read(assetViewerProvider.notifier).setControls(false);
}
}
}
// Match Flutter's ScrollPhysics defaults
static final _snapSpring = SpringDescription.withDampingRatio(mass: 0.5, stiffness: 100.0, ratio: 1.1);
static const _minFlingVelocity = 50.0; // px/s, matches ScrollPhysics.minFlingVelocity
Tolerance get _scrollTolerance {
final dpr = MediaQuery.devicePixelRatioOf(context);
return Tolerance(velocity: 1.0 / (0.050 * dpr), distance: 1.0 / dpr);
}
/// Drive the scroll controller by [dy] pixels (positive = scroll down).
void _scrollBy(double dy) {
if (!_scrollController.hasClients) return;
final newOffset = (_scrollController.offset - dy).clamp(0.0, _scrollController.position.maxScrollExtent);
_scrollController.jumpTo(newOffset);
}
/// Animate the scroll position to [target] using a spring simulation.
void _animateScrollTo(double target, double velocity) {
final offset = _scrollController.offset;
final tolerance = _scrollTolerance;
if ((offset - target).abs() < tolerance.distance) {
_scrollController.jumpTo(target);
return;
}
_ballisticAnimController.value = offset;
_ballisticAnimController.animateWith(
ScrollSpringSimulation(_snapSpring, offset, target, velocity, tolerance: tolerance),
);
}
/// Create a platform-appropriate fling simulation (clamping on Android, bouncing on iOS).
Simulation _createFlingSimulation(double offset, double velocity) {
final tolerance = _scrollTolerance;
if (CurrentPlatform.isIOS) {
return BouncingScrollSimulation(
position: offset,
velocity: velocity,
leadingExtent: _currentSnapOffset,
trailingExtent: _scrollController.position.maxScrollExtent,
spring: _snapSpring,
tolerance: tolerance,
);
}
return ClampingScrollSimulation(position: offset, velocity: velocity, tolerance: tolerance);
}
void _onBallisticTick() {
if (!_scrollController.hasClients) return;
final raw = _ballisticAnimController.value;
final max = _scrollController.position.maxScrollExtent;
final offset = raw.clamp(0.0, max);
final prevOffset = _scrollController.offset;
// Stop at bounds
if (raw != offset) {
_ballisticAnimController.stop();
_scrollController.jumpTo(offset);
return;
}
// During free-scroll deceleration, don't cross into the snap zone.
// Stop at snapOffset so the user can release there cleanly.
final snap = _currentSnapOffset;
if (prevOffset >= snap && offset < snap) {
_ballisticAnimController.stop();
_scrollController.jumpTo(snap);
return;
}
_scrollController.jumpTo(offset);
}
void _snapScroll(double velocity) {
if (!_scrollController.hasClients) return;
final offset = _scrollController.offset;
final snap = _currentSnapOffset;
if (snap <= 0) return;
// Above snap offset: free scroll or spring back to snap
if (offset >= snap) {
if (velocity.abs() < _minFlingVelocity) return;
if (velocity < -_minFlingVelocity) {
_animateScrollTo(snap, velocity);
return;
}
// Scrolling up: decelerate with platform-native physics
_ballisticAnimController.value = offset;
_ballisticAnimController.animateWith(_createFlingSimulation(offset, velocity));
return;
}
// In snap zone (0 → snapOffset): snap to nearest target
final double target;
if (velocity.abs() > _minFlingVelocity) {
target = velocity > 0 ? snap : 0;
} else {
target = (offset < snap / 2) ? 0 : snap;
}
_animateScrollTo(target, velocity);
}
@override @override
void dispose() { void dispose() {
_ballisticAnimController.dispose();
_scrollController.dispose();
pageController.dispose(); pageController.dispose();
bottomSheetController.dispose();
_cancelTimers(); _cancelTimers();
reloadSubscription?.cancel(); reloadSubscription?.cancel();
_scaleBoundarySub?.cancel();
_prevPreCacheStream?.removeListener(_dummyListener); _prevPreCacheStream?.removeListener(_dummyListener);
_nextPreCacheStream?.removeListener(_dummyListener); _nextPreCacheStream?.removeListener(_dummyListener);
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
@@ -169,7 +288,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
super.dispose(); super.dispose();
} }
bool get showingBottomSheet => ref.read(assetViewerProvider.select((s) => s.showingBottomSheet)); bool get showingDetails => _scrollController.offset > 0;
Color get backgroundColor { Color get backgroundColor {
final opacity = ref.read(assetViewerProvider.select((s) => s.backgroundOpacity)); final opacity = ref.read(assetViewerProvider.select((s) => s.backgroundOpacity));
@@ -183,9 +302,6 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
_delayedOperations.clear(); _delayedOperations.clear();
} }
double _getVerticalOffsetForBottomSheet(double extent) =>
(context.height * extent) - (context.height * _kBottomSheetMinimumExtent);
ImageStream _precacheImage(BaseAsset asset) { ImageStream _precacheImage(BaseAsset asset) {
final provider = getFullImageProvider(asset, size: context.sizeData); final provider = getFullImageProvider(asset, size: context.sizeData);
return provider.resolve(ImageConfiguration.empty)..addListener(_dummyListener); return provider.resolve(ImageConfiguration.empty)..addListener(_dummyListener);
@@ -220,6 +336,8 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
} }
void _onAssetChanged(int index) async { void _onAssetChanged(int index) async {
_ballisticAnimController.stop();
if (_scrollController.hasClients) _scrollController.jumpTo(0);
final timelineService = ref.read(timelineServiceProvider); final timelineService = ref.read(timelineServiceProvider);
final asset = await timelineService.getAssetAsync(index); final asset = await timelineService.getAssetAsync(index);
if (asset == null) { if (asset == null) {
@@ -263,20 +381,23 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
} }
} }
void _onPageBuild(PhotoViewControllerBase controller) {
viewController ??= controller;
if (showingBottomSheet && bottomSheetController.isAttached) {
final verticalOffset =
(context.height * bottomSheetController.size) - (context.height * _kBottomSheetMinimumExtent);
controller.position = Offset(0, -verticalOffset);
// Apply the zoom effect when the bottom sheet is showing
controller.scale = (controller.scale ?? 1.0) + 0.01;
}
}
void _onPageChanged(int index, PhotoViewControllerBase? controller) { void _onPageChanged(int index, PhotoViewControllerBase? controller) {
_onAssetChanged(index); _onAssetChanged(index);
viewController = controller; viewController = controller;
_listenForScaleBoundaries(controller);
}
void _listenForScaleBoundaries(PhotoViewControllerBase? controller) {
_scaleBoundarySub?.cancel();
_scaleBoundarySub = null;
if (controller == null || controller.scaleBoundaries != null) return;
_scaleBoundarySub = controller.outputStateStream.listen((_) {
if (controller.scaleBoundaries != null) {
_scaleBoundarySub?.cancel();
_scaleBoundarySub = null;
if (mounted) setState(() {});
}
});
} }
void _onDragStart( void _onDragStart(
@@ -285,40 +406,43 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
PhotoViewControllerBase controller, PhotoViewControllerBase controller,
PhotoViewScaleStateController scaleStateController, PhotoViewScaleStateController scaleStateController,
) { ) {
_ballisticAnimController.stop();
viewController = controller; viewController = controller;
dragDownPosition = details.localPosition; dragDownPosition = details.localPosition;
_dragStartGlobalPosition = details.globalPosition;
initialPhotoViewState = controller.value; initialPhotoViewState = controller.value;
_dragMode = showingDetails ? _DragMode.scroll : _DragMode.undecided;
final isZoomed = final isZoomed =
scaleStateController.scaleState == PhotoViewScaleState.zoomedIn || scaleStateController.scaleState == PhotoViewScaleState.zoomedIn ||
scaleStateController.scaleState == PhotoViewScaleState.covering; scaleStateController.scaleState == PhotoViewScaleState.covering;
if (!showingBottomSheet && isZoomed) { if (!showingDetails && isZoomed) {
blockGestures = true; blockGestures = true;
} }
} }
void _onDragEnd(BuildContext ctx, _, __) { void _onDragEnd(BuildContext ctx, DragEndDetails details, _) {
dragInProgress = false; dragInProgress = false;
final mode = _dragMode;
_dragMode = _DragMode.undecided;
if (mode == _DragMode.scroll) {
// Convert finger velocity to scroll velocity (inverted)
final scrollVelocity = -details.velocity.pixelsPerSecond.dy;
_snapScroll(scrollVelocity);
return;
}
if (shouldPopOnDrag) { if (shouldPopOnDrag) {
// Dismiss immediately without state updates to avoid rebuilds
ctx.maybePop(); ctx.maybePop();
return; return;
} }
// Do not reset the state if the bottom sheet is showing
if (showingBottomSheet) {
_snapBottomSheet();
return;
}
// If the gestures are blocked, do not reset the state
if (blockGestures) { if (blockGestures) {
blockGestures = false; blockGestures = false;
return; return;
} }
shouldPopOnDrag = false; shouldPopOnDrag = false;
hasDraggedDown = null;
viewController?.animateMultiple( viewController?.animateMultiple(
position: initialPhotoViewState.position, position: initialPhotoViewState.position,
scale: viewController?.initialScale ?? initialPhotoViewState.scale, scale: viewController?.initialScale ?? initialPhotoViewState.scale,
@@ -328,37 +452,28 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
} }
void _onDragUpdate(BuildContext ctx, DragUpdateDetails details, _) { void _onDragUpdate(BuildContext ctx, DragUpdateDetails details, _) {
if (blockGestures) { if (blockGestures) return;
return;
}
dragInProgress = true; dragInProgress = true;
if (_dragMode == _DragMode.undecided) {
final globalDelta = details.globalPosition - _dragStartGlobalPosition;
if (globalDelta.dy > 1) {
_dragMode = _DragMode.dismiss;
} else if (globalDelta.dy < -1) {
_dragMode = _DragMode.scroll;
} else {
return;
}
// Fall through to process this update immediately
}
if (_dragMode == _DragMode.dismiss) {
final delta = details.localPosition - dragDownPosition; final delta = details.localPosition - dragDownPosition;
hasDraggedDown ??= delta.dy > 0; _handleDragDown(ctx, delta);
if (!hasDraggedDown! || showingBottomSheet) {
_handleDragUp(ctx, delta);
return; return;
} }
_handleDragDown(ctx, delta); _scrollBy(details.delta.dy);
}
void _handleDragUp(BuildContext ctx, Offset delta) {
const double openThreshold = 50;
final position = initialPhotoViewState.position + Offset(0, delta.dy);
final distanceToOrigin = position.distance;
viewController?.updateMultiple(position: position);
// Moves the bottom sheet when the asset is being dragged up
if (showingBottomSheet && bottomSheetController.isAttached) {
final centre = (ctx.height * _kBottomSheetMinimumExtent);
bottomSheetController.jumpTo((centre + distanceToOrigin) / ctx.height);
}
if (distanceToOrigin > openThreshold && !showingBottomSheet && !ref.read(readonlyModeProvider)) {
_openBottomSheet(ctx);
}
} }
void _handleDragDown(BuildContext ctx, Offset delta) { void _handleDragDown(BuildContext ctx, Offset delta) {
@@ -382,54 +497,12 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
ref.read(assetViewerProvider.notifier).setOpacity(backgroundOpacity); ref.read(assetViewerProvider.notifier).setOpacity(backgroundOpacity);
} }
void _onTapDown(_, __, ___) { void _onTapUp(_, __, ___) {
if (!showingBottomSheet) { if (!showingDetails) {
ref.read(assetViewerProvider.notifier).toggleControls(); ref.read(assetViewerProvider.notifier).toggleControls();
} }
} }
bool _onNotification(Notification delta) {
if (delta is DraggableScrollableNotification) {
_handleDraggableNotification(delta);
}
// Handle sheet snap manually so that the it snaps only at _kBottomSheetSnapExtent but not after
// the isSnapping guard is to prevent the notification from recursively handling the
// notification, eventually resulting in a heap overflow
if (!isSnapping && delta is ScrollEndNotification) {
_snapBottomSheet();
}
return false;
}
void _handleDraggableNotification(DraggableScrollableNotification delta) {
final currentExtent = delta.extent;
final isDraggingDown = currentExtent < previousExtent;
previousExtent = currentExtent;
// Closes the bottom sheet if the user is dragging down
if (isDraggingDown && delta.extent < 0.67) {
if (dragInProgress) {
blockGestures = true;
}
// Jump to a lower position before starting close animation to prevent glitch
if (bottomSheetController.isAttached) {
bottomSheetController.jumpTo(0.67);
}
sheetCloseController?.close();
}
// If the asset is being dragged down, we do not want to update the asset position again
if (dragInProgress) {
return;
}
final verticalOffset = _getVerticalOffsetForBottomSheet(delta.extent);
// Moves the asset when the bottom sheet is being dragged
if (verticalOffset > 0) {
viewController?.position = Offset(0, -verticalOffset);
}
}
void _onEvent(Event event) { void _onEvent(Event event) {
if (event is TimelineReloadEvent) { if (event is TimelineReloadEvent) {
_onTimelineReloadEvent(); _onTimelineReloadEvent();
@@ -441,15 +514,18 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
return; return;
} }
if (event is ViewerOpenBottomSheetEvent) { if (event is ViewerShowDetailsEvent) {
final extent = _kBottomSheetMinimumExtent + 0.3; _showDetails();
_openBottomSheet(scaffoldContext!, extent: extent, activitiesMode: event.activitiesMode);
final offset = _getVerticalOffsetForBottomSheet(extent);
viewController?.position = Offset(0, -offset);
return; return;
} }
} }
void _showDetails() {
if (!_scrollController.hasClients || _currentSnapOffset <= 0) return;
_ballisticAnimController.stop();
_animateScrollTo(_currentSnapOffset, 0);
}
void _onTimelineReloadEvent() { void _onTimelineReloadEvent() {
totalAssets = ref.read(timelineServiceProvider).totalAssets; totalAssets = ref.read(timelineServiceProvider).totalAssets;
if (totalAssets == 0) { if (totalAssets == 0) {
@@ -474,57 +550,16 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
} }
final currentAsset = ref.read(currentAssetNotifier); final currentAsset = ref.read(currentAssetNotifier);
// Do not reload / close the bottom sheet if the asset has not changed // Do not reload if the asset has not changed
if (newAsset.heroTag == currentAsset?.heroTag) { if (newAsset.heroTag == currentAsset?.heroTag) {
return; return;
} }
setState(() { setState(() {
_onAssetChanged(pageController.page!.round()); _onAssetChanged(pageController.page!.round());
sheetCloseController?.close();
}); });
} }
void _openBottomSheet(BuildContext ctx, {double extent = _kBottomSheetMinimumExtent, bool activitiesMode = false}) {
ref.read(assetViewerProvider.notifier).setBottomSheet(true);
previousExtent = _kBottomSheetMinimumExtent;
sheetCloseController = showBottomSheet(
context: ctx,
sheetAnimationStyle: const AnimationStyle(duration: Durations.medium2, reverseDuration: Durations.medium2),
constraints: const BoxConstraints(maxWidth: double.infinity),
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(20.0))),
backgroundColor: ctx.colorScheme.surfaceContainerLowest,
builder: (_) {
return NotificationListener<Notification>(
onNotification: _onNotification,
child: activitiesMode
? ActivitiesBottomSheet(controller: bottomSheetController, initialChildSize: extent)
: AssetDetailBottomSheet(controller: bottomSheetController, initialChildSize: extent),
);
},
);
sheetCloseController?.closed.then((_) => _handleSheetClose());
}
void _handleSheetClose() {
viewController?.animateMultiple(position: Offset.zero);
viewController?.updateMultiple(scale: viewController?.initialScale);
ref.read(assetViewerProvider.notifier).setBottomSheet(false);
sheetCloseController = null;
shouldPopOnDrag = false;
hasDraggedDown = null;
}
void _snapBottomSheet() {
if (!bottomSheetController.isAttached ||
bottomSheetController.size > _kBottomSheetSnapExtent ||
bottomSheetController.size < 0.4) {
return;
}
isSnapping = true;
bottomSheetController.animateTo(_kBottomSheetSnapExtent, duration: Durations.short3, curve: Curves.easeOut);
}
Widget _placeholderBuilder(BuildContext ctx, ImageChunkEvent? progress, int index) { Widget _placeholderBuilder(BuildContext ctx, ImageChunkEvent? progress, int index) {
return const Center(child: ImmichLoadingIndicator()); return const Center(child: ImmichLoadingIndicator());
} }
@@ -538,7 +573,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
return; return;
} }
if (!showingBottomSheet) { if (!showingDetails) {
ref.read(assetViewerProvider.notifier).setControls(true); ref.read(assetViewerProvider.notifier).setControls(true);
} }
} }
@@ -587,11 +622,11 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
heroAttributes: PhotoViewHeroAttributes(tag: '${asset.heroTag}_$heroOffset'), heroAttributes: PhotoViewHeroAttributes(tag: '${asset.heroTag}_$heroOffset'),
filterQuality: FilterQuality.high, filterQuality: FilterQuality.high,
tightMode: true, tightMode: true,
disableScaleGestures: showingBottomSheet, disableScaleGestures: showingDetails,
onDragStart: _onDragStart, onDragStart: _onDragStart,
onDragUpdate: _onDragUpdate, onDragUpdate: _onDragUpdate,
onDragEnd: _onDragEnd, onDragEnd: _onDragEnd,
onTapDown: _onTapDown, onTapUp: _onTapUp,
onLongPressStart: asset.isMotionPhoto ? _onLongPress : null, onLongPressStart: asset.isMotionPhoto ? _onLongPress : null,
errorBuilder: (_, __, ___) => Container( errorBuilder: (_, __, ___) => Container(
width: size.width, width: size.width,
@@ -612,7 +647,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
onDragStart: _onDragStart, onDragStart: _onDragStart,
onDragUpdate: _onDragUpdate, onDragUpdate: _onDragUpdate,
onDragEnd: _onDragEnd, onDragEnd: _onDragEnd,
onTapDown: _onTapDown, onTapUp: _onTapUp,
heroAttributes: PhotoViewHeroAttributes(tag: '${asset.heroTag}_$heroOffset'), heroAttributes: PhotoViewHeroAttributes(tag: '${asset.heroTag}_$heroOffset'),
filterQuality: FilterQuality.high, filterQuality: FilterQuality.high,
maxScale: 1.0, maxScale: 1.0,
@@ -645,7 +680,6 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Rebuild the widget when the asset viewer state changes // Rebuild the widget when the asset viewer state changes
// Using multiple selectors to avoid unnecessary rebuilds for other state changes // Using multiple selectors to avoid unnecessary rebuilds for other state changes
ref.watch(assetViewerProvider.select((s) => s.showingBottomSheet));
ref.watch(assetViewerProvider.select((s) => s.backgroundOpacity)); ref.watch(assetViewerProvider.select((s) => s.backgroundOpacity));
ref.watch(assetViewerProvider.select((s) => s.stackIndex)); ref.watch(assetViewerProvider.select((s) => s.stackIndex));
ref.watch(isPlayingMotionVideoProvider); ref.watch(isPlayingMotionVideoProvider);
@@ -672,9 +706,6 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
} }
}); });
// Currently it is not possible to scroll the asset when the bottom sheet is open all the way.
// Issue: https://github.com/flutter/flutter/issues/109037
// TODO: Add a custom scrum builder once the fix lands on stable
return PopScope( return PopScope(
onPopInvokedWithResult: _onPop, onPopInvokedWithResult: _onPop,
child: Scaffold( child: Scaffold(
@@ -690,9 +721,48 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
child: const DownloadStatusFloatingButton(), child: const DownloadStatusFloatingButton(),
), ),
), ),
body: Stack( body: LayoutBuilder(
builder: (context, constraints) {
final viewportWidth = constraints.maxWidth;
final viewportHeight = constraints.maxHeight;
// Use the actual rendered image size from PhotoView when available,
// falling back to a calculation from asset metadata.
final sb = viewController?.scaleBoundaries;
double imageHeight;
if (sb != null) {
imageHeight = sb.childSize.height * sb.initialScale;
} else {
final asset = ref.read(currentAssetNotifier);
final assetWidth = asset?.width;
final assetHeight = asset?.height;
imageHeight = viewportHeight;
if (assetWidth != null && assetHeight != null && assetWidth > 0 && assetHeight > 0) {
final aspectRatio = assetWidth / assetHeight;
imageHeight = math.min(viewportWidth / aspectRatio, viewportHeight);
}
}
// Calculate padding to center the image in the viewport
final topPadding = math.max((viewportHeight - imageHeight) / 2, 0.0);
final snapOffset = math.max(topPadding + (imageHeight / 2), viewportHeight / 4 * 3);
_currentSnapOffset = snapOffset;
return Stack(
clipBehavior: Clip.none,
children: [ children: [
PhotoViewGallery.builder( SingleChildScrollView(
controller: _scrollController,
physics: const NeverScrollableScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedOverflowBox(
size: Size(double.infinity, topPadding + imageHeight - (kMinInteractiveDimension / 2)),
alignment: Alignment.topCenter,
child: SizedBox(
height: viewportHeight,
child: PhotoViewGallery.builder(
gaplessPlayback: true, gaplessPlayback: true,
loadingBuilder: _placeholderBuilder, loadingBuilder: _placeholderBuilder,
pageController: pageController, pageController: pageController,
@@ -701,18 +771,33 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
: const FastClampingScrollPhysics(), // Use heavy physics for Android : const FastClampingScrollPhysics(), // Use heavy physics for Android
itemCount: totalAssets, itemCount: totalAssets,
onPageChanged: _onPageChanged, onPageChanged: _onPageChanged,
onPageBuild: _onPageBuild,
scaleStateChangedCallback: _onScaleStateChanged, scaleStateChangedCallback: _onScaleStateChanged,
builder: _assetBuilder, builder: _assetBuilder,
backgroundDecoration: BoxDecoration(color: backgroundColor), backgroundDecoration: BoxDecoration(color: backgroundColor),
enablePanAlways: true, enablePanAlways: true,
), ),
if (!showingBottomSheet) ),
const Positioned( ),
GestureDetector(
onVerticalDragStart: (_) => _ballisticAnimController.stop(),
onVerticalDragUpdate: (details) => _scrollBy(details.delta.dy),
onVerticalDragEnd: (details) => _snapScroll(-details.velocity.pixelsPerSecond.dy),
child: AnimatedOpacity(
opacity: _assetDetailsOpacity,
duration: kThemeAnimationDuration,
child: AssetDetails(minHeight: viewportHeight / 4 * 3),
),
),
],
),
),
Positioned(
height: viewportHeight,
bottom: 0, bottom: 0,
left: 0, left: 0,
right: 0, right: 0,
child: Column( child: const Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
@@ -720,6 +805,8 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
), ),
), ),
], ],
);
},
), ),
), ),
); );
@@ -55,7 +55,7 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget {
IconButton( IconButton(
icon: const Icon(Icons.chat_outlined), icon: const Icon(Icons.chat_outlined),
onPressed: () { onPressed: () {
EventStream.shared.emit(const ViewerOpenBottomSheetEvent(activitiesMode: true)); EventStream.shared.emit(const ViewerShowDetailsEvent(activitiesMode: true));
}, },
), ),
@@ -15,7 +15,7 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
: super( : super(
const ServerInfo( const ServerInfo(
serverVersion: ServerVersion(major: 0, minor: 0, patch: 0), serverVersion: ServerVersion(major: 0, minor: 0, patch: 0),
latestVersion: ServerVersion(major: 0, minor: 0, patch: 0), latestVersion: null,
serverFeatures: ServerFeatures(map: true, trash: true, oauthEnabled: false, passwordLogin: true), serverFeatures: ServerFeatures(map: true, trash: true, oauthEnabled: false, passwordLogin: true),
serverConfig: ServerConfig( serverConfig: ServerConfig(
trashDays: 30, trashDays: 30,
@@ -43,7 +43,7 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
try { try {
final serverVersion = await _serverInfoService.getServerVersion(); final serverVersion = await _serverInfoService.getServerVersion();
// using isClientOutOfDate since that will show to users reguardless of if they are an admin // using isClientOutOfDate since that will show to users regardless of if they are an admin
if (serverVersion == null) { if (serverVersion == null) {
state = state.copyWith(versionStatus: VersionStatus.error); state = state.copyWith(versionStatus: VersionStatus.error);
return; return;
@@ -76,7 +76,7 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
state = state.copyWith(versionStatus: VersionStatus.upToDate); state = state.copyWith(versionStatus: VersionStatus.upToDate);
} }
handleReleaseInfo(ServerVersion serverVersion, ServerVersion latestVersion) { handleReleaseInfo(ServerVersion serverVersion, ServerVersion? latestVersion) {
// Update local server version // Update local server version
_checkServerVersionMismatch(serverVersion, latestVersion: latestVersion); _checkServerVersionMismatch(serverVersion, latestVersion: latestVersion);
} }
+1 -1
View File
@@ -225,7 +225,7 @@ enum ActionButtonType {
iconData: Icons.info_outline, iconData: Icons.info_outline,
iconColor: context.originalTheme?.iconTheme.color, iconColor: context.originalTheme?.iconTheme.color,
menuItem: true, menuItem: true,
onPressed: () => EventStream.shared.emit(const ViewerOpenBottomSheetEvent()), onPressed: () => EventStream.shared.emit(const ViewerShowDetailsEvent()),
), ),
ActionButtonType.viewInTimeline => BaseActionButton( ActionButtonType.viewInTimeline => BaseActionButton(
label: 'view_in_timeline'.tr(), label: 'view_in_timeline'.tr(),
@@ -170,6 +170,7 @@ class AppBarServerInfo extends HookConsumerWidget {
), ),
], ],
), ),
if (serverInfoState.latestVersion != null) ...[
const Padding(padding: EdgeInsets.symmetric(horizontal: 10), child: Divider(thickness: 1)), const Padding(padding: EdgeInsets.symmetric(horizontal: 10), child: Divider(thickness: 1)),
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -201,8 +202,8 @@ class AppBarServerInfo extends HookConsumerWidget {
child: Padding( child: Padding(
padding: const EdgeInsets.only(right: 10.0), padding: const EdgeInsets.only(right: 10.0),
child: Text( child: Text(
serverInfoState.latestVersion.major > 0 serverInfoState.latestVersion!.major > 0
? "${serverInfoState.latestVersion.major}.${serverInfoState.latestVersion.minor}.${serverInfoState.latestVersion.patch}" ? "${serverInfoState.latestVersion!.major}.${serverInfoState.latestVersion!.minor}.${serverInfoState.latestVersion!.patch}"
: "--", : "--",
style: TextStyle( style: TextStyle(
fontSize: contentFontSize, fontSize: contentFontSize,
@@ -215,6 +216,7 @@ class AppBarServerInfo extends HookConsumerWidget {
], ],
), ),
], ],
],
), ),
), ),
), ),
@@ -414,6 +414,7 @@ class LoginForm extends HookConsumerWidget {
keyboardAction: TextInputAction.next, keyboardAction: TextInputAction.next,
keyboardType: TextInputType.url, keyboardType: TextInputType.url,
autofillHints: const [AutofillHints.url], autofillHints: const [AutofillHints.url],
autoCorrect: false,
onSubmit: (ctx, _) => ImmichForm.of(ctx).submit(), onSubmit: (ctx, _) => ImmichForm.of(ctx).submit(),
), ),
), ),
@@ -203,9 +203,13 @@ class PhotoViewGestureRecognizer extends ScaleGestureRecognizer {
void _decideIfWeAcceptEvent(PointerEvent event) { void _decideIfWeAcceptEvent(PointerEvent event) {
final move = _initialFocalPoint! - _currentFocalPoint!; final move = _initialFocalPoint! - _currentFocalPoint!;
final bool shouldMove = validateAxis == Axis.vertical
? hitDetector!.shouldMove(move, Axis.vertical) // Accept gesture if movement is possible in the direction the user is swiping
: hitDetector!.shouldMove(move, Axis.horizontal); final bool isHorizontalGesture = move.dx.abs() > move.dy.abs();
final bool shouldMove = isHorizontalGesture
? hitDetector!.shouldMove(move, Axis.horizontal)
: hitDetector!.shouldMove(move, Axis.vertical);
if (shouldMove || _pointerLocations.keys.length > 1) { if (shouldMove || _pointerLocations.keys.length > 1) {
final double spanDelta = (_currentSpan! - _initialSpan!).abs(); final double spanDelta = (_currentSpan! - _initialSpan!).abs();
final double focalPointDelta = (_currentFocalPoint! - _initialFocalPoint!).distance; final double focalPointDelta = (_currentFocalPoint! - _initialFocalPoint!).distance;
+1 -1
View File
@@ -3,7 +3,7 @@ Immich API
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
- API version: 2.5.1 - API version: 2.5.2
- Generator version: 7.8.0 - Generator version: 7.8.0
- Build package: org.openapitools.codegen.languages.DartClientCodegen - Build package: org.openapitools.codegen.languages.DartClientCodegen
+14
View File
@@ -130,14 +130,19 @@ class ActivitiesApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] albumId (required): /// * [String] albumId (required):
/// Album ID
/// ///
/// * [String] assetId: /// * [String] assetId:
/// Asset ID (if activity is for an asset)
/// ///
/// * [ReactionLevel] level: /// * [ReactionLevel] level:
/// Filter by activity level
/// ///
/// * [ReactionType] type: /// * [ReactionType] type:
/// Filter by activity type
/// ///
/// * [String] userId: /// * [String] userId:
/// Filter by user ID
Future<Response> getActivitiesWithHttpInfo(String albumId, { String? assetId, ReactionLevel? level, ReactionType? type, String? userId, }) async { Future<Response> getActivitiesWithHttpInfo(String albumId, { String? assetId, ReactionLevel? level, ReactionType? type, String? userId, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/activities'; final apiPath = r'/activities';
@@ -184,14 +189,19 @@ class ActivitiesApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] albumId (required): /// * [String] albumId (required):
/// Album ID
/// ///
/// * [String] assetId: /// * [String] assetId:
/// Asset ID (if activity is for an asset)
/// ///
/// * [ReactionLevel] level: /// * [ReactionLevel] level:
/// Filter by activity level
/// ///
/// * [ReactionType] type: /// * [ReactionType] type:
/// Filter by activity type
/// ///
/// * [String] userId: /// * [String] userId:
/// Filter by user ID
Future<List<ActivityResponseDto>?> getActivities(String albumId, { String? assetId, ReactionLevel? level, ReactionType? type, String? userId, }) async { Future<List<ActivityResponseDto>?> getActivities(String albumId, { String? assetId, ReactionLevel? level, ReactionType? type, String? userId, }) async {
final response = await getActivitiesWithHttpInfo(albumId, assetId: assetId, level: level, type: type, userId: userId, ); final response = await getActivitiesWithHttpInfo(albumId, assetId: assetId, level: level, type: type, userId: userId, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -219,8 +229,10 @@ class ActivitiesApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] albumId (required): /// * [String] albumId (required):
/// Album ID
/// ///
/// * [String] assetId: /// * [String] assetId:
/// Asset ID (if activity is for an asset)
Future<Response> getActivityStatisticsWithHttpInfo(String albumId, { String? assetId, }) async { Future<Response> getActivityStatisticsWithHttpInfo(String albumId, { String? assetId, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/activities/statistics'; final apiPath = r'/activities/statistics';
@@ -258,8 +270,10 @@ class ActivitiesApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] albumId (required): /// * [String] albumId (required):
/// Album ID
/// ///
/// * [String] assetId: /// * [String] assetId:
/// Asset ID (if activity is for an asset)
Future<ActivityStatisticsResponseDto?> getActivityStatistics(String albumId, { String? assetId, }) async { Future<ActivityStatisticsResponseDto?> getActivityStatistics(String albumId, { String? assetId, }) async {
final response = await getActivityStatisticsWithHttpInfo(albumId, assetId: assetId, ); final response = await getActivityStatisticsWithHttpInfo(albumId, assetId: assetId, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
+6 -2
View File
@@ -347,6 +347,7 @@ class AlbumsApi {
/// * [String] slug: /// * [String] slug:
/// ///
/// * [bool] withoutAssets: /// * [bool] withoutAssets:
/// Exclude assets from response
Future<Response> getAlbumInfoWithHttpInfo(String id, { String? key, String? slug, bool? withoutAssets, }) async { Future<Response> getAlbumInfoWithHttpInfo(String id, { String? key, String? slug, bool? withoutAssets, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/albums/{id}' final apiPath = r'/albums/{id}'
@@ -396,6 +397,7 @@ class AlbumsApi {
/// * [String] slug: /// * [String] slug:
/// ///
/// * [bool] withoutAssets: /// * [bool] withoutAssets:
/// Exclude assets from response
Future<AlbumResponseDto?> getAlbumInfo(String id, { String? key, String? slug, bool? withoutAssets, }) async { Future<AlbumResponseDto?> getAlbumInfo(String id, { String? key, String? slug, bool? withoutAssets, }) async {
final response = await getAlbumInfoWithHttpInfo(id, key: key, slug: slug, withoutAssets: withoutAssets, ); final response = await getAlbumInfoWithHttpInfo(id, key: key, slug: slug, withoutAssets: withoutAssets, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -468,9 +470,10 @@ class AlbumsApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] assetId: /// * [String] assetId:
/// Only returns albums that contain the asset Ignores the shared parameter undefined: get all albums /// Filter albums containing this asset ID (ignores shared parameter)
/// ///
/// * [bool] shared: /// * [bool] shared:
/// Filter by shared status: true = only shared, false = only own, undefined = all
Future<Response> getAllAlbumsWithHttpInfo({ String? assetId, bool? shared, }) async { Future<Response> getAllAlbumsWithHttpInfo({ String? assetId, bool? shared, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/albums'; final apiPath = r'/albums';
@@ -510,9 +513,10 @@ class AlbumsApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] assetId: /// * [String] assetId:
/// Only returns albums that contain the asset Ignores the shared parameter undefined: get all albums /// Filter albums containing this asset ID (ignores shared parameter)
/// ///
/// * [bool] shared: /// * [bool] shared:
/// Filter by shared status: true = only shared, false = only own, undefined = all
Future<List<AlbumResponseDto>?> getAllAlbums({ String? assetId, bool? shared, }) async { Future<List<AlbumResponseDto>?> getAllAlbums({ String? assetId, bool? shared, }) async {
final response = await getAllAlbumsWithHttpInfo( assetId: assetId, shared: shared, ); final response = await getAllAlbumsWithHttpInfo( assetId: assetId, shared: shared, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
+62
View File
@@ -185,8 +185,10 @@ class AssetsApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] id (required): /// * [String] id (required):
/// Asset ID
/// ///
/// * [String] key (required): /// * [String] key (required):
/// Metadata key
Future<Response> deleteAssetMetadataWithHttpInfo(String id, String key,) async { Future<Response> deleteAssetMetadataWithHttpInfo(String id, String key,) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/assets/{id}/metadata/{key}' final apiPath = r'/assets/{id}/metadata/{key}'
@@ -221,8 +223,10 @@ class AssetsApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] id (required): /// * [String] id (required):
/// Asset ID
/// ///
/// * [String] key (required): /// * [String] key (required):
/// Metadata key
Future<void> deleteAssetMetadata(String id, String key,) async { Future<void> deleteAssetMetadata(String id, String key,) async {
final response = await deleteAssetMetadataWithHttpInfo(id, key,); final response = await deleteAssetMetadataWithHttpInfo(id, key,);
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -337,6 +341,7 @@ class AssetsApi {
/// * [String] id (required): /// * [String] id (required):
/// ///
/// * [bool] edited: /// * [bool] edited:
/// Return edited asset if available
/// ///
/// * [String] key: /// * [String] key:
/// ///
@@ -386,6 +391,7 @@ class AssetsApi {
/// * [String] id (required): /// * [String] id (required):
/// ///
/// * [bool] edited: /// * [bool] edited:
/// Return edited asset if available
/// ///
/// * [String] key: /// * [String] key:
/// ///
@@ -475,6 +481,7 @@ class AssetsApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] deviceId (required): /// * [String] deviceId (required):
/// Device ID
Future<Response> getAllUserAssetsByDeviceIdWithHttpInfo(String deviceId,) async { Future<Response> getAllUserAssetsByDeviceIdWithHttpInfo(String deviceId,) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/assets/device/{deviceId}' final apiPath = r'/assets/device/{deviceId}'
@@ -508,6 +515,7 @@ class AssetsApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] deviceId (required): /// * [String] deviceId (required):
/// Device ID
Future<List<String>?> getAllUserAssetsByDeviceId(String deviceId,) async { Future<List<String>?> getAllUserAssetsByDeviceId(String deviceId,) async {
final response = await getAllUserAssetsByDeviceIdWithHttpInfo(deviceId,); final response = await getAllUserAssetsByDeviceIdWithHttpInfo(deviceId,);
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -724,8 +732,10 @@ class AssetsApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] id (required): /// * [String] id (required):
/// Asset ID
/// ///
/// * [String] key (required): /// * [String] key (required):
/// Metadata key
Future<Response> getAssetMetadataByKeyWithHttpInfo(String id, String key,) async { Future<Response> getAssetMetadataByKeyWithHttpInfo(String id, String key,) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/assets/{id}/metadata/{key}' final apiPath = r'/assets/{id}/metadata/{key}'
@@ -760,8 +770,10 @@ class AssetsApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] id (required): /// * [String] id (required):
/// Asset ID
/// ///
/// * [String] key (required): /// * [String] key (required):
/// Metadata key
Future<AssetMetadataResponseDto?> getAssetMetadataByKey(String id, String key,) async { Future<AssetMetadataResponseDto?> getAssetMetadataByKey(String id, String key,) async {
final response = await getAssetMetadataByKeyWithHttpInfo(id, key,); final response = await getAssetMetadataByKeyWithHttpInfo(id, key,);
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -846,10 +858,13 @@ class AssetsApi {
/// Parameters: /// Parameters:
/// ///
/// * [bool] isFavorite: /// * [bool] isFavorite:
/// Filter by favorite status
/// ///
/// * [bool] isTrashed: /// * [bool] isTrashed:
/// Filter by trash status
/// ///
/// * [AssetVisibility] visibility: /// * [AssetVisibility] visibility:
/// Filter by visibility
Future<Response> getAssetStatisticsWithHttpInfo({ bool? isFavorite, bool? isTrashed, AssetVisibility? visibility, }) async { Future<Response> getAssetStatisticsWithHttpInfo({ bool? isFavorite, bool? isTrashed, AssetVisibility? visibility, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/assets/statistics'; final apiPath = r'/assets/statistics';
@@ -892,10 +907,13 @@ class AssetsApi {
/// Parameters: /// Parameters:
/// ///
/// * [bool] isFavorite: /// * [bool] isFavorite:
/// Filter by favorite status
/// ///
/// * [bool] isTrashed: /// * [bool] isTrashed:
/// Filter by trash status
/// ///
/// * [AssetVisibility] visibility: /// * [AssetVisibility] visibility:
/// Filter by visibility
Future<AssetStatsResponseDto?> getAssetStatistics({ bool? isFavorite, bool? isTrashed, AssetVisibility? visibility, }) async { Future<AssetStatsResponseDto?> getAssetStatistics({ bool? isFavorite, bool? isTrashed, AssetVisibility? visibility, }) async {
final response = await getAssetStatisticsWithHttpInfo( isFavorite: isFavorite, isTrashed: isTrashed, visibility: visibility, ); final response = await getAssetStatisticsWithHttpInfo( isFavorite: isFavorite, isTrashed: isTrashed, visibility: visibility, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -920,6 +938,7 @@ class AssetsApi {
/// Parameters: /// Parameters:
/// ///
/// * [num] count: /// * [num] count:
/// Number of random assets to return
Future<Response> getRandomWithHttpInfo({ num? count, }) async { Future<Response> getRandomWithHttpInfo({ num? count, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/assets/random'; final apiPath = r'/assets/random';
@@ -956,6 +975,7 @@ class AssetsApi {
/// Parameters: /// Parameters:
/// ///
/// * [num] count: /// * [num] count:
/// Number of random assets to return
Future<List<AssetResponseDto>?> getRandom({ num? count, }) async { Future<List<AssetResponseDto>?> getRandom({ num? count, }) async {
final response = await getRandomWithHttpInfo( count: count, ); final response = await getRandomWithHttpInfo( count: count, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -1106,22 +1126,29 @@ class AssetsApi {
/// * [String] id (required): /// * [String] id (required):
/// ///
/// * [MultipartFile] assetData (required): /// * [MultipartFile] assetData (required):
/// Asset file data
/// ///
/// * [String] deviceAssetId (required): /// * [String] deviceAssetId (required):
/// Device asset ID
/// ///
/// * [String] deviceId (required): /// * [String] deviceId (required):
/// Device ID
/// ///
/// * [DateTime] fileCreatedAt (required): /// * [DateTime] fileCreatedAt (required):
/// File creation date
/// ///
/// * [DateTime] fileModifiedAt (required): /// * [DateTime] fileModifiedAt (required):
/// File modification date
/// ///
/// * [String] key: /// * [String] key:
/// ///
/// * [String] slug: /// * [String] slug:
/// ///
/// * [String] duration: /// * [String] duration:
/// Duration (for videos)
/// ///
/// * [String] filename: /// * [String] filename:
/// Filename
Future<Response> replaceAssetWithHttpInfo(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? duration, String? filename, }) async { Future<Response> replaceAssetWithHttpInfo(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? duration, String? filename, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/assets/{id}/original' final apiPath = r'/assets/{id}/original'
@@ -1198,22 +1225,29 @@ class AssetsApi {
/// * [String] id (required): /// * [String] id (required):
/// ///
/// * [MultipartFile] assetData (required): /// * [MultipartFile] assetData (required):
/// Asset file data
/// ///
/// * [String] deviceAssetId (required): /// * [String] deviceAssetId (required):
/// Device asset ID
/// ///
/// * [String] deviceId (required): /// * [String] deviceId (required):
/// Device ID
/// ///
/// * [DateTime] fileCreatedAt (required): /// * [DateTime] fileCreatedAt (required):
/// File creation date
/// ///
/// * [DateTime] fileModifiedAt (required): /// * [DateTime] fileModifiedAt (required):
/// File modification date
/// ///
/// * [String] key: /// * [String] key:
/// ///
/// * [String] slug: /// * [String] slug:
/// ///
/// * [String] duration: /// * [String] duration:
/// Duration (for videos)
/// ///
/// * [String] filename: /// * [String] filename:
/// Filename
Future<AssetMediaResponseDto?> replaceAsset(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? duration, String? filename, }) async { Future<AssetMediaResponseDto?> replaceAsset(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? duration, String? filename, }) async {
final response = await replaceAssetWithHttpInfo(id, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, slug: slug, duration: duration, filename: filename, ); final response = await replaceAssetWithHttpInfo(id, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, slug: slug, duration: duration, filename: filename, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -1518,14 +1552,19 @@ class AssetsApi {
/// Parameters: /// Parameters:
/// ///
/// * [MultipartFile] assetData (required): /// * [MultipartFile] assetData (required):
/// Asset file data
/// ///
/// * [String] deviceAssetId (required): /// * [String] deviceAssetId (required):
/// Device asset ID
/// ///
/// * [String] deviceId (required): /// * [String] deviceId (required):
/// Device ID
/// ///
/// * [DateTime] fileCreatedAt (required): /// * [DateTime] fileCreatedAt (required):
/// File creation date
/// ///
/// * [DateTime] fileModifiedAt (required): /// * [DateTime] fileModifiedAt (required):
/// File modification date
/// ///
/// * [String] key: /// * [String] key:
/// ///
@@ -1535,18 +1574,25 @@ class AssetsApi {
/// sha1 checksum that can be used for duplicate detection before the file is uploaded /// sha1 checksum that can be used for duplicate detection before the file is uploaded
/// ///
/// * [String] duration: /// * [String] duration:
/// Duration (for videos)
/// ///
/// * [String] filename: /// * [String] filename:
/// Filename
/// ///
/// * [bool] isFavorite: /// * [bool] isFavorite:
/// Mark as favorite
/// ///
/// * [String] livePhotoVideoId: /// * [String] livePhotoVideoId:
/// Live photo video ID
/// ///
/// * [List<AssetMetadataUpsertItemDto>] metadata: /// * [List<AssetMetadataUpsertItemDto>] metadata:
/// Asset metadata items
/// ///
/// * [MultipartFile] sidecarData: /// * [MultipartFile] sidecarData:
/// Sidecar file data
/// ///
/// * [AssetVisibility] visibility: /// * [AssetVisibility] visibility:
/// Asset visibility
Future<Response> uploadAssetWithHttpInfo(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? xImmichChecksum, String? duration, String? filename, bool? isFavorite, String? livePhotoVideoId, List<AssetMetadataUpsertItemDto>? metadata, MultipartFile? sidecarData, AssetVisibility? visibility, }) async { Future<Response> uploadAssetWithHttpInfo(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? xImmichChecksum, String? duration, String? filename, bool? isFavorite, String? livePhotoVideoId, List<AssetMetadataUpsertItemDto>? metadata, MultipartFile? sidecarData, AssetVisibility? visibility, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/assets'; final apiPath = r'/assets';
@@ -1645,14 +1691,19 @@ class AssetsApi {
/// Parameters: /// Parameters:
/// ///
/// * [MultipartFile] assetData (required): /// * [MultipartFile] assetData (required):
/// Asset file data
/// ///
/// * [String] deviceAssetId (required): /// * [String] deviceAssetId (required):
/// Device asset ID
/// ///
/// * [String] deviceId (required): /// * [String] deviceId (required):
/// Device ID
/// ///
/// * [DateTime] fileCreatedAt (required): /// * [DateTime] fileCreatedAt (required):
/// File creation date
/// ///
/// * [DateTime] fileModifiedAt (required): /// * [DateTime] fileModifiedAt (required):
/// File modification date
/// ///
/// * [String] key: /// * [String] key:
/// ///
@@ -1662,18 +1713,25 @@ class AssetsApi {
/// sha1 checksum that can be used for duplicate detection before the file is uploaded /// sha1 checksum that can be used for duplicate detection before the file is uploaded
/// ///
/// * [String] duration: /// * [String] duration:
/// Duration (for videos)
/// ///
/// * [String] filename: /// * [String] filename:
/// Filename
/// ///
/// * [bool] isFavorite: /// * [bool] isFavorite:
/// Mark as favorite
/// ///
/// * [String] livePhotoVideoId: /// * [String] livePhotoVideoId:
/// Live photo video ID
/// ///
/// * [List<AssetMetadataUpsertItemDto>] metadata: /// * [List<AssetMetadataUpsertItemDto>] metadata:
/// Asset metadata items
/// ///
/// * [MultipartFile] sidecarData: /// * [MultipartFile] sidecarData:
/// Sidecar file data
/// ///
/// * [AssetVisibility] visibility: /// * [AssetVisibility] visibility:
/// Asset visibility
Future<AssetMediaResponseDto?> uploadAsset(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? xImmichChecksum, String? duration, String? filename, bool? isFavorite, String? livePhotoVideoId, List<AssetMetadataUpsertItemDto>? metadata, MultipartFile? sidecarData, AssetVisibility? visibility, }) async { Future<AssetMediaResponseDto?> uploadAsset(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? xImmichChecksum, String? duration, String? filename, bool? isFavorite, String? livePhotoVideoId, List<AssetMetadataUpsertItemDto>? metadata, MultipartFile? sidecarData, AssetVisibility? visibility, }) async {
final response = await uploadAssetWithHttpInfo(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, slug: slug, xImmichChecksum: xImmichChecksum, duration: duration, filename: filename, isFavorite: isFavorite, livePhotoVideoId: livePhotoVideoId, metadata: metadata, sidecarData: sidecarData, visibility: visibility, ); final response = await uploadAssetWithHttpInfo(assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, slug: slug, xImmichChecksum: xImmichChecksum, duration: duration, filename: filename, isFavorite: isFavorite, livePhotoVideoId: livePhotoVideoId, metadata: metadata, sidecarData: sidecarData, visibility: visibility, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -1700,10 +1758,12 @@ class AssetsApi {
/// * [String] id (required): /// * [String] id (required):
/// ///
/// * [bool] edited: /// * [bool] edited:
/// Return edited asset if available
/// ///
/// * [String] key: /// * [String] key:
/// ///
/// * [AssetMediaSize] size: /// * [AssetMediaSize] size:
/// Asset media size
/// ///
/// * [String] slug: /// * [String] slug:
Future<Response> viewAssetWithHttpInfo(String id, { bool? edited, String? key, AssetMediaSize? size, String? slug, }) async { Future<Response> viewAssetWithHttpInfo(String id, { bool? edited, String? key, AssetMediaSize? size, String? slug, }) async {
@@ -1754,10 +1814,12 @@ class AssetsApi {
/// * [String] id (required): /// * [String] id (required):
/// ///
/// * [bool] edited: /// * [bool] edited:
/// Return edited asset if available
/// ///
/// * [String] key: /// * [String] key:
/// ///
/// * [AssetMediaSize] size: /// * [AssetMediaSize] size:
/// Asset media size
/// ///
/// * [String] slug: /// * [String] slug:
Future<MultipartFile?> viewAsset(String id, { bool? edited, String? key, AssetMediaSize? size, String? slug, }) async { Future<MultipartFile?> viewAsset(String id, { bool? edited, String? key, AssetMediaSize? size, String? slug, }) async {
+20
View File
@@ -82,6 +82,7 @@ class DeprecatedApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] deviceId (required): /// * [String] deviceId (required):
/// Device ID
Future<Response> getAllUserAssetsByDeviceIdWithHttpInfo(String deviceId,) async { Future<Response> getAllUserAssetsByDeviceIdWithHttpInfo(String deviceId,) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/assets/device/{deviceId}' final apiPath = r'/assets/device/{deviceId}'
@@ -115,6 +116,7 @@ class DeprecatedApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] deviceId (required): /// * [String] deviceId (required):
/// Device ID
Future<List<String>?> getAllUserAssetsByDeviceId(String deviceId,) async { Future<List<String>?> getAllUserAssetsByDeviceId(String deviceId,) async {
final response = await getAllUserAssetsByDeviceIdWithHttpInfo(deviceId,); final response = await getAllUserAssetsByDeviceIdWithHttpInfo(deviceId,);
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -305,6 +307,7 @@ class DeprecatedApi {
/// Parameters: /// Parameters:
/// ///
/// * [num] count: /// * [num] count:
/// Number of random assets to return
Future<Response> getRandomWithHttpInfo({ num? count, }) async { Future<Response> getRandomWithHttpInfo({ num? count, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/assets/random'; final apiPath = r'/assets/random';
@@ -341,6 +344,7 @@ class DeprecatedApi {
/// Parameters: /// Parameters:
/// ///
/// * [num] count: /// * [num] count:
/// Number of random assets to return
Future<List<AssetResponseDto>?> getRandom({ num? count, }) async { Future<List<AssetResponseDto>?> getRandom({ num? count, }) async {
final response = await getRandomWithHttpInfo( count: count, ); final response = await getRandomWithHttpInfo( count: count, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -370,22 +374,29 @@ class DeprecatedApi {
/// * [String] id (required): /// * [String] id (required):
/// ///
/// * [MultipartFile] assetData (required): /// * [MultipartFile] assetData (required):
/// Asset file data
/// ///
/// * [String] deviceAssetId (required): /// * [String] deviceAssetId (required):
/// Device asset ID
/// ///
/// * [String] deviceId (required): /// * [String] deviceId (required):
/// Device ID
/// ///
/// * [DateTime] fileCreatedAt (required): /// * [DateTime] fileCreatedAt (required):
/// File creation date
/// ///
/// * [DateTime] fileModifiedAt (required): /// * [DateTime] fileModifiedAt (required):
/// File modification date
/// ///
/// * [String] key: /// * [String] key:
/// ///
/// * [String] slug: /// * [String] slug:
/// ///
/// * [String] duration: /// * [String] duration:
/// Duration (for videos)
/// ///
/// * [String] filename: /// * [String] filename:
/// Filename
Future<Response> replaceAssetWithHttpInfo(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? duration, String? filename, }) async { Future<Response> replaceAssetWithHttpInfo(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? duration, String? filename, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/assets/{id}/original' final apiPath = r'/assets/{id}/original'
@@ -462,22 +473,29 @@ class DeprecatedApi {
/// * [String] id (required): /// * [String] id (required):
/// ///
/// * [MultipartFile] assetData (required): /// * [MultipartFile] assetData (required):
/// Asset file data
/// ///
/// * [String] deviceAssetId (required): /// * [String] deviceAssetId (required):
/// Device asset ID
/// ///
/// * [String] deviceId (required): /// * [String] deviceId (required):
/// Device ID
/// ///
/// * [DateTime] fileCreatedAt (required): /// * [DateTime] fileCreatedAt (required):
/// File creation date
/// ///
/// * [DateTime] fileModifiedAt (required): /// * [DateTime] fileModifiedAt (required):
/// File modification date
/// ///
/// * [String] key: /// * [String] key:
/// ///
/// * [String] slug: /// * [String] slug:
/// ///
/// * [String] duration: /// * [String] duration:
/// Duration (for videos)
/// ///
/// * [String] filename: /// * [String] filename:
/// Filename
Future<AssetMediaResponseDto?> replaceAsset(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? duration, String? filename, }) async { Future<AssetMediaResponseDto?> replaceAsset(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? slug, String? duration, String? filename, }) async {
final response = await replaceAssetWithHttpInfo(id, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, slug: slug, duration: duration, filename: filename, ); final response = await replaceAssetWithHttpInfo(id, assetData, deviceAssetId, deviceId, fileCreatedAt, fileModifiedAt, key: key, slug: slug, duration: duration, filename: filename, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -502,6 +520,7 @@ class DeprecatedApi {
/// Parameters: /// Parameters:
/// ///
/// * [QueueName] name (required): /// * [QueueName] name (required):
/// Queue name
/// ///
/// * [QueueCommandDto] queueCommandDto (required): /// * [QueueCommandDto] queueCommandDto (required):
Future<Response> runQueueCommandLegacyWithHttpInfo(QueueName name, QueueCommandDto queueCommandDto,) async { Future<Response> runQueueCommandLegacyWithHttpInfo(QueueName name, QueueCommandDto queueCommandDto,) async {
@@ -537,6 +556,7 @@ class DeprecatedApi {
/// Parameters: /// Parameters:
/// ///
/// * [QueueName] name (required): /// * [QueueName] name (required):
/// Queue name
/// ///
/// * [QueueCommandDto] queueCommandDto (required): /// * [QueueCommandDto] queueCommandDto (required):
Future<QueueResponseLegacyDto?> runQueueCommandLegacy(QueueName name, QueueCommandDto queueCommandDto,) async { Future<QueueResponseLegacyDto?> runQueueCommandLegacy(QueueName name, QueueCommandDto queueCommandDto,) async {
+2
View File
@@ -126,6 +126,7 @@ class FacesApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] id (required): /// * [String] id (required):
/// Face ID
Future<Response> getFacesWithHttpInfo(String id,) async { Future<Response> getFacesWithHttpInfo(String id,) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/faces'; final apiPath = r'/faces';
@@ -160,6 +161,7 @@ class FacesApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] id (required): /// * [String] id (required):
/// Face ID
Future<List<AssetFaceResponseDto>?> getFaces(String id,) async { Future<List<AssetFaceResponseDto>?> getFaces(String id,) async {
final response = await getFacesWithHttpInfo(id,); final response = await getFacesWithHttpInfo(id,);
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
+2
View File
@@ -121,6 +121,7 @@ class JobsApi {
/// Parameters: /// Parameters:
/// ///
/// * [QueueName] name (required): /// * [QueueName] name (required):
/// Queue name
/// ///
/// * [QueueCommandDto] queueCommandDto (required): /// * [QueueCommandDto] queueCommandDto (required):
Future<Response> runQueueCommandLegacyWithHttpInfo(QueueName name, QueueCommandDto queueCommandDto,) async { Future<Response> runQueueCommandLegacyWithHttpInfo(QueueName name, QueueCommandDto queueCommandDto,) async {
@@ -156,6 +157,7 @@ class JobsApi {
/// Parameters: /// Parameters:
/// ///
/// * [QueueName] name (required): /// * [QueueName] name (required):
/// Queue name
/// ///
/// * [QueueCommandDto] queueCommandDto (required): /// * [QueueCommandDto] queueCommandDto (required):
Future<QueueResponseLegacyDto?> runQueueCommandLegacy(QueueName name, QueueCommandDto queueCommandDto,) async { Future<QueueResponseLegacyDto?> runQueueCommandLegacy(QueueName name, QueueCommandDto queueCommandDto,) async {
+16
View File
@@ -25,16 +25,22 @@ class MapApi {
/// Parameters: /// Parameters:
/// ///
/// * [DateTime] fileCreatedAfter: /// * [DateTime] fileCreatedAfter:
/// Filter assets created after this date
/// ///
/// * [DateTime] fileCreatedBefore: /// * [DateTime] fileCreatedBefore:
/// Filter assets created before this date
/// ///
/// * [bool] isArchived: /// * [bool] isArchived:
/// Filter by archived status
/// ///
/// * [bool] isFavorite: /// * [bool] isFavorite:
/// Filter by favorite status
/// ///
/// * [bool] withPartners: /// * [bool] withPartners:
/// Include partner assets
/// ///
/// * [bool] withSharedAlbums: /// * [bool] withSharedAlbums:
/// Include shared album assets
Future<Response> getMapMarkersWithHttpInfo({ DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, bool? isArchived, bool? isFavorite, bool? withPartners, bool? withSharedAlbums, }) async { Future<Response> getMapMarkersWithHttpInfo({ DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, bool? isArchived, bool? isFavorite, bool? withPartners, bool? withSharedAlbums, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/map/markers'; final apiPath = r'/map/markers';
@@ -86,16 +92,22 @@ class MapApi {
/// Parameters: /// Parameters:
/// ///
/// * [DateTime] fileCreatedAfter: /// * [DateTime] fileCreatedAfter:
/// Filter assets created after this date
/// ///
/// * [DateTime] fileCreatedBefore: /// * [DateTime] fileCreatedBefore:
/// Filter assets created before this date
/// ///
/// * [bool] isArchived: /// * [bool] isArchived:
/// Filter by archived status
/// ///
/// * [bool] isFavorite: /// * [bool] isFavorite:
/// Filter by favorite status
/// ///
/// * [bool] withPartners: /// * [bool] withPartners:
/// Include partner assets
/// ///
/// * [bool] withSharedAlbums: /// * [bool] withSharedAlbums:
/// Include shared album assets
Future<List<MapMarkerResponseDto>?> getMapMarkers({ DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, bool? isArchived, bool? isFavorite, bool? withPartners, bool? withSharedAlbums, }) async { Future<List<MapMarkerResponseDto>?> getMapMarkers({ DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, bool? isArchived, bool? isFavorite, bool? withPartners, bool? withSharedAlbums, }) async {
final response = await getMapMarkersWithHttpInfo( fileCreatedAfter: fileCreatedAfter, fileCreatedBefore: fileCreatedBefore, isArchived: isArchived, isFavorite: isFavorite, withPartners: withPartners, withSharedAlbums: withSharedAlbums, ); final response = await getMapMarkersWithHttpInfo( fileCreatedAfter: fileCreatedAfter, fileCreatedBefore: fileCreatedBefore, isArchived: isArchived, isFavorite: isFavorite, withPartners: withPartners, withSharedAlbums: withSharedAlbums, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -123,8 +135,10 @@ class MapApi {
/// Parameters: /// Parameters:
/// ///
/// * [double] lat (required): /// * [double] lat (required):
/// Latitude (-90 to 90)
/// ///
/// * [double] lon (required): /// * [double] lon (required):
/// Longitude (-180 to 180)
Future<Response> reverseGeocodeWithHttpInfo(double lat, double lon,) async { Future<Response> reverseGeocodeWithHttpInfo(double lat, double lon,) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/map/reverse-geocode'; final apiPath = r'/map/reverse-geocode';
@@ -160,8 +174,10 @@ class MapApi {
/// Parameters: /// Parameters:
/// ///
/// * [double] lat (required): /// * [double] lat (required):
/// Latitude (-90 to 90)
/// ///
/// * [double] lon (required): /// * [double] lon (required):
/// Longitude (-180 to 180)
Future<List<MapReverseGeocodeResponseDto>?> reverseGeocode(double lat, double lon,) async { Future<List<MapReverseGeocodeResponseDto>?> reverseGeocode(double lat, double lon,) async {
final response = await reverseGeocodeWithHttpInfo(lat, lon,); final response = await reverseGeocodeWithHttpInfo(lat, lon,);
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
+20
View File
@@ -251,17 +251,22 @@ class MemoriesApi {
/// Parameters: /// Parameters:
/// ///
/// * [DateTime] for_: /// * [DateTime] for_:
/// Filter by date
/// ///
/// * [bool] isSaved: /// * [bool] isSaved:
/// Filter by saved status
/// ///
/// * [bool] isTrashed: /// * [bool] isTrashed:
/// Include trashed memories
/// ///
/// * [MemorySearchOrder] order: /// * [MemorySearchOrder] order:
/// Sort order
/// ///
/// * [int] size: /// * [int] size:
/// Number of memories to return /// Number of memories to return
/// ///
/// * [MemoryType] type: /// * [MemoryType] type:
/// Memory type
Future<Response> memoriesStatisticsWithHttpInfo({ DateTime? for_, bool? isSaved, bool? isTrashed, MemorySearchOrder? order, int? size, MemoryType? type, }) async { Future<Response> memoriesStatisticsWithHttpInfo({ DateTime? for_, bool? isSaved, bool? isTrashed, MemorySearchOrder? order, int? size, MemoryType? type, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/memories/statistics'; final apiPath = r'/memories/statistics';
@@ -313,17 +318,22 @@ class MemoriesApi {
/// Parameters: /// Parameters:
/// ///
/// * [DateTime] for_: /// * [DateTime] for_:
/// Filter by date
/// ///
/// * [bool] isSaved: /// * [bool] isSaved:
/// Filter by saved status
/// ///
/// * [bool] isTrashed: /// * [bool] isTrashed:
/// Include trashed memories
/// ///
/// * [MemorySearchOrder] order: /// * [MemorySearchOrder] order:
/// Sort order
/// ///
/// * [int] size: /// * [int] size:
/// Number of memories to return /// Number of memories to return
/// ///
/// * [MemoryType] type: /// * [MemoryType] type:
/// Memory type
Future<MemoryStatisticsResponseDto?> memoriesStatistics({ DateTime? for_, bool? isSaved, bool? isTrashed, MemorySearchOrder? order, int? size, MemoryType? type, }) async { Future<MemoryStatisticsResponseDto?> memoriesStatistics({ DateTime? for_, bool? isSaved, bool? isTrashed, MemorySearchOrder? order, int? size, MemoryType? type, }) async {
final response = await memoriesStatisticsWithHttpInfo( for_: for_, isSaved: isSaved, isTrashed: isTrashed, order: order, size: size, type: type, ); final response = await memoriesStatisticsWithHttpInfo( for_: for_, isSaved: isSaved, isTrashed: isTrashed, order: order, size: size, type: type, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -412,17 +422,22 @@ class MemoriesApi {
/// Parameters: /// Parameters:
/// ///
/// * [DateTime] for_: /// * [DateTime] for_:
/// Filter by date
/// ///
/// * [bool] isSaved: /// * [bool] isSaved:
/// Filter by saved status
/// ///
/// * [bool] isTrashed: /// * [bool] isTrashed:
/// Include trashed memories
/// ///
/// * [MemorySearchOrder] order: /// * [MemorySearchOrder] order:
/// Sort order
/// ///
/// * [int] size: /// * [int] size:
/// Number of memories to return /// Number of memories to return
/// ///
/// * [MemoryType] type: /// * [MemoryType] type:
/// Memory type
Future<Response> searchMemoriesWithHttpInfo({ DateTime? for_, bool? isSaved, bool? isTrashed, MemorySearchOrder? order, int? size, MemoryType? type, }) async { Future<Response> searchMemoriesWithHttpInfo({ DateTime? for_, bool? isSaved, bool? isTrashed, MemorySearchOrder? order, int? size, MemoryType? type, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/memories'; final apiPath = r'/memories';
@@ -474,17 +489,22 @@ class MemoriesApi {
/// Parameters: /// Parameters:
/// ///
/// * [DateTime] for_: /// * [DateTime] for_:
/// Filter by date
/// ///
/// * [bool] isSaved: /// * [bool] isSaved:
/// Filter by saved status
/// ///
/// * [bool] isTrashed: /// * [bool] isTrashed:
/// Include trashed memories
/// ///
/// * [MemorySearchOrder] order: /// * [MemorySearchOrder] order:
/// Sort order
/// ///
/// * [int] size: /// * [int] size:
/// Number of memories to return /// Number of memories to return
/// ///
/// * [MemoryType] type: /// * [MemoryType] type:
/// Memory type
Future<List<MemoryResponseDto>?> searchMemories({ DateTime? for_, bool? isSaved, bool? isTrashed, MemorySearchOrder? order, int? size, MemoryType? type, }) async { Future<List<MemoryResponseDto>?> searchMemories({ DateTime? for_, bool? isSaved, bool? isTrashed, MemorySearchOrder? order, int? size, MemoryType? type, }) async {
final response = await searchMemoriesWithHttpInfo( for_: for_, isSaved: isSaved, isTrashed: isTrashed, order: order, size: size, type: type, ); final response = await searchMemoriesWithHttpInfo( for_: for_, isSaved: isSaved, isTrashed: isTrashed, order: order, size: size, type: type, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
+8
View File
@@ -179,12 +179,16 @@ class NotificationsApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] id: /// * [String] id:
/// Filter by notification ID
/// ///
/// * [NotificationLevel] level: /// * [NotificationLevel] level:
/// Filter by notification level
/// ///
/// * [NotificationType] type: /// * [NotificationType] type:
/// Filter by notification type
/// ///
/// * [bool] unread: /// * [bool] unread:
/// Filter by unread status
Future<Response> getNotificationsWithHttpInfo({ String? id, NotificationLevel? level, NotificationType? type, bool? unread, }) async { Future<Response> getNotificationsWithHttpInfo({ String? id, NotificationLevel? level, NotificationType? type, bool? unread, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/notifications'; final apiPath = r'/notifications';
@@ -230,12 +234,16 @@ class NotificationsApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] id: /// * [String] id:
/// Filter by notification ID
/// ///
/// * [NotificationLevel] level: /// * [NotificationLevel] level:
/// Filter by notification level
/// ///
/// * [NotificationType] type: /// * [NotificationType] type:
/// Filter by notification type
/// ///
/// * [bool] unread: /// * [bool] unread:
/// Filter by unread status
Future<List<NotificationDto>?> getNotifications({ String? id, NotificationLevel? level, NotificationType? type, bool? unread, }) async { Future<List<NotificationDto>?> getNotifications({ String? id, NotificationLevel? level, NotificationType? type, bool? unread, }) async {
final response = await getNotificationsWithHttpInfo( id: id, level: level, type: type, unread: unread, ); final response = await getNotificationsWithHttpInfo( id: id, level: level, type: type, unread: unread, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
+2
View File
@@ -138,6 +138,7 @@ class PartnersApi {
/// Parameters: /// Parameters:
/// ///
/// * [PartnerDirection] direction (required): /// * [PartnerDirection] direction (required):
/// Partner direction
Future<Response> getPartnersWithHttpInfo(PartnerDirection direction,) async { Future<Response> getPartnersWithHttpInfo(PartnerDirection direction,) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/partners'; final apiPath = r'/partners';
@@ -172,6 +173,7 @@ class PartnersApi {
/// Parameters: /// Parameters:
/// ///
/// * [PartnerDirection] direction (required): /// * [PartnerDirection] direction (required):
/// Partner direction
Future<List<PartnerResponseDto>?> getPartners(PartnerDirection direction,) async { Future<List<PartnerResponseDto>?> getPartners(PartnerDirection direction,) async {
final response = await getPartnersWithHttpInfo(direction,); final response = await getPartnersWithHttpInfo(direction,);
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
+6
View File
@@ -178,8 +178,10 @@ class PeopleApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] closestAssetId: /// * [String] closestAssetId:
/// Closest asset ID for similarity search
/// ///
/// * [String] closestPersonId: /// * [String] closestPersonId:
/// Closest person ID for similarity search
/// ///
/// * [num] page: /// * [num] page:
/// Page number for pagination /// Page number for pagination
@@ -188,6 +190,7 @@ class PeopleApi {
/// Number of items per page /// Number of items per page
/// ///
/// * [bool] withHidden: /// * [bool] withHidden:
/// Include hidden people
Future<Response> getAllPeopleWithHttpInfo({ String? closestAssetId, String? closestPersonId, num? page, num? size, bool? withHidden, }) async { Future<Response> getAllPeopleWithHttpInfo({ String? closestAssetId, String? closestPersonId, num? page, num? size, bool? withHidden, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/people'; final apiPath = r'/people';
@@ -236,8 +239,10 @@ class PeopleApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] closestAssetId: /// * [String] closestAssetId:
/// Closest asset ID for similarity search
/// ///
/// * [String] closestPersonId: /// * [String] closestPersonId:
/// Closest person ID for similarity search
/// ///
/// * [num] page: /// * [num] page:
/// Page number for pagination /// Page number for pagination
@@ -246,6 +251,7 @@ class PeopleApi {
/// Number of items per page /// Number of items per page
/// ///
/// * [bool] withHidden: /// * [bool] withHidden:
/// Include hidden people
Future<PeopleResponseDto?> getAllPeople({ String? closestAssetId, String? closestPersonId, num? page, num? size, bool? withHidden, }) async { Future<PeopleResponseDto?> getAllPeople({ String? closestAssetId, String? closestPersonId, num? page, num? size, bool? withHidden, }) async {
final response = await getAllPeopleWithHttpInfo( closestAssetId: closestAssetId, closestPersonId: closestPersonId, page: page, size: size, withHidden: withHidden, ); final response = await getAllPeopleWithHttpInfo( closestAssetId: closestAssetId, closestPersonId: closestPersonId, page: page, size: size, withHidden: withHidden, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
+10
View File
@@ -25,6 +25,7 @@ class QueuesApi {
/// Parameters: /// Parameters:
/// ///
/// * [QueueName] name (required): /// * [QueueName] name (required):
/// Queue name
/// ///
/// * [QueueDeleteDto] queueDeleteDto (required): /// * [QueueDeleteDto] queueDeleteDto (required):
Future<Response> emptyQueueWithHttpInfo(QueueName name, QueueDeleteDto queueDeleteDto,) async { Future<Response> emptyQueueWithHttpInfo(QueueName name, QueueDeleteDto queueDeleteDto,) async {
@@ -60,6 +61,7 @@ class QueuesApi {
/// Parameters: /// Parameters:
/// ///
/// * [QueueName] name (required): /// * [QueueName] name (required):
/// Queue name
/// ///
/// * [QueueDeleteDto] queueDeleteDto (required): /// * [QueueDeleteDto] queueDeleteDto (required):
Future<void> emptyQueue(QueueName name, QueueDeleteDto queueDeleteDto,) async { Future<void> emptyQueue(QueueName name, QueueDeleteDto queueDeleteDto,) async {
@@ -78,6 +80,7 @@ class QueuesApi {
/// Parameters: /// Parameters:
/// ///
/// * [QueueName] name (required): /// * [QueueName] name (required):
/// Queue name
Future<Response> getQueueWithHttpInfo(QueueName name,) async { Future<Response> getQueueWithHttpInfo(QueueName name,) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/queues/{name}' final apiPath = r'/queues/{name}'
@@ -111,6 +114,7 @@ class QueuesApi {
/// Parameters: /// Parameters:
/// ///
/// * [QueueName] name (required): /// * [QueueName] name (required):
/// Queue name
Future<QueueResponseDto?> getQueue(QueueName name,) async { Future<QueueResponseDto?> getQueue(QueueName name,) async {
final response = await getQueueWithHttpInfo(name,); final response = await getQueueWithHttpInfo(name,);
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -135,8 +139,10 @@ class QueuesApi {
/// Parameters: /// Parameters:
/// ///
/// * [QueueName] name (required): /// * [QueueName] name (required):
/// Queue name
/// ///
/// * [List<QueueJobStatus>] status: /// * [List<QueueJobStatus>] status:
/// Filter jobs by status
Future<Response> getQueueJobsWithHttpInfo(QueueName name, { List<QueueJobStatus>? status, }) async { Future<Response> getQueueJobsWithHttpInfo(QueueName name, { List<QueueJobStatus>? status, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/queues/{name}/jobs' final apiPath = r'/queues/{name}/jobs'
@@ -174,8 +180,10 @@ class QueuesApi {
/// Parameters: /// Parameters:
/// ///
/// * [QueueName] name (required): /// * [QueueName] name (required):
/// Queue name
/// ///
/// * [List<QueueJobStatus>] status: /// * [List<QueueJobStatus>] status:
/// Filter jobs by status
Future<List<QueueJobResponseDto>?> getQueueJobs(QueueName name, { List<QueueJobStatus>? status, }) async { Future<List<QueueJobResponseDto>?> getQueueJobs(QueueName name, { List<QueueJobStatus>? status, }) async {
final response = await getQueueJobsWithHttpInfo(name, status: status, ); final response = await getQueueJobsWithHttpInfo(name, status: status, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -254,6 +262,7 @@ class QueuesApi {
/// Parameters: /// Parameters:
/// ///
/// * [QueueName] name (required): /// * [QueueName] name (required):
/// Queue name
/// ///
/// * [QueueUpdateDto] queueUpdateDto (required): /// * [QueueUpdateDto] queueUpdateDto (required):
Future<Response> updateQueueWithHttpInfo(QueueName name, QueueUpdateDto queueUpdateDto,) async { Future<Response> updateQueueWithHttpInfo(QueueName name, QueueUpdateDto queueUpdateDto,) async {
@@ -289,6 +298,7 @@ class QueuesApi {
/// Parameters: /// Parameters:
/// ///
/// * [QueueName] name (required): /// * [QueueName] name (required):
/// Queue name
/// ///
/// * [QueueUpdateDto] queueUpdateDto (required): /// * [QueueUpdateDto] queueUpdateDto (required):
Future<QueueResponseDto?> updateQueue(QueueName name, QueueUpdateDto queueUpdateDto,) async { Future<QueueResponseDto?> updateQueue(QueueName name, QueueUpdateDto queueUpdateDto,) async {
+84
View File
@@ -127,18 +127,25 @@ class SearchApi {
/// Parameters: /// Parameters:
/// ///
/// * [SearchSuggestionType] type (required): /// * [SearchSuggestionType] type (required):
/// Suggestion type
/// ///
/// * [String] country: /// * [String] country:
/// Filter by country
/// ///
/// * [bool] includeNull: /// * [bool] includeNull:
/// Include null values in suggestions
/// ///
/// * [String] lensModel: /// * [String] lensModel:
/// Filter by lens model
/// ///
/// * [String] make: /// * [String] make:
/// Filter by camera make
/// ///
/// * [String] model: /// * [String] model:
/// Filter by camera model
/// ///
/// * [String] state: /// * [String] state:
/// Filter by state/province
Future<Response> getSearchSuggestionsWithHttpInfo(SearchSuggestionType type, { String? country, bool? includeNull, String? lensModel, String? make, String? model, String? state, }) async { Future<Response> getSearchSuggestionsWithHttpInfo(SearchSuggestionType type, { String? country, bool? includeNull, String? lensModel, String? make, String? model, String? state, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/search/suggestions'; final apiPath = r'/search/suggestions';
@@ -191,18 +198,25 @@ class SearchApi {
/// Parameters: /// Parameters:
/// ///
/// * [SearchSuggestionType] type (required): /// * [SearchSuggestionType] type (required):
/// Suggestion type
/// ///
/// * [String] country: /// * [String] country:
/// Filter by country
/// ///
/// * [bool] includeNull: /// * [bool] includeNull:
/// Include null values in suggestions
/// ///
/// * [String] lensModel: /// * [String] lensModel:
/// Filter by lens model
/// ///
/// * [String] make: /// * [String] make:
/// Filter by camera make
/// ///
/// * [String] model: /// * [String] model:
/// Filter by camera model
/// ///
/// * [String] state: /// * [String] state:
/// Filter by state/province
Future<List<String>?> getSearchSuggestions(SearchSuggestionType type, { String? country, bool? includeNull, String? lensModel, String? make, String? model, String? state, }) async { Future<List<String>?> getSearchSuggestions(SearchSuggestionType type, { String? country, bool? includeNull, String? lensModel, String? make, String? model, String? state, }) async {
final response = await getSearchSuggestionsWithHttpInfo(type, country: country, includeNull: includeNull, lensModel: lensModel, make: make, model: model, state: state, ); final response = await getSearchSuggestionsWithHttpInfo(type, country: country, includeNull: includeNull, lensModel: lensModel, make: make, model: model, state: state, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -342,68 +356,100 @@ class SearchApi {
/// Parameters: /// Parameters:
/// ///
/// * [List<String>] albumIds: /// * [List<String>] albumIds:
/// Filter by album IDs
/// ///
/// * [String] city: /// * [String] city:
/// Filter by city name
/// ///
/// * [String] country: /// * [String] country:
/// Filter by country name
/// ///
/// * [DateTime] createdAfter: /// * [DateTime] createdAfter:
/// Filter by creation date (after)
/// ///
/// * [DateTime] createdBefore: /// * [DateTime] createdBefore:
/// Filter by creation date (before)
/// ///
/// * [String] deviceId: /// * [String] deviceId:
/// Device ID to filter by
/// ///
/// * [bool] isEncoded: /// * [bool] isEncoded:
/// Filter by encoded status
/// ///
/// * [bool] isFavorite: /// * [bool] isFavorite:
/// Filter by favorite status
/// ///
/// * [bool] isMotion: /// * [bool] isMotion:
/// Filter by motion photo status
/// ///
/// * [bool] isNotInAlbum: /// * [bool] isNotInAlbum:
/// Filter assets not in any album
/// ///
/// * [bool] isOffline: /// * [bool] isOffline:
/// Filter by offline status
/// ///
/// * [String] lensModel: /// * [String] lensModel:
/// Filter by lens model
/// ///
/// * [String] libraryId: /// * [String] libraryId:
/// Library ID to filter by
/// ///
/// * [String] make: /// * [String] make:
/// Filter by camera make
/// ///
/// * [int] minFileSize: /// * [int] minFileSize:
/// Minimum file size in bytes
/// ///
/// * [String] model: /// * [String] model:
/// Filter by camera model
/// ///
/// * [String] ocr: /// * [String] ocr:
/// Filter by OCR text content
/// ///
/// * [List<String>] personIds: /// * [List<String>] personIds:
/// Filter by person IDs
/// ///
/// * [num] rating: /// * [num] rating:
/// Filter by rating
/// ///
/// * [num] size: /// * [num] size:
/// Number of results to return
/// ///
/// * [String] state: /// * [String] state:
/// Filter by state/province name
/// ///
/// * [List<String>] tagIds: /// * [List<String>] tagIds:
/// Filter by tag IDs
/// ///
/// * [DateTime] takenAfter: /// * [DateTime] takenAfter:
/// Filter by taken date (after)
/// ///
/// * [DateTime] takenBefore: /// * [DateTime] takenBefore:
/// Filter by taken date (before)
/// ///
/// * [DateTime] trashedAfter: /// * [DateTime] trashedAfter:
/// Filter by trash date (after)
/// ///
/// * [DateTime] trashedBefore: /// * [DateTime] trashedBefore:
/// Filter by trash date (before)
/// ///
/// * [AssetTypeEnum] type: /// * [AssetTypeEnum] type:
/// Asset type filter
/// ///
/// * [DateTime] updatedAfter: /// * [DateTime] updatedAfter:
/// Filter by update date (after)
/// ///
/// * [DateTime] updatedBefore: /// * [DateTime] updatedBefore:
/// Filter by update date (before)
/// ///
/// * [AssetVisibility] visibility: /// * [AssetVisibility] visibility:
/// Filter by visibility
/// ///
/// * [bool] withDeleted: /// * [bool] withDeleted:
/// Include deleted assets
/// ///
/// * [bool] withExif: /// * [bool] withExif:
/// Include EXIF data in response
Future<Response> searchLargeAssetsWithHttpInfo({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, String? ocr, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async { Future<Response> searchLargeAssetsWithHttpInfo({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, String? ocr, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/search/large-assets'; final apiPath = r'/search/large-assets';
@@ -533,68 +579,100 @@ class SearchApi {
/// Parameters: /// Parameters:
/// ///
/// * [List<String>] albumIds: /// * [List<String>] albumIds:
/// Filter by album IDs
/// ///
/// * [String] city: /// * [String] city:
/// Filter by city name
/// ///
/// * [String] country: /// * [String] country:
/// Filter by country name
/// ///
/// * [DateTime] createdAfter: /// * [DateTime] createdAfter:
/// Filter by creation date (after)
/// ///
/// * [DateTime] createdBefore: /// * [DateTime] createdBefore:
/// Filter by creation date (before)
/// ///
/// * [String] deviceId: /// * [String] deviceId:
/// Device ID to filter by
/// ///
/// * [bool] isEncoded: /// * [bool] isEncoded:
/// Filter by encoded status
/// ///
/// * [bool] isFavorite: /// * [bool] isFavorite:
/// Filter by favorite status
/// ///
/// * [bool] isMotion: /// * [bool] isMotion:
/// Filter by motion photo status
/// ///
/// * [bool] isNotInAlbum: /// * [bool] isNotInAlbum:
/// Filter assets not in any album
/// ///
/// * [bool] isOffline: /// * [bool] isOffline:
/// Filter by offline status
/// ///
/// * [String] lensModel: /// * [String] lensModel:
/// Filter by lens model
/// ///
/// * [String] libraryId: /// * [String] libraryId:
/// Library ID to filter by
/// ///
/// * [String] make: /// * [String] make:
/// Filter by camera make
/// ///
/// * [int] minFileSize: /// * [int] minFileSize:
/// Minimum file size in bytes
/// ///
/// * [String] model: /// * [String] model:
/// Filter by camera model
/// ///
/// * [String] ocr: /// * [String] ocr:
/// Filter by OCR text content
/// ///
/// * [List<String>] personIds: /// * [List<String>] personIds:
/// Filter by person IDs
/// ///
/// * [num] rating: /// * [num] rating:
/// Filter by rating
/// ///
/// * [num] size: /// * [num] size:
/// Number of results to return
/// ///
/// * [String] state: /// * [String] state:
/// Filter by state/province name
/// ///
/// * [List<String>] tagIds: /// * [List<String>] tagIds:
/// Filter by tag IDs
/// ///
/// * [DateTime] takenAfter: /// * [DateTime] takenAfter:
/// Filter by taken date (after)
/// ///
/// * [DateTime] takenBefore: /// * [DateTime] takenBefore:
/// Filter by taken date (before)
/// ///
/// * [DateTime] trashedAfter: /// * [DateTime] trashedAfter:
/// Filter by trash date (after)
/// ///
/// * [DateTime] trashedBefore: /// * [DateTime] trashedBefore:
/// Filter by trash date (before)
/// ///
/// * [AssetTypeEnum] type: /// * [AssetTypeEnum] type:
/// Asset type filter
/// ///
/// * [DateTime] updatedAfter: /// * [DateTime] updatedAfter:
/// Filter by update date (after)
/// ///
/// * [DateTime] updatedBefore: /// * [DateTime] updatedBefore:
/// Filter by update date (before)
/// ///
/// * [AssetVisibility] visibility: /// * [AssetVisibility] visibility:
/// Filter by visibility
/// ///
/// * [bool] withDeleted: /// * [bool] withDeleted:
/// Include deleted assets
/// ///
/// * [bool] withExif: /// * [bool] withExif:
/// Include EXIF data in response
Future<List<AssetResponseDto>?> searchLargeAssets({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, String? ocr, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async { Future<List<AssetResponseDto>?> searchLargeAssets({ List<String>? albumIds, String? city, String? country, DateTime? createdAfter, DateTime? createdBefore, String? deviceId, bool? isEncoded, bool? isFavorite, bool? isMotion, bool? isNotInAlbum, bool? isOffline, String? lensModel, String? libraryId, String? make, int? minFileSize, String? model, String? ocr, List<String>? personIds, num? rating, num? size, String? state, List<String>? tagIds, DateTime? takenAfter, DateTime? takenBefore, DateTime? trashedAfter, DateTime? trashedBefore, AssetTypeEnum? type, DateTime? updatedAfter, DateTime? updatedBefore, AssetVisibility? visibility, bool? withDeleted, bool? withExif, }) async {
final response = await searchLargeAssetsWithHttpInfo( albumIds: albumIds, city: city, country: country, createdAfter: createdAfter, createdBefore: createdBefore, deviceId: deviceId, isEncoded: isEncoded, isFavorite: isFavorite, isMotion: isMotion, isNotInAlbum: isNotInAlbum, isOffline: isOffline, lensModel: lensModel, libraryId: libraryId, make: make, minFileSize: minFileSize, model: model, ocr: ocr, personIds: personIds, rating: rating, size: size, state: state, tagIds: tagIds, takenAfter: takenAfter, takenBefore: takenBefore, trashedAfter: trashedAfter, trashedBefore: trashedBefore, type: type, updatedAfter: updatedAfter, updatedBefore: updatedBefore, visibility: visibility, withDeleted: withDeleted, withExif: withExif, ); final response = await searchLargeAssetsWithHttpInfo( albumIds: albumIds, city: city, country: country, createdAfter: createdAfter, createdBefore: createdBefore, deviceId: deviceId, isEncoded: isEncoded, isFavorite: isFavorite, isMotion: isMotion, isNotInAlbum: isNotInAlbum, isOffline: isOffline, lensModel: lensModel, libraryId: libraryId, make: make, minFileSize: minFileSize, model: model, ocr: ocr, personIds: personIds, rating: rating, size: size, state: state, tagIds: tagIds, takenAfter: takenAfter, takenBefore: takenBefore, trashedAfter: trashedAfter, trashedBefore: trashedBefore, type: type, updatedAfter: updatedAfter, updatedBefore: updatedBefore, visibility: visibility, withDeleted: withDeleted, withExif: withExif, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -622,8 +700,10 @@ class SearchApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] name (required): /// * [String] name (required):
/// Person name to search for
/// ///
/// * [bool] withHidden: /// * [bool] withHidden:
/// Include hidden people
Future<Response> searchPersonWithHttpInfo(String name, { bool? withHidden, }) async { Future<Response> searchPersonWithHttpInfo(String name, { bool? withHidden, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/search/person'; final apiPath = r'/search/person';
@@ -661,8 +741,10 @@ class SearchApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] name (required): /// * [String] name (required):
/// Person name to search for
/// ///
/// * [bool] withHidden: /// * [bool] withHidden:
/// Include hidden people
Future<List<PersonResponseDto>?> searchPerson(String name, { bool? withHidden, }) async { Future<List<PersonResponseDto>?> searchPerson(String name, { bool? withHidden, }) async {
final response = await searchPersonWithHttpInfo(name, withHidden: withHidden, ); final response = await searchPersonWithHttpInfo(name, withHidden: withHidden, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -690,6 +772,7 @@ class SearchApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] name (required): /// * [String] name (required):
/// Place name to search for
Future<Response> searchPlacesWithHttpInfo(String name,) async { Future<Response> searchPlacesWithHttpInfo(String name,) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/search/places'; final apiPath = r'/search/places';
@@ -724,6 +807,7 @@ class SearchApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] name (required): /// * [String] name (required):
/// Place name to search for
Future<List<PlacesResponseDto>?> searchPlaces(String name,) async { Future<List<PlacesResponseDto>?> searchPlaces(String name,) async {
final response = await searchPlacesWithHttpInfo(name,); final response = await searchPlacesWithHttpInfo(name,);
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
+8
View File
@@ -160,8 +160,10 @@ class SharedLinksApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] albumId: /// * [String] albumId:
/// Filter by album ID
/// ///
/// * [String] id: /// * [String] id:
/// Filter by shared link ID
Future<Response> getAllSharedLinksWithHttpInfo({ String? albumId, String? id, }) async { Future<Response> getAllSharedLinksWithHttpInfo({ String? albumId, String? id, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/shared-links'; final apiPath = r'/shared-links';
@@ -201,8 +203,10 @@ class SharedLinksApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] albumId: /// * [String] albumId:
/// Filter by album ID
/// ///
/// * [String] id: /// * [String] id:
/// Filter by shared link ID
Future<List<SharedLinkResponseDto>?> getAllSharedLinks({ String? albumId, String? id, }) async { Future<List<SharedLinkResponseDto>?> getAllSharedLinks({ String? albumId, String? id, }) async {
final response = await getAllSharedLinksWithHttpInfo( albumId: albumId, id: id, ); final response = await getAllSharedLinksWithHttpInfo( albumId: albumId, id: id, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -232,10 +236,12 @@ class SharedLinksApi {
/// * [String] key: /// * [String] key:
/// ///
/// * [String] password: /// * [String] password:
/// Link password
/// ///
/// * [String] slug: /// * [String] slug:
/// ///
/// * [String] token: /// * [String] token:
/// Access token
Future<Response> getMySharedLinkWithHttpInfo({ String? key, String? password, String? slug, String? token, }) async { Future<Response> getMySharedLinkWithHttpInfo({ String? key, String? password, String? slug, String? token, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/shared-links/me'; final apiPath = r'/shared-links/me';
@@ -283,10 +289,12 @@ class SharedLinksApi {
/// * [String] key: /// * [String] key:
/// ///
/// * [String] password: /// * [String] password:
/// Link password
/// ///
/// * [String] slug: /// * [String] slug:
/// ///
/// * [String] token: /// * [String] token:
/// Access token
Future<SharedLinkResponseDto?> getMySharedLink({ String? key, String? password, String? slug, String? token, }) async { Future<SharedLinkResponseDto?> getMySharedLink({ String? key, String? password, String? slug, String? token, }) async {
final response = await getMySharedLinkWithHttpInfo( key: key, password: password, slug: slug, token: token, ); final response = await getMySharedLinkWithHttpInfo( key: key, password: password, slug: slug, token: token, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
+2
View File
@@ -289,6 +289,7 @@ class StacksApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] primaryAssetId: /// * [String] primaryAssetId:
/// Filter by primary asset ID
Future<Response> searchStacksWithHttpInfo({ String? primaryAssetId, }) async { Future<Response> searchStacksWithHttpInfo({ String? primaryAssetId, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/stacks'; final apiPath = r'/stacks';
@@ -325,6 +326,7 @@ class StacksApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] primaryAssetId: /// * [String] primaryAssetId:
/// Filter by primary asset ID
Future<List<StackResponseDto>?> searchStacks({ String? primaryAssetId, }) async { Future<List<StackResponseDto>?> searchStacks({ String? primaryAssetId, }) async {
final response = await searchStacksWithHttpInfo( primaryAssetId: primaryAssetId, ); final response = await searchStacksWithHttpInfo( primaryAssetId: primaryAssetId, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
+10
View File
@@ -318,10 +318,13 @@ class UsersAdminApi {
/// * [String] id (required): /// * [String] id (required):
/// ///
/// * [bool] isFavorite: /// * [bool] isFavorite:
/// Filter by favorite status
/// ///
/// * [bool] isTrashed: /// * [bool] isTrashed:
/// Filter by trash status
/// ///
/// * [AssetVisibility] visibility: /// * [AssetVisibility] visibility:
/// Filter by visibility
Future<Response> getUserStatisticsAdminWithHttpInfo(String id, { bool? isFavorite, bool? isTrashed, AssetVisibility? visibility, }) async { Future<Response> getUserStatisticsAdminWithHttpInfo(String id, { bool? isFavorite, bool? isTrashed, AssetVisibility? visibility, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/admin/users/{id}/statistics' final apiPath = r'/admin/users/{id}/statistics'
@@ -367,10 +370,13 @@ class UsersAdminApi {
/// * [String] id (required): /// * [String] id (required):
/// ///
/// * [bool] isFavorite: /// * [bool] isFavorite:
/// Filter by favorite status
/// ///
/// * [bool] isTrashed: /// * [bool] isTrashed:
/// Filter by trash status
/// ///
/// * [AssetVisibility] visibility: /// * [AssetVisibility] visibility:
/// Filter by visibility
Future<AssetStatsResponseDto?> getUserStatisticsAdmin(String id, { bool? isFavorite, bool? isTrashed, AssetVisibility? visibility, }) async { Future<AssetStatsResponseDto?> getUserStatisticsAdmin(String id, { bool? isFavorite, bool? isTrashed, AssetVisibility? visibility, }) async {
final response = await getUserStatisticsAdminWithHttpInfo(id, isFavorite: isFavorite, isTrashed: isTrashed, visibility: visibility, ); final response = await getUserStatisticsAdminWithHttpInfo(id, isFavorite: isFavorite, isTrashed: isTrashed, visibility: visibility, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
@@ -452,8 +458,10 @@ class UsersAdminApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] id: /// * [String] id:
/// User ID filter
/// ///
/// * [bool] withDeleted: /// * [bool] withDeleted:
/// Include deleted users
Future<Response> searchUsersAdminWithHttpInfo({ String? id, bool? withDeleted, }) async { Future<Response> searchUsersAdminWithHttpInfo({ String? id, bool? withDeleted, }) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/admin/users'; final apiPath = r'/admin/users';
@@ -493,8 +501,10 @@ class UsersAdminApi {
/// Parameters: /// Parameters:
/// ///
/// * [String] id: /// * [String] id:
/// User ID filter
/// ///
/// * [bool] withDeleted: /// * [bool] withDeleted:
/// Include deleted users
Future<List<UserAdminResponseDto>?> searchUsersAdmin({ String? id, bool? withDeleted, }) async { Future<List<UserAdminResponseDto>?> searchUsersAdmin({ String? id, bool? withDeleted, }) async {
final response = await searchUsersAdminWithHttpInfo( id: id, withDeleted: withDeleted, ); final response = await searchUsersAdminWithHttpInfo( id: id, withDeleted: withDeleted, );
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
+2
View File
@@ -25,6 +25,7 @@ class UsersApi {
/// Parameters: /// Parameters:
/// ///
/// * [MultipartFile] file (required): /// * [MultipartFile] file (required):
/// Profile image file
Future<Response> createProfileImageWithHttpInfo(MultipartFile file,) async { Future<Response> createProfileImageWithHttpInfo(MultipartFile file,) async {
// ignore: prefer_const_declarations // ignore: prefer_const_declarations
final apiPath = r'/users/profile-image'; final apiPath = r'/users/profile-image';
@@ -67,6 +68,7 @@ class UsersApi {
/// Parameters: /// Parameters:
/// ///
/// * [MultipartFile] file (required): /// * [MultipartFile] file (required):
/// Profile image file
Future<CreateProfileImageResponseDto?> createProfileImage(MultipartFile file,) async { Future<CreateProfileImageResponseDto?> createProfileImage(MultipartFile file,) async {
final response = await createProfileImageWithHttpInfo(file,); final response = await createProfileImageWithHttpInfo(file,);
if (response.statusCode >= HttpStatus.badRequest) { if (response.statusCode >= HttpStatus.badRequest) {
+4
View File
@@ -19,8 +19,10 @@ class ActivityCreateDto {
required this.type, required this.type,
}); });
/// Album ID
String albumId; String albumId;
/// Asset ID (if activity is for an asset)
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -29,6 +31,7 @@ class ActivityCreateDto {
/// ///
String? assetId; String? assetId;
/// Comment text (required if type is comment)
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -37,6 +40,7 @@ class ActivityCreateDto {
/// ///
String? comment; String? comment;
/// Activity type (like or comment)
ReactionType type; ReactionType type;
@override @override
+5
View File
@@ -21,14 +21,19 @@ class ActivityResponseDto {
required this.user, required this.user,
}); });
/// Asset ID (if activity is for an asset)
String? assetId; String? assetId;
/// Comment text (for comment activities)
String? comment; String? comment;
/// Creation date
DateTime createdAt; DateTime createdAt;
/// Activity ID
String id; String id;
/// Activity type
ReactionType type; ReactionType type;
UserResponseDto user; UserResponseDto user;
@@ -17,8 +17,10 @@ class ActivityStatisticsResponseDto {
required this.likes, required this.likes,
}); });
/// Number of comments
int comments; int comments;
/// Number of likes
int likes; int likes;
@override @override
+1
View File
@@ -16,6 +16,7 @@ class AddUsersDto {
this.albumUsers = const [], this.albumUsers = const [],
}); });
/// Album users to add
List<AlbumUserAddDto> albumUsers; List<AlbumUserAddDto> albumUsers;
@override @override
@@ -16,6 +16,7 @@ class AdminOnboardingUpdateDto {
required this.isOnboarded, required this.isOnboarded,
}); });
/// Is admin onboarded
bool isOnboarded; bool isOnboarded;
@override @override
+15
View File
@@ -34,22 +34,28 @@ class AlbumResponseDto {
required this.updatedAt, required this.updatedAt,
}); });
/// Album name
String albumName; String albumName;
/// Thumbnail asset ID
String? albumThumbnailAssetId; String? albumThumbnailAssetId;
List<AlbumUserResponseDto> albumUsers; List<AlbumUserResponseDto> albumUsers;
/// Number of assets
int assetCount; int assetCount;
List<AssetResponseDto> assets; List<AssetResponseDto> assets;
List<ContributorCountResponseDto> contributorCounts; List<ContributorCountResponseDto> contributorCounts;
/// Creation date
DateTime createdAt; DateTime createdAt;
/// Album description
String description; String description;
/// End date (latest asset)
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -58,12 +64,16 @@ class AlbumResponseDto {
/// ///
DateTime? endDate; DateTime? endDate;
/// Has shared link
bool hasSharedLink; bool hasSharedLink;
/// Album ID
String id; String id;
/// Activity feed enabled
bool isActivityEnabled; bool isActivityEnabled;
/// Last modified asset timestamp
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -72,6 +82,7 @@ class AlbumResponseDto {
/// ///
DateTime? lastModifiedAssetTimestamp; DateTime? lastModifiedAssetTimestamp;
/// Asset sort order
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -82,10 +93,13 @@ class AlbumResponseDto {
UserResponseDto owner; UserResponseDto owner;
/// Owner user ID
String ownerId; String ownerId;
/// Is shared album
bool shared; bool shared;
/// Start date (earliest asset)
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -94,6 +108,7 @@ class AlbumResponseDto {
/// ///
DateTime? startDate; DateTime? startDate;
/// Last update date
DateTime updatedAt; DateTime updatedAt;
@override @override
@@ -18,10 +18,13 @@ class AlbumStatisticsResponseDto {
required this.shared, required this.shared,
}); });
/// Number of non-shared albums
int notShared; int notShared;
/// Number of owned albums
int owned; int owned;
/// Number of shared albums
int shared; int shared;
@override @override
+2
View File
@@ -17,8 +17,10 @@ class AlbumUserAddDto {
required this.userId, required this.userId,
}); });
/// Album user role
AlbumUserRole role; AlbumUserRole role;
/// User ID
String userId; String userId;
@override @override
+2
View File
@@ -17,8 +17,10 @@ class AlbumUserCreateDto {
required this.userId, required this.userId,
}); });
/// Album user role
AlbumUserRole role; AlbumUserRole role;
/// User ID
String userId; String userId;
@override @override
+1
View File
@@ -17,6 +17,7 @@ class AlbumUserResponseDto {
required this.user, required this.user,
}); });
/// Album user role
AlbumUserRole role; AlbumUserRole role;
UserResponseDto user; UserResponseDto user;
+1 -1
View File
@@ -10,7 +10,7 @@
part of openapi.api; part of openapi.api;
/// Album user role
class AlbumUserRole { class AlbumUserRole {
/// Instantiate a new enum with the provided [value]. /// Instantiate a new enum with the provided [value].
const AlbumUserRole._(this.value); const AlbumUserRole._(this.value);
+2
View File
@@ -17,8 +17,10 @@ class AlbumsAddAssetsDto {
this.assetIds = const [], this.assetIds = const [],
}); });
/// Album IDs
List<String> albumIds; List<String> albumIds;
/// Asset IDs
List<String> assetIds; List<String> assetIds;
@override @override
@@ -17,6 +17,7 @@ class AlbumsAddAssetsResponseDto {
required this.success, required this.success,
}); });
/// Error reason
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -25,6 +26,7 @@ class AlbumsAddAssetsResponseDto {
/// ///
BulkIdErrorReason? error; BulkIdErrorReason? error;
/// Operation success
bool success; bool success;
@override @override
+1
View File
@@ -16,6 +16,7 @@ class AlbumsResponse {
this.defaultAssetOrder = AssetOrder.desc, this.defaultAssetOrder = AssetOrder.desc,
}); });
/// Default asset order for albums
AssetOrder defaultAssetOrder; AssetOrder defaultAssetOrder;
@override @override
+1
View File
@@ -16,6 +16,7 @@ class AlbumsUpdate {
this.defaultAssetOrder, this.defaultAssetOrder,
}); });
/// Default asset order for albums
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
+2
View File
@@ -17,6 +17,7 @@ class APIKeyCreateDto {
this.permissions = const [], this.permissions = const [],
}); });
/// API key name
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -25,6 +26,7 @@ class APIKeyCreateDto {
/// ///
String? name; String? name;
/// List of permissions
List<Permission> permissions; List<Permission> permissions;
@override @override
@@ -19,6 +19,7 @@ class APIKeyCreateResponseDto {
APIKeyResponseDto apiKey; APIKeyResponseDto apiKey;
/// API key secret (only shown once)
String secret; String secret;
@override @override
+5
View File
@@ -20,14 +20,19 @@ class APIKeyResponseDto {
required this.updatedAt, required this.updatedAt,
}); });
/// Creation date
DateTime createdAt; DateTime createdAt;
/// API key ID
String id; String id;
/// API key name
String name; String name;
/// List of permissions
List<Permission> permissions; List<Permission> permissions;
/// Last update date
DateTime updatedAt; DateTime updatedAt;
@override @override
+2
View File
@@ -17,6 +17,7 @@ class APIKeyUpdateDto {
this.permissions = const [], this.permissions = const [],
}); });
/// API key name
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -25,6 +26,7 @@ class APIKeyUpdateDto {
/// ///
String? name; String? name;
/// List of permissions
List<Permission> permissions; List<Permission> permissions;
@override @override
+2
View File
@@ -17,6 +17,7 @@ class AssetBulkDeleteDto {
this.ids = const [], this.ids = const [],
}); });
/// Force delete even if in use
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -25,6 +26,7 @@ class AssetBulkDeleteDto {
/// ///
bool? force; bool? force;
/// IDs to process
List<String> ids; List<String> ids;
@override @override
+12
View File
@@ -26,6 +26,7 @@ class AssetBulkUpdateDto {
this.visibility, this.visibility,
}); });
/// Original date and time
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -34,6 +35,7 @@ class AssetBulkUpdateDto {
/// ///
String? dateTimeOriginal; String? dateTimeOriginal;
/// Relative time offset in seconds
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -42,6 +44,7 @@ class AssetBulkUpdateDto {
/// ///
num? dateTimeRelative; num? dateTimeRelative;
/// Asset description
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -50,10 +53,13 @@ class AssetBulkUpdateDto {
/// ///
String? description; String? description;
/// Duplicate asset ID
String? duplicateId; String? duplicateId;
/// Asset IDs to update
List<String> ids; List<String> ids;
/// Mark as favorite
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -62,6 +68,7 @@ class AssetBulkUpdateDto {
/// ///
bool? isFavorite; bool? isFavorite;
/// Latitude coordinate
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -70,6 +77,7 @@ class AssetBulkUpdateDto {
/// ///
num? latitude; num? latitude;
/// Longitude coordinate
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -78,6 +86,8 @@ class AssetBulkUpdateDto {
/// ///
num? longitude; num? longitude;
/// Rating
///
/// Minimum value: -1 /// Minimum value: -1
/// Maximum value: 5 /// Maximum value: 5
/// ///
@@ -88,6 +98,7 @@ class AssetBulkUpdateDto {
/// ///
num? rating; num? rating;
/// Time zone (IANA timezone)
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -96,6 +107,7 @@ class AssetBulkUpdateDto {
/// ///
String? timeZone; String? timeZone;
/// Asset visibility
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -16,6 +16,7 @@ class AssetBulkUploadCheckDto {
this.assets = const [], this.assets = const [],
}); });
/// Assets to check
List<AssetBulkUploadCheckItem> assets; List<AssetBulkUploadCheckItem> assets;
@override @override
+2 -1
View File
@@ -17,9 +17,10 @@ class AssetBulkUploadCheckItem {
required this.id, required this.id,
}); });
/// base64 or hex encoded sha1 hash /// Base64 or hex encoded SHA1 hash
String checksum; String checksum;
/// Asset ID
String id; String id;
@override @override
@@ -16,6 +16,7 @@ class AssetBulkUploadCheckResponseDto {
this.results = const [], this.results = const [],
}); });
/// Upload check results
List<AssetBulkUploadCheckResult> results; List<AssetBulkUploadCheckResult> results;
@override @override
@@ -20,8 +20,10 @@ class AssetBulkUploadCheckResult {
this.reason, this.reason,
}); });
/// Upload action
AssetBulkUploadCheckResultActionEnum action; AssetBulkUploadCheckResultActionEnum action;
/// Existing asset ID if duplicate
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -30,8 +32,10 @@ class AssetBulkUploadCheckResult {
/// ///
String? assetId; String? assetId;
/// Asset ID
String id; String id;
/// Whether existing asset is trashed
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -40,6 +44,7 @@ class AssetBulkUploadCheckResult {
/// ///
bool? isTrashed; bool? isTrashed;
/// Rejection reason if rejected
AssetBulkUploadCheckResultReasonEnum? reason; AssetBulkUploadCheckResultReasonEnum? reason;
@override @override
@@ -150,7 +155,7 @@ class AssetBulkUploadCheckResult {
}; };
} }
/// Upload action
class AssetBulkUploadCheckResultActionEnum { class AssetBulkUploadCheckResultActionEnum {
/// Instantiate a new enum with the provided [value]. /// Instantiate a new enum with the provided [value].
const AssetBulkUploadCheckResultActionEnum._(this.value); const AssetBulkUploadCheckResultActionEnum._(this.value);
@@ -224,7 +229,7 @@ class AssetBulkUploadCheckResultActionEnumTypeTransformer {
} }
/// Rejection reason if rejected
class AssetBulkUploadCheckResultReasonEnum { class AssetBulkUploadCheckResultReasonEnum {
/// Instantiate a new enum with the provided [value]. /// Instantiate a new enum with the provided [value].
const AssetBulkUploadCheckResultReasonEnum._(this.value); const AssetBulkUploadCheckResultReasonEnum._(this.value);
+7
View File
@@ -22,18 +22,25 @@ class AssetCopyDto {
required this.targetId, required this.targetId,
}); });
/// Copy album associations
bool albums; bool albums;
/// Copy favorite status
bool favorite; bool favorite;
/// Copy shared links
bool sharedLinks; bool sharedLinks;
/// Copy sidecar file
bool sidecar; bool sidecar;
/// Source asset ID
String sourceId; String sourceId;
/// Copy stack association
bool stack; bool stack;
/// Target asset ID
String targetId; String targetId;
@override @override
+2
View File
@@ -17,8 +17,10 @@ class AssetDeltaSyncDto {
this.userIds = const [], this.userIds = const [],
}); });
/// Sync assets updated after this date
DateTime updatedAfter; DateTime updatedAfter;
/// User IDs to sync
List<String> userIds; List<String> userIds;
@override @override
@@ -18,10 +18,13 @@ class AssetDeltaSyncResponseDto {
this.upserted = const [], this.upserted = const [],
}); });
/// Deleted asset IDs
List<String> deleted; List<String> deleted;
/// Whether full sync is needed
bool needsFullSync; bool needsFullSync;
/// Upserted assets
List<AssetResponseDto> upserted; List<AssetResponseDto> upserted;
@override @override
+1 -1
View File
@@ -10,7 +10,7 @@
part of openapi.api; part of openapi.api;
/// Type of edit action to perform
class AssetEditAction { class AssetEditAction {
/// Instantiate a new enum with the provided [value]. /// Instantiate a new enum with the provided [value].
const AssetEditAction._(this.value); const AssetEditAction._(this.value);
+1
View File
@@ -17,6 +17,7 @@ class AssetEditActionCrop {
required this.parameters, required this.parameters,
}); });
/// Type of edit action to perform
AssetEditAction action; AssetEditAction action;
CropParameters parameters; CropParameters parameters;
+1 -1
View File
@@ -16,7 +16,7 @@ class AssetEditActionListDto {
this.edits = const [], this.edits = const [],
}); });
/// list of edits /// List of edit actions to apply (crop, rotate, or mirror)
List<AssetEditActionListDtoEditsInner> edits; List<AssetEditActionListDtoEditsInner> edits;
@override @override
@@ -17,6 +17,7 @@ class AssetEditActionListDtoEditsInner {
required this.parameters, required this.parameters,
}); });
/// Type of edit action to perform
AssetEditAction action; AssetEditAction action;
MirrorParameters parameters; MirrorParameters parameters;
+1
View File
@@ -17,6 +17,7 @@ class AssetEditActionMirror {
required this.parameters, required this.parameters,
}); });
/// Type of edit action to perform
AssetEditAction action; AssetEditAction action;
MirrorParameters parameters; MirrorParameters parameters;
+1
View File
@@ -17,6 +17,7 @@ class AssetEditActionRotate {
required this.parameters, required this.parameters,
}); });
/// Type of edit action to perform
AssetEditAction action; AssetEditAction action;
RotateParameters parameters; RotateParameters parameters;
+2 -1
View File
@@ -17,9 +17,10 @@ class AssetEditsDto {
this.edits = const [], this.edits = const [],
}); });
/// Asset ID to apply edits to
String assetId; String assetId;
/// list of edits /// List of edit actions to apply (crop, rotate, or mirror)
List<AssetEditActionListDtoEditsInner> edits; List<AssetEditActionListDtoEditsInner> edits;
@override @override
+8
View File
@@ -23,20 +23,28 @@ class AssetFaceCreateDto {
required this.y, required this.y,
}); });
/// Asset ID
String assetId; String assetId;
/// Face bounding box height
int height; int height;
/// Image height in pixels
int imageHeight; int imageHeight;
/// Image width in pixels
int imageWidth; int imageWidth;
/// Person ID
String personId; String personId;
/// Face bounding box width
int width; int width;
/// Face bounding box X coordinate
int x; int x;
/// Face bounding box Y coordinate
int y; int y;
@override @override
+1
View File
@@ -16,6 +16,7 @@ class AssetFaceDeleteDto {
required this.force, required this.force,
}); });
/// Force delete even if person has other faces
bool force; bool force;
@override @override
+9
View File
@@ -24,22 +24,31 @@ class AssetFaceResponseDto {
this.sourceType, this.sourceType,
}); });
/// Bounding box X1 coordinate
int boundingBoxX1; int boundingBoxX1;
/// Bounding box X2 coordinate
int boundingBoxX2; int boundingBoxX2;
/// Bounding box Y1 coordinate
int boundingBoxY1; int boundingBoxY1;
/// Bounding box Y2 coordinate
int boundingBoxY2; int boundingBoxY2;
/// Face ID
String id; String id;
/// Image height in pixels
int imageHeight; int imageHeight;
/// Image width in pixels
int imageWidth; int imageWidth;
/// Person associated with face
PersonResponseDto? person; PersonResponseDto? person;
/// Face detection source type
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
+1
View File
@@ -16,6 +16,7 @@ class AssetFaceUpdateDto {
this.data = const [], this.data = const [],
}); });
/// Face update items
List<AssetFaceUpdateItem> data; List<AssetFaceUpdateItem> data;
@override @override
+2
View File
@@ -17,8 +17,10 @@ class AssetFaceUpdateItem {
required this.personId, required this.personId,
}); });
/// Asset ID
String assetId; String assetId;
/// Person ID
String personId; String personId;
@override @override
@@ -23,20 +23,28 @@ class AssetFaceWithoutPersonResponseDto {
this.sourceType, this.sourceType,
}); });
/// Bounding box X1 coordinate
int boundingBoxX1; int boundingBoxX1;
/// Bounding box X2 coordinate
int boundingBoxX2; int boundingBoxX2;
/// Bounding box Y1 coordinate
int boundingBoxY1; int boundingBoxY1;
/// Bounding box Y2 coordinate
int boundingBoxY2; int boundingBoxY2;
/// Face ID
String id; String id;
/// Image height in pixels
int imageHeight; int imageHeight;
/// Image width in pixels
int imageWidth; int imageWidth;
/// Face detection source type
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
+5
View File
@@ -19,6 +19,7 @@ class AssetFullSyncDto {
this.userId, this.userId,
}); });
/// Last asset ID (pagination)
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
@@ -27,11 +28,15 @@ class AssetFullSyncDto {
/// ///
String? lastId; String? lastId;
/// Maximum number of assets to return
///
/// Minimum value: 1 /// Minimum value: 1
int limit; int limit;
/// Sync assets updated until this date
DateTime updatedUntil; DateTime updatedUntil;
/// Filter by user ID
/// ///
/// Please note: This property should have been non-nullable! Since the specification file /// 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 /// does not include a default value (using the "default:" property), however, the generated
+1
View File
@@ -16,6 +16,7 @@ class AssetIdsDto {
this.assetIds = const [], this.assetIds = const [],
}); });
/// Asset IDs
List<String> assetIds; List<String> assetIds;
@override @override
+4 -1
View File
@@ -18,10 +18,13 @@ class AssetIdsResponseDto {
required this.success, required this.success,
}); });
/// Asset ID
String assetId; String assetId;
/// Error reason if failed
AssetIdsResponseDtoErrorEnum? error; AssetIdsResponseDtoErrorEnum? error;
/// Whether operation succeeded
bool success; bool success;
@override @override
@@ -116,7 +119,7 @@ class AssetIdsResponseDto {
}; };
} }
/// Error reason if failed
class AssetIdsResponseDtoErrorEnum { class AssetIdsResponseDtoErrorEnum {
/// Instantiate a new enum with the provided [value]. /// Instantiate a new enum with the provided [value].
const AssetIdsResponseDtoErrorEnum._(this.value); const AssetIdsResponseDtoErrorEnum._(this.value);
+1 -1
View File
@@ -10,7 +10,7 @@
part of openapi.api; part of openapi.api;
/// Job name
class AssetJobName { class AssetJobName {
/// Instantiate a new enum with the provided [value]. /// Instantiate a new enum with the provided [value].
const AssetJobName._(this.value); const AssetJobName._(this.value);
+2
View File
@@ -17,8 +17,10 @@ class AssetJobsDto {
required this.name, required this.name,
}); });
/// Asset IDs
List<String> assetIds; List<String> assetIds;
/// Job name
AssetJobName name; AssetJobName name;
@override @override
+2
View File
@@ -17,8 +17,10 @@ class AssetMediaResponseDto {
required this.status, required this.status,
}); });
/// Asset media ID
String id; String id;
/// Upload status
AssetMediaStatus status; AssetMediaStatus status;
@override @override
+1 -1
View File
@@ -10,7 +10,7 @@
part of openapi.api; part of openapi.api;
/// Upload status
class AssetMediaStatus { class AssetMediaStatus {
/// Instantiate a new enum with the provided [value]. /// Instantiate a new enum with the provided [value].
const AssetMediaStatus._(this.value); const AssetMediaStatus._(this.value);
@@ -16,6 +16,7 @@ class AssetMetadataBulkDeleteDto {
this.items = const [], this.items = const [],
}); });
/// Metadata items to delete
List<AssetMetadataBulkDeleteItemDto> items; List<AssetMetadataBulkDeleteItemDto> items;
@override @override
@@ -17,8 +17,10 @@ class AssetMetadataBulkDeleteItemDto {
required this.key, required this.key,
}); });
/// Asset ID
String assetId; String assetId;
/// Metadata key
String key; String key;
@override @override
@@ -19,12 +19,16 @@ class AssetMetadataBulkResponseDto {
required this.value, required this.value,
}); });
/// Asset ID
String assetId; String assetId;
/// Metadata key
String key; String key;
/// Last update date
DateTime updatedAt; DateTime updatedAt;
/// Metadata value (object)
Object value; Object value;
@override @override
@@ -16,6 +16,7 @@ class AssetMetadataBulkUpsertDto {
this.items = const [], this.items = const [],
}); });
/// Metadata items to upsert
List<AssetMetadataBulkUpsertItemDto> items; List<AssetMetadataBulkUpsertItemDto> items;
@override @override
@@ -18,10 +18,13 @@ class AssetMetadataBulkUpsertItemDto {
required this.value, required this.value,
}); });
/// Asset ID
String assetId; String assetId;
/// Metadata key
String key; String key;
/// Metadata value (object)
Object value; Object value;
@override @override
@@ -18,10 +18,13 @@ class AssetMetadataResponseDto {
required this.value, required this.value,
}); });
/// Metadata key
String key; String key;
/// Last update date
DateTime updatedAt; DateTime updatedAt;
/// Metadata value (object)
Object value; Object value;
@override @override
+1
View File
@@ -16,6 +16,7 @@ class AssetMetadataUpsertDto {
this.items = const [], this.items = const [],
}); });
/// Metadata items to upsert
List<AssetMetadataUpsertItemDto> items; List<AssetMetadataUpsertItemDto> items;
@override @override
@@ -17,8 +17,10 @@ class AssetMetadataUpsertItemDto {
required this.value, required this.value,
}); });
/// Metadata key
String key; String key;
/// Metadata value (object)
Object value; Object value;
@override @override
+1 -1
View File
@@ -10,7 +10,7 @@
part of openapi.api; part of openapi.api;
/// Asset sort order
class AssetOrder { class AssetOrder {
/// Instantiate a new enum with the provided [value]. /// Instantiate a new enum with the provided [value].
const AssetOrder._(this.value); const AssetOrder._(this.value);

Some files were not shown because too many files have changed in this diff Show More