hotwired / turbo-android

Android framework for making Turbo native apps
MIT License
424 stars 50 forks source link

Provide an example of using multiple activities #299

Closed kyrylo closed 7 months ago

kyrylo commented 9 months ago

I can see two slighty contradicting statements in the documentation. The first link heavily discourages me from using multiple activities, but the second one says it's possible and provides guidance.

https://github.com/hotwired/turbo-android/blob/b5ba0325e3a0ab5e87242a53fea5876d1322f4f5/docs/QUICK-START.md?plain=1#L54-L55

https://github.com/hotwired/turbo-android/blob/b5ba0325e3a0ab5e87242a53fea5876d1322f4f5/docs/ADVANCED-OPTIONS.md?plain=1#L96-L99


However, for someone who is new to Android development, the documentation lacks examples.

I am trying to display bottom navigation for my app, everywhere but on certain pages. For example, I want to hide it on the login screen of my app, which is a page served by Rails.

I followed the multiple activities doc, but after annotating them, I got an error:

Caused by: java.lang.IllegalArgumentException:
A start Fragment destination was not found for uri: turbo://activity/login
@TurboNavGraphDestination(uri = "turbo://activity/main")
class MainActivity : AppCompatActivity(), TurboActivity {
@TurboNavGraphDestination(uri = "turbo://activity/login")
class LoginActivity : AppCompatActivity(), TurboActivity {
{
  "patterns": [
    "^/sign_in$",
    "^/sign_up$"
  ],
  "properties": {
    "uri": "turbo://activity/login",
    "pull_to_refresh_enabled": false
  }
},

If my uri is an activity, am I expected to have res/navigation file? Any additional examples are appreciated.

P.S. I have figured out a way to hide the bottom navigation dynamically, inside a fragment, but I am wondering whether the activity approach is cleaner (since I wouldn't need to manage the bottom navigation state).

jayohms commented 7 months ago

@kyrylo my guess is that the Activity is not registered in your TurboSessionNavHostFragment.registeredActivities.

I would recommend against using multiple Activity instances at this point. It represents an architecture that Android has been moving away from for a long time. In fact, turbo-android may drop explicit support eventually. That being said, an app can always create and finish() its own Activity instances and within each Activity, you can have a Turbo nav graph.

I'd recommend leveraging your path configuration file and using a custom property to determine when to show/hide your bottom tabs. It'd look like something like this:

{
  "rules": [
    {
      "patterns": [
        ".*"
      ],
      "properties": {
        "context": "default",
        "presentation": "default",
        "uri": "turbo://fragment/web",
        "pull_to_refresh_enabled": true,
        "displays_bottom_tabs": true
      }
    },
    {
      "patterns": [
        "^/sign_in$",
        "^/sign_up$"
      ],
      "properties": {
        "uri": "turbo://fragment/login",
        "pull_to_refresh_enabled": false,
        "displays_bottom_tabs": false
      }
    }
  ]
}

You can create your own extension function to easily read this from any fragment destination:

// Extension function
val TurboPathConfigurationProperties.displayBottomTabs: Boolean
    get() = get("displays_bottom_tabs")?.toBoolean() ?: false

// Use
if (pathProperties.displayBottomTabs) {
  // Display bottom tabs
} else {
  // Hide bottom tabs
}