diff --git a/app/src/main/java/com/geeksville/mesh/ui/ContactsFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/ContactsFragment.kt index b3ba69892..af6fca96d 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/ContactsFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/ContactsFragment.kt @@ -21,7 +21,6 @@ import com.geeksville.mesh.model.Channel import com.geeksville.mesh.model.UIViewModel import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint -import java.text.DateFormat import java.util.* @AndroidEntryPoint @@ -48,19 +47,6 @@ class ContactsFragment : ScreenFragment("Messages"), Logging { private val contactsAdapter = object : RecyclerView.Adapter() { - private val dateTimeFormat: DateFormat = - DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT) - private val timeFormat: DateFormat = - DateFormat.getTimeInstance(DateFormat.SHORT) - - private fun getShortDateTime(time: Date): String { - // return time if within 24 hours, otherwise date/time - val oneDayMsec = 60 * 60 * 24 * 1000L - return if (System.currentTimeMillis() - time.time > oneDayMsec) { - dateTimeFormat.format(time) - } else timeFormat.format(time) - } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val inflater = LayoutInflater.from(requireContext()) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MessagesFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MessagesFragment.kt index f151ec670..ca689491d 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MessagesFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MessagesFragment.kt @@ -33,6 +33,17 @@ import dagger.hilt.android.AndroidEntryPoint import java.text.DateFormat import java.util.* +// return time if within 24 hours, otherwise date/time +internal fun getShortDateTime(date: Date): String { + val isWithin24Hours = System.currentTimeMillis() - date.time <= 24 * 60 * 60 * 1000L + + return if (isWithin24Hours) { + DateFormat.getTimeInstance(DateFormat.SHORT).format(date) + } else { + DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(date) + } +} + @AndroidEntryPoint class MessagesFragment : Fragment(), Logging { @@ -58,19 +69,6 @@ class MessagesFragment : Fragment(), Logging { private val messagesAdapter = object : RecyclerView.Adapter() { - private val dateTimeFormat: DateFormat = - DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT) - private val timeFormat: DateFormat = - DateFormat.getTimeInstance(DateFormat.SHORT) - - private fun getShortDateTime(time: Date): String { - // return time if within 24 hours, otherwise date/time - val oneDayMsec = 60 * 60 * 24 * 1000L - return if (System.currentTimeMillis() - time.time > oneDayMsec) { - dateTimeFormat.format(time) - } else timeFormat.format(time) - } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val inflater = LayoutInflater.from(requireContext()) @@ -83,6 +81,11 @@ class MessagesFragment : Fragment(), Logging { var messages = listOf() var selectedList = ArrayList() + val layoutManager get() = binding.messageListView.layoutManager as LinearLayoutManager + + fun scrollToBottom() { + if (itemCount > 0) layoutManager.scrollToPosition(itemCount - 1) + } override fun getItemCount(): Int = messages.size @@ -168,7 +171,7 @@ class MessagesFragment : Fragment(), Logging { } holder.itemView.setOnLongClickListener { - clickItem(holder) + clickItem(position) if (actionMode == null) { actionMode = (activity as AppCompatActivity).startSupportActionMode(actionModeCallback) @@ -176,7 +179,7 @@ class MessagesFragment : Fragment(), Logging { true } holder.itemView.setOnClickListener { - if (actionMode != null) clickItem(holder) + if (actionMode != null) clickItem(position) } if (selectedList.contains(packet)) { @@ -194,12 +197,10 @@ class MessagesFragment : Fragment(), Logging { } } - private fun clickItem(holder: ViewHolder) { - val position = holder.bindingAdapterPosition - if (!selectedList.contains(messages[position])) { - selectedList.add(messages[position]) - } else { - selectedList.remove(messages[position]) + private fun clickItem(position: Int) { + val message = messages[position] + selectedList.apply { + if (contains(message)) remove(message) else add(message) } if (selectedList.isEmpty()) { // finish action mode when no items selected @@ -213,12 +214,14 @@ class MessagesFragment : Fragment(), Logging { /// Called when our node DB changes fun onMessagesChanged(messages: List) { + val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition() + val shouldScrollToBottom = + lastVisibleItemPosition <= 0 || lastVisibleItemPosition == itemCount - 1 + this.messages = messages notifyDataSetChanged() // FIXME, this is super expensive and redraws all messages - // scroll to the last line - if (itemCount != 0) - binding.messageListView.scrollToPosition(itemCount - 1) + if (shouldScrollToBottom) scrollToBottom() } } @@ -242,25 +245,24 @@ class MessagesFragment : Fragment(), Logging { parentFragmentManager.popBackStack() } + fun sendMessageInputText() { + val str = binding.messageInputText.text.toString().trim() + if (str.isNotEmpty()) { + model.sendMessage(str) + messagesAdapter.scrollToBottom() + } + binding.messageInputText.setText("") // blow away the string the user just entered + // requireActivity().hideKeyboard() + } + binding.sendButton.setOnClickListener { debug("User clicked sendButton") - - val str = binding.messageInputText.text.toString().trim() - if (str.isNotEmpty()) - model.sendMessage(str) - binding.messageInputText.setText("") // blow away the string the user just entered - - // requireActivity().hideKeyboard() + sendMessageInputText() } binding.messageInputText.onEditorAction(EditorInfo.IME_ACTION_SEND) { debug("received IME_ACTION_SEND") - - val str = binding.messageInputText.text.toString().trim() - if (str.isNotEmpty()) model.sendMessage(str) - binding.messageInputText.setText("") // blow away the string the user just entered - - // requireActivity().hideKeyboard() + sendMessageInputText() } binding.messageListView.adapter = messagesAdapter @@ -269,6 +271,7 @@ class MessagesFragment : Fragment(), Logging { binding.messageListView.layoutManager = layoutManager model.messages.observe(viewLifecycleOwner) { + if (it.isNotEmpty() && it.first().contact_key != model.contactKey.value) return@observe debug("New messages received: ${it.size}") messagesAdapter.onMessagesChanged(it) } @@ -314,6 +317,7 @@ class MessagesFragment : Fragment(), Logging { binding.messageInputText.setSelection(newText.length) } else { model.sendMessage(action.message) + messagesAdapter.scrollToBottom() } } binding.quickChatLayout.addView(button)