[BUG] Android, swipe up issues on portrait orientated photos to show details #1956

Closed
opened 2026-02-05 04:35:22 +03:00 by OVERLORD · 8 comments
Owner

Originally created by @aisbergde on GitHub (Jan 8, 2024).

The bug

On the Android client, swipe up on photos should show details. This works fine on landscape photos. But it often not works on portrait orientated pictures.

The OS that Immich Server is running on

docker in synology

Version of Immich Server

1.91.4

Version of Immich Mobile App

v1.92.0

Platform with the issue

  • Server
  • Web
  • Mobile

Your docker-compose.yml content

-

Your .env content

-

Reproduction steps

1.
2.
3.
...

Additional information

No response

Originally created by @aisbergde on GitHub (Jan 8, 2024). ### The bug On the Android client, swipe up on photos should show details. This works fine on landscape photos. But it often not works on portrait orientated pictures. ### The OS that Immich Server is running on docker in synology ### Version of Immich Server 1.91.4 ### Version of Immich Mobile App v1.92.0 ### Platform with the issue - [ ] Server - [ ] Web - [X] Mobile ### Your docker-compose.yml content ```YAML - ``` ### Your .env content ```Shell - ``` ### Reproduction steps ```bash 1. 2. 3. ... ``` ### Additional information _No response_
OVERLORD added the 📱mobile label 2026-02-05 04:35:22 +03:00
Author
Owner

@aisbergde commented on GitHub (Feb 1, 2024):

another swipe issue on portrait orientation assets:
when an asset is in landscape orientation, then one swipe to the left or to the right is enough, to move to the previous or next picture. But if the asset is in portrait orientation, then always 2 swipes are required. This issue can always be reproduced.

@aisbergde commented on GitHub (Feb 1, 2024): another swipe issue on portrait orientation assets: when an asset is in landscape orientation, then one swipe to the left or to the right is enough, to move to the previous or next picture. But if the asset is in portrait orientation, then always 2 swipes are required. This issue can always be reproduced.
Author
Owner

@aisbergde commented on GitHub (Feb 1, 2024):

but what is not clear: when this happens. in some sessions it happens to all portrait orientated assets, in another session one swipe is enough. I did not yet understand, what's the difference.

@aisbergde commented on GitHub (Feb 1, 2024): but what is not clear: when this happens. in some sessions it happens to all portrait orientated assets, in another session one swipe is enough. I did not yet understand, what's the difference.
Author
Owner

@SilviuCPopa commented on GitHub (Dec 12, 2024):

I have the same issue on IOS

@SilviuCPopa commented on GitHub (Dec 12, 2024): I have the same issue on IOS
Author
Owner

@mrbiggfoot commented on GitHub (Dec 17, 2024):

when an asset is in landscape orientation, then one swipe to the left or to the right is enough, to move to the previous or next picture. But if the asset is in portrait orientation, then always 2 swipes are required. This issue can always be reproduced.

I can confirm. The latest Android app from the play store still has this problem. Very annoying.

@mrbiggfoot commented on GitHub (Dec 17, 2024): > when an asset is in landscape orientation, then one swipe to the left or to the right is enough, to move to the previous or next picture. But if the asset is in portrait orientation, then always 2 swipes are required. This issue can always be reproduced. I can confirm. The latest Android app from the play store still has this problem. Very annoying.
Author
Owner

@evildad commented on GitHub (Jan 9, 2025):

@jrasm91 I can confirm the double swipe issue, too. First I thought there's something wrong with my installation but I tried with the official Immich Demo and had the problem there, too.
Holding the phone in landscape mode fixes the swipe problem for portrait images and vice versa.
Is there any chance to debug the problem?

@evildad commented on GitHub (Jan 9, 2025): @jrasm91 I can confirm the double swipe issue, too. First I thought there's something wrong with my installation but I tried with the official Immich Demo and had the problem there, too. Holding the phone in landscape mode fixes the swipe problem for portrait images and vice versa. Is there any chance to debug the problem?
Author
Owner

@ch4rl3x commented on GitHub (Feb 12, 2025):

This issue still exists. Swiping left/right between pictures and swipe up for detail is often not working

@ch4rl3x commented on GitHub (Feb 12, 2025): This issue still exists. Swiping left/right between pictures and swipe up for detail is often not working
Author
Owner

@EinToni commented on GitHub (Apr 23, 2025):

I took a look into this and the culprit appears to be the PhotoViewGestureRecognizer set up here. When this gets removed, the zoom and pan is no longer working, but the left/right swipe and up swipe is working without needing a double swipe.
I can verify this problem appears on certain images, although I only have it happen on one specific image. I don't know what the actual reason is.

It appears that on certain image, the PhotoViewGestureRecognizer somehow swallows some input events and prevents the actual swipe.

Example Video

In the video you can also nicely see that something is indeed changing when I try to swipe (the color border of the widget changes), but nothing visibly happens.

https://github.com/user-attachments/assets/6fc1b5be-1720-40d5-a766-a9708e2fcc29

I also added a few more messages in the log:

Successful swipe Log

I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerAddedEvent
I/flutter ( 9409): handleEvent _TransformedPointerDownEvent, Axis.horizontal, didChangeConfiguration true, _pointerLocations {12: Offset(101.3, 473.9)}
I/flutter ( 9409): _currentSpan: 0.0
I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(0.0, 0.0), shouldMove: false, _pointerLocations.keys.length: 1
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerDownEvent
I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {12: Offset(102.5, 473.9)}
I/flutter ( 9409): _currentSpan: 0.0
I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-1.1, 0.0), shouldMove: false, _pointerLocations.keys.length: 1
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent
I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {12: Offset(105.5, 473.9)}
I/flutter ( 9409): _currentSpan: 0.0
I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-4.2, 0.0), shouldMove: false, _pointerLocations.keys.length: 1
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent
I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {12: Offset(109.7, 472.7)}
I/flutter ( 9409): _currentSpan: 0.0
I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-8.4, 1.2), shouldMove: false, _pointerLocations.keys.length: 1
4
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent
D/EGL_emulation( 9409): app_time_stats: avg=46762.25ms min=46762.25ms max=46762.25ms count=1
7
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerUpEvent
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerRemovedEvent

Failing swipe Log

I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerAddedEvent
I/flutter ( 9409): handleEvent _TransformedPointerDownEvent, Axis.horizontal, didChangeConfiguration true, _pointerLocations {11: Offset(123.4, 461.7)}
I/flutter ( 9409): _currentSpan: 0.0
I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(0.0, 0.0), shouldMove: false, _pointerLocations.keys.length: 1
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerDownEvent
I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {11: Offset(179.8, 465.9)}
I/flutter ( 9409): _currentSpan: 0.0
I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-56.4, -4.2), shouldMove: true, _pointerLocations.keys.length: 1
I/flutter ( 9409): spanDelta: 0.0, focalPointDelta: 56.531534976139824
I/flutter ( 9409): Accept Gesture!
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent
D/EGL_emulation( 9409): app_time_stats: avg=365.06ms min=7.67ms max=3636.16ms count=11
I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {11: Offset(275.4, 465.9)}
I/flutter ( 9409): _currentSpan: 0.0
I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-152.0, -4.2), shouldMove: false, _pointerLocations.keys.length: 1
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent
I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {11: Offset(351.6, 465.9)}
I/flutter ( 9409): _currentSpan: 0.0
I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-228.2, -4.2), shouldMove: false, _pointerLocations.keys.length: 1
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent
I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {11: Offset(387.0, 465.9)}
I/flutter ( 9409): _currentSpan: 0.0
I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-263.6, -4.2), shouldMove: false, _pointerLocations.keys.length: 1
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent
I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {11: Offset(411.0, 465.9)}
I/flutter ( 9409): _currentSpan: 0.0
I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-287.6, -4.2), shouldMove: false, _pointerLocations.keys.length: 1
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent
I/flutter ( 9409): handleEvent _TransformedPointerUpEvent, Axis.horizontal, didChangeConfiguration true, _pointerLocations {}
I/flutter ( 9409): _currentSpan: 0.0
I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(0.0, 0.0), shouldMove: false, _pointerLocations.keys.length: 0
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerUpEvent
I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerRemovedEvent

Unfortunately I am a bit lost and don't really know how to further continue my bug hunt. Maybe someone else has an idea.

@EinToni commented on GitHub (Apr 23, 2025): I took a look into this and the culprit appears to be the `PhotoViewGestureRecognizer` set up [here](https://github.com/immich-app/immich/blob/main/mobile/lib/widgets/photo_view/src/core/photo_view_gesture_detector.dart#L89). When this gets removed, the zoom and pan is no longer working, but the left/right swipe and up swipe is working without needing a double swipe. I can verify this problem appears on certain images, although I only have it happen on one specific image. I don't know what the actual reason is. It appears that on certain image, the `PhotoViewGestureRecognizer` somehow swallows some input events and prevents the actual swipe. <details><summary>Example Video</summary> <p> In the video you can also nicely see that something is indeed changing when I try to swipe (the color border of the widget changes), but nothing visibly happens. https://github.com/user-attachments/assets/6fc1b5be-1720-40d5-a766-a9708e2fcc29 </p> </details> I also added a few more messages in the log: <details><summary>Successful swipe Log</summary> <p> ``` I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerAddedEvent I/flutter ( 9409): handleEvent _TransformedPointerDownEvent, Axis.horizontal, didChangeConfiguration true, _pointerLocations {12: Offset(101.3, 473.9)} I/flutter ( 9409): _currentSpan: 0.0 I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(0.0, 0.0), shouldMove: false, _pointerLocations.keys.length: 1 I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerDownEvent I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {12: Offset(102.5, 473.9)} I/flutter ( 9409): _currentSpan: 0.0 I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-1.1, 0.0), shouldMove: false, _pointerLocations.keys.length: 1 I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {12: Offset(105.5, 473.9)} I/flutter ( 9409): _currentSpan: 0.0 I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-4.2, 0.0), shouldMove: false, _pointerLocations.keys.length: 1 I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {12: Offset(109.7, 472.7)} I/flutter ( 9409): _currentSpan: 0.0 I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-8.4, 1.2), shouldMove: false, _pointerLocations.keys.length: 1 4 I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent D/EGL_emulation( 9409): app_time_stats: avg=46762.25ms min=46762.25ms max=46762.25ms count=1 7 I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerUpEvent I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerRemovedEvent ``` </p> </details> <details><summary>Failing swipe Log</summary> <p> ``` I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerAddedEvent I/flutter ( 9409): handleEvent _TransformedPointerDownEvent, Axis.horizontal, didChangeConfiguration true, _pointerLocations {11: Offset(123.4, 461.7)} I/flutter ( 9409): _currentSpan: 0.0 I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(0.0, 0.0), shouldMove: false, _pointerLocations.keys.length: 1 I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerDownEvent I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {11: Offset(179.8, 465.9)} I/flutter ( 9409): _currentSpan: 0.0 I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-56.4, -4.2), shouldMove: true, _pointerLocations.keys.length: 1 I/flutter ( 9409): spanDelta: 0.0, focalPointDelta: 56.531534976139824 I/flutter ( 9409): Accept Gesture! I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent D/EGL_emulation( 9409): app_time_stats: avg=365.06ms min=7.67ms max=3636.16ms count=11 I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {11: Offset(275.4, 465.9)} I/flutter ( 9409): _currentSpan: 0.0 I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-152.0, -4.2), shouldMove: false, _pointerLocations.keys.length: 1 I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {11: Offset(351.6, 465.9)} I/flutter ( 9409): _currentSpan: 0.0 I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-228.2, -4.2), shouldMove: false, _pointerLocations.keys.length: 1 I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {11: Offset(387.0, 465.9)} I/flutter ( 9409): _currentSpan: 0.0 I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-263.6, -4.2), shouldMove: false, _pointerLocations.keys.length: 1 I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent I/flutter ( 9409): handleEvent _TransformedPointerMoveEvent, Axis.horizontal, didChangeConfiguration false, _pointerLocations {11: Offset(411.0, 465.9)} I/flutter ( 9409): _currentSpan: 0.0 I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(-287.6, -4.2), shouldMove: false, _pointerLocations.keys.length: 1 I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerMoveEvent I/flutter ( 9409): handleEvent _TransformedPointerUpEvent, Axis.horizontal, didChangeConfiguration true, _pointerLocations {} I/flutter ( 9409): _currentSpan: 0.0 I/flutter ( 9409): _decideIfWeAcceptEvent, move: Offset(0.0, 0.0), shouldMove: false, _pointerLocations.keys.length: 0 I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerUpEvent I/flutter ( 9409): (main.dart) Event GlobalRoute -> Pointer Event: PointerRemovedEvent ``` </p> </details> Unfortunately I am a bit lost and don't really know how to further continue my bug hunt. Maybe someone else has an idea.
Author
Owner

@alextran1502 commented on GitHub (Nov 9, 2025):

This is no longer relevant with the new implementation, please open a new issue if it is still persisted

@alextran1502 commented on GitHub (Nov 9, 2025): This is no longer relevant with the new implementation, please open a new issue if it is still persisted
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: immich-app/immich#1956