turbo-native-initializer 0.0.12 → 0.0.14
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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/BridgeComponentFactories.kt.tt +1 -0
- data/lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/MenuComponent.kt.tt +78 -0
- data/lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/MenuComponentAdapter.kt.tt +57 -0
- data/lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/NavButtonComponent.kt.tt +1 -1
- data/lib/turbo_native_initializer/templates/android_stack/base/app/src/main/res/layout/menu_component_adapter_row.xml +22 -0
- data/lib/turbo_native_initializer/templates/android_stack/base/app/src/main/res/layout/menu_component_bottom_sheet.xml +33 -0
- data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/BridgeComponentFactories.kt.tt +1 -0
- data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/MenuComponent.kt.tt +78 -0
- data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/MenuComponentAdapter.kt.tt +57 -0
- data/lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/NavButtonComponent.kt.tt +1 -1
- data/lib/turbo_native_initializer/templates/android_tabs/base/app/src/main/res/layout/menu_component_adapter_row.xml +22 -0
- data/lib/turbo_native_initializer/templates/android_tabs/base/app/src/main/res/layout/menu_component_bottom_sheet.xml +33 -0
- data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Strada/BridgeComponent+App.swift +6 -1
- data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Strada/MenuComponent.swift +77 -0
- data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject.xcodeproj/project.pbxproj.tt +4 -0
- data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Strada/BridgeComponent+App.swift +6 -1
- data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Strada/MenuComponent.swift +77 -0
- data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject.xcodeproj/project.pbxproj.tt +4 -0
- data/lib/turbo_native_initializer/version.rb +1 -1
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d89f212990b6d8acf8b1f37073d8b892b7f043bdf4a19d11997fabf620ba4ca1
|
4
|
+
data.tar.gz: d2b4ea5ee37d49c0d3eb23d4bb56894407a3ff5d535058ac21c54292439eae45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3002e6b664dd0c92f04c2535707e8008a5c38e6d61e129bf3d376aa586bf2906228323a6947910b7a9d107dbcc2e33403ee1a2de508d444d97d37cea54fa1434
|
7
|
+
data.tar.gz: 6884c3e84fef8d9462387a1ba5c787befe6b79053378bf6d21c5e65f68a3d31f117abf94a9eb0fb671581317968c17a3727247598b657b1171bf149316dbe00c
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ A turbo native project generator for iOS and Android.
|
|
12
12
|
- Added `visitable` property in order to avoid visits. (iOS)
|
13
13
|
- Added support for tab navigation. (iOS/Android)
|
14
14
|
- Added support for flash messages. (iOS/Android)
|
15
|
-
-
|
15
|
+
- Integrated with the gem [strada-rails](https://github.com/lazaronixon/strada-rails).
|
16
16
|
|
17
17
|
## Installation
|
18
18
|
|
@@ -6,4 +6,5 @@ val bridgeComponentFactories = listOf(
|
|
6
6
|
BridgeComponentFactory("form", ::FormComponent),
|
7
7
|
BridgeComponentFactory("nav-button", ::NavButtonComponent),
|
8
8
|
BridgeComponentFactory("flash-message", ::FlashMessageComponent),
|
9
|
+
BridgeComponentFactory("menu", ::MenuComponent)
|
9
10
|
)
|
@@ -0,0 +1,78 @@
|
|
1
|
+
package <%= package_name %>.strada
|
2
|
+
|
3
|
+
import android.util.Log
|
4
|
+
import android.view.LayoutInflater
|
5
|
+
import androidx.fragment.app.Fragment
|
6
|
+
import androidx.recyclerview.widget.LinearLayoutManager
|
7
|
+
import com.google.android.material.bottomsheet.BottomSheetDialog
|
8
|
+
import dev.hotwire.strada.BridgeComponent
|
9
|
+
import dev.hotwire.strada.BridgeDelegate
|
10
|
+
import dev.hotwire.strada.Message
|
11
|
+
import <%= package_name %>.base.NavDestination
|
12
|
+
import <%= package_name %>.databinding.MenuComponentBottomSheetBinding
|
13
|
+
import kotlinx.serialization.Serializable
|
14
|
+
|
15
|
+
class MenuComponent(
|
16
|
+
name: String,
|
17
|
+
private val delegate: BridgeDelegate<NavDestination>
|
18
|
+
) : BridgeComponent<NavDestination>(name, delegate) {
|
19
|
+
|
20
|
+
private val fragment: Fragment
|
21
|
+
get() = delegate.destination.fragment
|
22
|
+
|
23
|
+
override fun onReceive(message: Message) {
|
24
|
+
if (message.event == "display") {
|
25
|
+
handleDisplayEvent(message)
|
26
|
+
} else {
|
27
|
+
Log.w("TurboNative", "Unknown event for message: $message")
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
private fun handleDisplayEvent(message: Message) {
|
32
|
+
val data = message.data<MessageData>() ?: return
|
33
|
+
showBottomSheet(data.title, data.items)
|
34
|
+
}
|
35
|
+
|
36
|
+
private fun showBottomSheet(title: String, items: List<Item>) {
|
37
|
+
val view = fragment.view?.rootView ?: return
|
38
|
+
val inflater = LayoutInflater.from(view.context)
|
39
|
+
val bottomSheet = BottomSheetDialog(view.context)
|
40
|
+
val binding = MenuComponentBottomSheetBinding.inflate(inflater)
|
41
|
+
|
42
|
+
binding.toolbar.title = title
|
43
|
+
binding.recyclerView.layoutManager = LinearLayoutManager(view.context)
|
44
|
+
binding.recyclerView.adapter = MenuComponentAdapter().apply {
|
45
|
+
setData(items)
|
46
|
+
setListener {
|
47
|
+
bottomSheet.dismiss()
|
48
|
+
onItemSelected(it)
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
bottomSheet.apply {
|
53
|
+
setContentView(binding.root)
|
54
|
+
show()
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
private fun onItemSelected(item: Item) {
|
59
|
+
replyTo("display", SelectionMessageData(item.index))
|
60
|
+
}
|
61
|
+
|
62
|
+
@Serializable
|
63
|
+
data class MessageData(
|
64
|
+
val title: String,
|
65
|
+
val items: List<Item>
|
66
|
+
)
|
67
|
+
|
68
|
+
@Serializable
|
69
|
+
data class Item(
|
70
|
+
val title: String,
|
71
|
+
val index: Int
|
72
|
+
)
|
73
|
+
|
74
|
+
@Serializable
|
75
|
+
data class SelectionMessageData(
|
76
|
+
val selectedIndex: Int
|
77
|
+
)
|
78
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
package <%= package_name %>.strada
|
2
|
+
|
3
|
+
import android.annotation.SuppressLint
|
4
|
+
import android.view.LayoutInflater
|
5
|
+
import android.view.View
|
6
|
+
import android.view.ViewGroup
|
7
|
+
import androidx.recyclerview.widget.RecyclerView
|
8
|
+
import com.google.android.material.textview.MaterialTextView
|
9
|
+
import <%= package_name %>.R
|
10
|
+
|
11
|
+
class MenuComponentAdapter : RecyclerView.Adapter<MenuComponentAdapter.ViewHolder>() {
|
12
|
+
private val type = R.layout.menu_component_adapter_row
|
13
|
+
private var action: ((MenuComponent.Item) -> Unit)? = null
|
14
|
+
|
15
|
+
private var items = emptyList<MenuComponent.Item>()
|
16
|
+
@SuppressLint("NotifyDataSetChanged")
|
17
|
+
set(value) {
|
18
|
+
field = value
|
19
|
+
notifyDataSetChanged()
|
20
|
+
}
|
21
|
+
|
22
|
+
fun setData(items: List<MenuComponent.Item>) {
|
23
|
+
this.items = items
|
24
|
+
}
|
25
|
+
|
26
|
+
fun setListener(action: (item: MenuComponent.Item) -> Unit) {
|
27
|
+
this.action = action
|
28
|
+
}
|
29
|
+
|
30
|
+
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
31
|
+
holder.bind(items[position])
|
32
|
+
}
|
33
|
+
|
34
|
+
override fun getItemCount(): Int {
|
35
|
+
return items.count()
|
36
|
+
}
|
37
|
+
|
38
|
+
override fun getItemViewType(position: Int): Int {
|
39
|
+
return type
|
40
|
+
}
|
41
|
+
|
42
|
+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
43
|
+
val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
|
44
|
+
return ViewHolder(view)
|
45
|
+
}
|
46
|
+
|
47
|
+
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
48
|
+
private val textView: MaterialTextView = view.findViewById(R.id.title)
|
49
|
+
|
50
|
+
fun bind(item: MenuComponent.Item) {
|
51
|
+
textView.text = item.title
|
52
|
+
itemView.setOnClickListener {
|
53
|
+
action?.invoke(item)
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
@@ -19,7 +19,7 @@ class NavButtonComponent(
|
|
19
19
|
private val delegate: BridgeDelegate<NavDestination>
|
20
20
|
) : BridgeComponent<NavDestination>(name, delegate) {
|
21
21
|
|
22
|
-
private val navButtonItemId =
|
22
|
+
private val navButtonItemId = 10
|
23
23
|
private var navButtonMenuItem: MenuItem? = null
|
24
24
|
private val fragment: Fragment
|
25
25
|
get() = delegate.destination.fragment
|
@@ -0,0 +1,22 @@
|
|
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="wrap_content"
|
7
|
+
android:background="?selectableItemBackground">
|
8
|
+
|
9
|
+
<com.google.android.material.textview.MaterialTextView
|
10
|
+
style="@style/TextAppearance.AppCompat.Menu"
|
11
|
+
android:id="@+id/title"
|
12
|
+
android:layout_width="match_parent"
|
13
|
+
android:layout_height="wrap_content"
|
14
|
+
android:minHeight="48dp"
|
15
|
+
android:paddingLeft="16dp"
|
16
|
+
android:paddingTop="8dp"
|
17
|
+
android:paddingRight="16dp"
|
18
|
+
android:paddingBottom="8dp"
|
19
|
+
android:textSize="18sp"
|
20
|
+
app:layout_constraintTop_toTopOf="parent" />
|
21
|
+
|
22
|
+
</androidx.constraintlayout.widget.ConstraintLayout>
|
@@ -0,0 +1,33 @@
|
|
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
|
+
android:background="@color/transparent">
|
8
|
+
|
9
|
+
<com.google.android.material.appbar.AppBarLayout
|
10
|
+
android:id="@+id/app_bar"
|
11
|
+
android:layout_width="match_parent"
|
12
|
+
android:layout_height="wrap_content"
|
13
|
+
android:background="@color/transparent"
|
14
|
+
android:stateListAnimator="@null"
|
15
|
+
app:layout_constraintEnd_toEndOf="parent"
|
16
|
+
app:layout_constraintStart_toStartOf="parent"
|
17
|
+
app:layout_constraintTop_toTopOf="parent">
|
18
|
+
|
19
|
+
<com.google.android.material.appbar.MaterialToolbar
|
20
|
+
android:id="@+id/toolbar"
|
21
|
+
android:layout_width="match_parent"
|
22
|
+
android:layout_height="wrap_content" />
|
23
|
+
|
24
|
+
</com.google.android.material.appbar.AppBarLayout>
|
25
|
+
|
26
|
+
<androidx.recyclerview.widget.RecyclerView
|
27
|
+
android:id="@+id/recycler_view"
|
28
|
+
android:layout_width="match_parent"
|
29
|
+
android:layout_height="wrap_content"
|
30
|
+
app:layout_constraintBottom_toBottomOf="parent"
|
31
|
+
app:layout_constraintTop_toBottomOf="@+id/app_bar" />
|
32
|
+
|
33
|
+
</androidx.constraintlayout.widget.ConstraintLayout>
|
@@ -6,4 +6,5 @@ val bridgeComponentFactories = listOf(
|
|
6
6
|
BridgeComponentFactory("form", ::FormComponent),
|
7
7
|
BridgeComponentFactory("nav-button", ::NavButtonComponent),
|
8
8
|
BridgeComponentFactory("flash-message", ::FlashMessageComponent),
|
9
|
+
BridgeComponentFactory("menu", ::MenuComponent)
|
9
10
|
)
|
@@ -0,0 +1,78 @@
|
|
1
|
+
package <%= package_name %>.strada
|
2
|
+
|
3
|
+
import android.util.Log
|
4
|
+
import android.view.LayoutInflater
|
5
|
+
import androidx.fragment.app.Fragment
|
6
|
+
import androidx.recyclerview.widget.LinearLayoutManager
|
7
|
+
import com.google.android.material.bottomsheet.BottomSheetDialog
|
8
|
+
import dev.hotwire.strada.BridgeComponent
|
9
|
+
import dev.hotwire.strada.BridgeDelegate
|
10
|
+
import dev.hotwire.strada.Message
|
11
|
+
import <%= package_name %>.base.NavDestination
|
12
|
+
import <%= package_name %>.databinding.MenuComponentBottomSheetBinding
|
13
|
+
import kotlinx.serialization.Serializable
|
14
|
+
|
15
|
+
class MenuComponent(
|
16
|
+
name: String,
|
17
|
+
private val delegate: BridgeDelegate<NavDestination>
|
18
|
+
) : BridgeComponent<NavDestination>(name, delegate) {
|
19
|
+
|
20
|
+
private val fragment: Fragment
|
21
|
+
get() = delegate.destination.fragment
|
22
|
+
|
23
|
+
override fun onReceive(message: Message) {
|
24
|
+
if (message.event == "display") {
|
25
|
+
handleDisplayEvent(message)
|
26
|
+
} else {
|
27
|
+
Log.w("TurboNative", "Unknown event for message: $message")
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
private fun handleDisplayEvent(message: Message) {
|
32
|
+
val data = message.data<MessageData>() ?: return
|
33
|
+
showBottomSheet(data.title, data.items)
|
34
|
+
}
|
35
|
+
|
36
|
+
private fun showBottomSheet(title: String, items: List<Item>) {
|
37
|
+
val view = fragment.view?.rootView ?: return
|
38
|
+
val inflater = LayoutInflater.from(view.context)
|
39
|
+
val bottomSheet = BottomSheetDialog(view.context)
|
40
|
+
val binding = MenuComponentBottomSheetBinding.inflate(inflater)
|
41
|
+
|
42
|
+
binding.toolbar.title = title
|
43
|
+
binding.recyclerView.layoutManager = LinearLayoutManager(view.context)
|
44
|
+
binding.recyclerView.adapter = MenuComponentAdapter().apply {
|
45
|
+
setData(items)
|
46
|
+
setListener {
|
47
|
+
bottomSheet.dismiss()
|
48
|
+
onItemSelected(it)
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
bottomSheet.apply {
|
53
|
+
setContentView(binding.root)
|
54
|
+
show()
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
private fun onItemSelected(item: Item) {
|
59
|
+
replyTo("display", SelectionMessageData(item.index))
|
60
|
+
}
|
61
|
+
|
62
|
+
@Serializable
|
63
|
+
data class MessageData(
|
64
|
+
val title: String,
|
65
|
+
val items: List<Item>
|
66
|
+
)
|
67
|
+
|
68
|
+
@Serializable
|
69
|
+
data class Item(
|
70
|
+
val title: String,
|
71
|
+
val index: Int
|
72
|
+
)
|
73
|
+
|
74
|
+
@Serializable
|
75
|
+
data class SelectionMessageData(
|
76
|
+
val selectedIndex: Int
|
77
|
+
)
|
78
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
package <%= package_name %>.strada
|
2
|
+
|
3
|
+
import android.annotation.SuppressLint
|
4
|
+
import android.view.LayoutInflater
|
5
|
+
import android.view.View
|
6
|
+
import android.view.ViewGroup
|
7
|
+
import androidx.recyclerview.widget.RecyclerView
|
8
|
+
import com.google.android.material.textview.MaterialTextView
|
9
|
+
import <%= package_name %>.R
|
10
|
+
|
11
|
+
class MenuComponentAdapter : RecyclerView.Adapter<MenuComponentAdapter.ViewHolder>() {
|
12
|
+
private val type = R.layout.menu_component_adapter_row
|
13
|
+
private var action: ((MenuComponent.Item) -> Unit)? = null
|
14
|
+
|
15
|
+
private var items = emptyList<MenuComponent.Item>()
|
16
|
+
@SuppressLint("NotifyDataSetChanged")
|
17
|
+
set(value) {
|
18
|
+
field = value
|
19
|
+
notifyDataSetChanged()
|
20
|
+
}
|
21
|
+
|
22
|
+
fun setData(items: List<MenuComponent.Item>) {
|
23
|
+
this.items = items
|
24
|
+
}
|
25
|
+
|
26
|
+
fun setListener(action: (item: MenuComponent.Item) -> Unit) {
|
27
|
+
this.action = action
|
28
|
+
}
|
29
|
+
|
30
|
+
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
31
|
+
holder.bind(items[position])
|
32
|
+
}
|
33
|
+
|
34
|
+
override fun getItemCount(): Int {
|
35
|
+
return items.count()
|
36
|
+
}
|
37
|
+
|
38
|
+
override fun getItemViewType(position: Int): Int {
|
39
|
+
return type
|
40
|
+
}
|
41
|
+
|
42
|
+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
43
|
+
val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
|
44
|
+
return ViewHolder(view)
|
45
|
+
}
|
46
|
+
|
47
|
+
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
48
|
+
private val textView: MaterialTextView = view.findViewById(R.id.title)
|
49
|
+
|
50
|
+
fun bind(item: MenuComponent.Item) {
|
51
|
+
textView.text = item.title
|
52
|
+
itemView.setOnClickListener {
|
53
|
+
action?.invoke(item)
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
@@ -19,7 +19,7 @@ class NavButtonComponent(
|
|
19
19
|
private val delegate: BridgeDelegate<NavDestination>
|
20
20
|
) : BridgeComponent<NavDestination>(name, delegate) {
|
21
21
|
|
22
|
-
private val navButtonItemId =
|
22
|
+
private val navButtonItemId = 10
|
23
23
|
private var navButtonMenuItem: MenuItem? = null
|
24
24
|
private val fragment: Fragment
|
25
25
|
get() = delegate.destination.fragment
|
@@ -0,0 +1,22 @@
|
|
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="wrap_content"
|
7
|
+
android:background="?selectableItemBackground">
|
8
|
+
|
9
|
+
<com.google.android.material.textview.MaterialTextView
|
10
|
+
style="@style/TextAppearance.AppCompat.Menu"
|
11
|
+
android:id="@+id/title"
|
12
|
+
android:layout_width="match_parent"
|
13
|
+
android:layout_height="wrap_content"
|
14
|
+
android:minHeight="48dp"
|
15
|
+
android:paddingLeft="16dp"
|
16
|
+
android:paddingTop="8dp"
|
17
|
+
android:paddingRight="16dp"
|
18
|
+
android:paddingBottom="8dp"
|
19
|
+
android:textSize="18sp"
|
20
|
+
app:layout_constraintTop_toTopOf="parent" />
|
21
|
+
|
22
|
+
</androidx.constraintlayout.widget.ConstraintLayout>
|
@@ -0,0 +1,33 @@
|
|
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
|
+
android:background="@color/transparent">
|
8
|
+
|
9
|
+
<com.google.android.material.appbar.AppBarLayout
|
10
|
+
android:id="@+id/app_bar"
|
11
|
+
android:layout_width="match_parent"
|
12
|
+
android:layout_height="wrap_content"
|
13
|
+
android:background="@color/transparent"
|
14
|
+
android:stateListAnimator="@null"
|
15
|
+
app:layout_constraintEnd_toEndOf="parent"
|
16
|
+
app:layout_constraintStart_toStartOf="parent"
|
17
|
+
app:layout_constraintTop_toTopOf="parent">
|
18
|
+
|
19
|
+
<com.google.android.material.appbar.MaterialToolbar
|
20
|
+
android:id="@+id/toolbar"
|
21
|
+
android:layout_width="match_parent"
|
22
|
+
android:layout_height="wrap_content" />
|
23
|
+
|
24
|
+
</com.google.android.material.appbar.AppBarLayout>
|
25
|
+
|
26
|
+
<androidx.recyclerview.widget.RecyclerView
|
27
|
+
android:id="@+id/recycler_view"
|
28
|
+
android:layout_width="match_parent"
|
29
|
+
android:layout_height="wrap_content"
|
30
|
+
app:layout_constraintBottom_toBottomOf="parent"
|
31
|
+
app:layout_constraintTop_toBottomOf="@+id/app_bar" />
|
32
|
+
|
33
|
+
</androidx.constraintlayout.widget.ConstraintLayout>
|
@@ -3,6 +3,11 @@ import Strada
|
|
3
3
|
|
4
4
|
extension BridgeComponent {
|
5
5
|
static var allTypes: [BridgeComponent.Type] {
|
6
|
-
[
|
6
|
+
[
|
7
|
+
FormComponent.self,
|
8
|
+
NavButtonComponent.self,
|
9
|
+
MenuComponent.self,
|
10
|
+
FlashMessageComponent.self
|
11
|
+
]
|
7
12
|
}
|
8
13
|
}
|
data/lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Strada/MenuComponent.swift
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
import Foundation
|
2
|
+
import Strada
|
3
|
+
import UIKit
|
4
|
+
|
5
|
+
final class MenuComponent: BridgeComponent {
|
6
|
+
override class var name: String { "menu" }
|
7
|
+
|
8
|
+
override func onReceive(message: Message) {
|
9
|
+
guard let event = Event(rawValue: message.event) else {
|
10
|
+
return
|
11
|
+
}
|
12
|
+
|
13
|
+
if event == .display {
|
14
|
+
handleDisplayEvent(message: message)
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
// MARK: Private
|
19
|
+
|
20
|
+
private var viewController: UIViewController? {
|
21
|
+
delegate.destination as? UIViewController
|
22
|
+
}
|
23
|
+
|
24
|
+
private func handleDisplayEvent(message: Message) {
|
25
|
+
guard let data: MessageData = message.data() else { return }
|
26
|
+
showAlertSheet(with: data.title, items: data.items)
|
27
|
+
}
|
28
|
+
|
29
|
+
private func showAlertSheet(with title: String, items: [Item]) {
|
30
|
+
let alertController = UIAlertController(title: title,
|
31
|
+
message: nil,
|
32
|
+
preferredStyle: .actionSheet)
|
33
|
+
|
34
|
+
for item in items {
|
35
|
+
let action = UIAlertAction(title: item.title, style: .default) {[weak self] _ in
|
36
|
+
self?.onItemSelected(item: item)
|
37
|
+
}
|
38
|
+
alertController.addAction(action)
|
39
|
+
}
|
40
|
+
|
41
|
+
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
|
42
|
+
alertController.addAction(cancelAction)
|
43
|
+
|
44
|
+
viewController?.present(alertController, animated: true)
|
45
|
+
}
|
46
|
+
|
47
|
+
private func onItemSelected(item: Item) {
|
48
|
+
reply(to: Event.display.rawValue,
|
49
|
+
with: SelectionMessageData(selectedIndex: item.index))
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
// MARK: Events
|
54
|
+
|
55
|
+
private extension MenuComponent {
|
56
|
+
enum Event: String {
|
57
|
+
case display
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
// MARK: Message data
|
62
|
+
|
63
|
+
private extension MenuComponent {
|
64
|
+
struct MessageData: Decodable {
|
65
|
+
let title: String
|
66
|
+
let items: [Item]
|
67
|
+
}
|
68
|
+
|
69
|
+
struct Item: Decodable {
|
70
|
+
let title: String
|
71
|
+
let index: Int
|
72
|
+
}
|
73
|
+
|
74
|
+
struct SelectionMessageData: Encodable {
|
75
|
+
let selectedIndex:Int
|
76
|
+
}
|
77
|
+
}
|
@@ -14,6 +14,7 @@
|
|
14
14
|
5D281BB42ABC0CB0001CE599 /* BridgeComponent+App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D281BB32ABC0CB0001CE599 /* BridgeComponent+App.swift */; };
|
15
15
|
5D281BB62ABC0CB9001CE599 /* FormComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D281BB52ABC0CB9001CE599 /* FormComponent.swift */; };
|
16
16
|
5D91C5402AC538960046D872 /* FlashMessageComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D91C53F2AC538960046D872 /* FlashMessageComponent.swift */; };
|
17
|
+
5DA9C92F2AC7E38100FEA7E6 /* MenuComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DA9C92E2AC7E38100FEA7E6 /* MenuComponent.swift */; };
|
17
18
|
5DAF71B72AC3FB53002D04FE /* UIViewController+Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DAF71B62AC3FB53002D04FE /* UIViewController+Toast.swift */; };
|
18
19
|
5DCC50D42A959DF900B529A0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DCC50D32A959DF900B529A0 /* AppDelegate.swift */; };
|
19
20
|
5DCC50D62A959DF900B529A0 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DCC50D52A959DF900B529A0 /* SceneDelegate.swift */; };
|
@@ -35,6 +36,7 @@
|
|
35
36
|
5D281BB32ABC0CB0001CE599 /* BridgeComponent+App.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BridgeComponent+App.swift"; sourceTree = "<group>"; };
|
36
37
|
5D281BB52ABC0CB9001CE599 /* FormComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormComponent.swift; sourceTree = "<group>"; };
|
37
38
|
5D91C53F2AC538960046D872 /* FlashMessageComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlashMessageComponent.swift; sourceTree = "<group>"; };
|
39
|
+
5DA9C92E2AC7E38100FEA7E6 /* MenuComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuComponent.swift; sourceTree = "<group>"; };
|
38
40
|
5DAF71B62AC3FB53002D04FE /* UIViewController+Toast.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Toast.swift"; sourceTree = "<group>"; };
|
39
41
|
5DCC50D02A959DF900B529A0 /* <%= name %>.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = <%= name %>.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
40
42
|
5DCC50D32A959DF900B529A0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
@@ -70,6 +72,7 @@
|
|
70
72
|
5D281BB52ABC0CB9001CE599 /* FormComponent.swift */,
|
71
73
|
5D1F2EC02ABEB12300B2819A /* NavButtonComponent.swift */,
|
72
74
|
5D91C53F2AC538960046D872 /* FlashMessageComponent.swift */,
|
75
|
+
5DA9C92E2AC7E38100FEA7E6 /* MenuComponent.swift */,
|
73
76
|
);
|
74
77
|
path = Strada;
|
75
78
|
sourceTree = "<group>";
|
@@ -224,6 +227,7 @@
|
|
224
227
|
isa = PBXSourcesBuildPhase;
|
225
228
|
buildActionMask = 2147483647;
|
226
229
|
files = (
|
230
|
+
5DA9C92F2AC7E38100FEA7E6 /* MenuComponent.swift in Sources */,
|
227
231
|
5DCC50D82A959DF900B529A0 /* TurboWebViewController.swift in Sources */,
|
228
232
|
5DDD58812AA9A8BE00FAC961 /* NumbersViewController.swift in Sources */,
|
229
233
|
5D91C5402AC538960046D872 /* FlashMessageComponent.swift in Sources */,
|
@@ -3,6 +3,11 @@ import Strada
|
|
3
3
|
|
4
4
|
extension BridgeComponent {
|
5
5
|
static var allTypes: [BridgeComponent.Type] {
|
6
|
-
[
|
6
|
+
[
|
7
|
+
FormComponent.self,
|
8
|
+
NavButtonComponent.self,
|
9
|
+
MenuComponent.self,
|
10
|
+
FlashMessageComponent.self
|
11
|
+
]
|
7
12
|
}
|
8
13
|
}
|
data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Strada/MenuComponent.swift
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
import Foundation
|
2
|
+
import Strada
|
3
|
+
import UIKit
|
4
|
+
|
5
|
+
final class MenuComponent: BridgeComponent {
|
6
|
+
override class var name: String { "menu" }
|
7
|
+
|
8
|
+
override func onReceive(message: Message) {
|
9
|
+
guard let event = Event(rawValue: message.event) else {
|
10
|
+
return
|
11
|
+
}
|
12
|
+
|
13
|
+
if event == .display {
|
14
|
+
handleDisplayEvent(message: message)
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
// MARK: Private
|
19
|
+
|
20
|
+
private var viewController: UIViewController? {
|
21
|
+
delegate.destination as? UIViewController
|
22
|
+
}
|
23
|
+
|
24
|
+
private func handleDisplayEvent(message: Message) {
|
25
|
+
guard let data: MessageData = message.data() else { return }
|
26
|
+
showAlertSheet(with: data.title, items: data.items)
|
27
|
+
}
|
28
|
+
|
29
|
+
private func showAlertSheet(with title: String, items: [Item]) {
|
30
|
+
let alertController = UIAlertController(title: title,
|
31
|
+
message: nil,
|
32
|
+
preferredStyle: .actionSheet)
|
33
|
+
|
34
|
+
for item in items {
|
35
|
+
let action = UIAlertAction(title: item.title, style: .default) {[weak self] _ in
|
36
|
+
self?.onItemSelected(item: item)
|
37
|
+
}
|
38
|
+
alertController.addAction(action)
|
39
|
+
}
|
40
|
+
|
41
|
+
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
|
42
|
+
alertController.addAction(cancelAction)
|
43
|
+
|
44
|
+
viewController?.present(alertController, animated: true)
|
45
|
+
}
|
46
|
+
|
47
|
+
private func onItemSelected(item: Item) {
|
48
|
+
reply(to: Event.display.rawValue,
|
49
|
+
with: SelectionMessageData(selectedIndex: item.index))
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
// MARK: Events
|
54
|
+
|
55
|
+
private extension MenuComponent {
|
56
|
+
enum Event: String {
|
57
|
+
case display
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
// MARK: Message data
|
62
|
+
|
63
|
+
private extension MenuComponent {
|
64
|
+
struct MessageData: Decodable {
|
65
|
+
let title: String
|
66
|
+
let items: [Item]
|
67
|
+
}
|
68
|
+
|
69
|
+
struct Item: Decodable {
|
70
|
+
let title: String
|
71
|
+
let index: Int
|
72
|
+
}
|
73
|
+
|
74
|
+
struct SelectionMessageData: Encodable {
|
75
|
+
let selectedIndex:Int
|
76
|
+
}
|
77
|
+
}
|
data/lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject.xcodeproj/project.pbxproj.tt
CHANGED
@@ -15,6 +15,7 @@
|
|
15
15
|
5D8AB2FC2ABC117F00C6A82F /* BridgeComponent+App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D8AB2FA2ABC117F00C6A82F /* BridgeComponent+App.swift */; };
|
16
16
|
5D8AB2FE2ABC119900C6A82F /* WKWebViewConfiguration+App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D8AB2FD2ABC119900C6A82F /* WKWebViewConfiguration+App.swift */; };
|
17
17
|
5D8AB3012ABC127300C6A82F /* Strada in Frameworks */ = {isa = PBXBuildFile; productRef = 5D8AB3002ABC127300C6A82F /* Strada */; };
|
18
|
+
5DA9C9352AC874D200FEA7E6 /* MenuComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DA9C9342AC874D200FEA7E6 /* MenuComponent.swift */; };
|
18
19
|
5DCC50D42A959DF900B529A0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DCC50D32A959DF900B529A0 /* AppDelegate.swift */; };
|
19
20
|
5DCC50D62A959DF900B529A0 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DCC50D52A959DF900B529A0 /* SceneDelegate.swift */; };
|
20
21
|
5DCC50D82A959DF900B529A0 /* TurboWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DCC50D72A959DF900B529A0 /* TurboWebViewController.swift */; };
|
@@ -36,6 +37,7 @@
|
|
36
37
|
5D8AB2F92ABC117F00C6A82F /* FormComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormComponent.swift; sourceTree = "<group>"; };
|
37
38
|
5D8AB2FA2ABC117F00C6A82F /* BridgeComponent+App.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BridgeComponent+App.swift"; sourceTree = "<group>"; };
|
38
39
|
5D8AB2FD2ABC119900C6A82F /* WKWebViewConfiguration+App.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "WKWebViewConfiguration+App.swift"; sourceTree = "<group>"; };
|
40
|
+
5DA9C9342AC874D200FEA7E6 /* MenuComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuComponent.swift; sourceTree = "<group>"; };
|
39
41
|
5DCC50D02A959DF900B529A0 /* <%= name %>.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = <%= name %>.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
40
42
|
5DCC50D32A959DF900B529A0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
41
43
|
5DCC50D52A959DF900B529A0 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
@@ -79,6 +81,7 @@
|
|
79
81
|
5D8AB2F92ABC117F00C6A82F /* FormComponent.swift */,
|
80
82
|
5D1F2EC02ABEB12300B2819A /* NavButtonComponent.swift */,
|
81
83
|
5D2381402AC53D8900FABA1F /* FlashMessageComponent.swift */,
|
84
|
+
5DA9C9342AC874D200FEA7E6 /* MenuComponent.swift */,
|
82
85
|
);
|
83
86
|
path = Strada;
|
84
87
|
sourceTree = "<group>";
|
@@ -224,6 +227,7 @@
|
|
224
227
|
isa = PBXSourcesBuildPhase;
|
225
228
|
buildActionMask = 2147483647;
|
226
229
|
files = (
|
230
|
+
5DA9C9352AC874D200FEA7E6 /* MenuComponent.swift in Sources */,
|
227
231
|
5DCC50D82A959DF900B529A0 /* TurboWebViewController.swift in Sources */,
|
228
232
|
5DDD58812AA9A8BE00FAC961 /* NumbersViewController.swift in Sources */,
|
229
233
|
5D2381412AC53D8900FABA1F /* FlashMessageComponent.swift in Sources */,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: turbo-native-initializer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nixon
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -52,6 +52,8 @@ files:
|
|
52
52
|
- lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/BridgeComponentFactories.kt.tt
|
53
53
|
- lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/FlashMessageComponent.kt.tt
|
54
54
|
- lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/FormComponent.kt.tt
|
55
|
+
- lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/MenuComponent.kt.tt
|
56
|
+
- lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/MenuComponentAdapter.kt.tt
|
55
57
|
- lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/NavButtonComponent.kt.tt
|
56
58
|
- lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/util/Constants.kt.tt
|
57
59
|
- lib/turbo_native_initializer/templates/android_stack/app/src/main/java/dev/hotwire/turbo/turbonativeproject/util/Extension.kt.tt
|
@@ -73,6 +75,8 @@ files:
|
|
73
75
|
- lib/turbo_native_initializer/templates/android_stack/base/app/src/main/res/layout/form_component_submit.xml
|
74
76
|
- lib/turbo_native_initializer/templates/android_stack/base/app/src/main/res/layout/fragment_native.xml
|
75
77
|
- lib/turbo_native_initializer/templates/android_stack/base/app/src/main/res/layout/fragment_web_home.xml
|
78
|
+
- lib/turbo_native_initializer/templates/android_stack/base/app/src/main/res/layout/menu_component_adapter_row.xml
|
79
|
+
- lib/turbo_native_initializer/templates/android_stack/base/app/src/main/res/layout/menu_component_bottom_sheet.xml
|
76
80
|
- lib/turbo_native_initializer/templates/android_stack/base/app/src/main/res/layout/nav_button_component.xml
|
77
81
|
- lib/turbo_native_initializer/templates/android_stack/base/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
|
78
82
|
- lib/turbo_native_initializer/templates/android_stack/base/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
|
@@ -105,6 +109,8 @@ files:
|
|
105
109
|
- lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/BridgeComponentFactories.kt.tt
|
106
110
|
- lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/FlashMessageComponent.kt.tt
|
107
111
|
- lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/FormComponent.kt.tt
|
112
|
+
- lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/MenuComponent.kt.tt
|
113
|
+
- lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/MenuComponentAdapter.kt.tt
|
108
114
|
- lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/strada/NavButtonComponent.kt.tt
|
109
115
|
- lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/util/Constants.kt.tt
|
110
116
|
- lib/turbo_native_initializer/templates/android_tabs/app/src/main/java/dev/hotwire/turbo/turbonativeproject/util/Extension.kt.tt
|
@@ -128,6 +134,8 @@ files:
|
|
128
134
|
- lib/turbo_native_initializer/templates/android_tabs/base/app/src/main/res/layout/form_component_submit.xml
|
129
135
|
- lib/turbo_native_initializer/templates/android_tabs/base/app/src/main/res/layout/fragment_native.xml
|
130
136
|
- lib/turbo_native_initializer/templates/android_tabs/base/app/src/main/res/layout/fragment_web_home.xml
|
137
|
+
- lib/turbo_native_initializer/templates/android_tabs/base/app/src/main/res/layout/menu_component_adapter_row.xml
|
138
|
+
- lib/turbo_native_initializer/templates/android_tabs/base/app/src/main/res/layout/menu_component_bottom_sheet.xml
|
131
139
|
- lib/turbo_native_initializer/templates/android_tabs/base/app/src/main/res/layout/nav_button_component.xml
|
132
140
|
- lib/turbo_native_initializer/templates/android_tabs/base/app/src/main/res/menu/bottom_navigation_menu.xml
|
133
141
|
- lib/turbo_native_initializer/templates/android_tabs/base/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
|
@@ -173,6 +181,7 @@ files:
|
|
173
181
|
- lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Strada/BridgeComponent+App.swift
|
174
182
|
- lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Strada/FlashMessageComponent.swift
|
175
183
|
- lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Strada/FormComponent.swift
|
184
|
+
- lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Strada/MenuComponent.swift
|
176
185
|
- lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/Strada/NavButtonComponent.swift
|
177
186
|
- lib/turbo_native_initializer/templates/ios_stack/TurboNativeProject/TurboNativeProject.swift.tt
|
178
187
|
- lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject.xcodeproj/project.pbxproj.tt
|
@@ -200,6 +209,7 @@ files:
|
|
200
209
|
- lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Strada/BridgeComponent+App.swift
|
201
210
|
- lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Strada/FlashMessageComponent.swift
|
202
211
|
- lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Strada/FormComponent.swift
|
212
|
+
- lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Strada/MenuComponent.swift
|
203
213
|
- lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/Strada/NavButtonComponent.swift
|
204
214
|
- lib/turbo_native_initializer/templates/ios_tabs/TurboNativeProject/TurboNativeProject.swift.tt
|
205
215
|
- lib/turbo_native_initializer/version.rb
|