Swipe Back Nav Flicker (iOS PWA)

I am currently facing an issue where the swipe to go back functionality flickers/flashes back to the “from page” (home page in this example) after the gesture before finally going back to the “to page” (restaurant page in this example). This is happening intermittently, and usually doesn’t happen if you swipe back slowly (not sure if thats just a coincidence). I’ve included some code, my project info, and a video of the broken animation. Any ideas why this is happening?

home.page.html Router Link
<a routerLink="/restaurant/abc/123"><ion-button color="primary">Valid Restaurant</ion-button></a>

app-routing.module.ts Routes

const routes: Routes = [
  {
    path: 'login',
    loadChildren: () => import('./pages/login/login.module').then( m => m.LoginPageModule)
  },
  {
    path: 'create-restaurant-menu',
    loadChildren: () => import('./pages/create-restaurant-menu/create-restaurant-menu.module').then( m => m.CreateRestaurantMenuPageModule)
  },
  {
    path: 'create-restaurant-menu/:restaurantId',
    loadChildren: () => import('./pages/create-restaurant-menu/create-restaurant-menu.module').then( m => m.CreateRestaurantMenuPageModule)
  },
  {
    path: 'create-restaurant-account',
    loadChildren: () => import('./pages/create-restaurant-account/create-restaurant-account.module').then( m => m.CreateRestaurantAccountPageModule)
  },
  {
    path: 'home',
    loadChildren: () => import('./pages/home/home.module').then( m => m.HomePageModule)
  },
  {
    path: 'restaurant/:restaurantId/:tableId',
    loadChildren: () => import('./pages/restaurant/restaurant.module').then( m => m.RestaurantPageModule)
  },
  {
    path: '',
    redirectTo: 'home',
    pathMatch: 'full'
  },
];

Ionic Info

Ionic:

   Ionic CLI                     : 6.12.1 (/Users/tylerpashigian/.nvm/versions/node/v12.18.4/lib/node_modules/@ionic/cli)
   Ionic Framework               : @ionic/angular 5.3.5
   @angular-devkit/build-angular : 0.1000.8
   @angular-devkit/schematics    : 10.0.8
   @angular/cli                  : 10.0.8
   @ionic/angular-toolkit        : 2.3.3

Utility:

   cordova-res (update available: 0.15.3) : 0.15.1
   native-run (update available: 1.4.0)   : 0.3.0

System:

   NodeJS : v12.18.4 (/Users/tylerpashigian/.nvm/versions/node/v12.18.4/bin/node)
   npm    : 6.14.6
   OS     : macOS Big Sur

Video - I wasn’t able to attach a video so I created a link to the video stored on Google Drive

There are 2 issues I can see in the video provided:

  1. There is jank when the page shown in the video is entering. I am assuming you are performing some work in ionViewWillEnter that causes your template to re-render. This triggers a bug in WebKit. The good news is that the issue was fixed by Apple and should be released in an upcoming version of iOS. The workaround for now is to move the logic to ionViewDidEnter (or avoid it altogether).

  2. Swiping back appears to happen twice. What’s happening here is you are triggering the swipe to go back gesture that is built into Safari in addition to the swipe to go back gesture that is built into Ionic. The end result is you “swipe to go back” using the Safari gesture, and then Ionic’s gesture kicks in which results in a visible flicker. There is an open issue here: bug: ios, cannot disable Safari swipe to go back when running as PWA · Issue #22299 · ionic-team/ionic-framework · GitHub. While this is not a bug in Ionic, there is no good workaround at the moment other than disabling Ionic’s swipe to go back gesture. We have proposed an addition to the CSS pointer-events API to help account for this, but there has not been any movement on that front yet.

Thanks for the response!

  1. Ironically, I didn’t notice the first issue until I was recording the video for this post and was planning on digging into it after seeing it. Good news that Apple is planning to fix it…however my logic is currently in ionViewDidEnter. I built a global drawer component and I am reading one of the values from an injected service and setting the state of the drawer based on the value…do you see any reason why that would be causing an issue in ionViewDidEnter?
  2. Does this mean if I disable Ionic’s swipe to go back, it won’t work at all? Or will only work in Safari because Safari’s functionality will still exist? Either way I’ll keep an eye out on that GitHub issue, thanks for sharing that.

Try wrapping the code in ionViewDidEnter in a requestAnimationFrame. That should cause it to run ~1-2 frames after the animation itself finishes.

If you disable Ionic’s swipe to go back, you will still be able to use Safari’s swipe to go back, but it will not look as seamless.

I actually removed all of the code from ionViewDidEnter (and the lifecycle event altogether), and I am still seeing the issue. I do have a few things happening in my ngOnInit, including an async func to pull data from Firebase. Could that be the problem?

Yes, that could be the cause. If the call is async it likely runs during the animation as the animation runs directly after ngOnInit.

Is there a way to fix that issue? What would be the “best practice” to handle those network calls/set up subscriptions if doing them in ngOnInit is causing the flicker/pause effect when loading the view?

Something to note is that it only happens the 2nd time after navigating to the view when the view already has data (assume its cached?). When it loads the first time theres no animation issue, the page is just blank until the data loads.

The main issue is a bug in WebKit that has since been resolved. We are waiting on the fix to ship in an upcoming version of iOS. (See 228954 – REGRESSION (r275756): Accelerated animations freeze when invalidating layout with shadow dom)

The best way to avoid this issue is to ensure that the view does not get updated during the page animation. You could do this by caching or pre-fetching data prior to the animation starting.

1 Like

Awesome, thanks for all your help. I’ll give that a shot.

1 Like