Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
ebhsgit opened this issue Jul 6, 2021 · 15 comments
Closed
Assignees

Comments

@ebhsgit
Copy link
Contributor

ebhsgit commented Jul 6, 2021

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):

  • Device: Samsung S9+, Android emulators
  • OS: Android
  • Browser: Chrome
  • Version: 91.0.4472.120

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
Copy link
Contributor Author

ebhsgit commented Jul 6, 2021

My hack for the issue can be found here:

ebhsgit@d9dd666


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 roman-rr self-assigned this Jul 6, 2021
@roman-rr
Copy link
Collaborator

roman-rr commented Jul 6, 2021

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
Copy link
Contributor Author

ebhsgit commented Jul 6, 2021

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
Copy link
Contributor Author

ebhsgit commented Jul 6, 2021

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
Copy link
Collaborator

roman-rr commented Jul 9, 2021

@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
Copy link
Contributor Author

ebhsgit commented Jul 13, 2021

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).

  • Load the pane after Google map plugin load completes.
  • Prevent app user from dragging the pane until Google map plugin load completes.
  • Apply my code fix to cupertino-pane codebase (Not a guaranteed fix ATM, because we don't know the cause and why the last touch event is registered, but not the ones while the pane is being dragged).

@ebhsgit
Copy link
Contributor Author

ebhsgit commented Jul 13, 2021

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
Copy link
Collaborator

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

@ebhsgit
Copy link
Contributor Author

ebhsgit commented Jul 13, 2021

Let me know if I can be any help :)

@roman-rr
Copy link
Collaborator

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
Copy link
Contributor Author

ebhsgit commented Jul 19, 2021

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
Copy link
Collaborator

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
Copy link
Contributor Author

ebhsgit commented Aug 23, 2021

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
Copy link
Contributor Author

ebhsgit commented Aug 23, 2021

Another video captured using my phone recording the laptop screen.

20210823_162013_1.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 roman-rr changed the title [BUG] When used in conjunction with Cordova GoogleMapsPlugin, content with hide-on-bottom remains hidden, when the pane is dragged up to open show content during first GoogleMap.create() [BUG] Android: Fast drag with single frame not trigger checkOpacityAttr() Oct 28, 2021
@roman-rr
Copy link
Collaborator

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants