From 9a7ef3ca6c4ea443afa63dde013ea3064bba8e2e Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Mon, 1 Aug 2022 23:57:59 +0200 Subject: [PATCH] theme generic avatars for Material 3 Signed-off-by: Andy Scherzinger --- .../talk/adapters/items/ContactItem.java | 19 +++++++- .../talk/adapters/items/ConversationItem.java | 38 +++++++++++----- .../items/MentionAutocompleteItem.java | 16 ++++++- .../talk/adapters/items/ParticipantItem.java | 24 +++++++++-- .../controllers/ConversationInfoController.kt | 35 ++++++++++++--- .../MentionAutocompletePresenter.java | 7 ++- .../nextcloud/talk/ui/theme/ViewThemeUtils.kt | 32 ++++++++++++++ .../res/drawable-v24/ic_avatar_background.xml | 43 +++++++++++++++++++ .../main/res/drawable/ic_avatar_document.xml | 31 +++++++++++++ app/src/main/res/drawable/ic_avatar_group.xml | 31 +++++++++++++ app/src/main/res/drawable/ic_avatar_link.xml | 31 +++++++++++++ app/src/main/res/drawable/ic_avatar_mail.xml | 31 +++++++++++++ 12 files changed, 313 insertions(+), 25 deletions(-) create mode 100644 app/src/main/res/drawable-v24/ic_avatar_background.xml create mode 100644 app/src/main/res/drawable/ic_avatar_document.xml create mode 100644 app/src/main/res/drawable/ic_avatar_group.xml create mode 100644 app/src/main/res/drawable/ic_avatar_link.xml create mode 100644 app/src/main/res/drawable/ic_avatar_mail.xml diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/ContactItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/ContactItem.java index 5090bc761..2e5e8523f 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/ContactItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/ContactItem.java @@ -25,6 +25,7 @@ package com.nextcloud.talk.adapters.items; import android.annotation.SuppressLint; +import android.os.Build; import android.text.TextUtils; import android.view.View; @@ -162,11 +163,25 @@ public class ContactItem extends AbstractFlexibleItem= Build.VERSION_CODES.O) { + holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView, + R.drawable.ic_avatar_group))); + } else { + holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group); + } } else if (participant.getCalculatedActorType() == Participant.ActorType.EMAILS) { - holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_mail); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView, + R.drawable.ic_avatar_mail))); + } else { + holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_mail); + } } else if ( participant.getCalculatedActorType() == Participant.ActorType.GUESTS || diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java index a97cc6201..9779ac335 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java @@ -264,9 +264,15 @@ public class ConversationItem extends AbstractFlexibleItem= Build.VERSION_CODES.O) { + holder.binding.dialogAvatar.setImageDrawable( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.dialogAvatar, + R.drawable.ic_avatar_document))); + } else { + holder.binding.dialogAvatar.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_circular_document)); + } break; default: break; @@ -275,6 +281,7 @@ public class ConversationItem extends AbstractFlexibleItem= Build.VERSION_CODES.O) { + Drawable[] layers = new Drawable[2]; layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background); layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground); @@ -306,16 +313,27 @@ public class ConversationItem extends AbstractFlexibleItem= Build.VERSION_CODES.O) { + holder.binding.dialogAvatar.setImageDrawable( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.dialogAvatar, + R.drawable.ic_avatar_group))); + } else { + holder.binding.dialogAvatar.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_circular_group)); + } break; case ROOM_PUBLIC_CALL: - holder.binding.dialogAvatar.setImageDrawable( - ContextCompat.getDrawable(context, - R.drawable.ic_circular_link)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + holder.binding.dialogAvatar.setImageDrawable( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.dialogAvatar, + R.drawable.ic_avatar_link))); + } else { + holder.binding.dialogAvatar.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_circular_link)); + } break; default: holder.binding.dialogAvatar.setVisibility(View.GONE); diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java index ab1ea6749..f5c8a4c55 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java @@ -26,6 +26,7 @@ package com.nextcloud.talk.adapters.items; import android.annotation.SuppressLint; import android.content.Context; +import android.os.Build; import android.view.View; import com.facebook.drawee.backends.pipeline.Fresco; @@ -36,6 +37,7 @@ import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.models.json.mention.Mention; import com.nextcloud.talk.models.json.status.StatusType; import com.nextcloud.talk.ui.StatusDrawable; +import com.nextcloud.talk.ui.theme.ViewThemeUtils; import com.nextcloud.talk.utils.ApiUtils; import com.nextcloud.talk.utils.DisplayUtils; @@ -67,11 +69,12 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem= Build.VERSION_CODES.O) { + holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView, + R.drawable.ic_avatar_group))); + } else { + holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group); + } } } else { String avatarId = objectId; diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java index e3e7c61f4..ba93b67cc 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java @@ -27,6 +27,7 @@ package com.nextcloud.talk.adapters.items; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; +import android.os.Build; import android.text.TextUtils; import android.view.View; @@ -41,6 +42,7 @@ import com.nextcloud.talk.models.json.participants.Participant; import com.nextcloud.talk.models.json.participants.Participant.InCallFlags; import com.nextcloud.talk.models.json.status.StatusType; import com.nextcloud.talk.ui.StatusDrawable; +import com.nextcloud.talk.ui.theme.ViewThemeUtils; import com.nextcloud.talk.utils.ApiUtils; import com.nextcloud.talk.utils.DisplayUtils; @@ -64,14 +66,16 @@ public class ParticipantItem extends AbstractFlexibleItem= Build.VERSION_CODES.O) { + holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView, + R.drawable.ic_avatar_group))); + } else { + holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group); + } } else if (participant.getCalculatedActorType() == Participant.ActorType.EMAILS) { - holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_mail); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView, + R.drawable.ic_avatar_mail))); + } else { + holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_mail); + } } else if (participant.getCalculatedActorType() == Participant.ActorType.GUESTS || Participant.ParticipantType.GUEST.equals(participant.getType()) || Participant.ParticipantType.GUEST_MODERATOR.equals(participant.getType())) { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt index 6c9273789..59e82d425 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt @@ -30,6 +30,7 @@ import android.annotation.SuppressLint import android.content.Intent import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable +import android.os.Build import android.os.Bundle import android.os.Parcelable import android.text.TextUtils @@ -433,7 +434,7 @@ class ConversationInfoController(args: Bundle) : for (i in participants.indices) { participant = participants[i] - userItem = ParticipantItem(router.activity, participant, conversationUser) + userItem = ParticipantItem(router.activity, participant, conversationUser, viewThemeUtils) if (participant.sessionId != null) { userItem.isOnline = !participant.sessionId.equals("0") } else { @@ -785,12 +786,32 @@ class ConversationInfoController(args: Bundle) : .build() binding.avatarImage.controller = draweeController } - Conversation.ConversationType.ROOM_GROUP_CALL -> binding.avatarImage.hierarchy.setPlaceholderImage( - R.drawable.ic_circular_group - ) - Conversation.ConversationType.ROOM_PUBLIC_CALL -> binding.avatarImage.hierarchy.setPlaceholderImage( - R.drawable.ic_circular_link - ) + Conversation.ConversationType.ROOM_GROUP_CALL -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + binding.avatarImage.hierarchy.setPlaceholderImage( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(binding.avatarImage, R.drawable.ic_avatar_group) + ) + ) + } else { + binding.avatarImage.hierarchy.setPlaceholderImage( + R.drawable.ic_circular_group + ) + } + } + Conversation.ConversationType.ROOM_PUBLIC_CALL -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + binding.avatarImage.hierarchy.setPlaceholderImage( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(binding.avatarImage, R.drawable.ic_avatar_link) + ) + ) + } else { + binding.avatarImage.hierarchy.setPlaceholderImage( + R.drawable.ic_circular_link + ) + } + } Conversation.ConversationType.ROOM_SYSTEM -> { val layers = arrayOfNulls(2) layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background) diff --git a/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java b/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java index 977e0f51e..ada79fd7c 100644 --- a/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java +++ b/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java @@ -36,6 +36,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.models.json.mention.Mention; import com.nextcloud.talk.models.json.mention.MentionOverall; +import com.nextcloud.talk.ui.theme.ViewThemeUtils; import com.nextcloud.talk.users.UserManager; import com.nextcloud.talk.utils.ApiUtils; import com.otaliastudios.autocomplete.RecyclerViewPresenter; @@ -69,6 +70,9 @@ public class MentionAutocompletePresenter extends RecyclerViewPresenter @Inject UserManager userManager; + @Inject + ViewThemeUtils viewThemeUtils; + private User currentUser; private FlexibleAdapter adapter; private Context context; @@ -150,7 +154,8 @@ public class MentionAutocompletePresenter extends RecyclerViewPresenter new MentionAutocompleteItem( mention, currentUser, - context)); + context, + viewThemeUtils)); } if (adapter.getItemCount() != 0) { diff --git a/app/src/main/java/com/nextcloud/talk/ui/theme/ViewThemeUtils.kt b/app/src/main/java/com/nextcloud/talk/ui/theme/ViewThemeUtils.kt index 3b3d4d8c2..ef11077d2 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/theme/ViewThemeUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/theme/ViewThemeUtils.kt @@ -21,12 +21,15 @@ package com.nextcloud.talk.ui.theme +import android.annotation.TargetApi import android.app.Activity import android.content.Context import android.content.res.ColorStateList import android.graphics.Color import android.graphics.PorterDuff import android.graphics.drawable.Drawable +import android.graphics.drawable.LayerDrawable +import android.os.Build import android.view.View import android.view.ViewGroup import android.widget.CheckBox @@ -39,6 +42,7 @@ import android.widget.RadioButton import android.widget.SeekBar import android.widget.TextView import androidx.annotation.ColorInt +import androidx.annotation.DrawableRes import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView.SearchAutoComplete @@ -608,6 +612,34 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private } } + @TargetApi(Build.VERSION_CODES.O) + fun themePlaceholderAvatar(avatar: View, @DrawableRes foreground: Int): Drawable? { + var drawable: LayerDrawable? = null + withScheme(avatar) { scheme -> + val layers = arrayOfNulls(2) + layers[0] = ContextCompat.getDrawable(avatar.context, R.drawable.ic_avatar_background) + layers[0]?.setTint(scheme.surfaceVariant) + layers[1] = ContextCompat.getDrawable(avatar.context, foreground) + layers[1]?.setTint(scheme.onSurfaceVariant) + drawable = LayerDrawable(layers) + } + + return drawable + } + + private fun progressColor(context: Context, color: Int): Int { + val hsl = FloatArray(HSL_SIZE) + ColorUtils.RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), hsl) + + if (isDarkMode(context)) { + hsl[INDEX_LIGHTNESS] = LIGHTNESS_DARK_THEME + } else { + hsl[INDEX_LIGHTNESS] = LIGHTNESS_LIGHT_THEME + } + + return ColorUtils.HSLToColor(hsl) + } + private fun calculateDisabledColor(color: Int, opacity: Float): Int { return Color.argb( (Color.alpha(color) * opacity).roundToInt(), diff --git a/app/src/main/res/drawable-v24/ic_avatar_background.xml b/app/src/main/res/drawable-v24/ic_avatar_background.xml new file mode 100644 index 000000000..84b02c9cb --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_avatar_background.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_avatar_document.xml b/app/src/main/res/drawable/ic_avatar_document.xml new file mode 100644 index 000000000..5488941ab --- /dev/null +++ b/app/src/main/res/drawable/ic_avatar_document.xml @@ -0,0 +1,31 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_avatar_group.xml b/app/src/main/res/drawable/ic_avatar_group.xml new file mode 100644 index 000000000..3dcdb9e9b --- /dev/null +++ b/app/src/main/res/drawable/ic_avatar_group.xml @@ -0,0 +1,31 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_avatar_link.xml b/app/src/main/res/drawable/ic_avatar_link.xml new file mode 100644 index 000000000..c4890f82a --- /dev/null +++ b/app/src/main/res/drawable/ic_avatar_link.xml @@ -0,0 +1,31 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_avatar_mail.xml b/app/src/main/res/drawable/ic_avatar_mail.xml new file mode 100644 index 000000000..cbbfce6bf --- /dev/null +++ b/app/src/main/res/drawable/ic_avatar_mail.xml @@ -0,0 +1,31 @@ + + + + +