diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt index 7222cfc4..ebd378a0 100644 --- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt +++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt @@ -806,7 +806,8 @@ class MainActivity : AppCompatActivity(), Logging, // Init our messages table with the service's record of past text messages (ignore all other message types) val msgs = service.oldMessages.filter { p -> p.dataType == Portnums.PortNum.TEXT_MESSAGE_APP_VALUE } - debug("Service provided ${msgs.size} messages") + debug("Service provided ${msgs.size} messages and myNodeNum ${service.myNodeInfo?.myNodeNum}") + model.myNodeInfo.value = service.myNodeInfo model.messagesState.setMessages(msgs) val connectionState = MeshService.ConnectionState.valueOf(service.connectionState()) 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 dbec8b65..92c1d0d7 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MessagesFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MessagesFragment.kt @@ -8,6 +8,7 @@ import android.view.inputmethod.EditorInfo import android.widget.EditText import android.widget.ImageView import android.widget.TextView +import androidx.cardview.widget.CardView import androidx.fragment.app.activityViewModels import androidx.lifecycle.Observer import androidx.recyclerview.widget.LinearLayoutManager @@ -15,6 +16,7 @@ import androidx.recyclerview.widget.RecyclerView import com.geeksville.android.Logging import com.geeksville.mesh.DataPacket import com.geeksville.mesh.MessageStatus +import com.geeksville.mesh.NodeInfo import com.geeksville.mesh.R import com.geeksville.mesh.databinding.AdapterMessageLayoutBinding import com.geeksville.mesh.databinding.MessagesFragmentBinding @@ -22,6 +24,7 @@ import com.geeksville.mesh.model.UIViewModel import com.geeksville.mesh.service.MeshService import com.google.android.material.chip.Chip import java.text.DateFormat +import java.text.ParseException import java.util.* // Allows usage like email.on(EditorInfo.IME_ACTION_NEXT, { confirm() }) @@ -39,20 +42,35 @@ fun EditText.on(actionId: Int, func: () -> Unit) { class MessagesFragment : ScreenFragment("Messages"), Logging { private var _binding: MessagesFragmentBinding? = null + // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! private val model: UIViewModel by activityViewModels() - private val dateTimeFormat: DateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM) + 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 one_day = 60*60*24*100L + if (System.currentTimeMillis() - time.time > one_day) { + return dateTimeFormat.format(time) + } else return timeFormat.format(time) + } + // Provide a direct reference to each of the views within a data item // Used to cache the views within the item layout for fast access - class ViewHolder(itemView: AdapterMessageLayoutBinding) : RecyclerView.ViewHolder(itemView.root) { + class ViewHolder(itemView: AdapterMessageLayoutBinding) : + RecyclerView.ViewHolder(itemView.root) { val username: Chip = itemView.username val messageText: TextView = itemView.messageText val messageTime: TextView = itemView.messageTime val messageStatusIcon: ImageView = itemView.messageStatusIcon + val card: CardView = itemView.Card } private val messagesAdapter = object : RecyclerView.Adapter() { @@ -122,14 +140,32 @@ class MessagesFragment : ScreenFragment("Messages"), Logging { */ override fun onBindViewHolder(holder: ViewHolder, position: Int) { val msg = messages[position] - val nodes = model.nodeDB.nodes.value!! - - // If we can't find the sender, just use the ID val node = nodes.get(msg.from) - val user = node?.user - holder.username.text = user?.shortName ?: msg.from + // Determine if this is my message (originated on this device). + val isMe = model.myNodeInfo.value?.myNodeNum == node?.num + // Set cardview offset and color. + val marginParams = holder.card.layoutParams as ViewGroup.MarginLayoutParams + val messageOffset = resources.getDimensionPixelOffset(R.dimen.message_offset) + if (isMe) { + marginParams.leftMargin = messageOffset + marginParams.rightMargin = 0 + holder.card.setCardBackgroundColor(resources.getColor(R.color.colorMyMsg)) + } else { + marginParams.rightMargin = messageOffset + marginParams.leftMargin = 0 + holder.card.setCardBackgroundColor(resources.getColor(R.color.colorMsg)) + } + // Hide the username chip for my messages + if (isMe) { + holder.username.visibility = View.GONE + } else { + holder.username.visibility = View.VISIBLE + // If we can't find the sender, just use the ID + val user = node?.user + holder.username.text = user?.shortName ?: msg.from + } if (msg.errorMessage != null) { // FIXME, set the style to show a red error message holder.messageText.text = msg.errorMessage @@ -137,7 +173,7 @@ class MessagesFragment : ScreenFragment("Messages"), Logging { holder.messageText.text = msg.text } - holder.messageTime.text = dateTimeFormat.format(Date(msg.time)) + holder.messageTime.text = getShortDateTime(Date(msg.time)) val icon = when (msg.status) { MessageStatus.QUEUED -> R.drawable.ic_twotone_cloud_upload_24 @@ -150,6 +186,7 @@ class MessagesFragment : ScreenFragment("Messages"), Logging { if (icon != null) { holder.messageStatusIcon.setImageResource(icon) holder.messageStatusIcon.visibility = View.VISIBLE + } else holder.messageStatusIcon.visibility = View.INVISIBLE } diff --git a/app/src/main/res/layout/adapter_message_layout.xml b/app/src/main/res/layout/adapter_message_layout.xml index 51064e3c..6a464893 100644 --- a/app/src/main/res/layout/adapter_message_layout.xml +++ b/app/src/main/res/layout/adapter_message_layout.xml @@ -1,61 +1,68 @@ + android:contentDescription="Message delivery status"> - + android:layout_height="match_parent" + android:layout_marginEnd="@dimen/message_offset" + app:cardBackgroundColor="@color/colorMsg" + app:cardCornerRadius="12dp" + app:cardElevation="2dp" + app:cardUseCompatPadding="true"> - + - + - + - + - + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 898bcdd5..083caace 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -3,4 +3,6 @@ #3700B3 #3700B3 #D81B60 + #07000000 + #403700B3 diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 59a0b0c4..0aefc338 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -1,3 +1,4 @@ 16dp + 64dp