diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java index 19a0b9d4b..5fc9ab7f2 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java @@ -4,7 +4,7 @@ * @author Mario Danic * @author Andy Scherzinger * Copyright (C) 2022 Andy Scherzinger - * Copyright (C) 2017 Mario Danic (mario@lovelyhq.com) + * Copyright (C) 2017 Mario Danic * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -78,7 +78,6 @@ public class AdvancedUserItem extends AbstractFlexibleItem - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.nextcloud.talk.adapters.items; - -import android.graphics.drawable.Drawable; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.style.ForegroundColorSpan; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; -import androidx.annotation.Nullable; -import butterknife.BindView; -import butterknife.ButterKnife; -import com.nextcloud.talk.R; -import com.nextcloud.talk.application.NextcloudTalkApplication; -import eu.davidea.flexibleadapter.FlexibleAdapter; -import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; -import eu.davidea.flexibleadapter.items.IFlexible; -import eu.davidea.viewholders.FlexibleViewHolder; - -import java.util.List; - -public class AppItem extends AbstractFlexibleItem { - private String title; - private String packageName; - private String name; - @Nullable - private Drawable drawable; - - public AppItem(String title, String packageName, String name, @Nullable Drawable drawable) { - this.title = title; - this.packageName = packageName; - this.name = name; - this.drawable = drawable; - } - - @Override - public boolean equals(Object o) { - if (o instanceof AppItem) { - AppItem inItem = (AppItem) o; - return title.equals(inItem.getTitle()) && packageName.equals(inItem.getPackageName()) && name.equals(inItem - .getName()); - } - - return false; - } - - public String getTitle() { - return title; - } - - public String getPackageName() { - return packageName; - } - - public String getName() { - return name; - } - - @Override - public int getLayoutRes() { - return R.layout.rv_item_app; - } - - @Override - public void bindViewHolder(FlexibleAdapter adapter, AppItemViewHolder holder, int position, List payloads) { - if (drawable != null) { - holder.iconImageView.setVisibility(View.VISIBLE); - holder.iconImageView.setImageDrawable(drawable); - } else { - holder.iconImageView.setVisibility(View.GONE); - } - - if (position == 0) { - Spannable spannableString = new SpannableString(title); - spannableString.setSpan(new ForegroundColorSpan(NextcloudTalkApplication.Companion.getSharedApplication() - .getResources().getColor(R.color.grey_600)), 0, - spannableString.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - holder.appTitleTextView.setText(spannableString); - } else { - holder.appTitleTextView.setText(title); - } - } - - @Override - public AppItem.AppItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { - return new AppItemViewHolder(view, adapter); - } - - static class AppItemViewHolder extends FlexibleViewHolder { - @BindView(R.id.icon_image_view) - public ImageView iconImageView; - @BindView(R.id.app_title_text_view) - public TextView appTitleTextView; - - /** - * Default constructor. - */ - AppItemViewHolder(View view, FlexibleAdapter adapter) { - super(view, adapter); - ButterKnife.bind(this, view); - } - } - -} 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 new file mode 100644 index 000000000..abbc72817 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/ContactItem.java @@ -0,0 +1,237 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * @author Marcel Hibbe + * @author Andy Scherzinger + * Copyright (C) 2021 Andy Scherzinger + * Copyright (C) 2022 Marcel Hibbe + * Copyright (C) 2017 Mario Danic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.nextcloud.talk.adapters.items; + +import android.annotation.SuppressLint; +import android.text.TextUtils; +import android.view.View; + +import com.facebook.drawee.backends.pipeline.Fresco; +import com.facebook.drawee.interfaces.DraweeController; +import com.nextcloud.talk.R; +import com.nextcloud.talk.application.NextcloudTalkApplication; +import com.nextcloud.talk.databinding.RvItemContactBinding; +import com.nextcloud.talk.models.database.UserEntity; +import com.nextcloud.talk.models.json.participants.Participant; +import com.nextcloud.talk.utils.ApiUtils; +import com.nextcloud.talk.utils.DisplayUtils; + +import java.util.List; +import java.util.regex.Pattern; + +import androidx.core.content.res.ResourcesCompat; +import eu.davidea.flexibleadapter.FlexibleAdapter; +import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; +import eu.davidea.flexibleadapter.items.IFilterable; +import eu.davidea.flexibleadapter.items.ISectionable; +import eu.davidea.flexibleadapter.utils.FlexibleUtils; +import eu.davidea.viewholders.FlexibleViewHolder; + +public class ContactItem extends AbstractFlexibleItem implements + ISectionable, IFilterable { + + public static final String PARTICIPANT_SOURCE_CIRCLES = "circles"; + public static final String PARTICIPANT_SOURCE_GROUPS = "groups"; + public static final String PARTICIPANT_SOURCE_USERS = "users"; + + private final Participant participant; + private final UserEntity userEntity; + private GenericTextHeaderItem header; + public boolean isOnline = true; + + public ContactItem(Participant participant, + UserEntity userEntity, + GenericTextHeaderItem genericTextHeaderItem) { + this.participant = participant; + this.userEntity = userEntity; + this.header = genericTextHeaderItem; + } + + @Override + public boolean equals(Object o) { + if (o instanceof ContactItem) { + ContactItem inItem = (ContactItem) o; + return participant.getActorType() == inItem.getModel().getActorType() && + participant.getActorId().equals(inItem.getModel().getActorId()); + } + return false; + } + + @Override + public int hashCode() { + return participant.hashCode(); + } + + /** + * @return the model object + */ + public Participant getModel() { + return participant; + } + + + @Override + public int getLayoutRes() { + return R.layout.rv_item_contact; + } + + @Override + public ContactItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { + return new ContactItemViewHolder(view, adapter); + } + + @SuppressLint("SetTextI18n") + @Override + public void bindViewHolder(FlexibleAdapter adapter, ContactItemViewHolder holder, int position, List payloads) { + holder.binding.avatarDraweeView.setController(null); + + if (participant.isSelected()) { + holder.binding.checkedImageView.setVisibility(View.VISIBLE); + } else { + holder.binding.checkedImageView.setVisibility(View.GONE); + } + + if (!isOnline) { + holder.binding.nameText.setTextColor(ResourcesCompat.getColor( + holder.binding.nameText.getContext().getResources(), + R.color.medium_emphasis_text, + null) + ); + holder.binding.avatarDraweeView.setAlpha(0.38f); + } else { + holder.binding.nameText.setTextColor(ResourcesCompat.getColor( + holder.binding.nameText.getContext().getResources(), + R.color.high_emphasis_text, + null) + ); + holder.binding.avatarDraweeView.setAlpha(1.0f); + } + + if (adapter.hasFilter()) { + FlexibleUtils.highlightText(holder.binding.nameText, + participant.getDisplayName(), + String.valueOf(adapter.getFilter(String.class)), + NextcloudTalkApplication + .Companion + .getSharedApplication() + .getResources() + .getColor(R.color.colorPrimary)); + } + + holder.binding.nameText.setText(participant.getDisplayName()); + + if (TextUtils.isEmpty(participant.getDisplayName()) && + (participant.getType().equals(Participant.ParticipantType.GUEST) || + participant.getType().equals(Participant.ParticipantType.USER_FOLLOWING_LINK))) { + holder.binding.nameText.setText(NextcloudTalkApplication + .Companion + .getSharedApplication() + .getString(R.string.nc_guest)); + } + + if ( + participant.getActorType() == Participant.ActorType.GROUPS || + PARTICIPANT_SOURCE_GROUPS.equals(participant.getSource()) || + participant.getActorType() == Participant.ActorType.CIRCLES || + PARTICIPANT_SOURCE_CIRCLES.equals(participant.getSource())) { + + holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group); + + } else if (participant.getActorType() == Participant.ActorType.EMAILS) { + + holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_mail); + + } else if ( + participant.getActorType() == Participant.ActorType.GUESTS || + Participant.ParticipantType.GUEST.equals(participant.getType()) || + Participant.ParticipantType.GUEST_MODERATOR.equals(participant.getType())) { + + String displayName = NextcloudTalkApplication.Companion.getSharedApplication() + .getResources().getString(R.string.nc_guest); + + if (!TextUtils.isEmpty(participant.getDisplayName())) { + displayName = participant.getDisplayName(); + } + + DraweeController draweeController = Fresco.newDraweeControllerBuilder() + .setOldController(holder.binding.avatarDraweeView.getController()) + .setAutoPlayAnimations(true) + .setImageRequest(DisplayUtils.getImageRequestForUrl( + ApiUtils.getUrlForAvatarWithNameForGuests(userEntity.getBaseUrl(), + displayName, + R.dimen.avatar_size), + null)) + .build(); + holder.binding.avatarDraweeView.setController(draweeController); + + } else if (participant.getActorType() == Participant.ActorType.USERS || + PARTICIPANT_SOURCE_USERS.equals(participant.getSource())) { + DraweeController draweeController = Fresco.newDraweeControllerBuilder() + .setOldController(holder.binding.avatarDraweeView.getController()) + .setAutoPlayAnimations(true) + .setImageRequest(DisplayUtils.getImageRequestForUrl( + ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(), + participant.getActorId(), + R.dimen.avatar_size), + null)) + .build(); + holder.binding.avatarDraweeView.setController(draweeController); + } + } + + @Override + public boolean filter(String constraint) { + return participant.getDisplayName() != null && + (Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL) + .matcher(participant.getDisplayName().trim()) + .find() || + Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL) + .matcher(participant.getActorId().trim()) + .find()); + } + + @Override + public GenericTextHeaderItem getHeader() { + return header; + } + + @Override + public void setHeader(GenericTextHeaderItem header) { + this.header = header; + } + + static class ContactItemViewHolder extends FlexibleViewHolder { + + RvItemContactBinding binding; + + /** + * Default constructor. + */ + ContactItemViewHolder(View view, FlexibleAdapter adapter) { + super(view, adapter); + binding = RvItemContactBinding.bind(view); + } + } +} 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 f81664e07..0a7593b32 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 @@ -36,20 +36,17 @@ import android.text.TextUtils; import android.text.format.DateUtils; import android.view.View; import android.widget.ImageView; -import android.widget.TextView; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.drawee.interfaces.DraweeController; -import com.facebook.drawee.view.SimpleDraweeView; -import com.google.android.material.chip.Chip; import com.nextcloud.talk.R; import com.nextcloud.talk.application.NextcloudTalkApplication; +import com.nextcloud.talk.databinding.RvItemConversationWithLastMessageBinding; import com.nextcloud.talk.models.database.CapabilitiesUtil; import com.nextcloud.talk.models.database.UserEntity; import com.nextcloud.talk.models.json.chat.ChatMessage; import com.nextcloud.talk.models.json.conversations.Conversation; import com.nextcloud.talk.models.json.status.Status; -import com.nextcloud.talk.models.json.status.StatusType; import com.nextcloud.talk.ui.StatusDrawable; import com.nextcloud.talk.utils.ApiUtils; import com.nextcloud.talk.utils.DisplayUtils; @@ -59,9 +56,6 @@ import java.util.regex.Pattern; import androidx.core.content.ContextCompat; import androidx.core.content.res.ResourcesCompat; -import androidx.emoji.widget.EmojiTextView; -import butterknife.BindView; -import butterknife.ButterKnife; import eu.davidea.flexibleadapter.FlexibleAdapter; import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; import eu.davidea.flexibleadapter.items.IFilterable; @@ -70,16 +64,16 @@ import eu.davidea.flexibleadapter.items.ISectionable; import eu.davidea.flexibleadapter.utils.FlexibleUtils; import eu.davidea.viewholders.FlexibleViewHolder; -public class ConversationItem extends AbstractFlexibleItem implements ISectionable, - IFilterable { +public class ConversationItem extends AbstractFlexibleItem implements + ISectionable, IFilterable { private static final float STATUS_SIZE_IN_DP = 9f; - private Conversation conversation; - private UserEntity userEntity; - private Context context; + private final Conversation conversation; + private final UserEntity userEntity; + private final Context context; private GenericTextHeaderItem header; - private Status status; + private final Status status; public ConversationItem(Conversation conversation, UserEntity userEntity, Context activityContext, Status status) { this.conversation = conversation; @@ -127,31 +121,38 @@ public class ConversationItem extends AbstractFlexibleItem adapter, ConversationItemViewHolder holder, int position, List payloads) { + public void bindViewHolder(FlexibleAdapter adapter, + ConversationItemViewHolder holder, + int position, + List payloads) { Context appContext = NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext(); - holder.dialogAvatar.setController(null); + holder.binding.dialogAvatar.setController(null); - holder.dialogName.setTextColor(ResourcesCompat.getColor(context.getResources(), - R.color.conversation_item_header, - null)); + holder.binding.dialogName.setTextColor(ResourcesCompat.getColor(context.getResources(), + R.color.conversation_item_header, + null)); if (adapter.hasFilter()) { - FlexibleUtils.highlightText(holder.dialogName, conversation.getDisplayName(), - String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication() - .getResources().getColor(R.color.colorPrimary)); + FlexibleUtils.highlightText(holder.binding.dialogName, conversation.getDisplayName(), + String.valueOf(adapter.getFilter(String.class)), + NextcloudTalkApplication + .Companion + .getSharedApplication() + .getResources() + .getColor(R.color.colorPrimary)); } else { - holder.dialogName.setText(conversation.getDisplayName()); + holder.binding.dialogName.setText(conversation.getDisplayName()); } if (conversation.getUnreadMessages() > 0) { - holder.dialogName.setTypeface(holder.dialogName.getTypeface(), Typeface.BOLD); - holder.dialogLastMessage.setTypeface(holder.dialogLastMessage.getTypeface(), Typeface.BOLD); - holder.dialogUnreadBubble.setVisibility(View.VISIBLE); + holder.binding.dialogName.setTypeface(holder.binding.dialogName.getTypeface(), Typeface.BOLD); + holder.binding.dialogLastMessage.setTypeface(holder.binding.dialogLastMessage.getTypeface(), Typeface.BOLD); + holder.binding.dialogUnreadBubble.setVisibility(View.VISIBLE); if (conversation.getUnreadMessages() < 1000) { - holder.dialogUnreadBubble.setText(Long.toString(conversation.getUnreadMessages())); + holder.binding.dialogUnreadBubble.setText(Long.toString(conversation.getUnreadMessages())); } else { - holder.dialogUnreadBubble.setText(R.string.tooManyUnreadMessages); + holder.binding.dialogUnreadBubble.setText(R.string.tooManyUnreadMessages); } ColorStateList lightBubbleFillColor = ColorStateList.valueOf( @@ -165,45 +166,45 @@ public class ConversationItem extends AbstractFlexibleItem * Copyright (C) 2017-2018 Mario Danic * * This program is free software: you can redistribute it and/or modify @@ -22,21 +24,21 @@ package com.nextcloud.talk.adapters.items; import android.util.Log; import android.view.View; -import android.widget.TextView; -import butterknife.BindView; -import butterknife.ButterKnife; + import com.nextcloud.talk.R; +import com.nextcloud.talk.databinding.RvItemTitleHeaderBinding; + +import java.util.List; + import eu.davidea.flexibleadapter.FlexibleAdapter; import eu.davidea.flexibleadapter.items.AbstractHeaderItem; import eu.davidea.flexibleadapter.items.IFlexible; import eu.davidea.viewholders.FlexibleViewHolder; -import java.util.List; - public class GenericTextHeaderItem extends AbstractHeaderItem { private static final String TAG = "GenericTextHeaderItem"; - private String title; + private final String title; public GenericTextHeaderItem(String title) { super(); @@ -68,9 +70,8 @@ public class GenericTextHeaderItem extends AbstractHeaderItem 0) { Log.d(TAG, "We have payloads, so ignoring!"); } else { - holder.titleTextView.setText(title); + holder.binding.titleTextView.setText(title); } - } @Override @@ -80,16 +81,14 @@ public class GenericTextHeaderItem extends AbstractHeaderItem + * @author Marcel Hibbe + * @author Andy Scherzinger + * Copyright (C) 2021 Andy Scherzinger + * Copyright (C) 2022 Marcel Hibbe + * Copyright (C) 2017 Mario Danic * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,8 +51,8 @@ import eu.davidea.flexibleadapter.items.IFilterable; import eu.davidea.flexibleadapter.items.IFlexible; import eu.davidea.flexibleadapter.utils.FlexibleUtils; -public class MentionAutocompleteItem extends AbstractFlexibleItem - implements IFilterable { +public class MentionAutocompleteItem extends AbstractFlexibleItem + implements IFilterable { private static final float STATUS_SIZE_IN_DP = 9f; private static final String NO_ICON = ""; @@ -67,9 +69,9 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem adapter) { - return new UserItem.UserItemViewHolder(view, adapter); + public ParticipantItem.ParticipantItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { + return new ParticipantItem.ParticipantItemViewHolder(view, adapter); } - @SuppressLint("SetTextI18n") @Override - public void bindViewHolder( - FlexibleAdapter adapter, - UserItem.UserItemViewHolder holder, - int position, - List payloads) { + public void bindViewHolder(FlexibleAdapter adapter, + ParticipantItem.ParticipantItemViewHolder holder, + int position, + List payloads) { - holder.contactDisplayName.setTextColor(ResourcesCompat.getColor(context.getResources(), - R.color.conversation_item_header, - null)); + holder.binding.nameText.setTextColor( + ResourcesCompat.getColor(context.getResources(), + R.color.conversation_item_header, + null)); if (adapter.hasFilter()) { - FlexibleUtils.highlightText(holder.contactDisplayName, + FlexibleUtils.highlightText(holder.binding.nameText, displayName, String.valueOf(adapter.getFilter(String.class)), - Objects.requireNonNull(NextcloudTalkApplication.Companion.getSharedApplication()) + Objects.requireNonNull(NextcloudTalkApplication + .Companion + .getSharedApplication()) .getResources().getColor(R.color.colorPrimary)); - if (holder.contactMentionId != null) { - FlexibleUtils.highlightText(holder.contactMentionId, + if (holder.binding.secondaryText != null) { + FlexibleUtils.highlightText(holder.binding.secondaryText, "@" + objectId, String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication() .getResources().getColor(R.color.colorPrimary)); } } else { - holder.contactDisplayName.setText(displayName); - if (holder.contactMentionId != null) { - holder.contactMentionId.setText("@" + objectId); + holder.binding.nameText.setText(displayName); + if (holder.binding.secondaryText != null) { + holder.binding.secondaryText.setText("@" + objectId); } } if (SOURCE_CALLS.equals(source)) { - if (holder.participantAvatar != null){ - holder.participantAvatar.setImageResource(R.drawable.ic_circular_group); + if (holder.binding.avatarDraweeView != null) { + holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group); } } else { String avatarId = objectId; @@ -165,25 +168,27 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem - * Copyright (C) 2018 Andy Scherzinger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.nextcloud.talk.adapters.items; - - -import android.graphics.drawable.Drawable; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.style.ForegroundColorSpan; -import android.view.View; -import android.widget.TextView; -import butterknife.BindView; -import butterknife.ButterKnife; -import com.nextcloud.talk.R; -import com.nextcloud.talk.application.NextcloudTalkApplication; -import com.nextcloud.talk.utils.DisplayUtils; -import eu.davidea.flexibleadapter.FlexibleAdapter; -import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; -import eu.davidea.viewholders.FlexibleViewHolder; - -import java.util.List; - -public class MenuItem extends AbstractFlexibleItem { - private String title; - private Drawable icon; - private int tag; - private int padding; - - public MenuItem(String title, int tag, Drawable icon) { - this.title = title; - this.tag = tag; - this.icon = icon; - padding = (int) DisplayUtils.convertDpToPixel(32, - NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext()); - } - - @Override - public boolean equals(Object o) { - if (o instanceof MenuItem) { - MenuItem inItem = (MenuItem) o; - return tag == inItem.tag; - } - return false; - } - - public int getTag() { - return tag; - } - - @Override - public int getLayoutRes() { - return R.layout.rv_item_menu; - } - - @Override - public MenuItem.MenuItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { - return new MenuItemViewHolder(view, adapter); - } - - @Override - public void bindViewHolder(FlexibleAdapter adapter, MenuItem.MenuItemViewHolder holder, int position, List payloads) { - if (position == 0) { - Spannable spannableString = new SpannableString(title); - spannableString.setSpan(new ForegroundColorSpan(NextcloudTalkApplication.Companion.getSharedApplication() - .getResources().getColor(R.color.grey_600)), 0, - spannableString.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - holder.menuTitle.setText(spannableString); - } else { - holder.menuTitle.setText(title); - holder.menuTitle.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null); - holder.menuTitle.setCompoundDrawablePadding(padding); - } - } - - static class MenuItemViewHolder extends FlexibleViewHolder { - - @BindView(R.id.menu_text) - public TextView menuTitle; - - /** - * Default constructor. - */ - MenuItemViewHolder(View view, FlexibleAdapter adapter) { - super(view, adapter); - ButterKnife.bind(this, view); - } - } -} diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/NotificationSoundItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/NotificationSoundItem.java index f4bfb199c..5f2359b1e 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/NotificationSoundItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/NotificationSoundItem.java @@ -2,6 +2,8 @@ * Nextcloud Talk application * * @author Mario Danic + * @author Andy Scherzinger + * Copyright (C) 2022 Andy Scherzinger * Copyright (C) 2017-2018 Mario Danic * * This program is free software: you can redistribute it and/or modify @@ -22,13 +24,11 @@ package com.nextcloud.talk.adapters.items; import android.view.View; -import com.google.android.material.radiobutton.MaterialRadioButton; import com.nextcloud.talk.R; +import com.nextcloud.talk.databinding.RvItemNotificationSoundBinding; import java.util.List; -import butterknife.BindView; -import butterknife.ButterKnife; import eu.davidea.flexibleadapter.FlexibleAdapter; import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; import eu.davidea.flexibleadapter.items.IFlexible; @@ -68,21 +68,24 @@ public class NotificationSoundItem extends AbstractFlexibleItem adapter, NotificationSoundItemViewHolder holder, int position, List payloads) { - holder.notificationName.setText(notificationSoundName); - holder.notificationName.setChecked(adapter.isSelected(position)); + public void bindViewHolder(FlexibleAdapter adapter, + NotificationSoundItemViewHolder holder, + int position, + List payloads) { + holder.binding.notificationNameTextView.setText(notificationSoundName); + holder.binding.notificationNameTextView.setChecked(adapter.isSelected(position)); } static class NotificationSoundItemViewHolder extends FlexibleViewHolder { - @BindView(R.id.notificationNameTextView) - public MaterialRadioButton notificationName; + + RvItemNotificationSoundBinding binding; /** * Default constructor. */ NotificationSoundItemViewHolder(View view, FlexibleAdapter adapter) { super(view, adapter); - ButterKnife.bind(this, view); + binding = RvItemNotificationSoundBinding.bind(view); } } } 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 new file mode 100644 index 000000000..10e3961b7 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java @@ -0,0 +1,332 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * @author Marcel Hibbe + * @author Andy Scherzinger + * Copyright (C) 2021 Andy Scherzinger + * Copyright (C) 2022 Marcel Hibbe + * Copyright (C) 2017 Mario Danic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.nextcloud.talk.adapters.items; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.Resources; +import android.text.TextUtils; +import android.view.View; + +import com.facebook.drawee.backends.pipeline.Fresco; +import com.facebook.drawee.interfaces.DraweeController; +import com.nextcloud.talk.R; +import com.nextcloud.talk.application.NextcloudTalkApplication; +import com.nextcloud.talk.databinding.RvItemConversationInfoParticipantBinding; +import com.nextcloud.talk.models.database.UserEntity; +import com.nextcloud.talk.models.json.converters.EnumParticipantTypeConverter; +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.utils.ApiUtils; +import com.nextcloud.talk.utils.DisplayUtils; + +import java.util.List; +import java.util.regex.Pattern; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.res.ResourcesCompat; +import eu.davidea.flexibleadapter.FlexibleAdapter; +import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; +import eu.davidea.flexibleadapter.items.IFilterable; +import eu.davidea.flexibleadapter.utils.FlexibleUtils; +import eu.davidea.viewholders.FlexibleViewHolder; + +public class ParticipantItem extends AbstractFlexibleItem implements + IFilterable { + + private static final float STATUS_SIZE_IN_DP = 9f; + private static final String NO_ICON = ""; + + private final Context context; + private final Participant participant; + private final UserEntity userEntity; + public boolean isOnline = true; + + public ParticipantItem(Context activityContext, + Participant participant, + UserEntity userEntity) { + this.context = activityContext; + this.participant = participant; + this.userEntity = userEntity; + } + + public Participant getModel() { + return participant; + } + + @Override + public boolean equals(Object o) { + if (o instanceof ParticipantItem) { + ParticipantItem inItem = (ParticipantItem) o; + return participant.getActorType() == inItem.getModel().getActorType() && + participant.getActorId().equals(inItem.getModel().getActorId()); + } + return false; + } + + @Override + public int hashCode() { + return participant.hashCode(); + } + + @Override + public int getLayoutRes() { + return R.layout.rv_item_conversation_info_participant; + } + + @Override + public ParticipantItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { + return new ParticipantItemViewHolder(view, adapter); + } + + @SuppressLint("SetTextI18n") + @Override + public void bindViewHolder(FlexibleAdapter adapter, ParticipantItemViewHolder holder, int position, List payloads) { + + holder.binding.avatarDraweeView.setController(null); + + drawStatus(holder); + + if (!isOnline) { + holder.binding.nameText.setTextColor(ResourcesCompat.getColor( + holder.binding.nameText.getContext().getResources(), + R.color.medium_emphasis_text, + null) + ); + holder.binding.avatarDraweeView.setAlpha(0.38f); + } else { + holder.binding.nameText.setTextColor(ResourcesCompat.getColor( + holder.binding.nameText.getContext().getResources(), + R.color.high_emphasis_text, + null) + ); + holder.binding.avatarDraweeView.setAlpha(1.0f); + } + + if (adapter.hasFilter()) { + FlexibleUtils.highlightText(holder.binding.nameText, participant.getDisplayName(), + String.valueOf(adapter.getFilter(String.class)), + NextcloudTalkApplication.Companion.getSharedApplication() + .getResources() + .getColor(R.color.colorPrimary)); + } + + holder.binding.nameText.setText(participant.getDisplayName()); + + if (TextUtils.isEmpty(participant.getDisplayName()) && + (participant.getType().equals(Participant.ParticipantType.GUEST) || + participant.getType().equals(Participant.ParticipantType.USER_FOLLOWING_LINK))) { + holder.binding.nameText.setText(NextcloudTalkApplication + .Companion + .getSharedApplication() + .getString(R.string.nc_guest)); + } + + if (participant.getActorType() == Participant.ActorType.GROUPS || + "groups".equals(participant.getSource()) || + participant.getActorType() == Participant.ActorType.CIRCLES || + "circles".equals(participant.getSource())) { + holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group); + } else if (participant.getActorType() == Participant.ActorType.EMAILS) { + holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_mail); + } else if (participant.getActorType() == Participant.ActorType.GUESTS || + Participant.ParticipantType.GUEST.equals(participant.getType()) || + Participant.ParticipantType.GUEST_MODERATOR.equals(participant.getType())) { + + String displayName = NextcloudTalkApplication.Companion.getSharedApplication() + .getResources().getString(R.string.nc_guest); + + if (!TextUtils.isEmpty(participant.getDisplayName())) { + displayName = participant.getDisplayName(); + } + + DraweeController draweeController = Fresco.newDraweeControllerBuilder() + .setOldController(holder.binding.avatarDraweeView.getController()) + .setAutoPlayAnimations(true) + .setImageRequest(DisplayUtils.getImageRequestForUrl( + ApiUtils.getUrlForAvatarWithNameForGuests(userEntity.getBaseUrl(), + displayName, R.dimen.avatar_size), null)) + .build(); + holder.binding.avatarDraweeView.setController(draweeController); + + } else if (participant.getActorType() == Participant.ActorType.USERS || + participant.getSource().equals("users")) { + DraweeController draweeController = Fresco.newDraweeControllerBuilder() + .setOldController(holder.binding.avatarDraweeView.getController()) + .setAutoPlayAnimations(true) + .setImageRequest(DisplayUtils.getImageRequestForUrl( + ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(), + participant.getActorId(), R.dimen.avatar_size), null)) + .build(); + holder.binding.avatarDraweeView.setController(draweeController); + } + + Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources(); + + Long inCallFlag = participant.getInCall(); + if ((inCallFlag & InCallFlags.WITH_PHONE) > 0) { + holder.binding.videoCallIcon.setImageResource(R.drawable.ic_call_grey_600_24dp); + holder.binding.videoCallIcon.setVisibility(View.VISIBLE); + holder.binding.videoCallIcon.setContentDescription( + resources.getString(R.string.nc_call_state_with_phone, participant.displayName)); + } else if ((inCallFlag & InCallFlags.WITH_VIDEO) > 0) { + holder.binding.videoCallIcon.setImageResource(R.drawable.ic_videocam_grey_600_24dp); + holder.binding.videoCallIcon.setVisibility(View.VISIBLE); + holder.binding.videoCallIcon.setContentDescription( + resources.getString(R.string.nc_call_state_with_video, participant.displayName)); + } else if (inCallFlag > InCallFlags.DISCONNECTED) { + holder.binding.videoCallIcon.setImageResource(R.drawable.ic_mic_grey_600_24dp); + holder.binding.videoCallIcon.setVisibility(View.VISIBLE); + holder.binding.videoCallIcon.setContentDescription( + resources.getString(R.string.nc_call_state_in_call, participant.displayName)); + } else { + holder.binding.videoCallIcon.setVisibility(View.GONE); + } + + if (holder.binding.secondaryText != null) { + String userType = ""; + + switch (new EnumParticipantTypeConverter().convertToInt(participant.getType())) { + case 1: + //userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_owner); + //break; + case 2: + case 6: // Guest moderator + userType = NextcloudTalkApplication + .Companion + .getSharedApplication() + .getString(R.string.nc_moderator); + break; + case 3: + userType = NextcloudTalkApplication + .Companion + .getSharedApplication() + .getString(R.string.nc_user); + if (participant.getActorType() == Participant.ActorType.GROUPS) { + userType = NextcloudTalkApplication + .Companion + .getSharedApplication() + .getString(R.string.nc_group); + } + if (participant.getActorType() == Participant.ActorType.CIRCLES) { + userType = NextcloudTalkApplication + .Companion + .getSharedApplication() + .getString(R.string.nc_circle); + } + break; + case 4: + userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest); + if (participant.getActorType() == Participant.ActorType.EMAILS) { + userType = NextcloudTalkApplication + .Companion + .getSharedApplication() + .getString(R.string.nc_email); + } + break; + case 5: + userType = NextcloudTalkApplication + .Companion + .getSharedApplication() + .getString(R.string.nc_following_link); + break; + default: + break; + } + + if (!userType.equals(NextcloudTalkApplication + .Companion + .getSharedApplication() + .getString(R.string.nc_user))) { + holder.binding.secondaryText.setText("(" + userType + ")"); + } + } + } + + private void drawStatus(ParticipantItemViewHolder holder) { + float size = DisplayUtils.convertDpToPixel(STATUS_SIZE_IN_DP, context); + holder.binding.userStatusImage.setImageDrawable(new StatusDrawable( + participant.status, + NO_ICON, + size, + context.getResources().getColor(R.color.bg_default), + context)); + + if (participant.statusMessage != null) { + holder.binding.conversationInfoStatusMessage.setText(participant.statusMessage); + alignUsernameVertical(holder, 0); + } else { + holder.binding.conversationInfoStatusMessage.setText(""); + alignUsernameVertical(holder, 10); + } + + if (participant.statusIcon != null && !participant.statusIcon.isEmpty()) { + holder.binding.participantStatusEmoji.setText(participant.statusIcon); + } else { + holder.binding.participantStatusEmoji.setVisibility(View.GONE); + } + + if (participant.status != null && participant.status.equals(StatusType.DND.getString())) { + if (participant.statusMessage == null || participant.statusMessage.isEmpty()) { + holder.binding.conversationInfoStatusMessage.setText(R.string.dnd); + } + } else if (participant.status != null && participant.status.equals(StatusType.AWAY.getString())) { + if (participant.statusMessage == null || participant.statusMessage.isEmpty()) { + holder.binding.conversationInfoStatusMessage.setText(R.string.away); + } + } + } + + private void alignUsernameVertical(ParticipantItem.ParticipantItemViewHolder holder, float densityPixelsFromTop) { + ConstraintLayout.LayoutParams layoutParams = + (ConstraintLayout.LayoutParams) holder.binding.nameText.getLayoutParams(); + layoutParams.topMargin = (int) DisplayUtils.convertDpToPixel(densityPixelsFromTop, context); + holder.binding.nameText.setLayoutParams(layoutParams); + } + + @Override + public boolean filter(String constraint) { + return participant.getDisplayName() != null && + (Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL) + .matcher(participant.getDisplayName().trim()).find() || + Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL) + .matcher(participant.getActorId().trim()).find()); + } + + static class ParticipantItemViewHolder extends FlexibleViewHolder { + + RvItemConversationInfoParticipantBinding binding; + + /** + * Default constructor. + */ + ParticipantItemViewHolder(View view, FlexibleAdapter adapter) { + super(view, adapter); + binding = RvItemConversationInfoParticipantBinding.bind(view); + } + } +} diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/ProgressItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/ProgressItem.java deleted file mode 100644 index 14e5e74ef..000000000 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/ProgressItem.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Nextcloud Talk application - * - * @author Mario Danic - * Copyright (C) 2017-2018 Mario Danic - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Heavily copied from and influenced by - * https://github.com/davideas/FlexibleAdapter/wiki/5.x-%7C-On-Load-More#automatic-load-more. - * Author: David Steduto under Apache2 licence - */ - -package com.nextcloud.talk.adapters.items; - -import android.animation.Animator; -import android.content.Context; -import android.view.View; -import android.widget.ProgressBar; -import android.widget.TextView; -import androidx.annotation.NonNull; -import butterknife.BindView; -import butterknife.ButterKnife; -import com.nextcloud.talk.R; -import eu.davidea.flexibleadapter.FlexibleAdapter; -import eu.davidea.flexibleadapter.Payload; -import eu.davidea.flexibleadapter.helpers.AnimatorHelper; -import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; -import eu.davidea.flexibleadapter.items.IFlexible; -import eu.davidea.viewholders.FlexibleViewHolder; - -import java.util.List; - -/** - * @author Davide Steduto - * @since 22/04/2016 - */ -public class ProgressItem extends AbstractFlexibleItem { - - private StatusEnum status = StatusEnum.MORE_TO_LOAD; - - @Override - public boolean equals(Object o) { - return this == o;//The default implementation - } - - public StatusEnum getStatus() { - return status; - } - - public void setStatus(StatusEnum status) { - this.status = status; - } - - @Override - public int getLayoutRes() { - return R.layout.rv_item_progress; - } - - @Override - public void bindViewHolder(FlexibleAdapter adapter, ProgressViewHolder holder, int position, List payloads) { - Context context = holder.itemView.getContext(); - holder.progressBar.setVisibility(View.GONE); - holder.progressMessage.setVisibility(View.VISIBLE); - - if (!adapter.isEndlessScrollEnabled()) { - setStatus(StatusEnum.DISABLE_ENDLESS); - } else if (payloads.contains(Payload.NO_MORE_LOAD)) { - setStatus(StatusEnum.NO_MORE_LOAD); - } - - switch (this.status) { - case NO_MORE_LOAD: - holder.progressMessage.setText( - context.getString(R.string.nc_no_more_load_retry)); - // Reset to default status for next binding - setStatus(StatusEnum.MORE_TO_LOAD); - break; - case DISABLE_ENDLESS: - holder.progressMessage.setText(context.getString(R.string.nc_endless_disabled)); - break; - case ON_CANCEL: - holder.progressMessage.setText(context.getString(R.string.nc_endless_cancel)); - // Reset to default status for next binding - setStatus(StatusEnum.MORE_TO_LOAD); - break; - case ON_ERROR: - holder.progressMessage.setText(context.getString(R.string.nc_endless_error)); - // Reset to default status for next binding - setStatus(StatusEnum.MORE_TO_LOAD); - break; - default: - holder.progressBar.setVisibility(View.VISIBLE); - holder.progressMessage.setVisibility(View.GONE); - break; - } - } - - @Override - public ProgressViewHolder createViewHolder(View view, FlexibleAdapter adapter) { - return new ProgressViewHolder(view, adapter); - } - - - public enum StatusEnum { - MORE_TO_LOAD, //Default = should have an empty Payload - DISABLE_ENDLESS, //Endless is disabled because user has set limits - NO_MORE_LOAD, //Non-empty Payload = Payload.NO_MORE_LOAD - ON_CANCEL, - ON_ERROR - } - - static class ProgressViewHolder extends FlexibleViewHolder { - - @BindView(R.id.progress_bar) - ProgressBar progressBar; - @BindView(R.id.progress_message) - TextView progressMessage; - - ProgressViewHolder(View view, FlexibleAdapter adapter) { - super(view, adapter); - ButterKnife.bind(this, view); - } - - @Override - public void scrollAnimators(@NonNull List animators, int position, boolean isForward) { - AnimatorHelper.scaleAnimator(animators, itemView, 0f); - } - } - -} diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java deleted file mode 100644 index 78ce884c5..000000000 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Nextcloud Talk application - * - * @author Mario Danic - * @author Marcel Hibbe - * Copyright (C) 2017 Mario Danic (mario@lovelyhq.com) - * Copyright (C) 2022 Marcel Hibbe (dev@mhibbe.de) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.nextcloud.talk.adapters.items; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.res.Resources; -import android.text.TextUtils; -import android.view.View; -import android.widget.ImageView; - -import com.facebook.drawee.backends.pipeline.Fresco; -import com.facebook.drawee.interfaces.DraweeController; -import com.facebook.drawee.view.SimpleDraweeView; -import com.nextcloud.talk.R; -import com.nextcloud.talk.application.NextcloudTalkApplication; -import com.nextcloud.talk.models.database.UserEntity; -import com.nextcloud.talk.models.json.converters.EnumParticipantTypeConverter; -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.utils.ApiUtils; -import com.nextcloud.talk.utils.DisplayUtils; - -import java.util.List; -import java.util.regex.Pattern; - -import androidx.annotation.Nullable; -import androidx.constraintlayout.widget.ConstraintLayout; -import androidx.core.content.res.ResourcesCompat; -import androidx.emoji.widget.EmojiTextView; -import butterknife.BindView; -import butterknife.ButterKnife; -import eu.davidea.flexibleadapter.FlexibleAdapter; -import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; -import eu.davidea.flexibleadapter.items.IFilterable; -import eu.davidea.flexibleadapter.items.ISectionable; -import eu.davidea.flexibleadapter.utils.FlexibleUtils; -import eu.davidea.viewholders.FlexibleViewHolder; - -public class UserItem extends AbstractFlexibleItem implements - ISectionable, IFilterable { - - private static final float STATUS_SIZE_IN_DP = 9f; - private static final String NO_ICON = ""; - - private Context context; - private Participant participant; - private UserEntity userEntity; - private GenericTextHeaderItem header; - public boolean isOnline = true; - - public UserItem(Context activityContext, - Participant participant, - UserEntity userEntity, - GenericTextHeaderItem genericTextHeaderItem) { - this.context = activityContext; - this.participant = participant; - this.userEntity = userEntity; - this.header = genericTextHeaderItem; - } - - @Override - public boolean equals(Object o) { - if (o instanceof UserItem) { - UserItem inItem = (UserItem) o; - return participant.getActorType() == inItem.getModel().getActorType() && - participant.getActorId().equals(inItem.getModel().getActorId()); - } - return false; - } - - @Override - public int hashCode() { - return participant.hashCode(); - } - - /** - * @return the model object - */ - - public Participant getModel() { - return participant; - } - - public UserEntity getEntity() { - return userEntity; - } - - - @Override - public int getLayoutRes() { - if (header != null) { - return R.layout.rv_item_contact; - } else { - return R.layout.rv_item_conversation_info_participant; - } - } - - @Override - public UserItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { - return new UserItemViewHolder(view, adapter); - } - - @SuppressLint("SetTextI18n") - @Override - public void bindViewHolder(FlexibleAdapter adapter, UserItemViewHolder holder, int position, List payloads) { - - if (holder.participantAvatar != null) { - holder.participantAvatar.setController(null); - } - - if (holder.checkedImageView != null) { - if (participant.isSelected()) { - holder.checkedImageView.setVisibility(View.VISIBLE); - } else { - holder.checkedImageView.setVisibility(View.GONE); - } - } - - drawStatus(holder); - - if (!isOnline) { - holder.contactDisplayName.setTextColor(ResourcesCompat.getColor( - holder.contactDisplayName.getContext().getResources(), - R.color.medium_emphasis_text, - null) - ); - holder.participantAvatar.setAlpha(0.38f); - } else { - holder.contactDisplayName.setTextColor(ResourcesCompat.getColor( - holder.contactDisplayName.getContext().getResources(), - R.color.high_emphasis_text, - null) - ); - holder.participantAvatar.setAlpha(1.0f); - } - - if (adapter.hasFilter()) { - FlexibleUtils.highlightText(holder.contactDisplayName, participant.getDisplayName(), - String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication() - .getResources().getColor(R.color.colorPrimary)); - } - - holder.contactDisplayName.setText(participant.getDisplayName()); - - if (TextUtils.isEmpty(participant.getDisplayName()) && - (participant.getType().equals(Participant.ParticipantType.GUEST) || participant.getType().equals(Participant.ParticipantType.USER_FOLLOWING_LINK))) { - holder.contactDisplayName.setText(NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)); - } - - if (participant.getActorType() == Participant.ActorType.GROUPS || - "groups".equals(participant.getSource()) || - participant.getActorType() == Participant.ActorType.CIRCLES || - "circles".equals(participant.getSource())) { - holder.participantAvatar.setImageResource(R.drawable.ic_circular_group); - } else if (participant.getActorType() == Participant.ActorType.EMAILS) { - holder.participantAvatar.setImageResource(R.drawable.ic_circular_mail); - } else if (participant.getActorType() == Participant.ActorType.GUESTS || - Participant.ParticipantType.GUEST.equals(participant.getType()) || - Participant.ParticipantType.GUEST_MODERATOR.equals(participant.getType())) { - - String displayName = NextcloudTalkApplication.Companion.getSharedApplication() - .getResources().getString(R.string.nc_guest); - - if (!TextUtils.isEmpty(participant.getDisplayName())) { - displayName = participant.getDisplayName(); - } - - DraweeController draweeController = Fresco.newDraweeControllerBuilder() - .setOldController(holder.participantAvatar.getController()) - .setAutoPlayAnimations(true) - .setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithNameForGuests(userEntity.getBaseUrl(), - displayName, R.dimen.avatar_size), null)) - .build(); - holder.participantAvatar.setController(draweeController); - - } else if (participant.getActorType() == Participant.ActorType.USERS || participant.getSource().equals("users")) { - DraweeController draweeController = Fresco.newDraweeControllerBuilder() - .setOldController(holder.participantAvatar.getController()) - .setAutoPlayAnimations(true) - .setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(), - participant.getActorId(), R.dimen.avatar_size), null)) - .build(); - holder.participantAvatar.setController(draweeController); - } - - Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources(); - - if (header == null) { - Long inCallFlag = participant.getInCall(); - if ((inCallFlag & InCallFlags.WITH_PHONE) > 0) { - holder.videoCallIconView.setImageResource(R.drawable.ic_call_grey_600_24dp); - holder.videoCallIconView.setVisibility(View.VISIBLE); - holder.videoCallIconView.setContentDescription( - resources.getString(R.string.nc_call_state_with_phone, participant.displayName)); - } else if ((inCallFlag & InCallFlags.WITH_VIDEO) > 0) { - holder.videoCallIconView.setImageResource(R.drawable.ic_videocam_grey_600_24dp); - holder.videoCallIconView.setVisibility(View.VISIBLE); - holder.videoCallIconView.setContentDescription( - resources.getString(R.string.nc_call_state_with_video, participant.displayName)); - } else if (inCallFlag > InCallFlags.DISCONNECTED) { - holder.videoCallIconView.setImageResource(R.drawable.ic_mic_grey_600_24dp); - holder.videoCallIconView.setVisibility(View.VISIBLE); - holder.videoCallIconView.setContentDescription( - resources.getString(R.string.nc_call_state_in_call, participant.displayName)); - } else { - holder.videoCallIconView.setVisibility(View.GONE); - } - - if (holder.contactMentionId != null) { - String userType = ""; - - switch (new EnumParticipantTypeConverter().convertToInt(participant.getType())) { - case 1: - //userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_owner); - //break; - case 2: - case 6: // Guest moderator - userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_moderator); - break; - case 3: - userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_user); - if (participant.getActorType() == Participant.ActorType.GROUPS) { - userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_group); - } - if (participant.getActorType() == Participant.ActorType.CIRCLES) { - userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_circle); - } - break; - case 4: - userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest); - if (participant.getActorType() == Participant.ActorType.EMAILS) { - userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_email); - } - break; - case 5: - userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_following_link); - break; - default: - break; - } - - if (!userType.equals(NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_user))) { - holder.contactMentionId.setText("(" + userType + ")"); - } - } - } - } - - private void drawStatus(UserItemViewHolder holder) { - if (holder.statusMessage != null && holder.participantEmoji != null && holder.userStatusImage != null) { - float size = DisplayUtils.convertDpToPixel(STATUS_SIZE_IN_DP, context); - holder.userStatusImage.setImageDrawable(new StatusDrawable( - participant.status, - NO_ICON, - size, - context.getResources().getColor(R.color.bg_default), - context)); - - if (participant.statusMessage != null) { - holder.statusMessage.setText(participant.statusMessage); - alignUsernameVertical(holder, 0); - } else { - holder.statusMessage.setText(""); - alignUsernameVertical(holder, 10); - } - - if (participant.statusIcon != null && !participant.statusIcon.isEmpty()) { - holder.participantEmoji.setText(participant.statusIcon); - } else { - holder.participantEmoji.setVisibility(View.GONE); - } - - if (participant.status != null && participant.status.equals(StatusType.DND.getString())) { - if (participant.statusMessage == null || participant.statusMessage.isEmpty()) { - holder.statusMessage.setText(R.string.dnd); - } - } else if (participant.status != null && participant.status.equals(StatusType.AWAY.getString())) { - if (participant.statusMessage == null || participant.statusMessage.isEmpty()) { - holder.statusMessage.setText(R.string.away); - } - } - } - } - - private void alignUsernameVertical(UserItem.UserItemViewHolder holder, float densityPixelsFromTop) { - ConstraintLayout.LayoutParams layoutParams = - (ConstraintLayout.LayoutParams) holder.contactDisplayName.getLayoutParams(); - layoutParams.topMargin = (int) DisplayUtils.convertDpToPixel(densityPixelsFromTop, context); - holder.contactDisplayName.setLayoutParams(layoutParams); - } - - @Override - public boolean filter(String constraint) { - return participant.getDisplayName() != null && - (Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(participant.getDisplayName().trim()).find() || - Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(participant.getActorId().trim()).find()); - } - - @Override - public GenericTextHeaderItem getHeader() { - return header; - } - - @Override - public void setHeader(GenericTextHeaderItem header) { - this.header = header; - } - - static class UserItemViewHolder extends FlexibleViewHolder { - - @BindView(R.id.name_text) - public EmojiTextView contactDisplayName; - @Nullable - @BindView(R.id.avatar_drawee_view) - public SimpleDraweeView participantAvatar; - @Nullable - @BindView(R.id.secondary_text) - public EmojiTextView contactMentionId; - @Nullable - @BindView(R.id.videoCallIcon) - ImageView videoCallIconView; - @Nullable - @BindView(R.id.checkedImageView) - ImageView checkedImageView; - @Nullable - @BindView(R.id.participant_status_emoji) - com.vanniktech.emoji.EmojiEditText participantEmoji; - @Nullable - @BindView(R.id.user_status_image) - ImageView userStatusImage; - @Nullable - @BindView(R.id.conversation_info_status_message) - EmojiTextView statusMessage; - - /** - * Default constructor. - */ - UserItemViewHolder(View view, FlexibleAdapter adapter) { - super(view, adapter); - ButterKnife.bind(this, view); - } - } -} diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java index 1ca545dfc..2913b76c8 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java @@ -46,7 +46,7 @@ import android.widget.RelativeLayout; import com.bluelinelabs.logansquare.LoganSquare; import com.nextcloud.talk.R; import com.nextcloud.talk.adapters.items.GenericTextHeaderItem; -import com.nextcloud.talk.adapters.items.UserItem; +import com.nextcloud.talk.adapters.items.ContactItem; import com.nextcloud.talk.api.NcApi; import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.controllers.base.BaseController; @@ -550,8 +550,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ userHeaderItems.put(headerTitle, genericTextHeaderItem); } - UserItem newContactItem = new UserItem( - getApplicationContext(), + ContactItem newContactItem = new ContactItem( participant, currentUser, userHeaderItems.get(headerTitle) @@ -573,21 +572,21 @@ public class ContactsController extends BaseController implements SearchView.OnQ String firstName; String secondName; - if (o1 instanceof UserItem) { - firstName = ((UserItem) o1).getModel().getDisplayName(); + if (o1 instanceof ContactItem) { + firstName = ((ContactItem) o1).getModel().getDisplayName(); } else { firstName = ((GenericTextHeaderItem) o1).getModel(); } - if (o2 instanceof UserItem) { - secondName = ((UserItem) o2).getModel().getDisplayName(); + if (o2 instanceof ContactItem) { + secondName = ((ContactItem) o2).getModel().getDisplayName(); } else { secondName = ((GenericTextHeaderItem) o2).getModel(); } - if (o1 instanceof UserItem && o2 instanceof UserItem) { - String firstSource = ((UserItem) o1).getModel().getSource(); - String secondSource = ((UserItem) o2).getModel().getSource(); + if (o1 instanceof ContactItem && o2 instanceof ContactItem) { + String firstSource = ((ContactItem) o1).getModel().getSource(); + String secondSource = ((ContactItem) o2).getModel().getSource(); if (firstSource.equals(secondSource)) { return firstName.compareToIgnoreCase(secondName); } @@ -624,24 +623,24 @@ public class ContactsController extends BaseController implements SearchView.OnQ String firstName; String secondName; - if (o1 instanceof UserItem) { - firstName = ((UserItem) o1).getModel().getDisplayName(); + if (o1 instanceof ContactItem) { + firstName = ((ContactItem) o1).getModel().getDisplayName(); } else { firstName = ((GenericTextHeaderItem) o1).getModel(); } - if (o2 instanceof UserItem) { - secondName = ((UserItem) o2).getModel().getDisplayName(); + if (o2 instanceof ContactItem) { + secondName = ((ContactItem) o2).getModel().getDisplayName(); } else { secondName = ((GenericTextHeaderItem) o2).getModel(); } - if (o1 instanceof UserItem && o2 instanceof UserItem) { - if ("groups".equals(((UserItem) o1).getModel().getSource()) && "groups".equals(((UserItem) o2).getModel().getSource())) { + if (o1 instanceof ContactItem && o2 instanceof ContactItem) { + if ("groups".equals(((ContactItem) o1).getModel().getSource()) && "groups".equals(((ContactItem) o2).getModel().getSource())) { return firstName.compareToIgnoreCase(secondName); - } else if ("groups".equals(((UserItem) o1).getModel().getSource())) { + } else if ("groups".equals(((ContactItem) o1).getModel().getSource())) { return -1; - } else if ("groups".equals(((UserItem) o2).getModel().getSource())) { + } else if ("groups".equals(((ContactItem) o2).getModel().getSource())) { return 1; } } @@ -827,12 +826,12 @@ public class ContactsController extends BaseController implements SearchView.OnQ @Override public boolean onItemClick(View view, int position) { - if (adapter.getItem(position) instanceof UserItem) { + if (adapter.getItem(position) instanceof ContactItem) { if (!isNewConversationView && !isAddingParticipantsView) { - UserItem userItem = (UserItem) adapter.getItem(position); + ContactItem contactItem = (ContactItem) adapter.getItem(position); String roomType = "1"; - if ("groups".equals(userItem.getModel().getSource())) { + if ("groups".equals(contactItem.getModel().getSource())) { roomType = "2"; } @@ -842,7 +841,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ currentUser.getBaseUrl(), roomType, null, - userItem.getModel().getActorId(), + contactItem.getModel().getActorId(), null); ncApi.createRoom(credentials, @@ -881,7 +880,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ } }); } else { - Participant participant = ((UserItem) adapter.getItem(position)).getModel(); + Participant participant = ((ContactItem) adapter.getItem(position)).getModel(); participant.setSelected(!participant.isSelected()); if ("groups".equals(participant.getSource())) { @@ -912,10 +911,10 @@ public class ContactsController extends BaseController implements SearchView.OnQ if (CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, "last-room-activity") && !CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, "invite-groups-and-mails") && - "groups".equals(((UserItem) adapter.getItem(position)).getModel().getSource()) && + "groups".equals(((ContactItem) adapter.getItem(position)).getModel().getSource()) && participant.isSelected() && adapter.getSelectedItemCount() > 1) { - List currentItems = adapter.getCurrentItems(); + List currentItems = adapter.getCurrentItems(); Participant internalParticipant; for (int i = 0; i < currentItems.size(); i++) { internalParticipant = currentItems.get(i).getModel(); @@ -961,8 +960,8 @@ public class ContactsController extends BaseController implements SearchView.OnQ List currentItems = adapter.getCurrentItems(); Participant internalParticipant; for (int i = 0; i < currentItems.size(); i++) { - if (currentItems.get(i) instanceof UserItem) { - internalParticipant = ((UserItem) currentItems.get(i)).getModel(); + if (currentItems.get(i) instanceof ContactItem) { + internalParticipant = ((ContactItem) currentItems.get(i)).getModel(); if (internalParticipant.getActorType() == Participant.ActorType.GROUPS && internalParticipant.isSelected()) { internalParticipant.setSelected(false); @@ -973,10 +972,10 @@ public class ContactsController extends BaseController implements SearchView.OnQ } for (int i = 0; i < adapter.getItemCount(); i++) { - if (adapter.getItem(i) instanceof UserItem) { - UserItem userItem = (UserItem) adapter.getItem(i); - if ("groups".equals(userItem.getModel().getSource())) { - userItem.setEnabled(!isPublicCall); + if (adapter.getItem(i) instanceof ContactItem) { + ContactItem contactItem = (ContactItem) adapter.getItem(i); + if ("groups".equals(contactItem.getModel().getSource())) { + contactItem.setEnabled(!isPublicCall); } } } 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 5c0f77a60..c1ca994d3 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt @@ -49,7 +49,7 @@ import com.bluelinelabs.conductor.RouterTransaction import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler import com.facebook.drawee.backends.pipeline.Fresco import com.nextcloud.talk.R -import com.nextcloud.talk.adapters.items.UserItem +import com.nextcloud.talk.adapters.items.ParticipantItem import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.controllers.base.NewBaseController @@ -87,6 +87,7 @@ import io.reactivex.schedulers.Schedulers import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode +import java.util.ArrayList import java.util.Calendar import java.util.Collections import java.util.Comparator @@ -122,8 +123,8 @@ class ConversationInfoController(args: Bundle) : private var databaseStorageModule: DatabaseStorageModule? = null private var conversation: Conversation? = null - private var adapter: FlexibleAdapter? = null - private var userItems: MutableList = ArrayList() + private var adapter: FlexibleAdapter? = null + private var userItems: MutableList = ArrayList() private var saveStateHandler: LovelySaveStateHandler? = null @@ -378,15 +379,15 @@ class ConversationInfoController(args: Bundle) : } private fun handleParticipants(participants: List) { - var userItem: UserItem + var userItem: ParticipantItem var participant: Participant userItems = ArrayList() - var ownUserItem: UserItem? = null + var ownUserItem: ParticipantItem? = null for (i in participants.indices) { participant = participants[i] - userItem = UserItem(router.activity, participant, conversationUser, null) + userItem = ParticipantItem(router.activity, participant, conversationUser) if (participant.sessionId != null) { userItem.isOnline = !participant.sessionId.equals("0") } else { @@ -402,7 +403,7 @@ class ConversationInfoController(args: Bundle) : } } - Collections.sort(userItems, UserItemComparator()) + Collections.sort(userItems, ParticipantItemComparator()) if (ownUserItem != null) { userItems.add(0, ownUserItem) @@ -956,7 +957,7 @@ class ConversationInfoController(args: Bundle) : return true } - val userItem = adapter?.getItem(position) as UserItem + val userItem = adapter?.getItem(position) as ParticipantItem val participant = userItem.model val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.APIv4, 1)) @@ -1108,8 +1109,8 @@ class ConversationInfoController(args: Bundle) : /** * Comparator for participants, sorts by online-status, moderator-status and display name. */ - class UserItemComparator : Comparator { - override fun compare(left: UserItem, right: UserItem): Int { + class ParticipantItemComparator : Comparator { + override fun compare(left: ParticipantItem, right: ParticipantItem): Int { val leftIsGroup = left.model.actorType == GROUPS || left.model.actorType == CIRCLES val rightIsGroup = right.model.actorType == GROUPS || right.model.actorType == CIRCLES if (leftIsGroup != rightIsGroup) { diff --git a/app/src/main/res/layout/rv_item_app.xml b/app/src/main/res/layout/rv_item_app.xml deleted file mode 100644 index f438a4636..000000000 --- a/app/src/main/res/layout/rv_item_app.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - diff --git a/app/src/main/res/layout/rv_item_conversation_info_participant.xml b/app/src/main/res/layout/rv_item_conversation_info_participant.xml index 974cc00aa..c72f1b1d3 100644 --- a/app/src/main/res/layout/rv_item_conversation_info_participant.xml +++ b/app/src/main/res/layout/rv_item_conversation_info_participant.xml @@ -26,7 +26,6 @@ android:layout_marginBottom="@dimen/standard_half_margin" android:layout_marginTop="@dimen/standard_margin"> - - - - - - diff --git a/app/src/main/res/layout/rv_item_progress.xml b/app/src/main/res/layout/rv_item_progress.xml deleted file mode 100644 index 334e0fb9d..000000000 --- a/app/src/main/res/layout/rv_item_progress.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0cc93d084..cfb74f4f0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -102,9 +102,6 @@ message_ringtone Librem by feandesign No sound - Vibrate - Phone will vibrate unless it\'s silenced - notifications_vibrate Appearance Theme @@ -329,16 +326,7 @@ Remote audio off Add attachment - - No more items to load. Refresh to retry. - No more items to load (max reached). - Cancelled by the user. - An error occurred while loading more items. - - Menu for conversation with %1$s - Menu for group conversation %1$s - Menu for public conversation %1$s Send message diff --git a/scripts/analysis/findbugs-results.txt b/scripts/analysis/findbugs-results.txt index 4f09af713..9301519f5 100644 --- a/scripts/analysis/findbugs-results.txt +++ b/scripts/analysis/findbugs-results.txt @@ -1 +1 @@ -492 \ No newline at end of file +483 \ No newline at end of file diff --git a/scripts/analysis/lint-results.txt b/scripts/analysis/lint-results.txt index 06528635e..24f563551 100644 --- a/scripts/analysis/lint-results.txt +++ b/scripts/analysis/lint-results.txt @@ -1,2 +1,2 @@ DO NOT TOUCH; GENERATED BY DRONE - Lint Report: 1 error and 205 warnings + Lint Report: 1 error and 178 warnings