mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-27 17:08:34 +03:00
Initial steps towards #206
This commit is contained in:
parent
0e3f6495cf
commit
22614792df
8 changed files with 286 additions and 63 deletions
|
@ -20,6 +20,7 @@
|
|||
|
||||
package com.nextcloud.talk.adapters.items;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
@ -122,23 +123,36 @@ public class UserItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder>
|
|||
holder.contactDisplayName.setText(participant.getName());
|
||||
}
|
||||
|
||||
GlideUrl glideUrl = new GlideUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
|
||||
participant.getUserId(), R.dimen.avatar_size), new LazyHeaders.Builder()
|
||||
.setHeader("Accept", "image/*")
|
||||
.setHeader("User-Agent", ApiUtils.getUserAgent())
|
||||
.build());
|
||||
if (TextUtils.isEmpty(participant.getSource()) || participant.getSource().equals("users")) {
|
||||
GlideUrl glideUrl = new GlideUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
|
||||
participant.getUserId(), R.dimen.avatar_size), new LazyHeaders.Builder()
|
||||
.setHeader("Accept", "image/*")
|
||||
.setHeader("User-Agent", ApiUtils.getUserAgent())
|
||||
.build());
|
||||
|
||||
int avatarSize = Math.round(NextcloudTalkApplication
|
||||
.getSharedApplication().getResources().getDimension(R.dimen.avatar_size));
|
||||
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());
|
||||
GlideApp.with(NextcloudTalkApplication.getSharedApplication().getApplicationContext())
|
||||
.asBitmap()
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.load(glideUrl)
|
||||
.centerInside()
|
||||
.override(avatarSize, avatarSize)
|
||||
.apply(RequestOptions.bitmapTransform(new CircleCrop()))
|
||||
.into(holder.avatarFlipView.getFrontImageView());
|
||||
} else if (participant.getSource().equals("groups")) {
|
||||
int avatarSize = Math.round(NextcloudTalkApplication.getSharedApplication().getApplicationContext().getResources().getDimension(R.dimen.avatar_size));
|
||||
|
||||
GlideApp.with(NextcloudTalkApplication.getSharedApplication().getApplicationContext())
|
||||
.asBitmap()
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.load(R.drawable.ic_people_group_white_24px)
|
||||
.centerInside()
|
||||
.override(avatarSize, avatarSize)
|
||||
.apply(RequestOptions.bitmapTransform(new CircleCrop()))
|
||||
.into(holder.avatarFlipView.getFrontImageView());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -39,9 +39,11 @@ import com.nextcloud.talk.models.json.signaling.SignalingOverall;
|
|||
import com.nextcloud.talk.models.json.signaling.settings.SignalingSettingsOverall;
|
||||
import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.Response;
|
||||
import retrofit2.http.DELETE;
|
||||
import retrofit2.http.Field;
|
||||
|
@ -65,10 +67,15 @@ public interface NcApi {
|
|||
- "itemType" : "call"
|
||||
|
||||
Server URL is: baseUrl + ocsApiVersion + /apps/files_sharing/api/v1/sharees
|
||||
|
||||
or if we're on 14 and up:
|
||||
|
||||
baseUrl + ocsApiVersion + "/core/autocomplete/get");
|
||||
|
||||
*/
|
||||
@GET
|
||||
Observable<Response<ShareesOverall>> getContactsWithSearchParam(@Header("Authorization") String authorization, @Url String url,
|
||||
@QueryMap Map<String, Object> options);
|
||||
Observable<ResponseBody> getContactsWithSearchParam(@Header("Authorization") String authorization, @Url String url,
|
||||
@Nullable @Query("shareTypes[]") List<String> listOfShareTypes, @QueryMap Map<String, Object> options);
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -27,6 +27,8 @@ import android.os.Bundle;
|
|||
import android.os.Handler;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.bluelinelabs.logansquare.LoganSquare;
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
import androidx.core.view.MenuItemCompat;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
@ -34,6 +36,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import androidx.appcompat.widget.SearchView;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
|
@ -60,6 +63,8 @@ import com.nextcloud.talk.controllers.bottomsheet.OperationsMenuController;
|
|||
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
||||
import com.nextcloud.talk.models.RetrofitBucket;
|
||||
import com.nextcloud.talk.models.database.UserEntity;
|
||||
import com.nextcloud.talk.models.json.autocomplete.AutocompleteOverall;
|
||||
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser;
|
||||
import com.nextcloud.talk.models.json.participants.Participant;
|
||||
import com.nextcloud.talk.models.json.rooms.Conversation;
|
||||
import com.nextcloud.talk.models.json.rooms.RoomOverall;
|
||||
|
@ -99,6 +104,7 @@ import io.reactivex.Observer;
|
|||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.HttpException;
|
||||
import retrofit2.Response;
|
||||
|
||||
|
@ -413,6 +419,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
|||
|
||||
alreadyFetching = true;
|
||||
Set<Sharee> shareeHashSet = new HashSet<>();
|
||||
Set<AutocompleteUser> autocompleteUsersHashSet = new HashSet<>();
|
||||
|
||||
userHeaderItems = new HashMap<>();
|
||||
|
||||
|
@ -424,8 +431,15 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
|||
contactItems = new ArrayList<>();
|
||||
}
|
||||
|
||||
RetrofitBucket retrofitBucket = ApiUtils.getRetrofitBucketForContactsSearch(currentUser.getBaseUrl(),
|
||||
query);
|
||||
RetrofitBucket retrofitBucket;
|
||||
boolean serverIs14OrUp = false;
|
||||
if (currentUser.hasSpreedCapabilityWithName("last-room-activity")) {
|
||||
// a hack to see if we're on 14 or not
|
||||
retrofitBucket = ApiUtils.getRetrofitBucketForContactsSearchFor14(currentUser.getBaseUrl(), query);
|
||||
serverIs14OrUp = true;
|
||||
} else {
|
||||
retrofitBucket = ApiUtils.getRetrofitBucketForContactsSearch(currentUser.getBaseUrl(), query);
|
||||
}
|
||||
|
||||
int page = 1;
|
||||
if (!startFromScratch) {
|
||||
|
@ -439,73 +453,127 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
|||
Map<String, Object> modifiedQueryMap = new HashMap<>(retrofitBucket.getQueryMap());
|
||||
modifiedQueryMap.put("page", page);
|
||||
modifiedQueryMap.put("perPage", 100);
|
||||
|
||||
List<String> shareTypesList = null;
|
||||
|
||||
if (serverIs14OrUp) {
|
||||
shareTypesList = new ArrayList<>();
|
||||
// users
|
||||
shareTypesList.add("0");
|
||||
// groups
|
||||
shareTypesList.add("1");
|
||||
|
||||
modifiedQueryMap.put("shareTypes[]", shareTypesList);
|
||||
}
|
||||
|
||||
boolean finalServerIs14OrUp = serverIs14OrUp;
|
||||
ncApi.getContactsWithSearchParam(
|
||||
credentials,
|
||||
retrofitBucket.getUrl(), modifiedQueryMap)
|
||||
retrofitBucket.getUrl(), shareTypesList, modifiedQueryMap)
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.retry(3)
|
||||
.subscribe(new Observer<Response>() {
|
||||
.subscribe(new Observer<ResponseBody>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
contactsQueryDisposable = d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(Response response) {
|
||||
if (response.body() != null) {
|
||||
ShareesOverall shareesOverall = (ShareesOverall) response.body();
|
||||
|
||||
if (shareesOverall.getOcs().getData().getUsers() != null) {
|
||||
shareeHashSet.addAll(shareesOverall.getOcs().getData().getUsers());
|
||||
}
|
||||
|
||||
if (shareesOverall.getOcs().getData().getExactUsers() != null &&
|
||||
shareesOverall.getOcs().getData().getExactUsers().getExactSharees() != null) {
|
||||
shareeHashSet.addAll(shareesOverall.getOcs().getData().
|
||||
getExactUsers().getExactSharees());
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty((CharSequence) modifiedQueryMap.get("search"))) {
|
||||
canFetchFurther = !shareeHashSet.isEmpty();
|
||||
currentPage = (int) modifiedQueryMap.get("page");
|
||||
} else {
|
||||
canFetchSearchFurther = !shareeHashSet.isEmpty();
|
||||
currentSearchPage = (int) modifiedQueryMap.get("page");
|
||||
}
|
||||
|
||||
|
||||
public void onNext(ResponseBody responseBody) {
|
||||
if (responseBody != null) {
|
||||
Participant participant;
|
||||
|
||||
List<AbstractFlexibleItem> newUserItemList = new ArrayList<>();
|
||||
newUserItemList.addAll(contactItems);
|
||||
for (Sharee sharee : shareeHashSet) {
|
||||
if (!sharee.getValue().getShareWith().equals(currentUser.getUsername())) {
|
||||
participant = new Participant();
|
||||
participant.setName(sharee.getLabel());
|
||||
String headerTitle;
|
||||
|
||||
headerTitle = sharee.getLabel().substring(0, 1).toUpperCase();
|
||||
try {
|
||||
if (!finalServerIs14OrUp) {
|
||||
ShareesOverall shareesOverall = LoganSquare.parse(responseBody.string(), ShareesOverall.class);
|
||||
|
||||
UserHeaderItem userHeaderItem;
|
||||
if (!userHeaderItems.containsKey(headerTitle)) {
|
||||
userHeaderItem = new UserHeaderItem(headerTitle);
|
||||
userHeaderItems.put(headerTitle, userHeaderItem);
|
||||
if (shareesOverall.getOcs().getData().getUsers() != null) {
|
||||
shareeHashSet.addAll(shareesOverall.getOcs().getData().getUsers());
|
||||
}
|
||||
|
||||
participant.setUserId(sharee.getValue().getShareWith());
|
||||
|
||||
UserItem newContactItem = new UserItem(participant, currentUser,
|
||||
userHeaderItems.get(headerTitle));
|
||||
|
||||
if (!contactItems.contains(newContactItem)) {
|
||||
newUserItemList.add(newContactItem);
|
||||
if (shareesOverall.getOcs().getData().getExactUsers() != null &&
|
||||
shareesOverall.getOcs().getData().getExactUsers().getExactSharees() != null) {
|
||||
shareeHashSet.addAll(shareesOverall.getOcs().getData().
|
||||
getExactUsers().getExactSharees());
|
||||
}
|
||||
|
||||
for (Sharee sharee : shareeHashSet) {
|
||||
if (!sharee.getValue().getShareWith().equals(currentUser.getUserId())) {
|
||||
participant = new Participant();
|
||||
participant.setName(sharee.getLabel());
|
||||
String headerTitle;
|
||||
|
||||
headerTitle = sharee.getLabel().substring(0, 1).toUpperCase();
|
||||
|
||||
UserHeaderItem userHeaderItem;
|
||||
if (!userHeaderItems.containsKey(headerTitle)) {
|
||||
userHeaderItem = new UserHeaderItem(headerTitle);
|
||||
userHeaderItems.put(headerTitle, userHeaderItem);
|
||||
}
|
||||
|
||||
participant.setUserId(sharee.getValue().getShareWith());
|
||||
|
||||
UserItem newContactItem = new UserItem(participant, currentUser,
|
||||
userHeaderItems.get(headerTitle));
|
||||
|
||||
if (!contactItems.contains(newContactItem)) {
|
||||
newUserItemList.add(newContactItem);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
AutocompleteOverall autocompleteOverall = LoganSquare.parse(responseBody.string(), AutocompleteOverall.class);
|
||||
autocompleteUsersHashSet.addAll(autocompleteOverall.getOcs().getData());
|
||||
|
||||
for (AutocompleteUser autocompleteUser : autocompleteUsersHashSet) {
|
||||
if (!autocompleteUser.getId().equals(currentUser.getUserId())) {
|
||||
participant = new Participant();
|
||||
participant.setName(autocompleteUser.getLabel());
|
||||
participant.setUserId(autocompleteUser.getId());
|
||||
participant.setSource(autocompleteUser.getSource());
|
||||
|
||||
String headerTitle;
|
||||
|
||||
headerTitle = participant.getName().substring(0, 1).toUpperCase();
|
||||
|
||||
UserHeaderItem userHeaderItem;
|
||||
if (!userHeaderItems.containsKey(headerTitle)) {
|
||||
userHeaderItem = new UserHeaderItem(headerTitle);
|
||||
userHeaderItems.put(headerTitle, userHeaderItem);
|
||||
}
|
||||
|
||||
participant.setUserId(participant.getUserId());
|
||||
|
||||
UserItem newContactItem = new UserItem(participant, currentUser,
|
||||
userHeaderItems.get(headerTitle));
|
||||
|
||||
if (!contactItems.contains(newContactItem)) {
|
||||
newUserItemList.add(newContactItem);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception exception) {
|
||||
Log.e(TAG, "Parsing response body failed while getting contacts");
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty((CharSequence) modifiedQueryMap.get("search"))) {
|
||||
canFetchFurther = !shareeHashSet.isEmpty() || (finalServerIs14OrUp && !autocompleteUsersHashSet.isEmpty());
|
||||
currentPage = (int) modifiedQueryMap.get("page");
|
||||
} else {
|
||||
canFetchSearchFurther = !shareeHashSet.isEmpty() || (finalServerIs14OrUp && !autocompleteUsersHashSet.isEmpty()) ;
|
||||
currentSearchPage = (int) modifiedQueryMap.get("page");
|
||||
}
|
||||
|
||||
|
||||
|
||||
boolean shouldFilterManually = false;
|
||||
if (newUserItemList.size() == contactItems.size()) {
|
||||
|
@ -554,7 +622,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
|||
checkAndHandleDoneMenuItem();
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.models.json.autocomplete;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.nextcloud.talk.models.json.generic.GenericOCS;
|
||||
import com.nextcloud.talk.models.json.sharees.SharesData;
|
||||
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Parcel
|
||||
@Data
|
||||
@JsonObject
|
||||
public class AutocompleteOCS extends GenericOCS {
|
||||
@JsonField(name = "data")
|
||||
List<AutocompleteUser> data;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.models.json.autocomplete;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.nextcloud.talk.models.json.sharees.ShareesOCS;
|
||||
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Parcel
|
||||
@Data
|
||||
@JsonObject
|
||||
public class AutocompleteOverall {
|
||||
@JsonField(name = "ocs")
|
||||
AutocompleteOCS ocs;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.models.json.autocomplete;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.nextcloud.talk.models.json.sharees.Value;
|
||||
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Parcel
|
||||
@Data
|
||||
@JsonObject
|
||||
public class AutocompleteUser {
|
||||
@JsonField(name = "id")
|
||||
String id;
|
||||
|
||||
@JsonField(name = "label")
|
||||
String label;
|
||||
|
||||
@JsonField(name = "source")
|
||||
String source;
|
||||
}
|
|
@ -52,6 +52,8 @@ public class Participant {
|
|||
@JsonField(name = "inCall")
|
||||
boolean inCall;
|
||||
|
||||
String source;
|
||||
|
||||
public enum ParticipantType {
|
||||
DUMMY,
|
||||
OWNER,
|
||||
|
|
|
@ -28,7 +28,9 @@ import com.nextcloud.talk.R;
|
|||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
import com.nextcloud.talk.models.RetrofitBucket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import okhttp3.Credentials;
|
||||
|
@ -61,6 +63,16 @@ public class ApiUtils {
|
|||
return retrofitBucket;
|
||||
}
|
||||
|
||||
public static RetrofitBucket getRetrofitBucketForContactsSearchFor14(String baseUrl, @Nullable String searchQuery) {
|
||||
RetrofitBucket retrofitBucket = getRetrofitBucketForContactsSearch(baseUrl, searchQuery);
|
||||
retrofitBucket.setUrl(baseUrl + ocsApiVersion + "/core/autocomplete/get");
|
||||
|
||||
retrofitBucket.getQueryMap().put("itemId", "new");
|
||||
|
||||
return retrofitBucket;
|
||||
}
|
||||
|
||||
|
||||
public static String getUrlForSettingMyselfAsActiveParticipant(String baseUrl, String token) {
|
||||
return getRoom(baseUrl, token) + "/participants/active";
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue