Differences in Server-Driven Routing

Open
#175 3 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
android, kotlin
Domain
mobile-dev

Research direction

Reproduce the modal server-driven routing cases in the demo app, following the listed Basic navigation, Modal navigation, and refresh/resume steps, with and without the JavaScript URL update. Start by tracing the Android routing logic that compares the upcoming URL with startingLocation. Done means refresh, resume, URL preservation, and modal behavior match the documented iOS results without the reported race condition.

Written by the indexing model from the issue text.

Description

Hi there,

We have noticed some differences in behavior between iOS and Android when performing server side routing actions (recede, refresh, resume) from within a modal.
Similar / Related issues: #84, #153

To get an overview of the current situation I've tried to create the tables below.

TL;DR:

  • Android reloads the URL of the modal in the case of a "refresh". Which in some cases can even trigger a race condition where the content of the modal will get shown in fragment of the main stack.
  • Android loses the updated URL after refresh or resume. iOS respects the updated / current WebURL.
  • Android does reload a fragment after a "resume", compared to iOS which does not.

1. Modal -> Direct link to server side routing URLs

Android iOS Identical?
recede 1. Close modal
2. Pop to screenA
3. No refresh on screenA
1. Close modal
2. Pop to screenA
3. No refresh on screenA
recede (with JS URL update) 1. Close modal
2. Pop to screenA
3. No refresh on screenA
1. Close modal
2. Pop to screenA
3. No refresh on screenA
refresh 1. Reload modal 🤷‍♂️
2. Close modal
3. Refresh screenB

⚠️ Race condition: modal content can appear in screenB
1. Close modal
2. Refresh screenB
refresh (with JS URL update) 1. Reload modal 🤷‍♂️
2. Close modal
3. Refresh screenB, and loses updated URL from JS

⚠️ Race condition: modal content can appear in screenB
1. Close modal
2. Refresh screenB WITH updated URL with JS
resume 1. Close modal 1. Close modal
resume (with JS URL update) 1. Close modal 1. Close modal

2. Modal -> Form Submit -> Server side redirect

Android iOS Identical?
recede 1. Close modal
2. Pop to screenA
3. Refresh screenA
1. Close modal
2. Pop to screenA
3. Refresh screenA
recede (with JS URL update) 1. Close modal
2. Pop to screenA
3. Refresh screenA
1. Close modal
2. Pop to screenA
3. Refresh screenA
refresh 1. Reload modal 🤷‍♂️
2. Close modal
3. Refresh screenB

⚠️ Race condition: modal content can appear in screenB
1. Close modal
2. Refresh screenB
refresh (with JS URL update) 1. Reload modal 🤷‍♂️
2. Close modal
3. Refresh screenB, and loses updated URL from JS
1. Close modal
2. Refresh screenB WITH updated URL with JS
resume 1. Close modal
2. Refresh screenB
1. Close modal
resume (with JS URL update) 1. Close modal
2. Refresh screenB, and loses updated URL from JS
1. Close modal

Test Setup:

  • Navigation stack: screenA → screenB
  • Modal opened from screenB
  • Tested with iOS: v1.2.2 / Android: v1.2.4
  • Tested with the demo app and this fork of the demo server. All relevant changes were done in this commit

Reproduction Steps:

  • Open the demo app
  • Navigate with "Basic navigation" link
  • (For JS URL update scenarios) Click "SET param foo" button
  • Navigate with "Modal navigation" link
  • Trigger one of the server-side routing paths

Screen recording of an example test run: (Server side redirect /refresh_historical_location (with JS URL update))
https://github.com/user-attachments/assets/da11a70f-d877-43c0-9ac6-012cd3d92a15

Main questions

  1. Android loses the updated URL after refresh or resume. iOS respects the updated / current WebURL.
  2. Android reloads the URL of the modal in the case of a "refresh". Which in some cases can even trigger a race condition where the content of the modal will get shown in fragment of the main stack.
  3. Android does reload screen 1 after a "resume" redirection of the server. Even though it should not reload anything.

Background:

  • In Hotwire Native Android we check the upcoming URL against the startingLocation. When you update the URL with JS, the startingLocation remains the same. Which explains why the updated URL is lost on refresh / resume.
Dominant language
Kotlin
Stars
163
Forks
37
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from hotwired/hotwire-native-android

All issues in hotwired/hotwire-native-android

Similar issues

More Kotlin issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.