tech-systems / panes

🎉📱 Create dynamic modals, cards, panes for your applications in few steps. One instance – Thousands solutions. Any framework and free.
https://panejs.com
MIT License
681 stars 40 forks source link

[BUG] Android: Fast drag with single frame not trigger checkOpacityAttr() #154

Closed ebhsgit closed 2 years ago

ebhsgit commented 3 years ago

Describe the bug The setup

A page has a cupertino pane and google maps.

The pane has initial position set to bottom, and has middle breakpoint enabled, and top disabled. And UpperThanTop is set to false. There is content to be shown in the middle breakpoint. The content html element has the hide-on-bottom attribute.

On page load, both the pane and google map are created/displayed at the same time.

While the google map is still loading, when the user drag the pane to above the top position to open the pane to show the content.

The content is blank, but clickable (opacity = 0)

Dragging the pane again will result in showing the content (opacity = 1)

To Reproduce Create a app with the setup as described

Steps to reproduce the behavior:

  1. Start app
  2. As soon as the app loads. While the map is still loading, (ie: blank map still) Drag the pane up to open the pane, to show the content.
  3. Make sure to drag the pane above the middle break point

Demo src code that can reproduce the issue https://github.com/ebhsgit/cupertino-pane-test/tree/bug-content_not_visible

NOTE: If you want actual map to show, you need to change google map API key in config.xml

Expected behavior The content should be visible.

Screenshots Issue issue

Expected expected

Smartphone (please complete the following information):

Additional context

The problem is caused by TouchMove event not firing while the pane is being dragged.

Only the last event where the touchEvent position is above the topper. Which results in touchMove() exiting without executing checkOpacityAttr() and checkOverflowAttr()

I don't know what causes the touchMove events to be lost.

ebhsgit commented 3 years ago

My hack for the issue can be found here:

https://github.com/ebhsgit/cupertino-pane/commit/d9dd666455d4dcf1912d3ff41d10a03a2b377907


I did not raise the PR for my fix, because it is not fixing the cause of the issue (why touchMove events are not firing)

roman-rr commented 3 years ago

Hello @ebhsgit Nice to see you again! This is what i got from your repo video.mov.zip

Content is visible when i drag pane. I miss some step ?

ebhsgit commented 3 years ago

Hi @roman-rr Nice to hear from you again too :)

Here's the video of the issue capture.zip

To reproduce, you have to drag the pane as soon as the app starts.

Because, the issue exists only during the map loading phase. Once the map completes load, there is no issue.

I was able to confirm this by delaying the map load to after 3 seconds after page load (ie: setTimeout(() => loadMap(), 3000)). This way, at start of app dragging the pane is ok. Then I put it back to bottom state before map load. And during map load, when I drag to open again, the content is invisible.

ebhsgit commented 3 years ago

Here's the map delayed load example to show the issue is related to something that occurs during cordova google map loading.

The drag action has to occur after "starting map", but before "map load complete" toast.

Video map load with 3s delay.zip

Source code change example: image

roman-rr commented 3 years ago

@ebhsgit I have a few things to discuss regarding your issue.

  1. Do you have any ideas how to solve it ? image #1 image #2

  2. I guess that issue of few seconds callback is how to cordova-plugin-googlemaps prepare and modify DOM. Please read this

  3. Try to remove plugin and use google maps as html + js code and let me know difference then.

    <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"  async></script>
ebhsgit commented 3 years ago

For 1. The error is expected if you are "simulating" the ionic app in a browser. The plugin requires the device/host to have Google Services

How are you running/emulating the app? Simulate in browser? Or running on a device (including emulator)?

For 2. & 3. I am certain the issue is because cordova-plugin-googlemaps performs some form of DOM modification that is causing the events to not be triggered. I am not sure what exactly is the cause.

I was having bug reports from users saying that the pane was blank and I was never able to reproduce it. And looking through all the code, everything seems fine.

So I am reporting the issue so that you and others are made aware that there are issues using the 2 packages together (and possible others packages that would be doing the same or other DOM changes - since we don't know what changes causes the issue)


It would great if we can determine exactly what type of DOM changes causes touch event to be lost, so that we can either fix the issue or document the assumptions.

Even if the issue can't be fix, there are a few of work arounds developers could do in their app. (I'll use Google map as an example, but could be replaced with any other package that has compatibility issue with this package).

ebhsgit commented 3 years ago

Additionally, in my investigation of the issue.

I found a SO that talks about touch events being lost if DOM element is removed.

https://stackoverflow.com/questions/33298828/touch-move-event-dont-fire-after-touch-start-target-is-removed?noredirect=1&lq=1

From what I understand, the events in cupertino-pane is registered assuming no DOM change. (which should be ok assumption).


NOTE

I didn't find any thing in the cordova-plugin-googlemaps codebase that removed any elements. That said, the codebase is complex, so I could have easily missed something.

Maybe the cordova-plugin-googlemaps package owner @wf9a5m75 could let us know provide info. If he has time.

roman-rr commented 3 years ago

Thank you for investigation @ebhsgit I will look here more deeply to find an exact reason.

ebhsgit commented 3 years ago

Let me know if I can be any help :)

roman-rr commented 3 years ago

Hello @ebhsgit let's continue.

  1. I found strange behavior on videos you provided map load with 3s delay.zip and capture.zip. After "starting map" toast you move pane to the middle breakpoint. Pane moved immediately without animation with one frame. How you did it ? By fast drag gesture ? Normally it should be with at least few animation frames. I believe the issue is here.

  2. In my case google map initialized in less than 1 second and i can't reproduce and debug behavior. Any ways to reduce initialization speed ?
    initializationMap.mov.zip

  3. Google maps plugin make a lot's of changes in DOM, but i still doesn't check what exactly until we doesn't determinate reason of drag with one frame.

ebhsgit commented 3 years ago

Hi @roman-rr

Very good eyes. I didn't notice the pane opened in 1 frame in the video. When the issue occurs in real-time though, the pane open/dragging still looks smooth.

Answers to your question:

  1. I opened the pane by drag gesture. I drag the pane above the middle break point in one action. I guess it could be considered fast drag.

  2. I don't know of anyway to slow down the initialization. The easiest way to reproduce the issue is to use the test app without any changes (ie: without the 3 sec delay). Drag the pane, as soon as app start. For me I can reproduce it about 75% of the time with this approach.

roman-rr commented 3 years ago

Hello @ebhsgit To solve the issue we must recognize a reason, why pane moved without transition (with one animation frame) in the process of plugin initialization.

Even if it's "fast drag", transition must be visible to next breakpoint. To be sure that it is not fast drag, please try to reproduce with fastSwipeSensivity: 1000. 1000 should be enough for totally disable fastSwipe gesture.

If fastSwipeSensivity: 1000 solve issue, then i will looking how to fix this gesture. If still exist, then i will create pairing issue at plugin repository to define an exact reason.

Thank you.

ebhsgit commented 3 years ago

Thanks @roman-rr

I can confirm that I can still reproduce it with fastSwipeSensivity: 1000

It is easier to reproduce when the test app has the Google Map API Key set in the config.xml

ebhsgit commented 3 years ago

Another video captured using my phone recording the laptop screen.

https://user-images.githubusercontent.com/48874658/130400425-19236619-5c44-4f96-aeba-72a38b5235cb.mp4

The pane seems to complete the transition between bottom to top over a few frames. There are a few frames where the pane is still at the bottom, both there is also an expanded pane (in grey) Then a few frames later, the bottom pane disappears and the expanded pane "solidifies"

roman-rr commented 2 years ago

@ebhsgit Thank you for helps, it is definitely make pane better in common. The problem was not in google maps. Android trigger touchmove with low frequency on fast user swipe gesture. Therefore, touch end was interpreted gesture as tap and prevent opacity checks.

And this is why i personally like apple devices, for high responsible gestures. Anyway, fixed.