Browse Source

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

Conversation info improvement
Mario Đanić 6 năm trước cách đây
mục cha
commit
119e684f8d
25 tập tin đã thay đổi với 715 bổ sung27 xóa
  1. 1 1
      app/build.gradle
  2. 1 1
      app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java
  3. 2 2
      app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java
  4. 2 2
      app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.java
  5. 17 2
      app/src/main/java/com/nextcloud/talk/controllers/CallController.java
  6. 1 1
      app/src/main/java/com/nextcloud/talk/controllers/ChatController.java
  7. 62 1
      app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.java
  8. 22 1
      app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java
  9. 4 4
      app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/CallMenuController.java
  10. 3 3
      app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.java
  11. 1 1
      app/src/main/java/com/nextcloud/talk/events/EventStatus.java
  12. 115 0
      app/src/main/java/com/nextcloud/talk/jobs/DeleteConversationWorker.java
  13. 115 0
      app/src/main/java/com/nextcloud/talk/jobs/LeaveConversationWorker.java
  14. 2 2
      app/src/main/java/com/nextcloud/talk/jobs/SignalingSettingsWorker.java
  15. 2 1
      app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java
  16. 0 1
      app/src/main/java/com/nextcloud/talk/utils/NotificationUtils.java
  17. 194 0
      app/src/main/java/com/nextcloud/talk/utils/power/PowerManagerUtils.java
  18. 65 0
      app/src/main/java/com/nextcloud/talk/utils/power/ProximityLock.java
  19. 8 0
      app/src/main/java/com/nextcloud/talk/webrtc/MagicAudioManager.java
  20. 1 1
      app/src/main/res/drawable/ic_delete_black_24dp.xml
  21. 1 1
      app/src/main/res/drawable/ic_exit_to_app_black_24dp.xml
  22. 25 0
      app/src/main/res/drawable/ic_star_black_24dp.xml
  23. 25 0
      app/src/main/res/drawable/ic_star_border_black_24dp.xml
  24. 1 1
      app/src/main/res/drawable/shape_favorite_bubble.xml
  25. 45 1
      app/src/main/res/layout/controller_conversation_info.xml

+ 1 - 1
app/build.gradle

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

+ 1 - 1
app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java

@@ -114,7 +114,7 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
 
 
         holder.serverUrl.setText(userEntity.getBaseUrl());
         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);
             holder.avatarImageView.setVisibility(View.VISIBLE);
             GlideUrl glideUrl = new GlideUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
             GlideUrl glideUrl = new GlideUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
                     participant.getUserId(), R.dimen.avatar_size), new LazyHeaders.Builder()
                     participant.getUserId(), R.dimen.avatar_size), new LazyHeaders.Builder()

+ 2 - 2
app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java

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

+ 2 - 2
app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.java

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

+ 17 - 2
app/src/main/java/com/nextcloud/talk/controllers/CallController.java

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

+ 1 - 1
app/src/main/java/com/nextcloud/talk/controllers/ChatController.java

@@ -389,7 +389,7 @@ public class ChatController extends BaseController implements MessagesListAdapte
         messageInputView.getButton().setContentDescription(getResources()
         messageInputView.getButton().setContentDescription(getResources()
                 .getString(R.string.nc_description_send_message_button));
                 .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());
             getActivity().findViewById(R.id.toolbar).setOnClickListener(v -> showConversationInfoScreen());
         }
         }
 
 

+ 62 - 1
app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.java

@@ -30,8 +30,14 @@ import android.view.ViewGroup;
 import android.widget.ProgressBar;
 import android.widget.ProgressBar;
 import androidx.annotation.NonNull;
 import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.recyclerview.widget.RecyclerView;
+import androidx.work.Data;
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.WorkManager;
 import autodagger.AutoInjector;
 import autodagger.AutoInjector;
 import butterknife.BindView;
 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.backends.pipeline.Fresco;
 import com.facebook.drawee.interfaces.DraweeController;
 import com.facebook.drawee.interfaces.DraweeController;
 import com.facebook.drawee.view.SimpleDraweeView;
 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.api.NcApi;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.controllers.base.BaseController;
 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.database.UserEntity;
 import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter;
 import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter;
 import com.nextcloud.talk.models.json.participants.Participant;
 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.MaterialChoicePreference;
 import com.yarolegovich.mp.MaterialPreferenceCategory;
 import com.yarolegovich.mp.MaterialPreferenceCategory;
 import com.yarolegovich.mp.MaterialPreferenceScreen;
 import com.yarolegovich.mp.MaterialPreferenceScreen;
+import com.yarolegovich.mp.MaterialStandardPreference;
 import eu.davidea.flexibleadapter.FlexibleAdapter;
 import eu.davidea.flexibleadapter.FlexibleAdapter;
 import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager;
 import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager;
 import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
 import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
@@ -61,7 +70,6 @@ import io.reactivex.Observer;
 import io.reactivex.android.schedulers.AndroidSchedulers;
 import io.reactivex.android.schedulers.AndroidSchedulers;
 import io.reactivex.disposables.Disposable;
 import io.reactivex.disposables.Disposable;
 import io.reactivex.schedulers.Schedulers;
 import io.reactivex.schedulers.Schedulers;
-import org.parceler.Parcels;
 
 
 import javax.inject.Inject;
 import javax.inject.Inject;
 import java.util.ArrayList;
 import java.util.ArrayList;
@@ -87,6 +95,11 @@ public class ConversationInfoController extends BaseController {
     MaterialPreferenceCategory participantsListCategory;
     MaterialPreferenceCategory participantsListCategory;
     @BindView(R.id.recycler_view)
     @BindView(R.id.recycler_view)
     RecyclerView recyclerView;
     RecyclerView recyclerView;
+    @BindView(R.id.deleteConversationAction)
+    MaterialStandardPreference deleteConversationAction;
+    @BindView(R.id.ownOptions)
+    MaterialPreferenceCategory ownOptionsCategory;
+
     @Inject
     @Inject
     NcApi ncApi;
     NcApi ncApi;
     private String baseUrl;
     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() {
     private void fetchRoomInfo() {
         ncApi.getRoom(credentials, ApiUtils.getRoom(conversationUser.getBaseUrl(), conversationToken))
         ncApi.getRoom(credentials, ApiUtils.getRoom(conversationUser.getBaseUrl(), conversationToken))
                 .subscribeOn(Schedulers.newThread())
                 .subscribeOn(Schedulers.newThread())
@@ -241,6 +294,14 @@ public class ConversationInfoController extends BaseController {
                     @Override
                     @Override
                     public void onNext(RoomOverall roomOverall) {
                     public void onNext(RoomOverall roomOverall) {
                         conversation = roomOverall.getOcs().getData();
                         conversation = roomOverall.getOcs().getData();
+
+                        ownOptionsCategory.setVisibility(View.VISIBLE);
+                        if (!conversation.isDeletable()) {
+                            deleteConversationAction.setVisibility(View.GONE);
+                        } else {
+                            deleteConversationAction.setVisibility(View.VISIBLE);
+                        }
+
                         getListOfParticipants();
                         getListOfParticipants();
 
 
                         if (progressBar != null) {
                         if (progressBar != null) {

+ 22 - 1
app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java

@@ -66,6 +66,7 @@ import com.nextcloud.talk.controllers.base.BaseController;
 import com.nextcloud.talk.controllers.bottomsheet.CallMenuController;
 import com.nextcloud.talk.controllers.bottomsheet.CallMenuController;
 import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController;
 import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController;
 import com.nextcloud.talk.events.BottomSheetLockEvent;
 import com.nextcloud.talk.events.BottomSheetLockEvent;
+import com.nextcloud.talk.events.EventStatus;
 import com.nextcloud.talk.events.MoreMenuClickEvent;
 import com.nextcloud.talk.events.MoreMenuClickEvent;
 import com.nextcloud.talk.models.database.UserEntity;
 import com.nextcloud.talk.models.database.UserEntity;
 import com.nextcloud.talk.models.json.participants.Participant;
 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 adapterWasNull = true;
 
 
+    private boolean isRefreshing;
+
     private String lastClickedConversationToken;
     private String lastClickedConversationToken;
     private int scrollTo = 0;
     private int scrollTo = 0;
 
 
@@ -292,6 +295,8 @@ public class ConversationsListController extends BaseController implements Searc
     private void fetchData(boolean fromBottomSheet) {
     private void fetchData(boolean fromBottomSheet) {
         dispose(null);
         dispose(null);
 
 
+        isRefreshing = true;
+
         callItems = new ArrayList<>();
         callItems = new ArrayList<>();
 
 
         roomsQueryDisposable = ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(currentUser.getBaseUrl()))
         roomsQueryDisposable = ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(currentUser.getBaseUrl()))
@@ -412,6 +417,7 @@ public class ConversationsListController extends BaseController implements Searc
                         }, 2500);
                         }, 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;
+            }
+        }
+    }
+}

+ 4 - 4
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/CallMenuController.java

@@ -43,6 +43,7 @@ import com.nextcloud.talk.controllers.base.BaseController;
 import com.nextcloud.talk.events.BottomSheetLockEvent;
 import com.nextcloud.talk.events.BottomSheetLockEvent;
 import com.nextcloud.talk.models.database.UserEntity;
 import com.nextcloud.talk.models.database.UserEntity;
 import com.nextcloud.talk.models.json.rooms.Conversation;
 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.ShareUtils;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
 import com.nextcloud.talk.utils.database.user.UserUtils;
 import com.nextcloud.talk.utils.database.user.UserUtils;
@@ -130,12 +131,11 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
             UserEntity currentUser;
             UserEntity currentUser;
 
 
             if (conversation.isFavorite()) {
             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 &&
             } else if ((currentUser = userUtils.getCurrentUser()) != null &&
                     currentUser.hasSpreedCapabilityWithName("favorites")) {
                     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()) {
             if (conversation.isNameEditable()) {

+ 3 - 3
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.java

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

+ 1 - 1
app/src/main/java/com/nextcloud/talk/events/EventStatus.java

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

+ 115 - 0
app/src/main/java/com/nextcloud/talk/jobs/DeleteConversationWorker.java

@@ -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();
+    }
+}

+ 115 - 0
app/src/main/java/com/nextcloud/talk/jobs/LeaveConversationWorker.java

@@ -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();
+    }
+}

+ 2 - 2
app/src/main/java/com/nextcloud/talk/jobs/SignalingSettingsJob.java → app/src/main/java/com/nextcloud/talk/jobs/SignalingSettingsWorker.java

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

+ 2 - 1
app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java

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

+ 0 - 1
app/src/main/java/com/nextcloud/talk/utils/NotificationUtils.java

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

+ 194 - 0
app/src/main/java/com/nextcloud/talk/utils/power/PowerManagerUtils.java

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

+ 65 - 0
app/src/main/java/com/nextcloud/talk/utils/power/ProximityLock.java

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

+ 8 - 0
app/src/main/java/com/nextcloud/talk/webrtc/MagicAudioManager.java

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

+ 1 - 1
app/src/main/res/drawable/ic_star_grey600_24dp.xml → app/src/main/res/drawable/ic_delete_black_24dp.xml

@@ -21,5 +21,5 @@
 <vector android:autoMirrored="true" android:height="24dp"
 <vector android:autoMirrored="true" android:height="24dp"
     android:viewportHeight="24.0" android:viewportWidth="24.0"
     android:viewportHeight="24.0" android:viewportWidth="24.0"
     android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
     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>
 </vector>

+ 1 - 1
app/src/main/res/drawable/ic_star_border_grey600_24dp.xml → app/src/main/res/drawable/ic_exit_to_app_black_24dp.xml

@@ -21,5 +21,5 @@
 <vector android:autoMirrored="true" android:height="24dp"
 <vector android:autoMirrored="true" android:height="24dp"
     android:viewportHeight="24.0" android:viewportWidth="24.0"
     android:viewportHeight="24.0" android:viewportWidth="24.0"
     android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
     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>
 </vector>

+ 25 - 0
app/src/main/res/drawable/ic_star_black_24dp.xml

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

+ 25 - 0
app/src/main/res/drawable/ic_star_border_black_24dp.xml

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

+ 1 - 1
app/src/main/res/drawable/shape_favorite_bubble.xml

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

+ 45 - 1
app/src/main/res/layout/controller_conversation_info.xml

@@ -76,11 +76,30 @@
                 </RelativeLayout>
                 </RelativeLayout>
             </com.yarolegovich.mp.MaterialPreferenceCategory>
             </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
             <include
                 layout="@layout/notification_settings_item"
                 layout="@layout/notification_settings_item"
                 android:layout_width="match_parent"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_below="@id/conversation_info_name"
+                android:layout_below="@id/otherRoomOptions"
                 android:visibility="gone" />
                 android:visibility="gone" />
 
 
             <com.yarolegovich.mp.MaterialPreferenceCategory
             <com.yarolegovich.mp.MaterialPreferenceCategory
@@ -100,6 +119,31 @@
                     tools:listitem="@layout/rv_item_contact"></androidx.recyclerview.widget.RecyclerView>
                     tools:listitem="@layout/rv_item_contact"></androidx.recyclerview.widget.RecyclerView>
 
 
             </com.yarolegovich.mp.MaterialPreferenceCategory>
             </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>
         </RelativeLayout>
     </ScrollView>
     </ScrollView>
 </RelativeLayout>
 </RelativeLayout>