Merge pull request #484 from nextcloud/conversation-info-improvement

Conversation info improvement
This commit is contained in:
Mario Đanić 2019-03-04 09:06:08 +01:00 committed by GitHub
commit 119e684f8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 715 additions and 27 deletions

View File

@ -17,7 +17,7 @@ android {
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
versionCode 85
versionCode 155
versionName "3.2.6"
flavorDimensions "default"

View File

@ -114,7 +114,7 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
holder.serverUrl.setText(userEntity.getBaseUrl());
if (userEntity.getBaseUrl().startsWith("http://") || userEntity.getBaseUrl().startsWith("https://")) {
if (userEntity != null && userEntity.getBaseUrl() != null && userEntity.getBaseUrl().startsWith("http://") || userEntity.getBaseUrl().startsWith("https://")) {
holder.avatarImageView.setVisibility(View.VISIBLE);
GlideUrl glideUrl = new GlideUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
participant.getUserId(), R.dimen.avatar_size), new LazyHeaders.Builder()

View File

@ -41,7 +41,7 @@ import com.nextcloud.talk.dagger.modules.RestModule;
import com.nextcloud.talk.jobs.AccountRemovalWorker;
import com.nextcloud.talk.jobs.CapabilitiesWorker;
import com.nextcloud.talk.jobs.PushRegistrationWorker;
import com.nextcloud.talk.jobs.SignalingSettingsJob;
import com.nextcloud.talk.jobs.SignalingSettingsWorker;
import com.nextcloud.talk.utils.ClosedInterfaceImpl;
import com.nextcloud.talk.utils.DeviceUtils;
import com.nextcloud.talk.utils.DisplayUtils;
@ -142,7 +142,7 @@ public class NextcloudTalkApplication extends MultiDexApplication implements Lif
PeriodicWorkRequest periodicCapabilitiesUpdateWork = new PeriodicWorkRequest.Builder(CapabilitiesWorker.class,
1, TimeUnit.DAYS).build();
OneTimeWorkRequest capabilitiesUpdateWork = new OneTimeWorkRequest.Builder(CapabilitiesWorker.class).build();
OneTimeWorkRequest signalingSettingsWork = new OneTimeWorkRequest.Builder(SignalingSettingsJob.class).build();
OneTimeWorkRequest signalingSettingsWork = new OneTimeWorkRequest.Builder(SignalingSettingsWorker.class).build();
//WorkManager.initialize(getApplicationContext(), new Configuration.Builder().build());
WorkManager.getInstance().enqueue(pushRegistrationWork);

View File

@ -43,7 +43,7 @@ import com.nextcloud.talk.controllers.base.BaseController;
import com.nextcloud.talk.events.EventStatus;
import com.nextcloud.talk.jobs.CapabilitiesWorker;
import com.nextcloud.talk.jobs.PushRegistrationWorker;
import com.nextcloud.talk.jobs.SignalingSettingsJob;
import com.nextcloud.talk.jobs.SignalingSettingsWorker;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.generic.Status;
import com.nextcloud.talk.models.json.rooms.RoomsOverall;
@ -395,7 +395,7 @@ public class AccountVerificationController extends BaseController {
.putLong(BundleKeys.KEY_INTERNAL_USER_ID, internalAccountId)
.build();
OneTimeWorkRequest signalingSettings = new OneTimeWorkRequest.Builder(SignalingSettingsJob.class)
OneTimeWorkRequest signalingSettings = new OneTimeWorkRequest.Builder(SignalingSettingsWorker.class)
.setInputData(userData)
.build();
WorkManager.getInstance().enqueue(signalingSettings);

View File

@ -74,6 +74,7 @@ import com.nextcloud.talk.utils.animations.PulseAnimation;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
import com.nextcloud.talk.utils.glide.GlideApp;
import com.nextcloud.talk.utils.power.PowerManagerUtils;
import com.nextcloud.talk.utils.preferences.AppPreferences;
import com.nextcloud.talk.utils.singletons.ApplicationWideCurrentRoomHolder;
import com.nextcloud.talk.webrtc.*;
@ -92,7 +93,6 @@ import org.apache.commons.lang3.StringEscapeUtils;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.parceler.Parcels;
import org.webrtc.*;
import pub.devrel.easypermissions.AfterPermissionGranted;
@ -210,6 +210,8 @@ public class CallController extends BaseController {
private boolean hasExternalSignalingServer;
private String conversationPassword;
private PowerManagerUtils powerManagerUtils;
public CallController(Bundle args) {
super(args);
NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
@ -229,6 +231,7 @@ public class CallController extends BaseController {
}
isFromNotification = TextUtils.isEmpty(roomToken);
powerManagerUtils = new PowerManagerUtils();
}
@Override
@ -493,7 +496,18 @@ public class CallController extends BaseController {
final MagicAudioManager.AudioDevice device, final Set<MagicAudioManager.AudioDevice> availableDevices) {
Log.d(TAG, "onAudioManagerDevicesChanged: " + availableDevices + ", "
+ "selected: " + device);
final boolean shouldDisableProximityLock = (device.equals(MagicAudioManager.AudioDevice.WIRED_HEADSET)
|| device.equals(MagicAudioManager.AudioDevice.SPEAKER_PHONE)
|| device.equals(MagicAudioManager.AudioDevice.BLUETOOTH));
if (shouldDisableProximityLock) {
powerManagerUtils.updatePhoneState(PowerManagerUtils.PhoneState.WITHOUT_PROXIMITY_SENSOR_LOCK);
} else {
powerManagerUtils.updatePhoneState(PowerManagerUtils.PhoneState.WITH_PROXIMITY_SENSOR_LOCK);
}
}
private void cameraInitialization() {
videoCapturer = createCameraCapturer(cameraEnumerator);
@ -718,7 +732,6 @@ public class CallController extends BaseController {
if (localMediaStream != null && localMediaStream.videoTracks.size() > 0) {
localMediaStream.videoTracks.get(0).setEnabled(enable);
}
if (enable) {
pipVideoView.setVisibility(View.VISIBLE);
} else {
@ -1593,6 +1606,8 @@ public class CallController extends BaseController {
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(ConfigurationChangeEvent configurationChangeEvent) {
powerManagerUtils.setOrientation(Objects.requireNonNull(getResources()).getConfiguration().orientation);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
remoteRenderersLayout.setOrientation(LinearLayout.HORIZONTAL);
} else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {

View File

@ -389,7 +389,7 @@ public class ChatController extends BaseController implements MessagesListAdapte
messageInputView.getButton().setContentDescription(getResources()
.getString(R.string.nc_description_send_message_button));
if (!conversationUser.getUserId().equals("?") && conversationUser.hasSpreedCapabilityWithName("mention" + "-flag") && getActivity() != null) {
if (!conversationUser.getUserId().equals("?") && conversationUser.hasSpreedCapabilityWithName("mention-flag") && getActivity() != null) {
getActivity().findViewById(R.id.toolbar).setOnClickListener(v -> showConversationInfoScreen());
}

View File

@ -30,8 +30,14 @@ import android.view.ViewGroup;
import android.widget.ProgressBar;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.work.Data;
import androidx.work.OneTimeWorkRequest;
import androidx.work.WorkManager;
import autodagger.AutoInjector;
import butterknife.BindView;
import butterknife.OnClick;
import com.bluelinelabs.conductor.RouterTransaction;
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;
@ -40,6 +46,8 @@ 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.jobs.DeleteConversationWorker;
import com.nextcloud.talk.jobs.LeaveConversationWorker;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter;
import com.nextcloud.talk.models.json.participants.Participant;
@ -54,6 +62,7 @@ import com.vanniktech.emoji.EmojiTextView;
import com.yarolegovich.mp.MaterialChoicePreference;
import com.yarolegovich.mp.MaterialPreferenceCategory;
import com.yarolegovich.mp.MaterialPreferenceScreen;
import com.yarolegovich.mp.MaterialStandardPreference;
import eu.davidea.flexibleadapter.FlexibleAdapter;
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager;
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
@ -61,7 +70,6 @@ import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import org.parceler.Parcels;
import javax.inject.Inject;
import java.util.ArrayList;
@ -87,6 +95,11 @@ public class ConversationInfoController extends BaseController {
MaterialPreferenceCategory participantsListCategory;
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@BindView(R.id.deleteConversationAction)
MaterialStandardPreference deleteConversationAction;
@BindView(R.id.ownOptions)
MaterialPreferenceCategory ownOptionsCategory;
@Inject
NcApi ncApi;
private String baseUrl;
@ -228,6 +241,46 @@ public class ConversationInfoController extends BaseController {
}
@OnClick(R.id.leaveConversationAction)
void leaveConversation() {
Data data;
if ((data = getWorkerData()) != null) {
OneTimeWorkRequest leaveConversationWorker =
new OneTimeWorkRequest.Builder(LeaveConversationWorker.class).setInputData(data).build();
WorkManager.getInstance().enqueue(leaveConversationWorker);
popTwoLastControllers();
}
}
@OnClick(R.id.deleteConversationAction)
void deleteConversation() {
Data data;
if ((data = getWorkerData()) != null) {
OneTimeWorkRequest deleteConversationWorker =
new OneTimeWorkRequest.Builder(DeleteConversationWorker.class).setInputData(data).build();
WorkManager.getInstance().enqueue(deleteConversationWorker);
popTwoLastControllers();
}
}
private Data getWorkerData() {
if (!TextUtils.isEmpty(conversationToken) && conversationUser != null) {
Data.Builder data = new Data.Builder();
data.putString(BundleKeys.KEY_ROOM_TOKEN, conversationToken);
data.putLong(BundleKeys.KEY_INTERNAL_USER_ID, conversationUser.getId());
return data.build();
}
return null;
}
private void popTwoLastControllers() {
List<RouterTransaction> backstack = getRouter().getBackstack();
backstack.remove(backstack.size() - 2);
getRouter().setBackstack(backstack, new HorizontalChangeHandler());
getRouter().popCurrentController();
}
private void fetchRoomInfo() {
ncApi.getRoom(credentials, ApiUtils.getRoom(conversationUser.getBaseUrl(), conversationToken))
.subscribeOn(Schedulers.newThread())
@ -241,6 +294,14 @@ public class ConversationInfoController extends BaseController {
@Override
public void onNext(RoomOverall roomOverall) {
conversation = roomOverall.getOcs().getData();
ownOptionsCategory.setVisibility(View.VISIBLE);
if (!conversation.isDeletable()) {
deleteConversationAction.setVisibility(View.GONE);
} else {
deleteConversationAction.setVisibility(View.VISIBLE);
}
getListOfParticipants();
if (progressBar != null) {

View File

@ -66,6 +66,7 @@ import com.nextcloud.talk.controllers.base.BaseController;
import com.nextcloud.talk.controllers.bottomsheet.CallMenuController;
import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController;
import com.nextcloud.talk.events.BottomSheetLockEvent;
import com.nextcloud.talk.events.EventStatus;
import com.nextcloud.talk.events.MoreMenuClickEvent;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.participants.Participant;
@ -153,6 +154,8 @@ public class ConversationsListController extends BaseController implements Searc
private boolean adapterWasNull = true;
private boolean isRefreshing;
private String lastClickedConversationToken;
private int scrollTo = 0;
@ -292,6 +295,8 @@ public class ConversationsListController extends BaseController implements Searc
private void fetchData(boolean fromBottomSheet) {
dispose(null);
isRefreshing = true;
callItems = new ArrayList<>();
roomsQueryDisposable = ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(currentUser.getBaseUrl()))
@ -412,6 +417,7 @@ public class ConversationsListController extends BaseController implements Searc
}, 2500);
}
isRefreshing = false;
});
}
@ -668,4 +674,19 @@ public class ConversationsListController extends BaseController implements Searc
}
}
}
@Subscribe(sticky = true, threadMode = ThreadMode.BACKGROUND)
public void onMessageEvent(EventStatus eventStatus) {
if (currentUser != null && eventStatus.getUserId() == currentUser.getId()){
switch (eventStatus.getEventType()) {
case CONVERSATION_UPDATE:
if (eventStatus.isAllGood() && !isRefreshing) {
fetchData(false);
}
break;
default:
break;
}
}
}
}

View File

@ -43,6 +43,7 @@ import com.nextcloud.talk.controllers.base.BaseController;
import com.nextcloud.talk.events.BottomSheetLockEvent;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.rooms.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;
@ -130,12 +131,11 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
UserEntity currentUser;
if (conversation.isFavorite()) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_remove_from_favorites), 97, getResources()
.getDrawable(R.drawable.ic_star_border_grey600_24dp)));
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 ((currentUser = userUtils.getCurrentUser()) != null &&
currentUser.hasSpreedCapabilityWithName("favorites")) {
menuItems.add(new MenuItem(getResources().getString(R.string.nc_add_to_favorites), 98, getResources()
.getDrawable(R.drawable.ic_star_grey600_24dp)));
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.isNameEditable()) {

View File

@ -185,8 +185,7 @@ public class OperationsMenuController extends BaseController {
switch (operationCode) {
case 1:
ncApi.removeSelfFromRoom(credentials, ApiUtils.getUrlForRemoveSelfFromRoom(currentUser.getBaseUrl
(), conversation.getToken()))
ncApi.removeSelfFromRoom(credentials, ApiUtils.getUrlForRemoveSelfFromRoom(currentUser.getBaseUrl(), conversation.getToken()))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
@ -234,7 +233,8 @@ public class OperationsMenuController extends BaseController {
.subscribe(operationsObserver);
break;
case 9:
ncApi.deleteRoom(credentials, ApiUtils.getUrlForSettingMyselfAsActiveParticipant(currentUser.getBaseUrl(), conversation.getToken()))
ncApi.deleteRoom(credentials, ApiUtils.getRoom(currentUser.getBaseUrl(),
conversation.getToken()))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)

View File

@ -35,7 +35,7 @@ public class EventStatus {
}
public enum EventType {
PUSH_REGISTRATION, CAPABILITIES_FETCH, SIGNALING_SETTINGS
PUSH_REGISTRATION, CAPABILITIES_FETCH, SIGNALING_SETTINGS, CONVERSATION_UPDATE
}
}

View File

@ -0,0 +1,115 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.jobs;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.work.Data;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import autodagger.AutoInjector;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.events.EventStatus;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.generic.GenericOverall;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.JavaNetCookieJar;
import okhttp3.OkHttpClient;
import org.greenrobot.eventbus.EventBus;
import retrofit2.Retrofit;
import javax.inject.Inject;
import java.net.CookieManager;
@AutoInjector(NextcloudTalkApplication.class)
public class DeleteConversationWorker extends Worker {
@Inject
Retrofit retrofit;
@Inject
OkHttpClient okHttpClient;
@Inject
UserUtils userUtils;
@Inject
EventBus eventBus;
NcApi ncApi;
public DeleteConversationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
}
@NonNull
@Override
public Result doWork() {
Data data = getInputData();
long operationUserId = data.getLong(BundleKeys.KEY_INTERNAL_USER_ID, -1);
String conversationToken = data.getString(BundleKeys.KEY_ROOM_TOKEN);
UserEntity operationUser = userUtils.getUserWithId(operationUserId);
if (operationUser != null) {
String credentials = ApiUtils.getCredentials(operationUser.getUsername(), operationUser.getToken());
ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new
JavaNetCookieJar(new CookieManager())).build()).build().create(NcApi.class);
EventStatus eventStatus = new EventStatus(operationUser.getId(),
EventStatus.EventType.CONVERSATION_UPDATE, true);
ncApi.deleteRoom(credentials, ApiUtils.getRoom(operationUser.getBaseUrl(), conversationToken))
.subscribeOn(Schedulers.newThread())
.blockingSubscribe(new Observer<GenericOverall>() {
Disposable disposable;
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(GenericOverall genericOverall) {
eventBus.postSticky(eventStatus);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
disposable.dispose();
}
});
}
return Result.success();
}
}

View File

@ -0,0 +1,115 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.jobs;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.work.Data;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import autodagger.AutoInjector;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.events.EventStatus;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.generic.GenericOverall;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.bundle.BundleKeys;
import com.nextcloud.talk.utils.database.user.UserUtils;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.JavaNetCookieJar;
import okhttp3.OkHttpClient;
import org.greenrobot.eventbus.EventBus;
import retrofit2.Retrofit;
import javax.inject.Inject;
import java.net.CookieManager;
@AutoInjector(NextcloudTalkApplication.class)
public class LeaveConversationWorker extends Worker {
@Inject
Retrofit retrofit;
@Inject
OkHttpClient okHttpClient;
@Inject
UserUtils userUtils;
@Inject
EventBus eventBus;
NcApi ncApi;
public LeaveConversationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
}
@NonNull
@Override
public Result doWork() {
Data data = getInputData();
long operationUserId = data.getLong(BundleKeys.KEY_INTERNAL_USER_ID, -1);
String conversationToken = data.getString(BundleKeys.KEY_ROOM_TOKEN);
UserEntity operationUser = userUtils.getUserWithId(operationUserId);
if (operationUser != null) {
String credentials = ApiUtils.getCredentials(operationUser.getUsername(), operationUser.getToken());
ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new
JavaNetCookieJar(new CookieManager())).build()).build().create(NcApi.class);
EventStatus eventStatus = new EventStatus(operationUser.getId(),
EventStatus.EventType.CONVERSATION_UPDATE, true);
ncApi.removeSelfFromRoom(credentials, ApiUtils.getUrlForRemoveSelfFromRoom(operationUser.getBaseUrl(), conversationToken))
.subscribeOn(Schedulers.newThread())
.blockingSubscribe(new Observer<GenericOverall>() {
Disposable disposable;
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(GenericOverall genericOverall) {
eventBus.postSticky(eventStatus);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
disposable.dispose();
}
});
}
return Result.success();
}
}

View File

@ -46,7 +46,7 @@ import java.util.ArrayList;
import java.util.List;
@AutoInjector(NextcloudTalkApplication.class)
public class SignalingSettingsJob extends Worker {
public class SignalingSettingsWorker extends Worker {
private static final String TAG = "SignalingSettingsJob";
@Inject
@ -58,7 +58,7 @@ public class SignalingSettingsJob extends Worker {
@Inject
EventBus eventBus;
public SignalingSettingsJob(@NonNull Context context, @NonNull WorkerParameters workerParams) {
public SignalingSettingsWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}

View File

@ -20,14 +20,15 @@
package com.nextcloud.talk.utils;
import android.net.Uri;
import android.text.TextUtils;
import androidx.annotation.DimenRes;
import com.nextcloud.talk.BuildConfig;
import com.nextcloud.talk.R;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.models.RetrofitBucket;
import okhttp3.Credentials;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;

View File

@ -107,5 +107,4 @@ public class NotificationUtils {
}
}
}
}

View File

@ -0,0 +1,194 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* This class is in part based on the code from the great people that wrote Signal
* https://github.com/signalapp/Signal-Android/raw/f9adb4e4554a44fd65b77320e34bf4bccf7924ce/src/org/thoughtcrime/securesms/webrtc/locks/LockManager.java
*/
package com.nextcloud.talk.utils.power;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.PowerManager;
import android.provider.Settings;
import autodagger.AutoInjector;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import javax.inject.Inject;
@AutoInjector(NextcloudTalkApplication.class)
public class PowerManagerUtils {
private static final String TAG = "PowerManagerUtils";
@Inject
Context context;
private final PowerManager.WakeLock fullLock;
private final PowerManager.WakeLock partialLock;
private final WifiManager.WifiLock wifiLock;
private ProximityLock proximityLock;
private final boolean wifiLockEnforced;
private boolean proximityDisabled = false;
private int orientation;
public enum PhoneState {
IDLE,
PROCESSING, //used when the phone is active but before the user should be alerted.
INTERACTIVE,
WITHOUT_PROXIMITY_SENSOR_LOCK,
WITH_PROXIMITY_SENSOR_LOCK
}
public enum WakeLockState {
FULL,
PARTIAL,
SLEEP,
PROXIMITY
}
public void setOrientation(int newOrientation) {
orientation = newOrientation;
updateInCallWakeLockState();
}
public PowerManagerUtils() {
NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
fullLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "nctalk:fullwakelock");
partialLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "nctalk:partialwakelock");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
proximityLock = new ProximityLock(pm);
}
// we suppress a possible leak because this is indeed application context
@SuppressLint("WifiManagerPotentialLeak") WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "nctalk:wifiwakelock");
fullLock.setReferenceCounted(false);
partialLock.setReferenceCounted(false);
wifiLock.setReferenceCounted(false);
wifiLockEnforced = isWifiPowerActiveModeEnabled(context);
orientation = context.getResources().getConfiguration().orientation;
}
public void updatePhoneState(PhoneState state) {
switch(state) {
case IDLE:
setWakeLockState(WakeLockState.SLEEP);
break;
case PROCESSING:
setWakeLockState(WakeLockState.PARTIAL);
break;
case INTERACTIVE:
setWakeLockState(WakeLockState.FULL);
break;
case WITH_PROXIMITY_SENSOR_LOCK:
proximityDisabled = false;
updateInCallWakeLockState();
break;
case WITHOUT_PROXIMITY_SENSOR_LOCK:
proximityDisabled = true;
updateInCallWakeLockState();
break;
}
}
private void updateInCallWakeLockState() {
if (orientation != Configuration.ORIENTATION_LANDSCAPE && wifiLockEnforced && !proximityDisabled) {
setWakeLockState(WakeLockState.PROXIMITY);
} else {
setWakeLockState(WakeLockState.FULL);
}
}
private boolean isWifiPowerActiveModeEnabled(Context context) {
int wifi_pwr_active_mode = Settings.Secure.getInt(context.getContentResolver(), "wifi_pwr_active_mode", -1);
return (wifi_pwr_active_mode != 0);
}
@SuppressLint("WakelockTimeout")
private synchronized void setWakeLockState(WakeLockState newState) {
switch(newState) {
case FULL:
if (!fullLock.isHeld()) {
fullLock.acquire();
}
if (!partialLock.isHeld()) {
partialLock.acquire();
}
if (!wifiLock.isHeld()) {
wifiLock.acquire();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
proximityLock.release();
}
break;
case PARTIAL:
if (!partialLock.isHeld()) {
partialLock.acquire();
}
if (!wifiLock.isHeld()) {
wifiLock.acquire();
}
fullLock.release();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
proximityLock.release();
}
break;
case SLEEP:
fullLock.release();
partialLock.release();
wifiLock.release();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
proximityLock.release();
}
break;
case PROXIMITY:
if (!partialLock.isHeld()) {
partialLock.acquire();
}
if (!wifiLock.isHeld()) {
wifiLock.acquire();
}
fullLock.release(
);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
proximityLock.acquire();
}
break;
default:
// something went very very wrong
}
}
}

View File

@ -0,0 +1,65 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.utils.power;
import android.annotation.SuppressLint;
import android.os.Build;
import android.os.PowerManager;
import androidx.annotation.RequiresApi;
import java.util.Optional;
class ProximityLock {
private final Optional<PowerManager.WakeLock> proximityLock;
@RequiresApi(api = Build.VERSION_CODES.N)
ProximityLock(PowerManager pm) {
proximityLock = getProximityLock(pm);
}
@RequiresApi(api = Build.VERSION_CODES.N)
private Optional<PowerManager.WakeLock> getProximityLock(PowerManager powerManager) {
if (powerManager.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
return Optional.ofNullable(powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "nctalk:proximitylock"));
} else {
return Optional.empty();
}
}
@SuppressLint("WakelockTimeout")
@RequiresApi(api = Build.VERSION_CODES.N)
void acquire() {
if (!proximityLock.isPresent() || proximityLock.get().isHeld()) {
return;
}
proximityLock.get().acquire();
}
@RequiresApi(api = Build.VERSION_CODES.N)
void release() {
if (!proximityLock.isPresent() || !proximityLock.get().isHeld()) {
return;
}
proximityLock.get().release(PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY);
}
}

View File

@ -41,6 +41,7 @@ import android.media.AudioManager;
import android.os.Build;
import android.util.Log;
import com.nextcloud.talk.events.PeerConnectionEvent;
import com.nextcloud.talk.utils.power.PowerManagerUtils;
import org.greenrobot.eventbus.EventBus;
import org.webrtc.ThreadUtils;
@ -94,6 +95,8 @@ public class MagicAudioManager {
// Callback method for changes in audio focus.
private AudioManager.OnAudioFocusChangeListener audioFocusChangeListener;
private PowerManagerUtils powerManagerUtils;
private MagicAudioManager(Context context, boolean useProximitySensor) {
Log.d(TAG, "ctor");
ThreadUtils.checkIsOnMainThread();
@ -103,6 +106,9 @@ public class MagicAudioManager {
wiredHeadsetReceiver = new WiredHeadsetReceiver();
amState = AudioManagerState.UNINITIALIZED;
powerManagerUtils = new PowerManagerUtils();
powerManagerUtils.updatePhoneState(PowerManagerUtils.PhoneState.WITH_PROXIMITY_SENSOR_LOCK);
if (useProximitySensor) {
useSpeakerphone = SPEAKERPHONE_AUTO;
} else {
@ -313,6 +319,8 @@ public class MagicAudioManager {
proximitySensor = null;
}
powerManagerUtils.updatePhoneState(PowerManagerUtils.PhoneState.IDLE);
audioManagerEvents = null;
Log.d(TAG, "AudioManager stopped");
}

View File

@ -21,5 +21,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#757575" android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
<path android:fillColor="#FF000000" android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</vector>

View File

@ -21,5 +21,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#757575" android:pathData="M22,9.24l-7.19,-0.62L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21 12,17.27 18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27 1,-4.28 -3.32,-2.88 4.38,-0.38L12,6.1l1.71,4.04 4.38,0.38 -3.32,2.88 1,4.28L12,15.4z"/>
<path android:fillColor="#FF000000" android:pathData="M10.09,15.59L11.5,17l5,-5 -5,-5 -1.41,1.41L12.67,11H3v2h9.67l-2.58,2.59zM19,3H5c-1.11,0 -2,0.9 -2,2v4h2V5h14v14H5v-4H3v4c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"/>
</vector>

View File

@ -0,0 +1,25 @@
<!--
~ Nextcloud Talk application
~
~ @author Mario Danic
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
</vector>

View File

@ -0,0 +1,25 @@
<!--
~ Nextcloud Talk application
~
~ @author Mario Danic
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M22,9.24l-7.19,-0.62L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21 12,17.27 18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27 1,-4.28 -3.32,-2.88 4.38,-0.38L12,6.1l1.71,4.04 4.38,0.38 -3.32,2.88 1,4.28L12,15.4z"/>
</vector>

View File

@ -26,5 +26,5 @@
<solid android:color="@color/white"/>
</shape>
</item>
<item android:drawable="@drawable/ic_star_grey600_24dp"/>
<item android:drawable="@drawable/ic_star_black_24dp" android:tint="@color/grey_600"/>
</layer-list>

View File

@ -76,11 +76,30 @@
</RelativeLayout>
</com.yarolegovich.mp.MaterialPreferenceCategory>
<com.yarolegovich.mp.MaterialPreferenceCategory
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/conversation_info_name"
android:id="@+id/otherRoomOptions"
android:visibility="gone">
<com.yarolegovich.mp.MaterialStandardPreference
android:layout_width="match_parent"
android:layout_height="wrap_content"
apc:mp_icon="@drawable/ic_star_black_24dp"
apc:mp_icon_tint="@color/grey_600"
apc:mp_title="@string/nc_add_to_favorites"
android:id="@+id/favoriteConversationAction">
</com.yarolegovich.mp.MaterialStandardPreference>
</com.yarolegovich.mp.MaterialPreferenceCategory>
<include
layout="@layout/notification_settings_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/conversation_info_name"
android:layout_below="@id/otherRoomOptions"
android:visibility="gone" />
<com.yarolegovich.mp.MaterialPreferenceCategory
@ -100,6 +119,31 @@
tools:listitem="@layout/rv_item_contact"></androidx.recyclerview.widget.RecyclerView>
</com.yarolegovich.mp.MaterialPreferenceCategory>
<com.yarolegovich.mp.MaterialPreferenceCategory
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/participants_list_category"
android:visibility="gone"
android:id="@+id/ownOptions">
<com.yarolegovich.mp.MaterialStandardPreference
android:layout_width="match_parent"
android:layout_height="wrap_content"
apc:mp_title="@string/nc_leave"
apc:mp_icon="@drawable/ic_exit_to_app_black_24dp"
apc:mp_icon_tint="@color/grey_600"
android:id="@+id/leaveConversationAction" />
<com.yarolegovich.mp.MaterialStandardPreference
android:layout_width="match_parent"
android:layout_height="wrap_content"
apc:mp_title="@string/nc_delete_call"
apc:mp_icon_tint="@color/grey_600"
apc:mp_icon="@drawable/ic_delete_black_24dp"
android:id="@+id/deleteConversationAction" />
</com.yarolegovich.mp.MaterialPreferenceCategory>
</RelativeLayout>
</ScrollView>
</RelativeLayout>