Feat: Show channel number and name in direct message title (#1131)

* Feat: Show channel number and name in direct message title

This commit updates the message title to include the channel number and name when viewing direct messages.

This improves the user experience by providing more context about the conversation.

* Refactor: Improve message fragment toolbar

Use MaterialToolbar's built-in title and subtitle features to display channel name and number, simplifying the layout and improving UI consistency.
pull/1147/head
James Rich 2024-07-13 05:25:22 -05:00 zatwierdzone przez GitHub
rodzic 7a6ef224f5
commit 8dad5a085e
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
2 zmienionych plików z 48 dodań i 28 usunięć

Wyświetl plik

@ -4,8 +4,15 @@ import android.graphics.Color
import android.graphics.Rect import android.graphics.Rect
import android.graphics.drawable.GradientDrawable import android.graphics.drawable.GradientDrawable
import android.os.Bundle import android.os.Bundle
import android.view.* import android.view.LayoutInflater
import android.widget.* import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.cardview.widget.CardView import androidx.cardview.widget.CardView
@ -15,25 +22,30 @@ import androidx.core.view.allViews
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.asLiveData import androidx.lifecycle.asLiveData
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.DataPacket import com.geeksville.mesh.DataPacket
import com.geeksville.mesh.MessageStatus import com.geeksville.mesh.MessageStatus
import com.geeksville.mesh.NodeInfo import com.geeksville.mesh.NodeInfo
import com.geeksville.mesh.R import com.geeksville.mesh.R
import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.database.entity.Packet import com.geeksville.mesh.database.entity.Packet
import com.geeksville.mesh.database.entity.QuickChatAction import com.geeksville.mesh.database.entity.QuickChatAction
import com.geeksville.mesh.databinding.AdapterMessageLayoutBinding import com.geeksville.mesh.databinding.AdapterMessageLayoutBinding
import com.geeksville.mesh.databinding.MessagesFragmentBinding import com.geeksville.mesh.databinding.MessagesFragmentBinding
import com.geeksville.mesh.model.UIViewModel import com.geeksville.mesh.model.UIViewModel
import com.geeksville.mesh.model.getChannel
import com.geeksville.mesh.util.Utf8ByteLengthFilter import com.geeksville.mesh.util.Utf8ByteLengthFilter
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import java.text.DateFormat import java.text.DateFormat
import java.util.* import java.util.Date
// return time if within 24 hours, otherwise date/time // return time if within 24 hours, otherwise date/time
internal fun getShortDateTime(date: Date): String { internal fun getShortDateTime(date: Date): String {
@ -232,7 +244,12 @@ class MessagesFragment : Fragment(), Logging {
holder.itemView.background = GradientDrawable().apply { holder.itemView.background = GradientDrawable().apply {
shape = GradientDrawable.RECTANGLE shape = GradientDrawable.RECTANGLE
cornerRadius = 32f cornerRadius = 32f
setColor(ContextCompat.getColor(holder.itemView.context, R.color.colorAdvancedBackground)) setColor(
ContextCompat.getColor(
holder.itemView.context,
R.color.colorAdvancedBackground
)
)
} }
} }
} }
@ -288,7 +305,21 @@ class MessagesFragment : Fragment(), Logging {
val contactKey = arguments?.getString("contactKey").toString() val contactKey = arguments?.getString("contactKey").toString()
val contactName = arguments?.getString("contactName").toString() val contactName = arguments?.getString("contactName").toString()
binding.messageTitle.text = contactName val title = contactName
binding.toolbar.title = title
if (contactKey[1] == '!') {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
val channelNumber = contactKey[0].digitToInt()
model.channels.collect { channels ->
val channelName =
channels.getChannel(channelNumber)?.name ?: "Unknown Channel"
val subtitle = "(ch: $channelNumber - $channelName)"
binding.toolbar.subtitle = subtitle
}
}
}
}
fun sendMessageInputText() { fun sendMessageInputText() {
val str = binding.messageInputText.text.toString().trim() val str = binding.messageInputText.text.toString().trim()
@ -358,12 +389,14 @@ class MessagesFragment : Fragment(), Logging {
button.text = action.name button.text = action.name
button.isEnabled = model.isConnected() button.isEnabled = model.isConnected()
if (action.mode == QuickChatAction.Mode.Instant) { if (action.mode == QuickChatAction.Mode.Instant) {
button.backgroundTintList = ContextCompat.getColorStateList(requireActivity(), R.color.colorMyMsg) button.backgroundTintList =
ContextCompat.getColorStateList(requireActivity(), R.color.colorMyMsg)
} }
button.setOnClickListener { button.setOnClickListener {
if (action.mode == QuickChatAction.Mode.Append) { if (action.mode == QuickChatAction.Mode.Append) {
val originalText = binding.messageInputText.text ?: "" val originalText = binding.messageInputText.text ?: ""
val needsSpace = !originalText.endsWith(' ') && originalText.isNotEmpty() val needsSpace =
!originalText.endsWith(' ') && originalText.isNotEmpty()
val newText = buildString { val newText = buildString {
append(originalText) append(originalText)
if (needsSpace) append(' ') if (needsSpace) append(' ')
@ -421,6 +454,7 @@ class MessagesFragment : Fragment(), Logging {
} }
.show() .show()
} }
R.id.selectAllButton -> { R.id.selectAllButton -> {
// if all selected -> unselect all // if all selected -> unselect all
if (messagesAdapter.selectedList.size == messagesAdapter.messages.size) { if (messagesAdapter.selectedList.size == messagesAdapter.messages.size) {
@ -434,6 +468,7 @@ class MessagesFragment : Fragment(), Logging {
actionMode?.title = messagesAdapter.selectedList.size.toString() actionMode?.title = messagesAdapter.selectedList.size.toString()
messagesAdapter.notifyDataSetChanged() messagesAdapter.notifyDataSetChanged()
} }
R.id.resendButton -> { R.id.resendButton -> {
debug("User clicked resendButton") debug("User clicked resendButton")
val selectedList = messagesAdapter.selectedList val selectedList = messagesAdapter.selectedList
@ -441,7 +476,7 @@ class MessagesFragment : Fragment(), Logging {
selectedList.forEach { selectedList.forEach {
resendText = resendText + it.data.text + System.lineSeparator() resendText = resendText + it.data.text + System.lineSeparator()
} }
if (resendText!="") if (resendText != "")
resendText = resendText.substring(0, resendText.length - 1) resendText = resendText.substring(0, resendText.length - 1)
binding.messageInputText.setText(resendText) binding.messageInputText.setText(resendText)
mode.finish() mode.finish()

Wyświetl plik

@ -10,28 +10,13 @@
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
style="@style/MyToolbar" style="@style/MyToolbar"
android:title="@string/channel_name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" app:layout_constraintHeight_min="?attr/actionBarSize"
android:layout_height="wrap_content"
android:background="@color/toolbarBackground" android:background="@color/toolbarBackground"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="?android:attr/homeAsUpIndicator"> app:navigationIcon="?android:attr/homeAsUpIndicator"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/messageTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/channel_name"
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.MaterialToolbar>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/messageListView" android:id="@+id/messageListView"