From 1de2261426ed112e1b50342a9f2e2d8a7d20918f Mon Sep 17 00:00:00 2001 From: Marcel Hibbe Date: Fri, 21 Jan 2022 13:53:39 +0100 Subject: [PATCH 1/4] add open conversations to search Signed-off-by: Marcel Hibbe --- .../talk/adapters/items/CallItem.java | 20 +- .../talk/adapters/items/ConversationItem.java | 25 ++- .../java/com/nextcloud/talk/api/NcApi.java | 7 + .../ConversationsListController.java | 193 ++++++++++++++---- .../com/nextcloud/talk/utils/ApiUtils.java | 4 + app/src/main/res/values/strings.xml | 3 + 6 files changed, 203 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/CallItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/CallItem.java index 4958ee569..5818e83dc 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/CallItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/CallItem.java @@ -49,19 +49,27 @@ 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 CallItem extends AbstractFlexibleItem implements IFilterable { +public class CallItem extends AbstractFlexibleItem implements ISectionable, IFilterable { private Conversation conversation; private UserEntity userEntity; + private GenericTextHeaderItem header; public CallItem(Conversation conversation, UserEntity userEntity) { this.conversation = conversation; this.userEntity = userEntity; } + public CallItem(Conversation conversation, UserEntity userEntity, GenericTextHeaderItem genericTextHeaderItem) { + this.conversation = conversation; + this.userEntity = userEntity; + this.header = genericTextHeaderItem; + } + @Override public boolean equals(Object o) { if (o instanceof CallItem) { @@ -168,6 +176,16 @@ public class CallItem extends AbstractFlexibleItem Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(conversation.getDisplayName().trim()).find(); } + @Override + public GenericTextHeaderItem getHeader() { + return header; + } + + @Override + public void setHeader(GenericTextHeaderItem header) { + this.header = header; + } + static class RoomItemViewHolder extends FlexibleViewHolder { @BindView(R.id.name_text) 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 861528357..f63b1f3cf 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 @@ -61,24 +61,33 @@ import eu.davidea.flexibleadapter.FlexibleAdapter; import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; import eu.davidea.flexibleadapter.items.IFilterable; import eu.davidea.flexibleadapter.items.IFlexible; +import eu.davidea.flexibleadapter.items.ISectionable; import eu.davidea.flexibleadapter.utils.FlexibleUtils; import eu.davidea.viewholders.FlexibleViewHolder; -public class ConversationItem extends AbstractFlexibleItem implements +public class ConversationItem extends AbstractFlexibleItem implements ISectionable, IFilterable { private Conversation conversation; private UserEntity userEntity; private Context context; + private GenericTextHeaderItem header; - public ConversationItem(Conversation conversation, UserEntity userEntity, - Context activityContext) { + public ConversationItem(Conversation conversation, UserEntity userEntity, Context activityContext) { this.conversation = conversation; this.userEntity = userEntity; this.context = activityContext; } + public ConversationItem(Conversation conversation, UserEntity userEntity, + Context activityContext, GenericTextHeaderItem genericTextHeaderItem) { + this.conversation = conversation; + this.userEntity = userEntity; + this.context = activityContext; + this.header = genericTextHeaderItem; + } + @Override public boolean equals(Object o) { if (o instanceof ConversationItem) { @@ -286,6 +295,16 @@ public class ConversationItem extends AbstractFlexibleItem setChatReadMarker(@Header("Authorization") String authorization, @Url String url, @Field("lastReadMessage") int lastReadMessage); + + /* + Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /listed-room + */ + @GET + Observable getOpenConversations(@Header("Authorization") String authorization, @Url String url); + } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java index 76b3867ba..1becbac2c 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java @@ -66,6 +66,7 @@ import com.nextcloud.talk.R; import com.nextcloud.talk.activities.MainActivity; import com.nextcloud.talk.adapters.items.CallItem; import com.nextcloud.talk.adapters.items.ConversationItem; +import com.nextcloud.talk.adapters.items.GenericTextHeaderItem; import com.nextcloud.talk.api.NcApi; import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.controllers.base.BaseController; @@ -106,6 +107,7 @@ import org.parceler.Parcels; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Objects; @@ -178,8 +180,11 @@ public class ConversationsListController extends BaseController implements Searc private UserEntity currentUser; private Disposable roomsQueryDisposable; + private Disposable openConversationsQueryDisposable; private FlexibleAdapter adapter; private List callItems = new ArrayList<>(); + private List callItemsWithHeader = new ArrayList<>(); + private List searchableCallItems = new ArrayList<>(); private BottomSheet bottomSheet; private MenuItem searchItem; @@ -212,6 +217,8 @@ public class ConversationsListController extends BaseController implements Searc private SmoothScrollLinearLayoutManager layoutManager; + private HashMap callHeaderItems = new HashMap<>(); + public ConversationsListController(Bundle bundle) { super(); setHasOptionsMenu(true); @@ -400,11 +407,20 @@ public class ConversationsListController extends BaseController implements Searc searchItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() { @Override public boolean onMenuItemActionExpand(MenuItem item) { + adapter.setHeadersShown(true); + adapter.updateDataSet(searchableCallItems, false); + adapter.showAllHeaders(); + swipeRefreshLayout.setEnabled(false); return true; } @Override public boolean onMenuItemActionCollapse(MenuItem item) { + adapter.setHeadersShown(false); + adapter.updateDataSet(callItems, false); + adapter.hideAllHeaders(); + swipeRefreshLayout.setEnabled(true); + searchView.onActionViewCollapsed(); MainActivity activity = (MainActivity) getActivity(); if (activity != null) { @@ -462,6 +478,7 @@ public class ConversationsListController extends BaseController implements Searc isRefreshing = true; callItems = new ArrayList<>(); + callItemsWithHeader = new ArrayList<>(); int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[]{ApiUtils.APIv4, ApiUtils.APIv3, 1}); @@ -494,69 +511,68 @@ public class ConversationsListController extends BaseController implements Searc } } - Conversation conversation; - for (int i = 0; i < roomsOverall.getOcs().getData().size(); i++) { - conversation = roomsOverall.getOcs().getData().get(i); - + for (Conversation conversation : roomsOverall.getOcs().getData()) { if (bundle.containsKey(BundleKeys.INSTANCE.getKEY_FORWARD_HIDE_SOURCE_ROOM()) && conversation.roomId.equals(bundle.getString( BundleKeys.INSTANCE.getKEY_FORWARD_HIDE_SOURCE_ROOM()))) { continue; } + String headerTitle; + + headerTitle = getResources().getString(R.string.conversations); + + GenericTextHeaderItem genericTextHeaderItem; + if (!callHeaderItems.containsKey(headerTitle)) { + genericTextHeaderItem = new GenericTextHeaderItem(headerTitle); + callHeaderItems.put(headerTitle, genericTextHeaderItem); + } + if (shouldUseLastMessageLayout) { if (getActivity() != null) { - ConversationItem conversationItem = new ConversationItem(conversation - , currentUser, getActivity()); + ConversationItem conversationItem = new ConversationItem( + conversation, + currentUser, + getActivity()); callItems.add(conversationItem); + + ConversationItem conversationItemWithHeader = new ConversationItem( + conversation, + currentUser, + getActivity(), + callHeaderItems.get(headerTitle)); + + callItemsWithHeader.add(conversationItemWithHeader); } } else { - CallItem callItem = new CallItem(conversation, currentUser); + CallItem callItem = new CallItem( + conversation, + currentUser); callItems.add(callItem); + + CallItem callItemWithHeader = new CallItem( + conversation, + currentUser, + callHeaderItems.get(headerTitle)); + + callItemsWithHeader.add(callItemWithHeader); } } - if (CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, "last-room-activity")) { - Collections.sort(callItems, (o1, o2) -> { - Conversation conversation1 = ((ConversationItem) o1).getModel(); - Conversation conversation2 = ((ConversationItem) o2).getModel(); - return new CompareToBuilder() - .append(conversation2.isFavorite(), conversation1.isFavorite()) - .append(conversation2.getLastActivity(), conversation1.getLastActivity()) - .toComparison(); - }); - } else { - Collections.sort(callItems, (callItem, t1) -> - Long.compare(((CallItem) t1).getModel().getLastPing(), - ((CallItem) callItem).getModel().getLastPing())); - } + sortConversations(callItems); + sortConversations(callItemsWithHeader); adapter.updateDataSet(callItems, false); + new Handler().postDelayed(this::checkToShowUnreadBubble, UNREAD_BUBBLE_DELAY); + fetchOpenConversations(apiVersion); + if (swipeRefreshLayout != null) { swipeRefreshLayout.setRefreshing(false); } }, throwable -> { - if (throwable instanceof HttpException) { - HttpException exception = (HttpException) throwable; - switch (exception.code()) { - case 401: - if (getParentController() != null && getParentController().getRouter() != null) { - Log.d(TAG, "Starting reauth webview via getParentController()"); - getParentController().getRouter().pushController((RouterTransaction.with - (new WebViewLoginController(currentUser.getBaseUrl(), true)) - .pushChangeHandler(new VerticalChangeHandler()) - .popChangeHandler(new VerticalChangeHandler()))); - } else { - Log.d(TAG, "Starting reauth webview via ConversationsListController"); - showUnauthorizedDialog(); - } - break; - default: - break; - } - } + handleHttpExceptions(throwable); if (swipeRefreshLayout != null) { swipeRefreshLayout.setRefreshing(false); } @@ -580,6 +596,94 @@ public class ConversationsListController extends BaseController implements Searc }); } + private void sortConversations(List callItems) { + if (CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, "last-room-activity")) { + Collections.sort(callItems, (o1, o2) -> { + Conversation conversation1 = ((ConversationItem) o1).getModel(); + Conversation conversation2 = ((ConversationItem) o2).getModel(); + return new CompareToBuilder() + .append(conversation2.isFavorite(), conversation1.isFavorite()) + .append(conversation2.getLastActivity(), conversation1.getLastActivity()) + .toComparison(); + }); + } else { + Collections.sort(callItems, (callItem, t1) -> + Long.compare(((CallItem) t1).getModel().getLastPing(), + ((CallItem) callItem).getModel().getLastPing())); + } + } + + private void fetchOpenConversations(int apiVersion){ + searchableCallItems.clear(); + searchableCallItems.addAll(callItemsWithHeader); + + if (CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, "listable-rooms")) { + List openConversationItems = new ArrayList<>(); + + openConversationsQueryDisposable = ncApi.getOpenConversations( + credentials, + ApiUtils.getUrlForOpenConversations(apiVersion, currentUser.getBaseUrl())) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(roomsOverall -> { + + for (Conversation conversation : roomsOverall.getOcs().getData()) { + String headerTitle = getResources().getString(R.string.openConversations); + + GenericTextHeaderItem genericTextHeaderItem; + if (!callHeaderItems.containsKey(headerTitle)) { + genericTextHeaderItem = new GenericTextHeaderItem(headerTitle); + callHeaderItems.put(headerTitle, genericTextHeaderItem); + } + + + if (shouldUseLastMessageLayout) { + if (getActivity() != null) { + ConversationItem conversationItem = new ConversationItem(conversation + , currentUser, getActivity(), callHeaderItems.get(headerTitle)); + openConversationItems.add(conversationItem); + } + } else { + CallItem callItem = new CallItem(conversation, currentUser, callHeaderItems.get(headerTitle)); + openConversationItems.add(callItem); + } + } + + searchableCallItems.addAll(openConversationItems); + + }, throwable -> { + handleHttpExceptions(throwable); + dispose(openConversationsQueryDisposable); + }, () -> { + dispose(openConversationsQueryDisposable); + }); + } else { + Log.d(TAG, "no open conversations fetched because of missing capability"); + } + } + + private void handleHttpExceptions(Throwable throwable) { + if (throwable instanceof HttpException) { + HttpException exception = (HttpException) throwable; + switch (exception.code()) { + case 401: + if (getParentController() != null && getParentController().getRouter() != null) { + Log.d(TAG, "Starting reauth webview via getParentController()"); + getParentController().getRouter().pushController((RouterTransaction.with + (new WebViewLoginController(currentUser.getBaseUrl(), true)) + .pushChangeHandler(new VerticalChangeHandler()) + .popChangeHandler(new VerticalChangeHandler()))); + } else { + Log.d(TAG, "Starting reauth webview via ConversationsListController"); + showUnauthorizedDialog(); + } + break; + default: + break; + } + } + } + private void prepareViews() { layoutManager = new SmoothScrollLinearLayoutManager(Objects.requireNonNull(getActivity())); recyclerView.setLayoutManager(layoutManager); @@ -671,6 +775,10 @@ public class ConversationsListController extends BaseController implements Searc roomsQueryDisposable != null && !roomsQueryDisposable.isDisposed()) { roomsQueryDisposable.dispose(); roomsQueryDisposable = null; + } else if (disposable == null && + openConversationsQueryDisposable != null && !openConversationsQueryDisposable.isDisposed()) { + openConversationsQueryDisposable.dispose(); + openConversationsQueryDisposable = null; } } @@ -716,11 +824,6 @@ public class ConversationsListController extends BaseController implements Searc adapter.filterItems(300); } } - - if (swipeRefreshLayout != null) { - swipeRefreshLayout.setEnabled(!adapter.hasFilter()); - } - return true; } diff --git a/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java b/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java index 6b0be29d0..01c5c7f74 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java @@ -275,6 +275,10 @@ public class ApiUtils { return getUrlForSignaling(version, baseUrl) + "/" + token; } + public static String getUrlForOpenConversations(int version, String baseUrl) { + return getUrlForApi(version, baseUrl) + "/listed-room"; + } + public static RetrofitBucket getRetrofitBucketForCreateRoom(int version, String baseUrl, String roomType, @Nullable String source, @Nullable String invite, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8eee9721f..94ca857b3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -273,6 +273,8 @@ Unread mentions + Conversations + Open conversations Enter a message… @@ -492,4 +494,5 @@ Send Error taking picture Taking a photo is not possible without permissions + From edc409161157104b4e7519fa0722beb728ba84d4 Mon Sep 17 00:00:00 2001 From: Marcel Hibbe Date: Tue, 25 Jan 2022 14:35:50 +0100 Subject: [PATCH 2/4] hide keyboard when scrolling in conversation search Signed-off-by: Marcel Hibbe --- .../talk/controllers/ConversationsListController.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java index 1becbac2c..0f04addf8 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java @@ -44,6 +44,7 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.Toast; @@ -684,6 +685,7 @@ public class ConversationsListController extends BaseController implements Searc } } + @SuppressLint("ClickableViewAccessibility") private void prepareViews() { layoutManager = new SmoothScrollLinearLayoutManager(Objects.requireNonNull(getActivity())); recyclerView.setLayoutManager(layoutManager); @@ -699,6 +701,13 @@ public class ConversationsListController extends BaseController implements Searc } }); + recyclerView.setOnTouchListener((v, event) -> { + InputMethodManager imm = + (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(v.getWindowToken(), 0); + return false; + }); + swipeRefreshLayout.setOnRefreshListener(() -> fetchData(false)); swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary); swipeRefreshLayout.setProgressBackgroundColorSchemeResource(R.color.refresh_spinner_background); From 70b4eed6541e6d013b8104159faf01483b8b3a18 Mon Sep 17 00:00:00 2001 From: Marcel Hibbe Date: Wed, 26 Jan 2022 17:20:45 +0100 Subject: [PATCH 3/4] delete deprecated CallItem + refactor related code CallItem was only used before NC 14. rv_item_conversation.xml was used by CallItem. After CallItem is now deleted, rv_item_conversation.xml was deleted from other xml classes as "tool"-view (this didn't make sense & was only a placeholder) Furthermore, it was renamed to account_item.xml as now it is only used for account selection. Signed-off-by: Marcel Hibbe --- .../talk/adapters/items/AdvancedUserItem.java | 21 +- .../talk/adapters/items/CallItem.java | 207 ------------------ .../ConversationsListController.java | 136 ++++-------- app/src/main/res/layout/account_item.xml | 40 +--- .../main/res/layout/controller_call_menu.xml | 3 +- .../layout/controller_conversations_rv.xml | 3 +- .../main/res/layout/controller_generic_rv.xml | 3 +- .../main/res/layout/current_account_item.xml | 144 ++++++++++++ .../main/res/layout/dialog_choose_account.xml | 2 +- .../main/res/layout/rv_item_conversation.xml | 98 --------- 10 files changed, 197 insertions(+), 460 deletions(-) delete mode 100644 app/src/main/java/com/nextcloud/talk/adapters/items/CallItem.java create mode 100644 app/src/main/res/layout/current_account_item.xml delete mode 100644 app/src/main/res/layout/rv_item_conversation.xml 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 fcab9f4ad..cdc1ea72b 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 @@ -100,7 +100,7 @@ public class AdvancedUserItem extends AbstractFlexibleItem. - */ - -package com.nextcloud.talk.adapters.items; - -import android.content.res.Resources; -import android.text.TextUtils; -import android.text.format.DateUtils; -import android.view.View; -import android.widget.ImageButton; -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.events.MoreMenuClickEvent; -import com.nextcloud.talk.models.database.UserEntity; -import com.nextcloud.talk.models.json.conversations.Conversation; -import com.nextcloud.talk.utils.ApiUtils; -import com.nextcloud.talk.utils.DisplayUtils; - -import org.greenrobot.eventbus.EventBus; - -import java.util.List; -import java.util.regex.Pattern; - -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 CallItem extends AbstractFlexibleItem implements ISectionable, IFilterable { - - private Conversation conversation; - private UserEntity userEntity; - private GenericTextHeaderItem header; - - public CallItem(Conversation conversation, UserEntity userEntity) { - this.conversation = conversation; - this.userEntity = userEntity; - } - - public CallItem(Conversation conversation, UserEntity userEntity, GenericTextHeaderItem genericTextHeaderItem) { - this.conversation = conversation; - this.userEntity = userEntity; - this.header = genericTextHeaderItem; - } - - @Override - public boolean equals(Object o) { - if (o instanceof CallItem) { - CallItem inItem = (CallItem) o; - return conversation.equals(inItem.getModel()); - } - return false; - } - - @Override - public int hashCode() { - return conversation.hashCode(); - } - - /** - * @return the model object - */ - - public Conversation getModel() { - return conversation; - } - - /** - * Filter is applied to the model fields. - */ - - @Override - public int getLayoutRes() { - return R.layout.rv_item_conversation; - } - - @Override - public RoomItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { - return new RoomItemViewHolder(view, adapter); - } - - @Override - public void bindViewHolder(final FlexibleAdapter adapter, RoomItemViewHolder holder, int position, List payloads) { - if (adapter.hasFilter()) { - FlexibleUtils.highlightText(holder.roomDisplayName, conversation.getDisplayName(), - String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication() - .getResources().getColor(R.color.colorPrimary)); - } else { - holder.roomDisplayName.setText(conversation.getDisplayName()); - } - - if (conversation.getLastPing() == 0) { - holder.roomLastPing.setText(R.string.nc_never); - } else { - holder.roomLastPing.setText(DateUtils.getRelativeTimeSpanString(conversation.getLastPing() * 1000L, - System.currentTimeMillis(), 0, DateUtils.FORMAT_ABBREV_RELATIVE)); - } - - if (conversation.hasPassword) { - holder.passwordProtectedImageView.setVisibility(View.VISIBLE); - } else { - holder.passwordProtectedImageView.setVisibility(View.GONE); - } - - Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources(); - switch (conversation.getType()) { - case ROOM_TYPE_ONE_TO_ONE_CALL: - holder.avatarImageView.setVisibility(View.VISIBLE); - - holder.moreMenuButton.setContentDescription(String.format(resources.getString(R.string - .nc_description_more_menu_one_to_one), conversation.getDisplayName())); - - if (!TextUtils.isEmpty(conversation.getName())) { - DraweeController draweeController = Fresco.newDraweeControllerBuilder() - .setOldController(holder.avatarImageView.getController()) - .setAutoPlayAnimations(true) - .setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(), - conversation.getName(), - R.dimen.avatar_size), null)) - .build(); - holder.avatarImageView.setController(draweeController); - } else { - holder.avatarImageView.setVisibility(View.GONE); - } - break; - case ROOM_GROUP_CALL: - holder.moreMenuButton.setContentDescription(String.format(resources.getString(R.string - .nc_description_more_menu_group), conversation.getDisplayName())); - holder.avatarImageView.setActualImageResource(R.drawable.ic_circular_group); - holder.avatarImageView.setVisibility(View.VISIBLE); - break; - case ROOM_PUBLIC_CALL: - holder.moreMenuButton.setContentDescription(String.format(resources.getString(R.string - .nc_description_more_menu_public), conversation.getDisplayName())); - holder.avatarImageView.setActualImageResource(R.drawable.ic_circular_link); - holder.avatarImageView.setVisibility(View.VISIBLE); - break; - default: - holder.avatarImageView.setVisibility(View.GONE); - - } - - holder.moreMenuButton.setOnClickListener(view -> EventBus.getDefault().post(new MoreMenuClickEvent(conversation))); - } - - @Override - public boolean filter(String constraint) { - return conversation.getDisplayName() != null && - Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL).matcher(conversation.getDisplayName().trim()).find(); - } - - @Override - public GenericTextHeaderItem getHeader() { - return header; - } - - @Override - public void setHeader(GenericTextHeaderItem header) { - this.header = header; - } - - static class RoomItemViewHolder extends FlexibleViewHolder { - - @BindView(R.id.name_text) - public EmojiTextView roomDisplayName; - @BindView(R.id.secondary_text) - public EmojiTextView roomLastPing; - @BindView(R.id.avatar_image) - public SimpleDraweeView avatarImageView; - @BindView(R.id.more_menu) - public ImageButton moreMenuButton; - @BindView(R.id.password_protected_image_view) - ImageView passwordProtectedImageView; - - RoomItemViewHolder(View view, FlexibleAdapter adapter) { - super(view, adapter); - ButterKnife.bind(this, view); - } - } -} diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java index 0f04addf8..40c3cdf49 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java @@ -65,7 +65,6 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.kennyc.bottomsheet.BottomSheet; import com.nextcloud.talk.R; import com.nextcloud.talk.activities.MainActivity; -import com.nextcloud.talk.adapters.items.CallItem; import com.nextcloud.talk.adapters.items.ConversationItem; import com.nextcloud.talk.adapters.items.GenericTextHeaderItem; import com.nextcloud.talk.api.NcApi; @@ -183,9 +182,9 @@ public class ConversationsListController extends BaseController implements Searc private Disposable roomsQueryDisposable; private Disposable openConversationsQueryDisposable; private FlexibleAdapter adapter; - private List callItems = new ArrayList<>(); - private List callItemsWithHeader = new ArrayList<>(); - private List searchableCallItems = new ArrayList<>(); + private List conversationItems = new ArrayList<>(); + private List conversationItemsWithHeader = new ArrayList<>(); + private final List searchableConversationItems = new ArrayList<>(); private BottomSheet bottomSheet; private MenuItem searchItem; @@ -193,7 +192,6 @@ public class ConversationsListController extends BaseController implements Searc private String searchQuery; private View view; - private boolean shouldUseLastMessageLayout; private String credentials; @@ -246,7 +244,7 @@ public class ConversationsListController extends BaseController implements Searc } if (adapter == null) { - adapter = new FlexibleAdapter<>(callItems, getActivity(), true); + adapter = new FlexibleAdapter<>(conversationItems, getActivity(), true); } else { loadingContent.setVisibility(View.GONE); } @@ -309,8 +307,6 @@ public class ConversationsListController extends BaseController implements Searc } credentials = ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken()); - shouldUseLastMessageLayout = CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, - "last-room-activity"); if (getActivity() != null && getActivity() instanceof MainActivity) { loadUserAvatar(((MainActivity) getActivity()).binding.switchAccountButton); } @@ -372,7 +368,7 @@ public class ConversationsListController extends BaseController implements Searc } else { MainActivity activity = (MainActivity) getActivity(); - searchItem.setVisible(callItems.size() > 0); + searchItem.setVisible(conversationItems.size() > 0); if (activity != null) { if (adapter.hasFilter()) { showSearchView(activity, searchView, searchItem); @@ -409,7 +405,7 @@ public class ConversationsListController extends BaseController implements Searc @Override public boolean onMenuItemActionExpand(MenuItem item) { adapter.setHeadersShown(true); - adapter.updateDataSet(searchableCallItems, false); + adapter.updateDataSet(searchableConversationItems, false); adapter.showAllHeaders(); swipeRefreshLayout.setEnabled(false); return true; @@ -418,7 +414,7 @@ public class ConversationsListController extends BaseController implements Searc @Override public boolean onMenuItemActionCollapse(MenuItem item) { adapter.setHeadersShown(false); - adapter.updateDataSet(callItems, false); + adapter.updateDataSet(conversationItems, false); adapter.hideAllHeaders(); swipeRefreshLayout.setEnabled(true); @@ -478,8 +474,8 @@ public class ConversationsListController extends BaseController implements Searc isRefreshing = true; - callItems = new ArrayList<>(); - callItemsWithHeader = new ArrayList<>(); + conversationItems = new ArrayList<>(); + conversationItemsWithHeader = new ArrayList<>(); int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[]{ApiUtils.APIv4, ApiUtils.APIv3, 1}); @@ -528,41 +524,26 @@ public class ConversationsListController extends BaseController implements Searc callHeaderItems.put(headerTitle, genericTextHeaderItem); } - if (shouldUseLastMessageLayout) { - if (getActivity() != null) { - ConversationItem conversationItem = new ConversationItem( - conversation, - currentUser, - getActivity()); - callItems.add(conversationItem); - - ConversationItem conversationItemWithHeader = new ConversationItem( - conversation, - currentUser, - getActivity(), - callHeaderItems.get(headerTitle)); - - callItemsWithHeader.add(conversationItemWithHeader); - } - } else { - CallItem callItem = new CallItem( - conversation, - currentUser); - callItems.add(callItem); - - CallItem callItemWithHeader = new CallItem( + if (getActivity() != null) { + ConversationItem conversationItem = new ConversationItem( conversation, currentUser, - callHeaderItems.get(headerTitle)); + getActivity()); + conversationItems.add(conversationItem); - callItemsWithHeader.add(callItemWithHeader); + ConversationItem conversationItemWithHeader = new ConversationItem( + conversation, + currentUser, + getActivity(), + callHeaderItems.get(headerTitle)); + conversationItemsWithHeader.add(conversationItemWithHeader); } } - sortConversations(callItems); - sortConversations(callItemsWithHeader); + sortConversations(conversationItems); + sortConversations(conversationItemsWithHeader); - adapter.updateDataSet(callItems, false); + adapter.updateDataSet(conversationItems, false); new Handler().postDelayed(this::checkToShowUnreadBubble, UNREAD_BUBBLE_DELAY); @@ -597,26 +578,20 @@ public class ConversationsListController extends BaseController implements Searc }); } - private void sortConversations(List callItems) { - if (CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, "last-room-activity")) { - Collections.sort(callItems, (o1, o2) -> { - Conversation conversation1 = ((ConversationItem) o1).getModel(); - Conversation conversation2 = ((ConversationItem) o2).getModel(); - return new CompareToBuilder() - .append(conversation2.isFavorite(), conversation1.isFavorite()) - .append(conversation2.getLastActivity(), conversation1.getLastActivity()) - .toComparison(); - }); - } else { - Collections.sort(callItems, (callItem, t1) -> - Long.compare(((CallItem) t1).getModel().getLastPing(), - ((CallItem) callItem).getModel().getLastPing())); - } + private void sortConversations(List conversationItems) { + Collections.sort(conversationItems, (o1, o2) -> { + Conversation conversation1 = ((ConversationItem) o1).getModel(); + Conversation conversation2 = ((ConversationItem) o2).getModel(); + return new CompareToBuilder() + .append(conversation2.isFavorite(), conversation1.isFavorite()) + .append(conversation2.getLastActivity(), conversation1.getLastActivity()) + .toComparison(); + }); } private void fetchOpenConversations(int apiVersion){ - searchableCallItems.clear(); - searchableCallItems.addAll(callItemsWithHeader); + searchableConversationItems.clear(); + searchableConversationItems.addAll(conversationItemsWithHeader); if (CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, "listable-rooms")) { List openConversationItems = new ArrayList<>(); @@ -637,20 +612,15 @@ public class ConversationsListController extends BaseController implements Searc callHeaderItems.put(headerTitle, genericTextHeaderItem); } + ConversationItem conversationItem = new ConversationItem( + conversation, + currentUser, + getActivity(), + callHeaderItems.get(headerTitle)); - if (shouldUseLastMessageLayout) { - if (getActivity() != null) { - ConversationItem conversationItem = new ConversationItem(conversation - , currentUser, getActivity(), callHeaderItems.get(headerTitle)); - openConversationItems.add(conversationItem); - } - } else { - CallItem callItem = new CallItem(conversation, currentUser, callHeaderItems.get(headerTitle)); - openConversationItems.add(callItem); - } + openConversationItems.add(conversationItem); } - - searchableCallItems.addAll(openConversationItems); + searchableConversationItems.addAll(openConversationItems); }, throwable -> { handleHttpExceptions(throwable); @@ -746,7 +716,7 @@ public class ConversationsListController extends BaseController implements Searc private void checkToShowUnreadBubble() { try { int lastVisibleItem = layoutManager.findLastCompletelyVisibleItemPosition(); - for (AbstractFlexibleItem flexItem : callItems) { + for (AbstractFlexibleItem flexItem : conversationItems) { Conversation conversationItem = ((ConversationItem) flexItem).getModel(); int position = adapter.getGlobalPositionOf(flexItem); if ((conversationItem.unreadMention || @@ -902,7 +872,7 @@ public class ConversationsListController extends BaseController implements Searc @Override public boolean onItemClick(View view, int position) { - selectedConversation = getConversation(position); + selectedConversation = ((ConversationItem) Objects.requireNonNull(adapter.getItem(position))).getModel(); if (selectedConversation != null && getActivity() != null) { if (showShareToScreen) { handleSharedData(); @@ -973,20 +943,13 @@ public class ConversationsListController extends BaseController implements Searc @Override public void onItemLongClick(int position) { - if (showShareToScreen) { Log.d(TAG, "sharing to multiple rooms not yet implemented. onItemLongClick is ignored."); - } else if (CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, "last-room-activity")) { + } else { Object clickedItem = adapter.getItem(position); if (clickedItem != null) { - Conversation conversation; - if (shouldUseLastMessageLayout) { - conversation = ((ConversationItem) clickedItem).getModel(); - } else { - conversation = ((CallItem) clickedItem).getModel(); - } - + Conversation conversation = ((ConversationItem) clickedItem).getModel(); MoreMenuClickEvent moreMenuClickEvent = new MoreMenuClickEvent(conversation); onMessageEvent(moreMenuClickEvent); } @@ -1110,17 +1073,6 @@ public class ConversationsListController extends BaseController implements Searc } } - private Conversation getConversation(int position) { - Object clickedItem = adapter.getItem(position); - Conversation conversation; - if (shouldUseLastMessageLayout) { - conversation = ((ConversationItem) clickedItem).getModel(); - } else { - conversation = ((CallItem) clickedItem).getModel(); - } - return conversation; - } - @Subscribe(sticky = true, threadMode = ThreadMode.BACKGROUND) public void onMessageEvent(EventStatus eventStatus) { if (currentUser != null && eventStatus.getUserId() == currentUser.getId()) { diff --git a/app/src/main/res/layout/account_item.xml b/app/src/main/res/layout/account_item.xml index 004cd3f3b..d14829831 100644 --- a/app/src/main/res/layout/account_item.xml +++ b/app/src/main/res/layout/account_item.xml @@ -57,16 +57,6 @@ fresco:placeholderImage="@drawable/account_circle_48dp" fresco:failureImage="@drawable/account_circle_48dp" app:roundAsCircle="true"/> - - @@ -80,7 +70,7 @@ android:paddingStart="3dp" android:paddingEnd="0dp"> - - - - - diff --git a/app/src/main/res/layout/controller_call_menu.xml b/app/src/main/res/layout/controller_call_menu.xml index 85c8d822e..06a836a81 100644 --- a/app/src/main/res/layout/controller_call_menu.xml +++ b/app/src/main/res/layout/controller_call_menu.xml @@ -27,8 +27,7 @@ + android:layout_height="wrap_content" /> diff --git a/app/src/main/res/layout/controller_conversations_rv.xml b/app/src/main/res/layout/controller_conversations_rv.xml index 62b263c5c..d571421cd 100644 --- a/app/src/main/res/layout/controller_conversations_rv.xml +++ b/app/src/main/res/layout/controller_conversations_rv.xml @@ -103,8 +103,7 @@ + android:layout_height="match_parent" /> diff --git a/app/src/main/res/layout/controller_generic_rv.xml b/app/src/main/res/layout/controller_generic_rv.xml index 66cfe6cda..3178906d1 100644 --- a/app/src/main/res/layout/controller_generic_rv.xml +++ b/app/src/main/res/layout/controller_generic_rv.xml @@ -43,6 +43,5 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:layout_anchor="@+id/swipe_refresh_layout" - app:layout_anchorGravity="center" - tools:listitem="@layout/rv_item_conversation" /> + app:layout_anchorGravity="center" /> diff --git a/app/src/main/res/layout/current_account_item.xml b/app/src/main/res/layout/current_account_item.xml new file mode 100644 index 000000000..5e6ab4d57 --- /dev/null +++ b/app/src/main/res/layout/current_account_item.xml @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/dialog_choose_account.xml b/app/src/main/res/layout/dialog_choose_account.xml index 3e84ff898..b15e29920 100644 --- a/app/src/main/res/layout/dialog_choose_account.xml +++ b/app/src/main/res/layout/dialog_choose_account.xml @@ -23,7 +23,7 @@ - - - - - - - - - - - - - - - - - - - - - - From ca7861358db2365be6a3be2452239a5df22d8209 Mon Sep 17 00:00:00 2001 From: drone Date: Wed, 26 Jan 2022 17:02:13 +0000 Subject: [PATCH 4/4] fix klint + findbugs warnings Signed-off-by: Marcel Hibbe --- .../talk/jobs/GetFirebasePushTokenWorker.kt | 35 +++++++++++-------- .../talk/utils/ClosedInterfaceImpl.kt | 12 +++++-- scripts/analysis/findbugs-results.txt | 2 +- scripts/analysis/lint-results.txt | 2 +- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/app/src/gplay/java/com/nextcloud/talk/jobs/GetFirebasePushTokenWorker.kt b/app/src/gplay/java/com/nextcloud/talk/jobs/GetFirebasePushTokenWorker.kt index 38206210a..afc7c7bb7 100644 --- a/app/src/gplay/java/com/nextcloud/talk/jobs/GetFirebasePushTokenWorker.kt +++ b/app/src/gplay/java/com/nextcloud/talk/jobs/GetFirebasePushTokenWorker.kt @@ -42,22 +42,27 @@ class GetFirebasePushTokenWorker(val context: Context, workerParameters: WorkerP @SuppressLint("LongLogTag") override fun doWork(): Result { - FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task -> - if (!task.isSuccessful) { - Log.w(TAG, "Fetching FCM registration token failed", task.exception) - return@OnCompleteListener + FirebaseMessaging.getInstance().token.addOnCompleteListener( + OnCompleteListener { task -> + if (!task.isSuccessful) { + Log.w(TAG, "Fetching FCM registration token failed", task.exception) + return@OnCompleteListener + } + + val token = task.result + + appPreferences?.pushToken = token + + val data: Data = + Data.Builder() + .putString(PushRegistrationWorker.ORIGIN, "GetFirebasePushTokenWorker") + .build() + val pushRegistrationWork = OneTimeWorkRequest.Builder(PushRegistrationWorker::class.java) + .setInputData(data) + .build() + WorkManager.getInstance(context).enqueue(pushRegistrationWork) } - - val token = task.result - - appPreferences?.pushToken = token - - val data: Data = Data.Builder().putString(PushRegistrationWorker.ORIGIN, "GetFirebasePushTokenWorker").build() - val pushRegistrationWork = OneTimeWorkRequest.Builder(PushRegistrationWorker::class.java) - .setInputData(data) - .build() - WorkManager.getInstance(context).enqueue(pushRegistrationWork) - }) + ) return Result.success() } diff --git a/app/src/gplay/java/com/nextcloud/talk/utils/ClosedInterfaceImpl.kt b/app/src/gplay/java/com/nextcloud/talk/utils/ClosedInterfaceImpl.kt index 7dc8ff74d..83edacd4a 100644 --- a/app/src/gplay/java/com/nextcloud/talk/utils/ClosedInterfaceImpl.kt +++ b/app/src/gplay/java/com/nextcloud/talk/utils/ClosedInterfaceImpl.kt @@ -75,7 +75,11 @@ class ClosedInterfaceImpl : ClosedInterface, ProviderInstaller.ProviderInstallLi } private fun registerLocalToken() { - val data: Data = Data.Builder().putString(PushRegistrationWorker.ORIGIN, "ClosedInterfaceImpl#registerLocalToken").build() + val data: Data = Data.Builder().putString( + PushRegistrationWorker.ORIGIN, + "ClosedInterfaceImpl#registerLocalToken" + ) + .build() val pushRegistrationWork = OneTimeWorkRequest.Builder(PushRegistrationWorker::class.java) .setInputData(data) .build() @@ -83,7 +87,11 @@ class ClosedInterfaceImpl : ClosedInterface, ProviderInstaller.ProviderInstallLi } private fun setUpPeriodicLocalTokenRegistration() { - val data: Data = Data.Builder().putString(PushRegistrationWorker.ORIGIN, "ClosedInterfaceImpl#setUpPeriodicLocalTokenRegistration").build() + val data: Data = Data.Builder().putString( + PushRegistrationWorker.ORIGIN, + "ClosedInterfaceImpl#setUpPeriodicLocalTokenRegistration" + ) + .build() val periodicTokenRegistration = PeriodicWorkRequest.Builder( PushRegistrationWorker::class.java, diff --git a/scripts/analysis/findbugs-results.txt b/scripts/analysis/findbugs-results.txt index c02176735..8d28c8c9e 100644 --- a/scripts/analysis/findbugs-results.txt +++ b/scripts/analysis/findbugs-results.txt @@ -1 +1 @@ -558 \ No newline at end of file +554 \ No newline at end of file diff --git a/scripts/analysis/lint-results.txt b/scripts/analysis/lint-results.txt index 7d0dd5fec..96101281e 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 224 warnings + Lint Report: 1 error and 222 warnings