-
Notifications
You must be signed in to change notification settings - Fork 88
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
Turbo visit with replace action flashes elements #136
Comments
it's because it's trying to show the loading icon as it changes to a whole new web view. It's not possible to easily get it to behave like it does in safari since the first thing it does is disable the normal Turbo page behaviour. |
@jayohms @joemasilotti @afcapel @jorgemanrubia What kind of support could the community provide to move this forward? To give some more background, we're in the process of upgrading an application's web-side Turbo dependency from 7 to 8. A large portion of Turbo 8's value proposition hinges on "replace" Turbo Action navigations (for example, to integrate with Morphing). The white flashing offsets any interactivity gained from Morphing and draws attention to the hybrid nature of the application. We've found that #155 might help here. Are there other explorations into resolving this issue that could use some more testing help? |
@seanpdoyle we fixed a similar issue with #160 and hotwired/turbo-android#292. Is this one different to those? |
On a related note, I've found that Turbo Native doesn't differentiate between replace actions triggered by navigation (eg. a tap on a button or pull-to-refresh) and replace actions triggered programatically, eg. Turbo Stream. Combined with the fact that Turbo iOS shows a spinner if there's no snapshot cache and that Turbo web exempts a page-to-be-refreshed from snapshot cache: refresh(url, requestId) {
const isRecentRequest = requestId && this.recentRequests.has(requestId)
if (!isRecentRequest) {
this.cache.exemptPageFromPreview()
this.visit(url, { action: "replace" })
}
} .. this means that any MorphingShowingSpinners.mp4I think a stream-triggered refresh should not show any blocking spinners, but I haven't found a good way to skip spinners as there's no differentiation today. I've opened a PR to add a We'll be happy to help with a PR for the native libraries that would support a better logic around showing activity indicators for replace actions if this could be a way forward? |
As a less invasive workaround, I've opened hotwired/turbo#1188 which stores a snapshot of the page before doing a refresh. This at least removes any blocking loading indicators while refreshing, but the visitable views is still disabled during the refresh action (ie. a screenshot is shown instead of the WebView, while the refresh is on-going): TurboReplaceMorphing.movI still believe that the native adapters would need the granularity that an explicit |
@pfeiffer I'm going to look at this closer next week so we can get this issue over the finish line.
Do you see a visit proposal the iOS library when a Turbo Stream replace action is triggered? I don't believe we need a separate Are you able to see if the |
@jayohms I'm really happy to hear that!
Yeah, both visit proposal and visit delegate methods are received on the native side. The latter is especially important as it makes it hard to bypass the native adapter flow. Eg. even if we skip proposing a refresh to the native side, the spinners will still be shown as delegate methods are called during the visit lifecycle ( As an example, trying to short-circuit any visit proposals to the native adapters on refresh actions like this will still show spinners: // turbo.js
visitProposedToLocation(location, options) {
// Bypass proposals to native
if (new URL(location).pathname === document.location.pathname && options.action === "replace") {
Turbo.navigator.startVisit(location, "", { "action": "replace" })
}
...
} On the native side, we can see that the visit lifecycle methods being called:
The lifecycle methods on the native side are responsible for showing the indicators etc., so in this case - even when trying to bypass the native adapter proposal - indicators are still shown. The culprint for showing indicators is in func visitDidStart(_ visit: Visit) {
guard !visit.hasCachedSnapshot else { return }
visit.visitable.showVisitableActivityIndicator()
} So here we'd could skip calling |
I've opened a PR in the Turbo Native demo server repo bumping Turbo to version 8 and adding buttons to simulate a Turbo Stream refresh: hotwired/turbo-native-demo#30. |
I wonder if adding a delay to showing the spinner could help. Even something very small, like 10ms. |
#178 resolves flickering issues with same-page |
In local development (isolating slow network), the app is smooth between Turbo replace visits in Safari and Chrome. However, on the simulator and actual hardware, there's a flash during the rendering.
Simulator.Screen.Recording.-.iPhone.14.Pro.-.2023-08-10.at.18.15.45.mp4
I was able to reproduce this using the turbo-native-demo app with an additional link to make the flash more obvious.
Another example from my app which has more elements (it's still smooth from safari / chrome)
Simulator.Screen.Recording.-.iPhone.14.Pro.-.2023-08-10.at.17.56.00.mp4
https://jch.app/demo for live link for comparison
The text was updated successfully, but these errors were encountered: