From fce49d717e75b35f1b2932b9e3b4cd20042fd699 Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Fri, 4 May 2018 03:59:27 +0200 Subject: [PATCH] Initial mention implementation Signed-off-by: Mario Danic --- app/build.gradle | 1 + .../items/MentionAutocompleteItem.java | 116 +++++++++++++ .../talk/adapters/items/UserItem.java | 4 + .../java/com/nextcloud/talk/api/NcApi.java | 8 + .../MentionAutocompleteCallback.java | 45 ++++++ .../talk/controllers/ChatController.java | 39 +++++ .../talk/models/json/chat/ChatOCS.java | 4 +- .../talk/models/json/generic/GenericMeta.java | 2 +- .../talk/models/json/mention/Mention.java | 42 +++++ .../talk/models/json/mention/MentionOCS.java | 38 +++++ .../models/json/mention/MentionOverall.java | 35 ++++ .../MentionAutocompletePresenter.java | 153 ++++++++++++++++++ .../com/nextcloud/talk/utils/ApiUtils.java | 4 + .../talk/utils/database/user/UserUtils.java | 3 +- app/src/main/res/layout/rv_item_mention.xml | 78 +++++++++ 15 files changed, 568 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java create mode 100644 app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java create mode 100644 app/src/main/java/com/nextcloud/talk/models/json/mention/Mention.java create mode 100644 app/src/main/java/com/nextcloud/talk/models/json/mention/MentionOCS.java create mode 100644 app/src/main/java/com/nextcloud/talk/models/json/mention/MentionOverall.java create mode 100644 app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java create mode 100644 app/src/main/res/layout/rv_item_mention.xml diff --git a/app/build.gradle b/app/build.gradle index c3e6fa979..1c1df3de7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -151,6 +151,7 @@ dependencies { implementation 'com.github.wooplr:Spotlight:1.2.3' implementation 'com.github.stfalcon:chatkit:0.2.2' + implementation 'com.otaliastudios:autocomplete:1.1.0' implementation 'com.github.Kennyc1012:BottomSheet:2.4.0' implementation 'eu.davidea:flipview:1.1.3' diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java new file mode 100644 index 000000000..1deb90905 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java @@ -0,0 +1,116 @@ +/* + * 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 . + */ + +package com.nextcloud.talk.adapters.items; + +import android.view.View; + +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.load.model.GlideUrl; +import com.bumptech.glide.load.model.LazyHeaders; +import com.bumptech.glide.load.resource.bitmap.CircleCrop; +import com.bumptech.glide.request.RequestOptions; +import com.nextcloud.talk.R; +import com.nextcloud.talk.application.NextcloudTalkApplication; +import com.nextcloud.talk.models.database.UserEntity; +import com.nextcloud.talk.utils.ApiUtils; +import com.nextcloud.talk.utils.glide.GlideApp; + +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +import eu.davidea.flexibleadapter.FlexibleAdapter; +import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; +import eu.davidea.flexibleadapter.items.IFilterable; +import eu.davidea.flexibleadapter.items.IFlexible; + +public class MentionAutocompleteItem extends AbstractFlexibleItem + implements IFilterable { + + private String userId; + private String displayName; + private UserEntity currentUser; + + public MentionAutocompleteItem(String userId, String displayName, UserEntity currentUser) { + this.userId = userId; + this.displayName = displayName; + this.currentUser = currentUser; + } + + public String getUserId() { + return userId; + } + + public String getDisplayName() { + return displayName; + } + + @Override + public boolean equals(Object o) { + if (o instanceof MentionAutocompleteItem) { + MentionAutocompleteItem inItem = (MentionAutocompleteItem) o; + return (userId.equals(inItem.userId) && displayName.equals(inItem.displayName)); + } + + return false; + } + + @Override + public int getLayoutRes() { + return R.layout.rv_item_mention; + } + + @Override + public UserItem.UserItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { + return new UserItem.UserItemViewHolder(view, adapter); + } + + + @Override + public void bindViewHolder(FlexibleAdapter adapter, UserItem.UserItemViewHolder holder, int position, List payloads) { + holder.contactDisplayName.setText(displayName); + holder.contactMentionId.setText("@" + userId); + + GlideUrl glideUrl = new GlideUrl(ApiUtils.getUrlForAvatarWithName(currentUser.getBaseUrl(), + userId, false), new LazyHeaders.Builder() + .setHeader("Accept", "image/*") + .setHeader("User-Agent", ApiUtils.getUserAgent()) + .build()); + + int avatarSize = Math.round(NextcloudTalkApplication + .getSharedApplication().getResources().getDimension(R.dimen.avatar_size)); + + GlideApp.with(NextcloudTalkApplication.getSharedApplication().getApplicationContext()) + .asBitmap() + .diskCacheStrategy(DiskCacheStrategy.NONE) + .load(glideUrl) + .centerInside() + .override(avatarSize, avatarSize) + .apply(RequestOptions.bitmapTransform(new CircleCrop())) + .into(holder.avatarFlipView.getFrontImageView()); + } + + @Override + public boolean filter(String constraint) { + return userId != null && StringUtils.containsIgnoreCase(userId, constraint); + + } +} 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 index a731ea999..a4730d1da 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java @@ -39,6 +39,8 @@ import org.apache.commons.lang3.StringUtils; import java.util.List; +import javax.annotation.Nullable; + import butterknife.BindView; import butterknife.ButterKnife; import eu.davidea.flexibleadapter.FlexibleAdapter; @@ -161,6 +163,8 @@ public class UserItem extends AbstractFlexibleItem public TextView contactDisplayName; @BindView(R.id.avatar_flip_view) public FlipView avatarFlipView; + @Nullable @BindView(R.id.secondary_text) + public TextView contactMentionId; /** * Default constructor. diff --git a/app/src/main/java/com/nextcloud/talk/api/NcApi.java b/app/src/main/java/com/nextcloud/talk/api/NcApi.java index 56f16d316..902e2dacd 100644 --- a/app/src/main/java/com/nextcloud/talk/api/NcApi.java +++ b/app/src/main/java/com/nextcloud/talk/api/NcApi.java @@ -27,6 +27,7 @@ import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall; import com.nextcloud.talk.models.json.chat.ChatOverall; import com.nextcloud.talk.models.json.generic.GenericOverall; import com.nextcloud.talk.models.json.generic.Status; +import com.nextcloud.talk.models.json.mention.MentionOverall; import com.nextcloud.talk.models.json.participants.AddParticipantOverall; import com.nextcloud.talk.models.json.participants.ParticipantsOverall; import com.nextcloud.talk.models.json.push.PushRegistrationOverall; @@ -49,6 +50,7 @@ import retrofit2.http.GET; import retrofit2.http.Header; import retrofit2.http.POST; import retrofit2.http.PUT; +import retrofit2.http.Query; import retrofit2.http.QueryMap; import retrofit2.http.Url; @@ -282,4 +284,10 @@ public interface NcApi { @FieldMap Map fields); + //@Headers("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0") + @GET + Observable getMentionAutocompleteSuggestions(@Header("Authorization") String authorization, + @Url String url, @Query("search") String query, + @Nullable @Query("limit") Integer limit); + } diff --git a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java new file mode 100644 index 000000000..2ab795fc0 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java @@ -0,0 +1,45 @@ +/* + * 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 . + */ + +package com.nextcloud.talk.callbacks; + +import android.text.Editable; + +import com.nextcloud.talk.models.json.mention.Mention; +import com.otaliastudios.autocomplete.AutocompleteCallback; +import com.otaliastudios.autocomplete.CharPolicy; + +public class MentionAutocompleteCallback implements AutocompleteCallback { + @Override + public boolean onPopupItemClicked(Editable editable, Mention item) { + int[] range = CharPolicy.getQueryRange(editable); + if (range == null) return false; + int start = range[0]; + int end = range[1]; + String replacement = item.getId() + " "; + editable.replace(start, end, replacement); + return true; + } + + @Override + public void onPopupVisibilityChanged(boolean shown) { + + } +} diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java index 3bb8fd0cf..f9772b9ac 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java @@ -22,6 +22,9 @@ package com.nextcloud.talk.controllers; import android.content.Intent; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v7.widget.LinearLayoutManager; @@ -32,6 +35,7 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; import android.widget.ImageView; import com.bluelinelabs.conductor.RouterTransaction; @@ -44,6 +48,7 @@ import com.nextcloud.talk.activities.CallActivity; import com.nextcloud.talk.adapters.messages.MagicIncomingTextMessageViewHolder; import com.nextcloud.talk.api.NcApi; import com.nextcloud.talk.application.NextcloudTalkApplication; +import com.nextcloud.talk.callbacks.MentionAutocompleteCallback; import com.nextcloud.talk.controllers.base.BaseController; import com.nextcloud.talk.models.database.UserEntity; import com.nextcloud.talk.models.json.call.Call; @@ -51,10 +56,16 @@ import com.nextcloud.talk.models.json.call.CallOverall; import com.nextcloud.talk.models.json.chat.ChatMessage; import com.nextcloud.talk.models.json.chat.ChatOverall; import com.nextcloud.talk.models.json.generic.GenericOverall; +import com.nextcloud.talk.models.json.mention.Mention; +import com.nextcloud.talk.presenters.MentionAutocompletePresenter; import com.nextcloud.talk.utils.ApiUtils; import com.nextcloud.talk.utils.bundle.BundleKeys; import com.nextcloud.talk.utils.database.user.UserUtils; import com.nextcloud.talk.utils.glide.GlideApp; +import com.otaliastudios.autocomplete.Autocomplete; +import com.otaliastudios.autocomplete.AutocompleteCallback; +import com.otaliastudios.autocomplete.AutocompletePresenter; +import com.otaliastudios.autocomplete.CharPolicy; import com.stfalcon.chatkit.commons.ImageLoader; import com.stfalcon.chatkit.messages.MessageInput; import com.stfalcon.chatkit.messages.MessagesList; @@ -106,6 +117,15 @@ public class ChatController extends BaseController implements MessagesListAdapte private MessagesListAdapter adapter; private Menu globalMenu; + private Autocomplete mentionAutocomplete; + /* + TODO: + - format mentions + - copy message + - autocomplete nicks + - check push notifications + - new conversation handling + */ public ChatController(Bundle args) { super(args); setHasOptionsMenu(true); @@ -155,6 +175,10 @@ public class ChatController extends BaseController implements MessagesListAdapte adapter.setDateHeadersFormatter(this::format); //adapter.enableSelectionMode(this); + + setupMentionAutocomplete(); + + messageInput.getInputEditText().setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); messageInput.setInputListener(input -> { sendMessage(input.toString()); return true; @@ -165,6 +189,21 @@ public class ChatController extends BaseController implements MessagesListAdapte } } + private void setupMentionAutocomplete() { + float elevation = 6f; + Drawable backgroundDrawable = new ColorDrawable(Color.WHITE); + AutocompletePresenter presenter = new MentionAutocompletePresenter(getApplicationContext(), roomToken); + AutocompleteCallback callback = new MentionAutocompleteCallback(); + + mentionAutocomplete = Autocomplete.on(messageInput.getInputEditText()) + .with(elevation) + .with(backgroundDrawable) + .with(new CharPolicy('@')) + .with(presenter) + .with(callback) + .build(); + } + @Override protected void onAttach(@NonNull View view) { super.onAttach(view); diff --git a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCS.java b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCS.java index b39952570..d09144094 100644 --- a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCS.java +++ b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCS.java @@ -27,12 +27,14 @@ import org.parceler.Parcel; import java.util.List; +import javax.annotation.Nullable; + import lombok.Data; @Data @Parcel @JsonObject public class ChatOCS extends GenericOCS { - @JsonField(name = "data") + @Nullable @JsonField(name = "data") List data; } diff --git a/app/src/main/java/com/nextcloud/talk/models/json/generic/GenericMeta.java b/app/src/main/java/com/nextcloud/talk/models/json/generic/GenericMeta.java index 24a856f5f..ef375d3c9 100644 --- a/app/src/main/java/com/nextcloud/talk/models/json/generic/GenericMeta.java +++ b/app/src/main/java/com/nextcloud/talk/models/json/generic/GenericMeta.java @@ -29,7 +29,7 @@ import lombok.Data; @Parcel @Data -@JsonObject +@JsonObject(serializeNullObjects = true) public class GenericMeta { @JsonField(name = "status") String status; diff --git a/app/src/main/java/com/nextcloud/talk/models/json/mention/Mention.java b/app/src/main/java/com/nextcloud/talk/models/json/mention/Mention.java new file mode 100644 index 000000000..a5b264aa0 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/models/json/mention/Mention.java @@ -0,0 +1,42 @@ +/* + * 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 . + */ +package com.nextcloud.talk.models.json.mention; + +import com.bluelinelabs.logansquare.annotation.JsonField; +import com.bluelinelabs.logansquare.annotation.JsonObject; + +import org.parceler.Parcel; + +import lombok.Data; + +@Parcel +@Data +@JsonObject +public class Mention { + @JsonField(name = "id") + String id; + + @JsonField(name = "label") + String label; + + // type of user (guests or users) + @JsonField(name = "source") + String source; +} diff --git a/app/src/main/java/com/nextcloud/talk/models/json/mention/MentionOCS.java b/app/src/main/java/com/nextcloud/talk/models/json/mention/MentionOCS.java new file mode 100644 index 000000000..2d5faf7bf --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/models/json/mention/MentionOCS.java @@ -0,0 +1,38 @@ +/* + * 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 . + */ +package com.nextcloud.talk.models.json.mention; + +import com.bluelinelabs.logansquare.annotation.JsonField; +import com.bluelinelabs.logansquare.annotation.JsonObject; +import com.nextcloud.talk.models.json.generic.GenericOCS; + +import org.parceler.Parcel; + +import java.util.List; + +import lombok.Data; + +@Data +@Parcel +@JsonObject +public class MentionOCS extends GenericOCS { + @JsonField(name = "data") + List data; +} diff --git a/app/src/main/java/com/nextcloud/talk/models/json/mention/MentionOverall.java b/app/src/main/java/com/nextcloud/talk/models/json/mention/MentionOverall.java new file mode 100644 index 000000000..b8b4e8afa --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/models/json/mention/MentionOverall.java @@ -0,0 +1,35 @@ +/* + * 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 . + */ +package com.nextcloud.talk.models.json.mention; + +import com.bluelinelabs.logansquare.annotation.JsonField; +import com.bluelinelabs.logansquare.annotation.JsonObject; + +import org.parceler.Parcel; + +import lombok.Data; + +@Data +@Parcel +@JsonObject +public class MentionOverall { + @JsonField(name = "ocs") + MentionOCS ocs; +} diff --git a/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java b/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java new file mode 100644 index 000000000..cced3c8c3 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java @@ -0,0 +1,153 @@ +/* + * 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 . + */ + +package com.nextcloud.talk.presenters; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.nextcloud.talk.adapters.items.MentionAutocompleteItem; +import com.nextcloud.talk.api.NcApi; +import com.nextcloud.talk.application.NextcloudTalkApplication; +import com.nextcloud.talk.models.database.UserEntity; +import com.nextcloud.talk.models.json.mention.Mention; +import com.nextcloud.talk.models.json.mention.MentionOverall; +import com.nextcloud.talk.utils.ApiUtils; +import com.nextcloud.talk.utils.database.user.UserUtils; +import com.otaliastudios.autocomplete.RecyclerViewPresenter; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import autodagger.AutoInjector; +import eu.davidea.flexibleadapter.FlexibleAdapter; +import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; +import io.reactivex.Observer; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; + +@AutoInjector(NextcloudTalkApplication.class) +public class MentionAutocompletePresenter extends RecyclerViewPresenter implements FlexibleAdapter.OnItemClickListener { + @Inject + NcApi ncApi; + + @Inject + UserUtils userUtils; + + private FlexibleAdapter adapter; + private Context context; + + private String roomToken; + private List userItemList = new ArrayList<>(); + + public MentionAutocompletePresenter(Context context) { + super(context); + this.context = context; + NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this); + } + + public MentionAutocompletePresenter(Context context, String roomToken) { + super(context); + this.roomToken = roomToken; + this.context = context; + NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this); + } + + @Override + protected RecyclerView.Adapter instantiateAdapter() { + adapter = new FlexibleAdapter<>(userItemList, context, true); + adapter.addListener(this); + return adapter; + } + + @Override + protected void onQuery(@Nullable CharSequence query) { + if (query != null && query.length() > 0) { + UserEntity currentUser = userUtils.getCurrentUser(); + + ncApi.getMentionAutocompleteSuggestions(ApiUtils.getCredentials(currentUser.getUserId(), currentUser + .getToken()), ApiUtils.getUrlForMentionSuggestions(currentUser.getBaseUrl(), roomToken), + query.toString(), null) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .retry(3) + .subscribe(new Observer() { + @Override + public void onSubscribe(Disposable d) { + } + + @Override + public void onNext(MentionOverall mentionOverall) { + List mentionsList = mentionOverall.getOcs().getData(); + userItemList = new ArrayList<>(); + if (mentionsList.size() == 1 && mentionsList.get(0).getId().equals(query.toString())) { + adapter.updateDataSet(userItemList, false); + clearRecycledPool(); + } else { + for (Mention mention : mentionsList) { + userItemList.add(new MentionAutocompleteItem(mention.getId(), mention + .getLabel(), currentUser)); + } + adapter.updateDataSet(userItemList, true); + clearRecycledPool(); + } + } + + @Override + public void onError(Throwable e) { + userItemList = new ArrayList<>(); + adapter.updateDataSet(userItemList, false); + clearRecycledPool(); + } + + @Override + public void onComplete() { + + } + }); + } else { + userItemList = new ArrayList<>(); + adapter.updateDataSet(userItemList, false); + clearRecycledPool(); + } + } + + private void clearRecycledPool() { + if (getRecyclerView() != null) { + getRecyclerView().getRecycledViewPool().clear(); + } + } + + @Override + public boolean onItemClick(View view, int position) { + Mention mention = new Mention(); + MentionAutocompleteItem mentionAutocompleteItem = (MentionAutocompleteItem) userItemList.get(position); + mention.setId(mentionAutocompleteItem.getUserId()); + mention.setLabel(mentionAutocompleteItem.getDisplayName()); + mention.setSource("users"); + dispatchClick(mention); + 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 0b71fa5dd..7783a80af 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java @@ -130,6 +130,10 @@ public class ApiUtils { return baseUrl + ocsApiVersion + spreedApiVersion + "/chat/" + token; } + public static String getUrlForMentionSuggestions(String baseUrl, String token) { + return getUrlForChat(baseUrl, token) + "/mentions"; + } + public static String getUrlForSignaling(String baseUrl, @Nullable String token) { String signalingUrl = baseUrl + ocsApiVersion + spreedApiVersion + "/signaling"; if (token == null) { diff --git a/app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java b/app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java index 562bd82bf..06f8e1281 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java @@ -245,8 +245,7 @@ public class UserUtils { return dataStore.upsert(user) .toObservable() - .subscribeOn(Schedulers.newThread()) - .observeOn(AndroidSchedulers.mainThread()); + .subscribeOn(Schedulers.newThread()); } } diff --git a/app/src/main/res/layout/rv_item_mention.xml b/app/src/main/res/layout/rv_item_mention.xml new file mode 100644 index 000000000..344e0c612 --- /dev/null +++ b/app/src/main/res/layout/rv_item_mention.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + +