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

[Chrome] MediaObserver asObservable() emit wrong events on breakpoints #1059

Open
eprevot opened this issue May 9, 2019 · 9 comments
Open
Assignees
Labels
blocked bug in-progress P0 Critical issue that needs to be resolved immediately
Projects

Comments

@eprevot
Copy link

eprevot commented May 9, 2019

Bug Report

What is the expected behavior?

When I resize the screen from 959px to 960px, MediaObserver.asObservable() should emit a MediaChange event with mqAlias="md"

What is the current behavior?

When I resize the screen from 959px to 960px, MediaObserver.asObservable() emits (among others) 2 MediaChange events with mqAlias="md" and mqAlias="sm"

What are the steps to reproduce?

A component with

public ngOnInit() {
    this.watcher = this.mediaObserver.asObservable()
      .subscribe((changes: MediaChange[]) => {
        console.log(changes)
      })
}

What is the use-case or motivation for changing an existing behavior?

When I resize slowly, MediaObserver.media$ does not always emit an event when breakpoints are crossed. I think it may be related.

Is there anything else we should know?

It may be related to the recent changes about the breakpoints (i.e. max-width: 959.99 instead of 959)
fxLayout version: 7.0.0-beta.24

@PapaNappa
Copy link

Same here.

This is my code

mediaObserver.asObservable().subscribe(changes => {
  console.log(changes.map(c => c.mqAlias));
});

In Chrome, when I resize fast (from lg to md and back), I get the following outputs

(5) ["lg", "lt-xl", "gt-md", "gt-sm", "gt-xs"] # after page load
(5) ["md", "lt-lg", "lt-xl", "gt-sm", "gt-xs"] # after making window smaller
(5) ["md", "lt-lg", "lt-xl", "gt-sm", "gt-xs"] # same event at the same time
(5) ["lg", "lt-xl", "gt-md", "gt-sm", "gt-xs"] # after making window larger
(5) ["lg", "lt-xl", "gt-md", "gt-sm", "gt-xs"] # same event at the same time

This is expected (except that all events are emitted twice).

When resizing slowly, I get the following outputs

(5) ["lg", "lt-xl", "gt-md", "gt-sm", "gt-xs"] # after page load
(7) ["md", "lt-lg", "lg", "lt-xl", "gt-md", "gt-sm", "gt-xs"] # after making window smaller
(7) ["md", "lt-lg", "lg", "lt-xl", "gt-md", "gt-sm", "gt-xs"] # same event at the same time
(7) ["md", "lt-lg", "lg", "lt-xl", "gt-md", "gt-sm", "gt-xs"] # after making window larger
(7) ["md", "lt-lg", "lg", "lt-xl", "gt-md", "gt-sm", "gt-xs"] # same event at the same time

As you can see, both "md" and "lg" are reported.

In Firefox, things get even weirder:

Array(5) [ "lg", "lt-xl", "gt-md", "gt-sm", "gt-xs" ] # after page load
Array(4) [ "lt-lg", "lt-xl", "gt-sm", "gt-xs" ] # after making window smaller
Array(5) [ "md", "lt-lg", "lt-xl", "gt-sm", "gt-xs" ] # second yet different event at the same time
Array(6) [ "md", "lt-lg", "lt-xl", "gt-md", "gt-sm", "gt-xs" ] # after making window larger
Array(7) [ "md", "lt-lg", "lg", "lt-xl", "gt-md", "gt-sm", "gt-xs" ] # second yet different event at the same time

First, when making the window smaller, no 'single' mqAlias is reported, but only ranges. In contrast to the initial result, the "lg" and "gt-md" aliases are removed, but only the "lt-lg" alias is added. I would expect that also the "md" alias is added.

Then right after the first event, a second event gets fired with the correct "md" alias added.

When making the window larger, the "gt-md" alias is added, but not the "lg" alias. The "md" alias is not removed. I would expect that "md" would also be removed and "lg" would be added.

Then right after the first event, a second event gets fired with the "lg" alias added, but the "md" alias is still not removed.

@Londovir
Copy link

Londovir commented Jun 6, 2019

I can perhaps see why you would potentially get two aliases (md and lg) in a single report after reading the comments made in the related commit/issue where this change was implemented (not that I agree with this breaking change at all, but that's a different thought process unrelated to this issue here).

However, that said, what you are reporting for this bug does seem like it contradicts the note in the comments that this MediaChange[] emission would be sorted in priority of the aliases; if the intent is for the return packet to include all aliases involved in the change, a shrinking of the window which crosses from lg over to md would make sense to lead off with ["lg", "lt-xl", "gt-md", "gt-sm", "gt-xs", ...] before then listing ["md", "lt-lg", "lt-xl", ...]. At least in that instance, if you parse the returned array and look for the first "non-comparative" alias you encounter (which would be "lg"), you would "know" in your code which sizing breakpoint the window is currently "in".

As it stands, though, it's wrong. In your Chrome example at the end, my logic would try to tell me the window is still in "md", even though it is in "lg" mode at that point. It is almost as though the act of slowly dragging the window locks the MediaChange[] result into the first alias it determines, and then it will doggedly report that until you release the drag operation.

@paulotokimatu
Copy link

I am having a similar issue, I am just posting here to help a bit with videos and stackblitz of the problem:

On Firefox, when I am on XS screen size and change the width of my screen to be more than 600px, a MediaQuery with an alias of SM should be emitted. But what actually happens on Firefox is that I receive a XS MediaQuery.

This also happens when changing other screen sizes, for example, from SM to MD.

Check the stackblitz here:
https://stackblitz.com/edit/angular-flex-layout-seed-a9w5hl

https://imgur.com/vEgsTAW


Also, there is another issue that happens in Chrome and Safari too:

If you resize slowly the screen, it is possible that both XS and SM MediaQuery will be activated. If you resize at normal speed, then it works as intended:

https://imgur.com/DzjVm8B

paulotokimatu pushed a commit to paulotokimatu/flex-layout that referenced this issue Aug 19, 2019
MediaObserver was showing an inconsistent behavior of the public `asObservable` method, emitting incorrect MediaChange events. For example, it was possible to receive both `sm` and `md` events at the same time as you resize your screen.

Related to angular#1059
@nilsmehlhorn
Copy link

nilsmehlhorn commented Sep 30, 2019

As a workaround you might use the BreakpointObserver from Angular CDK.

@AsafAgranat
Copy link

Since this hasn't been fixed yet, this can be circumvented with the distinctUntilChanged operator. It'll compare between previous and current breakpoint alias, and prevent the emission if identical:

this.mediaObserver.asObservable()
 .pipe(
   distinctUntilChanged((prev, curr) => prev[0].mqAlias === curr[0].mqAlias),
   map((arr: MediaChange[]) => arr.map((change: MediaChange) => change.mqAlias)),
 )

https://stackblitz.com/edit/flex-layout-mediaobserver-deduped

@CaerusKaru
Copy link
Member

It is quite honestly ridiculous how annoying this issue is. For those who have been suffering in silence, I feel for you on this. There is some sort of issue with how the media queries are getting fired. The underlying infrastructure is working flawlessly, especially since #1377 was merged. But the issue of events not firing when they should be is perplexing, because in theory everything is in place and should just work. I'll keep digging on this, and hopefully come back with better news.

@CaerusKaru CaerusKaru added P0 Critical issue that needs to be resolved immediately bug in-progress labels Dec 23, 2021
@CaerusKaru CaerusKaru self-assigned this Dec 23, 2021
@CaerusKaru CaerusKaru added this to Pending in API Fixes via automation Dec 23, 2021
@CaerusKaru CaerusKaru added this to the 13.0.0-beta.37 milestone Dec 23, 2021
@CaerusKaru
Copy link
Member

So this looks like a browser issue, and one that I'm not sure we'll be able to get patched at a higher level. In Chrome (haven't found the Firefox one yet), this is/was explained in this comment. Essentially, Chrome is suppressing quick changes in display, with a very wonky definition for "quick". This leaves Flex Layout applications and users in a lurch though, because we depend on these events reliably firing for every change, no matter how quick.

I'm currently researching/discussing with team members some possible mitigations for this, because there has to be something we can do in the meantime.

@CaerusKaru
Copy link
Member

At least on Mac, I've confirmed this isn't an issue with latest Firefox and Safari releases. Can anyone second/refute this? If so, it may be easier to get this patched in Chromium.

@CaerusKaru CaerusKaru pinned this issue Dec 29, 2021
@CaerusKaru CaerusKaru changed the title MediaObserver asObservable() emit wrong events on breakpoints [Chrome] MediaObserver asObservable() emit wrong events on breakpoints Dec 29, 2021
@CaerusKaru
Copy link
Member

I've filed a ticket with the Chromium team, and they've identified the root cause and assigned priority to the case, which hopefully means we can get this addressed in one of the next major versions.

Tracking: https://bugs.chromium.org/p/chromium/issues/detail?id=1285532 (please do not spam the ticket)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked bug in-progress P0 Critical issue that needs to be resolved immediately
Projects
API Fixes
  
Pending
Development

No branches or pull requests

7 participants