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

Users report frozen screens #88

Open
michaelloistl opened this issue Feb 20, 2025 · 8 comments
Open

Users report frozen screens #88

michaelloistl opened this issue Feb 20, 2025 · 8 comments

Comments

@michaelloistl
Copy link

After some investigation, it turned out that the screenshot is being shown which creates for the user the impression that the screen is frozen. I have not been able to recreate this issue myself, but got countless reports from users. I distributed a TestFlight build with color coded screen borders for all the functions that call showVisitableScreenshot(). Based on the color reported back from users, the following function would cause that frozen screen for them:

private func deactivateVisitable(_ visitable: Visitable, showScreenshot: Bool = false) {
  guard isActivatedVisitable(visitable) else { return }

  if showScreenshot {
    visitable.updateVisitableScreenshot()
    visitable.showVisitableScreenshot()

    // Color red added for test purposes
    visitable.visitableView.layer.borderWidth = 5
    visitable.visitableView.layer.borderColor = UIColor.red.cgColor
  }

  visitable.deactivateVisitableWebView()
  activatedVisitable = nil
}

The following screen recording shows when that happens to the user. We have however received reports that this happens across all of the tabs, so it's not unique to that scenario where a user comments on a post and returns to the feed.

ScreenRecording_02-20-2025.09-13-34_1_.mp4
@joemasilotti
Copy link
Member

Thanks for reporting. After some poking around I can reproduce with the new version of the demo server that uses tabs on iOS.

RocketSim_Recording_iPhone_16_Pro_6.3_2025-02-20_05.41.12.mp4

The freeze can be reproduced by:

  1. Submitting a form
  2. Switching to a different tab
  3. Switching back to the original tab
  4. Tapping the tab button (again) to pop to root

Not 100% of the time, though. So I'm wondering if there is a race condition occurring somewhere.

If I had to guess, this might be related to #50 by @svara. Only because that's the only custom code we have in place around tabs and such. There's also a high possibility the way I'm setting up tabs in #87 is causing the issue.

@michaelloistl
Copy link
Author

@joemasilotti as this is really urgent (having frustrated users & client), has there been any progress in fixing this issue or a suggestion for a hotfix?

@joemasilotti
Copy link
Member

Digging in some more, it looks like the guard statement in the code you mentioned is incorrectly returning false when switching between tabs (sometimes). I'll post more information as I uncover it.

private func deactivateVisitable(_ visitable: Visitable, showScreenshot: Bool = false) {
  guard isActivatedVisitable(visitable) else { return } // HERE!

@joemasilotti
Copy link
Member

OK, getting closer (maybe?)!

When the highlighted line below sees .tabSelected it doesn't call the delegate function on the following line. This means the screenshot is never removed and the web view appears frozen.

open class VisitableViewController: UIViewController, Visitable {
    override open func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if appearReason == .tabSelected { return } // HERE!
        visitableDelegate?.visitableViewWillAppear(self)
    }
}

appearReason is correctly set (most of the time) to .pushedOntoNavigationStack. The only place this is set is in:

open class HotwireNavigationController: UINavigationController {
    open override func viewWillAppear(_ animated: Bool) {
        if let topVisitableViewController = topViewController as? VisitableViewController,
           topVisitableViewController.disappearReason == .tabDeselected {
            topVisitableViewController.appearReason = .tabSelected // HERE!
        }
        super.viewWillAppear(animated)
    }
}

I'm thinking this is caused by either:

  • missing some custom handling for modals presenting/dismissing.
  • a race condition with which navigation controller (main or modal) receives the lifecycle methods.

@joemasilotti
Copy link
Member

joemasilotti commented Feb 27, 2025

@michaelloistl, can you try PR #91 and see if that fixes the issue?

@michaelloistl
Copy link
Author

Thank you @joemasilotti, I've shared a new TestFlight build to our testers and so far nobody got the freezing screen experience, so 🤞.

@joemasilotti
Copy link
Member

OK, that's a good start! Let me know if anything pops up over the next few days. If not, we can bring in the team for a review.

@michaelloistl
Copy link
Author

michaelloistl commented Mar 7, 2025

@joemasilotti since the PR#91 fix there have been no screen freezes, so looks like that can go into team review 👍

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

No branches or pull requests

2 participants