Initial steps towards #206

This commit is contained in:
Mario Danic 2018-10-23 21:36:04 +02:00
parent 0e3f6495cf
commit 22614792df
8 changed files with 286 additions and 63 deletions

View file

@ -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

View file

@ -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);
/*

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -52,6 +52,8 @@ public class Participant {
@JsonField(name = "inCall")
boolean inCall;
String source;
public enum ParticipantType {
DUMMY,
OWNER,

View file

@ -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";
}