mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-21 20:49:36 +01:00
Merge pull request #1285 from nextcloud/bug/992/fixDesignWhenKeyboardShown
fix design when keyboard is shown
This commit is contained in:
commit
db1071d2ee
@ -266,7 +266,6 @@ dependencies {
|
||||
|
||||
implementation 'com.novoda:merlin:1.2.1'
|
||||
|
||||
implementation 'com.github.Kennyc1012:BottomSheet:2.4.1'
|
||||
implementation 'com.github.nextcloud:PopupBubble:1.0.6'
|
||||
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
||||
|
||||
|
@ -304,7 +304,9 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {}
|
||||
override fun onError(e: Throwable) {
|
||||
// unused atm
|
||||
}
|
||||
override fun onComplete() {
|
||||
stopForeground(true)
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
|
@ -2,7 +2,9 @@
|
||||
~ Nextcloud Talk application
|
||||
~
|
||||
~ @author Mario Danic
|
||||
~ @author Marcel Hibbe
|
||||
~ Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
||||
~ Copyright (C) 2021-2022 Marcel Hibbe <dev@mhibbe.de>
|
||||
~
|
||||
~ 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
|
||||
@ -97,7 +99,7 @@
|
||||
<activity
|
||||
android:name=".activities.MainActivity"
|
||||
android:label="@string/nc_app_name"
|
||||
android:windowSoftInputMode="adjustPan">
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
@ -246,7 +246,9 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Observer<RoomOverall> {
|
||||
override fun onSubscribe(d: Disposable) {}
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
override fun onNext(roomOverall: RoomOverall) {
|
||||
val bundle = Bundle()
|
||||
bundle.putParcelable(KEY_USER_ENTITY, currentUser)
|
||||
@ -265,7 +267,9 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Observer<RoomOverall> {
|
||||
override fun onSubscribe(d: Disposable) {}
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
override fun onNext(roomOverall: RoomOverall) {
|
||||
bundle.putParcelable(
|
||||
KEY_ACTIVE_CONVERSATION,
|
||||
@ -277,13 +281,21 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
||||
)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {}
|
||||
override fun onComplete() {}
|
||||
override fun onError(e: Throwable) {
|
||||
// unused atm
|
||||
}
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {}
|
||||
override fun onComplete() {}
|
||||
override fun onError(e: Throwable) {
|
||||
// unused atm
|
||||
}
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,6 @@ import com.nextcloud.talk.utils.ContactUtils
|
||||
import com.nextcloud.talk.utils.DateUtils
|
||||
import com.nextcloud.talk.utils.DisplayUtils
|
||||
import com.nextcloud.talk.utils.ImageEmojiEditText
|
||||
import com.nextcloud.talk.utils.KeyboardUtils
|
||||
import com.nextcloud.talk.utils.MagicCharPolicy
|
||||
import com.nextcloud.talk.utils.NotificationUtils
|
||||
import com.nextcloud.talk.utils.UriUtils
|
||||
@ -347,6 +346,7 @@ class ChatController(args: Bundle) :
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
@ -389,9 +389,11 @@ class ChatController(args: Bundle) :
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -666,6 +668,7 @@ class ChatController(args: Bundle) :
|
||||
}
|
||||
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
|
||||
@ -1262,7 +1265,9 @@ class ChatController(args: Bundle) :
|
||||
UploadAndShareFilesWorker.requestStoragePermission(this)
|
||||
}
|
||||
}
|
||||
.setNegativeButton(R.string.nc_no) {}
|
||||
.setNegativeButton(R.string.nc_no) {
|
||||
// unused atm
|
||||
}
|
||||
.show()
|
||||
} catch (e: IllegalStateException) {
|
||||
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG)
|
||||
@ -1541,10 +1546,6 @@ class ChatController(args: Bundle) :
|
||||
cancelReply()
|
||||
}
|
||||
|
||||
if (activity != null) {
|
||||
KeyboardUtils(activity, getView(), false)
|
||||
}
|
||||
|
||||
cancelNotificationsForCurrentConversation()
|
||||
|
||||
if (inConversation) {
|
||||
@ -1698,9 +1699,11 @@ class ChatController(args: Bundle) :
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@ -1764,7 +1767,9 @@ class ChatController(args: Bundle) :
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {}
|
||||
override fun onError(e: Throwable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
dispose()
|
||||
|
@ -2,7 +2,9 @@
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
|
||||
* @author Marcel Hibbe
|
||||
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
|
||||
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||
*
|
||||
* 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
|
||||
@ -20,12 +22,14 @@
|
||||
|
||||
package com.nextcloud.talk.controllers;
|
||||
|
||||
import static com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_INVITE_USERS;
|
||||
import static com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_GET_AND_JOIN_ROOM;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
@ -39,19 +43,14 @@ import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
|
||||
import com.bluelinelabs.logansquare.LoganSquare;
|
||||
import com.kennyc.bottomsheet.BottomSheet;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.adapters.items.GenericTextHeaderItem;
|
||||
import com.nextcloud.talk.adapters.items.UserItem;
|
||||
import com.nextcloud.talk.api.NcApi;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
import com.nextcloud.talk.controllers.base.BaseController;
|
||||
import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController;
|
||||
import com.nextcloud.talk.controllers.bottomsheet.OperationsMenuController;
|
||||
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
||||
import com.nextcloud.talk.events.OpenConversationEvent;
|
||||
import com.nextcloud.talk.jobs.AddParticipantsToConversation;
|
||||
import com.nextcloud.talk.models.RetrofitBucket;
|
||||
import com.nextcloud.talk.models.database.CapabilitiesUtil;
|
||||
@ -62,9 +61,9 @@ import com.nextcloud.talk.models.json.conversations.Conversation;
|
||||
import com.nextcloud.talk.models.json.conversations.RoomOverall;
|
||||
import com.nextcloud.talk.models.json.converters.EnumActorTypeConverter;
|
||||
import com.nextcloud.talk.models.json.participants.Participant;
|
||||
import com.nextcloud.talk.ui.dialog.ContactsBottomDialog;
|
||||
import com.nextcloud.talk.utils.ApiUtils;
|
||||
import com.nextcloud.talk.utils.ConductorRemapping;
|
||||
import com.nextcloud.talk.utils.KeyboardUtils;
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferences;
|
||||
@ -113,7 +112,7 @@ import okhttp3.ResponseBody;
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication.class)
|
||||
public class ContactsController extends BaseController implements SearchView.OnQueryTextListener,
|
||||
FlexibleAdapter.OnItemClickListener {
|
||||
FlexibleAdapter.OnItemClickListener {
|
||||
|
||||
public static final String TAG = "ContactsController";
|
||||
|
||||
@ -167,8 +166,6 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
private Disposable cacheQueryDisposable;
|
||||
private FlexibleAdapter adapter;
|
||||
private List<AbstractFlexibleItem> contactItems;
|
||||
private BottomSheet bottomSheet;
|
||||
private View view;
|
||||
|
||||
private SmoothScrollLinearLayoutManager layoutManager;
|
||||
|
||||
@ -192,6 +189,8 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
private boolean isAddingParticipantsView;
|
||||
private String conversationToken;
|
||||
|
||||
private ContactsBottomDialog contactsBottomDialog;
|
||||
|
||||
public ContactsController() {
|
||||
super();
|
||||
setHasOptionsMenu(true);
|
||||
@ -266,12 +265,12 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
|
||||
private void setupAdapter() {
|
||||
adapter.setNotifyChangeOfUnfilteredItems(true)
|
||||
.setMode(SelectableAdapter.Mode.MULTI);
|
||||
.setMode(SelectableAdapter.Mode.MULTI);
|
||||
|
||||
adapter.setStickyHeaderElevation(5)
|
||||
.setUnlinkAllItemsOnRemoveHeaders(true)
|
||||
.setDisplayHeadersAtStartUp(true)
|
||||
.setStickyHeaders(true);
|
||||
.setUnlinkAllItemsOnRemoveHeaders(true)
|
||||
.setDisplayHeadersAtStartUp(true)
|
||||
.setStickyHeaders(true);
|
||||
|
||||
adapter.addListener(this);
|
||||
}
|
||||
@ -294,7 +293,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
userId = selectedUserIds.iterator().next();
|
||||
}
|
||||
|
||||
int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {ApiUtils.APIv4, 1});
|
||||
int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[]{ApiUtils.APIv4, 1});
|
||||
RetrofitBucket retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion,
|
||||
currentUser.getBaseUrl(),
|
||||
roomType,
|
||||
@ -302,65 +301,65 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
userId,
|
||||
null);
|
||||
ncApi.createRoom(credentials,
|
||||
retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Observer<RoomOverall>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Observer<RoomOverall>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(RoomOverall roomOverall) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), currentUser);
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomOverall.getOcs().getData().getToken());
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), roomOverall.getOcs().getData().getRoomId());
|
||||
@Override
|
||||
public void onNext(RoomOverall roomOverall) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), currentUser);
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomOverall.getOcs().getData().getToken());
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), roomOverall.getOcs().getData().getRoomId());
|
||||
|
||||
// FIXME once APIv2 or later is used only, the createRoom already returns all the data
|
||||
ncApi.getRoom(credentials,
|
||||
ApiUtils.getUrlForRoom(apiVersion, currentUser.getBaseUrl(),
|
||||
roomOverall.getOcs().getData().getToken()))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Observer<RoomOverall>() {
|
||||
// FIXME once APIv2 or later is used only, the createRoom already returns all the data
|
||||
ncApi.getRoom(credentials,
|
||||
ApiUtils.getUrlForRoom(apiVersion, currentUser.getBaseUrl(),
|
||||
roomOverall.getOcs().getData().getToken()))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Observer<RoomOverall>() {
|
||||
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(RoomOverall roomOverall) {
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(),
|
||||
Parcels.wrap(roomOverall.getOcs().getData()));
|
||||
@Override
|
||||
public void onNext(RoomOverall roomOverall) {
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(),
|
||||
Parcels.wrap(roomOverall.getOcs().getData()));
|
||||
|
||||
ConductorRemapping.INSTANCE.remapChatController(getRouter(), currentUser.getId(),
|
||||
roomOverall.getOcs().getData().getToken(), bundle, true);
|
||||
}
|
||||
ConductorRemapping.INSTANCE.remapChatController(getRouter(), currentUser.getId(),
|
||||
roomOverall.getOcs().getData().getToken(), bundle, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
@Override
|
||||
public void onComplete() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onComplete() {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
@ -382,8 +381,8 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
bundle.putStringArrayList(BundleKeys.INSTANCE.getKEY_INVITED_GROUP(), groupIdsArray);
|
||||
bundle.putStringArrayList(BundleKeys.INSTANCE.getKEY_INVITED_EMAIL(), emailsArray);
|
||||
bundle.putStringArrayList(BundleKeys.INSTANCE.getKEY_INVITED_CIRCLE(), circleIdsArray);
|
||||
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), 11);
|
||||
prepareAndShowBottomSheetWithBundle(bundle, true);
|
||||
bundle.putSerializable(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), OPS_CODE_INVITE_USERS);
|
||||
prepareAndShowBottomSheetWithBundle(bundle);
|
||||
}
|
||||
} else {
|
||||
String[] userIdsArray = selectedUserIds.toArray(new String[selectedUserIds.size()]);
|
||||
@ -400,7 +399,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
data.putStringArray(BundleKeys.INSTANCE.getKEY_SELECTED_CIRCLES(), circleIdsArray);
|
||||
|
||||
OneTimeWorkRequest addParticipantsToConversationWorker =
|
||||
new OneTimeWorkRequest.Builder(AddParticipantsToConversation.class).setInputData(data.build()).build();
|
||||
new OneTimeWorkRequest.Builder(AddParticipantsToConversation.class).setInputData(data.build()).build();
|
||||
WorkManager.getInstance().enqueue(addParticipantsToConversationWorker);
|
||||
|
||||
getRouter().popCurrentController();
|
||||
@ -500,186 +499,186 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
modifiedQueryMap.put("shareTypes[]", shareTypesList);
|
||||
|
||||
ncApi.getContactsWithSearchParam(
|
||||
credentials,
|
||||
retrofitBucket.getUrl(), shareTypesList, modifiedQueryMap)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.retry(3)
|
||||
.subscribe(new Observer<ResponseBody>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
contactsQueryDisposable = d;
|
||||
}
|
||||
credentials,
|
||||
retrofitBucket.getUrl(), shareTypesList, modifiedQueryMap)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.retry(3)
|
||||
.subscribe(new Observer<ResponseBody>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
contactsQueryDisposable = d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(ResponseBody responseBody) {
|
||||
if (responseBody != null) {
|
||||
Participant participant;
|
||||
@Override
|
||||
public void onNext(ResponseBody responseBody) {
|
||||
if (responseBody != null) {
|
||||
Participant participant;
|
||||
|
||||
List<AbstractFlexibleItem> newUserItemList = new ArrayList<>();
|
||||
EnumActorTypeConverter actorTypeConverter = new EnumActorTypeConverter();
|
||||
List<AbstractFlexibleItem> newUserItemList = new ArrayList<>();
|
||||
EnumActorTypeConverter actorTypeConverter = new EnumActorTypeConverter();
|
||||
|
||||
try {
|
||||
AutocompleteOverall autocompleteOverall = LoganSquare.parse(
|
||||
responseBody.string(),
|
||||
AutocompleteOverall.class);
|
||||
autocompleteUsersHashSet.addAll(autocompleteOverall.getOcs().getData());
|
||||
try {
|
||||
AutocompleteOverall autocompleteOverall = LoganSquare.parse(
|
||||
responseBody.string(),
|
||||
AutocompleteOverall.class);
|
||||
autocompleteUsersHashSet.addAll(autocompleteOverall.getOcs().getData());
|
||||
|
||||
for (AutocompleteUser autocompleteUser : autocompleteUsersHashSet) {
|
||||
if (!autocompleteUser.getId().equals(currentUser.getUserId())
|
||||
&& !existingParticipants.contains(autocompleteUser.getId())) {
|
||||
participant = new Participant();
|
||||
participant.setActorId(autocompleteUser.getId());
|
||||
participant.setActorType(actorTypeConverter.getFromString(autocompleteUser.getSource()));
|
||||
participant.setDisplayName(autocompleteUser.getLabel());
|
||||
participant.setSource(autocompleteUser.getSource());
|
||||
for (AutocompleteUser autocompleteUser : autocompleteUsersHashSet) {
|
||||
if (!autocompleteUser.getId().equals(currentUser.getUserId())
|
||||
&& !existingParticipants.contains(autocompleteUser.getId())) {
|
||||
participant = new Participant();
|
||||
participant.setActorId(autocompleteUser.getId());
|
||||
participant.setActorType(actorTypeConverter.getFromString(autocompleteUser.getSource()));
|
||||
participant.setDisplayName(autocompleteUser.getLabel());
|
||||
participant.setSource(autocompleteUser.getSource());
|
||||
|
||||
String headerTitle;
|
||||
String headerTitle;
|
||||
|
||||
if (participant.getActorType() == Participant.ActorType.GROUPS) {
|
||||
headerTitle = getResources().getString(R.string.nc_groups);
|
||||
} else if (participant.getActorType() == Participant.ActorType.CIRCLES) {
|
||||
headerTitle = getResources().getString(R.string.nc_circles);
|
||||
} else {
|
||||
headerTitle =
|
||||
participant.getDisplayName().substring(0, 1).toUpperCase(Locale.getDefault());
|
||||
}
|
||||
if (participant.getActorType() == Participant.ActorType.GROUPS) {
|
||||
headerTitle = getResources().getString(R.string.nc_groups);
|
||||
} else if (participant.getActorType() == Participant.ActorType.CIRCLES) {
|
||||
headerTitle = getResources().getString(R.string.nc_circles);
|
||||
} else {
|
||||
headerTitle =
|
||||
participant.getDisplayName().substring(0, 1).toUpperCase(Locale.getDefault());
|
||||
}
|
||||
|
||||
GenericTextHeaderItem genericTextHeaderItem;
|
||||
if (!userHeaderItems.containsKey(headerTitle)) {
|
||||
genericTextHeaderItem = new GenericTextHeaderItem(headerTitle);
|
||||
userHeaderItems.put(headerTitle, genericTextHeaderItem);
|
||||
}
|
||||
GenericTextHeaderItem genericTextHeaderItem;
|
||||
if (!userHeaderItems.containsKey(headerTitle)) {
|
||||
genericTextHeaderItem = new GenericTextHeaderItem(headerTitle);
|
||||
userHeaderItems.put(headerTitle, genericTextHeaderItem);
|
||||
}
|
||||
|
||||
UserItem newContactItem = new UserItem(
|
||||
participant,
|
||||
currentUser,
|
||||
userHeaderItems.get(headerTitle)
|
||||
);
|
||||
UserItem newContactItem = new UserItem(
|
||||
participant,
|
||||
currentUser,
|
||||
userHeaderItems.get(headerTitle)
|
||||
);
|
||||
|
||||
if (!contactItems.contains(newContactItem)) {
|
||||
newUserItemList.add(newContactItem);
|
||||
}
|
||||
if (!contactItems.contains(newContactItem)) {
|
||||
newUserItemList.add(newContactItem);
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
Log.e(TAG, "Parsing response body failed while getting contacts", ioe);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
Log.e(TAG, "Parsing response body failed while getting contacts", ioe);
|
||||
}
|
||||
|
||||
userHeaderItems = new HashMap<>();
|
||||
contactItems.addAll(newUserItemList);
|
||||
|
||||
Collections.sort(newUserItemList, (o1, o2) -> {
|
||||
String firstName;
|
||||
String secondName;
|
||||
|
||||
if (o1 instanceof UserItem) {
|
||||
firstName = ((UserItem) o1).getModel().getDisplayName();
|
||||
} else {
|
||||
firstName = ((GenericTextHeaderItem) o1).getModel();
|
||||
}
|
||||
|
||||
userHeaderItems = new HashMap<>();
|
||||
contactItems.addAll(newUserItemList);
|
||||
if (o2 instanceof UserItem) {
|
||||
secondName = ((UserItem) o2).getModel().getDisplayName();
|
||||
} else {
|
||||
secondName = ((GenericTextHeaderItem) o2).getModel();
|
||||
}
|
||||
|
||||
Collections.sort(newUserItemList, (o1, o2) -> {
|
||||
String firstName;
|
||||
String secondName;
|
||||
|
||||
if (o1 instanceof UserItem) {
|
||||
firstName = ((UserItem) o1).getModel().getDisplayName();
|
||||
} else {
|
||||
firstName = ((GenericTextHeaderItem) o1).getModel();
|
||||
}
|
||||
|
||||
if (o2 instanceof UserItem) {
|
||||
secondName = ((UserItem) o2).getModel().getDisplayName();
|
||||
} else {
|
||||
secondName = ((GenericTextHeaderItem) o2).getModel();
|
||||
}
|
||||
|
||||
if (o1 instanceof UserItem && o2 instanceof UserItem) {
|
||||
String firstSource = ((UserItem) o1).getModel().getSource();
|
||||
String secondSource = ((UserItem) o2).getModel().getSource();
|
||||
if (firstSource.equals(secondSource)) {
|
||||
return firstName.compareToIgnoreCase(secondName);
|
||||
}
|
||||
|
||||
// First users
|
||||
if ("users".equals(firstSource)) {
|
||||
return -1;
|
||||
} else if ("users".equals(secondSource)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Then groups
|
||||
if ("groups".equals(firstSource)) {
|
||||
return -1;
|
||||
} else if ("groups".equals(secondSource)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Then circles
|
||||
if ("circles".equals(firstSource)) {
|
||||
return -1;
|
||||
} else if ("circles".equals(secondSource)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Otherwise fall back to name sorting
|
||||
if (o1 instanceof UserItem && o2 instanceof UserItem) {
|
||||
String firstSource = ((UserItem) o1).getModel().getSource();
|
||||
String secondSource = ((UserItem) o2).getModel().getSource();
|
||||
if (firstSource.equals(secondSource)) {
|
||||
return firstName.compareToIgnoreCase(secondName);
|
||||
}
|
||||
|
||||
// First users
|
||||
if ("users".equals(firstSource)) {
|
||||
return -1;
|
||||
} else if ("users".equals(secondSource)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Then groups
|
||||
if ("groups".equals(firstSource)) {
|
||||
return -1;
|
||||
} else if ("groups".equals(secondSource)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Then circles
|
||||
if ("circles".equals(firstSource)) {
|
||||
return -1;
|
||||
} else if ("circles".equals(secondSource)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Otherwise fall back to name sorting
|
||||
return firstName.compareToIgnoreCase(secondName);
|
||||
});
|
||||
}
|
||||
|
||||
Collections.sort(contactItems, (o1, o2) -> {
|
||||
String firstName;
|
||||
String secondName;
|
||||
return firstName.compareToIgnoreCase(secondName);
|
||||
});
|
||||
|
||||
if (o1 instanceof UserItem) {
|
||||
firstName = ((UserItem) o1).getModel().getDisplayName();
|
||||
} else {
|
||||
firstName = ((GenericTextHeaderItem) o1).getModel();
|
||||
}
|
||||
Collections.sort(contactItems, (o1, o2) -> {
|
||||
String firstName;
|
||||
String secondName;
|
||||
|
||||
if (o2 instanceof UserItem) {
|
||||
secondName = ((UserItem) o2).getModel().getDisplayName();
|
||||
} else {
|
||||
secondName = ((GenericTextHeaderItem) o2).getModel();
|
||||
}
|
||||
|
||||
if (o1 instanceof UserItem && o2 instanceof UserItem) {
|
||||
if ("groups".equals(((UserItem) o1).getModel().getSource()) && "groups".equals(((UserItem) o2).getModel().getSource())) {
|
||||
return firstName.compareToIgnoreCase(secondName);
|
||||
} else if ("groups".equals(((UserItem) o1).getModel().getSource())) {
|
||||
return -1;
|
||||
} else if ("groups".equals(((UserItem) o2).getModel().getSource())) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return firstName.compareToIgnoreCase(secondName);
|
||||
});
|
||||
|
||||
if (newUserItemList.size() > 0) {
|
||||
adapter.updateDataSet(newUserItemList);
|
||||
if (o1 instanceof UserItem) {
|
||||
firstName = ((UserItem) o1).getModel().getDisplayName();
|
||||
} else {
|
||||
adapter.filterItems();
|
||||
firstName = ((GenericTextHeaderItem) o1).getModel();
|
||||
}
|
||||
|
||||
if (swipeRefreshLayout != null) {
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
if (o2 instanceof UserItem) {
|
||||
secondName = ((UserItem) o2).getModel().getDisplayName();
|
||||
} else {
|
||||
secondName = ((GenericTextHeaderItem) o2).getModel();
|
||||
}
|
||||
|
||||
if (o1 instanceof UserItem && o2 instanceof UserItem) {
|
||||
if ("groups".equals(((UserItem) o1).getModel().getSource()) && "groups".equals(((UserItem) o2).getModel().getSource())) {
|
||||
return firstName.compareToIgnoreCase(secondName);
|
||||
} else if ("groups".equals(((UserItem) o1).getModel().getSource())) {
|
||||
return -1;
|
||||
} else if ("groups".equals(((UserItem) o2).getModel().getSource())) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return firstName.compareToIgnoreCase(secondName);
|
||||
});
|
||||
|
||||
if (newUserItemList.size() > 0) {
|
||||
adapter.updateDataSet(newUserItemList);
|
||||
} else {
|
||||
adapter.filterItems();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
if (swipeRefreshLayout != null) {
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
dispose(contactsQueryDisposable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
if (swipeRefreshLayout != null) {
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
dispose(contactsQueryDisposable);
|
||||
alreadyFetching = false;
|
||||
|
||||
disengageProgressBar();
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
if (swipeRefreshLayout != null) {
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
});
|
||||
dispose(contactsQueryDisposable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
if (swipeRefreshLayout != null) {
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
dispose(contactsQueryDisposable);
|
||||
alreadyFetching = false;
|
||||
|
||||
disengageProgressBar();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@ -694,14 +693,14 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
swipeRefreshLayout.setProgressBackgroundColorSchemeResource(R.color.refresh_spinner_background);
|
||||
|
||||
joinConversationViaLinkImageView
|
||||
.getBackground()
|
||||
.setColorFilter(ResourcesCompat.getColor(getResources(), R.color.colorBackgroundDarker, null),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
.getBackground()
|
||||
.setColorFilter(ResourcesCompat.getColor(getResources(), R.color.colorBackgroundDarker, null),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
|
||||
publicCallLinkImageView
|
||||
.getBackground()
|
||||
.setColorFilter(ResourcesCompat.getColor(getResources(), R.color.colorPrimary, null),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
.getBackground()
|
||||
.setColorFilter(ResourcesCompat.getColor(getResources(), R.color.colorPrimary, null),
|
||||
PorterDuff.Mode.SRC_IN);
|
||||
|
||||
disengageProgressBar();
|
||||
}
|
||||
@ -801,59 +800,21 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void prepareAndShowBottomSheetWithBundle(Bundle bundle, boolean showEntrySheet) {
|
||||
if (view == null) {
|
||||
view = getActivity().getLayoutInflater().inflate(R.layout.bottom_sheet, null, false);
|
||||
}
|
||||
|
||||
if (bottomSheet == null) {
|
||||
bottomSheet = new BottomSheet.Builder(getActivity()).setView(view).create();
|
||||
}
|
||||
|
||||
if (showEntrySheet) {
|
||||
getChildRouter((ViewGroup) view).setRoot(
|
||||
RouterTransaction.with(new EntryMenuController(bundle))
|
||||
.popChangeHandler(new VerticalChangeHandler())
|
||||
.pushChangeHandler(new VerticalChangeHandler()));
|
||||
} else {
|
||||
getChildRouter((ViewGroup) view).setRoot(
|
||||
RouterTransaction.with(new OperationsMenuController(bundle))
|
||||
.popChangeHandler(new VerticalChangeHandler())
|
||||
.pushChangeHandler(new VerticalChangeHandler()));
|
||||
}
|
||||
|
||||
bottomSheet.setOnShowListener(dialog -> {
|
||||
if (showEntrySheet) {
|
||||
new KeyboardUtils(getActivity(), bottomSheet.getLayout(), true);
|
||||
} else {
|
||||
eventBus.post(new BottomSheetLockEvent(false, 0,
|
||||
false, false));
|
||||
}
|
||||
});
|
||||
|
||||
bottomSheet.setOnDismissListener(dialog -> getActionBar().setDisplayHomeAsUpEnabled(getRouter().getBackstackSize() > 1));
|
||||
|
||||
bottomSheet.show();
|
||||
private void prepareAndShowBottomSheetWithBundle(Bundle bundle) {
|
||||
// 11: create conversation-enter name for new conversation
|
||||
// 10: get&join room when enter link
|
||||
contactsBottomDialog = new ContactsBottomDialog(getActivity(), bundle);
|
||||
contactsBottomDialog.show();
|
||||
}
|
||||
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onMessageEvent(BottomSheetLockEvent bottomSheetLockEvent) {
|
||||
|
||||
if (bottomSheet != null) {
|
||||
if (!bottomSheetLockEvent.isCancelable()) {
|
||||
bottomSheet.setCancelable(bottomSheetLockEvent.isCancelable());
|
||||
} else {
|
||||
bottomSheet.setCancelable(bottomSheetLockEvent.isCancelable());
|
||||
if (bottomSheet.isShowing() && bottomSheetLockEvent.isCancel()) {
|
||||
new Handler().postDelayed(() -> {
|
||||
bottomSheet.setOnCancelListener(null);
|
||||
bottomSheet.cancel();
|
||||
|
||||
}, bottomSheetLockEvent.getDelay());
|
||||
}
|
||||
}
|
||||
public void onMessageEvent(OpenConversationEvent openConversationEvent) {
|
||||
ConductorRemapping.INSTANCE.remapChatController(getRouter(), currentUser.getId(),
|
||||
openConversationEvent.getConversation().getToken(),
|
||||
openConversationEvent.getBundle(), true);
|
||||
if (contactsBottomDialog != null) {
|
||||
contactsBottomDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@ -874,7 +835,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
roomType = "2";
|
||||
}
|
||||
|
||||
int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {ApiUtils.APIv4, 1});
|
||||
int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[]{ApiUtils.APIv4, 1});
|
||||
|
||||
RetrofitBucket retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(apiVersion,
|
||||
currentUser.getBaseUrl(),
|
||||
@ -884,40 +845,40 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
null);
|
||||
|
||||
ncApi.createRoom(credentials,
|
||||
retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Observer<RoomOverall>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Observer<RoomOverall>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(RoomOverall roomOverall) {
|
||||
if (getActivity() != null) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), currentUser);
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomOverall.getOcs().getData().getToken());
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), roomOverall.getOcs().getData().getRoomId());
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(),
|
||||
Parcels.wrap(roomOverall.getOcs().getData()));
|
||||
|
||||
ConductorRemapping.INSTANCE.remapChatController(getRouter(), currentUser.getId(),
|
||||
roomOverall.getOcs().getData().getToken(), bundle, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(RoomOverall roomOverall) {
|
||||
if (getActivity() != null) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), currentUser);
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomOverall.getOcs().getData().getToken());
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), roomOverall.getOcs().getData().getRoomId());
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(),
|
||||
Parcels.wrap(roomOverall.getOcs().getData()));
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
|
||||
ConductorRemapping.INSTANCE.remapChatController(getRouter(), currentUser.getId(),
|
||||
roomOverall.getOcs().getData().getToken(), bundle, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
@Override
|
||||
public void onComplete() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Participant participant = ((UserItem) adapter.getItem(position)).getModel();
|
||||
participant.setSelected(!participant.isSelected());
|
||||
@ -949,17 +910,17 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
}
|
||||
|
||||
if (CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, "last-room-activity")
|
||||
&& !CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, "invite-groups-and-mails") &&
|
||||
"groups".equals(((UserItem) adapter.getItem(position)).getModel().getSource()) &&
|
||||
participant.isSelected() &&
|
||||
adapter.getSelectedItemCount() > 1) {
|
||||
&& !CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, "invite-groups-and-mails") &&
|
||||
"groups".equals(((UserItem) adapter.getItem(position)).getModel().getSource()) &&
|
||||
participant.isSelected() &&
|
||||
adapter.getSelectedItemCount() > 1) {
|
||||
List<UserItem> currentItems = adapter.getCurrentItems();
|
||||
Participant internalParticipant;
|
||||
for (int i = 0; i < currentItems.size(); i++) {
|
||||
internalParticipant = currentItems.get(i).getModel();
|
||||
if (internalParticipant.getActorId().equals(participant.getActorId()) &&
|
||||
internalParticipant.getActorType() == Participant.ActorType.GROUPS &&
|
||||
internalParticipant.isSelected()) {
|
||||
internalParticipant.getActorType() == Participant.ActorType.GROUPS &&
|
||||
internalParticipant.isSelected()) {
|
||||
internalParticipant.setSelected(false);
|
||||
selectedGroupIds.remove(internalParticipant.getActorId());
|
||||
}
|
||||
@ -978,9 +939,9 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
@OnClick(R.id.joinConversationViaLinkRelativeLayout)
|
||||
void joinConversationViaLink() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), 10);
|
||||
bundle.putSerializable(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), OPS_CODE_GET_AND_JOIN_ROOM);
|
||||
|
||||
prepareAndShowBottomSheetWithBundle(bundle, true);
|
||||
prepareAndShowBottomSheetWithBundle(bundle);
|
||||
}
|
||||
|
||||
@Optional
|
||||
@ -1002,7 +963,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
if (currentItems.get(i) instanceof UserItem) {
|
||||
internalParticipant = ((UserItem) currentItems.get(i)).getModel();
|
||||
if (internalParticipant.getActorType() == Participant.ActorType.GROUPS &&
|
||||
internalParticipant.isSelected()) {
|
||||
internalParticipant.isSelected()) {
|
||||
internalParticipant.setSelected(false);
|
||||
selectedGroupIds.remove(internalParticipant.getActorId());
|
||||
}
|
||||
|
@ -287,15 +287,19 @@ class ConversationInfoController(args: Bundle) :
|
||||
?.observeOn(AndroidSchedulers.mainThread())
|
||||
?.subscribe(object : Observer<GenericOverall> {
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(t: GenericOverall) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -305,6 +309,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
ID_DELETE_CONVERSATION_DIALOG -> showDeleteConversationDialog(savedInstanceState)
|
||||
ID_CLEAR_CHAT_DIALOG -> showClearHistoryDialog(savedInstanceState)
|
||||
else -> {
|
||||
// unused atm
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -444,6 +449,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
@ -525,6 +531,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
?.observeOn(AndroidSchedulers.mainThread())
|
||||
?.subscribe(object : Observer<GenericOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(genericOverall: GenericOverall) {
|
||||
@ -538,6 +545,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -598,13 +606,13 @@ class ConversationInfoController(args: Bundle) :
|
||||
|
||||
setupWebinaryView()
|
||||
|
||||
if (!conversation!!.canLeave(conversationUser)) {
|
||||
if (!conversation!!.canLeave()) {
|
||||
binding.leaveConversationAction.visibility = View.GONE
|
||||
} else {
|
||||
binding.leaveConversationAction.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
if (!conversation!!.canDelete(conversationUser)) {
|
||||
if (!conversation!!.canDelete()) {
|
||||
binding.deleteConversationAction.visibility = View.GONE
|
||||
} else {
|
||||
binding.deleteConversationAction.visibility = View.VISIBLE
|
||||
@ -647,6 +655,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
@ -731,6 +740,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
}
|
||||
|
||||
else -> {
|
||||
// unused atm
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -738,6 +748,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
private fun toggleModeratorStatus(apiVersion: Int, participant: Participant) {
|
||||
val subscriber = object : Observer<GenericOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(genericOverall: GenericOverall) {
|
||||
@ -750,6 +761,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
}
|
||||
|
||||
@ -789,6 +801,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
private fun toggleModeratorStatusLegacy(apiVersion: Int, participant: Participant) {
|
||||
val subscriber = object : Observer<GenericOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(genericOverall: GenericOverall) {
|
||||
@ -801,6 +814,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
}
|
||||
|
||||
@ -848,6 +862,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
?.observeOn(AndroidSchedulers.mainThread())
|
||||
?.subscribe(object : Observer<GenericOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(genericOverall: GenericOverall) {
|
||||
@ -860,6 +875,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@ -879,6 +895,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
?.observeOn(AndroidSchedulers.mainThread())
|
||||
?.subscribe(object : Observer<GenericOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(genericOverall: GenericOverall) {
|
||||
@ -891,6 +908,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@ -907,6 +925,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
?.observeOn(AndroidSchedulers.mainThread())
|
||||
?.subscribe(object : Observer<GenericOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(genericOverall: GenericOverall) {
|
||||
@ -919,6 +938,7 @@ class ConversationInfoController(args: Bundle) :
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -3,8 +3,10 @@
|
||||
*
|
||||
* @author Mario Danic
|
||||
* @author Andy Scherzinger
|
||||
* @author Marcel Hibbe
|
||||
* Copyright (C) 2021 Andy Scherzinger (info@andy-scherzinger.de)
|
||||
* Copyright (C) 2017-2020 Mario Danic (mario@lovelyhq.com)
|
||||
* Copyright (C) 2022 Marcel Hibbe (dev@mhibbe.de)
|
||||
*
|
||||
* 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
|
||||
@ -62,7 +64,7 @@ import com.facebook.imagepipeline.image.CloseableImage;
|
||||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
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.ConversationItem;
|
||||
@ -70,11 +72,10 @@ 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;
|
||||
import com.nextcloud.talk.controllers.bottomsheet.CallMenuController;
|
||||
import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum;
|
||||
import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController;
|
||||
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
||||
import com.nextcloud.talk.events.ConversationsListFetchDataEvent;
|
||||
import com.nextcloud.talk.events.EventStatus;
|
||||
import com.nextcloud.talk.events.MoreMenuClickEvent;
|
||||
import com.nextcloud.talk.interfaces.ConversationMenuInterface;
|
||||
import com.nextcloud.talk.jobs.AccountRemovalWorker;
|
||||
import com.nextcloud.talk.jobs.ContactAddressBookWorker;
|
||||
@ -85,11 +86,11 @@ import com.nextcloud.talk.models.database.UserEntity;
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation;
|
||||
import com.nextcloud.talk.models.json.participants.Participant;
|
||||
import com.nextcloud.talk.ui.dialog.ChooseAccountDialogFragment;
|
||||
import com.nextcloud.talk.ui.dialog.ConversationsListBottomDialog;
|
||||
import com.nextcloud.talk.utils.ApiUtils;
|
||||
import com.nextcloud.talk.utils.ClosedInterfaceImpl;
|
||||
import com.nextcloud.talk.utils.ConductorRemapping;
|
||||
import com.nextcloud.talk.utils.DisplayUtils;
|
||||
import com.nextcloud.talk.utils.KeyboardUtils;
|
||||
import com.nextcloud.talk.utils.UriUtils;
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
||||
@ -186,7 +187,6 @@ public class ConversationsListController extends BaseController implements Searc
|
||||
private List<AbstractFlexibleItem> conversationItemsWithHeader = new ArrayList<>();
|
||||
private final List<AbstractFlexibleItem> searchableConversationItems = new ArrayList<>();
|
||||
|
||||
private BottomSheet bottomSheet;
|
||||
private MenuItem searchItem;
|
||||
private SearchView searchView;
|
||||
private String searchQuery;
|
||||
@ -218,6 +218,8 @@ public class ConversationsListController extends BaseController implements Searc
|
||||
|
||||
private HashMap<String, GenericTextHeaderItem> callHeaderItems = new HashMap<>();
|
||||
|
||||
private ConversationsListBottomDialog conversationsListBottomDialog;
|
||||
|
||||
public ConversationsListController(Bundle bundle) {
|
||||
super();
|
||||
setHasOptionsMenu(true);
|
||||
@ -310,7 +312,7 @@ public class ConversationsListController extends BaseController implements Searc
|
||||
if (getActivity() != null && getActivity() instanceof MainActivity) {
|
||||
loadUserAvatar(((MainActivity) getActivity()).binding.switchAccountButton);
|
||||
}
|
||||
fetchData(false);
|
||||
fetchData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -453,6 +455,7 @@ public class ConversationsListController extends BaseController implements Searc
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showSearchOrToolbar() {
|
||||
if (TextUtils.isEmpty(searchQuery)) {
|
||||
super.showSearchOrToolbar();
|
||||
@ -469,7 +472,7 @@ public class ConversationsListController extends BaseController implements Searc
|
||||
}
|
||||
|
||||
@SuppressLint("LongLogTag")
|
||||
private void fetchData(boolean fromBottomSheet) {
|
||||
public void fetchData() {
|
||||
dispose(null);
|
||||
|
||||
isRefreshing = true;
|
||||
@ -565,15 +568,6 @@ public class ConversationsListController extends BaseController implements Searc
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
if (fromBottomSheet) {
|
||||
new Handler().postDelayed(() -> {
|
||||
bottomSheet.setCancelable(true);
|
||||
if (bottomSheet.isShowing()) {
|
||||
bottomSheet.cancel();
|
||||
}
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
isRefreshing = false;
|
||||
});
|
||||
}
|
||||
@ -678,7 +672,7 @@ public class ConversationsListController extends BaseController implements Searc
|
||||
return false;
|
||||
});
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener(() -> fetchData(false));
|
||||
swipeRefreshLayout.setOnRefreshListener(() -> fetchData());
|
||||
swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary);
|
||||
swipeRefreshLayout.setProgressBackgroundColorSchemeResource(R.color.refresh_spinner_background);
|
||||
|
||||
@ -811,60 +805,6 @@ public class ConversationsListController extends BaseController implements Searc
|
||||
return onQueryTextChange(query);
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onMessageEvent(BottomSheetLockEvent bottomSheetLockEvent) {
|
||||
if (bottomSheet != null) {
|
||||
if (!bottomSheetLockEvent.isCancelable()) {
|
||||
bottomSheet.setCancelable(bottomSheetLockEvent.isCancelable());
|
||||
} else {
|
||||
if (bottomSheetLockEvent.getDelay() != 0 && bottomSheetLockEvent.isShouldRefreshData()) {
|
||||
fetchData(true);
|
||||
} else {
|
||||
bottomSheet.setCancelable(bottomSheetLockEvent.isCancelable());
|
||||
if (bottomSheet.isShowing() && bottomSheetLockEvent.isCancel()) {
|
||||
bottomSheet.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onMessageEvent(MoreMenuClickEvent moreMenuClickEvent) {
|
||||
Bundle bundle = new Bundle();
|
||||
Conversation conversation = moreMenuClickEvent.getConversation();
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_MENU_TYPE(), Parcels.wrap(CallMenuController.MenuType.REGULAR));
|
||||
|
||||
prepareAndShowBottomSheetWithBundle(bundle, true);
|
||||
}
|
||||
|
||||
private void prepareAndShowBottomSheetWithBundle(Bundle bundle, boolean shouldShowCallMenuController) {
|
||||
if (view == null) {
|
||||
view = getActivity().getLayoutInflater().inflate(R.layout.bottom_sheet, null, false);
|
||||
}
|
||||
|
||||
if (shouldShowCallMenuController) {
|
||||
getChildRouter((ViewGroup) view).setRoot(
|
||||
RouterTransaction.with(new CallMenuController(bundle, this))
|
||||
.popChangeHandler(new VerticalChangeHandler())
|
||||
.pushChangeHandler(new VerticalChangeHandler()));
|
||||
} else {
|
||||
getChildRouter((ViewGroup) view).setRoot(
|
||||
RouterTransaction.with(new EntryMenuController(bundle))
|
||||
.popChangeHandler(new VerticalChangeHandler())
|
||||
.pushChangeHandler(new VerticalChangeHandler()));
|
||||
}
|
||||
|
||||
if (bottomSheet == null) {
|
||||
bottomSheet = new BottomSheet.Builder(getActivity()).setView(view).create();
|
||||
}
|
||||
|
||||
bottomSheet.setOnShowListener(dialog -> new KeyboardUtils(getActivity(), bottomSheet.getLayout(), true));
|
||||
bottomSheet.setOnDismissListener(dialog -> showSearchOrToolbar());
|
||||
bottomSheet.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return getResources().getString(R.string.nc_app_product_name);
|
||||
@ -950,8 +890,12 @@ public class ConversationsListController extends BaseController implements Searc
|
||||
Object clickedItem = adapter.getItem(position);
|
||||
if (clickedItem != null) {
|
||||
Conversation conversation = ((ConversationItem) clickedItem).getModel();
|
||||
MoreMenuClickEvent moreMenuClickEvent = new MoreMenuClickEvent(conversation);
|
||||
onMessageEvent(moreMenuClickEvent);
|
||||
conversationsListBottomDialog = new ConversationsListBottomDialog(
|
||||
getActivity(),
|
||||
this,
|
||||
userUtils.getCurrentUser(),
|
||||
conversation);
|
||||
conversationsListBottomDialog.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1055,22 +999,13 @@ public class ConversationsListController extends BaseController implements Searc
|
||||
private void openConversation(String textToPaste) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), currentUser);
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(), Parcels.wrap(selectedConversation));
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), selectedConversation.getToken());
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), selectedConversation.getRoomId());
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_SHARED_TEXT(), textToPaste);
|
||||
|
||||
if (selectedConversation.hasPassword && selectedConversation.participantType ==
|
||||
Participant.ParticipantType.GUEST ||
|
||||
selectedConversation.participantType == Participant.ParticipantType.USER_FOLLOWING_LINK) {
|
||||
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), 99);
|
||||
prepareAndShowBottomSheetWithBundle(bundle, false);
|
||||
} else {
|
||||
currentUser = userUtils.getCurrentUser();
|
||||
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(), Parcels.wrap(selectedConversation));
|
||||
ConductorRemapping.INSTANCE.remapChatController(getRouter(), currentUser.getId(),
|
||||
selectedConversation.getToken(), bundle, false);
|
||||
}
|
||||
ConductorRemapping.INSTANCE.remapChatController(getRouter(), currentUser.getId(),
|
||||
selectedConversation.getToken(), bundle, false);
|
||||
}
|
||||
|
||||
@Subscribe(sticky = true, threadMode = ThreadMode.BACKGROUND)
|
||||
@ -1079,7 +1014,7 @@ public class ConversationsListController extends BaseController implements Searc
|
||||
switch (eventStatus.getEventType()) {
|
||||
case CONVERSATION_UPDATE:
|
||||
if (eventStatus.isAllGood() && !isRefreshing) {
|
||||
fetchData(false);
|
||||
fetchData();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -1088,6 +1023,17 @@ public class ConversationsListController extends BaseController implements Searc
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onMessageEvent(ConversationsListFetchDataEvent conversationsListFetchDataEvent) {
|
||||
fetchData();
|
||||
|
||||
new Handler().postDelayed(() -> {
|
||||
if (conversationsListBottomDialog.isShowing()) {
|
||||
conversationsListBottomDialog.dismiss();
|
||||
}
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
private void showDeleteConversationDialog(Bundle savedInstanceState) {
|
||||
if (getActivity() != null && conversationMenuBundle != null && currentUser != null && conversationMenuBundle.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID()) == currentUser.getId()) {
|
||||
|
||||
@ -1240,7 +1186,6 @@ public class ConversationsListController extends BaseController implements Searc
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,7 +46,9 @@ abstract class ButterKnifeController : Controller {
|
||||
return view
|
||||
}
|
||||
|
||||
protected open fun onViewBound(view: View) {}
|
||||
protected open fun onViewBound(view: View) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
super.onDestroyView(view)
|
||||
|
@ -1,356 +0,0 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017 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.controllers.bottomsheet;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||
import com.kennyc.bottomsheet.adapters.AppAdapter;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.adapters.items.AppItem;
|
||||
import com.nextcloud.talk.adapters.items.MenuItem;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
import com.nextcloud.talk.controllers.ConversationsListController;
|
||||
import com.nextcloud.talk.controllers.base.BaseController;
|
||||
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
||||
import com.nextcloud.talk.interfaces.ConversationMenuInterface;
|
||||
import com.nextcloud.talk.jobs.LeaveConversationWorker;
|
||||
import com.nextcloud.talk.models.database.CapabilitiesUtil;
|
||||
import com.nextcloud.talk.models.database.UserEntity;
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation;
|
||||
import com.nextcloud.talk.utils.DisplayUtils;
|
||||
import com.nextcloud.talk.utils.ShareUtils;
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.parceler.Parcel;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.work.Data;
|
||||
import androidx.work.OneTimeWorkRequest;
|
||||
import androidx.work.WorkManager;
|
||||
import autodagger.AutoInjector;
|
||||
import butterknife.BindView;
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager;
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication.class)
|
||||
public class CallMenuController extends BaseController implements FlexibleAdapter.OnItemClickListener {
|
||||
public static final int ALL_MESSAGES_READ = 0;
|
||||
@BindView(R.id.recycler_view)
|
||||
RecyclerView recyclerView;
|
||||
|
||||
@Inject
|
||||
EventBus eventBus;
|
||||
|
||||
@Inject
|
||||
UserUtils userUtils;
|
||||
|
||||
@Inject
|
||||
Context context;
|
||||
|
||||
private Conversation conversation;
|
||||
private List<AbstractFlexibleItem> menuItems;
|
||||
private FlexibleAdapter<AbstractFlexibleItem> adapter;
|
||||
private MenuType menuType;
|
||||
private Intent shareIntent;
|
||||
|
||||
private UserEntity currentUser;
|
||||
private ConversationMenuInterface conversationMenuInterface;
|
||||
|
||||
public CallMenuController(Bundle args) {
|
||||
super(args);
|
||||
this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
|
||||
if (args.containsKey(BundleKeys.INSTANCE.getKEY_MENU_TYPE())) {
|
||||
this.menuType = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_MENU_TYPE()));
|
||||
}
|
||||
}
|
||||
|
||||
public CallMenuController(Bundle args, @Nullable ConversationMenuInterface conversationMenuInterface) {
|
||||
super(args);
|
||||
this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
|
||||
if (args.containsKey(BundleKeys.INSTANCE.getKEY_MENU_TYPE())) {
|
||||
this.menuType = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_MENU_TYPE()));
|
||||
}
|
||||
this.conversationMenuInterface = conversationMenuInterface;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
return inflater.inflate(R.layout.controller_call_menu, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
|
||||
prepareViews();
|
||||
}
|
||||
|
||||
private void prepareViews() {
|
||||
LinearLayoutManager layoutManager = new SmoothScrollLinearLayoutManager(getActivity());
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
recyclerView.setHasFixedSize(true);
|
||||
|
||||
prepareMenu();
|
||||
if (adapter == null) {
|
||||
adapter = new FlexibleAdapter<>(menuItems, getActivity(), false);
|
||||
}
|
||||
|
||||
adapter.addListener(this);
|
||||
recyclerView.setAdapter(adapter);
|
||||
}
|
||||
|
||||
private void prepareIntent() {
|
||||
shareIntent = new Intent(Intent.ACTION_SEND);
|
||||
shareIntent.setType("text/plain");
|
||||
shareIntent.putExtra(Intent.EXTRA_SUBJECT, String.format(getResources().getString(R.string.nc_share_subject),
|
||||
getResources().getString(R.string.nc_app_product_name)));
|
||||
}
|
||||
|
||||
private void prepareMenu() {
|
||||
menuItems = new ArrayList<>();
|
||||
|
||||
if (menuType.equals(MenuType.REGULAR)) {
|
||||
if (!TextUtils.isEmpty(conversation.getDisplayName())) {
|
||||
menuItems.add(new MenuItem(conversation.getDisplayName(), 0, null));
|
||||
} else if (!TextUtils.isEmpty(conversation.getName())) {
|
||||
menuItems.add(new MenuItem(conversation.getName(), 0, null));
|
||||
} else {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_configure_room), 0, null));
|
||||
}
|
||||
|
||||
currentUser = userUtils.getCurrentUser();
|
||||
|
||||
if (conversation.isFavorite()) {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_remove_from_favorites), 97, DisplayUtils.getTintedDrawable(getResources(), R.drawable.ic_star_border_black_24dp, R.color.grey_600)));
|
||||
} else if (CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, "favorites")) {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_add_to_favorites),
|
||||
98,
|
||||
DisplayUtils.getTintedDrawable(getResources(),
|
||||
R.drawable.ic_star_black_24dp,
|
||||
R.color.grey_600)));
|
||||
}
|
||||
|
||||
if(conversation.unreadMessages > ALL_MESSAGES_READ && CapabilitiesUtil.canSetChatReadMarker(currentUser)) {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_mark_as_read),
|
||||
96,
|
||||
ContextCompat.getDrawable(context, R.drawable.ic_eye)));
|
||||
}
|
||||
|
||||
if (conversation.isNameEditable(currentUser)) {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_rename),
|
||||
2,
|
||||
ContextCompat.getDrawable(context,
|
||||
R.drawable.ic_pencil_grey600_24dp)));
|
||||
}
|
||||
|
||||
if (conversation.canModerate(currentUser)) {
|
||||
if (!conversation.isPublic()) {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_make_call_public),
|
||||
3, ContextCompat.getDrawable(context,
|
||||
R.drawable.ic_link_grey600_24px)));
|
||||
} else {
|
||||
if (conversation.isHasPassword()) {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_change_password),
|
||||
4, ContextCompat.getDrawable(context,
|
||||
R.drawable.ic_lock_grey600_24px)));
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_clear_password),
|
||||
5,
|
||||
ContextCompat.getDrawable(context,
|
||||
R.drawable.ic_lock_open_grey600_24dp)));
|
||||
} else {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_set_password),
|
||||
6, ContextCompat.getDrawable(context,
|
||||
R.drawable.ic_lock_plus_grey600_24dp)));
|
||||
}
|
||||
}
|
||||
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_delete_call),
|
||||
9, ContextCompat.getDrawable(context,
|
||||
R.drawable.ic_delete_grey600_24dp)));
|
||||
}
|
||||
|
||||
if (conversation.isPublic()) {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_share_link),
|
||||
7, ContextCompat.getDrawable(context,
|
||||
R.drawable.ic_link_grey600_24px)));
|
||||
if (conversation.canModerate(currentUser)) {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_make_call_private),
|
||||
8, ContextCompat.getDrawable(context,
|
||||
R.drawable.ic_group_grey600_24px)));
|
||||
}
|
||||
}
|
||||
|
||||
if (conversation.canLeave(currentUser)) {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_leave), 1,
|
||||
DisplayUtils.getTintedDrawable(getResources(),
|
||||
R.drawable.ic_exit_to_app_black_24dp, R.color.grey_600)
|
||||
));
|
||||
}
|
||||
} else if (menuType.equals(MenuType.SHARE)) {
|
||||
prepareIntent();
|
||||
List<AppAdapter.AppInfo> appInfoList = ShareUtils.getShareApps(getActivity(), shareIntent, null,
|
||||
null);
|
||||
menuItems.add(new AppItem(getResources().getString(R.string.nc_share_link_via),
|
||||
"",
|
||||
"",
|
||||
ContextCompat.getDrawable(context, R.drawable.ic_link_grey600_24px)));
|
||||
if (appInfoList != null) {
|
||||
for (AppAdapter.AppInfo appInfo : appInfoList) {
|
||||
menuItems.add(new AppItem(appInfo.title, appInfo.packageName, appInfo.name, appInfo.drawable));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_start_conversation), 0, null));
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_new_conversation),
|
||||
1, ContextCompat.getDrawable(context,
|
||||
R.drawable.ic_add_grey600_24px)));
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_join_via_link),
|
||||
2, ContextCompat.getDrawable(context,
|
||||
R.drawable.ic_link_grey600_24px)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemClick(View view, int position) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
|
||||
|
||||
if (menuType.equals(MenuType.REGULAR)) {
|
||||
MenuItem menuItem = (MenuItem) adapter.getItem(position);
|
||||
if (menuItem != null) {
|
||||
|
||||
int tag = menuItem.getTag();
|
||||
if (tag == 5) {
|
||||
conversation.setPassword("");
|
||||
}
|
||||
|
||||
if (tag > 0) {
|
||||
if (tag == 1 || tag == 9) {
|
||||
if (tag == 1) {
|
||||
Data data;
|
||||
if ((data = getWorkerData()) != null) {
|
||||
OneTimeWorkRequest leaveConversationWorker =
|
||||
new OneTimeWorkRequest.Builder(LeaveConversationWorker.class).setInputData(data).build();
|
||||
WorkManager.getInstance().enqueue(leaveConversationWorker);
|
||||
}
|
||||
} else {
|
||||
Bundle deleteConversationBundle;
|
||||
if ((deleteConversationBundle = getDeleteConversationBundle()) != null) {
|
||||
conversationMenuInterface.openLovelyDialogWithIdAndBundle(ConversationsListController.ID_DELETE_CONVERSATION_DIALOG, deleteConversationBundle);
|
||||
}
|
||||
}
|
||||
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
|
||||
} else {
|
||||
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), tag);
|
||||
if (tag != 2 && tag != 4 && tag != 6 && tag != 7) {
|
||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
} else if (tag != 7) {
|
||||
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
} else {
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_MENU_TYPE(), Parcels.wrap(MenuType.SHARE));
|
||||
getRouter().pushController(RouterTransaction.with(new CallMenuController(bundle, null))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (menuType.equals(MenuType.SHARE) && position != 0) {
|
||||
AppItem appItem = (AppItem) adapter.getItem(position);
|
||||
if (appItem != null && getActivity() != null) {
|
||||
if (!conversation.hasPassword) {
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, ShareUtils.getStringForIntent(getActivity(), null,
|
||||
userUtils, conversation));
|
||||
Intent intent = new Intent(shareIntent);
|
||||
intent.setComponent(new ComponentName(appItem.getPackageName(), appItem.getName()));
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
|
||||
getActivity().startActivity(intent);
|
||||
} else {
|
||||
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), 7);
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_SHARE_INTENT(), Parcels.wrap(shareIntent));
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_APP_ITEM_PACKAGE_NAME(), appItem.getPackageName());
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_APP_ITEM_NAME(), appItem.getName());
|
||||
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Data getWorkerData() {
|
||||
if (!TextUtils.isEmpty(conversation.getToken())) {
|
||||
Data.Builder data = new Data.Builder();
|
||||
data.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), conversation.getToken());
|
||||
data.putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), currentUser.getId());
|
||||
return data.build();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Bundle getDeleteConversationBundle() {
|
||||
if (!TextUtils.isEmpty(conversation.getToken())) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), currentUser.getId());
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
|
||||
return bundle;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Parcel
|
||||
public enum MenuType {
|
||||
REGULAR, SHARE
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Marcel Hibbe
|
||||
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||
*
|
||||
* 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.controllers.bottomsheet
|
||||
|
||||
enum class ConversationOperationEnum {
|
||||
OPS_CODE_RENAME_ROOM,
|
||||
OPS_CODE_MAKE_PUBLIC,
|
||||
OPS_CODE_CHANGE_PASSWORD,
|
||||
OPS_CODE_CLEAR_PASSWORD,
|
||||
OPS_CODE_SET_PASSWORD,
|
||||
OPS_CODE_SHARE_LINK,
|
||||
OPS_CODE_MAKE_PRIVATE,
|
||||
OPS_CODE_GET_AND_JOIN_ROOM,
|
||||
OPS_CODE_INVITE_USERS,
|
||||
OPS_CODE_MARK_AS_READ,
|
||||
OPS_CODE_REMOVE_FAVORITE,
|
||||
OPS_CODE_ADD_FAVORITE,
|
||||
OPS_CODE_JOIN_ROOM
|
||||
}
|
@ -2,7 +2,9 @@
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* @author Marcel Hibbe
|
||||
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
|
||||
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||
*
|
||||
* 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
|
||||
@ -20,6 +22,14 @@
|
||||
|
||||
package com.nextcloud.talk.controllers.bottomsheet;
|
||||
|
||||
import static com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_JOIN_ROOM;
|
||||
import static com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_GET_AND_JOIN_ROOM;
|
||||
import static com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_INVITE_USERS;
|
||||
import static com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_CHANGE_PASSWORD;
|
||||
import static com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_SET_PASSWORD;
|
||||
import static com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_SHARE_LINK;
|
||||
import static com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_RENAME_ROOM;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PorterDuff;
|
||||
@ -41,7 +51,6 @@ import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
import com.nextcloud.talk.controllers.base.BaseController;
|
||||
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation;
|
||||
import com.nextcloud.talk.utils.EmojiTextInputEditText;
|
||||
import com.nextcloud.talk.utils.ShareUtils;
|
||||
@ -86,7 +95,7 @@ public class EntryMenuController extends BaseController {
|
||||
@Inject
|
||||
UserUtils userUtils;
|
||||
|
||||
private int operationCode;
|
||||
private ConversationOperationEnum operation;
|
||||
private Conversation conversation;
|
||||
private Intent shareIntent;
|
||||
private String packageName;
|
||||
@ -101,7 +110,7 @@ public class EntryMenuController extends BaseController {
|
||||
super(args);
|
||||
originalBundle = args;
|
||||
|
||||
this.operationCode = args.getInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE());
|
||||
this.operation = (ConversationOperationEnum) args.getSerializable(BundleKeys.INSTANCE.getKEY_OPERATION_CODE());
|
||||
if (args.containsKey(BundleKeys.INSTANCE.getKEY_ROOM())) {
|
||||
this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
|
||||
}
|
||||
@ -143,13 +152,12 @@ public class EntryMenuController extends BaseController {
|
||||
@OnClick(R.id.ok_button)
|
||||
public void onProceedButtonClick() {
|
||||
Bundle bundle;
|
||||
if (operationCode == 99) {
|
||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
||||
if (operation == OPS_CODE_JOIN_ROOM) {
|
||||
bundle = new Bundle();
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), callUrl);
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), editText.getText().toString());
|
||||
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
|
||||
bundle.putSerializable(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operation);
|
||||
if (originalBundle.containsKey(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES())) {
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES(), originalBundle.getParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES()));
|
||||
}
|
||||
@ -157,20 +165,19 @@ public class EntryMenuController extends BaseController {
|
||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
} else if (operationCode != 7 && operationCode != 10 && operationCode != 11) {
|
||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
||||
} else if (operation != OPS_CODE_SHARE_LINK && operation != OPS_CODE_GET_AND_JOIN_ROOM && operation != OPS_CODE_INVITE_USERS) {
|
||||
bundle = new Bundle();
|
||||
if (operationCode == 4 || operationCode == 6) {
|
||||
if (operation == OPS_CODE_CHANGE_PASSWORD || operation == OPS_CODE_SET_PASSWORD) {
|
||||
conversation.setPassword(editText.getText().toString());
|
||||
} else {
|
||||
conversation.setName(editText.getText().toString());
|
||||
}
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
|
||||
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
|
||||
bundle.putSerializable(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operation);
|
||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
} else if (operationCode == 7) {
|
||||
} else if (operation == OPS_CODE_SHARE_LINK) {
|
||||
if (getActivity() != null) {
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, ShareUtils.getStringForIntent(getActivity(),
|
||||
editText.getText().toString(), userUtils, conversation));
|
||||
@ -178,19 +185,16 @@ public class EntryMenuController extends BaseController {
|
||||
intent.setComponent(new ComponentName(packageName, name));
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
getActivity().startActivity(intent);
|
||||
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
|
||||
}
|
||||
} else if (operationCode != 11) {
|
||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
||||
} else if (operation != OPS_CODE_INVITE_USERS) {
|
||||
bundle = new Bundle();
|
||||
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
|
||||
bundle.putSerializable(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operation);
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), editText.getText().toString());
|
||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
|
||||
} else if (operationCode == 11) {
|
||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
||||
} else if (operation == OPS_CODE_INVITE_USERS) {
|
||||
originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), editText.getText().toString());
|
||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(originalBundle))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
@ -204,7 +208,7 @@ public class EntryMenuController extends BaseController {
|
||||
super.onViewBound(view);
|
||||
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
|
||||
|
||||
if (conversation != null && operationCode == 2) {
|
||||
if (conversation != null && operation == OPS_CODE_RENAME_ROOM) {
|
||||
editText.setText(conversation.getName());
|
||||
}
|
||||
|
||||
@ -230,7 +234,7 @@ public class EntryMenuController extends BaseController {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (!TextUtils.isEmpty(s)) {
|
||||
if (operationCode == 2) {
|
||||
if (operation == OPS_CODE_RENAME_ROOM) {
|
||||
if (conversation.getName() == null || !conversation.getName().equals(s.toString())) {
|
||||
if (!proceedButton.isEnabled()) {
|
||||
proceedButton.setEnabled(true);
|
||||
@ -244,7 +248,7 @@ public class EntryMenuController extends BaseController {
|
||||
}
|
||||
textInputLayout.setError(getResources().getString(R.string.nc_call_name_is_same));
|
||||
}
|
||||
} else if (operationCode != 10) {
|
||||
} else if (operation != OPS_CODE_GET_AND_JOIN_ROOM) {
|
||||
if (!proceedButton.isEnabled()) {
|
||||
proceedButton.setEnabled(true);
|
||||
proceedButton.setAlpha(1.0f);
|
||||
@ -253,7 +257,6 @@ public class EntryMenuController extends BaseController {
|
||||
} else if ((editText.getText().toString().startsWith("http://") ||
|
||||
editText.getText().toString().startsWith("https://")) &&
|
||||
editText.getText().toString().contains("/call/")) {
|
||||
// operation code 10
|
||||
if (!proceedButton.isEnabled()) {
|
||||
proceedButton.setEnabled(true);
|
||||
proceedButton.setAlpha(1.0f);
|
||||
@ -277,9 +280,9 @@ public class EntryMenuController extends BaseController {
|
||||
});
|
||||
|
||||
String labelText = "";
|
||||
switch (operationCode) {
|
||||
case 11:
|
||||
case 2:
|
||||
switch (operation) {
|
||||
case OPS_CODE_INVITE_USERS:
|
||||
case OPS_CODE_RENAME_ROOM:
|
||||
labelText = getResources().getString(R.string.nc_call_name);
|
||||
editText.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
smileyButton.setVisibility(View.VISIBLE);
|
||||
@ -307,18 +310,18 @@ public class EntryMenuController extends BaseController {
|
||||
}).build(editText);
|
||||
|
||||
break;
|
||||
case 4:
|
||||
case OPS_CODE_CHANGE_PASSWORD:
|
||||
labelText = getResources().getString(R.string.nc_new_password);
|
||||
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
case 99:
|
||||
case OPS_CODE_SET_PASSWORD:
|
||||
case OPS_CODE_SHARE_LINK:
|
||||
case OPS_CODE_JOIN_ROOM:
|
||||
// 99 is joining a conversation via password
|
||||
labelText = getResources().getString(R.string.nc_password);
|
||||
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
break;
|
||||
case 10:
|
||||
case OPS_CODE_GET_AND_JOIN_ROOM:
|
||||
labelText = getResources().getString(R.string.nc_conversation_link);
|
||||
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
|
||||
break;
|
||||
@ -326,7 +329,10 @@ public class EntryMenuController extends BaseController {
|
||||
break;
|
||||
}
|
||||
|
||||
if (operationCode == 99 || operationCode == 4 || operationCode == 6 || operationCode == 7) {
|
||||
if (operation == OPS_CODE_JOIN_ROOM
|
||||
|| operation == OPS_CODE_CHANGE_PASSWORD
|
||||
|| operation == OPS_CODE_SET_PASSWORD
|
||||
|| operation == OPS_CODE_SHARE_LINK) {
|
||||
textInputLayout.setEndIconMode(TextInputLayout.END_ICON_PASSWORD_TOGGLE);
|
||||
} else {
|
||||
textInputLayout.setEndIconMode(TextInputLayout.END_ICON_NONE);
|
||||
@ -335,4 +341,9 @@ public class EntryMenuController extends BaseController {
|
||||
textInputLayout.setHint(labelText);
|
||||
textInputLayout.requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppBarLayoutType getAppBarLayoutType() {
|
||||
return AppBarLayoutType.SEARCH_BAR;
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,9 @@
|
||||
|
||||
package com.nextcloud.talk.controllers.bottomsheet;
|
||||
|
||||
import static com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_JOIN_ROOM;
|
||||
import static com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_REMOVE_FAVORITE;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
@ -33,7 +36,6 @@ import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||
@ -42,7 +44,8 @@ import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.api.NcApi;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
import com.nextcloud.talk.controllers.base.BaseController;
|
||||
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
||||
import com.nextcloud.talk.events.ConversationsListFetchDataEvent;
|
||||
import com.nextcloud.talk.events.OpenConversationEvent;
|
||||
import com.nextcloud.talk.models.RetrofitBucket;
|
||||
import com.nextcloud.talk.models.database.CapabilitiesUtil;
|
||||
import com.nextcloud.talk.models.database.UserEntity;
|
||||
@ -53,7 +56,6 @@ import com.nextcloud.talk.models.json.conversations.RoomOverall;
|
||||
import com.nextcloud.talk.models.json.generic.GenericOverall;
|
||||
import com.nextcloud.talk.models.json.participants.AddParticipantOverall;
|
||||
import com.nextcloud.talk.utils.ApiUtils;
|
||||
import com.nextcloud.talk.utils.ConductorRemapping;
|
||||
import com.nextcloud.talk.utils.DisplayUtils;
|
||||
import com.nextcloud.talk.utils.NoSupportedApiException;
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
||||
@ -75,7 +77,6 @@ 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;
|
||||
|
||||
@ -108,7 +109,7 @@ public class OperationsMenuController extends BaseController {
|
||||
@Inject
|
||||
EventBus eventBus;
|
||||
|
||||
private int operationCode;
|
||||
private ConversationOperationEnum operation;
|
||||
private Conversation conversation;
|
||||
|
||||
private UserEntity currentUser;
|
||||
@ -130,7 +131,7 @@ public class OperationsMenuController extends BaseController {
|
||||
|
||||
public OperationsMenuController(Bundle args) {
|
||||
super(args);
|
||||
this.operationCode = args.getInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE());
|
||||
this.operation = (ConversationOperationEnum) args.getSerializable(BundleKeys.INSTANCE.getKEY_OPERATION_CODE());
|
||||
if (args.containsKey(BundleKeys.INSTANCE.getKEY_ROOM())) {
|
||||
this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
|
||||
}
|
||||
@ -283,8 +284,8 @@ public class OperationsMenuController extends BaseController {
|
||||
int apiVersion = ApiUtils.getConversationApiVersion(currentUser, new int[] {ApiUtils.APIv4, ApiUtils.APIv1});
|
||||
int chatApiVersion = ApiUtils.getChatApiVersion(currentUser, new int[] {ApiUtils.APIv1});
|
||||
|
||||
switch (operationCode) {
|
||||
case 2:
|
||||
switch (operation) {
|
||||
case OPS_CODE_RENAME_ROOM:
|
||||
ncApi.renameRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, currentUser.getBaseUrl(),
|
||||
conversation.getToken()),
|
||||
conversation.getName())
|
||||
@ -293,7 +294,7 @@ public class OperationsMenuController extends BaseController {
|
||||
.retry(1)
|
||||
.subscribe(genericOperationsObserver);
|
||||
break;
|
||||
case 3:
|
||||
case OPS_CODE_MAKE_PUBLIC:
|
||||
ncApi.makeRoomPublic(credentials, ApiUtils.getUrlForRoomPublic(apiVersion, currentUser.getBaseUrl(),
|
||||
conversation.getToken()))
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -301,9 +302,9 @@ public class OperationsMenuController extends BaseController {
|
||||
.retry(1)
|
||||
.subscribe(genericOperationsObserver);
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case OPS_CODE_CHANGE_PASSWORD:
|
||||
case OPS_CODE_CLEAR_PASSWORD:
|
||||
case OPS_CODE_SET_PASSWORD:
|
||||
String pass = "";
|
||||
if (conversation.getPassword() != null) {
|
||||
pass = conversation.getPassword();
|
||||
@ -315,10 +316,7 @@ public class OperationsMenuController extends BaseController {
|
||||
.retry(1)
|
||||
.subscribe(genericOperationsObserver);
|
||||
break;
|
||||
case 7:
|
||||
// Operation 7 is sharing, so we handle this differently
|
||||
break;
|
||||
case 8:
|
||||
case OPS_CODE_MAKE_PRIVATE:
|
||||
ncApi.makeRoomPrivate(credentials, ApiUtils.getUrlForRoomPublic(apiVersion,
|
||||
currentUser.getBaseUrl(),
|
||||
conversation.getToken()))
|
||||
@ -327,7 +325,7 @@ public class OperationsMenuController extends BaseController {
|
||||
.retry(1)
|
||||
.subscribe(genericOperationsObserver);
|
||||
break;
|
||||
case 10:
|
||||
case OPS_CODE_GET_AND_JOIN_ROOM:
|
||||
ncApi.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, baseUrl, conversationToken))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -342,8 +340,7 @@ public class OperationsMenuController extends BaseController {
|
||||
public void onNext(@io.reactivex.annotations.NonNull RoomOverall roomOverall) {
|
||||
conversation = roomOverall.getOcs().getData();
|
||||
if (conversation.isHasPassword() && conversation.isGuest()) {
|
||||
eventBus.post(new BottomSheetLockEvent(true, 0,
|
||||
true, false));
|
||||
eventBus.post(new ConversationsListFetchDataEvent());
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), callUrl);
|
||||
@ -355,7 +352,7 @@ public class OperationsMenuController extends BaseController {
|
||||
Log.e(TAG, "Failed to parse capabilities for guest");
|
||||
showResultImage(false, false);
|
||||
}
|
||||
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), 99);
|
||||
bundle.putSerializable(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), OPS_CODE_JOIN_ROOM);
|
||||
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
@ -407,7 +404,7 @@ public class OperationsMenuController extends BaseController {
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 11:
|
||||
case OPS_CODE_INVITE_USERS:
|
||||
RetrofitBucket retrofitBucket;
|
||||
String invite = null;
|
||||
|
||||
@ -483,7 +480,7 @@ public class OperationsMenuController extends BaseController {
|
||||
});
|
||||
|
||||
break;
|
||||
case 96:
|
||||
case OPS_CODE_MARK_AS_READ:
|
||||
ncApi.setChatReadMarker(credentials,
|
||||
ApiUtils.getUrlForSetChatReadMarker(chatApiVersion,
|
||||
currentUser.getBaseUrl(),
|
||||
@ -494,9 +491,9 @@ public class OperationsMenuController extends BaseController {
|
||||
.retry(1)
|
||||
.subscribe(genericOperationsObserver);
|
||||
break;
|
||||
case 97:
|
||||
case 98:
|
||||
if (operationCode == 97) {
|
||||
case OPS_CODE_REMOVE_FAVORITE:
|
||||
case OPS_CODE_ADD_FAVORITE:
|
||||
if (operation == OPS_CODE_REMOVE_FAVORITE) {
|
||||
ncApi.removeConversationFromFavorites(credentials,
|
||||
ApiUtils.getUrlForRoomFavorite(apiVersion,
|
||||
currentUser.getBaseUrl(),
|
||||
@ -516,7 +513,7 @@ public class OperationsMenuController extends BaseController {
|
||||
.subscribe(genericOperationsObserver);
|
||||
}
|
||||
break;
|
||||
case 99:
|
||||
case OPS_CODE_JOIN_ROOM:
|
||||
ncApi.joinRoom(credentials, ApiUtils.getUrlForParticipantsActive(apiVersion,
|
||||
baseUrl,
|
||||
conversationToken),
|
||||
@ -557,10 +554,8 @@ public class OperationsMenuController extends BaseController {
|
||||
} else {
|
||||
resultsTextView.setText(R.string.nc_failed_signaling_settings);
|
||||
webButton.setOnClickListener(v -> {
|
||||
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(callUrl));
|
||||
startActivity(browserIntent);
|
||||
new BottomSheetLockEvent(true, 0, false, true);
|
||||
});
|
||||
webButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
@ -568,12 +563,11 @@ public class OperationsMenuController extends BaseController {
|
||||
|
||||
resultsTextView.setVisibility(View.VISIBLE);
|
||||
if (everythingOK) {
|
||||
eventBus.post(new BottomSheetLockEvent(true, 2500, true, true));
|
||||
eventBus.post(new ConversationsListFetchDataEvent());
|
||||
} else {
|
||||
resultImageView.setImageDrawable(DisplayUtils.getTintedDrawable(getResources(), R.drawable
|
||||
.ic_cancel_black_24dp, R.color.nc_darkRed));
|
||||
okButton.setOnClickListener(v -> eventBus.post(new BottomSheetLockEvent(true, 0, operationCode != 99
|
||||
&& operationCode != 10, true)));
|
||||
okButton.setOnClickListener(v -> eventBus.post(new ConversationsListFetchDataEvent()));
|
||||
okButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
@ -724,8 +718,7 @@ public class OperationsMenuController extends BaseController {
|
||||
}
|
||||
|
||||
private void initiateConversation(boolean dismissView) {
|
||||
eventBus.post(new BottomSheetLockEvent(true, 0,
|
||||
true, true, dismissView));
|
||||
eventBus.post(new ConversationsListFetchDataEvent());
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), conversation.getToken());
|
||||
@ -735,20 +728,15 @@ public class OperationsMenuController extends BaseController {
|
||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(), Parcels.wrap(conversation));
|
||||
bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), callPassword);
|
||||
|
||||
if (getParentController() != null) {
|
||||
ConductorRemapping.INSTANCE.remapChatController(getParentController().getRouter(), currentUser.getId(),
|
||||
conversation.getToken(), bundle, true);
|
||||
}
|
||||
eventBus.post(new OpenConversationEvent(conversation, bundle));
|
||||
}
|
||||
|
||||
private void handleObserverError(@io.reactivex.annotations.NonNull Throwable e) {
|
||||
if (operationCode != 99 || !(e instanceof HttpException)) {
|
||||
if (operation != OPS_CODE_JOIN_ROOM || !(e instanceof HttpException)) {
|
||||
showResultImage(false, false);
|
||||
} else {
|
||||
Response<?> response = ((HttpException) e).response();
|
||||
if (response != null && response.code() == 403) {
|
||||
eventBus.post(new BottomSheetLockEvent(true, 0, false,
|
||||
false));
|
||||
ApplicationWideMessageHolder.getInstance().setMessageType(ApplicationWideMessageHolder.MessageType.CALL_PASSWORD_WRONG);
|
||||
getRouter().popCurrentController();
|
||||
} else {
|
||||
@ -767,7 +755,7 @@ public class OperationsMenuController extends BaseController {
|
||||
|
||||
@Override
|
||||
public void onNext(@io.reactivex.annotations.NonNull GenericOverall genericOverall) {
|
||||
if (operationCode != 99) {
|
||||
if (operation != OPS_CODE_JOIN_ROOM) {
|
||||
showResultImage(true, false);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported operation code observed!");
|
||||
@ -795,7 +783,7 @@ public class OperationsMenuController extends BaseController {
|
||||
@Override
|
||||
public void onNext(@io.reactivex.annotations.NonNull RoomOverall roomOverall) {
|
||||
conversation = roomOverall.getOcs().getData();
|
||||
if (operationCode != 99) {
|
||||
if (operation != OPS_CODE_JOIN_ROOM) {
|
||||
showResultImage(true, false);
|
||||
} else {
|
||||
conversation = roomOverall.getOcs().getData();
|
||||
@ -813,4 +801,9 @@ public class OperationsMenuController extends BaseController {
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppBarLayoutType getAppBarLayoutType() {
|
||||
return AppBarLayoutType.SEARCH_BAR;
|
||||
}
|
||||
}
|
||||
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017 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.events;
|
||||
|
||||
public class BottomSheetLockEvent {
|
||||
private final boolean cancelable;
|
||||
private final int delay;
|
||||
private final boolean shouldRefreshData;
|
||||
private final boolean cancel;
|
||||
private boolean dismissView;
|
||||
|
||||
public BottomSheetLockEvent(boolean cancelable, int delay, boolean shouldRefreshData, boolean cancel) {
|
||||
this.cancelable = cancelable;
|
||||
this.delay = delay;
|
||||
this.shouldRefreshData = shouldRefreshData;
|
||||
this.cancel = cancel;
|
||||
this.dismissView = true;
|
||||
}
|
||||
|
||||
public BottomSheetLockEvent(boolean cancelable, int delay, boolean shouldRefreshData, boolean cancel, boolean
|
||||
dismissView) {
|
||||
this.cancelable = cancelable;
|
||||
this.delay = delay;
|
||||
this.shouldRefreshData = shouldRefreshData;
|
||||
this.cancel = cancel;
|
||||
this.dismissView = dismissView;
|
||||
}
|
||||
|
||||
public boolean isCancelable() {
|
||||
return this.cancelable;
|
||||
}
|
||||
|
||||
public int getDelay() {
|
||||
return this.delay;
|
||||
}
|
||||
|
||||
public boolean isShouldRefreshData() {
|
||||
return this.shouldRefreshData;
|
||||
}
|
||||
|
||||
public boolean isCancel() {
|
||||
return this.cancel;
|
||||
}
|
||||
|
||||
public boolean isDismissView() {
|
||||
return this.dismissView;
|
||||
}
|
||||
|
||||
public void setDismissView(boolean dismissView) {
|
||||
this.dismissView = dismissView;
|
||||
}
|
||||
|
||||
public boolean equals(final Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof BottomSheetLockEvent)) {
|
||||
return false;
|
||||
}
|
||||
final BottomSheetLockEvent other = (BottomSheetLockEvent) o;
|
||||
if (!other.canEqual((Object) this)) {
|
||||
return false;
|
||||
}
|
||||
if (this.isCancelable() != other.isCancelable()) {
|
||||
return false;
|
||||
}
|
||||
if (this.getDelay() != other.getDelay()) {
|
||||
return false;
|
||||
}
|
||||
if (this.isShouldRefreshData() != other.isShouldRefreshData()) {
|
||||
return false;
|
||||
}
|
||||
if (this.isCancel() != other.isCancel()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.isDismissView() == other.isDismissView();
|
||||
}
|
||||
|
||||
protected boolean canEqual(final Object other) {
|
||||
return other instanceof BottomSheetLockEvent;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
final int PRIME = 59;
|
||||
int result = 1;
|
||||
result = result * PRIME + (this.isCancelable() ? 79 : 97);
|
||||
result = result * PRIME + this.getDelay();
|
||||
result = result * PRIME + (this.isShouldRefreshData() ? 79 : 97);
|
||||
result = result * PRIME + (this.isCancel() ? 79 : 97);
|
||||
result = result * PRIME + (this.isDismissView() ? 79 : 97);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "BottomSheetLockEvent(cancelable=" + this.isCancelable() + ", delay=" + this.getDelay() + ", shouldRefreshData=" + this.isShouldRefreshData() + ", cancel=" + this.isCancel() + ", dismissView=" + this.isDismissView() + ")";
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Marcel Hibbe
|
||||
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||
*
|
||||
* 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.events
|
||||
|
||||
class ConversationsListFetchDataEvent
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Marcel Hibbe
|
||||
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||
*
|
||||
* 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.events
|
||||
|
||||
import android.os.Bundle
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
|
||||
class OpenConversationEvent {
|
||||
var conversation: Conversation? = null
|
||||
var bundle: Bundle? = null
|
||||
|
||||
constructor(conversation: Conversation?, bundle: Bundle?) {
|
||||
this.conversation = conversation
|
||||
this.bundle = bundle
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as OpenConversationEvent
|
||||
|
||||
if (conversation != other.conversation) return false
|
||||
if (bundle != other.bundle) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = conversation?.hashCode() ?: 0
|
||||
result = 31 * result + (bundle?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
}
|
@ -21,6 +21,8 @@
|
||||
package com.nextcloud.talk.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.work.Data;
|
||||
import androidx.work.Worker;
|
||||
@ -48,6 +50,8 @@ import java.net.CookieManager;
|
||||
@AutoInjector(NextcloudTalkApplication.class)
|
||||
public class LeaveConversationWorker extends Worker {
|
||||
|
||||
private static String TAG = "LeaveConversationWorker";
|
||||
|
||||
@Inject
|
||||
Retrofit retrofit;
|
||||
|
||||
@ -106,7 +110,7 @@ public class LeaveConversationWorker extends Worker {
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
|
||||
Log.e(TAG, "failed to remove self from room", e);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -148,23 +148,12 @@ public class Conversation {
|
||||
return (canModerate(conversationUser) && !ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL.equals(type));
|
||||
}
|
||||
|
||||
public boolean canLeave(UserEntity conversationUser) {
|
||||
if (canLeaveConversation != null) {
|
||||
// Available since APIv2
|
||||
return canLeaveConversation;
|
||||
}
|
||||
// Fallback for APIv1
|
||||
return !canModerate(conversationUser) ||
|
||||
(getType() != ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL && this.participants.size() > 1);
|
||||
public boolean canLeave() {
|
||||
return canLeaveConversation;
|
||||
}
|
||||
|
||||
public boolean canDelete(UserEntity conversationUser) {
|
||||
if (canDeleteConversation != null) {
|
||||
// Available since APIv2
|
||||
return canDeleteConversation;
|
||||
}
|
||||
// Fallback for APIv1
|
||||
return canModerate(conversationUser);
|
||||
public boolean canDelete() {
|
||||
return canDeleteConversation;
|
||||
}
|
||||
|
||||
public String getRoomId() {
|
||||
|
@ -63,6 +63,7 @@ class ProfileBottomSheet(val ncApi: NcApi, val userEntity: UserEntity, val route
|
||||
).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : io.reactivex.Observer<HoverCardOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(hoverCardOverall: HoverCardOverall) {
|
||||
@ -74,6 +75,7 @@ class ProfileBottomSheet(val ncApi: NcApi, val userEntity: UserEntity, val route
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Marcel Hibbe
|
||||
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||
*
|
||||
* 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.ui.dialog
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import autodagger.AutoInjector
|
||||
import com.bluelinelabs.conductor.Conductor
|
||||
import com.bluelinelabs.conductor.Router
|
||||
import com.bluelinelabs.conductor.RouterTransaction
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController
|
||||
import com.nextcloud.talk.databinding.DialogBottomContactsBinding
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class ContactsBottomDialog(
|
||||
val activity: Activity,
|
||||
val bundle: Bundle
|
||||
) : BottomSheetDialog(activity, R.style.BottomSheetDialogThemeNoFloating) {
|
||||
|
||||
private var dialogRouter: Router? = null
|
||||
|
||||
private lateinit var binding: DialogBottomContactsBinding
|
||||
|
||||
init {
|
||||
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = DialogBottomContactsBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
|
||||
executeEntryMenuController(bundle)
|
||||
}
|
||||
|
||||
private fun executeEntryMenuController(bundle: Bundle) {
|
||||
dialogRouter = Conductor.attachRouter(activity, binding.root, null)
|
||||
|
||||
dialogRouter!!.pushController(
|
||||
RouterTransaction.with(EntryMenuController(bundle))
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler())
|
||||
)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val bottomSheet = findViewById<View>(R.id.design_bottom_sheet)
|
||||
val behavior = BottomSheetBehavior.from(bottomSheet as View)
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ContactsBottomDialog"
|
||||
}
|
||||
}
|
@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Marcel Hibbe
|
||||
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||
*
|
||||
* 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.ui.dialog
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.work.Data
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.WorkManager
|
||||
import autodagger.AutoInjector
|
||||
import com.bluelinelabs.conductor.Conductor
|
||||
import com.bluelinelabs.conductor.Router
|
||||
import com.bluelinelabs.conductor.RouterTransaction
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.api.NcApi
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.controllers.ConversationsListController
|
||||
import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum
|
||||
import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_ADD_FAVORITE
|
||||
import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_REMOVE_FAVORITE
|
||||
import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_CHANGE_PASSWORD
|
||||
import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_SET_PASSWORD
|
||||
import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_CLEAR_PASSWORD
|
||||
import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_MAKE_PRIVATE
|
||||
import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_MAKE_PUBLIC
|
||||
import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_RENAME_ROOM
|
||||
import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_MARK_AS_READ
|
||||
import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController
|
||||
import com.nextcloud.talk.controllers.bottomsheet.OperationsMenuController
|
||||
import com.nextcloud.talk.databinding.DialogConversationOperationsBinding
|
||||
import com.nextcloud.talk.jobs.LeaveConversationWorker
|
||||
import com.nextcloud.talk.models.database.CapabilitiesUtil
|
||||
import com.nextcloud.talk.models.database.UserEntity
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.nextcloud.talk.utils.ShareUtils
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INTERNAL_USER_ID
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_OPERATION_CODE
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils
|
||||
import org.parceler.Parcels
|
||||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class ConversationsListBottomDialog(
|
||||
val activity: Activity,
|
||||
val controller: ConversationsListController,
|
||||
val currentUser: UserEntity,
|
||||
val conversation: Conversation
|
||||
) : BottomSheetDialog(activity, R.style.BottomSheetDialogThemeNoFloating) {
|
||||
|
||||
private var dialogRouter: Router? = null
|
||||
|
||||
private lateinit var binding: DialogConversationOperationsBinding
|
||||
|
||||
@Inject
|
||||
@JvmField
|
||||
var ncApi: NcApi? = null
|
||||
|
||||
@Inject
|
||||
@JvmField
|
||||
var userUtils: UserUtils? = null
|
||||
|
||||
init {
|
||||
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = DialogConversationOperationsBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
|
||||
initHeaderDescription()
|
||||
initItemsVisibility()
|
||||
initClickListeners()
|
||||
}
|
||||
|
||||
private fun initHeaderDescription() {
|
||||
if (!TextUtils.isEmpty(conversation.getDisplayName())) {
|
||||
binding.conversationOperationHeader.text = conversation.getDisplayName()
|
||||
} else if (!TextUtils.isEmpty(conversation.getName())) {
|
||||
binding.conversationOperationHeader.text = conversation.getName()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initItemsVisibility() {
|
||||
val hasFavoritesCapability = CapabilitiesUtil.hasSpreedFeatureCapability(currentUser, "favorites")
|
||||
val canModerate = conversation.canModerate(currentUser)
|
||||
|
||||
binding.conversationOperationRemoveFavorite.visibility = setVisibleIf(
|
||||
hasFavoritesCapability && conversation.isFavorite()
|
||||
)
|
||||
binding.conversationOperationAddFavorite.visibility = setVisibleIf(
|
||||
hasFavoritesCapability && !conversation.isFavorite()
|
||||
)
|
||||
|
||||
binding.conversationOperationMarkAsRead.visibility = setVisibleIf(
|
||||
conversation.unreadMessages > 0 && CapabilitiesUtil.canSetChatReadMarker(currentUser)
|
||||
)
|
||||
|
||||
binding.conversationOperationRename.visibility = setVisibleIf(
|
||||
conversation.isNameEditable(currentUser)
|
||||
)
|
||||
|
||||
binding.conversationOperationMakePublic.visibility = setVisibleIf(
|
||||
canModerate && !conversation.isPublic
|
||||
)
|
||||
|
||||
binding.conversationOperationChangePassword.visibility = setVisibleIf(
|
||||
canModerate && conversation.isHasPassword && conversation.isPublic
|
||||
)
|
||||
|
||||
binding.conversationOperationClearPassword.visibility = setVisibleIf(
|
||||
canModerate && conversation.isHasPassword && conversation.isPublic
|
||||
)
|
||||
|
||||
binding.conversationOperationSetPassword.visibility = setVisibleIf(
|
||||
canModerate && !conversation.isHasPassword && conversation.isPublic
|
||||
)
|
||||
|
||||
binding.conversationOperationDelete.visibility = setVisibleIf(
|
||||
canModerate
|
||||
)
|
||||
|
||||
binding.conversationOperationShareLink.visibility = setVisibleIf(
|
||||
conversation.isPublic
|
||||
)
|
||||
|
||||
binding.conversationOperationMakePrivate.visibility = setVisibleIf(
|
||||
conversation.isPublic && canModerate
|
||||
)
|
||||
|
||||
binding.conversationOperationLeave.visibility = setVisibleIf(
|
||||
conversation.canLeave() &&
|
||||
// leaving is by api not possible for the last user with moderator permissions.
|
||||
// for now, hide this option for all moderators.
|
||||
!conversation.canModerate(currentUser)
|
||||
)
|
||||
}
|
||||
|
||||
private fun setVisibleIf(boolean: Boolean): Int {
|
||||
return if (boolean) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun initClickListeners() {
|
||||
binding.conversationOperationAddFavorite.setOnClickListener {
|
||||
executeOperationsMenuController(OPS_CODE_ADD_FAVORITE)
|
||||
}
|
||||
|
||||
binding.conversationOperationRemoveFavorite.setOnClickListener {
|
||||
executeOperationsMenuController(OPS_CODE_REMOVE_FAVORITE)
|
||||
}
|
||||
|
||||
binding.conversationOperationLeave.setOnClickListener {
|
||||
val dataBuilder = Data.Builder()
|
||||
dataBuilder.putString(KEY_ROOM_TOKEN, conversation.getToken())
|
||||
dataBuilder.putLong(KEY_INTERNAL_USER_ID, currentUser.id)
|
||||
val data = dataBuilder.build()
|
||||
|
||||
val leaveConversationWorker =
|
||||
OneTimeWorkRequest.Builder(LeaveConversationWorker::class.java).setInputData(
|
||||
data
|
||||
).build()
|
||||
WorkManager.getInstance().enqueue(leaveConversationWorker)
|
||||
|
||||
dismiss()
|
||||
}
|
||||
|
||||
binding.conversationOperationDelete.setOnClickListener {
|
||||
if (!TextUtils.isEmpty(conversation.getToken())) {
|
||||
val bundle = Bundle()
|
||||
bundle.putLong(KEY_INTERNAL_USER_ID, currentUser.id)
|
||||
bundle.putParcelable(KEY_ROOM, Parcels.wrap(conversation))
|
||||
|
||||
controller.openLovelyDialogWithIdAndBundle(
|
||||
ConversationsListController.ID_DELETE_CONVERSATION_DIALOG,
|
||||
bundle
|
||||
)
|
||||
}
|
||||
|
||||
dismiss()
|
||||
}
|
||||
|
||||
binding.conversationOperationMakePublic.setOnClickListener {
|
||||
executeOperationsMenuController(OPS_CODE_MAKE_PUBLIC)
|
||||
}
|
||||
|
||||
binding.conversationOperationMakePrivate.setOnClickListener {
|
||||
executeOperationsMenuController(OPS_CODE_MAKE_PRIVATE)
|
||||
}
|
||||
|
||||
binding.conversationOperationChangePassword.setOnClickListener {
|
||||
executeEntryMenuController(OPS_CODE_CHANGE_PASSWORD)
|
||||
}
|
||||
|
||||
binding.conversationOperationClearPassword.setOnClickListener {
|
||||
executeOperationsMenuController(OPS_CODE_CLEAR_PASSWORD)
|
||||
}
|
||||
|
||||
binding.conversationOperationSetPassword.setOnClickListener {
|
||||
executeEntryMenuController(OPS_CODE_SET_PASSWORD)
|
||||
}
|
||||
|
||||
binding.conversationOperationRename.setOnClickListener {
|
||||
executeEntryMenuController(OPS_CODE_RENAME_ROOM)
|
||||
}
|
||||
|
||||
binding.conversationOperationMarkAsRead.setOnClickListener {
|
||||
executeOperationsMenuController(OPS_CODE_MARK_AS_READ)
|
||||
}
|
||||
|
||||
binding.conversationOperationShareLink.setOnClickListener {
|
||||
val sendIntent: Intent = Intent().apply {
|
||||
action = Intent.ACTION_SEND
|
||||
type = "text/plain"
|
||||
putExtra(
|
||||
Intent.EXTRA_SUBJECT,
|
||||
String.format(
|
||||
activity.resources.getString(R.string.nc_share_subject),
|
||||
activity.resources.getString(R.string.nc_app_product_name)
|
||||
)
|
||||
)
|
||||
// password should not be shared!!
|
||||
putExtra(
|
||||
Intent.EXTRA_TEXT,
|
||||
ShareUtils.getStringForIntent(activity, null, userUtils, conversation)
|
||||
)
|
||||
}
|
||||
|
||||
val shareIntent = Intent.createChooser(sendIntent, null)
|
||||
activity.startActivity(shareIntent)
|
||||
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun executeOperationsMenuController(operation: ConversationOperationEnum) {
|
||||
val bundle = Bundle()
|
||||
bundle.putParcelable(KEY_ROOM, Parcels.wrap(conversation))
|
||||
bundle.putSerializable(KEY_OPERATION_CODE, operation)
|
||||
|
||||
binding.operationItemsLayout.visibility = View.GONE
|
||||
|
||||
dialogRouter = Conductor.attachRouter(activity, binding.root, null)
|
||||
|
||||
dialogRouter!!.pushController(
|
||||
RouterTransaction.with(OperationsMenuController(bundle))
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler())
|
||||
)
|
||||
|
||||
controller.fetchData()
|
||||
}
|
||||
|
||||
private fun executeEntryMenuController(operation: ConversationOperationEnum) {
|
||||
val bundle = Bundle()
|
||||
bundle.putParcelable(KEY_ROOM, Parcels.wrap(conversation))
|
||||
bundle.putSerializable(KEY_OPERATION_CODE, operation)
|
||||
|
||||
binding.operationItemsLayout.visibility = View.GONE
|
||||
|
||||
dialogRouter = Conductor.attachRouter(activity, binding.root, null)
|
||||
|
||||
dialogRouter!!.pushController(
|
||||
|
||||
// TODO: refresh conversation list after EntryMenuController finished (throw event? / pass controller
|
||||
// into EntryMenuController to execute fetch data... ?!)
|
||||
// for example if you set a password, the dialog items should be refreshed for the next time you open it
|
||||
// without to manually have to refresh the conversations list
|
||||
// also see BottomSheetLockEvent ??
|
||||
|
||||
RouterTransaction.with(EntryMenuController(bundle))
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler())
|
||||
)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val bottomSheet = findViewById<View>(R.id.design_bottom_sheet)
|
||||
val behavior = BottomSheetBehavior.from(bottomSheet as View)
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ConversationOperationDialog"
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Mike Penz All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 14.03.15.
|
||||
* This class implements a hack to change the layout padding on bottom if the keyboard is shown
|
||||
* to allow long lists with editTextViews
|
||||
* Basic idea for this solution found here: http://stackoverflow.com/a/9108219/325479
|
||||
*/
|
||||
public class KeyboardUtils {
|
||||
private View decorView;
|
||||
private View contentView;
|
||||
private boolean isUsedInBottomSheet;
|
||||
//a small helper to allow showing the editText focus
|
||||
ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
Rect r = new Rect();
|
||||
//r will be populated with the coordinates of your view that area still visible.
|
||||
decorView.getWindowVisibleDisplayFrame(r);
|
||||
|
||||
//get screen height and calculate the difference with the useable area from the r
|
||||
int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
|
||||
|
||||
int diff = height - r.bottom;
|
||||
|
||||
boolean shouldSetBottomPadding = (isUsedInBottomSheet && diff != 0) || (diff > 0);
|
||||
|
||||
if (shouldSetBottomPadding) {
|
||||
if (contentView.getPaddingBottom() != diff) {
|
||||
//set the padding of the contentView for the keyboard
|
||||
contentView.setPadding(0, 0, 0, diff);
|
||||
}
|
||||
} else {
|
||||
//check if the padding is != initialBottomPadding (if yes reset the padding)
|
||||
if (contentView.getPaddingBottom() != 0) {
|
||||
//reset the padding of the contentView
|
||||
contentView.setPadding(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public KeyboardUtils(Activity act, View contentView, boolean isUsedInBottomSheet) {
|
||||
this.decorView = act.getWindow().getDecorView();
|
||||
this.contentView = contentView;
|
||||
this.isUsedInBottomSheet = isUsedInBottomSheet;
|
||||
|
||||
decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to hide the keyboard
|
||||
*
|
||||
* @param act
|
||||
*/
|
||||
public static void hideKeyboard(Activity act) {
|
||||
if (act != null && act.getCurrentFocus() != null) {
|
||||
InputMethodManager inputMethodManager = (InputMethodManager) act.getSystemService(Activity.INPUT_METHOD_SERVICE);
|
||||
inputMethodManager.hideSoftInputFromWindow(act.getCurrentFocus().getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
decorView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
|
||||
}
|
||||
}
|
@ -16,29 +16,19 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Part of the code in ShareUtils was inspired by BottomSheet under the Apache licence
|
||||
* located here: https://github.com/Kennyc1012/BottomSheet/blob/master/library/src/main/java/com/kennyc/bottomsheet/BottomSheet.java#L425
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.kennyc.bottomsheet.adapters.AppAdapter;
|
||||
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.models.database.UserEntity;
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation;
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class ShareUtils {
|
||||
|
||||
@ -58,49 +48,4 @@ public class ShareUtils {
|
||||
|
||||
return shareString;
|
||||
}
|
||||
|
||||
public static List<AppAdapter.AppInfo> getShareApps(Context context, Intent intent,
|
||||
@Nullable Set<String> appsFilter, @Nullable Set<String> toExclude) {
|
||||
|
||||
if (context == null || intent == null) return null;
|
||||
|
||||
PackageManager manager = context.getPackageManager();
|
||||
List<ResolveInfo> apps = manager.queryIntentActivities(intent, 0);
|
||||
|
||||
if (apps != null && !apps.isEmpty()) {
|
||||
List<AppAdapter.AppInfo> appResources = new ArrayList<>(apps.size());
|
||||
boolean shouldCheckPackages = appsFilter != null && !appsFilter.isEmpty();
|
||||
|
||||
for (ResolveInfo resolveInfo : apps) {
|
||||
String packageName = resolveInfo.activityInfo.packageName;
|
||||
|
||||
if (shouldCheckPackages && !appsFilter.contains(packageName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String title = resolveInfo.loadLabel(manager).toString();
|
||||
String name = resolveInfo.activityInfo.name;
|
||||
Drawable drawable = resolveInfo.loadIcon(manager);
|
||||
appResources.add(new AppAdapter.AppInfo(title, packageName, name, drawable));
|
||||
}
|
||||
|
||||
if (toExclude != null && !toExclude.isEmpty()) {
|
||||
List<AppAdapter.AppInfo> toRemove = new ArrayList<>();
|
||||
|
||||
for (AppAdapter.AppInfo appInfo : appResources) {
|
||||
if (toExclude.contains(appInfo.packageName)) {
|
||||
toRemove.add(appInfo);
|
||||
}
|
||||
}
|
||||
|
||||
if (!toRemove.isEmpty()) appResources.removeAll(toRemove);
|
||||
}
|
||||
|
||||
return appResources;
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,49 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Nextcloud Talk application
|
||||
~
|
||||
~ @author Mario Danic
|
||||
~ Copyright (C) 2017-2019 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/>.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16">
|
||||
|
||||
<path
|
||||
android:fillColor="#0082c9"
|
||||
android:pathData="M1.5,2 C1.25,2,1,2.25,1,2.5 L1,13.5 C1,13.76,1.24,14,1.5,14 L14.5,14
|
||||
C14.76,14,15,13.759,15,13.5 L15,4.5 C15,4.25,14.75,4,14.5,4 L8,4 L6,2 L1.5,2 Z
|
||||
M9.834,5.5 C10.268,5.4981,10.7,5.6545,11.02,5.9746
|
||||
C11.66,6.6153,11.66,7.7166,11.02,8.3574 L10.17,9.207
|
||||
C10.197,8.7574,10.151,8.4573,9.8633,8.0508 L10.287,7.625
|
||||
C10.562,7.3498,10.539,6.9967,10.289,6.709
|
||||
C10.019,6.4391,9.645,6.4388,9.373,6.7109 L7.7266,8.3574
|
||||
C7.4437,8.6404,7.431,8.9797,7.7246,9.2734 L6.9941,10.006
|
||||
C6.7069,9.7186,6.5083,9.3329,6.4824,8.8984
|
||||
C6.4568,8.464,6.6281,7.9913,6.9941,7.625 L8.6406,5.9766
|
||||
C8.9651,5.6619,9.4004,5.5019,9.834,5.5 Z M9.0078,7.9902
|
||||
C9.296,8.2773,9.4947,8.6645,9.5195,9.0996
|
||||
C9.5449,9.5348,9.3746,10.006,9.0078,10.373 L7.3594,12.02
|
||||
C6.7198,12.659,5.6199,12.659,4.9805,12.02
|
||||
C4.3409,11.38,4.339,10.282,4.9805,9.6406 L5.8418,8.7773
|
||||
C5.8155,9.2266,5.8645,9.5278,6.1523,9.9336 L5.7129,10.373
|
||||
C5.4541,10.632,5.3887,10.963,5.7129,11.287
|
||||
C5.9567,11.531,6.2686,11.594,6.6289,11.287 L8.2754,9.6406
|
||||
C8.5401,9.3758,8.562,9.0075,8.2773,8.7227 L9.0078,7.9902 Z" />
|
||||
</vector>
|
@ -1,34 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Nextcloud Talk application
|
||||
~
|
||||
~ @author Mario Danic
|
||||
~ Copyright (C) 2017-2019 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/>.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16">
|
||||
|
||||
<path
|
||||
android:fillColor="#0082c9"
|
||||
android:pathData="M1.5,2 C1.25,2,1,2.25,1,2.5 L1,13.5 C1,13.76,1.24,14,1.5,14 L14.5,14
|
||||
C14.76,14,15,13.759,15,13.5 L15,4.5 C15,4.25,14.75,4,14.5,4 L8,4 L6,2 L1.5,2 Z
|
||||
M8,5.25 L9.1,7.9004 L12,8.125 L9.75,10 L10.5,12.75 L8,11.199 L5.5,12.75 L6.25,10
|
||||
L4,8.125 L6.9,7.9004 L8,5.25 Z" />
|
||||
</vector>
|
@ -52,7 +52,9 @@
|
||||
android:layout_marginEnd="@dimen/standard_half_margin"
|
||||
android:layout_toStartOf="@id/smileyButton"
|
||||
app:errorTextAppearance="@style/ErrorAppearance"
|
||||
app:passwordToggleTint="@color/grey_600">
|
||||
app:passwordToggleTint="@color/grey_600"
|
||||
app:boxStrokeColor="@color/colorPrimary"
|
||||
app:hintTextColor="@color/colorPrimary">
|
||||
|
||||
<com.nextcloud.talk.utils.EmojiTextInputEditText
|
||||
android:id="@+id/text_edit"
|
||||
|
@ -19,9 +19,9 @@
|
||||
-->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/controller_operations_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/bg_default">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/result_image_view"
|
||||
|
@ -1,8 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Nextcloud Talk application
|
||||
~
|
||||
~ @author Mario Danic
|
||||
~ Copyright (C) 2017 Mario Danic
|
||||
~ @author Marcel Hibbe
|
||||
~ @author Andy Scherzinger
|
||||
~ Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
~ Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||
~
|
||||
~ 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
|
||||
@ -17,17 +20,13 @@
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/bg_default">
|
||||
android:background="@color/bg_bottom_sheet"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/standard_padding"
|
||||
android:paddingEnd="@dimen/standard_padding"
|
||||
android:paddingBottom="@dimen/standard_half_padding">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
376
app/src/main/res/layout/dialog_conversation_operations.xml
Normal file
376
app/src/main/res/layout/dialog_conversation_operations.xml
Normal file
@ -0,0 +1,376 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Nextcloud Talk application
|
||||
~
|
||||
~ @author Marcel Hibbe
|
||||
~ @author Andy Scherzinger
|
||||
~ Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
~ Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||
~
|
||||
~ 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/>.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/bg_bottom_sheet"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/standard_padding"
|
||||
android:paddingEnd="@dimen/standard_padding"
|
||||
android:paddingBottom="@dimen/standard_half_padding">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/operation_items_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/conversation_operation_header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/bottom_sheet_item_height"
|
||||
android:gravity="start|center_vertical"
|
||||
android:textColor="@color/medium_emphasis_text"
|
||||
android:textSize="@dimen/bottom_sheet_text_size"
|
||||
tools:text="conversation name" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conversation_operation_remove_favorite"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_star_border_black_24dp"
|
||||
app:tint="@color/grey_600" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:paddingStart="40dp"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/nc_remove_from_favorites"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="@color/high_emphasis_text"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conversation_operation_add_favorite"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_star_black_24dp"
|
||||
app:tint="@color/grey_600" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:paddingStart="40dp"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/nc_add_to_favorites"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="@color/high_emphasis_text"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conversation_operation_mark_as_read"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_eye"
|
||||
app:tint="@color/grey_600" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:paddingStart="40dp"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/nc_mark_as_read"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="@color/high_emphasis_text"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conversation_operation_rename"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_pencil_grey600_24dp"
|
||||
app:tint="@color/grey_600" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:paddingStart="40dp"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/nc_rename"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="@color/high_emphasis_text"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conversation_operation_make_public"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_link_grey600_24px"
|
||||
app:tint="@color/grey_600" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:paddingStart="40dp"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/nc_make_call_public"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="@color/high_emphasis_text"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conversation_operation_change_password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_lock_grey600_24px"
|
||||
app:tint="@color/grey_600" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:paddingStart="40dp"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/nc_change_password"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="@color/high_emphasis_text"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conversation_operation_clear_password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_lock_open_grey600_24dp"
|
||||
app:tint="@color/grey_600" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:paddingStart="40dp"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/nc_clear_password"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="@color/high_emphasis_text"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conversation_operation_set_password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_lock_plus_grey600_24dp"
|
||||
app:tint="@color/grey_600" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:paddingStart="40dp"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/nc_set_password"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="@color/high_emphasis_text"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conversation_operation_delete"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_delete_grey600_24dp"
|
||||
app:tint="@color/grey_600" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:paddingStart="40dp"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/nc_delete_call"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="@color/high_emphasis_text"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conversation_operation_share_link"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_link_grey600_24px"
|
||||
app:tint="@color/grey_600" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:paddingStart="40dp"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/nc_share_link"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="@color/high_emphasis_text"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conversation_operation_make_private"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_group_grey600_24px"
|
||||
app:tint="@color/grey_600" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:paddingStart="40dp"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/nc_make_call_private"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="@color/high_emphasis_text"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/conversation_operation_leave"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_exit_to_app_black_24dp"
|
||||
app:tint="@color/grey_600" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:paddingStart="40dp"
|
||||
android:paddingEnd="@dimen/zero"
|
||||
android:text="@string/nc_leave"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="@color/high_emphasis_text"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@ -24,6 +24,7 @@
|
||||
|
||||
<dimen name="item_height">72dp</dimen>
|
||||
<dimen name="bottom_sheet_item_height">56dp</dimen>
|
||||
<dimen name="bottom_sheet_text_size">16sp</dimen>
|
||||
<dimen name="small_item_height">48dp</dimen>
|
||||
|
||||
<dimen name="min_size_clickable_area">48dp</dimen>
|
||||
|
@ -165,8 +165,6 @@
|
||||
<string name="nc_profile_personal_info_title">Personal Info</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<string name="nc_start_conversation">Start a conversation</string>
|
||||
<string name="nc_configure_room">Configure conversation</string>
|
||||
<string name="nc_leave">Leave conversation</string>
|
||||
<string name="nc_clear_history">Delete all messages</string>
|
||||
<string name="nc_clear_history_warning">Do you really want to delete all messages in this conversation?</string>
|
||||
@ -176,7 +174,6 @@
|
||||
<string name="nc_change_password">Change password</string>
|
||||
<string name="nc_clear_password">Clear password</string>
|
||||
<string name="nc_share_link">Share link</string>
|
||||
<string name="nc_share_link_via">Share link via</string>
|
||||
<string name="nc_make_call_public">Make conversation public</string>
|
||||
<string name="nc_make_call_private">Make conversation private</string>
|
||||
<string name="nc_delete_call">Delete conversation</string>
|
||||
|
@ -72,7 +72,7 @@
|
||||
<item name="android:textSize">12sp</item>
|
||||
</style>
|
||||
|
||||
<style name="ListItem" parent="BottomSheet.ListItem.TextAppearance">
|
||||
<style name="ListItem">
|
||||
<item name="android:textColor">@color/high_emphasis_text</item>
|
||||
<item name="android:textSize">16sp</item>
|
||||
</style>
|
||||
@ -235,4 +235,9 @@
|
||||
<item name="android:colorControlNormal">#ffffff</item>
|
||||
</style>
|
||||
|
||||
<style name="BottomSheetDialogThemeNoFloating" parent="Theme.Design.Light.BottomSheetDialog">
|
||||
<item name="android:windowIsFloating">false</item>
|
||||
<item name="android:windowSoftInputMode">adjustResize</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@ -1 +1 @@
|
||||
552
|
||||
542
|
@ -1,2 +1,2 @@
|
||||
DO NOT TOUCH; GENERATED BY DRONE
|
||||
<span class="mdl-layout-title">Lint Report: 1 error and 221 warnings</span>
|
||||
<span class="mdl-layout-title">Lint Report: 1 error and 218 warnings</span>
|
||||
|
Loading…
Reference in New Issue
Block a user