mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-26 23:25:20 +03:00
add open conversations to search
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
8969f4b11f
commit
1de2261426
6 changed files with 203 additions and 49 deletions
|
@ -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<CallItem.RoomItemViewHolder> implements IFilterable<String> {
|
||||
public class CallItem extends AbstractFlexibleItem<CallItem.RoomItemViewHolder> implements ISectionable<CallItem.RoomItemViewHolder, GenericTextHeaderItem>, IFilterable<String> {
|
||||
|
||||
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<CallItem.RoomItemViewHolder>
|
|||
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)
|
||||
|
|
|
@ -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<ConversationItem.ConversationItemViewHolder> implements
|
||||
public class ConversationItem extends AbstractFlexibleItem<ConversationItem.ConversationItemViewHolder> implements ISectionable<ConversationItem.ConversationItemViewHolder, GenericTextHeaderItem>,
|
||||
IFilterable<String> {
|
||||
|
||||
|
||||
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<ConversationItem.Conv
|
|||
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 ConversationItemViewHolder extends FlexibleViewHolder {
|
||||
@BindView(R.id.dialogAvatar)
|
||||
SimpleDraweeView dialogAvatar;
|
||||
|
|
|
@ -436,4 +436,11 @@ public interface NcApi {
|
|||
Observable<GenericOverall> setChatReadMarker(@Header("Authorization") String authorization,
|
||||
@Url String url,
|
||||
@Field("lastReadMessage") int lastReadMessage);
|
||||
|
||||
/*
|
||||
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /listed-room
|
||||
*/
|
||||
@GET
|
||||
Observable<RoomsOverall> getOpenConversations(@Header("Authorization") String authorization, @Url String url);
|
||||
|
||||
}
|
||||
|
|
|
@ -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<AbstractFlexibleItem> adapter;
|
||||
private List<AbstractFlexibleItem> callItems = new ArrayList<>();
|
||||
private List<AbstractFlexibleItem> callItemsWithHeader = new ArrayList<>();
|
||||
private List<AbstractFlexibleItem> 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<String, GenericTextHeaderItem> 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<AbstractFlexibleItem> 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<AbstractFlexibleItem> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -273,6 +273,8 @@
|
|||
|
||||
<!-- Conversations List-->
|
||||
<string name="nc_new_mention">Unread mentions</string>
|
||||
<string name="conversations">Conversations</string>
|
||||
<string name="openConversations">Open conversations</string>
|
||||
|
||||
<!-- Chat -->
|
||||
<string name="nc_hint_enter_a_message">Enter a message…</string>
|
||||
|
@ -492,4 +494,5 @@
|
|||
<string name="take_photo_send">Send</string>
|
||||
<string name="take_photo_error_deleting_picture">Error taking picture</string>
|
||||
<string name="take_photo_permission">Taking a photo is not possible without permissions</string>
|
||||
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue