turbo-native-initializer 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -1
  3. data/README.md +23 -2
  4. data/lib/turbo_native_initializer/generator.rb +11 -39
  5. data/lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/base/NavDestination.kt.tt +0 -4
  6. data/lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/features/native/NativeFragment.kt.tt +25 -0
  7. data/lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/features/native/NumbersFragment.kt.tt +40 -0
  8. data/lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/features/web/WebFragment.kt.tt +0 -19
  9. data/lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/main/MainSessionNavHostFragment.kt.tt +2 -1
  10. data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/build.gradle.kts.tt +16 -3
  11. data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/assets/json/configuration.json +2 -1
  12. data/lib/turbo_native_initializer/templates/android_stack/base/app/src/main/res/layout/fragment_native.xml +36 -0
  13. data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/base/NavDestination.kt.tt +0 -4
  14. data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/features/native/NativeFragment.kt.tt +25 -0
  15. data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/features/native/NumbersFragment.kt.tt +40 -0
  16. data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/features/web/WebFragment.kt.tt +1 -22
  17. data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/main/BaseSessionNavHostFragment.kt.tt +32 -0
  18. data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/main/MainActivity.kt.tt +8 -5
  19. data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/main/TabOneSessionNavHostFragment.kt.tt +2 -30
  20. data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/main/TabTwoSessionNavHostFragment.kt.tt +2 -30
  21. data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/build.gradle.kts.tt +16 -3
  22. data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/assets/json/configuration.json +2 -1
  23. data/lib/turbo_native_initializer/templates/android_tabs/base/app/src/main/res/layout/fragment_native.xml +36 -0
  24. data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Configuration/path-configuration.json +2 -1
  25. data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Controllers/NumbersViewController.swift +31 -0
  26. data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Controllers/TurboNavigationController.swift +1 -1
  27. data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Delegates/AppDelegate.swift +1 -5
  28. data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Delegates/SceneDelegate.swift.tt +1 -1
  29. data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject.xcodeproj/project.pbxproj.tt +4 -0
  30. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Configuration/path-configuration.json +2 -1
  31. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Controllers/NumbersViewController.swift +31 -0
  32. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Controllers/TurboNavigationController.swift +2 -2
  33. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Delegates/AppDelegate.swift +1 -5
  34. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Delegates/SceneDelegate.swift.tt +10 -9
  35. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Resources/Base.lproj/Main.storyboard +2 -2
  36. data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject.xcodeproj/project.pbxproj.tt +4 -0
  37. data/lib/turbo_native_initializer/version.rb +1 -1
  38. metadata +80 -75
  39. data/lib/turbo_native_initializer/templates/android_stack/app/src/main/res/layout/toolbar_progress.xml +0 -13
  40. data/lib/turbo_native_initializer/templates/android_stack/app/src/main/res/menu/web.xml +0 -14
  41. data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/res/layout/toolbar_progress.xml +0 -13
  42. data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/res/menu/web.xml +0 -14
  43. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/.gitignore +0 -0
  44. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/proguard-rules.pro +0 -0
  45. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/debug/AndroidManifest.xml.tt +0 -0
  46. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/AndroidManifest.xml.tt +0 -0
  47. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/anim/nav_slide_enter.xml +0 -0
  48. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/anim/nav_slide_exit.xml +0 -0
  49. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/anim/nav_slide_pop_enter.xml +0 -0
  50. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/anim/nav_slide_pop_exit.xml +0 -0
  51. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/anim/overshoot_interpolator.xml +0 -0
  52. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/drawable/ic_close.xml +0 -0
  53. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/drawable/ic_launcher_foreground.xml +0 -0
  54. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/layout/activity_main.xml.tt +0 -0
  55. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/layout/fragment_web_home.xml +0 -0
  56. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +0 -0
  57. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +0 -0
  58. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  59. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  60. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  61. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  62. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  63. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  64. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/values/colors.xml +0 -0
  65. /data/lib/turbo_native_initializer/templates/android_stack/{app → base/app}/src/main/res/values/themes.xml.tt +0 -0
  66. /data/lib/turbo_native_initializer/templates/android_stack/{build.gradle.kts → base/build.gradle.kts} +0 -0
  67. /data/lib/turbo_native_initializer/templates/android_stack/{gradle → base/gradle}/wrapper/gradle-wrapper.jar +0 -0
  68. /data/lib/turbo_native_initializer/templates/android_stack/{gradle → base/gradle}/wrapper/gradle-wrapper.properties +0 -0
  69. /data/lib/turbo_native_initializer/templates/android_stack/{gradle.properties → base/gradle.properties} +0 -0
  70. /data/lib/turbo_native_initializer/templates/android_stack/{gradlew → base/gradlew} +0 -0
  71. /data/lib/turbo_native_initializer/templates/android_stack/{gradlew.bat → base/gradlew.bat} +0 -0
  72. /data/lib/turbo_native_initializer/templates/android_stack/{local.properties → base/local.properties} +0 -0
  73. /data/lib/turbo_native_initializer/templates/android_stack/{settings.gradle.kts.tt → base/settings.gradle.kts.tt} +0 -0
  74. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/.gitignore +0 -0
  75. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/proguard-rules.pro +0 -0
  76. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/debug/AndroidManifest.xml.tt +0 -0
  77. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/AndroidManifest.xml.tt +0 -0
  78. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/anim/nav_slide_enter.xml +0 -0
  79. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/anim/nav_slide_exit.xml +0 -0
  80. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/anim/nav_slide_pop_enter.xml +0 -0
  81. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/anim/nav_slide_pop_exit.xml +0 -0
  82. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/anim/overshoot_interpolator.xml +0 -0
  83. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/drawable/ic_close.xml +0 -0
  84. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/drawable/ic_home.xml +0 -0
  85. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/drawable/ic_launcher_foreground.xml +0 -0
  86. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/drawable/ic_settings.xml +0 -0
  87. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/layout/activity_main.xml.tt +0 -0
  88. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/layout/fragment_web_home.xml +0 -0
  89. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/menu/bottom_navigation_menu.xml +0 -0
  90. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +0 -0
  91. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +0 -0
  92. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  93. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  94. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  95. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  96. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  97. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  98. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/values/colors.xml +0 -0
  99. /data/lib/turbo_native_initializer/templates/android_tabs/{app → base/app}/src/main/res/values/themes.xml.tt +0 -0
  100. /data/lib/turbo_native_initializer/templates/android_tabs/{build.gradle.kts → base/build.gradle.kts} +0 -0
  101. /data/lib/turbo_native_initializer/templates/android_tabs/{gradle → base/gradle}/wrapper/gradle-wrapper.jar +0 -0
  102. /data/lib/turbo_native_initializer/templates/android_tabs/{gradle → base/gradle}/wrapper/gradle-wrapper.properties +0 -0
  103. /data/lib/turbo_native_initializer/templates/android_tabs/{gradle.properties → base/gradle.properties} +0 -0
  104. /data/lib/turbo_native_initializer/templates/android_tabs/{gradlew → base/gradlew} +0 -0
  105. /data/lib/turbo_native_initializer/templates/android_tabs/{gradlew.bat → base/gradlew.bat} +0 -0
  106. /data/lib/turbo_native_initializer/templates/android_tabs/{local.properties → base/local.properties} +0 -0
  107. /data/lib/turbo_native_initializer/templates/android_tabs/{settings.gradle.kts.tt → base/settings.gradle.kts.tt} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf0fb14c659e3a981d1174b378d7a064f6cba913476b82413bd32f5f41448248
4
- data.tar.gz: 2e1bf6f4f9f54b1a11ea72d1bf69a21e1793632c2502da9218fee889d15b9efb
3
+ metadata.gz: 87f651e0de673db040c8ed9f369d404b8f08946654c721329d07bfd9cbbc0149
4
+ data.tar.gz: ec47793c2bf2370f5cd4390bcf45a8ef14bad81ff70f0f3c4ba6cb1d3bb8c980
5
5
  SHA512:
6
- metadata.gz: f559f58710faa8aff5a7dc6fe4c331dfb77ae08e8f7b9dac937d8f94781839c409d2ebca00255e41e45daf71a01fac95282eccd7734fe7dd7b9b69280d9d07c3
7
- data.tar.gz: 4d4dbc4750b58104185d6527b131f69f35b978ced92b72171815406d9eb76d66cae8ead57bd5d02eb5fe25c7144e62f61cbbbee5ec450ad0f1202a25196fd734
6
+ metadata.gz: 40079d2dc7c716940cf72a536304801180f62c509a8d64e6bf7bcdd4cf4f5179f52b1e2213f57ac7e9fb4e1865c02a45f8ba8e123813fbff92e3f541090909a8
7
+ data.tar.gz: 0bebf193304c04ed0ddaa53340fb4d0c9f4d46209471f18f883a9e0df83ec8038b2a16544372d2b704d421119519552b01c0641cd0f82181615287db906724e0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.0] - 2023-08-23
3
+ ## [0.0.3] - 2023-09-08
4
+
5
+ - Add a Swift UI native screen
6
+ - Add a jetpack compose screen
7
+ - Fix android package
8
+
9
+ ## [0.0.2] - 2023-09-07
10
+
11
+ - Fix android tab navigation
12
+ - General cleanup
13
+
14
+ ## [0.0.1] - 2023-09-06
4
15
 
5
16
  - Initial release
data/README.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  A turbo native project generator for iOS and Android.
4
4
 
5
+ ## Differences when compared to the demos
6
+
7
+ - Added SwiftUI error screen. (iOS)
8
+ - Added SwiftUI numbers screen. (iOS)
9
+ - Added Jetpack Compose numbers screen. (Android)
10
+ - Added UIAlertController to handle `turbo-native-confirm`. (iOS)
11
+ - Added presentations `clear-all`, `replace-all`, `replace`, `pop`, `refresh`, and `none`. (iOS)
12
+ - Added visitable property in order to avoid visits. (iOS)
13
+ - Added full screen option to modals. (iOS/Android)
14
+ - Added support for tab navigation. (iOS/Android)
15
+
5
16
  ## Installation
6
17
 
7
18
  ```
@@ -28,10 +39,20 @@ $ cd AwesomeProject
28
39
  $ studio .
29
40
  ```
30
41
 
31
- For more options check --help.
42
+ ## Usage
32
43
 
33
44
  ```
34
- $ turbo-native-initializer --help
45
+ Usage:
46
+ turbo-native-initializer NAME --platform=PLATFORM
47
+
48
+ Options:
49
+ --platform=PLATFORM
50
+ # Possible values: ios, android
51
+ [--navigation=NAVIGATION]
52
+ # Default: stack
53
+ # Possible values: stack, tabs
54
+ [--package=PACKAGE]
55
+ # Default: dev.hotwire.turbo
35
56
  ```
36
57
 
37
58
  ## Development
@@ -18,60 +18,32 @@ module TurboNativeInitializer
18
18
 
19
19
  def copy_template_files
20
20
  case options.platform
21
- when "android"
22
- copy_android_files
23
21
  when "ios"
24
- copy_ios_files
25
- end
26
- end
27
-
28
- private
29
- def project
30
- "#{options[:platform]}_#{options[:navigation]}"
31
- end
32
-
33
- def copy_ios_files
34
- # project/TurboNativeProject
35
22
  directory "#{project}/TurboNativeProject/Configuration", "#{name}/#{name}/Configuration"
36
23
  directory "#{project}/TurboNativeProject/Controllers", "#{name}/#{name}/Controllers"
37
24
  directory "#{project}/TurboNativeProject/Delegates", "#{name}/#{name}/Delegates"
38
25
  directory "#{project}/TurboNativeProject/Resources", "#{name}/#{name}/Resources"
39
- template "#{project}/TurboNativeProject/TurboNativeProject.swift", "#{name}/#{name}/#{name}.swift"
40
- # project
41
26
  directory "#{project}/TurboNativeProject.xcodeproj", "#{name}/#{name}.xcodeproj"
42
- end
43
-
44
- def copy_android_files
45
- # project/app
46
- copy_file "#{project}/app/.gitignore", "#{name}/app/.gitignore"
47
- copy_file "#{project}/app/proguard-rules.pro", "#{name}/app/proguard-rules.pro"
48
- template "#{project}/app/build.gradle.kts", "#{name}/app/build.gradle.kts"
49
- # project/app/src/debug
50
- directory "#{project}/app/src/debug", "#{name}/app/src/debug"
51
- # project/app/src/main
52
- directory "#{project}/app/src/main/assets", "#{name}/app/src/main/assets"
27
+ template "#{project}/TurboNativeProject/TurboNativeProject.swift", "#{name}/#{name}/#{name}.swift"
28
+ when "android"
29
+ directory "#{project}/base", "#{name}"
53
30
  directory "#{project}/app/src/main/java/dev/hotwire/turbo/turbonativeproject", "#{name}/app/src/main/java/#{package_path}"
54
- directory "#{project}/app/src/main/res", "#{name}/app/src/main/res"
55
- template "#{project}/app/src/main/AndroidManifest.xml", "#{name}/app/src/main/AndroidManifest.xml"
56
- # project/gradle
57
- directory "#{project}/gradle", "#{name}/gradle"
58
- # project
59
- copy_file "#{project}/build.gradle.kts", "#{name}/build.gradle.kts"
60
- copy_file "#{project}/gradle.properties", "#{name}/gradle.properties"
61
- copy_file "#{project}/gradlew", "#{name}/gradlew"
62
- copy_file "#{project}/gradlew.bat", "#{name}/gradlew.bat"
63
- copy_file "#{project}/local.properties", "#{name}/local.properties"
64
- template "#{project}/settings.gradle.kts", "#{name}/settings.gradle.kts"
65
31
  end
32
+ end
66
33
 
67
- def package_path
68
- options[:package].split(".").join("/")
34
+ private
35
+ def project
36
+ "#{options[:platform]}_#{options[:navigation]}"
69
37
  end
70
38
 
71
39
  def package_name
72
40
  "#{options[:package]}.#{name.downcase}"
73
41
  end
74
42
 
43
+ def package_path
44
+ package_name.split(".").join("/")
45
+ end
46
+
75
47
  def bundle_identifier
76
48
  "#{options[:package]}.#{name}"
77
49
  end
@@ -1,7 +1,6 @@
1
1
  package <%= package_name %>.base
2
2
 
3
3
  import android.net.Uri
4
- import android.view.MenuItem
5
4
  import androidx.browser.customtabs.CustomTabColorSchemeParams
6
5
  import androidx.browser.customtabs.CustomTabsIntent
7
6
  import androidx.browser.customtabs.CustomTabsIntent.SHARE_STATE_ON
@@ -15,9 +14,6 @@ import dev.hotwire.turbo.nav.TurboNavDestination
15
14
  import dev.hotwire.turbo.nav.TurboNavPresentationContext.MODAL
16
15
 
17
16
  interface NavDestination : TurboNavDestination {
18
- val menuProgress: MenuItem?
19
- get() = toolbarForNavigation()?.menu?.findItem(R.id.menu_progress)
20
-
21
17
  override fun shouldNavigateTo(newLocation: String): Boolean {
22
18
  return when (isNavigable(newLocation)) {
23
19
  true -> true
@@ -0,0 +1,25 @@
1
+ package <%= package_name %>.features.native
2
+
3
+ import android.view.LayoutInflater
4
+ import android.view.View
5
+ import android.view.ViewGroup
6
+ import androidx.compose.runtime.Composable
7
+ import androidx.compose.ui.platform.ComposeView
8
+ import androidx.compose.ui.platform.ViewCompositionStrategy
9
+ import dev.hotwire.turbo.fragments.TurboFragment
10
+ import <%= package_name %>.R
11
+ import <%= package_name %>.base.NavDestination
12
+
13
+ abstract class NativeFragment : TurboFragment(), NavDestination {
14
+ fun setContent(inflater: LayoutInflater, container: ViewGroup?, content: @Composable () -> Unit): View? {
15
+ val root = inflater.inflate(R.layout.fragment_native, container, false)
16
+ val composeView = root.findViewById<ComposeView>(R.id.compose_view)
17
+
18
+ composeView.apply {
19
+ setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
20
+ setContent { content.invoke() }
21
+ }
22
+
23
+ return root
24
+ }
25
+ }
@@ -0,0 +1,40 @@
1
+ package <%= package_name %>.features.native
2
+
3
+ import android.os.Bundle
4
+ import android.view.LayoutInflater
5
+ import android.view.View
6
+ import android.view.ViewGroup
7
+ import androidx.compose.foundation.lazy.LazyColumn
8
+ import androidx.compose.material3.Divider
9
+ import androidx.compose.material3.ListItem
10
+ import androidx.compose.material3.Text
11
+ import dev.hotwire.turbo.nav.TurboNavGraphDestination
12
+ import androidx.compose.runtime.Composable
13
+ import androidx.compose.ui.tooling.preview.Preview
14
+
15
+ @TurboNavGraphDestination(uri = "turbo://fragment/numbers")
16
+ class NumbersFragment : NativeFragment() {
17
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
18
+ return setContent(inflater, container) {
19
+ NumbersList()
20
+ }
21
+ }
22
+ }
23
+
24
+ @Composable
25
+ fun NumbersList() {
26
+ val numbers = 1..100
27
+
28
+ LazyColumn {
29
+ items(numbers.count()) { index ->
30
+ ListItem(headlineContent = { Text("Row number ${index + 1}") })
31
+ Divider()
32
+ }
33
+ }
34
+ }
35
+
36
+ @Preview
37
+ @Composable
38
+ fun PreviewNumbersList() {
39
+ NumbersList()
40
+ }
@@ -1,8 +1,5 @@
1
1
  package <%= package_name %>.features.web
2
2
 
3
- import android.os.Bundle
4
- import android.view.View
5
- import <%= package_name %>.R
6
3
  import <%= package_name %>.base.NavDestination
7
4
  import <%= package_name %>.util.SIGN_IN_URL
8
5
  import dev.hotwire.turbo.fragments.TurboWebFragment
@@ -12,26 +9,10 @@ import dev.hotwire.turbo.visit.TurboVisitOptions
12
9
 
13
10
  @TurboNavGraphDestination(uri = "turbo://fragment/web")
14
11
  open class WebFragment : TurboWebFragment(), NavDestination {
15
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
16
- super.onViewCreated(view, savedInstanceState); setupMenu()
17
- }
18
-
19
- override fun onFormSubmissionStarted(location: String) {
20
- menuProgress?.isVisible = true
21
- }
22
-
23
- override fun onFormSubmissionFinished(location: String) {
24
- menuProgress?.isVisible = false
25
- }
26
-
27
12
  override fun onVisitErrorReceived(location: String, errorCode: Int) {
28
13
  when (errorCode) {
29
14
  401 -> navigate(SIGN_IN_URL, TurboVisitOptions(action = REPLACE))
30
15
  else -> super.onVisitErrorReceived(location, errorCode)
31
16
  }
32
17
  }
33
-
34
- private fun setupMenu() {
35
- toolbarForNavigation()?.inflateMenu(R.menu.web)
36
- }
37
18
  }
@@ -4,6 +4,7 @@ import android.webkit.WebView
4
4
  import androidx.appcompat.app.AppCompatActivity
5
5
  import androidx.fragment.app.Fragment
6
6
  import dev.hotwire.turbo.config.TurboPathConfiguration
7
+ import <%= package_name %>.features.native.NumbersFragment
7
8
  import <%= package_name %>.features.web.WebFragment
8
9
  import <%= package_name %>.features.web.WebHomeFragment
9
10
  import <%= package_name %>.features.web.WebModalFragment
@@ -21,7 +22,7 @@ class MainSessionNavHostFragment : TurboSessionNavHostFragment() {
21
22
  get() = listOf()
22
23
 
23
24
  override val registeredFragments: List<KClass<out Fragment>>
24
- get() = listOf(WebFragment::class, WebHomeFragment::class, WebModalFragment::class)
25
+ get() = listOf(WebFragment::class, WebHomeFragment::class, WebModalFragment::class, NumbersFragment::class)
25
26
 
26
27
  override val pathConfigurationLocation: TurboPathConfiguration.Location
27
28
  get() = TurboPathConfiguration.Location(assetFilePath = "json/configuration.json")
@@ -13,8 +13,6 @@ android {
13
13
  targetSdk = 33
14
14
  versionCode = 1
15
15
  versionName = "1.0"
16
-
17
- testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
18
16
  }
19
17
 
20
18
  buildTypes {
@@ -33,12 +31,27 @@ android {
33
31
  kotlinOptions {
34
32
  jvmTarget = "1.8"
35
33
  }
34
+ buildFeatures {
35
+ compose = true
36
+ }
37
+ composeOptions {
38
+ kotlinCompilerExtensionVersion = "1.5.2"
39
+ }
36
40
  }
37
-
38
41
  dependencies {
42
+ // Android
39
43
  implementation("androidx.core:core-ktx:1.9.0")
40
44
  implementation("androidx.appcompat:appcompat:1.6.1")
41
45
  implementation("androidx.browser:browser:1.5.0")
42
46
  implementation("com.google.android.material:material:1.9.0")
47
+
48
+ // Jetpack Compose
49
+ implementation(platform("androidx.compose:compose-bom:2023.06.01"))
50
+ implementation("androidx.compose.material3:material3")
51
+ implementation("androidx.compose.ui:ui-tooling-preview")
52
+ debugImplementation("androidx.compose.ui:ui-tooling")
53
+ implementation("androidx.activity:activity-compose:1.7.2")
54
+
55
+ // Turbo Android
43
56
  implementation("dev.hotwire:turbo:7.0.0")
44
57
  }
@@ -6,6 +6,7 @@
6
6
  { "patterns": ["/recede_historical_location"], "properties": { "presentation": "pop" } },
7
7
  { "patterns": ["/resume_historical_location"], "properties": { "presentation": "none" } },
8
8
  { "patterns": ["^/$"], "properties": { "uri": "turbo://fragment/web/home", "presentation": "replace_all" } },
9
- { "patterns": ["/new$", "/edit$", "/signin$"], "properties": { "context": "modal", "uri": "turbo://fragment/web/modal" } }
9
+ { "patterns": ["/new$", "/edit$", "/signin$"], "properties": { "context": "modal", "uri": "turbo://fragment/web/modal" } },
10
+ { "patterns": ["/numbers$"], "properties": { "uri": "turbo://fragment/numbers", "title": "Numbers" } }
10
11
  ]
11
12
  }
@@ -0,0 +1,36 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <androidx.constraintlayout.widget.ConstraintLayout
3
+ xmlns:android="http://schemas.android.com/apk/res/android"
4
+ xmlns:app="http://schemas.android.com/apk/res-auto"
5
+ android:layout_width="match_parent"
6
+ android:layout_height="match_parent">
7
+
8
+ <com.google.android.material.appbar.AppBarLayout
9
+ android:id="@+id/app_bar"
10
+ android:layout_width="match_parent"
11
+ android:layout_height="56dp"
12
+ app:layout_constraintEnd_toEndOf="parent"
13
+ app:layout_constraintStart_toStartOf="parent"
14
+ app:layout_constraintTop_toTopOf="parent">
15
+
16
+ <FrameLayout
17
+ android:layout_width="match_parent"
18
+ android:layout_height="match_parent">
19
+
20
+ <com.google.android.material.appbar.MaterialToolbar
21
+ android:id="@+id/toolbar"
22
+ android:layout_width="match_parent"
23
+ android:layout_height="wrap_content" />
24
+
25
+ </FrameLayout>
26
+
27
+ </com.google.android.material.appbar.AppBarLayout>
28
+
29
+ <androidx.compose.ui.platform.ComposeView
30
+ android:id="@+id/compose_view"
31
+ android:layout_width="match_parent"
32
+ android:layout_height="0dp"
33
+ app:layout_constraintBottom_toBottomOf="parent"
34
+ app:layout_constraintTop_toBottomOf="@+id/app_bar" />
35
+
36
+ </androidx.constraintlayout.widget.ConstraintLayout>
@@ -1,7 +1,6 @@
1
1
  package <%= package_name %>.base
2
2
 
3
3
  import android.net.Uri
4
- import android.view.MenuItem
5
4
  import androidx.browser.customtabs.CustomTabColorSchemeParams
6
5
  import androidx.browser.customtabs.CustomTabsIntent
7
6
  import androidx.browser.customtabs.CustomTabsIntent.SHARE_STATE_ON
@@ -15,9 +14,6 @@ import dev.hotwire.turbo.nav.TurboNavDestination
15
14
  import dev.hotwire.turbo.nav.TurboNavPresentationContext.MODAL
16
15
 
17
16
  interface NavDestination : TurboNavDestination {
18
- val menuProgress: MenuItem?
19
- get() = toolbarForNavigation()?.menu?.findItem(R.id.menu_progress)
20
-
21
17
  override fun shouldNavigateTo(newLocation: String): Boolean {
22
18
  return when (isNavigable(newLocation)) {
23
19
  true -> true
@@ -0,0 +1,25 @@
1
+ package <%= package_name %>.features.native
2
+
3
+ import android.view.LayoutInflater
4
+ import android.view.View
5
+ import android.view.ViewGroup
6
+ import androidx.compose.runtime.Composable
7
+ import androidx.compose.ui.platform.ComposeView
8
+ import androidx.compose.ui.platform.ViewCompositionStrategy
9
+ import dev.hotwire.turbo.fragments.TurboFragment
10
+ import <%= package_name %>.R
11
+ import <%= package_name %>.base.NavDestination
12
+
13
+ abstract class NativeFragment : TurboFragment(), NavDestination {
14
+ fun setContent(inflater: LayoutInflater, container: ViewGroup?, content: @Composable () -> Unit): View? {
15
+ val root = inflater.inflate(R.layout.fragment_native, container, false)
16
+ val composeView = root.findViewById<ComposeView>(R.id.compose_view)
17
+
18
+ composeView.apply {
19
+ setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
20
+ setContent { content.invoke() }
21
+ }
22
+
23
+ return root
24
+ }
25
+ }
@@ -0,0 +1,40 @@
1
+ package <%= package_name %>.features.native
2
+
3
+ import android.os.Bundle
4
+ import android.view.LayoutInflater
5
+ import android.view.View
6
+ import android.view.ViewGroup
7
+ import androidx.compose.foundation.lazy.LazyColumn
8
+ import androidx.compose.material3.Divider
9
+ import androidx.compose.material3.ListItem
10
+ import androidx.compose.material3.Text
11
+ import dev.hotwire.turbo.nav.TurboNavGraphDestination
12
+ import androidx.compose.runtime.Composable
13
+ import androidx.compose.ui.tooling.preview.Preview
14
+
15
+ @TurboNavGraphDestination(uri = "turbo://fragment/numbers")
16
+ class NumbersFragment : NativeFragment() {
17
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
18
+ return setContent(inflater, container) {
19
+ NumbersList()
20
+ }
21
+ }
22
+ }
23
+
24
+ @Composable
25
+ fun NumbersList() {
26
+ val numbers = 1..100
27
+
28
+ LazyColumn {
29
+ items(numbers.count()) { index ->
30
+ ListItem(headlineContent = { Text("Row number ${index + 1}") })
31
+ Divider()
32
+ }
33
+ }
34
+ }
35
+
36
+ @Preview
37
+ @Composable
38
+ fun PreviewNumbersList() {
39
+ NumbersList()
40
+ }
@@ -1,29 +1,8 @@
1
1
  package <%= package_name %>.features.web
2
2
 
3
- import android.os.Bundle
4
- import android.view.View
5
- import <%= package_name %>.R
6
3
  import <%= package_name %>.base.NavDestination
7
4
  import dev.hotwire.turbo.fragments.TurboWebFragment
8
5
  import dev.hotwire.turbo.nav.TurboNavGraphDestination
9
- import dev.hotwire.turbo.visit.TurboVisitAction.REPLACE
10
- import dev.hotwire.turbo.visit.TurboVisitOptions
11
6
 
12
7
  @TurboNavGraphDestination(uri = "turbo://fragment/web")
13
- open class WebFragment : TurboWebFragment(), NavDestination {
14
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
15
- super.onViewCreated(view, savedInstanceState); setupMenu()
16
- }
17
-
18
- override fun onFormSubmissionStarted(location: String) {
19
- menuProgress?.isVisible = true
20
- }
21
-
22
- override fun onFormSubmissionFinished(location: String) {
23
- menuProgress?.isVisible = false
24
- }
25
-
26
- private fun setupMenu() {
27
- toolbarForNavigation()?.inflateMenu(R.menu.web)
28
- }
29
- }
8
+ open class WebFragment : TurboWebFragment(), NavDestination
@@ -0,0 +1,32 @@
1
+ package <%= package_name %>.main
2
+
3
+ import android.webkit.WebView
4
+ import androidx.appcompat.app.AppCompatActivity
5
+ import androidx.fragment.app.Fragment
6
+ import dev.hotwire.turbo.config.TurboPathConfiguration
7
+ import <%= package_name %>.features.native.NumbersFragment
8
+ import <%= package_name %>.features.web.WebFragment
9
+ import <%= package_name %>.features.web.WebHomeFragment
10
+ import <%= package_name %>.features.web.WebModalFragment
11
+ import dev.hotwire.turbo.session.TurboSessionNavHostFragment
12
+ import kotlin.reflect.KClass
13
+
14
+ abstract class BaseSessionNavHostFragment : TurboSessionNavHostFragment() {
15
+ override val registeredActivities: List<KClass<out AppCompatActivity>>
16
+ get() = listOf()
17
+
18
+ override val registeredFragments: List<KClass<out Fragment>>
19
+ get() = listOf(WebFragment::class, WebHomeFragment::class, WebModalFragment::class, NumbersFragment::class)
20
+
21
+ override val pathConfigurationLocation: TurboPathConfiguration.Location
22
+ get() = TurboPathConfiguration.Location(assetFilePath = "json/configuration.json")
23
+
24
+ override fun onSessionCreated() {
25
+ super.onSessionCreated()
26
+ session.webView.settings.userAgentString = customUserAgent(session.webView)
27
+ }
28
+
29
+ private fun customUserAgent(webView: WebView): String {
30
+ return "Turbo Native Android ${webView.settings.userAgentString}"
31
+ }
32
+ }
@@ -9,6 +9,12 @@ import dev.hotwire.turbo.delegates.TurboActivityDelegate
9
9
  import <%= package_name %>.R
10
10
 
11
11
  class MainActivity : AppCompatActivity(), TurboActivity {
12
+ private val viewFliper: ViewFlipper
13
+ get() = findViewById(R.id.view_flipper)
14
+
15
+ private val bottomNavigationView: BottomNavigationView
16
+ get() = findViewById(R.id.bottom_navigation_view)
17
+
12
18
  override lateinit var delegate: TurboActivityDelegate
13
19
 
14
20
  override fun onCreate(savedInstanceState: Bundle?) {
@@ -23,19 +29,16 @@ class MainActivity : AppCompatActivity(), TurboActivity {
23
29
  }
24
30
 
25
31
  private fun setupBottomNavigationView() {
26
- val viewFliper = findViewById<ViewFlipper>(R.id.view_flipper)
27
- val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_navigation_view)
28
-
29
32
  bottomNavigationView.setOnItemSelectedListener {
30
33
  when (it.itemId) {
31
34
  R.id.tab_item_one -> {
32
- viewFliper.displayedChild = 0
33
35
  delegate.currentNavHostFragmentId = R.id.tab_one_nav_host
36
+ viewFliper.displayedChild = 0
34
37
  true
35
38
  }
36
39
  R.id.tab_item_two -> {
37
- viewFliper.displayedChild = 1
38
40
  delegate.currentNavHostFragmentId = R.id.tab_two_nav_host
41
+ viewFliper.displayedChild = 1
39
42
  true
40
43
  }
41
44
  else -> {
@@ -1,37 +1,9 @@
1
1
  package <%= package_name %>.main
2
2
 
3
- import android.webkit.WebView
4
- import androidx.appcompat.app.AppCompatActivity
5
- import androidx.fragment.app.Fragment
6
- import dev.hotwire.turbo.config.TurboPathConfiguration
7
- import <%= package_name %>.features.web.WebFragment
8
- import <%= package_name %>.features.web.WebHomeFragment
9
- import <%= package_name %>.features.web.WebModalFragment
10
3
  import <%= package_name %>.util.CURRENT_URL_1
11
- import dev.hotwire.turbo.session.TurboSessionNavHostFragment
12
- import kotlin.reflect.KClass
13
4
 
14
5
  @Suppress("unused")
15
- class TabOneSessionNavHostFragment : TurboSessionNavHostFragment() {
16
- override val sessionName = "main"
17
-
6
+ class TabOneSessionNavHostFragment : BaseSessionNavHostFragment() {
7
+ override val sessionName = "tab_one"
18
8
  override val startLocation = CURRENT_URL_1
19
-
20
- override val registeredActivities: List<KClass<out AppCompatActivity>>
21
- get() = listOf()
22
-
23
- override val registeredFragments: List<KClass<out Fragment>>
24
- get() = listOf(WebFragment::class, WebHomeFragment::class, WebModalFragment::class)
25
-
26
- override val pathConfigurationLocation: TurboPathConfiguration.Location
27
- get() = TurboPathConfiguration.Location(assetFilePath = "json/configuration.json")
28
-
29
- override fun onSessionCreated() {
30
- super.onSessionCreated()
31
- session.webView.settings.userAgentString = customUserAgent(session.webView)
32
- }
33
-
34
- private fun customUserAgent(webView: WebView): String {
35
- return "Turbo Native Android ${webView.settings.userAgentString}"
36
- }
37
9
  }
@@ -1,37 +1,9 @@
1
1
  package <%= package_name %>.main
2
2
 
3
- import android.webkit.WebView
4
- import androidx.appcompat.app.AppCompatActivity
5
- import androidx.fragment.app.Fragment
6
- import dev.hotwire.turbo.config.TurboPathConfiguration
7
- import <%= package_name %>.features.web.WebFragment
8
- import <%= package_name %>.features.web.WebHomeFragment
9
- import <%= package_name %>.features.web.WebModalFragment
10
3
  import <%= package_name %>.util.CURRENT_URL_2
11
- import dev.hotwire.turbo.session.TurboSessionNavHostFragment
12
- import kotlin.reflect.KClass
13
4
 
14
5
  @Suppress("unused")
15
- class TabTwoSessionNavHostFragment : TurboSessionNavHostFragment() {
16
- override val sessionName = "main"
17
-
6
+ class TabTwoSessionNavHostFragment : BaseSessionNavHostFragment() {
7
+ override val sessionName = "tab_two"
18
8
  override val startLocation = CURRENT_URL_2
19
-
20
- override val registeredActivities: List<KClass<out AppCompatActivity>>
21
- get() = listOf()
22
-
23
- override val registeredFragments: List<KClass<out Fragment>>
24
- get() = listOf(WebFragment::class, WebHomeFragment::class, WebModalFragment::class)
25
-
26
- override val pathConfigurationLocation: TurboPathConfiguration.Location
27
- get() = TurboPathConfiguration.Location(assetFilePath = "json/configuration.json")
28
-
29
- override fun onSessionCreated() {
30
- super.onSessionCreated()
31
- session.webView.settings.userAgentString = customUserAgent(session.webView)
32
- }
33
-
34
- private fun customUserAgent(webView: WebView): String {
35
- return "Turbo Native Android ${webView.settings.userAgentString}"
36
- }
37
9
  }