turbo-native-initializer 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
  }