88 *
99 * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
1010 */
11-
12- package com.owncloud.android.ui ;
11+ package com.owncloud.android.ui
12+
13+ import android.content.Context
14+ import android.content.res.Resources
15+ import android.graphics.drawable.Drawable
16+ import android.util.AttributeSet
17+ import android.widget.ImageView
18+ import android.widget.RelativeLayout
19+ import androidx.annotation.Px
20+ import androidx.core.content.ContextCompat
21+ import androidx.core.content.res.ResourcesCompat
22+ import androidx.core.graphics.drawable.DrawableCompat
23+ import com.nextcloud.android.common.ui.theme.utils.ColorRole
24+ import com.nextcloud.client.account.User
25+ import com.nextcloud.utils.GlideHelper.loadCircularBitmapIntoImageView
26+ import com.owncloud.android.R
27+ import com.owncloud.android.lib.common.utils.Log_OC
28+ import com.owncloud.android.lib.resources.shares.ShareType
29+ import com.owncloud.android.lib.resources.shares.ShareeUser
30+ import com.owncloud.android.utils.DisplayUtils
31+ import com.owncloud.android.utils.DisplayUtils.AvatarGenerationListener
32+ import com.owncloud.android.utils.theme.ViewThemeUtils
33+ import kotlin.math.min
1334
1435import android.content.Context;
1536import android.content.res.Resources;
@@ -29,7 +50,8 @@ import com.owncloud.android.lib.resources.shares.ShareeUser;
2950import com.owncloud.android.utils.DisplayUtils;
3051import com.owncloud.android.utils.theme.ViewThemeUtils;
3152
32- import java.util.List;
53+ @Px
54+ private val avatarBorderSize: Int = DisplayUtils .convertDpToPixel(2f , context)
3355
3456import androidx.annotation.NonNull;
3557import androidx.annotation.Px;
@@ -39,129 +61,113 @@ import androidx.core.graphics.drawable.DrawableCompat;
3961import androidx.core.graphics.drawable.RoundedBitmapDrawable;
4062import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
4163
42- public class AvatarGroupLayout extends RelativeLayout implements DisplayUtils .AvatarGenerationListener {
43- private static final String TAG = AvatarGroupLayout .class .getSimpleName();
44-
45- private final static int MAX_AVATAR_COUNT = 3 ;
46-
47- private final Drawable borderDrawable;
48- @Px private final int avatarSize;
49- @Px private final int avatarBorderSize;
50- @Px private final int overlapPx;
51-
52- public AvatarGroupLayout (Context context) {
53- this (context, null );
64+ init {
65+ checkNotNull(borderDrawable)
66+ DrawableCompat .setTint(borderDrawable, ContextCompat .getColor(context, R .color.bg_default))
5467 }
5568
56- public AvatarGroupLayout (Context context, AttributeSet attrs) {
57- this (context, attrs, 0 );
58- }
69+ @Suppress(" LongMethod" , " TooGenericExceptionCaught" )
70+ fun setAvatars (user : User , sharees : MutableList <ShareeUser >, viewThemeUtils : ViewThemeUtils ) {
71+ val context = getContext()
72+ removeAllViews()
73+ var avatarLayoutParams: LayoutParams ?
74+ val shareeSize = min(sharees.size, MAX_AVATAR_COUNT )
75+ val resources = context.resources
76+ val avatarRadius = resources.getDimension(R .dimen.list_item_avatar_icon_radius)
77+ var sharee: ShareeUser
78+
79+ var avatarCount = 0
80+ while (avatarCount < shareeSize) {
81+ avatarLayoutParams = LayoutParams (avatarSize, avatarSize).apply {
82+ setMargins(0 , 0 , avatarCount * overlapPx, 0 )
83+ addRule(ALIGN_PARENT_RIGHT )
84+ }
5985
60- public AvatarGroupLayout (Context context, AttributeSet attrs, int defStyleAttr) {
61- this (context, attrs, defStyleAttr, 0 );
62- }
86+ val avatar = ImageView (context).apply {
87+ layoutParams = avatarLayoutParams
88+ setPadding(avatarBorderSize, avatarBorderSize, avatarBorderSize, avatarBorderSize)
89+ background = borderDrawable
90+ }
6391
64- public AvatarGroupLayout (Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
65- super (context, attrs, defStyleAttr, defStyleRes);
66- avatarBorderSize = DisplayUtils .convertDpToPixel(2 , context);
67- avatarSize = DisplayUtils .convertDpToPixel(40 , context);
68- overlapPx = DisplayUtils .convertDpToPixel(24 , context);
69- borderDrawable = ContextCompat .getDrawable(context, R .drawable.round_bgnd);
70- assert borderDrawable != null ;
71- DrawableCompat .setTint(borderDrawable, ContextCompat .getColor(context, R .color.bg_default));
72- }
92+ addView(avatar)
93+ avatar.requestLayout()
7394
74- public void setAvatars(@NonNull User user,
75- @NonNull List <ShareeUser > sharees,
76- final ViewThemeUtils viewThemeUtils) {
77- @NonNull Context context = getContext();
78- removeAllViews();
79- RelativeLayout .LayoutParams avatarLayoutParams;
80- int avatarCount;
81- int shareeSize = Math .min(sharees.size(), MAX_AVATAR_COUNT );
82-
83- Resources resources = context.getResources();
84- float avatarRadius = resources.getDimension(R .dimen.list_item_avatar_icon_radius);
85- ShareeUser sharee;
86-
87- for (avatarCount = 0 ; avatarCount < shareeSize; avatarCount++ ) {
88- avatarLayoutParams = new RelativeLayout .LayoutParams (avatarSize, avatarSize);
89- avatarLayoutParams.setMargins(0 , 0 , avatarCount * overlapPx, 0 );
90- avatarLayoutParams.addRule(RelativeLayout .ALIGN_PARENT_RIGHT );
91-
92- final ImageView avatar = new ImageView (context);
93- avatar.setLayoutParams(avatarLayoutParams);
94- avatar.setPadding(avatarBorderSize, avatarBorderSize, avatarBorderSize, avatarBorderSize);
95-
96- avatar.setBackground(borderDrawable);
97- addView(avatar);
98- avatar.requestLayout();
99-
100- if (avatarCount == 0 && sharees.size() > MAX_AVATAR_COUNT ) {
101- avatar.setImageResource(R .drawable.ic_people);
102- viewThemeUtils.platform.tintTextDrawable(context, avatar.getDrawable());
95+ if (avatarCount == 0 && sharees.size > MAX_AVATAR_COUNT ) {
96+ avatar.setImageResource(R .drawable.ic_people)
97+ viewThemeUtils.platform.tintDrawable(context, avatar.drawable, ColorRole .ON_SURFACE )
10398 } else {
104- sharee = sharees.get(avatarCount);
105- switch (sharee.getShareType()) {
106- case GROUP :
107- case EMAIL :
108- case ROOM :
109- case CIRCLE :
110- viewThemeUtils.files.createAvatar(sharee.getShareType(), avatar, context);
111- break ;
112- case FEDERATED :
113- showFederatedShareAvatar(context,
114- sharee.getUserId(),
115- avatarRadius,
116- resources,
117- avatar,
118- viewThemeUtils);
119- break ;
120- default:
121- avatar.setTag(sharee);
122- DisplayUtils .setAvatar(user,
123- sharee.getUserId(),
124- sharee.getDisplayName(),
125- this ,
126- avatarRadius,
127- resources,
128- avatar,
129- context);
130- break ;
99+ sharee = sharees[avatarCount]
100+ when (sharee.shareType) {
101+ ShareType .GROUP , ShareType .EMAIL , ShareType .ROOM , ShareType .CIRCLE ->
102+ viewThemeUtils.files.createAvatar(
103+ sharee.shareType,
104+ avatar,
105+ context
106+ )
107+
108+ ShareType .FEDERATED -> showFederatedShareAvatar(
109+ context,
110+ sharee.userId!! ,
111+ avatarRadius,
112+ resources,
113+ avatar,
114+ viewThemeUtils
115+ )
116+
117+ else -> {
118+ avatar.tag = sharee
119+ DisplayUtils .setAvatar(
120+ user,
121+ sharee.userId!! ,
122+ sharee.displayName,
123+ this ,
124+ avatarRadius,
125+ resources,
126+ avatar,
127+ context
128+ )
129+ }
131130 }
132131 }
132+ avatarCount++
133133 }
134134
135135 // Recalculate container size based on avatar count
136- int size = overlapPx * (avatarCount - 1 ) + avatarSize;
137- ViewGroup . LayoutParams rememberParam = getLayoutParams();
138- rememberParam.width = size;
139- setLayoutParams( rememberParam);
136+ val size = overlapPx * (avatarCount - 1 ) + avatarSize
137+ val rememberParam = layoutParams
138+ rememberParam.width = size
139+ layoutParams = rememberParam
140140 }
141141
142- private void showFederatedShareAvatar(Context context,
143- String user,
144- float avatarRadius,
145- Resources resources,
146- ImageView avatar,
147- ViewThemeUtils viewThemeUtils) {
142+ @Suppress(" TooGenericExceptionCaught" )
143+ private fun showFederatedShareAvatar (
144+ context : Context ,
145+ user : String ,
146+ avatarRadius : Float ,
147+ resources : Resources ,
148+ avatar : ImageView ,
149+ viewThemeUtils : ViewThemeUtils
150+ ) {
148151 // maybe federated share
149- String [] split = user.split(" @" );
150- String userId = split[0 ];
151- String server = split[1 ];
152+ val split = user.split(" @" .toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
153+ val userId: String? = split[0 ]
154+ val server = split[1 ]
152155
153- String url = " https://" + server + " /index.php/avatar/" + userId + " /" +
154- resources.getInteger(R .integer.file_avatar_px);
155-
156- Drawable placeholder;
156+ val url = " https://" + server + " /index.php/avatar/" + userId + " /" +
157+ resources.getInteger(R .integer.file_avatar_px)
158+ var placeholder: Drawable ?
157159 try {
158- placeholder = TextDrawable .createAvatarByUserId(userId, avatarRadius);
159- } catch (Exception e) {
160- Log_OC .e(TAG , " Error calculating RGB value for active account icon." , e);
161- placeholder = viewThemeUtils.platform.colorDrawable(ResourcesCompat .getDrawable(resources,
162- R .drawable.account_circle_white,
163- null ),
164- ContextCompat .getColor(context, R .color.black));
160+ placeholder = TextDrawable .createAvatarByUserId(userId, avatarRadius)
161+ } catch (e: Exception ) {
162+ Log_OC .e(TAG , " Error calculating RGB value for active account icon." , e)
163+ placeholder = viewThemeUtils.platform.colorDrawable(
164+ ResourcesCompat .getDrawable(
165+ resources,
166+ R .drawable.account_circle_white,
167+ null
168+ )!! ,
169+ ContextCompat .getColor(context, R .color.black)
170+ )
165171 }
166172
167173 avatar.setTag(null );
@@ -180,13 +186,15 @@ public class AvatarGroupLayout extends RelativeLayout implements DisplayUtils.Av
180186 });
181187 }
182188
183- @Override
184- public void avatarGenerated(Drawable avatarDrawable, Object callContext) {
185- ((ImageView ) callContext).setImageDrawable(avatarDrawable);
189+ override fun avatarGenerated (avatarDrawable : Drawable ? , callContext : Any ) {
190+ (callContext as ImageView ).setImageDrawable(avatarDrawable)
186191 }
187192
188- @Override
189- public boolean shouldCallGeneratedCallback(String tag, Object callContext) {
190- return ((ImageView ) callContext).getTag().equals(tag);
193+ override fun shouldCallGeneratedCallback (tag : String? , callContext : Any ): Boolean =
194+ (callContext as ImageView ).tag == tag
195+
196+ companion object {
197+ private val TAG : String = AvatarGroupLayout ::class .java.simpleName
198+ private const val MAX_AVATAR_COUNT = 3
191199 }
192200}
0 commit comments