Compare commits

...

3 Commits

Author SHA1 Message Date
github-actions
bede19a3ca chore: version v1.138.0 2025-08-13 17:08:29 +00:00
Alex
aefa62b234 fix: asset_viewer page viewing experience (#20889)
* fix: zoomed in effect on swiped when bottom sheet is open

* fix: memory leaked

* fix: asset out of range when swiping in asset_viewer
2025-08-13 11:35:42 -05:00
renovate[bot]
b3fb831994 fix(deps): update machine-learning (#20878)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-13 11:24:09 -04:00
23 changed files with 1785 additions and 1698 deletions

6
cli/package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.77", "version": "2.2.78",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.77", "version": "2.2.78",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"chokidar": "^4.0.3", "chokidar": "^4.0.3",
@@ -54,7 +54,7 @@
}, },
"../open-api/typescript-sdk": { "../open-api/typescript-sdk": {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.137.3", "version": "1.138.0",
"dev": true, "dev": true,
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.77", "version": "2.2.78",
"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",

View File

@@ -1,4 +1,8 @@
[ [
{
"label": "v1.138.0",
"url": "https://v1.138.0.archive.immich.app"
},
{ {
"label": "v1.137.3", "label": "v1.137.3",
"url": "https://v1.137.3.archive.immich.app" "url": "https://v1.137.3.archive.immich.app"

8
e2e/package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "immich-e2e", "name": "immich-e2e",
"version": "1.137.3", "version": "1.138.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "immich-e2e", "name": "immich-e2e",
"version": "1.137.3", "version": "1.138.0",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "^3.1.0", "@eslint/eslintrc": "^3.1.0",
@@ -46,7 +46,7 @@
}, },
"../cli": { "../cli": {
"name": "@immich/cli", "name": "@immich/cli",
"version": "2.2.77", "version": "2.2.78",
"dev": true, "dev": true,
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
@@ -95,7 +95,7 @@
}, },
"../open-api/typescript-sdk": { "../open-api/typescript-sdk": {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.137.3", "version": "1.138.0",
"dev": true, "dev": true,
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "immich-e2e", "name": "immich-e2e",
"version": "1.137.3", "version": "1.138.0",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",

View File

@@ -1,6 +1,6 @@
ARG DEVICE=cpu ARG DEVICE=cpu
FROM python:3.11-bookworm@sha256:c1239cb82bf08176c4c90421ab425a1696257b098d9ce21e68de9319c255a47d AS builder-cpu FROM python:3.11-bookworm@sha256:85c4ac66dea23fbd1beb5c48957c2589d104002f8b11c90a186be421117da5e0 AS builder-cpu
FROM builder-cpu AS builder-openvino FROM builder-cpu AS builder-openvino
@@ -59,7 +59,7 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
RUN apt-get update && apt-get install -y --no-install-recommends g++ RUN apt-get update && apt-get install -y --no-install-recommends g++
COPY --from=ghcr.io/astral-sh/uv:latest@sha256:67b2bcccdc103d608727d1b577e58008ef810f751ed324715eb60b3f0c040d30 /uv /uvx /bin/ COPY --from=ghcr.io/astral-sh/uv:latest@sha256:cda9608307dbbfc1769f3b6b1f9abf5f1360de0be720f544d29a7ae2863c47ef /uv /uvx /bin/
RUN --mount=type=cache,target=/root/.cache/uv \ RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
@@ -68,11 +68,11 @@ RUN if [ "$DEVICE" = "rocm" ]; then \
uv pip install /opt/onnxruntime_rocm-*.whl; \ uv pip install /opt/onnxruntime_rocm-*.whl; \
fi fi
FROM python:3.11-slim-bookworm@sha256:0ce77749ac83174a31d5e107ce0cfa6b28a2fd6b0615e029d9d84b39c48976ee AS prod-cpu FROM python:3.11-slim-bookworm@sha256:01f98e2d213e1cda58a21dabfd107c4a71c99caa0c932c593acfce05315b7251 AS prod-cpu
ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2 ENV LD_PRELOAD=/usr/lib/libmimalloc.so.2
FROM python:3.11-slim-bookworm@sha256:0ce77749ac83174a31d5e107ce0cfa6b28a2fd6b0615e029d9d84b39c48976ee AS prod-openvino FROM python:3.11-slim-bookworm@sha256:01f98e2d213e1cda58a21dabfd107c4a71c99caa0c932c593acfce05315b7251 AS prod-openvino
RUN apt-get update && \ RUN apt-get update && \
apt-get install --no-install-recommends -yqq ocl-icd-libopencl1 wget && \ apt-get install --no-install-recommends -yqq ocl-icd-libopencl1 wget && \

3250
machine-learning/uv.lock generated

File diff suppressed because it is too large Load Diff

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" => 3002, "android.injected.version.code" => 3003,
"android.injected.version.name" => "1.137.3", "android.injected.version.name" => "1.138.0",
} }
) )
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')

View File

@@ -22,7 +22,7 @@ platform :ios do
path: "./Runner.xcodeproj", path: "./Runner.xcodeproj",
) )
increment_version_number( increment_version_number(
version_number: "1.137.3" version_number: "1.138.0"
) )
increment_build_number( increment_build_number(
build_number: latest_testflight_build_number + 1, build_number: latest_testflight_build_number + 1,

View File

@@ -169,6 +169,36 @@ class TimelineService {
return _buffer.elementAt(index - _bufferOffset); return _buffer.elementAt(index - _bufferOffset);
} }
/// Gets an asset at the given index, automatically loading the buffer if needed.
/// This is an async version that can handle out-of-range indices by loading the appropriate buffer.
Future<BaseAsset?> getAssetAsync(int index) async {
if (index < 0 || index >= _totalAssets) {
return null;
}
if (hasRange(index, 1)) {
return _buffer.elementAt(index - _bufferOffset);
}
// Load the buffer containing the requested index
try {
final assets = await loadAssets(index, 1);
return assets.isNotEmpty ? assets.first : null;
} catch (e) {
return null;
}
}
/// Safely gets an asset at the given index without throwing a RangeError.
/// Returns null if the index is out of bounds or not currently in the buffer.
/// For automatic buffer loading, use getAssetAsync instead.
BaseAsset? getAssetSafe(int index) {
if (index < 0 || index >= _totalAssets || !hasRange(index, 1)) {
return null;
}
return _buffer.elementAt(index - _bufferOffset);
}
Future<void> dispose() async { Future<void> dispose() async {
await _bucketSubscription?.cancel(); await _bucketSubscription?.cancel();
_bucketSubscription = null; _bucketSubscription = null;

View File

@@ -127,20 +127,21 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
_delayedOperations.clear(); _delayedOperations.clear();
} }
// This is used to calculate the scale of the asset when the bottom sheet is showing.
// It is a small increment to ensure that the asset is slightly zoomed in when the
// bottom sheet is showing, which emulates the zoom effect.
double get _getScaleForBottomSheet => (viewController?.prevValue.scale ?? viewController?.value.scale ?? 1.0) + 0.01;
double _getVerticalOffsetForBottomSheet(double extent) => double _getVerticalOffsetForBottomSheet(double extent) =>
(context.height * extent) - (context.height * _kBottomSheetMinimumExtent); (context.height * extent) - (context.height * _kBottomSheetMinimumExtent);
Future<void> _precacheImage(int index) async { Future<void> _precacheImage(int index) async {
if (!mounted || index < 0 || index >= totalAssets) { if (!mounted) {
return;
}
final timelineService = ref.read(timelineServiceProvider);
final asset = await timelineService.getAssetAsync(index);
if (asset == null || !mounted) {
return; return;
} }
final asset = ref.read(timelineServiceProvider).getAsset(index);
final screenSize = Size(context.width, context.height); final screenSize = Size(context.width, context.height);
// Precache both thumbnail and full image for smooth transitions // Precache both thumbnail and full image for smooth transitions
@@ -152,8 +153,15 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
); );
} }
void _onAssetChanged(int index) { void _onAssetChanged(int index) async {
final asset = ref.read(timelineServiceProvider).getAsset(index); // Validate index bounds and try to get asset, loading buffer if needed
final timelineService = ref.read(timelineServiceProvider);
final asset = await timelineService.getAssetAsync(index);
if (asset == null) {
return;
}
// Always holds the current asset from the timeline // Always holds the current asset from the timeline
ref.read(assetViewerProvider.notifier).setAsset(asset); ref.read(assetViewerProvider.notifier).setAsset(asset);
// The currentAssetNotifier actually holds the current asset that is displayed // The currentAssetNotifier actually holds the current asset that is displayed
@@ -217,19 +225,15 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
final verticalOffset = final verticalOffset =
(context.height * bottomSheetController.size) - (context.height * _kBottomSheetMinimumExtent); (context.height * bottomSheetController.size) - (context.height * _kBottomSheetMinimumExtent);
controller.position = Offset(0, -verticalOffset); controller.position = Offset(0, -verticalOffset);
// Apply the zoom effect when the bottom sheet is showing
initialScale = controller.scale;
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;
// If the bottom sheet is showing, we need to adjust scale the asset to
// emulate the zoom effect
if (showingBottomSheet) {
initialScale = controller?.scale;
controller?.scale = _getScaleForBottomSheet;
}
} }
void _onDragStart( void _onDragStart(
@@ -412,16 +416,22 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
} }
} }
void _onAssetReloadEvent() { void _onAssetReloadEvent() async {
setState(() { final index = pageController.page?.round() ?? 0;
final index = pageController.page?.round() ?? 0; final timelineService = ref.read(timelineServiceProvider);
final newAsset = ref.read(timelineServiceProvider).getAsset(index); final newAsset = await timelineService.getAssetAsync(index);
final currentAsset = ref.read(currentAssetNotifier);
// Do not reload / close the bottom sheet if the asset has not changed
if (newAsset.heroTag == currentAsset?.heroTag) {
return;
}
if (newAsset == null) {
return;
}
final currentAsset = ref.read(currentAssetNotifier);
// Do not reload / close the bottom sheet if the asset has not changed
if (newAsset.heroTag == currentAsset?.heroTag) {
return;
}
setState(() {
_onAssetChanged(pageController.page!.round()); _onAssetChanged(pageController.page!.round());
sheetCloseController?.close(); sheetCloseController?.close();
}); });
@@ -430,7 +440,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
void _openBottomSheet(BuildContext ctx, {double extent = _kBottomSheetMinimumExtent}) { void _openBottomSheet(BuildContext ctx, {double extent = _kBottomSheetMinimumExtent}) {
ref.read(assetViewerProvider.notifier).setBottomSheet(true); ref.read(assetViewerProvider.notifier).setBottomSheet(true);
initialScale = viewController?.scale; initialScale = viewController?.scale;
viewController?.updateMultiple(scale: _getScaleForBottomSheet); // viewController?.updateMultiple(scale: (viewController?.scale ?? 1.0) + 0.01);
previousExtent = _kBottomSheetMinimumExtent; previousExtent = _kBottomSheetMinimumExtent;
sheetCloseController = showBottomSheet( sheetCloseController = showBottomSheet(
context: ctx, context: ctx,
@@ -468,16 +478,29 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
} }
Widget _placeholderBuilder(BuildContext ctx, ImageChunkEvent? progress, int index) { Widget _placeholderBuilder(BuildContext ctx, ImageChunkEvent? progress, int index) {
BaseAsset asset = ref.read(timelineServiceProvider).getAsset(index); final timelineService = ref.read(timelineServiceProvider);
final asset = timelineService.getAssetSafe(index);
// If asset is not available in buffer, show a loading container
if (asset == null) {
return Container(
width: double.infinity,
height: double.infinity,
color: backgroundColor,
child: const Center(child: CircularProgressIndicator()),
);
}
BaseAsset displayAsset = asset;
final stackChildren = ref.read(stackChildrenNotifier(asset)).valueOrNull; final stackChildren = ref.read(stackChildrenNotifier(asset)).valueOrNull;
if (stackChildren != null && stackChildren.isNotEmpty) { if (stackChildren != null && stackChildren.isNotEmpty) {
asset = stackChildren.elementAt(ref.read(assetViewerProvider.select((s) => s.stackIndex))); displayAsset = stackChildren.elementAt(ref.read(assetViewerProvider.select((s) => s.stackIndex)));
} }
return Container( return Container(
width: double.infinity, width: double.infinity,
height: double.infinity, height: double.infinity,
color: backgroundColor, color: backgroundColor,
child: Thumbnail(asset: asset, fit: BoxFit.contain), child: Thumbnail(asset: displayAsset, fit: BoxFit.contain),
); );
} }
@@ -493,18 +516,34 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
PhotoViewGalleryPageOptions _assetBuilder(BuildContext ctx, int index) { PhotoViewGalleryPageOptions _assetBuilder(BuildContext ctx, int index) {
scaffoldContext ??= ctx; scaffoldContext ??= ctx;
BaseAsset asset = ref.read(timelineServiceProvider).getAsset(index); final timelineService = ref.read(timelineServiceProvider);
final asset = timelineService.getAssetSafe(index);
// If asset is not available in buffer, return a placeholder
if (asset == null) {
return PhotoViewGalleryPageOptions.customChild(
heroAttributes: PhotoViewHeroAttributes(tag: 'loading_$index'),
child: Container(
width: ctx.width,
height: ctx.height,
color: backgroundColor,
child: const Center(child: CircularProgressIndicator()),
),
);
}
BaseAsset displayAsset = asset;
final stackChildren = ref.read(stackChildrenNotifier(asset)).valueOrNull; final stackChildren = ref.read(stackChildrenNotifier(asset)).valueOrNull;
if (stackChildren != null && stackChildren.isNotEmpty) { if (stackChildren != null && stackChildren.isNotEmpty) {
asset = stackChildren.elementAt(ref.read(assetViewerProvider.select((s) => s.stackIndex))); displayAsset = stackChildren.elementAt(ref.read(assetViewerProvider.select((s) => s.stackIndex)));
} }
final isPlayingMotionVideo = ref.read(isPlayingMotionVideoProvider); final isPlayingMotionVideo = ref.read(isPlayingMotionVideoProvider);
if (asset.isImage && !isPlayingMotionVideo) { if (displayAsset.isImage && !isPlayingMotionVideo) {
return _imageBuilder(ctx, asset); return _imageBuilder(ctx, displayAsset);
} }
return _videoBuilder(ctx, asset); return _videoBuilder(ctx, displayAsset);
} }
PhotoViewGalleryPageOptions _imageBuilder(BuildContext ctx, BaseAsset asset) { PhotoViewGalleryPageOptions _imageBuilder(BuildContext ctx, BaseAsset asset) {
@@ -515,8 +554,6 @@ 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,
initialScale: PhotoViewComputedScale.contained * 0.999,
minScale: PhotoViewComputedScale.contained * 0.999,
disableScaleGestures: showingBottomSheet, disableScaleGestures: showingBottomSheet,
onDragStart: _onDragStart, onDragStart: _onDragStart,
onDragUpdate: _onDragUpdate, onDragUpdate: _onDragUpdate,
@@ -545,9 +582,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
onTapDown: _onTapDown, onTapDown: _onTapDown,
heroAttributes: PhotoViewHeroAttributes(tag: '${asset.heroTag}_$heroOffset'), heroAttributes: PhotoViewHeroAttributes(tag: '${asset.heroTag}_$heroOffset'),
filterQuality: FilterQuality.high, filterQuality: FilterQuality.high,
initialScale: PhotoViewComputedScale.contained * 0.99,
maxScale: 1.0, maxScale: 1.0,
minScale: PhotoViewComputedScale.contained * 0.99,
basePosition: Alignment.center, basePosition: Alignment.center,
child: SizedBox( child: SizedBox(
width: ctx.width, width: ctx.width,

View File

@@ -11,7 +11,6 @@ import 'package:immich_mobile/domain/services/setting.service.dart';
import 'package:immich_mobile/extensions/codec_extensions.dart'; import 'package:immich_mobile/extensions/codec_extensions.dart';
import 'package:immich_mobile/infrastructure/repositories/asset_media.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/asset_media.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
import 'package:immich_mobile/presentation/widgets/images/one_frame_multi_image_stream_completer.dart'; import 'package:immich_mobile/presentation/widgets/images/one_frame_multi_image_stream_completer.dart';
import 'package:immich_mobile/presentation/widgets/timeline/constants.dart'; import 'package:immich_mobile/presentation/widgets/timeline/constants.dart';
import 'package:immich_mobile/providers/image/cache/thumbnail_image_cache_manager.dart'; import 'package:immich_mobile/providers/image/cache/thumbnail_image_cache_manager.dart';
@@ -107,7 +106,6 @@ class LocalFullImageProvider extends ImageProvider<LocalFullImageProvider> {
ImageStreamCompleter loadImage(LocalFullImageProvider key, ImageDecoderCallback decode) { ImageStreamCompleter loadImage(LocalFullImageProvider key, ImageDecoderCallback decode) {
return OneFramePlaceholderImageStreamCompleter( return OneFramePlaceholderImageStreamCompleter(
_codec(key, decode), _codec(key, decode),
initialImage: getCachedImage(LocalThumbProvider(id: key.id, updatedAt: key.updatedAt)),
informationCollector: () => <DiagnosticsNode>[ informationCollector: () => <DiagnosticsNode>[
DiagnosticsProperty<String>('Id', key.id), DiagnosticsProperty<String>('Id', key.id),
DiagnosticsProperty<DateTime>('Updated at', key.updatedAt), DiagnosticsProperty<DateTime>('Updated at', key.updatedAt),
@@ -117,13 +115,30 @@ class LocalFullImageProvider extends ImageProvider<LocalFullImageProvider> {
} }
// Streams in each stage of the image as we ask for it // Streams in each stage of the image as we ask for it
Stream<ImageInfo> _codec(LocalFullImageProvider key, ImageDecoderCallback decode) { Stream<ImageInfo> _codec(LocalFullImageProvider key, ImageDecoderCallback decode) async* {
try { try {
return switch (key.type) { // First, yield the thumbnail image from LocalThumbProvider
final thumbProvider = LocalThumbProvider(id: key.id, updatedAt: key.updatedAt);
try {
final thumbCodec = await thumbProvider._codec(
thumbProvider,
thumbProvider.cacheManager ?? ThumbnailImageCacheManager(),
decode,
);
final thumbImageInfo = await thumbCodec.getImageInfo();
yield thumbImageInfo;
} catch (_) {}
// Then proceed with the main image loading stream
final mainStream = switch (key.type) {
AssetType.image => _decodeProgressive(key, decode), AssetType.image => _decodeProgressive(key, decode),
AssetType.video => _getThumbnailCodec(key, decode), AssetType.video => _getThumbnailCodec(key, decode),
_ => throw StateError('Unsupported asset type ${key.type}'), _ => throw StateError('Unsupported asset type ${key.type}'),
}; };
await for (final imageInfo in mainStream) {
yield imageInfo;
}
} catch (error, stack) { } catch (error, stack) {
Logger('ImmichLocalImageProvider').severe('Error loading local image ${key.id}', error, stack); Logger('ImmichLocalImageProvider').severe('Error loading local image ${key.id}', error, stack);
throw const ImageLoadingException('Could not load image from local storage'); throw const ImageLoadingException('Could not load image from local storage');

View File

@@ -86,6 +86,7 @@ class _ImageWrapperState extends State<ImageWrapper> {
Size? _imageSize; Size? _imageSize;
Object? _lastException; Object? _lastException;
StackTrace? _lastStack; StackTrace? _lastStack;
bool _didLoadSynchronously = false;
@override @override
void dispose() { void dispose() {
@@ -130,9 +131,11 @@ class _ImageWrapperState extends State<ImageWrapper> {
_loadingProgress = null; _loadingProgress = null;
_lastException = null; _lastException = null;
_lastStack = null; _lastStack = null;
_didLoadSynchronously = synchronousCall;
} }
synchronousCall ? setupCB() : setState(setupCB); synchronousCall && !_didLoadSynchronously ? setupCB() : setState(setupCB);
} }
void handleError(dynamic error, StackTrace? stackTrace) { void handleError(dynamic error, StackTrace? stackTrace) {

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: 1.137.3 - API version: 1.138.0
- Generator version: 7.8.0 - Generator version: 7.8.0
- Build package: org.openapitools.codegen.languages.DartClientCodegen - Build package: org.openapitools.codegen.languages.DartClientCodegen

View File

@@ -2,7 +2,7 @@ name: immich_mobile
description: Immich - selfhosted backup media file on mobile phone description: Immich - selfhosted backup media file on mobile phone
publish_to: 'none' publish_to: 'none'
version: 1.137.3+3002 version: 1.138.0+3003
environment: environment:
sdk: '>=3.8.0 <4.0.0' sdk: '>=3.8.0 <4.0.0'

View File

@@ -9499,7 +9499,7 @@
"info": { "info": {
"title": "Immich", "title": "Immich",
"description": "Immich API", "description": "Immich API",
"version": "1.137.3", "version": "1.138.0",
"contact": {} "contact": {}
}, },
"tags": [], "tags": [],

View File

@@ -1,12 +1,12 @@
{ {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.137.3", "version": "1.138.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.137.3", "version": "1.138.0",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"@oazapfts/runtime": "^1.0.2" "@oazapfts/runtime": "^1.0.2"

View File

@@ -1,6 +1,6 @@
{ {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.137.3", "version": "1.138.0",
"description": "Auto-generated TypeScript SDK for the Immich API", "description": "Auto-generated TypeScript SDK for the Immich API",
"type": "module", "type": "module",
"main": "./build/index.js", "main": "./build/index.js",

View File

@@ -1,6 +1,6 @@
/** /**
* Immich * Immich
* 1.137.3 * 1.138.0
* DO NOT MODIFY - This file has been generated using oazapfts. * DO NOT MODIFY - This file has been generated using oazapfts.
* See https://www.npmjs.com/package/oazapfts * See https://www.npmjs.com/package/oazapfts
*/ */

View File

@@ -1,12 +1,12 @@
{ {
"name": "immich", "name": "immich",
"version": "1.137.3", "version": "1.138.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "immich", "name": "immich",
"version": "1.137.3", "version": "1.138.0",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"@nestjs/bullmq": "^11.0.1", "@nestjs/bullmq": "^11.0.1",

View File

@@ -1,6 +1,6 @@
{ {
"name": "immich", "name": "immich",
"version": "1.137.3", "version": "1.138.0",
"description": "", "description": "",
"author": "", "author": "",
"private": true, "private": true,

6
web/package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "immich-web", "name": "immich-web",
"version": "1.137.3", "version": "1.138.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "immich-web", "name": "immich-web",
"version": "1.137.3", "version": "1.138.0",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"@formatjs/icu-messageformat-parser": "^2.9.8", "@formatjs/icu-messageformat-parser": "^2.9.8",
@@ -94,7 +94,7 @@
}, },
"../open-api/typescript-sdk": { "../open-api/typescript-sdk": {
"name": "@immich/sdk", "name": "@immich/sdk",
"version": "1.137.3", "version": "1.138.0",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"dependencies": { "dependencies": {
"@oazapfts/runtime": "^1.0.2" "@oazapfts/runtime": "^1.0.2"

View File

@@ -1,6 +1,6 @@
{ {
"name": "immich-web", "name": "immich-web",
"version": "1.137.3", "version": "1.138.0",
"license": "GNU Affero General Public License version 3", "license": "GNU Affero General Public License version 3",
"type": "module", "type": "module",
"scripts": { "scripts": {