diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 8a2ba9f841434..bf393bbcf6439 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -43,7 +43,7 @@ jobs: retag_ml: name: Re-Tag ML needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_ml == 'false' }} + if: ${{ needs.pre-job.outputs.should_run_ml == 'false' && !github.event.pull_request.head.repo.fork }} runs-on: ubuntu-latest strategy: matrix: @@ -51,8 +51,6 @@ jobs: steps: - name: Login to GitHub Container Registry uses: docker/login-action@v3 - # Skip when PR from a fork - if: ${{ !github.event.pull_request.head.repo.fork }} with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -68,7 +66,7 @@ jobs: retag_server: name: Re-Tag Server needs: pre-job - if: ${{ needs.pre-job.outputs.should_run_server == 'false' }} + if: ${{ needs.pre-job.outputs.should_run_server == 'false' && !github.event.pull_request.head.repo.fork }} runs-on: ubuntu-latest strategy: matrix: @@ -76,8 +74,6 @@ jobs: steps: - name: Login to GitHub Container Registry uses: docker/login-action@v3 - # Skip when PR from a fork - if: ${{ !github.event.pull_request.head.repo.fork }} with: registry: ghcr.io username: ${{ github.repository_owner }} diff --git a/deployment/modules/cloudflare/docs-release/.terraform.lock.hcl b/deployment/modules/cloudflare/docs-release/.terraform.lock.hcl index 096177bb05366..afa00e60677c1 100644 --- a/deployment/modules/cloudflare/docs-release/.terraform.lock.hcl +++ b/deployment/modules/cloudflare/docs-release/.terraform.lock.hcl @@ -2,37 +2,37 @@ # Manual edits may be lost in future updates. provider "registry.opentofu.org/cloudflare/cloudflare" { - version = "4.40.0" - constraints = "4.40.0" + version = "4.41.0" + constraints = "4.41.0" hashes = [ - "h1:GP2N1tXrmpxu+qEDvFAmkfv9aeZNhag3bchyJpGpYbU=", - "h1:HDJKZBQkVU0kQl4gViQ5L7EcFLn9hB0iuvO+ORJiDS4=", - "h1:KrbeEsZoCJOnnX68yNI5h3QhMjc5bBCQW4yvYaEFq3s=", - "h1:LelwnzU0OVn6g2+T9Ub9XdpC+vbheraIL/qgXhWBs/k=", - "h1:TIq9CynfWrKgCxKL97Akj89cYlvJKn/AL4UXogd8/FM=", - "h1:Uoy5oPdm1ipDG7yIMCUN1IXMpsTGXahPw3I0rVA/6wA=", - "h1:Wunfpm+IZhENdoimrh4iXiakVnCsfKOHo80yJUjMQXM=", - "h1:cRdCuahMOFrNyldnCInqGQRBT1DTkRPSfPnaf5r05iw=", - "h1:k+zpXg8BO7gdbTIfSGyQisHhs5aVWQVbPLa5uUdr2UA=", - "h1:kWNrzZ8Rh0OpHikexkmwJIIucD6SMZPi4oGyDsKJitw=", - "h1:lomfTTjK78BdSEVTFcJUBQRy7IQHuGQImMaPWaYpfgQ=", - "h1:oWcWlZe52ZRyLQciNe94RaWzhHifSTu03nlK0uL7rlM=", - "h1:p3JJrhGEPlPQP7Uwy9FNMdvqCyD8tuT4lnXuJ+pSF/M=", - "h1:wtB0sKxG2K/H41hWJI4uJdImWquuaP34Sip5LmfE410=", - "zh:01742e5946f936548f8e42120287ffc757abf97e7cbbe34e25c266a438fb54fd", - "zh:08d81f5a5aab4cc269f983b8c6b5be0e278105136aca9681740802619577371f", - "zh:0d75131ba70902cfc94a7a5900369bdde56528b2aad6e10b164449cc97d57396", - "zh:3890a715a012e197541daacdacb8cceec6d364814daa4640ddfe98a8ba9036cb", - "zh:58254ce5ebe1faed4664df86210c39d660bcdc60280f17b25fe4d4dbea21ea8c", - "zh:6b0abc1adbc2edee79368ce9f7338ebcb5d0bf941e8d7d9ac505b750f20f80a2", - "zh:81cc415d1477174a1ca288d25fdb57e5ee488c2d7f61f265ef995b255a53b0ce", - "zh:8680140c7fe5beaefe61c5cfa471bf88422dc0c0f05dad6d3cb482d4ffd22be4", + "h1:0mc+YrjQrcctGrGYDmzlcqcgSv9MYB74rvMaZylIKC8=", + "h1:0zUx4vk4jOORQqn6xHBF7dO6N6bielFHdJ0mgF4Obn8=", + "h1:AsIZW3uLFNOZO7kL/K7/Y/S0IYxUV9Hz85NNk/3TTsA=", + "h1:FSgYM4+LHMbX/a4Y1kx7FPPWmXqS3/MQYzvjMJHHHWM=", + "h1:Tx6Nh3BWP1x9L3KK/Eyi+ET0T26g3+jf1jyiuqpNIis=", + "h1:VRI9wu8P43xxfpeTndRwsisLnqncfnmEYMOEH5zH4pQ=", + "h1:YxQqmiES/Yanq/VfGqBEqg+VIO7FGhO88aKoWFHyGIg=", + "h1:ZWHiaesjgDLKWlfdNj0oKyj/DWdxcfsO6NINu39zfpY=", + "h1:a2aCgDDBz3ccrr8YstIMl7VFnKo1xZAp+rOv59PPJ7U=", + "h1:aRyv8tB6wBAF9lKsLEdiHyCqnK5LfZq0FqMXCcUB4UU=", + "h1:lXpuO7zv2uD2GzPE1ARxznreRAh+QHTc2lAJ7iOoFgY=", + "h1:sA1xq0QNQ4fH8SHXouYNq50xirVD18SamKQwPsBQrrY=", + "h1:v7sHvKq7oqMYPn47ULHFyIQsKD9o+6Xg/uHbxQUixEw=", + "h1:wo/x4atWyXuWGlfR6h5nH0YwBAmBwTRY27HtWP8ycLo=", + "zh:339d26e06dc6fb299ea8aad9476a60fd65bb1d40631ae8eeb81cddf2dd2bebc8", + "zh:3dec2ad96ac2c283fd34ce65781b55c4edbb4d5c5cb53da8e31537176c0ed562", + "zh:5f63a5f8080319a2fff09d4d49944829fa708723436520787cfb60725ced80cf", + "zh:67162c28ccea71cb8141ed15c0637e35621354ebe14878e0b75a8f160fc5505d", + "zh:6ac1e07f5347b6395aca690ed22101bb25e957d25f986f760ff673a7adfd5ef6", + "zh:70282a723c7b52fcabde2baad41c864ed3a8d69f0c4d27a6b6933cac434cffc6", "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", - "zh:a491d26236122ccb83dac8cb490d2c0aa1f4d3a0b4abe99300fd49b1a624f42f", - "zh:a70d9c469dc8d55715ba77c9d1a4ede1fdebf79e60ee18438a0844868db54e0d", - "zh:a7fcb7d5c4222e14ec6d9a15adf8b9a083d84b102c3d0e4a0d102df5a1360b62", - "zh:b4f9677174fabd199c8ebd2e9e5eb3528cf887e700569a4fb61eef4e070cec5e", - "zh:c27f0f7519221d75dae4a3787a59e05acd5cc9a0d30a390eff349a77d20d52e6", - "zh:db00d8605dbf43ca42fe1481a6c67fdcaa73debb7d2a0f613cb95ae5c5e7150e", + "zh:924cd23abc326c6b3914e2cd9c94c7832c2552e1e9ae258fb9fd9aedaa5f7ce7", + "zh:a4b75e4c239879296259e7d54f1befbc7fdc16da2d62d1294e9f73add4cae61e", + "zh:a6ceb08feb63b00c7141783b31e45a154c76fd8cdebbdf371074805f0053572d", + "zh:afae1843f9ba85f2f6d94108c65cf43a457e83531a632d44d863e935160cb2ba", + "zh:bd6628ce60c778960a5755f7010b7e2cc5c6ff0341a21c175341b28058ec843d", + "zh:cd30866a1ff99d72b5fa1699db582fa4f25562e6ab21dcc6870324f3056108e0", + "zh:df5924cca691a8220aaaebb5cb55c3d6c32ff0a881f198695eff28155eb12b54", + "zh:e78d0696c941aba58df1cb36b8a0d25cd5f3963f01d9338fdbda74db58afdd49", ] } diff --git a/deployment/modules/cloudflare/docs-release/config.tf b/deployment/modules/cloudflare/docs-release/config.tf index 63c96fc49805b..18d8ff1eb4665 100644 --- a/deployment/modules/cloudflare/docs-release/config.tf +++ b/deployment/modules/cloudflare/docs-release/config.tf @@ -5,7 +5,7 @@ terraform { required_providers { cloudflare = { source = "cloudflare/cloudflare" - version = "4.40.0" + version = "4.41.0" } } } diff --git a/deployment/modules/cloudflare/docs/.terraform.lock.hcl b/deployment/modules/cloudflare/docs/.terraform.lock.hcl index 096177bb05366..afa00e60677c1 100644 --- a/deployment/modules/cloudflare/docs/.terraform.lock.hcl +++ b/deployment/modules/cloudflare/docs/.terraform.lock.hcl @@ -2,37 +2,37 @@ # Manual edits may be lost in future updates. provider "registry.opentofu.org/cloudflare/cloudflare" { - version = "4.40.0" - constraints = "4.40.0" + version = "4.41.0" + constraints = "4.41.0" hashes = [ - "h1:GP2N1tXrmpxu+qEDvFAmkfv9aeZNhag3bchyJpGpYbU=", - "h1:HDJKZBQkVU0kQl4gViQ5L7EcFLn9hB0iuvO+ORJiDS4=", - "h1:KrbeEsZoCJOnnX68yNI5h3QhMjc5bBCQW4yvYaEFq3s=", - "h1:LelwnzU0OVn6g2+T9Ub9XdpC+vbheraIL/qgXhWBs/k=", - "h1:TIq9CynfWrKgCxKL97Akj89cYlvJKn/AL4UXogd8/FM=", - "h1:Uoy5oPdm1ipDG7yIMCUN1IXMpsTGXahPw3I0rVA/6wA=", - "h1:Wunfpm+IZhENdoimrh4iXiakVnCsfKOHo80yJUjMQXM=", - "h1:cRdCuahMOFrNyldnCInqGQRBT1DTkRPSfPnaf5r05iw=", - "h1:k+zpXg8BO7gdbTIfSGyQisHhs5aVWQVbPLa5uUdr2UA=", - "h1:kWNrzZ8Rh0OpHikexkmwJIIucD6SMZPi4oGyDsKJitw=", - "h1:lomfTTjK78BdSEVTFcJUBQRy7IQHuGQImMaPWaYpfgQ=", - "h1:oWcWlZe52ZRyLQciNe94RaWzhHifSTu03nlK0uL7rlM=", - "h1:p3JJrhGEPlPQP7Uwy9FNMdvqCyD8tuT4lnXuJ+pSF/M=", - "h1:wtB0sKxG2K/H41hWJI4uJdImWquuaP34Sip5LmfE410=", - "zh:01742e5946f936548f8e42120287ffc757abf97e7cbbe34e25c266a438fb54fd", - "zh:08d81f5a5aab4cc269f983b8c6b5be0e278105136aca9681740802619577371f", - "zh:0d75131ba70902cfc94a7a5900369bdde56528b2aad6e10b164449cc97d57396", - "zh:3890a715a012e197541daacdacb8cceec6d364814daa4640ddfe98a8ba9036cb", - "zh:58254ce5ebe1faed4664df86210c39d660bcdc60280f17b25fe4d4dbea21ea8c", - "zh:6b0abc1adbc2edee79368ce9f7338ebcb5d0bf941e8d7d9ac505b750f20f80a2", - "zh:81cc415d1477174a1ca288d25fdb57e5ee488c2d7f61f265ef995b255a53b0ce", - "zh:8680140c7fe5beaefe61c5cfa471bf88422dc0c0f05dad6d3cb482d4ffd22be4", + "h1:0mc+YrjQrcctGrGYDmzlcqcgSv9MYB74rvMaZylIKC8=", + "h1:0zUx4vk4jOORQqn6xHBF7dO6N6bielFHdJ0mgF4Obn8=", + "h1:AsIZW3uLFNOZO7kL/K7/Y/S0IYxUV9Hz85NNk/3TTsA=", + "h1:FSgYM4+LHMbX/a4Y1kx7FPPWmXqS3/MQYzvjMJHHHWM=", + "h1:Tx6Nh3BWP1x9L3KK/Eyi+ET0T26g3+jf1jyiuqpNIis=", + "h1:VRI9wu8P43xxfpeTndRwsisLnqncfnmEYMOEH5zH4pQ=", + "h1:YxQqmiES/Yanq/VfGqBEqg+VIO7FGhO88aKoWFHyGIg=", + "h1:ZWHiaesjgDLKWlfdNj0oKyj/DWdxcfsO6NINu39zfpY=", + "h1:a2aCgDDBz3ccrr8YstIMl7VFnKo1xZAp+rOv59PPJ7U=", + "h1:aRyv8tB6wBAF9lKsLEdiHyCqnK5LfZq0FqMXCcUB4UU=", + "h1:lXpuO7zv2uD2GzPE1ARxznreRAh+QHTc2lAJ7iOoFgY=", + "h1:sA1xq0QNQ4fH8SHXouYNq50xirVD18SamKQwPsBQrrY=", + "h1:v7sHvKq7oqMYPn47ULHFyIQsKD9o+6Xg/uHbxQUixEw=", + "h1:wo/x4atWyXuWGlfR6h5nH0YwBAmBwTRY27HtWP8ycLo=", + "zh:339d26e06dc6fb299ea8aad9476a60fd65bb1d40631ae8eeb81cddf2dd2bebc8", + "zh:3dec2ad96ac2c283fd34ce65781b55c4edbb4d5c5cb53da8e31537176c0ed562", + "zh:5f63a5f8080319a2fff09d4d49944829fa708723436520787cfb60725ced80cf", + "zh:67162c28ccea71cb8141ed15c0637e35621354ebe14878e0b75a8f160fc5505d", + "zh:6ac1e07f5347b6395aca690ed22101bb25e957d25f986f760ff673a7adfd5ef6", + "zh:70282a723c7b52fcabde2baad41c864ed3a8d69f0c4d27a6b6933cac434cffc6", "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", - "zh:a491d26236122ccb83dac8cb490d2c0aa1f4d3a0b4abe99300fd49b1a624f42f", - "zh:a70d9c469dc8d55715ba77c9d1a4ede1fdebf79e60ee18438a0844868db54e0d", - "zh:a7fcb7d5c4222e14ec6d9a15adf8b9a083d84b102c3d0e4a0d102df5a1360b62", - "zh:b4f9677174fabd199c8ebd2e9e5eb3528cf887e700569a4fb61eef4e070cec5e", - "zh:c27f0f7519221d75dae4a3787a59e05acd5cc9a0d30a390eff349a77d20d52e6", - "zh:db00d8605dbf43ca42fe1481a6c67fdcaa73debb7d2a0f613cb95ae5c5e7150e", + "zh:924cd23abc326c6b3914e2cd9c94c7832c2552e1e9ae258fb9fd9aedaa5f7ce7", + "zh:a4b75e4c239879296259e7d54f1befbc7fdc16da2d62d1294e9f73add4cae61e", + "zh:a6ceb08feb63b00c7141783b31e45a154c76fd8cdebbdf371074805f0053572d", + "zh:afae1843f9ba85f2f6d94108c65cf43a457e83531a632d44d863e935160cb2ba", + "zh:bd6628ce60c778960a5755f7010b7e2cc5c6ff0341a21c175341b28058ec843d", + "zh:cd30866a1ff99d72b5fa1699db582fa4f25562e6ab21dcc6870324f3056108e0", + "zh:df5924cca691a8220aaaebb5cb55c3d6c32ff0a881f198695eff28155eb12b54", + "zh:e78d0696c941aba58df1cb36b8a0d25cd5f3963f01d9338fdbda74db58afdd49", ] } diff --git a/deployment/modules/cloudflare/docs/config.tf b/deployment/modules/cloudflare/docs/config.tf index 63c96fc49805b..18d8ff1eb4665 100644 --- a/deployment/modules/cloudflare/docs/config.tf +++ b/deployment/modules/cloudflare/docs/config.tf @@ -5,7 +5,7 @@ terraform { required_providers { cloudflare = { source = "cloudflare/cloudflare" - version = "4.40.0" + version = "4.41.0" } } } diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index 492f5b0c3d6e4..f42bcc0ab0a73 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -98,7 +98,7 @@ services: redis: container_name: immich_redis - image: redis:6.2-alpine@sha256:fd1b5400ca24adc2ff77abdf00acb72c3aae85b94e43557ab2606d29a74bfa01 + image: redis:6.2-alpine@sha256:2d1463258f2764328496376f5d965f20c6a67f66ea2b06dc42af351f75248792 healthcheck: test: redis-cli ping || exit 1 diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml index 20126457aa47e..05e35ac8c1fe5 100644 --- a/docker/docker-compose.prod.yml +++ b/docker/docker-compose.prod.yml @@ -47,7 +47,7 @@ services: redis: container_name: immich_redis - image: redis:6.2-alpine@sha256:fd1b5400ca24adc2ff77abdf00acb72c3aae85b94e43557ab2606d29a74bfa01 + image: redis:6.2-alpine@sha256:2d1463258f2764328496376f5d965f20c6a67f66ea2b06dc42af351f75248792 healthcheck: test: redis-cli ping || exit 1 restart: always diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index f0590385e4f90..eec723dc08dbb 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -48,7 +48,7 @@ services: redis: container_name: immich_redis - image: docker.io/redis:6.2-alpine@sha256:fd1b5400ca24adc2ff77abdf00acb72c3aae85b94e43557ab2606d29a74bfa01 + image: docker.io/redis:6.2-alpine@sha256:2d1463258f2764328496376f5d965f20c6a67f66ea2b06dc42af351f75248792 healthcheck: test: redis-cli ping || exit 1 restart: always diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml index ce3d1d7ab1334..dbb95f176d7e7 100644 --- a/e2e/docker-compose.yml +++ b/e2e/docker-compose.yml @@ -33,7 +33,7 @@ services: - 2285:3001 redis: - image: redis:6.2-alpine@sha256:fd1b5400ca24adc2ff77abdf00acb72c3aae85b94e43557ab2606d29a74bfa01 + image: redis:6.2-alpine@sha256:2d1463258f2764328496376f5d965f20c6a67f66ea2b06dc42af351f75248792 database: image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0 diff --git a/mobile/lib/widgets/asset_grid/draggable_scrollbar_custom.dart b/mobile/lib/widgets/asset_grid/draggable_scrollbar_custom.dart index 4490da7aedac1..746bbde6efd3c 100644 --- a/mobile/lib/widgets/asset_grid/draggable_scrollbar_custom.dart +++ b/mobile/lib/widgets/asset_grid/draggable_scrollbar_custom.dart @@ -59,8 +59,6 @@ class DraggableScrollbar extends StatefulWidget { final Function(bool scrolling) scrollStateListener; - final double viewPortHeight; - DraggableScrollbar.semicircle({ super.key, Key? scrollThumbKey, @@ -69,7 +67,6 @@ class DraggableScrollbar extends StatefulWidget { required this.controller, required this.itemPositionsListener, required this.scrollStateListener, - required this.viewPortHeight, this.heightScrollThumb = 48.0, this.backgroundColor = Colors.white, this.padding, @@ -254,7 +251,7 @@ class DraggableScrollbarState extends State } double get barMaxScrollExtent => - widget.viewPortHeight - + (context.size?.height ?? 0) - widget.heightScrollThumb - (widget.heightOffset ?? 0); @@ -340,8 +337,8 @@ class DraggableScrollbarState extends State _thumbAnimationController.forward(); } - if (itemPos < maxItemCount) { - _currentItem = itemPos; + if (itemPosition < maxItemCount) { + _currentItem = itemPosition; } _fadeoutTimer?.cancel(); @@ -365,25 +362,35 @@ class DraggableScrollbarState extends State widget.scrollStateListener(true); } - int get itemPos { + int get itemPosition { int numberOfItems = widget.child.itemCount; return ((_barOffset / barMaxScrollExtent) * numberOfItems).toInt(); } - void _jumpToBarPos() { - if (itemPos > maxItemCount - 1) { + void _jumpToBarPosition() { + if (itemPosition > maxItemCount - 1) { return; } - _currentItem = itemPos; + _currentItem = itemPosition; + + /// If the bar is at the bottom but the item position is still smaller than the max item count (due to rounding error) + /// jump to the end of the list + if (barMaxScrollExtent - _barOffset < 10 && itemPosition < maxItemCount) { + widget.controller.jumpTo( + index: maxItemCount, + ); + + return; + } widget.controller.jumpTo( - index: itemPos, + index: itemPosition, ); } Timer? dragHaltTimer; - int lastTimerPos = 0; + int lastTimerPosition = 0; void _onVerticalDragUpdate(DragUpdateDetails details) { setState(() { @@ -400,8 +407,8 @@ class DraggableScrollbarState extends State _barOffset = barMaxScrollExtent; } - if (itemPos != lastTimerPos) { - lastTimerPos = itemPos; + if (itemPosition != lastTimerPosition) { + lastTimerPosition = itemPosition; dragHaltTimer?.cancel(); widget.scrollStateListener(true); @@ -413,7 +420,7 @@ class DraggableScrollbarState extends State ); } - _jumpToBarPos(); + _jumpToBarPosition(); } }); } @@ -426,7 +433,7 @@ class DraggableScrollbarState extends State }); setState(() { - _jumpToBarPos(); + _jumpToBarPosition(); _isDragInProcess = false; }); diff --git a/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart b/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart index 8ae74ba120f59..38e499b5dec8e 100644 --- a/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart +++ b/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart @@ -264,7 +264,6 @@ class ImmichAssetGridViewState extends ConsumerState { final child = (useDragScrolling && ModalRoute.of(context) != null) ? DraggableScrollbar.semicircle( - viewPortHeight: context.height, scrollStateListener: dragScrolling, itemPositionsListener: _itemPositionsListener, controller: _itemScrollController, diff --git a/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart b/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart index 1c9713f4d7fc5..cd694336bc5af 100644 --- a/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart +++ b/mobile/lib/widgets/common/app_bar_dialog/app_bar_dialog.dart @@ -237,35 +237,40 @@ class ImmichAppBarDialog extends HookConsumerWidget { ); } - return Dialog( - clipBehavior: Clip.hardEdge, - alignment: Alignment.topCenter, - insetPadding: EdgeInsets.only( - top: isHorizontal ? 20 : 40, - left: horizontalPadding, - right: horizontalPadding, - bottom: isHorizontal ? 20 : 100, - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - child: SizedBox( - child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - padding: const EdgeInsets.all(20), - child: buildTopRow(), - ), - const AppBarProfileInfoBox(), - buildStorageInformation(), - const AppBarServerInfo(), - buildAppLogButton(), - buildSettingButton(), - buildSignOutButton(), - buildFooter(), - ], + return Dismissible( + direction: DismissDirection.down, + onDismissed: (_) => Navigator.of(context).pop(), + key: const Key('app_bar_dialog'), + child: Dialog( + clipBehavior: Clip.hardEdge, + alignment: Alignment.topCenter, + insetPadding: EdgeInsets.only( + top: isHorizontal ? 20 : 40, + left: horizontalPadding, + right: horizontalPadding, + bottom: isHorizontal ? 20 : 100, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + child: SizedBox( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: const EdgeInsets.all(20), + child: buildTopRow(), + ), + const AppBarProfileInfoBox(), + buildStorageInformation(), + const AppBarServerInfo(), + buildAppLogButton(), + buildSettingButton(), + buildSignOutButton(), + buildFooter(), + ], + ), ), ), ), diff --git a/server/src/migrations/1725730782681-RemoveHiddenAssetsFromAlbums.ts b/server/src/migrations/1725730782681-RemoveHiddenAssetsFromAlbums.ts new file mode 100644 index 0000000000000..2dfb5b7978be3 --- /dev/null +++ b/server/src/migrations/1725730782681-RemoveHiddenAssetsFromAlbums.ts @@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class RemoveHiddenAssetsFromAlbums1725730782681 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `DELETE FROM "albums_assets_assets" WHERE "assetsId" IN (SELECT "id" FROM "assets" WHERE "isVisible" = false)`, + ); + } + + public async down(): Promise { + // noop + } +} diff --git a/server/src/services/asset-media.service.ts b/server/src/services/asset-media.service.ts index 9ce2e58d28fad..76c6b49716413 100644 --- a/server/src/services/asset-media.service.ts +++ b/server/src/services/asset-media.service.ts @@ -163,7 +163,7 @@ export class AssetMediaService { throw new BadRequestException('Live photo video not found'); } if (motionAsset.type !== AssetType.VIDEO) { - throw new BadRequestException('Live photo vide must be a video'); + throw new BadRequestException('Live photo video must be a video'); } if (motionAsset.ownerId !== auth.user.id) { throw new BadRequestException('Live photo video does not belong to the user'); diff --git a/server/src/services/metadata.service.spec.ts b/server/src/services/metadata.service.spec.ts index 5b447c235539e..8e865bd20fd90 100644 --- a/server/src/services/metadata.service.spec.ts +++ b/server/src/services/metadata.service.spec.ts @@ -453,7 +453,7 @@ describe(MetadataService.name, () => { it('should extract hierarchy from HierarchicalSubject', async () => { assetMock.getByIds.mockResolvedValue([assetStub.image]); - metadataMock.readTags.mockResolvedValue({ HierarchicalSubject: ['Parent|Child'] }); + metadataMock.readTags.mockResolvedValue({ HierarchicalSubject: ['Parent|Child', 'TagA'] }); tagMock.upsertValue.mockResolvedValueOnce(tagStub.parent); tagMock.upsertValue.mockResolvedValueOnce(tagStub.child); @@ -465,6 +465,7 @@ describe(MetadataService.name, () => { value: 'Parent/Child', parent: tagStub.parent, }); + expect(tagMock.upsertValue).toHaveBeenNthCalledWith(3, { userId: 'user-id', value: 'TagA', parent: undefined }); }); it('should extract ignore / characters in a HierarchicalSubject tag', async () => { diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index cf51a332f844c..83f0abd79bdf8 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -384,12 +384,12 @@ export class MetadataService { } private async applyTagList(asset: AssetEntity, exifTags: ImmichTags) { - const tags: unknown[] = []; + const tags: Array = []; if (exifTags.TagsList) { tags.push(...exifTags.TagsList); } else if (exifTags.HierarchicalSubject) { tags.push( - exifTags.HierarchicalSubject.map((tag) => + ...exifTags.HierarchicalSubject.map((tag) => tag // convert | to / .replaceAll('/', '') diff --git a/web/src/lib/components/shared-components/navigation-bar/account-info-panel.svelte b/web/src/lib/components/shared-components/navigation-bar/account-info-panel.svelte index a23ef6eab2a4b..ef103a9e03d4d 100644 --- a/web/src/lib/components/shared-components/navigation-bar/account-info-panel.svelte +++ b/web/src/lib/components/shared-components/navigation-bar/account-info-panel.svelte @@ -7,13 +7,14 @@ import { preferences, user } from '$lib/stores/user.store'; import { handleError } from '$lib/utils/handle-error'; import { deleteProfileImage, updateMyPreferences, type UserAvatarColor } from '@immich/sdk'; - import { mdiCog, mdiLogout, mdiPencil } from '@mdi/js'; + import { mdiCog, mdiLogout, mdiPencil, mdiWrench } from '@mdi/js'; import { createEventDispatcher } from 'svelte'; import { fade } from 'svelte/transition'; import { NotificationType, notificationController } from '../notification/notification'; import UserAvatar from '../user-avatar.svelte'; import AvatarSelector from './avatar-selector.svelte'; import { t } from 'svelte-i18n'; + import { page } from '$app/stores'; let isShowSelectAvatar = false; @@ -46,7 +47,7 @@ in:fade={{ duration: 100 }} out:fade={{ duration: 100 }} id="account-info-panel" - class="absolute right-[25px] top-[75px] z-[100] w-[360px] rounded-3xl bg-gray-200 shadow-lg dark:border dark:border-immich-dark-gray dark:bg-immich-dark-gray" + class="absolute right-[25px] top-[75px] z-[100] w-[min(360px,100vw-50px)] rounded-3xl bg-gray-200 shadow-lg dark:border dark:border-immich-dark-gray dark:bg-immich-dark-gray" use:focusTrap >
{$user.email}

- +
+ + {#if $user.isAdmin} + + {/if} +
diff --git a/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte b/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte index ad8801ff3f8bf..58a4c23d741a4 100644 --- a/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte +++ b/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte @@ -9,10 +9,10 @@ import { user } from '$lib/stores/user.store'; import { handleLogout } from '$lib/utils/auth'; import { logout } from '@immich/sdk'; - import { mdiCog, mdiMagnify, mdiTrayArrowUp } from '@mdi/js'; + import { mdiMagnify, mdiTrayArrowUp } from '@mdi/js'; import { createEventDispatcher } from 'svelte'; import { t } from 'svelte-i18n'; - import { fade, fly } from 'svelte/transition'; + import { fade } from 'svelte/transition'; import { AppRoute } from '../../../constants'; import ImmichLogo from '../immich-logo.svelte'; import SearchBar from '../search-bar/search-bar.svelte'; @@ -45,72 +45,41 @@ -
-