Skip to content

Commit

Permalink
refactor android 2
Browse files Browse the repository at this point in the history
  • Loading branch information
lazaronixon committed Sep 30, 2023
1 parent 10a1221 commit f9cf516
Show file tree
Hide file tree
Showing 9 changed files with 222 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ open class WebFragment : TurboWebFragment(), NavDestination {

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupMenu()
viewLifecycleOwner.lifecycle.addObserver(bridgeDelegate)
}

Expand Down Expand Up @@ -49,4 +50,8 @@ open class WebFragment : TurboWebFragment(), NavDestination {
override fun createErrorView(statusCode: Int): View {
return layoutInflater.inflate(R.layout.error_web, null)
}

private fun setupMenu() {
toolbarForNavigation()?.inflateMenu(R.menu.web)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ val bridgeComponentFactories = listOf(
BridgeComponentFactory("form", ::FormComponent),
BridgeComponentFactory("nav-button", ::NavButtonComponent),
BridgeComponentFactory("flash-message", ::FlashMessageComponent),
BridgeComponentFactory("menu", ::MenuComponent)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package <%= package_name %>.strada

import android.util.Log
import android.view.LayoutInflater
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.bottomsheet.BottomSheetDialog
import dev.hotwire.strada.BridgeComponent
import dev.hotwire.strada.BridgeDelegate
import dev.hotwire.strada.Message
import <%= package_name %>.base.NavDestination
import <%= package_name %>.databinding.MenuComponentBottomSheetBinding
import kotlinx.serialization.Serializable

class MenuComponent(
name: String,
private val delegate: BridgeDelegate<NavDestination>
) : BridgeComponent<NavDestination>(name, delegate) {

private val fragment: Fragment
get() = delegate.destination.fragment

override fun onReceive(message: Message) {
if (message.event == "display") {
handleDisplayEvent(message)
} else {
Log.w("TurboNative", "Unknown event for message: $message")
}
}

private fun handleDisplayEvent(message: Message) {
val data = message.data<MessageData>() ?: return
showBottomSheet(data.title, data.items)
}

private fun showBottomSheet(title: String, items: List<Item>) {
val view = fragment.view?.rootView ?: return
val inflater = LayoutInflater.from(view.context)
val bottomSheet = BottomSheetDialog(view.context)
val binding = MenuComponentBottomSheetBinding.inflate(inflater)

binding.toolbar.title = title
binding.recyclerView.layoutManager = LinearLayoutManager(view.context)
binding.recyclerView.adapter = MenuComponentAdapter().apply {
setData(items)
setListener {
bottomSheet.dismiss()
onItemSelected(it)
}
}

bottomSheet.apply {
setContentView(binding.root)
show()
}
}

private fun onItemSelected(item: Item) {
replyTo("display", SelectionMessageData(item.index))
}

@Serializable
data class MessageData(
val title: String,
val items: List<Item>
)

@Serializable
data class Item(
val title: String,
val index: Int
)

@Serializable
data class SelectionMessageData(
val selectedIndex: Int
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package <%= package_name %>.strada

import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.textview.MaterialTextView
import <%= package_name %>.R

class MenuComponentAdapter : RecyclerView.Adapter<MenuComponentAdapter.ViewHolder>() {
private val type = R.layout.menu_component_adapter_row
private var action: ((MenuComponent.Item) -> Unit)? = null

private var items = emptyList<MenuComponent.Item>()
@SuppressLint("NotifyDataSetChanged")
set(value) {
field = value
notifyDataSetChanged()
}

fun setData(items: List<MenuComponent.Item>) {
this.items = items
}

fun setListener(action: (item: MenuComponent.Item) -> Unit) {
this.action = action
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position])
}

override fun getItemCount(): Int {
return items.count()
}

override fun getItemViewType(position: Int): Int {
return type
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
return ViewHolder(view)
}

inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val textView: MaterialTextView = view.findViewById(R.id.title)

fun bind(item: MenuComponent.Item) {
textView.text = item.title
itemView.setOnClickListener {
action?.invoke(item)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
package <%= package_name %>.strada

import android.util.Log
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment
import dev.hotwire.strada.BridgeComponent
import dev.hotwire.strada.BridgeDelegate
import dev.hotwire.strada.Message
import <%= package_name %>.R
import <%= package_name %>.base.NavDestination
import <%= package_name %>.databinding.NavButtonComponentBinding
import kotlinx.serialization.Serializable

class NavButtonComponent(
name: String,
private val delegate: BridgeDelegate<NavDestination>
) : BridgeComponent<NavDestination>(name, delegate) {

private val navButtonItemId = 20
private var navButtonMenuItem: MenuItem? = null
private val fragment: Fragment
get() = delegate.destination.fragment
private val toolbar: Toolbar?
Expand All @@ -40,27 +34,26 @@ class NavButtonComponent(
}

private fun showToolbarButton(data: MessageData) {
val menu = toolbar?.menu ?: return
val inflater = LayoutInflater.from(fragment.requireContext())
val binding = NavButtonComponentBinding.inflate(inflater)
val order = 999 // Show as the right-most button
val toolbar = toolbar ?: return

binding.navButton.apply {
text = data.title
setOnClickListener {
performAction()
}
toolbar.menu.findItem(R.id.navButton)?.apply {
isVisible = true
title = data.title
}

menu.removeItem(navButtonItemId)
navButtonMenuItem = menu.add(Menu.NONE, navButtonItemId, order, data.title).apply {
actionView = binding.root
setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
toolbar.setOnMenuItemClickListener {
when (it.itemId) {
R.id.navButton -> {
performClick()
true
}
else -> false
}
}
}

private fun performAction(): Boolean {
return replyTo("connect")
private fun performClick() {
replyTo("connect")
}

@Serializable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground">

<com.google.android.material.textview.MaterialTextView
style="@style/TextAppearance.AppCompat.Menu"
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:paddingLeft="16dp"
android:paddingTop="8dp"
android:paddingRight="16dp"
android:paddingBottom="8dp"
android:textSize="18sp"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent">

<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/transparent"
android:stateListAnimator="@null"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

</com.google.android.material.appbar.AppBarLayout>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/app_bar" />

</androidx.constraintlayout.widget.ConstraintLayout>

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="@+id/navButton"
android:orderInCategory="999"
android:visible="false"
app:iconTint="?colorControlNormal"
app:showAsAction="always"
tools:ignore="AlwaysShowAction" />
</menu>

0 comments on commit f9cf516

Please sign in to comment.