From cf9d0c4f092a450882247ca42c93492e493749f9 Mon Sep 17 00:00:00 2001 From: kosyak Date: Mon, 5 Aug 2024 22:34:10 +0200 Subject: [PATCH] show contact status in a separate widget --- .../siacs/conversations/entities/Contact.java | 4 -- .../ui/ContactDetailsActivity.java | 2 + .../ui/adapter/ConversationAdapter.java | 9 +++ .../ui/adapter/ListItemAdapter.java | 12 ++++ .../conversations/ui/adapter/UserAdapter.java | 2 + .../ui/adapter/UserPreviewAdapter.java | 7 ++ .../ui/widget/PresenceIndicator.kt | 64 +++++++++++++++++++ .../siacs/conversations/utils/UIHelper.java | 23 +++++++ .../res/layout/activity_contact_details.xml | 10 +++ src/main/res/layout/contact.xml | 10 +++ src/main/res/layout/conversation_list_row.xml | 10 +++ src/main/res/layout/user_preview.xml | 8 +++ src/main/res/values/dimens.xml | 2 + 13 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 src/main/java/eu/siacs/conversations/ui/widget/PresenceIndicator.kt diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index 7b530300f..6b0554240 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -197,10 +197,6 @@ public class Contact implements ListItem, Blockable { final HashSet tags = new HashSet<>(); tags.addAll(getGroupTags()); - Presence.Status status = getShownStatus(); - if (status != Presence.Status.OFFLINE) { - tags.add(UIHelper.getTagForStatus(context, status)); - } if (isBlocked()) { tags.add(new Tag(context.getString(R.string.blocked), 0xff2e2f3b)); } diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java index 79177eb55..cc7773ad2 100644 --- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -523,6 +523,8 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp AvatarWorkerTask.loadAvatar(contact, binding.detailsContactBadge, R.dimen.avatar_on_details_screen_size); binding.detailsContactBadge.setOnClickListener(this::onBadgeClick); + binding.presenceIndicator.setStatus(contact.getShownStatus()); + binding.detailsContactKeys.removeAllViews(); boolean hasKeys = false; final LayoutInflater inflater = getLayoutInflater(); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index 993b1aa67..4862e0ca1 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -32,6 +32,7 @@ import java.util.Set; import eu.siacs.conversations.R; import eu.siacs.conversations.databinding.ConversationListRowBinding; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Conversational; import eu.siacs.conversations.entities.ListItem; @@ -388,6 +389,14 @@ public class ConversationAdapter viewHolder.binding.conversationName.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, null, null); } + Contact contact = conversation.getContact(); + + if (contact != null) { + viewHolder.binding.presenceIndicator.setStatus(contact.getShownStatus()); + } else { + viewHolder.binding.presenceIndicator.setStatus(null); + } + if (draft != null) { viewHolder.binding.conversationLastmsgImg.setVisibility(View.GONE); viewHolder.binding.conversationLastmsg.setText(draft.getMessage()); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index 5d6d72684..febfb964f 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -17,11 +17,13 @@ import java.util.List; import eu.siacs.conversations.R; import eu.siacs.conversations.databinding.ContactBinding; +import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.ListItem; import eu.siacs.conversations.ui.SettingsActivity; import eu.siacs.conversations.ui.XmppActivity; import eu.siacs.conversations.ui.util.AvatarWorkerTask; import eu.siacs.conversations.ui.util.StyledAttributes; +import eu.siacs.conversations.ui.widget.PresenceIndicator; import eu.siacs.conversations.utils.IrregularUnicodeDetector; import eu.siacs.conversations.xmpp.Jid; @@ -86,6 +88,13 @@ public class ListItemAdapter extends ArrayAdapter { } viewHolder.name.setText(item.getDisplayName()); AvatarWorkerTask.loadAvatar(item, viewHolder.avatar, R.dimen.avatar); + + if (item instanceof Contact) { + viewHolder.presenceIndicator.setStatus(((Contact) item).getShownStatus()); + } else { + viewHolder.presenceIndicator.setStatus(null); + } + return view; } @@ -104,6 +113,8 @@ public class ListItemAdapter extends ArrayAdapter { private ImageView avatar; private FlowLayout tags; + private PresenceIndicator presenceIndicator; + private ViewHolder() { } @@ -114,6 +125,7 @@ public class ListItemAdapter extends ArrayAdapter { viewHolder.jid = binding.contactJid; viewHolder.avatar = binding.contactPhoto; viewHolder.tags = binding.tags; + viewHolder.presenceIndicator = binding.presenceIndicator; binding.getRoot().setTag(viewHolder); return viewHolder; } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/UserAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/UserAdapter.java index de3216908..525fec6f6 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/UserAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/UserAdapter.java @@ -91,9 +91,11 @@ public class UserAdapter extends ListAdapter { final XmppActivity activity = XmppActivity.find(v); if (activity != null) { diff --git a/src/main/java/eu/siacs/conversations/ui/widget/PresenceIndicator.kt b/src/main/java/eu/siacs/conversations/ui/widget/PresenceIndicator.kt new file mode 100644 index 000000000..4704c3ef5 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/ui/widget/PresenceIndicator.kt @@ -0,0 +1,64 @@ +package eu.siacs.conversations.ui.widget + +import android.content.Context +import android.content.res.Resources +import android.graphics.Canvas +import android.graphics.Outline +import android.graphics.Paint +import android.util.AttributeSet +import android.view.View +import android.view.ViewOutlineProvider +import eu.siacs.conversations.entities.Presence +import eu.siacs.conversations.ui.util.StyledAttributes +import eu.siacs.conversations.utils.UIHelper + +class PresenceIndicator : View { + private var paint: Paint = Paint().also { + it.setColor(StyledAttributes.getColor(this.context, androidx.appcompat.R.attr.colorPrimaryDark)) + it.style = Paint.Style.STROKE + it.strokeWidth = 1 * Resources.getSystem().displayMetrics.density + } + + var status: Presence.Status? = null + set(value) { + if (field != value) { + field = value + invalidate() + } + } + + constructor(context: Context?) : super(context) + constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) + constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) + + constructor( + context: Context?, + attrs: AttributeSet?, + defStyleAttr: Int, + defStyleRes: Int + ) : super(context, attrs, defStyleAttr, defStyleRes) + + init { + clipToOutline = true + outlineProvider = object : ViewOutlineProvider() { + override fun getOutline(view: View, outline: Outline) { + outline.setOval(0, 0, view.width, view.height) + } + } + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + + val color: Int? = UIHelper.getColorForStatus(status); + + if (color != null) { + canvas.drawColor(color) + canvas.drawCircle(width / 2f, height / 2f, width / 2f, paint) + } + } +} \ No newline at end of file diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java index 84e4002a6..5680a5e60 100644 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java @@ -7,6 +7,7 @@ import android.text.format.DateUtils; import android.util.Pair; import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; import com.google.common.base.Strings; @@ -608,6 +609,28 @@ public class UIHelper { } } + @Nullable + public static Integer getColorForStatus(Presence.Status status) { + if (status == null) { + return null; + } + + switch (status) { + case CHAT: + return 0xff259b24; + case AWAY: + return 0xffff9800; + case XA: + return 0xfff44336; + case DND: + return 0xfff44336; + case ONLINE: + return 0xff259b24; + default: + return null; + } + } + public static boolean isStatusTag(Context context, ListItem.Tag tag) { String name = tag.getName(); return name.equals(context.getString(R.string.presence_chat)) || diff --git a/src/main/res/layout/activity_contact_details.xml b/src/main/res/layout/activity_contact_details.xml index e9117daf1..dfe72d6b9 100644 --- a/src/main/res/layout/activity_contact_details.xml +++ b/src/main/res/layout/activity_contact_details.xml @@ -42,6 +42,16 @@ android:layout_alignParentTop="true" android:scaleType="centerCrop" /> + + + + + + + + diff --git a/src/main/res/values/dimens.xml b/src/main/res/values/dimens.xml index a6544901a..78ca44de0 100644 --- a/src/main/res/values/dimens.xml +++ b/src/main/res/values/dimens.xml @@ -80,4 +80,6 @@ 30dp 8dp + 12dp + 2dp