Эх сурвалжийг харах

Lobby & Various bugfixes and improvements

Includes conversion to Kotlin of some files

Signed-off-by: Mario Danic <mario@lovelyhq.com>
Mario Danic 5 жил өмнө
parent
commit
6a5aaac224
100 өөрчлөгдсөн 2052 нэмэгдсэн , 2124 устгасан
  1. 6 0
      app/build.gradle
  2. 20 0
      app/src/androidTest/java/com/nextcloud/talk/ExampleInstrumentedTest.java
  3. 3 3
      app/src/gplay/java/com/nextcloud/talk/services/firebase/MagicFirebaseMessagingService.java
  4. 3 2
      app/src/gplay/java/com/nextcloud/talk/utils/ClosedInterfaceImpl.java
  5. 1 1
      app/src/main/java/com/nextcloud/talk/activities/BaseActivity.java
  6. 2 2
      app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.java
  7. 6 6
      app/src/main/java/com/nextcloud/talk/activities/MainActivity.java
  8. 2 2
      app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java
  9. 1 1
      app/src/main/java/com/nextcloud/talk/adapters/items/AppItem.java
  10. 3 3
      app/src/main/java/com/nextcloud/talk/adapters/items/CallItem.java
  11. 5 5
      app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java
  12. 3 3
      app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java
  13. 2 2
      app/src/main/java/com/nextcloud/talk/adapters/items/MenuItem.java
  14. 1 1
      app/src/main/java/com/nextcloud/talk/adapters/items/NotificationSoundItem.java
  15. 10 10
      app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java
  16. 4 4
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java
  17. 2 2
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.java
  18. 6 6
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java
  19. 2 2
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicSystemMessageViewHolder.java
  20. 9 2
      app/src/main/java/com/nextcloud/talk/api/NcApi.java
  21. 0 239
      app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java
  22. 217 0
      app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.kt
  23. 3 3
      app/src/main/java/com/nextcloud/talk/components/filebrowser/adapters/items/BrowserFileItem.java
  24. 7 7
      app/src/main/java/com/nextcloud/talk/components/filebrowser/controllers/BrowserController.java
  25. 10 10
      app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.java
  26. 9 9
      app/src/main/java/com/nextcloud/talk/controllers/CallController.java
  27. 11 11
      app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java
  28. 168 98
      app/src/main/java/com/nextcloud/talk/controllers/ChatController.java
  29. 19 19
      app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java
  30. 0 507
      app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.java
  31. 552 0
      app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt
  32. 16 16
      app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java
  33. 1 1
      app/src/main/java/com/nextcloud/talk/controllers/LockedController.java
  34. 2 2
      app/src/main/java/com/nextcloud/talk/controllers/RingtoneSelectionController.java
  35. 9 9
      app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.java
  36. 6 8
      app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java
  37. 9 9
      app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java
  38. 5 5
      app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.java
  39. 1 1
      app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.java
  40. 19 19
      app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/CallMenuController.java
  41. 21 21
      app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.java
  42. 32 32
      app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.java
  43. 2 2
      app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java
  44. 1 1
      app/src/main/java/com/nextcloud/talk/events/MoreMenuClickEvent.java
  45. 1 1
      app/src/main/java/com/nextcloud/talk/events/WebSocketCommunicationEvent.java
  46. 4 4
      app/src/main/java/com/nextcloud/talk/interfaces/ClosedInterface.kt
  47. 4 4
      app/src/main/java/com/nextcloud/talk/interfaces/ConversationMenuInterface.kt
  48. 4 4
      app/src/main/java/com/nextcloud/talk/interfaces/SelectionInterface.kt
  49. 1 1
      app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalWorker.java
  50. 2 2
      app/src/main/java/com/nextcloud/talk/jobs/CapabilitiesWorker.java
  51. 3 3
      app/src/main/java/com/nextcloud/talk/jobs/DeleteConversationWorker.java
  52. 3 3
      app/src/main/java/com/nextcloud/talk/jobs/LeaveConversationWorker.java
  53. 19 19
      app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java
  54. 4 4
      app/src/main/java/com/nextcloud/talk/jobs/ShareOperationWorker.java
  55. 2 2
      app/src/main/java/com/nextcloud/talk/jobs/SignalingSettingsWorker.java
  56. 1 1
      app/src/main/java/com/nextcloud/talk/jobs/WebsocketConnectionsWorker.java
  57. 22 19
      app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java
  58. 26 6
      app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.java
  59. 2 2
      app/src/main/java/com/nextcloud/talk/models/json/conversations/RoomOCS.java
  60. 2 2
      app/src/main/java/com/nextcloud/talk/models/json/conversations/RoomOverall.java
  61. 2 2
      app/src/main/java/com/nextcloud/talk/models/json/conversations/RoomsOCS.java
  62. 2 2
      app/src/main/java/com/nextcloud/talk/models/json/conversations/RoomsOverall.java
  63. 50 0
      app/src/main/java/com/nextcloud/talk/models/json/converters/EnumLobbyStateConverter.java
  64. 1 1
      app/src/main/java/com/nextcloud/talk/models/json/converters/EnumNotificationLevelConverter.java
  65. 1 1
      app/src/main/java/com/nextcloud/talk/models/json/converters/EnumReadOnlyConversationConverter.java
  66. 1 1
      app/src/main/java/com/nextcloud/talk/models/json/converters/EnumRoomTypeConverter.java
  67. 0 126
      app/src/main/java/com/nextcloud/talk/models/json/converters/EnumSystemMessageTypeConverter.java
  68. 98 0
      app/src/main/java/com/nextcloud/talk/models/json/converters/EnumSystemMessageTypeConverter.kt
  69. 3 3
      app/src/main/java/com/nextcloud/talk/models/json/generic/GenericMeta.java
  70. 1 1
      app/src/main/java/com/nextcloud/talk/models/json/generic/GenericOCS.java
  71. 1 1
      app/src/main/java/com/nextcloud/talk/models/json/generic/GenericOverall.java
  72. 1 1
      app/src/main/java/com/nextcloud/talk/models/json/participants/AddParticipantOCS.java
  73. 1 1
      app/src/main/java/com/nextcloud/talk/models/json/participants/AddParticipantOverall.java
  74. 10 10
      app/src/main/java/com/nextcloud/talk/models/json/participants/Participant.java
  75. 1 1
      app/src/main/java/com/nextcloud/talk/models/json/participants/ParticipantsOCS.java
  76. 1 1
      app/src/main/java/com/nextcloud/talk/models/json/participants/ParticipantsOverall.java
  77. 1 1
      app/src/main/java/com/nextcloud/talk/models/json/websocket/RoomPropertiesWebSocketMessage.java
  78. 2 2
      app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java
  79. 1 1
      app/src/main/java/com/nextcloud/talk/receivers/PackageReplacedReceiver.java
  80. 0 156
      app/src/main/java/com/nextcloud/talk/utils/AccountUtils.java
  81. 149 0
      app/src/main/java/com/nextcloud/talk/utils/AccountUtils.kt
  82. 6 2
      app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java
  83. 0 39
      app/src/main/java/com/nextcloud/talk/utils/BottomNavigationUtils.java
  84. 0 59
      app/src/main/java/com/nextcloud/talk/utils/ConductorRemapping.java
  85. 57 0
      app/src/main/java/com/nextcloud/talk/utils/ConductorRemapping.kt
  86. 15 15
      app/src/main/java/com/nextcloud/talk/utils/DateUtils.kt
  87. 2 2
      app/src/main/java/com/nextcloud/talk/utils/DeviceUtils.java
  88. 3 3
      app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java
  89. 0 79
      app/src/main/java/com/nextcloud/talk/utils/DoNotDisturbUtils.java
  90. 74 0
      app/src/main/java/com/nextcloud/talk/utils/DoNotDisturbUtils.kt
  91. 0 161
      app/src/main/java/com/nextcloud/talk/utils/DrawableUtils.java
  92. 158 0
      app/src/main/java/com/nextcloud/talk/utils/DrawableUtils.kt
  93. 0 77
      app/src/main/java/com/nextcloud/talk/utils/LoggingUtils.java
  94. 78 0
      app/src/main/java/com/nextcloud/talk/utils/LoggingUtils.kt
  95. 7 7
      app/src/main/java/com/nextcloud/talk/utils/MagicMap.kt
  96. 7 7
      app/src/main/java/com/nextcloud/talk/utils/NotificationUtils.java
  97. 5 5
      app/src/main/java/com/nextcloud/talk/utils/PushUtils.java
  98. 1 1
      app/src/main/java/com/nextcloud/talk/utils/SecurityUtils.java
  99. 1 1
      app/src/main/java/com/nextcloud/talk/utils/ShareUtils.java
  100. 0 191
      app/src/main/java/com/nextcloud/talk/utils/bundle/BundleBuilder.java

+ 6 - 0
app/build.gradle

@@ -232,6 +232,12 @@ dependencies {
     implementation 'com.github.mario:PopupBubble:a365177d96'
     implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
     implementation 'eu.medsea.mimeutil:mime-util:2.1.3'
+
+    implementation 'com.afollestad.material-dialogs:core:3.1.0'
+    implementation 'com.afollestad.material-dialogs:datetime:3.1.0'
+    implementation 'com.afollestad.material-dialogs:bottomsheets:3.1.0'
+    implementation 'com.afollestad.material-dialogs:lifecycle:3.1.0'
+
     testImplementation 'junit:junit:4.12'
     testImplementation 'org.mockito:mockito-core:3.0.0'
     testImplementation 'org.powermock:powermock-core:2.0.2'

+ 20 - 0
app/src/androidTest/java/com/nextcloud/talk/ExampleInstrumentedTest.java

@@ -1,3 +1,23 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
 package com.nextcloud.talk;
 
 import android.content.Context;

+ 3 - 3
app/src/gplay/java/com/nextcloud/talk/services/firebase/MagicFirebaseMessagingService.java

@@ -45,7 +45,7 @@ public class MagicFirebaseMessagingService extends FirebaseMessagingService {
     @Override
     public void onNewToken(String token) {
         super.onNewToken(token);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
         appPreferences.setPushToken(token);
         OneTimeWorkRequest pushRegistrationWork = new OneTimeWorkRequest.Builder(PushRegistrationWorker.class).build();
         WorkManager.getInstance().enqueue(pushRegistrationWork);
@@ -60,8 +60,8 @@ public class MagicFirebaseMessagingService extends FirebaseMessagingService {
 
         if (remoteMessage.getData() != null) {
             Data messageData = new Data.Builder()
-                    .putString(BundleKeys.KEY_NOTIFICATION_SUBJECT, remoteMessage.getData().get("subject"))
-                    .putString(BundleKeys.KEY_NOTIFICATION_SIGNATURE, remoteMessage.getData().get("signature"))
+                    .putString(BundleKeys.INSTANCE.getKEY_NOTIFICATION_SUBJECT(), remoteMessage.getData().get("subject"))
+                    .putString(BundleKeys.INSTANCE.getKEY_NOTIFICATION_SIGNATURE(), remoteMessage.getData().get("signature"))
                     .build();
 
             OneTimeWorkRequest pushNotificationWork = new OneTimeWorkRequest.Builder(NotificationWorker.class)

+ 3 - 2
app/src/gplay/java/com/nextcloud/talk/utils/ClosedInterfaceImpl.java

@@ -33,14 +33,15 @@ import com.nextcloud.talk.interfaces.ClosedInterface;
 public class ClosedInterfaceImpl implements ClosedInterface, ProviderInstallListener {
     @Override
     public void providerInstallerInstallIfNeededAsync() {
-        ProviderInstaller.installIfNeededAsync(NextcloudTalkApplication.getSharedApplication().getApplicationContext(),
+        ProviderInstaller.installIfNeededAsync(NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext(),
                 this);
     }
 
     @Override
     public boolean isGooglePlayServicesAvailable() {
         GoogleApiAvailability api = GoogleApiAvailability.getInstance();
-        int code = api.isGooglePlayServicesAvailable(NextcloudTalkApplication.getSharedApplication().getApplicationContext());
+        int code =
+                api.isGooglePlayServicesAvailable(NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext());
         return code == ConnectionResult.SUCCESS;
     }
 

+ 1 - 1
app/src/main/java/com/nextcloud/talk/activities/BaseActivity.java

@@ -62,7 +62,7 @@ public class BaseActivity extends AppCompatActivity {
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
         super.onCreate(savedInstanceState);
     }
 

+ 2 - 2
app/src/main/java/com/nextcloud/talk/activities/MagicCallActivity.java

@@ -64,7 +64,7 @@ public class MagicCallActivity extends BaseActivity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         requestWindowFeature(Window.FEATURE_NO_TITLE);
         getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
@@ -80,7 +80,7 @@ public class MagicCallActivity extends BaseActivity {
         router.setPopsLastView(false);
 
         if (!router.hasRootController()) {
-            if (getIntent().getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
+            if (getIntent().getBooleanExtra(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL(), false)) {
                 router.setRoot(RouterTransaction.with(new CallNotificationController(getIntent().getExtras()))
                         .pushChangeHandler(new HorizontalChangeHandler())
                         .popChangeHandler(new HorizontalChangeHandler()));

+ 6 - 6
app/src/main/java/com/nextcloud/talk/activities/MainActivity.java

@@ -77,7 +77,7 @@ public final class MainActivity extends BaseActivity implements ActionBarProvide
 
         setContentView(R.layout.activity_main);
 
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
         ButterKnife.bind(this);
 
         setSupportActionBar(toolbar);
@@ -92,7 +92,7 @@ public final class MainActivity extends BaseActivity implements ActionBarProvide
             hasDb = false;
         }
 
-        if (getIntent().hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
+        if (getIntent().hasExtra(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL())) {
             if (!router.hasRootController()) {
                 router.setRoot(RouterTransaction.with(new ConversationsListController())
                         .pushChangeHandler(new HorizontalChangeHandler())
@@ -148,14 +148,14 @@ public final class MainActivity extends BaseActivity implements ActionBarProvide
     protected void onNewIntent(Intent intent) {
         super.onNewIntent(intent);
 
-        if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
-            if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
+        if (intent.hasExtra(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL())) {
+            if (intent.getBooleanExtra(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL(), false)) {
                 router.pushController(RouterTransaction.with(new CallNotificationController(intent.getExtras()))
                         .pushChangeHandler(new HorizontalChangeHandler())
                         .popChangeHandler(new HorizontalChangeHandler()));
             } else {
-                ConductorRemapping.remapChatController(router, intent.getLongExtra(BundleKeys.KEY_INTERNAL_USER_ID, -1),
-                        intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN), intent.getExtras(), false);
+                ConductorRemapping.INSTANCE.remapChatController(router, intent.getLongExtra(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1),
+                        intent.getStringExtra(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN()), intent.getExtras(), false);
                 ;
             }
         }

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

@@ -105,7 +105,7 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
 
         if (adapter.hasFilter()) {
             FlexibleUtils.highlightText(holder.contactDisplayName, participant.getName(),
-                    String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.getSharedApplication()
+                    String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication()
                             .getResources().getColor(R.color.colorPrimary));
         } else {
             holder.contactDisplayName.setText(participant.getName());
@@ -127,7 +127,7 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
         } else {
             holder.avatarImageView.setVisibility(View.GONE);
             RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) holder.linearLayout.getLayoutParams();
-            layoutParams.setMarginStart((int) NextcloudTalkApplication.getSharedApplication().getApplicationContext()
+            layoutParams.setMarginStart((int) NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext()
                     .getResources().getDimension(R.dimen.activity_horizontal_margin));
             layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START);
             holder.linearLayout.setLayoutParams(layoutParams);

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

@@ -92,7 +92,7 @@ public class AppItem extends AbstractFlexibleItem<AppItem.AppItemViewHolder> {
 
         if (position == 0) {
             Spannable spannableString = new SpannableString(title);
-            spannableString.setSpan(new ForegroundColorSpan(NextcloudTalkApplication.getSharedApplication()
+            spannableString.setSpan(new ForegroundColorSpan(NextcloudTalkApplication.Companion.getSharedApplication()
                             .getResources().getColor(R.color.grey_600)), 0,
                     spannableString.length(),
                     Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

+ 3 - 3
app/src/main/java/com/nextcloud/talk/adapters/items/CallItem.java

@@ -36,7 +36,7 @@ import com.nextcloud.talk.R;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.events.MoreMenuClickEvent;
 import com.nextcloud.talk.models.database.UserEntity;
-import com.nextcloud.talk.models.json.rooms.Conversation;
+import com.nextcloud.talk.models.json.conversations.Conversation;
 import com.nextcloud.talk.utils.ApiUtils;
 import com.nextcloud.talk.utils.DisplayUtils;
 import eu.davidea.flexibleadapter.FlexibleAdapter;
@@ -99,7 +99,7 @@ public class CallItem extends AbstractFlexibleItem<CallItem.RoomItemViewHolder>
     public void bindViewHolder(final FlexibleAdapter adapter, RoomItemViewHolder holder, int position, List payloads) {
         if (adapter.hasFilter()) {
             FlexibleUtils.highlightText(holder.roomDisplayName, conversation.getDisplayName(),
-                    String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.getSharedApplication()
+                    String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication()
                             .getResources().getColor(R.color.colorPrimary));
         } else {
             holder.roomDisplayName.setText(conversation.getDisplayName());
@@ -118,7 +118,7 @@ public class CallItem extends AbstractFlexibleItem<CallItem.RoomItemViewHolder>
             holder.passwordProtectedImageView.setVisibility(View.GONE);
         }
 
-        Resources resources = NextcloudTalkApplication.getSharedApplication().getResources();
+        Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
         switch (conversation.getType()) {
             case ROOM_TYPE_ONE_TO_ONE_CALL:
                 holder.avatarImageView.setVisibility(View.VISIBLE);

+ 5 - 5
app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java

@@ -39,7 +39,7 @@ import com.nextcloud.talk.R;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.models.database.UserEntity;
 import com.nextcloud.talk.models.json.chat.ChatMessage;
-import com.nextcloud.talk.models.json.rooms.Conversation;
+import com.nextcloud.talk.models.json.conversations.Conversation;
 import com.nextcloud.talk.utils.ApiUtils;
 import com.nextcloud.talk.utils.DisplayUtils;
 import eu.davidea.flexibleadapter.FlexibleAdapter;
@@ -94,14 +94,14 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
 
     @Override
     public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, ConversationItemViewHolder holder, int position, List<Object> payloads) {
-        Context context = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
+        Context context = NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext();
 
         holder.dialogAvatar.setController(null);
         holder.dialogLastMessageUserAvatar.setController(null);
 
         if (adapter.hasFilter()) {
             FlexibleUtils.highlightText(holder.dialogName, conversation.getDisplayName(),
-                    String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.getSharedApplication()
+                    String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication()
                             .getResources().getColor(R.color.colorPrimary));
         } else {
             holder.dialogName.setText(conversation.getDisplayName());
@@ -156,7 +156,7 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
                         authorDisplayName = !TextUtils.isEmpty(conversation.getLastMessage().getActorDisplayName()) ?
                                 conversation.getLastMessage().getActorDisplayName() :
                                 "guests".equals(conversation.getLastMessage().getActorType()) ?
-                                        NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_guest) : "";
+                                        NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest) : "";
                         text = String.format(context.getString(R.string.nc_formatted_message),
                                 authorDisplayName,
                                 conversation.getLastMessage().getLastMessageDisplayText());
@@ -169,7 +169,7 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
 
                 if (conversation.getLastMessage().getActorType().equals("guests")) {
                     if (TextUtils.isEmpty(authorDisplayName)) {
-                        authorDisplayName = NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_guest);
+                        authorDisplayName = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest);
                     }
                     holder.dialogLastMessageUserAvatar.setVisibility(View.VISIBLE);
                     TextDrawable drawable = TextDrawable.builder().beginConfig().bold()

+ 3 - 3
app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java

@@ -96,11 +96,11 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem<UserItem.UserI
 
         if (adapter.hasFilter()) {
             FlexibleUtils.highlightText(holder.contactDisplayName, displayName,
-                    String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.getSharedApplication()
+                    String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication()
                             .getResources().getColor(R.color.colorPrimary));
             if (holder.contactMentionId != null) {
                 FlexibleUtils.highlightText(holder.contactMentionId, "@" + objectId,
-                        String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.getSharedApplication()
+                        String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication()
                                 .getResources().getColor(R.color.colorPrimary));
             }
         } else {
@@ -111,7 +111,7 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem<UserItem.UserI
         }
 
         if (source.equals("calls")) {
-            holder.simpleDraweeView.getHierarchy().setPlaceholderImage(DisplayUtils.getRoundedBitmapDrawableFromVectorDrawableResource(NextcloudTalkApplication.getSharedApplication().getResources(), R.drawable.ic_people_group_white_24px));
+            holder.simpleDraweeView.getHierarchy().setPlaceholderImage(DisplayUtils.getRoundedBitmapDrawableFromVectorDrawableResource(NextcloudTalkApplication.Companion.getSharedApplication().getResources(), R.drawable.ic_people_group_white_24px));
         } else {
         holder.simpleDraweeView.setController(null);
             DraweeController draweeController = Fresco.newDraweeControllerBuilder()

+ 2 - 2
app/src/main/java/com/nextcloud/talk/adapters/items/MenuItem.java

@@ -51,7 +51,7 @@ public class MenuItem extends AbstractFlexibleItem<MenuItem.MenuItemViewHolder>
         this.tag = tag;
         this.icon = icon;
         padding = (int) DisplayUtils.convertDpToPixel(16,
-                NextcloudTalkApplication.getSharedApplication().getApplicationContext());
+                NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext());
     }
 
     @Override
@@ -81,7 +81,7 @@ public class MenuItem extends AbstractFlexibleItem<MenuItem.MenuItemViewHolder>
     public void bindViewHolder(FlexibleAdapter adapter, MenuItem.MenuItemViewHolder holder, int position, List payloads) {
         if (position == 0) {
             Spannable spannableString = new SpannableString(title);
-            spannableString.setSpan(new ForegroundColorSpan(NextcloudTalkApplication.getSharedApplication()
+            spannableString.setSpan(new ForegroundColorSpan(NextcloudTalkApplication.Companion.getSharedApplication()
                             .getResources().getColor(R.color.grey_600)), 0,
                     spannableString.length(),
                     Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

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

@@ -80,7 +80,7 @@ public class NotificationSoundItem extends AbstractFlexibleItem<NotificationSoun
             holder.checkedImageView.setVisibility(View.GONE);
         }
 
-        Resources resources = NextcloudTalkApplication.getSharedApplication().getResources();
+        Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
         holder.simpleDraweeView.getHierarchy().setBackgroundImage(new ColorDrawable(resources.getColor(R.color.colorPrimary)));
         if (position == 0) {
             holder.simpleDraweeView.getHierarchy().setImage(resources.getDrawable(R.drawable.ic_stop_white_24dp), 100,

+ 10 - 10
app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java

@@ -118,14 +118,14 @@ public class UserItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder>
 
         if (adapter.hasFilter()) {
             FlexibleUtils.highlightText(holder.contactDisplayName, participant.getDisplayName(),
-                    String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.getSharedApplication()
+                    String.valueOf(adapter.getFilter(String.class)), NextcloudTalkApplication.Companion.getSharedApplication()
                             .getResources().getColor(R.color.colorPrimary));
         } else {
             holder.contactDisplayName.setText(participant.getDisplayName());
 
             if (TextUtils.isEmpty(participant.getDisplayName()) &&
                     (participant.getType().equals(Participant.ParticipantType.GUEST) || participant.getType().equals(Participant.ParticipantType.USER_FOLLOWING_LINK))) {
-                holder.contactDisplayName.setText(NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_guest));
+                holder.contactDisplayName.setText(NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest));
             }
         }
 
@@ -146,7 +146,7 @@ public class UserItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder>
 
             }
         } else if ("groups".equals(participant.getSource())) {
-            holder.simpleDraweeView.getHierarchy().setImage(new BitmapDrawable(DisplayUtils.getRoundedBitmapFromVectorDrawableResource(NextcloudTalkApplication.getSharedApplication().getResources(), R.drawable.ic_people_group_white_24px)), 100, true);
+            holder.simpleDraweeView.getHierarchy().setImage(new BitmapDrawable(DisplayUtils.getRoundedBitmapFromVectorDrawableResource(NextcloudTalkApplication.Companion.getSharedApplication().getResources(), R.drawable.ic_people_group_white_24px)), 100, true);
         }
 
         if (!isEnabled()) {
@@ -155,7 +155,7 @@ public class UserItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder>
             holder.itemView.setAlpha(1.0f);
         }
 
-        Resources resources = NextcloudTalkApplication.getSharedApplication().getResources();
+        Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
 
         if (header == null) {
             Participant.ParticipantFlags participantFlags = participant.getParticipantFlags();
@@ -198,19 +198,19 @@ public class UserItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder>
 
                 switch (new EnumParticipantTypeConverter().convertToInt(participant.getType())) {
                     case 1:
-                        //userType = NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_owner);
+                        //userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_owner);
                         //break;
                     case 2:
-                        userType = NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_moderator);
+                        userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_moderator);
                         break;
                     case 3:
-                        userType = NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_user);
+                        userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_user);
                         break;
                     case 4:
-                        userType = NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_guest);
+                        userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest);
                         break;
                     case 5:
-                        userType = NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_following_link);
+                        userType = NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_following_link);
                         break;
                     default:
                         break;
@@ -218,7 +218,7 @@ public class UserItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder>
 
                 if (!holder.contactMentionId.getText().equals(userType)) {
                     holder.contactMentionId.setText(userType);
-                    holder.contactMentionId.setTextColor(NextcloudTalkApplication.getSharedApplication().getResources().getColor(R.color.colorPrimary));
+                    holder.contactMentionId.setTextColor(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getColor(R.color.colorPrimary));
                 }
             }
         }

+ 4 - 4
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java

@@ -82,7 +82,7 @@ public class MagicIncomingTextMessageViewHolder
     public MagicIncomingTextMessageViewHolder(View itemView) {
         super(itemView);
         ButterKnife.bind(this, itemView);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         this.itemView = itemView;
     }
@@ -103,8 +103,8 @@ public class MagicIncomingTextMessageViewHolder
             messageUserAvatarView.setVisibility(View.VISIBLE);
             if (message.getActorType().equals("guests")) {
                 TextDrawable drawable = TextDrawable.builder().beginConfig().bold()
-                        .endConfig().buildRound(String.valueOf(messageAuthor.getText().charAt(0)), NextcloudTalkApplication
-                                .getSharedApplication().getResources().getColor(R.color.nc_grey));
+                        .endConfig().buildRound(String.valueOf(messageAuthor.getText().charAt(0))
+                                , NextcloudTalkApplication.Companion.getSharedApplication().getResources().getColor(R.color.nc_grey));
                 messageUserAvatarView.getHierarchy().setPlaceholderImage(drawable);
             } else if (message.getActorType().equals("bots") && message.getActorId().equals("changelog")) {
                 messageUserAvatarView.setController(null);
@@ -139,7 +139,7 @@ public class MagicIncomingTextMessageViewHolder
 
         HashMap<String, HashMap<String, String>> messageParameters = message.getMessageParameters();
 
-        Context context = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
+        Context context = NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext();
         itemView.setSelected(false);
         messageTimeView.setTextColor(context.getResources().getColor(R.color.warm_grey_four));
 

+ 2 - 2
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.java

@@ -66,7 +66,7 @@ public class MagicOutcomingTextMessageViewHolder extends MessageHolders.Outcomin
     public MagicOutcomingTextMessageViewHolder(View itemView) {
         super(itemView);
         ButterKnife.bind(this, itemView);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         this.itemView = itemView;
     }
@@ -128,7 +128,7 @@ public class MagicOutcomingTextMessageViewHolder extends MessageHolders.Outcomin
             itemView.setSelected(true);
         }
 
-        Resources resources = NextcloudTalkApplication.getSharedApplication().getResources();
+        Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
         if (message.isGrouped) {
             Drawable bubbleDrawable = DisplayUtils.getMessageSelector(resources.getColor(R.color.colorPrimary),
                     resources.getColor(R.color.transparent),

+ 6 - 6
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java

@@ -70,7 +70,7 @@ public class MagicPreviewMessageViewHolder extends MessageHolders.IncomingImageM
     public MagicPreviewMessageViewHolder(View itemView) {
         super(itemView);
         ButterKnife.bind(this, itemView);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
     }
 
     @SuppressLint("SetTextI18n")
@@ -99,7 +99,7 @@ public class MagicPreviewMessageViewHolder extends MessageHolders.IncomingImageM
             messageText.setText(message.getSelectedIndividualHashMap().get("name"));
             DisplayUtils.setClickableString(message.getSelectedIndividualHashMap().get("name"), message.getSelectedIndividualHashMap().get("link"), messageText);
             if (message.getSelectedIndividualHashMap().containsKey("mimetype")) {
-                image.getHierarchy().setPlaceholderImage(context.getDrawable(DrawableUtils.getDrawableResourceIdForMimeType(message.getSelectedIndividualHashMap().get("mimetype"))));
+                image.getHierarchy().setPlaceholderImage(context.getDrawable(DrawableUtils.INSTANCE.getDrawableResourceIdForMimeType(message.getSelectedIndividualHashMap().get("mimetype"))));
             } else {
                 fetchFileInformation("/" + message.getSelectedIndividualHashMap().get("path"), message.getActiveUser());
             }
@@ -109,14 +109,14 @@ public class MagicPreviewMessageViewHolder extends MessageHolders.IncomingImageM
                 String accountString =
                         message.getActiveUser().getUsername() + "@" + message.getActiveUser().getBaseUrl().replace("https://", "").replace("http://", "");
 
-                if (AccountUtils.canWeOpenFilesApp(context, accountString)) {
+                if (AccountUtils.INSTANCE.canWeOpenFilesApp(context, accountString)) {
                     Intent filesAppIntent = new Intent(Intent.ACTION_VIEW, null);
                     final ComponentName componentName = new ComponentName(context.getString(R.string.nc_import_accounts_from), "com.owncloud.android.ui.activity.FileDisplayActivity");
                     filesAppIntent.setComponent(componentName);
                     filesAppIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                     filesAppIntent.setPackage(context.getString(R.string.nc_import_accounts_from));
-                    filesAppIntent.putExtra(BundleKeys.KEY_ACCOUNT, accountString);
-                    filesAppIntent.putExtra(BundleKeys.KEY_FILE_ID, message.getSelectedIndividualHashMap().get("id"));
+                    filesAppIntent.putExtra(BundleKeys.INSTANCE.getKEY_ACCOUNT(), accountString);
+                    filesAppIntent.putExtra(BundleKeys.INSTANCE.getKEY_FILE_ID(), message.getSelectedIndividualHashMap().get("id"));
                     context.startActivity(filesAppIntent);
                 } else {
                     Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(message.getSelectedIndividualHashMap().get("link")));
@@ -163,7 +163,7 @@ public class MagicPreviewMessageViewHolder extends MessageHolders.IncomingImageM
                         if (davResponse.getData() != null) {
                             List<BrowserFile> browserFileList = (List<BrowserFile>) davResponse.getData();
                             if (!browserFileList.isEmpty()) {
-                                new Handler(context.getMainLooper()).post(() -> image.getHierarchy().setPlaceholderImage(context.getDrawable(DrawableUtils.getDrawableResourceIdForMimeType(browserFileList.get(0).getMimeType()))));
+                                new Handler(context.getMainLooper()).post(() -> image.getHierarchy().setPlaceholderImage(context.getDrawable(DrawableUtils.INSTANCE.getDrawableResourceIdForMimeType(browserFileList.get(0).getMimeType()))));
                             }
                         }
                     }

+ 2 - 2
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicSystemMessageViewHolder.java

@@ -49,14 +49,14 @@ public class MagicSystemMessageViewHolder extends MessageHolders.IncomingTextMes
 
     public MagicSystemMessageViewHolder(View itemView) {
         super(itemView);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
     }
 
     @Override
     public void onBind(ChatMessage message) {
         super.onBind(message);
 
-        Resources resources = NextcloudTalkApplication.getSharedApplication().getResources();
+        Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
         int normalColor;
         int pressedColor;
         int mentionYouColor;

+ 9 - 2
app/src/main/java/com/nextcloud/talk/api/NcApi.java

@@ -31,8 +31,8 @@ import com.nextcloud.talk.models.json.notifications.NotificationOverall;
 import com.nextcloud.talk.models.json.participants.AddParticipantOverall;
 import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
 import com.nextcloud.talk.models.json.push.PushRegistrationOverall;
-import com.nextcloud.talk.models.json.rooms.RoomOverall;
-import com.nextcloud.talk.models.json.rooms.RoomsOverall;
+import com.nextcloud.talk.models.json.conversations.RoomOverall;
+import com.nextcloud.talk.models.json.conversations.RoomsOverall;
 import com.nextcloud.talk.models.json.signaling.SignalingOverall;
 import com.nextcloud.talk.models.json.signaling.settings.SignalingSettingsOverall;
 import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
@@ -311,4 +311,11 @@ public interface NcApi {
                                        @Field("path") String remotePath,
                                        @Field("shareWith") String roomToken,
                                        @Field("shareType") String shareType);
+
+    @FormUrlEncoded
+    @PUT
+    Observable<GenericOverall> setLobbyForConversation(@Header("Authorization") String authorization,
+                                      @Url String url, @Field("state") Integer state,
+                                                       @Field("timer") Long timer);
+
 }

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

@@ -1,239 +0,0 @@
-/*
- *
- *   Nextcloud Talk application
- *
- *   @author Mario Danic
- *   Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation, either version 3 of the License, or
- *   at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-package com.nextcloud.talk.application;
-
-import android.content.Context;
-import android.os.Build;
-import android.util.Log;
-import androidx.emoji.bundled.BundledEmojiCompatConfig;
-import androidx.emoji.text.EmojiCompat;
-
-import androidx.appcompat.app.AppCompatDelegate;
-import androidx.lifecycle.LifecycleObserver;
-import androidx.multidex.MultiDex;
-import androidx.multidex.MultiDexApplication;
-import androidx.work.ExistingPeriodicWorkPolicy;
-import androidx.work.OneTimeWorkRequest;
-import androidx.work.PeriodicWorkRequest;
-import androidx.work.WorkManager;
-import autodagger.AutoComponent;
-import autodagger.AutoInjector;
-import com.facebook.cache.disk.DiskCacheConfig;
-import com.facebook.drawee.backends.pipeline.Fresco;
-import com.facebook.imagepipeline.core.ImagePipelineConfig;
-import com.nextcloud.talk.BuildConfig;
-import com.nextcloud.talk.components.filebrowser.webdav.DavUtils;
-import com.nextcloud.talk.dagger.modules.BusModule;
-import com.nextcloud.talk.dagger.modules.ContextModule;
-import com.nextcloud.talk.dagger.modules.DatabaseModule;
-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.SignalingSettingsWorker;
-import com.nextcloud.talk.utils.ClosedInterfaceImpl;
-import com.nextcloud.talk.utils.DeviceUtils;
-import com.nextcloud.talk.utils.DisplayUtils;
-import com.nextcloud.talk.utils.OkHttpNetworkFetcherWithCache;
-import com.nextcloud.talk.utils.database.arbitrarystorage.ArbitraryStorageModule;
-import com.nextcloud.talk.utils.database.user.UserModule;
-import com.nextcloud.talk.utils.preferences.AppPreferences;
-import com.nextcloud.talk.webrtc.MagicWebRTCUtils;
-import com.vanniktech.emoji.EmojiManager;
-import com.vanniktech.emoji.googlecompat.GoogleCompatEmojiProvider;
-
-import de.cotech.hw.SecurityKeyManager;
-import de.cotech.hw.SecurityKeyManagerConfig;
-import okhttp3.OkHttpClient;
-import org.conscrypt.Conscrypt;
-import org.webrtc.PeerConnectionFactory;
-import org.webrtc.voiceengine.WebRtcAudioManager;
-import org.webrtc.voiceengine.WebRtcAudioUtils;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import java.security.Security;
-import java.util.concurrent.TimeUnit;
-
-@AutoComponent(
-        modules = {
-                BusModule.class,
-                ContextModule.class,
-                DatabaseModule.class,
-                RestModule.class,
-                UserModule.class,
-                ArbitraryStorageModule.class,
-        }
-)
-
-@Singleton
-@AutoInjector(NextcloudTalkApplication.class)
-public class NextcloudTalkApplication extends MultiDexApplication implements LifecycleObserver {
-    private static final String TAG = NextcloudTalkApplication.class.getSimpleName();
-    //region Singleton
-    protected static NextcloudTalkApplication sharedApplication;
-    //region Fields (components)
-    protected NextcloudTalkApplicationComponent componentApplication;
-
-    @Inject
-    AppPreferences appPreferences;
-    @Inject
-    OkHttpClient okHttpClient;
-    //endregion
-
-    public static NextcloudTalkApplication getSharedApplication() {
-        return sharedApplication;
-    }
-    //endregion
-
-    //region private methods
-    private void initializeWebRtc() {
-        try {
-            if (MagicWebRTCUtils.HARDWARE_AEC_BLACKLIST.contains(Build.MODEL)) {
-                WebRtcAudioUtils.setWebRtcBasedAcousticEchoCanceler(true);
-            }
-
-            if (!MagicWebRTCUtils.OPEN_SL_ES_WHITELIST.contains(Build.MODEL)) {
-                WebRtcAudioManager.setBlacklistDeviceForOpenSLESUsage(true);
-            }
-
-
-            PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions.builder(this)
-                    .setEnableVideoHwAcceleration(MagicWebRTCUtils.shouldEnableVideoHardwareAcceleration())
-                    .createInitializationOptions());
-        } catch (UnsatisfiedLinkError e) {
-            Log.w(TAG, e);
-        }
-    }
-
-    //endregion
-
-    //region Overridden methods
-    @Override
-    public void onCreate() {
-        sharedApplication = this;
-
-        SecurityKeyManager securityKeyManager = SecurityKeyManager.getInstance();
-        SecurityKeyManagerConfig securityKeyConfig = new SecurityKeyManagerConfig.Builder()
-                .setEnableDebugLogging(BuildConfig.DEBUG)
-                .build();
-        securityKeyManager.init(this, securityKeyConfig);
-
-        initializeWebRtc();
-        DisplayUtils.useCompatVectorIfNeeded();
-        buildComponent();
-        DavUtils.registerCustomFactories();
-
-        componentApplication.inject(this);
-
-        setAppTheme(appPreferences.getTheme());
-        super.onCreate();
-
-        ImagePipelineConfig imagePipelineConfig = ImagePipelineConfig.newBuilder(this)
-                .setNetworkFetcher(new OkHttpNetworkFetcherWithCache(okHttpClient))
-                .setMainDiskCacheConfig(DiskCacheConfig.newBuilder(this)
-                        .setMaxCacheSize(0)
-                        .setMaxCacheSizeOnLowDiskSpace(0)
-                        .setMaxCacheSizeOnVeryLowDiskSpace(0)
-                        .build())
-                .build();
-
-        Fresco.initialize(this, imagePipelineConfig);
-        Security.insertProviderAt(Conscrypt.newProvider(), 1);
-
-        new ClosedInterfaceImpl().providerInstallerInstallIfNeededAsync();
-        DeviceUtils.ignoreSpecialBatteryFeatures();
-
-        OneTimeWorkRequest pushRegistrationWork = new OneTimeWorkRequest.Builder(PushRegistrationWorker.class).build();
-        OneTimeWorkRequest accountRemovalWork = new OneTimeWorkRequest.Builder(AccountRemovalWorker.class).build();
-        PeriodicWorkRequest periodicCapabilitiesUpdateWork = new PeriodicWorkRequest.Builder(CapabilitiesWorker.class,
-                12, TimeUnit.HOURS).build();
-        OneTimeWorkRequest capabilitiesUpdateWork = new OneTimeWorkRequest.Builder(CapabilitiesWorker.class).build();
-        OneTimeWorkRequest signalingSettingsWork = new OneTimeWorkRequest.Builder(SignalingSettingsWorker.class).build();
-
-        WorkManager.getInstance().enqueue(pushRegistrationWork);
-        WorkManager.getInstance().enqueue(accountRemovalWork);
-        WorkManager.getInstance().enqueue(capabilitiesUpdateWork);
-        WorkManager.getInstance().enqueue(signalingSettingsWork);
-        WorkManager.getInstance().enqueueUniquePeriodicWork("DailyCapabilitiesUpdateWork", ExistingPeriodicWorkPolicy.REPLACE, periodicCapabilitiesUpdateWork);
-
-        final EmojiCompat.Config config = new BundledEmojiCompatConfig(this);
-        config.setReplaceAll(true);
-        EmojiCompat emojiCompat = EmojiCompat.init(config);
-
-        EmojiManager.install(new GoogleCompatEmojiProvider(emojiCompat));
-    }
-
-    @Override
-    public void onTerminate() {
-        super.onTerminate();
-        sharedApplication = null;
-    }
-
-    //endregion
-
-    //region Getters
-    public NextcloudTalkApplicationComponent getComponentApplication() {
-        return componentApplication;
-    }
-    //endregion
-
-    //region Setters
-    public static void setAppTheme(String theme) {
-        switch (theme) {
-            case "night_no":
-                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
-                break;
-            case "night_yes":
-                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
-                break;
-            case "battery_saver":
-                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
-                break;
-            default:
-                // will be "follow_system" only for now
-                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
-
-        }
-    }
-    //endregion
-
-
-
-    //region Protected methods
-    protected void buildComponent() {
-        componentApplication = DaggerNextcloudTalkApplicationComponent.builder()
-                .busModule(new BusModule())
-                .contextModule(new ContextModule(getApplicationContext()))
-                .databaseModule(new DatabaseModule())
-                .restModule(new RestModule(getApplicationContext()))
-                .userModule(new UserModule())
-                .arbitraryStorageModule(new ArbitraryStorageModule())
-                .build();
-    }
-
-    @Override
-    protected void attachBaseContext(Context base) {
-        super.attachBaseContext(base);
-        MultiDex.install(this);
-    }
-    //endregion
-}

+ 217 - 0
app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.kt

@@ -0,0 +1,217 @@
+/*
+ *
+ *   Nextcloud Talk application
+ *
+ *   @author Mario Danic
+ *   Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.nextcloud.talk.application
+
+import android.content.Context
+import android.os.Build
+import android.util.Log
+import androidx.emoji.bundled.BundledEmojiCompatConfig
+import androidx.emoji.text.EmojiCompat
+
+import androidx.appcompat.app.AppCompatDelegate
+import androidx.lifecycle.LifecycleObserver
+import androidx.multidex.MultiDex
+import androidx.multidex.MultiDexApplication
+import androidx.work.ExistingPeriodicWorkPolicy
+import androidx.work.OneTimeWorkRequest
+import androidx.work.PeriodicWorkRequest
+import androidx.work.WorkManager
+import autodagger.AutoComponent
+import autodagger.AutoInjector
+import com.facebook.cache.disk.DiskCacheConfig
+import com.facebook.drawee.backends.pipeline.Fresco
+import com.facebook.imagepipeline.core.ImagePipelineConfig
+import com.nextcloud.talk.BuildConfig
+import com.nextcloud.talk.components.filebrowser.webdav.DavUtils
+import com.nextcloud.talk.dagger.modules.BusModule
+import com.nextcloud.talk.dagger.modules.ContextModule
+import com.nextcloud.talk.dagger.modules.DatabaseModule
+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.SignalingSettingsWorker
+import com.nextcloud.talk.utils.ClosedInterfaceImpl
+import com.nextcloud.talk.utils.DeviceUtils
+import com.nextcloud.talk.utils.DisplayUtils
+import com.nextcloud.talk.utils.OkHttpNetworkFetcherWithCache
+import com.nextcloud.talk.utils.database.arbitrarystorage.ArbitraryStorageModule
+import com.nextcloud.talk.utils.database.user.UserModule
+import com.nextcloud.talk.utils.preferences.AppPreferences
+import com.nextcloud.talk.webrtc.MagicWebRTCUtils
+import com.vanniktech.emoji.EmojiManager
+import com.vanniktech.emoji.googlecompat.GoogleCompatEmojiProvider
+
+import de.cotech.hw.SecurityKeyManager
+import de.cotech.hw.SecurityKeyManagerConfig
+import okhttp3.OkHttpClient
+import org.conscrypt.Conscrypt
+import org.webrtc.PeerConnectionFactory
+import org.webrtc.voiceengine.WebRtcAudioManager
+import org.webrtc.voiceengine.WebRtcAudioUtils
+
+import javax.inject.Inject
+import javax.inject.Singleton
+import java.security.Security
+import java.util.concurrent.TimeUnit
+
+@AutoComponent(modules = [BusModule::class, ContextModule::class, DatabaseModule::class, RestModule::class, UserModule::class, ArbitraryStorageModule::class])
+@Singleton
+@AutoInjector(NextcloudTalkApplication::class)
+class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
+    //region Fields (components)
+    lateinit var componentApplication: NextcloudTalkApplicationComponent
+        private set
+    //endregion
+
+    //region Getters
+
+    @Inject
+    lateinit var appPreferences: AppPreferences
+    @Inject
+    lateinit var okHttpClient: OkHttpClient
+    //endregion
+
+    //region private methods
+    private fun initializeWebRtc() {
+        try {
+            if (MagicWebRTCUtils.HARDWARE_AEC_BLACKLIST.contains(Build.MODEL)) {
+                WebRtcAudioUtils.setWebRtcBasedAcousticEchoCanceler(true)
+            }
+
+            if (!MagicWebRTCUtils.OPEN_SL_ES_WHITELIST.contains(Build.MODEL)) {
+                WebRtcAudioManager.setBlacklistDeviceForOpenSLESUsage(true)
+            }
+
+
+            PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions.builder(this)
+                    .setEnableVideoHwAcceleration(MagicWebRTCUtils.shouldEnableVideoHardwareAcceleration())
+                    .createInitializationOptions())
+        } catch (e: UnsatisfiedLinkError) {
+            Log.w(TAG, e)
+        }
+
+    }
+
+    //endregion
+
+    //region Overridden methods
+    override fun onCreate() {
+        sharedApplication = this
+
+        val securityKeyManager = SecurityKeyManager.getInstance()
+        val securityKeyConfig = SecurityKeyManagerConfig.Builder()
+                .setEnableDebugLogging(BuildConfig.DEBUG)
+                .build()
+        securityKeyManager.init(this, securityKeyConfig)
+
+        initializeWebRtc()
+        DisplayUtils.useCompatVectorIfNeeded()
+        buildComponent()
+        DavUtils.registerCustomFactories()
+
+        componentApplication.inject(this)
+
+        setAppTheme(appPreferences!!.theme)
+        super.onCreate()
+
+        val imagePipelineConfig = ImagePipelineConfig.newBuilder(this)
+                .setNetworkFetcher(OkHttpNetworkFetcherWithCache(okHttpClient))
+                .setMainDiskCacheConfig(DiskCacheConfig.newBuilder(this)
+                        .setMaxCacheSize(0)
+                        .setMaxCacheSizeOnLowDiskSpace(0)
+                        .setMaxCacheSizeOnVeryLowDiskSpace(0)
+                        .build())
+                .build()
+
+        Fresco.initialize(this, imagePipelineConfig)
+        Security.insertProviderAt(Conscrypt.newProvider(), 1)
+
+        ClosedInterfaceImpl().providerInstallerInstallIfNeededAsync()
+        DeviceUtils.ignoreSpecialBatteryFeatures()
+
+        val pushRegistrationWork = OneTimeWorkRequest.Builder(PushRegistrationWorker::class.java).build()
+        val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
+        val periodicCapabilitiesUpdateWork = PeriodicWorkRequest.Builder(CapabilitiesWorker::class.java,
+                12, TimeUnit.HOURS).build()
+        val capabilitiesUpdateWork = OneTimeWorkRequest.Builder(CapabilitiesWorker::class.java).build()
+        val signalingSettingsWork = OneTimeWorkRequest.Builder(SignalingSettingsWorker::class.java).build()
+
+        WorkManager.getInstance().enqueue(pushRegistrationWork)
+        WorkManager.getInstance().enqueue(accountRemovalWork)
+        WorkManager.getInstance().enqueue(capabilitiesUpdateWork)
+        WorkManager.getInstance().enqueue(signalingSettingsWork)
+        WorkManager.getInstance().enqueueUniquePeriodicWork("DailyCapabilitiesUpdateWork", ExistingPeriodicWorkPolicy.REPLACE, periodicCapabilitiesUpdateWork)
+
+        val config = BundledEmojiCompatConfig(this)
+        config.setReplaceAll(true)
+        val emojiCompat = EmojiCompat.init(config)
+
+        EmojiManager.install(GoogleCompatEmojiProvider(emojiCompat))
+    }
+
+    override fun onTerminate() {
+        super.onTerminate()
+        sharedApplication = null
+    }
+    //endregion
+
+
+    //region Protected methods
+    protected fun buildComponent() {
+        componentApplication = DaggerNextcloudTalkApplicationComponent.builder()
+                .busModule(BusModule())
+                .contextModule(ContextModule(applicationContext))
+                .databaseModule(DatabaseModule())
+                .restModule(RestModule(applicationContext))
+                .userModule(UserModule())
+                .arbitraryStorageModule(ArbitraryStorageModule())
+                .build()
+    }
+
+    override fun attachBaseContext(base: Context) {
+        super.attachBaseContext(base)
+        MultiDex.install(this)
+    }
+
+    companion object {
+        private val TAG = NextcloudTalkApplication::class.java.simpleName
+        //region Singleton
+        //endregion
+
+        var sharedApplication: NextcloudTalkApplication? = null
+            protected set
+        //endregion
+
+        //region Setters
+        fun setAppTheme(theme: String) {
+            when (theme) {
+                "night_no" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
+                "night_yes" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
+                "battery_saver" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)
+                else ->
+                    // will be "follow_system" only for now
+                    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
+            }
+        }
+    }
+    //endregion
+}

+ 3 - 3
app/src/main/java/com/nextcloud/talk/components/filebrowser/adapters/items/BrowserFileItem.java

@@ -63,7 +63,7 @@ public class BrowserFileItem extends AbstractFlexibleItem<BrowserFileItem.ViewHo
         this.browserFile = browserFile;
         this.activeUser = activeUser;
         this.selectionInterface = selectionInterface;
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
     }
 
     @Override
@@ -119,7 +119,7 @@ public class BrowserFileItem extends AbstractFlexibleItem<BrowserFileItem.ViewHo
             holder.fileFavoriteImageView.setVisibility(View.GONE);
         }
 
-        holder.fileIconImageView.getHierarchy().setPlaceholderImage(context.getDrawable(DrawableUtils.getDrawableResourceIdForMimeType(browserFile.getMimeType())));
+        holder.fileIconImageView.getHierarchy().setPlaceholderImage(context.getDrawable(DrawableUtils.INSTANCE.getDrawableResourceIdForMimeType(browserFile.getMimeType())));
 
         if (browserFile.isHasPreview()) {
             String path = ApiUtils.getUrlForFilePreviewWithRemotePath(activeUser.getBaseUrl(),
@@ -138,7 +138,7 @@ public class BrowserFileItem extends AbstractFlexibleItem<BrowserFileItem.ViewHo
         holder.filenameTextView.setText(browserFile.getDisplayName());
         holder.fileModifiedTextView.setText(String.format(context.getString(R.string.nc_last_modified),
                 Formatter.formatShortFileSize(context, browserFile.getSize()),
-                DateUtils.getLocalDateTimeStringFromTimestamp(context, browserFile.getModifiedTimestamp())));
+                DateUtils.INSTANCE.getLocalDateTimeStringFromTimestamp(browserFile.getModifiedTimestamp())));
         setSelected(selectionInterface.isPathSelected(browserFile.getPath()));
         holder.selectFileCheckbox.setChecked(isSelected());
 

+ 7 - 7
app/src/main/java/com/nextcloud/talk/components/filebrowser/controllers/BrowserController.java

@@ -94,10 +94,10 @@ public class BrowserController extends BaseController implements ListingInterfac
     public BrowserController(Bundle args) {
         super(args);
         setHasOptionsMenu(true);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
-        browserType = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_BROWSER_TYPE));
-        activeUser = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_USER_ENTITY));
-        roomToken = args.getString(BundleKeys.KEY_ROOM_TOKEN);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
+        browserType = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_BROWSER_TYPE()));
+        activeUser = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY()));
+        roomToken = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
 
         currentPath = "/";
         if (BrowserType.DAV_BROWSER.equals(browserType)) {
@@ -139,9 +139,9 @@ public class BrowserController extends BaseController implements ListingInterfac
                 iterator.remove();
                 if (paths.size() == 10 || !iterator.hasNext()) {
                     data = new Data.Builder()
-                            .putLong(BundleKeys.KEY_INTERNAL_USER_ID, activeUser.getId())
-                            .putString(BundleKeys.KEY_ROOM_TOKEN, roomToken)
-                            .putStringArray(BundleKeys.KEY_FILE_PATHS, paths.toArray(new String[0]))
+                            .putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), activeUser.getId())
+                            .putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomToken)
+                            .putStringArray(BundleKeys.INSTANCE.getKEY_FILE_PATHS(), paths.toArray(new String[0]))
                             .build();
                     shareWorker = new OneTimeWorkRequest.Builder(ShareOperationWorker.class)
                             .setInputData(data)

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

@@ -46,7 +46,7 @@ import com.nextcloud.talk.jobs.PushRegistrationWorker;
 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;
+import com.nextcloud.talk.models.json.conversations.RoomsOverall;
 import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
 import com.nextcloud.talk.utils.ApiUtils;
 import com.nextcloud.talk.utils.ClosedInterfaceImpl;
@@ -106,14 +106,14 @@ public class AccountVerificationController extends BaseController {
     public AccountVerificationController(Bundle args) {
         super(args);
         if (args != null) {
-            baseUrl = args.getString(BundleKeys.KEY_BASE_URL);
-            username = args.getString(BundleKeys.KEY_USERNAME);
-            token = args.getString(BundleKeys.KEY_TOKEN);
-            if (args.containsKey(BundleKeys.KEY_IS_ACCOUNT_IMPORT)) {
+            baseUrl = args.getString(BundleKeys.INSTANCE.getKEY_BASE_URL());
+            username = args.getString(BundleKeys.INSTANCE.getKEY_USERNAME());
+            token = args.getString(BundleKeys.INSTANCE.getKEY_TOKEN());
+            if (args.containsKey(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT())) {
                 isAccountImport = true;
             }
-            if (args.containsKey(BundleKeys.KEY_ORIGINAL_PROTOCOL)) {
-                originalProtocol = args.getString(BundleKeys.KEY_ORIGINAL_PROTOCOL);
+            if (args.containsKey(BundleKeys.INSTANCE.getKEY_ORIGINAL_PROTOCOL())) {
+                originalProtocol = args.getString(BundleKeys.INSTANCE.getKEY_ORIGINAL_PROTOCOL());
             }
         }
     }
@@ -138,7 +138,7 @@ public class AccountVerificationController extends BaseController {
     @Override
     protected void onViewBound(@NonNull View view) {
         super.onViewBound(view);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         if (getActivity() != null) {
             getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
@@ -384,7 +384,7 @@ public class AccountVerificationController extends BaseController {
 
     private void fetchAndStoreCapabilities() {
         Data userData = new Data.Builder()
-                .putLong(BundleKeys.KEY_INTERNAL_USER_ID, internalAccountId)
+                .putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), internalAccountId)
                 .build();
 
         OneTimeWorkRequest pushNotificationWork = new OneTimeWorkRequest.Builder(CapabilitiesWorker.class)
@@ -395,7 +395,7 @@ public class AccountVerificationController extends BaseController {
 
     private void fetchAndStoreExternalSignalingSettings() {
         Data userData = new Data.Builder()
-                .putLong(BundleKeys.KEY_INTERNAL_USER_ID, internalAccountId)
+                .putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), internalAccountId)
                 .build();
 
         OneTimeWorkRequest signalingSettings = new OneTimeWorkRequest.Builder(SignalingSettingsWorker.class)

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

@@ -63,8 +63,8 @@ import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall;
 import com.nextcloud.talk.models.json.generic.GenericOverall;
 import com.nextcloud.talk.models.json.participants.Participant;
 import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
-import com.nextcloud.talk.models.json.rooms.Conversation;
-import com.nextcloud.talk.models.json.rooms.RoomsOverall;
+import com.nextcloud.talk.models.json.conversations.Conversation;
+import com.nextcloud.talk.models.json.conversations.RoomsOverall;
 import com.nextcloud.talk.models.json.signaling.*;
 import com.nextcloud.talk.models.json.signaling.settings.IceServer;
 import com.nextcloud.talk.models.json.signaling.settings.SignalingSettingsOverall;
@@ -228,17 +228,17 @@ public class CallController extends BaseController {
 
     public CallController(Bundle args) {
         super(args);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
-        roomId = args.getString(BundleKeys.KEY_ROOM_ID, "");
-        roomToken = args.getString(BundleKeys.KEY_ROOM_TOKEN, "");
-        conversationUser = args.getParcelable(BundleKeys.KEY_USER_ENTITY);
-        conversationPassword = args.getString(BundleKeys.KEY_CONVERSATION_PASSWORD, "");
-        isVoiceOnlyCall = args.getBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, false);
+        roomId = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), "");
+        roomToken = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), "");
+        conversationUser = args.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY());
+        conversationPassword = args.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), "");
+        isVoiceOnlyCall = args.getBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), false);
 
         credentials = ApiUtils.getCredentials(conversationUser.getUsername(), conversationUser.getToken());
 
-        baseUrl = args.getString(BundleKeys.KEY_MODIFIED_BASE_URL, "");
+        baseUrl = args.getString(BundleKeys.INSTANCE.getKEY_MODIFIED_BASE_URL(), "");
 
         if (TextUtils.isEmpty(baseUrl)) {
             baseUrl = conversationUser.getBaseUrl();

+ 11 - 11
app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.java

@@ -66,8 +66,8 @@ import com.nextcloud.talk.models.RingtoneSettings;
 import com.nextcloud.talk.models.database.UserEntity;
 import com.nextcloud.talk.models.json.participants.Participant;
 import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
-import com.nextcloud.talk.models.json.rooms.Conversation;
-import com.nextcloud.talk.models.json.rooms.RoomsOverall;
+import com.nextcloud.talk.models.json.conversations.Conversation;
+import com.nextcloud.talk.models.json.conversations.RoomsOverall;
 import com.nextcloud.talk.utils.ApiUtils;
 import com.nextcloud.talk.utils.DisplayUtils;
 import com.nextcloud.talk.utils.DoNotDisturbUtils;
@@ -143,11 +143,11 @@ public class CallNotificationController extends BaseController {
 
     public CallNotificationController(Bundle args) {
         super(args);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
-        this.roomId = args.getString(BundleKeys.KEY_ROOM_ID, "");
-        this.currentConversation = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
-        this.userBeingCalled = args.getParcelable(BundleKeys.KEY_USER_ENTITY);
+        this.roomId = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), "");
+        this.currentConversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
+        this.userBeingCalled = args.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY());
 
         this.originalBundle = args;
         credentials = ApiUtils.getCredentials(userBeingCalled.getUsername(), userBeingCalled.getToken());
@@ -174,18 +174,18 @@ public class CallNotificationController extends BaseController {
 
     @OnClick(R.id.callAnswerCameraView)
     void answerWithCamera() {
-        originalBundle.putBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, false);
+        originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), false);
         proceedToCall();
     }
 
     @OnClick(R.id.callAnswerVoiceOnlyView)
     void answerVoiceOnly() {
-        originalBundle.putBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, true);
+        originalBundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), true);
         proceedToCall();
     }
 
     private void proceedToCall() {
-        originalBundle.putString(BundleKeys.KEY_ROOM_TOKEN, currentConversation.getToken());
+        originalBundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), currentConversation.getToken());
 
         getRouter().replaceTopController(RouterTransaction.with(new CallController(originalBundle))
                 .popChangeHandler(new HorizontalChangeHandler())
@@ -310,7 +310,7 @@ public class CallNotificationController extends BaseController {
             runAllThings();
         }
 
-        if (DoNotDisturbUtils.shouldPlaySound()) {
+        if (DoNotDisturbUtils.INSTANCE.shouldPlaySound()) {
             String callRingtonePreferenceString = appPreferences.getCallRingtoneUri();
             Uri ringtoneUri;
 
@@ -348,7 +348,7 @@ public class CallNotificationController extends BaseController {
             }
         }
 
-        if (DoNotDisturbUtils.shouldVibrate(appPreferences.getShouldVibrateSetting())) {
+        if (DoNotDisturbUtils.INSTANCE.shouldVibrate(appPreferences.getShouldVibrateSetting())) {
             vibrator = (Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
 
             if (vibrator != null) {

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

@@ -2,7 +2,7 @@
  * Nextcloud Talk application
  *
  * @author Mario Danic
- * Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
+ * Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -25,7 +25,6 @@ import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
 import android.content.Intent;
-import android.graphics.Color;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -36,17 +35,23 @@ import android.text.InputFilter;
 import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.Log;
-import android.view.*;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
 import android.widget.AbsListView;
 import android.widget.EditText;
 import android.widget.ImageButton;
 import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
 import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
-import autodagger.AutoInjector;
-import butterknife.BindView;
-import butterknife.OnClick;
+
 import com.bluelinelabs.conductor.RouterTransaction;
 import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
 import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
@@ -72,13 +77,19 @@ import com.nextcloud.talk.models.json.call.Call;
 import com.nextcloud.talk.models.json.call.CallOverall;
 import com.nextcloud.talk.models.json.chat.ChatMessage;
 import com.nextcloud.talk.models.json.chat.ChatOverall;
+import com.nextcloud.talk.models.json.conversations.Conversation;
+import com.nextcloud.talk.models.json.conversations.RoomOverall;
+import com.nextcloud.talk.models.json.conversations.RoomsOverall;
 import com.nextcloud.talk.models.json.generic.GenericOverall;
 import com.nextcloud.talk.models.json.mention.Mention;
-import com.nextcloud.talk.models.json.rooms.Conversation;
-import com.nextcloud.talk.models.json.rooms.RoomOverall;
-import com.nextcloud.talk.models.json.rooms.RoomsOverall;
 import com.nextcloud.talk.presenters.MentionAutocompletePresenter;
-import com.nextcloud.talk.utils.*;
+import com.nextcloud.talk.utils.ApiUtils;
+import com.nextcloud.talk.utils.ConductorRemapping;
+import com.nextcloud.talk.utils.DateUtils;
+import com.nextcloud.talk.utils.DisplayUtils;
+import com.nextcloud.talk.utils.KeyboardUtils;
+import com.nextcloud.talk.utils.MagicCharPolicy;
+import com.nextcloud.talk.utils.NotificationUtils;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
 import com.nextcloud.talk.utils.database.user.UserUtils;
 import com.nextcloud.talk.utils.preferences.AppPreferences;
@@ -103,22 +114,33 @@ import com.vanniktech.emoji.listeners.OnEmojiClickListener;
 import com.vanniktech.emoji.listeners.OnEmojiPopupDismissListener;
 import com.vanniktech.emoji.listeners.OnEmojiPopupShownListener;
 import com.webianks.library.PopupBubble;
-import io.reactivex.Observer;
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.Disposable;
-import io.reactivex.schedulers.Schedulers;
+
 import org.greenrobot.eventbus.EventBus;
 import org.greenrobot.eventbus.Subscribe;
 import org.greenrobot.eventbus.ThreadMode;
 import org.parceler.Parcels;
-import retrofit2.HttpException;
-import retrofit2.Response;
 
-import javax.inject.Inject;
 import java.lang.reflect.Field;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 
+import javax.inject.Inject;
+
+import autodagger.AutoInjector;
+import butterknife.BindView;
+import butterknife.OnClick;
+import io.reactivex.Observer;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+import retrofit2.HttpException;
+import retrofit2.Response;
+
 @AutoInjector(NextcloudTalkApplication.class)
 public class ChatController extends BaseController implements MessagesListAdapter.OnLoadMoreListener,
         MessagesListAdapter.Formatter<Date>, MessagesListAdapter.OnMessageLongClickListener, MessageHolders.ContentChecker {
@@ -146,6 +168,10 @@ public class ChatController extends BaseController implements MessagesListAdapte
     ProgressBar loadingProgressBar;
     @BindView(R.id.smileyButton)
     ImageButton smileyButton;
+    @BindView(R.id.lobby_view)
+    RelativeLayout lobbyView;
+    @BindView(R.id.lobby_text_view)
+    TextView conversationLobbyText;
     private List<Disposable> disposableList = new ArrayList<>();
     private String conversationName;
     private String roomToken;
@@ -167,41 +193,39 @@ public class ChatController extends BaseController implements MessagesListAdapte
     private String roomId;
     private boolean voiceOnly;
     private boolean isFirstMessagesProcessing = true;
-    private boolean havePulledFutureBefore = false;
     private boolean isLeavingForConversation;
     private boolean isLinkPreviewAllowed;
     private boolean wasDetached;
     private EmojiPopup emojiPopup;
 
     private CharSequence myFirstMessage;
-
-    private boolean waitingForFutureResponse = false;
+    private boolean checkingLobbyStatus;
 
     private MenuItem conversationInfoMenuItem;
     private MenuItem conversationVoiceCallMenuItem;
     private MenuItem conversationVideoMenuItem;
 
-    private boolean readOnlyCheckPerformed;
-
     private MagicWebSocketInstance magicWebSocketInstance;
 
+    private Handler lobbyTimerHandler;
+
     public ChatController(Bundle args) {
         super(args);
         setHasOptionsMenu(true);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
-        this.conversationUser = args.getParcelable(BundleKeys.KEY_USER_ENTITY);
-        this.roomId = args.getString(BundleKeys.KEY_ROOM_ID, "");
-        this.roomToken = args.getString(BundleKeys.KEY_ROOM_TOKEN, "");
+        this.conversationUser = args.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY());
+        this.roomId = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), "");
+        this.roomToken = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), "");
 
-        if (args.containsKey(BundleKeys.KEY_ACTIVE_CONVERSATION)) {
-            this.currentConversation = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION));
+        if (args.containsKey(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION())) {
+            this.currentConversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION()));
             if (currentConversation != null) {
                 conversationName = currentConversation.getDisplayName();
             }
         }
 
-        this.roomPassword = args.getString(BundleKeys.KEY_CONVERSATION_PASSWORD, "");
+        this.roomPassword = args.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), "");
 
         if (conversationUser.getUserId().equals("?")) {
             credentials = null;
@@ -209,14 +233,19 @@ public class ChatController extends BaseController implements MessagesListAdapte
             credentials = ApiUtils.getCredentials(conversationUser.getUsername(), conversationUser.getToken());
         }
 
-        if (args.containsKey(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
-            this.startCallFromNotification = args.getBoolean(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL);
+        if (args.containsKey(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL())) {
+            this.startCallFromNotification = args.getBoolean(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL());
         }
 
-        this.voiceOnly = args.getBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, false);
+        this.voiceOnly = args.getBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), false);
     }
 
     private void getRoomInfo() {
+        boolean shouldRepeat = conversationUser.hasSpreedFeatureCapability("webinary-lobby");
+        if (shouldRepeat) {
+            checkingLobbyStatus = true;
+        }
+
         ncApi.getRoom(credentials, ApiUtils.getRoom(conversationUser.getBaseUrl(), roomToken))
                 .subscribeOn(Schedulers.io())
                 .observeOn(AndroidSchedulers.mainThread())
@@ -228,12 +257,28 @@ public class ChatController extends BaseController implements MessagesListAdapte
 
                     @Override
                     public void onNext(RoomOverall roomOverall) {
+                        Conversation oldConversation = null;
+
+                        if (currentConversation != null) {
+                            oldConversation = currentConversation;
+                        }
+
                         currentConversation = roomOverall.getOcs().getData();
-                        conversationName = currentConversation.getDisplayName();
-                        setTitle();
 
-                        setupMentionAutocomplete();
-                        joinRoomWithPassword();
+                        if (oldConversation == null) {
+                            conversationName = currentConversation.getDisplayName();
+                            setTitle();
+                            setupMentionAutocomplete();
+                        }
+
+                        checkReadOnlyState();
+                        if (oldConversation == null || (!oldConversation.getLobbyState().equals(currentConversation.getLobbyState()) || !oldConversation.getLobbyTimer().equals(currentConversation.getLobbyTimer()))) {
+                            checkLobbyState(oldConversation != null && (!oldConversation.getLobbyState().equals(currentConversation.getLobbyState())));
+                        }
+
+                        if (oldConversation == null) {
+                            joinRoomWithPassword();
+                        }
 
                     }
 
@@ -244,7 +289,13 @@ public class ChatController extends BaseController implements MessagesListAdapte
 
                     @Override
                     public void onComplete() {
+                        if (shouldRepeat) {
+                            if (lobbyTimerHandler == null) {
+                                lobbyTimerHandler = new Handler();
+                            }
 
+                            lobbyTimerHandler.postDelayed(() -> getRoomInfo(), 5000);
+                        }
                     }
                 });
     }
@@ -265,6 +316,8 @@ public class ChatController extends BaseController implements MessagesListAdapte
                             if (roomId.equals(conversation.getRoomId())) {
                                 roomToken = conversation.getToken();
                                 currentConversation = conversation;
+                                checkLobbyState(false);
+                                checkReadOnlyState();
                                 conversationName = conversation.getDisplayName();
                                 setTitle();
                                 break;
@@ -377,10 +430,10 @@ public class ChatController extends BaseController implements MessagesListAdapte
 
 
         InputFilter[] filters = new InputFilter[1];
-        int lenghtFilter = conversationUser.getMessageMaxLength();
+        int lengthFilter = conversationUser.getMessageMaxLength();
 
 
-        filters[0] = new InputFilter.LengthFilter(lenghtFilter);
+        filters[0] = new InputFilter.LengthFilter(lengthFilter);
         messageInput.setFilters(filters);
 
         messageInput.addTextChangedListener(new TextWatcher() {
@@ -391,8 +444,8 @@ public class ChatController extends BaseController implements MessagesListAdapte
 
             @Override
             public void onTextChanged(CharSequence s, int start, int before, int count) {
-                if (s.length() >= lenghtFilter) {
-                    messageInput.setError(String.format(Objects.requireNonNull(getResources()).getString(R.string.nc_limit_hit), Integer.toString(lenghtFilter)));
+                if (s.length() >= lengthFilter) {
+                    messageInput.setError(String.format(Objects.requireNonNull(getResources()).getString(R.string.nc_limit_hit), Integer.toString(lengthFilter)));
                 } else {
                     messageInput.setError(null);
                 }
@@ -433,6 +486,10 @@ public class ChatController extends BaseController implements MessagesListAdapte
             getActivity().findViewById(R.id.toolbar).setOnClickListener(v -> showConversationInfoScreen());
         }
 
+        if (currentConversation != null) {
+            checkLobbyState(false);
+        }
+
         if (adapterWasNull) {
             // we're starting
             if (TextUtils.isEmpty(roomToken)) {
@@ -448,19 +505,16 @@ public class ChatController extends BaseController implements MessagesListAdapte
 
 
     private void checkReadOnlyState() {
-        if (currentConversation != null && !readOnlyCheckPerformed) {
-
-            readOnlyCheckPerformed = true;
-            if (currentConversation.getConversationReadOnlyState() != null && currentConversation.getConversationReadOnlyState().equals(Conversation.ConversationReadOnlyState.CONVERSATION_READ_ONLY)) {
-                messageInput.setHint(R.string.nc_readonly_hint);
+        if (currentConversation != null) {
+            if (currentConversation.shouldShowLobby(conversationUser) || (currentConversation.getConversationReadOnlyState() != null && currentConversation.getConversationReadOnlyState().equals(Conversation.ConversationReadOnlyState.CONVERSATION_READ_ONLY))) {
 
                 conversationVoiceCallMenuItem.getIcon().setAlpha(99);
                 conversationVideoMenuItem.getIcon().setAlpha(99);
+                if (messageInputView != null) {
+                    messageInputView.setVisibility(View.GONE);
+                }
 
-                setChildrenState(messageInputView, false);
             } else {
-                messageInput.setHint("");
-
                 if (conversationVoiceCallMenuItem != null) {
                     conversationVoiceCallMenuItem.getIcon().setAlpha(255);
                 }
@@ -468,38 +522,57 @@ public class ChatController extends BaseController implements MessagesListAdapte
                 if (conversationVideoMenuItem != null) {
                     conversationVideoMenuItem.getIcon().setAlpha(255);
                 }
-                
-                setChildrenState(messageInputView, true);
+
+                if (messageInputView != null) {
+                    if (currentConversation.shouldShowLobby(conversationUser)) {
+                        messageInputView.setVisibility(View.GONE);
+                    } else {
+                        messageInputView.setVisibility(View.VISIBLE);
+                    }
+                }
             }
         }
     }
 
-    private void setChildrenState(View view, boolean enabled) {
-        if (view.getId() != R.id.messageSendButton) {
-            view.setEnabled(enabled);
-        }
+    private void checkLobbyState(boolean lobbyStateChanged) {
+        if (currentConversation != null) {
 
-        if (enabled) {
-            view.setAlpha(1.0f);
-        } else {
-            view.setAlpha(0.38f);
-        }
+            if (!checkingLobbyStatus) {
+                getRoomInfo();
+            }
 
-        if (view instanceof ViewGroup) {
-            ViewGroup viewGroup = (ViewGroup) view;
-            for (int i = 0; i < viewGroup.getChildCount(); i++) {
-                View child = viewGroup.getChildAt(i);
-                setChildrenState(child, enabled);
+            if (currentConversation.shouldShowLobby(conversationUser)) {
+                lobbyView.setVisibility(View.VISIBLE);
+                messagesListView.setVisibility(View.GONE);
+                messageInputView.setVisibility(View.GONE);
+                loadingProgressBar.setVisibility(View.GONE);
+
+                if (currentConversation.getLobbyTimer() != null && currentConversation.getLobbyTimer() != 0) {
+                    conversationLobbyText.setText(String.format(getResources().getString(R.string.nc_lobby_waiting_with_date), DateUtils.INSTANCE.getLocalDateStringFromTimestampForLobby(currentConversation.getLobbyTimer())));
+                } else {
+                    conversationLobbyText.setText(R.string.nc_lobby_waiting);
+                }
+            } else {
+                lobbyView.setVisibility(View.GONE);
+                messagesListView.setVisibility(View.VISIBLE);
+                messageInput.setVisibility(View.VISIBLE);
+                if (lobbyStateChanged) {
+                    loadingProgressBar.setVisibility(View.VISIBLE);
+                    if (isFirstMessagesProcessing) {
+                        pullChatMessages(0);
+                    } else {
+                        pullChatMessages(1);
+                    }
+                }
             }
         }
     }
 
-
     private void showBrowserScreen(BrowserController.BrowserType browserType) {
         Bundle bundle = new Bundle();
-        bundle.putParcelable(BundleKeys.KEY_BROWSER_TYPE, Parcels.wrap(browserType));
-        bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap(conversationUser));
-        bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomToken);
+        bundle.putParcelable(BundleKeys.INSTANCE.getKEY_BROWSER_TYPE(), Parcels.wrap(browserType));
+        bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), Parcels.wrap(conversationUser));
+        bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomToken);
         getRouter().pushController((RouterTransaction.with(new BrowserController(bundle))
                 .pushChangeHandler(new VerticalChangeHandler())
                 .popChangeHandler(new VerticalChangeHandler())));
@@ -507,8 +580,8 @@ public class ChatController extends BaseController implements MessagesListAdapte
 
     private void showConversationInfoScreen() {
         Bundle bundle = new Bundle();
-        bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, conversationUser);
-        bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomToken);
+        bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), conversationUser);
+        bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomToken);
         getRouter().pushController((RouterTransaction.with(new ConversationInfoController(bundle))
                 .pushChangeHandler(new HorizontalChangeHandler())
                 .popChangeHandler(new HorizontalChangeHandler())));
@@ -689,7 +762,8 @@ public class ChatController extends BaseController implements MessagesListAdapte
                             currentCall = callOverall.getOcs().getData();
                             ApplicationWideCurrentRoomHolder.getInstance().setSession(currentCall.getSessionId());
                             startPing();
-                            havePulledFutureBefore = false;
+
+                            checkLobbyState(false);
 
                             setupWebsocket();
 
@@ -751,6 +825,12 @@ public class ChatController extends BaseController implements MessagesListAdapte
                     public void onNext(GenericOverall genericOverall) {
                         dispose();
 
+                        checkingLobbyStatus = false;
+
+                        if (lobbyTimerHandler != null) {
+                            lobbyTimerHandler.removeCallbacksAndMessages(null);
+                        }
+
                         if (magicWebSocketInstance != null && currentCall != null) {
                             magicWebSocketInstance.joinRoomWithRoomTokenAndSession("", currentCall.getSessionId());
                         }
@@ -858,23 +938,14 @@ public class ChatController extends BaseController implements MessagesListAdapte
             return;
         }
 
-        if (havePulledFutureBefore && lookIntoFuture == 1 && magicWebSocketInstance != null ) {
+        if (currentConversation.shouldShowLobby(conversationUser)) {
             return;
         }
 
         if (lookIntoFuture > 0) {
-            if (waitingForFutureResponse) {
-                return;
-            } else {
-                waitingForFutureResponse = true;
-            }
-
             lookingIntoFuture = true;
-            havePulledFutureBefore = true;
         }
 
-        lookIntoFuture = lookIntoFuture > 0 ? 1 : 0;
-
         Map<String, Integer> fieldMap = new HashMap<>();
         fieldMap.put("lookIntoFuture", lookIntoFuture);
         fieldMap.put("limit", 25);
@@ -906,19 +977,17 @@ public class ChatController extends BaseController implements MessagesListAdapte
 
                             @Override
                             public void onNext(Response response) {
-                                waitingForFutureResponse = false;
                                 processMessages(response, true);
                             }
 
                             @Override
                             public void onError(Throwable e) {
-                                waitingForFutureResponse = false;
 
                             }
 
                             @Override
                             public void onComplete() {
-                                if (magicWebSocketInstance == null) {
+                                if (currentConversation.shouldShowLobby(conversationUser)) {
                                     pullChatMessages(1);
                                 }
                             }
@@ -1116,7 +1185,6 @@ public class ChatController extends BaseController implements MessagesListAdapte
     @Override
     public void onPrepareOptionsMenu(@NonNull Menu menu) {
         super.onPrepareOptionsMenu(menu);
-
         if (conversationUser.hasSpreedFeatureCapability("read-only-rooms")) {
             checkReadOnlyState();
         }
@@ -1167,14 +1235,14 @@ public class ChatController extends BaseController implements MessagesListAdapte
     private Intent getIntentForCall(boolean isVoiceOnlyCall) {
         if (currentConversation != null) {
             Bundle bundle = new Bundle();
-            bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomToken);
-            bundle.putString(BundleKeys.KEY_ROOM_ID, roomId);
-            bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, conversationUser);
-            bundle.putString(BundleKeys.KEY_CONVERSATION_PASSWORD, roomPassword);
-            bundle.putString(BundleKeys.KEY_MODIFIED_BASE_URL, conversationUser.getBaseUrl());
+            bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomToken);
+            bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), roomId);
+            bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), conversationUser);
+            bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), roomPassword);
+            bundle.putString(BundleKeys.INSTANCE.getKEY_MODIFIED_BASE_URL(), conversationUser.getBaseUrl());
 
             if (isVoiceOnlyCall) {
-                bundle.putBoolean(BundleKeys.KEY_CALL_VOICE_ONLY, true);
+                bundle.putBoolean(BundleKeys.INSTANCE.getKEY_CALL_VOICE_ONLY(), true);
             }
 
             if (getActivity() != null) {
@@ -1215,8 +1283,10 @@ public class ChatController extends BaseController implements MessagesListAdapte
 
     @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onMessageEvent(WebSocketCommunicationEvent webSocketCommunicationEvent) {
+        /*
         switch (webSocketCommunicationEvent.getType()) {
             case "refreshChat":
+
                 if (webSocketCommunicationEvent.getHashMap().get(BundleKeys.KEY_INTERNAL_USER_ID).equals(Long.toString(conversationUser.getId()))) {
                     if (roomToken.equals(webSocketCommunicationEvent.getHashMap().get(BundleKeys.KEY_ROOM_TOKEN))) {
                         pullChatMessages(2);
@@ -1224,7 +1294,7 @@ public class ChatController extends BaseController implements MessagesListAdapte
                 }
                 break;
             default:
-        }
+        }*/
     }
 
     @Subscribe(threadMode = ThreadMode.BACKGROUND)
@@ -1248,16 +1318,16 @@ public class ChatController extends BaseController implements MessagesListAdapte
                         public void onNext(RoomOverall roomOverall) {
                             Intent conversationIntent = new Intent(getActivity(), MagicCallActivity.class);
                             Bundle bundle = new Bundle();
-                            bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, conversationUser);
-                            bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.getOcs().getData().getToken());
-                            bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.getOcs().getData().getRoomId());
+                            bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), conversationUser);
+                            bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomOverall.getOcs().getData().getToken());
+                            bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), roomOverall.getOcs().getData().getRoomId());
 
                             if (conversationUser.hasSpreedFeatureCapability("chat-v2")) {
-                                bundle.putParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION,
+                                bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(),
                                         Parcels.wrap(roomOverall.getOcs().getData()));
                                 conversationIntent.putExtras(bundle);
 
-                                ConductorRemapping.remapChatController(getRouter(), conversationUser.getId(),
+                                ConductorRemapping.INSTANCE.remapChatController(getRouter(), conversationUser.getId(),
                                         roomOverall.getOcs().getData().getToken(), bundle, false);
 
                             } else {

+ 19 - 19
app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java

@@ -64,8 +64,8 @@ import com.nextcloud.talk.models.database.UserEntity;
 import com.nextcloud.talk.models.json.autocomplete.AutocompleteOverall;
 import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser;
 import com.nextcloud.talk.models.json.participants.Participant;
-import com.nextcloud.talk.models.json.rooms.Conversation;
-import com.nextcloud.talk.models.json.rooms.RoomOverall;
+import com.nextcloud.talk.models.json.conversations.Conversation;
+import com.nextcloud.talk.models.json.conversations.RoomOverall;
 import com.nextcloud.talk.models.json.sharees.Sharee;
 import com.nextcloud.talk.models.json.sharees.ShareesOverall;
 import com.nextcloud.talk.utils.ApiUtils;
@@ -170,7 +170,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
     public ContactsController(Bundle args) {
         super(args);
         setHasOptionsMenu(true);
-        if (args.containsKey(BundleKeys.KEY_NEW_CONVERSATION)) {
+        if (args.containsKey(BundleKeys.INSTANCE.getKEY_NEW_CONVERSATION())) {
             isNewConversationView = true;
         }
 
@@ -196,7 +196,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
     @Override
     protected void onViewBound(@NonNull View view) {
         super.onViewBound(view);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         currentUser = userUtils.getCurrentUser();
 
@@ -259,15 +259,15 @@ public class ContactsController extends BaseController implements SearchView.OnQ
                         public void onNext(RoomOverall roomOverall) {
                             Intent conversationIntent = new Intent(getActivity(), MagicCallActivity.class);
                             Bundle bundle = new Bundle();
-                            bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, currentUser);
-                            bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.getOcs().getData().getToken());
-                            bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.getOcs().getData().getRoomId());
+                            bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), currentUser);
+                            bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomOverall.getOcs().getData().getToken());
+                            bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), roomOverall.getOcs().getData().getRoomId());
 
                             if (currentUser.hasSpreedFeatureCapability("chat-v2")) {
-                                bundle.putParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION,
+                                bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(),
                                         Parcels.wrap(roomOverall.getOcs().getData()));
 
-                                ConductorRemapping.remapChatController(getRouter(), currentUser.getId(),
+                                ConductorRemapping.INSTANCE.remapChatController(getRouter(), currentUser.getId(),
                                         roomOverall.getOcs().getData().getToken(), bundle, true);
                             } else {
                                 conversationIntent.putExtras(bundle);
@@ -306,10 +306,10 @@ public class ContactsController extends BaseController implements SearchView.OnQ
             ArrayList<String> groupIdsArray = new ArrayList<>(selectedGroupIds);
 
 
-            bundle.putParcelable(BundleKeys.KEY_CONVERSATION_TYPE, Parcels.wrap(roomType));
-            bundle.putStringArrayList(BundleKeys.KEY_INVITED_PARTICIPANTS, userIdsArray);
-            bundle.putStringArrayList(BundleKeys.KEY_INVITED_GROUP, groupIdsArray);
-            bundle.putInt(BundleKeys.KEY_OPERATION_CODE, 11);
+            bundle.putParcelable(BundleKeys.INSTANCE.getKEY_CONVERSATION_TYPE(), Parcels.wrap(roomType));
+            bundle.putStringArrayList(BundleKeys.INSTANCE.getKEY_INVITED_PARTICIPANTS(), userIdsArray);
+            bundle.putStringArrayList(BundleKeys.INSTANCE.getKEY_INVITED_GROUP(), groupIdsArray);
+            bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), 11);
             prepareAndShowBottomSheetWithBundle(bundle, true);
         }
     }
@@ -839,16 +839,16 @@ public class ContactsController extends BaseController implements SearchView.OnQ
                                 if (getActivity() != null) {
                                     Intent conversationIntent = new Intent(getActivity(), MagicCallActivity.class);
                                     Bundle bundle = new Bundle();
-                                    bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, currentUser);
-                                    bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.getOcs().getData().getToken());
-                                    bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.getOcs().getData().getRoomId());
+                                    bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), currentUser);
+                                    bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomOverall.getOcs().getData().getToken());
+                                    bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), roomOverall.getOcs().getData().getRoomId());
                                     conversationIntent.putExtras(bundle);
 
                                     if (currentUser.hasSpreedFeatureCapability("chat-v2")) {
-                                        bundle.putParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION,
+                                        bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(),
                                                 Parcels.wrap(roomOverall.getOcs().getData()));
 
-                                        ConductorRemapping.remapChatController(getRouter(), currentUser.getId(),
+                                        ConductorRemapping.INSTANCE.remapChatController(getRouter(), currentUser.getId(),
                                                 roomOverall.getOcs().getData().getToken(), bundle, true);
                                     } else {
                                         startActivity(conversationIntent);
@@ -914,7 +914,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
     @OnClick(R.id.joinConversationViaLinkRelativeLayout)
     void joinConversationViaLink() {
         Bundle bundle = new Bundle();
-        bundle.putInt(BundleKeys.KEY_OPERATION_CODE, 10);
+        bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), 10);
 
         prepareAndShowBottomSheetWithBundle(bundle, true);
     }

+ 0 - 507
app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.java

@@ -1,507 +0,0 @@
-/*
- * 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.controllers;
-
-import android.app.Activity;
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-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;
-import com.nextcloud.talk.R;
-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;
-import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
-import com.nextcloud.talk.models.json.rooms.Conversation;
-import com.nextcloud.talk.models.json.rooms.RoomOverall;
-import com.nextcloud.talk.utils.ApiUtils;
-import com.nextcloud.talk.utils.DisplayUtils;
-import com.nextcloud.talk.utils.bundle.BundleKeys;
-import com.nextcloud.talk.utils.preferences.preferencestorage.DatabaseStorageModule;
-import com.yarolegovich.lovelydialog.LovelySaveStateHandler;
-import com.yarolegovich.lovelydialog.LovelyStandardDialog;
-import com.yarolegovich.mp.*;
-import eu.davidea.flexibleadapter.FlexibleAdapter;
-import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager;
-import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
-import io.reactivex.Observer;
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.Disposable;
-import io.reactivex.schedulers.Schedulers;
-
-import javax.inject.Inject;
-import java.util.ArrayList;
-import java.util.List;
-
-
-@AutoInjector(NextcloudTalkApplication.class)
-public class ConversationInfoController extends BaseController {
-
-    private static final int ID_DELETE_CONVERSATION_DIALOG = 0;
-
-    @BindView(R.id.notification_settings)
-    MaterialPreferenceScreen materialPreferenceScreen;
-    @BindView(R.id.progressBar)
-    ProgressBar progressBar;
-    @BindView(R.id.conversation_info_message_notifications)
-    MaterialChoicePreference messageNotificationLevel;
-    @BindView(R.id.conversation_info_name)
-    MaterialPreferenceCategory nameCategoryView;
-    @BindView(R.id.avatar_image)
-    SimpleDraweeView conversationAvatarImageView;
-    @BindView(R.id.display_name_text)
-    TextView conversationDisplayName;
-    @BindView(R.id.participants_list_category)
-    MaterialPreferenceCategory participantsListCategory;
-    @BindView(R.id.recycler_view)
-    RecyclerView recyclerView;
-    @BindView(R.id.deleteConversationAction)
-    MaterialStandardPreference deleteConversationAction;
-    @BindView(R.id.leaveConversationAction)
-    MaterialStandardPreference leaveConversationAction;
-    @BindView(R.id.ownOptions)
-    MaterialPreferenceCategory ownOptionsCategory;
-    @BindView(R.id.muteCalls)
-    MaterialSwitchPreference muteCalls;
-
-    @Inject
-    NcApi ncApi;
-    @Inject
-    Context context;
-
-    private String conversationToken;
-    private UserEntity conversationUser;
-    private String credentials;
-    private Disposable roomDisposable;
-    private Disposable participantsDisposable;
-
-    private Conversation conversation;
-
-    private FlexibleAdapter<AbstractFlexibleItem> adapter;
-    private List<AbstractFlexibleItem> recyclerViewItems = new ArrayList<>();
-
-    private LovelySaveStateHandler saveStateHandler;
-
-    public ConversationInfoController(Bundle args) {
-        super(args);
-        setHasOptionsMenu(true);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
-        conversationUser = args.getParcelable(BundleKeys.KEY_USER_ENTITY);
-        conversationToken = args.getString(BundleKeys.KEY_ROOM_TOKEN);
-        credentials = ApiUtils.getCredentials(conversationUser.getUsername(), conversationUser.getToken());
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
-        switch (item.getItemId()) {
-            case android.R.id.home:
-                getRouter().popCurrentController();
-                return true;
-            default:
-                return super.onOptionsItemSelected(item);
-        }
-    }
-
-    @Override
-    protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
-        return inflater.inflate(R.layout.controller_conversation_info, container, false);
-    }
-
-    @Override
-    protected void onViewBound(@NonNull View view) {
-        super.onViewBound(view);
-
-        if (saveStateHandler == null) {
-            saveStateHandler = new LovelySaveStateHandler();
-        }
-
-        materialPreferenceScreen.setStorageModule(new DatabaseStorageModule(conversationUser, conversationToken));
-        if (adapter == null) {
-            fetchRoomInfo();
-        } else {
-            loadConversationAvatar();
-            materialPreferenceScreen.setVisibility(View.VISIBLE);
-            nameCategoryView.setVisibility(View.VISIBLE);
-            participantsListCategory.setVisibility(View.VISIBLE);
-            progressBar.setVisibility(View.GONE);
-            conversationDisplayName.setText(conversation.getDisplayName());
-            setupAdapter();
-        }
-    }
-
-    private void showLovelyDialog(int dialogId, Bundle savedInstanceState) {
-        switch (dialogId) {
-            case ID_DELETE_CONVERSATION_DIALOG:
-                showDeleteConversationDialog(savedInstanceState);
-                break;
-            default:
-                break;
-        }
-    }
-
-
-    private void showDeleteConversationDialog(Bundle savedInstanceState) {
-        if (getActivity() != null) {
-            new LovelyStandardDialog(getActivity(), LovelyStandardDialog.ButtonLayout.HORIZONTAL)
-                    .setTopColorRes(R.color.nc_darkRed)
-                    .setIcon(DisplayUtils.getTintedDrawable(context.getResources(),
-                            R.drawable.ic_delete_black_24dp, R.color.bg_default))
-                    .setPositiveButtonColor(context.getResources().getColor(R.color.nc_darkRed))
-                    .setTitle(R.string.nc_delete_call)
-                    .setMessage(conversation.getDeleteWarningMessage())
-                    .setPositiveButton(R.string.nc_delete, new View.OnClickListener() {
-                        @Override
-                        public void onClick(View v) {
-                            deleteConversation();
-                        }
-                    })
-                    .setNegativeButton(R.string.nc_cancel, null)
-                    .setInstanceStateHandler(ID_DELETE_CONVERSATION_DIALOG, saveStateHandler)
-                    .setSavedInstanceState(savedInstanceState)
-                    .show();
-        }
-    }
-
-    @Override
-    protected void onSaveViewState(@NonNull View view, @NonNull Bundle outState) {
-        saveStateHandler.saveInstanceState(outState);
-        super.onSaveViewState(view, outState);
-    }
-
-    @Override
-    protected void onRestoreViewState(@NonNull View view, @NonNull Bundle savedViewState) {
-        super.onRestoreViewState(view, savedViewState);
-        if (LovelySaveStateHandler.wasDialogOnScreen(savedViewState)) {
-            //Dialog won't be restarted automatically, so we need to call this method.
-            //Each dialog knows how to restore its state
-            showLovelyDialog(LovelySaveStateHandler.getSavedDialogId(savedViewState), savedViewState);
-        }
-    }
-
-    private void setupAdapter() {
-        Activity activity;
-
-        if ((activity = getActivity()) != null) {
-            if (adapter == null) {
-                adapter = new FlexibleAdapter<>(recyclerViewItems, activity, true);
-            }
-
-            if (recyclerView != null) {
-                SmoothScrollLinearLayoutManager layoutManager =
-                        new SmoothScrollLinearLayoutManager(activity);
-                recyclerView.setLayoutManager(layoutManager);
-                recyclerView.setHasFixedSize(true);
-                recyclerView.setAdapter(adapter);
-            }
-        }
-    }
-
-    private void handleParticipants(List<Participant> participants) {
-        UserItem userItem;
-        Participant participant;
-
-        recyclerViewItems = new ArrayList<>();
-        UserItem ownUserItem = null;
-
-        for (int i = 0; i < participants.size(); i++) {
-            participant = participants.get(i);
-            userItem = new UserItem(participant, conversationUser, null);
-            userItem.setEnabled(!participant.getSessionId().equals("0"));
-            if (!TextUtils.isEmpty(participant.getUserId()) && participant.getUserId().equals(conversationUser.getUserId())) {
-                ownUserItem = userItem;
-                userItem.getModel().setSessionId("-1");
-                userItem.setEnabled(true);
-            } else {
-                recyclerViewItems.add(userItem);
-            }
-        }
-
-
-        if (ownUserItem != null) {
-            recyclerViewItems.add(0, ownUserItem);
-        }
-
-        setupAdapter();
-
-        if (participantsListCategory != null) {
-            participantsListCategory.setVisibility(View.VISIBLE);
-        }
-        adapter.notifyDataSetChanged();
-    }
-
-    @Override
-    protected String getTitle() {
-        return getResources().getString(R.string.nc_conversation_menu_conversation_info);
-    }
-
-    private void getListOfParticipants() {
-        ncApi.getPeersForCall(credentials, ApiUtils.getUrlForParticipants(conversationUser.getBaseUrl(), conversationToken))
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribe(new Observer<ParticipantsOverall>() {
-                    @Override
-                    public void onSubscribe(Disposable d) {
-                        participantsDisposable = d;
-                    }
-
-                    @Override
-                    public void onNext(ParticipantsOverall participantsOverall) {
-                        handleParticipants(participantsOverall.getOcs().getData());
-                    }
-
-                    @Override
-                    public void onError(Throwable e) {
-
-                    }
-
-                    @Override
-                    public void onComplete() {
-                        participantsDisposable.dispose();
-                    }
-                });
-
-    }
-
-    @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();
-        }
-    }
-
-    private void deleteConversation() {
-        Data data;
-        if ((data = getWorkerData()) != null) {
-            OneTimeWorkRequest deleteConversationWorker =
-                    new OneTimeWorkRequest.Builder(DeleteConversationWorker.class).setInputData(data).build();
-            WorkManager.getInstance().enqueue(deleteConversationWorker);
-            popTwoLastControllers();
-        }
-    }
-
-    @OnClick(R.id.deleteConversationAction)
-    void deleteConversationClick() {
-        showDeleteConversationDialog(null);
-    }
-
-    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 = backstack.subList(0, backstack.size() - 2);
-        getRouter().setBackstack(backstack, new HorizontalChangeHandler());
-    }
-
-    private void fetchRoomInfo() {
-        ncApi.getRoom(credentials, ApiUtils.getRoom(conversationUser.getBaseUrl(), conversationToken))
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribe(new Observer<RoomOverall>() {
-                    @Override
-                    public void onSubscribe(Disposable d) {
-                        roomDisposable = d;
-                    }
-
-                    @Override
-                    public void onNext(RoomOverall roomOverall) {
-                        conversation = roomOverall.getOcs().getData();
-
-                        if (isAttached() && (!isBeingDestroyed() || !isDestroyed())) {
-                            ownOptionsCategory.setVisibility(View.VISIBLE);
-
-                            if (leaveConversationAction != null) {
-                                if (!conversation.canLeave(conversationUser)) {
-                                    leaveConversationAction.setVisibility(View.GONE);
-                                } else {
-                                    leaveConversationAction.setVisibility(View.VISIBLE);
-                                }
-                            }
-
-                            if (!conversation.canModerate(conversationUser)) {
-                                deleteConversationAction.setVisibility(View.GONE);
-                            } else {
-                                deleteConversationAction.setVisibility(View.VISIBLE);
-                            }
-
-                            if (Conversation.ConversationType.ROOM_SYSTEM.equals(conversation.getType())) {
-                                muteCalls.setVisibility(View.GONE);
-                            }
-
-                            getListOfParticipants();
-
-                            if (progressBar != null) {
-                                progressBar.setVisibility(View.GONE);
-                            }
-
-                            if (nameCategoryView != null) {
-                                nameCategoryView.setVisibility(View.VISIBLE);
-                            }
-
-                            if (conversationDisplayName != null) {
-                                conversationDisplayName.setText(conversation.getDisplayName());
-                            }
-
-                            loadConversationAvatar();
-
-                            if (conversationUser.hasSpreedFeatureCapability("notification-levels")) {
-                                if (messageNotificationLevel != null) {
-                                    messageNotificationLevel.setEnabled(true);
-                                    messageNotificationLevel.setAlpha(1.0f);
-                                }
-
-                                if (!conversation.getNotificationLevel().equals(Conversation.NotificationLevel.DEFAULT)) {
-                                    String stringValue;
-                                    switch (new EnumNotificationLevelConverter().convertToInt(conversation.getNotificationLevel())) {
-                                        case 1:
-                                            stringValue = "always";
-                                            break;
-                                        case 2:
-                                            stringValue = "mention";
-                                            break;
-                                        case 3:
-                                            stringValue = "never";
-                                            break;
-                                        default:
-                                            stringValue = "mention";
-                                            break;
-                                    }
-
-                                    if (messageNotificationLevel != null) {
-                                        messageNotificationLevel.setValue(stringValue);
-                                    }
-                                } else {
-                                    setProperNotificationValue(conversation);
-                                }
-                            } else {
-                                if (messageNotificationLevel != null) {
-                                    messageNotificationLevel.setEnabled(false);
-                                    messageNotificationLevel.setAlpha(0.38f);
-                                }
-                                setProperNotificationValue(conversation);
-                            }
-
-                            materialPreferenceScreen.setVisibility(View.VISIBLE);
-                        }
-                    }
-
-                    @Override
-                    public void onError(Throwable e) {
-
-                    }
-
-                    @Override
-                    public void onComplete() {
-                        roomDisposable.dispose();
-                    }
-                });
-    }
-
-    private void setProperNotificationValue(Conversation conversation) {
-        if (messageNotificationLevel != null) {
-            if (conversation.getType().equals(Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL)) {
-                // hack to see if we get mentioned always or just on mention
-                if (conversationUser.hasSpreedFeatureCapability("mention-flag")) {
-                    messageNotificationLevel.setValue("always");
-                } else {
-                    messageNotificationLevel.setValue("mention");
-                }
-            } else {
-                messageNotificationLevel.setValue("mention");
-            }
-        }
-    }
-
-    private void loadConversationAvatar() {
-        if (conversationAvatarImageView != null) {
-            switch (conversation.getType()) {
-                case ROOM_TYPE_ONE_TO_ONE_CALL:
-                    if (!TextUtils.isEmpty(conversation.getName())) {
-                        DraweeController draweeController = Fresco.newDraweeControllerBuilder()
-                                .setOldController(conversationAvatarImageView.getController())
-                                .setAutoPlayAnimations(true)
-                                .setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(conversationUser.getBaseUrl(),
-                                        conversation.getName(), R.dimen.avatar_size_big), null))
-                                .build();
-                        conversationAvatarImageView.setController(draweeController);
-                    }
-                    break;
-                case ROOM_GROUP_CALL:
-                    conversationAvatarImageView.getHierarchy().setPlaceholderImage(DisplayUtils
-                            .getRoundedBitmapDrawableFromVectorDrawableResource(getResources(),
-                                    R.drawable.ic_people_group_white_24px));
-                    break;
-                case ROOM_PUBLIC_CALL:
-                    conversationAvatarImageView.getHierarchy().setPlaceholderImage(DisplayUtils
-                            .getRoundedBitmapDrawableFromVectorDrawableResource(getResources(),
-                                    R.drawable.ic_link_white_24px));
-                    break;
-                case ROOM_SYSTEM:
-                        Drawable[] layers = new Drawable[2];
-                        layers[0] = context.getDrawable(R.drawable.ic_launcher_background);
-                        layers[1] = context.getDrawable(R.drawable.ic_launcher_foreground);
-                        LayerDrawable layerDrawable = new LayerDrawable(layers);
-                        conversationAvatarImageView.getHierarchy().setPlaceholderImage(DisplayUtils.getRoundedDrawable(layerDrawable));
-
-                default:
-                    break;
-            }
-        }
-    }
-}

+ 552 - 0
app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt

@@ -0,0 +1,552 @@
+/*
+ * 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.controllers
+
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.LayerDrawable
+import android.os.Bundle
+import android.text.TextUtils
+import android.view.LayoutInflater
+import android.view.MenuItem
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ProgressBar
+import android.widget.TextView
+import androidx.appcompat.widget.SwitchCompat
+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.afollestad.materialdialogs.LayoutMode.WRAP_CONTENT
+import com.afollestad.materialdialogs.MaterialDialog
+import com.afollestad.materialdialogs.bottomsheets.BottomSheet
+import com.afollestad.materialdialogs.datetime.dateTimePicker
+import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
+import com.facebook.drawee.backends.pipeline.Fresco
+import com.facebook.drawee.view.SimpleDraweeView
+import com.nextcloud.talk.R
+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.conversations.Conversation
+import com.nextcloud.talk.models.json.conversations.RoomOverall
+import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter
+import com.nextcloud.talk.models.json.generic.GenericOverall
+import com.nextcloud.talk.models.json.participants.Participant
+import com.nextcloud.talk.models.json.participants.ParticipantsOverall
+import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateUtils
+import com.nextcloud.talk.utils.DisplayUtils
+import com.nextcloud.talk.utils.bundle.BundleKeys
+import com.nextcloud.talk.utils.preferences.preferencestorage.DatabaseStorageModule
+import com.yarolegovich.lovelydialog.LovelySaveStateHandler
+import com.yarolegovich.lovelydialog.LovelyStandardDialog
+import com.yarolegovich.mp.*
+import eu.davidea.flexibleadapter.FlexibleAdapter
+import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
+import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
+import io.reactivex.Observer
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.Disposable
+import io.reactivex.schedulers.Schedulers
+import java.util.*
+import javax.inject.Inject
+
+
+@AutoInjector(NextcloudTalkApplication::class)
+class ConversationInfoController(args: Bundle) : BaseController(args) {
+
+    @BindView(R.id.notification_settings)
+    lateinit var materialPreferenceScreen: MaterialPreferenceScreen
+    @BindView(R.id.progressBar)
+    lateinit var progressBar: ProgressBar
+    @BindView(R.id.conversation_info_message_notifications)
+    lateinit var messageNotificationLevel: MaterialChoicePreference
+    @BindView(R.id.webinar_settings)
+    lateinit var conversationInfoWebinar: MaterialPreferenceScreen
+    @BindView(R.id.conversation_info_lobby)
+    lateinit var conversationInfoLobby: MaterialSwitchPreference
+    @BindView(R.id.conversation_info_name)
+    lateinit var nameCategoryView: MaterialPreferenceCategory
+    @BindView(R.id.start_time_preferences)
+    lateinit var startTimeView: MaterialStandardPreference
+    @BindView(R.id.avatar_image)
+    lateinit var conversationAvatarImageView: SimpleDraweeView
+    @BindView(R.id.display_name_text)
+    lateinit var conversationDisplayName: TextView
+    @BindView(R.id.participants_list_category)
+    lateinit var participantsListCategory: MaterialPreferenceCategory
+    @BindView(R.id.recycler_view)
+    lateinit var recyclerView: RecyclerView
+    @BindView(R.id.deleteConversationAction)
+    lateinit var deleteConversationAction: MaterialStandardPreference
+    @BindView(R.id.leaveConversationAction)
+    lateinit var leaveConversationAction: MaterialStandardPreference
+    @BindView(R.id.ownOptions)
+    lateinit var ownOptionsCategory: MaterialPreferenceCategory
+    @BindView(R.id.muteCalls)
+    lateinit var muteCalls: MaterialSwitchPreference
+
+    @set:Inject
+    lateinit var ncApi: NcApi
+    @set:Inject
+    lateinit var context: Context
+
+    private val conversationToken: String?
+    private val conversationUser: UserEntity?
+    private val credentials: String?
+    private var roomDisposable: Disposable? = null
+    private var participantsDisposable: Disposable? = null
+
+    private var conversation: Conversation? = null
+
+    private var adapter: FlexibleAdapter<AbstractFlexibleItem<*>>? = null
+    private var recyclerViewItems: MutableList<AbstractFlexibleItem<*>> = ArrayList()
+
+    private var saveStateHandler: LovelySaveStateHandler? = null
+
+    private val workerData: Data?
+        get() {
+            if (!TextUtils.isEmpty(conversationToken) && conversationUser != null) {
+                val data = Data.Builder()
+                data.putString(BundleKeys.KEY_ROOM_TOKEN, conversationToken)
+                data.putLong(BundleKeys.KEY_INTERNAL_USER_ID, conversationUser.id)
+                return data.build()
+            }
+
+            return null
+        }
+
+    init {
+        setHasOptionsMenu(true)
+        NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
+        conversationUser = args.getParcelable(BundleKeys.KEY_USER_ENTITY)
+        conversationToken = args.getString(BundleKeys.KEY_ROOM_TOKEN)
+        credentials = ApiUtils.getCredentials(conversationUser!!.username, conversationUser.token)
+    }
+
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        when (item.itemId) {
+            android.R.id.home -> {
+                router.popCurrentController()
+                return true
+            }
+            else -> return super.onOptionsItemSelected(item)
+        }
+    }
+
+    override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
+        return inflater.inflate(R.layout.controller_conversation_info, container, false)
+    }
+
+    override fun onViewBound(view: View) {
+        super.onViewBound(view)
+
+        if (saveStateHandler == null) {
+            saveStateHandler = LovelySaveStateHandler()
+        }
+
+        val databaseStorageModule = DatabaseStorageModule(conversationUser!!,
+                conversationToken)
+
+        materialPreferenceScreen.setStorageModule(databaseStorageModule)
+        conversationInfoWebinar.setStorageModule(databaseStorageModule)
+
+        if (adapter == null) {
+            fetchRoomInfo()
+        } else {
+            loadConversationAvatar()
+            materialPreferenceScreen.visibility = View.VISIBLE
+            nameCategoryView.visibility = View.VISIBLE
+            participantsListCategory.visibility = View.VISIBLE
+            progressBar.visibility = View.GONE
+            conversationDisplayName.text = conversation!!.displayName
+
+            setupWebinaryView()
+            setupAdapter()
+        }
+    }
+
+    private fun setupWebinaryView() {
+        if (conversationUser!!.hasSpreedFeatureCapability("webinary-lobby") && (conversation!!.type
+                        == Conversation.ConversationType.ROOM_GROUP_CALL || conversation!!.type ==
+                        Conversation.ConversationType.ROOM_PUBLIC_CALL) && conversation!!.canModerate(conversationUser)) {
+            conversationInfoWebinar.visibility = View.VISIBLE
+
+            val isLobbyOpenToModeratorsOnly = conversation!!.lobbyState == Conversation.LobbyState.LOBBY_STATE_MODERATORS_ONLY
+            (conversationInfoLobby.findViewById<View>(R.id.mp_checkable) as SwitchCompat)
+                    .isChecked = isLobbyOpenToModeratorsOnly
+
+            reconfigureLobbyTimerView()
+
+            val currentTimeCalendar = Calendar.getInstance()
+            if (conversation!!.lobbyTimer != null && conversation!!.lobbyTimer != 0L) {
+                currentTimeCalendar.set(Calendar.MILLISECOND, (conversation!!.lobbyTimer * 1000).toInt())
+            }
+
+            startTimeView.setOnClickListener {
+                MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
+                    dateTimePicker(minDateTime = Calendar.getInstance(), requireFutureDateTime =
+                    true, currentDateTime = currentTimeCalendar, dateTimeCallback = { _,
+                                                                                      dateTime ->
+                        reconfigureLobbyTimerView(dateTime)
+                        submitLobbyChanges()
+                    })
+                }
+            }
+
+            (conversationInfoLobby.findViewById<View>(R.id.mp_checkable) as SwitchCompat).setOnCheckedChangeListener { _, _ ->
+                reconfigureLobbyTimerView()
+                submitLobbyChanges()
+            }
+        } else {
+            conversationInfoWebinar.visibility = View.GONE
+        }
+    }
+
+    fun reconfigureLobbyTimerView(dateTime: Calendar? = null) {
+        val isChecked = (conversationInfoLobby.findViewById<View>(R.id.mp_checkable) as SwitchCompat).isChecked
+
+        if (dateTime != null && isChecked) {
+            conversation!!.lobbyTimer = dateTime.timeInMillis / 1000
+        } else if (!isChecked) {
+            conversation!!.lobbyTimer = 0
+        }
+
+        conversation!!.lobbyState = if (isChecked) Conversation.LobbyState
+                .LOBBY_STATE_MODERATORS_ONLY else Conversation.LobbyState.LOBBY_STATE_ALL_PARTICIPANTS
+
+        if (conversation!!.lobbyTimer != null && conversation!!.lobbyTimer != java.lang.Long.MIN_VALUE && conversation!!.lobbyTimer != 0L) {
+            startTimeView.setSummary(DateUtils.getLocalDateStringFromTimestampForLobby(conversation!!.lobbyTimer))
+        } else {
+            startTimeView.setSummary(R.string.nc_manual)
+        }
+
+        if (isChecked) {
+            startTimeView.visibility = View.VISIBLE
+        } else {
+            startTimeView.visibility = View.GONE
+        }
+    }
+
+    fun submitLobbyChanges() {
+        val state = if ((conversationInfoLobby.findViewById<View>(R.id
+                        .mp_checkable) as SwitchCompat).isChecked) 1 else 0
+        ncApi.setLobbyForConversation(ApiUtils.getCredentials(conversationUser!!.username,
+                conversationUser.token), ApiUtils.getUrlForLobbyForConversation
+        (conversationUser.baseUrl, conversation!!.token), state, conversation!!.lobbyTimer)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(object : Observer<GenericOverall> {
+                    override fun onComplete() {
+                    }
+
+                    override fun onSubscribe(d: Disposable) {
+                    }
+
+                    override fun onNext(t: GenericOverall) {
+                    }
+
+                    override fun onError(e: Throwable) {
+                    }
+
+                })
+    }
+
+    private fun showLovelyDialog(dialogId: Int, savedInstanceState: Bundle) {
+        when (dialogId) {
+            ID_DELETE_CONVERSATION_DIALOG -> showDeleteConversationDialog(savedInstanceState)
+            else -> {
+            }
+        }
+    }
+
+
+    private fun showDeleteConversationDialog(savedInstanceState: Bundle?) {
+        if (activity != null) {
+            LovelyStandardDialog(activity, LovelyStandardDialog.ButtonLayout.HORIZONTAL)
+                    .setTopColorRes(R.color.nc_darkRed)
+                    .setIcon(DisplayUtils.getTintedDrawable(context!!.resources,
+                            R.drawable.ic_delete_black_24dp, R.color.bg_default))
+                    .setPositiveButtonColor(context!!.resources.getColor(R.color.nc_darkRed))
+                    .setTitle(R.string.nc_delete_call)
+                    .setMessage(conversation!!.deleteWarningMessage)
+                    .setPositiveButton(R.string.nc_delete) { deleteConversation() }
+                    .setNegativeButton(R.string.nc_cancel, null)
+                    .setInstanceStateHandler(ID_DELETE_CONVERSATION_DIALOG, saveStateHandler!!)
+                    .setSavedInstanceState(savedInstanceState)
+                    .show()
+        }
+    }
+
+    override fun onSaveViewState(view: View, outState: Bundle) {
+        saveStateHandler!!.saveInstanceState(outState)
+        super.onSaveViewState(view, outState)
+    }
+
+    override fun onRestoreViewState(view: View, savedViewState: Bundle) {
+        super.onRestoreViewState(view, savedViewState)
+        if (LovelySaveStateHandler.wasDialogOnScreen(savedViewState)) {
+            //Dialog won't be restarted automatically, so we need to call this method.
+            //Each dialog knows how to restore its state
+            showLovelyDialog(LovelySaveStateHandler.getSavedDialogId(savedViewState), savedViewState)
+        }
+    }
+
+    private fun setupAdapter() {
+        if (activity != null) {
+            if (adapter == null) {
+                adapter = FlexibleAdapter(recyclerViewItems, activity, true)
+            }
+
+            val layoutManager = SmoothScrollLinearLayoutManager(activity)
+            recyclerView.layoutManager = layoutManager
+            recyclerView.setHasFixedSize(true)
+            recyclerView.adapter = adapter
+        }
+    }
+
+    private fun handleParticipants(participants: List<Participant>) {
+        var userItem: UserItem
+        var participant: Participant
+
+        recyclerViewItems = ArrayList()
+        var ownUserItem: UserItem? = null
+
+        for (i in participants.indices) {
+            participant = participants[i]
+            userItem = UserItem(participant, conversationUser, null)
+            userItem.isEnabled = participant.sessionId != "0"
+            if (!TextUtils.isEmpty(participant.userId) && participant.userId == conversationUser!!.userId) {
+                ownUserItem = userItem
+                userItem.model.sessionId = "-1"
+                userItem.isEnabled = true
+            } else {
+                recyclerViewItems.add(userItem)
+            }
+        }
+
+
+        if (ownUserItem != null) {
+            recyclerViewItems.add(0, ownUserItem)
+        }
+
+        setupAdapter()
+
+        participantsListCategory.visibility = View.VISIBLE
+        adapter!!.notifyDataSetChanged()
+    }
+
+    override fun getTitle(): String? {
+        return resources!!.getString(R.string.nc_conversation_menu_conversation_info)
+    }
+
+    private fun getListOfParticipants() {
+        ncApi!!.getPeersForCall(credentials, ApiUtils.getUrlForParticipants(conversationUser!!.baseUrl, conversationToken))
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(object : Observer<ParticipantsOverall> {
+                    override fun onSubscribe(d: Disposable) {
+                        participantsDisposable = d
+                    }
+
+                    override fun onNext(participantsOverall: ParticipantsOverall) {
+                        handleParticipants(participantsOverall.ocs.data)
+                    }
+
+                    override fun onError(e: Throwable) {
+
+                    }
+
+                    override fun onComplete() {
+                        participantsDisposable!!.dispose()
+                    }
+                })
+
+    }
+
+    @OnClick(R.id.leaveConversationAction)
+    internal fun leaveConversation() {
+        workerData?.let {
+            WorkManager.getInstance().enqueue(OneTimeWorkRequest.Builder
+            (LeaveConversationWorker::class
+                    .java).setInputData(it).build()
+            )
+            popTwoLastControllers()
+        }
+    }
+
+    private fun deleteConversation() {
+        workerData?.let {
+            WorkManager.getInstance().enqueue(OneTimeWorkRequest.Builder
+            (DeleteConversationWorker::class.java).setInputData(it).build())
+            popTwoLastControllers()
+        }
+    }
+
+    @OnClick(R.id.deleteConversationAction)
+    internal fun deleteConversationClick() {
+        showDeleteConversationDialog(null)
+    }
+
+    private fun popTwoLastControllers() {
+        var backstack = router.backstack
+        backstack = backstack.subList(0, backstack.size - 2)
+        router.setBackstack(backstack, HorizontalChangeHandler())
+    }
+
+    private fun fetchRoomInfo() {
+        ncApi!!.getRoom(credentials, ApiUtils.getRoom(conversationUser!!.baseUrl, conversationToken))
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(object : Observer<RoomOverall> {
+                    override fun onSubscribe(d: Disposable) {
+                        roomDisposable = d
+                    }
+
+                    override fun onNext(roomOverall: RoomOverall) {
+                        conversation = roomOverall.ocs.data
+
+                        if (isAttached && (!isBeingDestroyed || !isDestroyed)) {
+                            ownOptionsCategory.visibility = View.VISIBLE
+
+                            setupWebinaryView()
+
+                            if (!conversation!!.canLeave(conversationUser)) {
+                                leaveConversationAction.visibility = View.GONE
+                            } else {
+                                leaveConversationAction.visibility = View.VISIBLE
+                            }
+
+                            if (!conversation!!.canModerate(conversationUser)) {
+                                deleteConversationAction.visibility = View.GONE
+                            } else {
+                                deleteConversationAction.visibility = View.VISIBLE
+                            }
+
+                            if (Conversation.ConversationType.ROOM_SYSTEM == conversation!!.type) {
+                                muteCalls.visibility = View.GONE
+                            }
+
+                            getListOfParticipants()
+
+                            progressBar.visibility = View.GONE
+
+                            nameCategoryView.visibility = View.VISIBLE
+
+                            conversationDisplayName.text = conversation!!.displayName
+
+
+                            loadConversationAvatar()
+
+                            if (conversationUser.hasSpreedFeatureCapability("notification-levels")) {
+                                messageNotificationLevel.isEnabled = true
+                                messageNotificationLevel.alpha = 1.0f
+
+                                if (conversation!!.notificationLevel != Conversation.NotificationLevel.DEFAULT) {
+                                    val stringValue: String = when (EnumNotificationLevelConverter().convertToInt(conversation!!.notificationLevel)) {
+                                        1 -> "always"
+                                        2 -> "mention"
+                                        3 -> "never"
+                                        else -> "mention"
+                                    }
+
+                                    messageNotificationLevel.value = stringValue
+                                } else {
+                                    setProperNotificationValue(conversation)
+                                }
+                            } else {
+                                messageNotificationLevel.isEnabled = false
+                                messageNotificationLevel.alpha = 0.38f
+                                setProperNotificationValue(conversation)
+                            }
+
+                            materialPreferenceScreen.visibility = View.VISIBLE
+                        }
+                    }
+
+                    override fun onError(e: Throwable) {
+
+                    }
+
+                    override fun onComplete() {
+                        roomDisposable!!.dispose()
+                    }
+                })
+    }
+
+    private fun setProperNotificationValue(conversation: Conversation?) {
+        if (conversation!!.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
+            // hack to see if we get mentioned always or just on mention
+            if (conversationUser!!.hasSpreedFeatureCapability("mention-flag")) {
+                messageNotificationLevel.value = "always"
+            } else {
+                messageNotificationLevel.value = "mention"
+            }
+        } else {
+            messageNotificationLevel.value = "mention"
+        }
+    }
+
+    private fun loadConversationAvatar() {
+        when (conversation!!.type) {
+            Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (!TextUtils.isEmpty
+                    (conversation!!.name)) {
+                val draweeController = Fresco.newDraweeControllerBuilder()
+                        .setOldController(conversationAvatarImageView.controller)
+                        .setAutoPlayAnimations(true)
+                        .setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(conversationUser!!.baseUrl,
+                                conversation!!.name, R.dimen.avatar_size_big), null))
+                        .build()
+                conversationAvatarImageView.controller = draweeController
+            }
+            Conversation.ConversationType.ROOM_GROUP_CALL -> conversationAvatarImageView.hierarchy.setPlaceholderImage(DisplayUtils
+                    .getRoundedBitmapDrawableFromVectorDrawableResource(resources,
+                            R.drawable.ic_people_group_white_24px))
+            Conversation.ConversationType.ROOM_PUBLIC_CALL -> conversationAvatarImageView.hierarchy.setPlaceholderImage(DisplayUtils
+                    .getRoundedBitmapDrawableFromVectorDrawableResource(resources,
+                            R.drawable.ic_link_white_24px))
+            Conversation.ConversationType.ROOM_SYSTEM -> {
+                val layers = arrayOfNulls<Drawable>(2)
+                layers[0] = context!!.getDrawable(R.drawable.ic_launcher_background)
+                layers[1] = context!!.getDrawable(R.drawable.ic_launcher_foreground)
+                val layerDrawable = LayerDrawable(layers)
+                conversationAvatarImageView.hierarchy.setPlaceholderImage(DisplayUtils.getRoundedDrawable(layerDrawable))
+            }
+
+            else -> {
+            }
+        }
+    }
+
+    companion object {
+
+        private const val ID_DELETE_CONVERSATION_DIALOG = 0
+    }
+}

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

@@ -77,7 +77,7 @@ import com.nextcloud.talk.interfaces.ConversationMenuInterface;
 import com.nextcloud.talk.jobs.DeleteConversationWorker;
 import com.nextcloud.talk.models.database.UserEntity;
 import com.nextcloud.talk.models.json.participants.Participant;
-import com.nextcloud.talk.models.json.rooms.Conversation;
+import com.nextcloud.talk.models.json.conversations.Conversation;
 import com.nextcloud.talk.utils.ApiUtils;
 import com.nextcloud.talk.utils.ConductorRemapping;
 import com.nextcloud.talk.utils.DisplayUtils;
@@ -184,7 +184,7 @@ public class ConversationsListController extends BaseController implements Searc
     @Override
     protected void onViewBound(@NonNull View view) {
         super.onViewBound(view);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         if (getActionBar() != null) {
             getActionBar().show();
@@ -462,7 +462,7 @@ public class ConversationsListController extends BaseController implements Searc
 
     private void showNewConversationsScreen() {
         Bundle bundle = new Bundle();
-        bundle.putBoolean(BundleKeys.KEY_NEW_CONVERSATION, true);
+        bundle.putBoolean(BundleKeys.INSTANCE.getKEY_NEW_CONVERSATION(), true);
         getRouter().pushController((RouterTransaction.with(new ContactsController(bundle))
                 .pushChangeHandler(new HorizontalChangeHandler())
                 .popChangeHandler(new HorizontalChangeHandler())));
@@ -556,8 +556,8 @@ public class ConversationsListController extends BaseController implements Searc
     public void onMessageEvent(MoreMenuClickEvent moreMenuClickEvent) {
         Bundle bundle = new Bundle();
         Conversation conversation = moreMenuClickEvent.getConversation();
-        bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(conversation));
-        bundle.putParcelable(BundleKeys.KEY_MENU_TYPE, Parcels.wrap(CallMenuController.MenuType.REGULAR));
+        bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
+        bundle.putParcelable(BundleKeys.INSTANCE.getKEY_MENU_TYPE(), Parcels.wrap(CallMenuController.MenuType.REGULAR));
 
         prepareAndShowBottomSheetWithBundle(bundle, true);
     }
@@ -612,20 +612,20 @@ public class ConversationsListController extends BaseController implements Searc
 
 
             Bundle bundle = new Bundle();
-            bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, currentUser);
-            bundle.putString(BundleKeys.KEY_ROOM_TOKEN, conversation.getToken());
-            bundle.putString(BundleKeys.KEY_ROOM_ID, conversation.getRoomId());
+            bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), currentUser);
+            bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), conversation.getToken());
+            bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), conversation.getRoomId());
 
             if (conversation.hasPassword && (conversation.participantType.equals(Participant.ParticipantType.GUEST) ||
                     conversation.participantType.equals(Participant.ParticipantType.USER_FOLLOWING_LINK))) {
-                bundle.putInt(BundleKeys.KEY_OPERATION_CODE, 99);
+                bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), 99);
                 prepareAndShowBottomSheetWithBundle(bundle, false);
             } else {
                 currentUser = userUtils.getCurrentUser();
 
                 if (currentUser.hasSpreedFeatureCapability("chat-v2")) {
-                    bundle.putParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION, Parcels.wrap(conversation));
-                    ConductorRemapping.remapChatController(getRouter(), currentUser.getId(),
+                    bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(), Parcels.wrap(conversation));
+                    ConductorRemapping.INSTANCE.remapChatController(getRouter(), currentUser.getId(),
                             conversation.getToken(), bundle, false);
                 } else {
                     overridePushHandler(new NoOpControllerChangeHandler());
@@ -674,10 +674,10 @@ public class ConversationsListController extends BaseController implements Searc
     }
 
     private void showDeleteConversationDialog(Bundle savedInstanceState) {
-        if (getActivity() != null && conversationMenuBundle != null && currentUser != null && conversationMenuBundle.getLong(BundleKeys.KEY_INTERNAL_USER_ID) == currentUser.getId()) {
+        if (getActivity() != null && conversationMenuBundle != null && currentUser != null && conversationMenuBundle.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID()) == currentUser.getId()) {
 
             Conversation conversation =
-                    Parcels.unwrap(conversationMenuBundle.getParcelable(BundleKeys.KEY_ROOM));
+                    Parcels.unwrap(conversationMenuBundle.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
 
             if (conversation != null) {
                 new LovelyStandardDialog(getActivity(), LovelyStandardDialog.ButtonLayout.HORIZONTAL)
@@ -691,9 +691,9 @@ public class ConversationsListController extends BaseController implements Searc
                             @Override
                             public void onClick(View v) {
                                 Data.Builder data = new Data.Builder();
-                                data.putLong(BundleKeys.KEY_INTERNAL_USER_ID,
-                                        conversationMenuBundle.getLong(BundleKeys.KEY_INTERNAL_USER_ID));
-                                data.putString(BundleKeys.KEY_ROOM_TOKEN, conversation.getToken());
+                                data.putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(),
+                                        conversationMenuBundle.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID()));
+                                data.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), conversation.getToken());
                                 conversationMenuBundle = null;
                                 deleteConversation(data.build());
                             }

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

@@ -63,7 +63,7 @@ public class LockedController extends BaseController {
     @Override
     protected void onViewBound(@NonNull View view) {
         super.onViewBound(view);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
         if (getActionBar() != null) {
             getActionBar().hide();
         }

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

@@ -85,7 +85,7 @@ public class RingtoneSelectionController extends BaseController implements Flexi
     public RingtoneSelectionController(Bundle args) {
         super(args);
         setHasOptionsMenu(true);
-        this.callNotificationSounds = args.getBoolean(BundleKeys.KEY_ARE_CALL_SOUNDS, false);
+        this.callNotificationSounds = args.getBoolean(BundleKeys.INSTANCE.getKEY_ARE_CALL_SOUNDS(), false);
     }
 
     @Override
@@ -96,7 +96,7 @@ public class RingtoneSelectionController extends BaseController implements Flexi
     @Override
     protected void onViewBound(@NonNull View view) {
         super.onViewBound(view);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         if (adapter == null) {
             adapter = new FlexibleAdapter<>(abstractFlexibleItemList, getActivity(), false);

+ 9 - 9
app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.java

@@ -111,7 +111,7 @@ public class ServerSelectionController extends BaseController {
     @Override
     protected void onViewBound(@NonNull View view) {
         super.onViewBound(view);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         if (getActivity() != null) {
             getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
@@ -134,7 +134,7 @@ public class ServerSelectionController extends BaseController {
         } else {
             if ((TextUtils.isEmpty(getResources
                     ().getString(R.string.nc_import_account_type)) ||
-                    AccountUtils.findAccounts(userUtils.getUsers()).size() == 0) &&
+                    AccountUtils.INSTANCE.findAccounts(userUtils.getUsers()).size() == 0) &&
                     userUtils.getUsers().size() == 0) {
 
                 providersTextView.setText(R.string.nc_get_from_provider);
@@ -143,20 +143,20 @@ public class ServerSelectionController extends BaseController {
                             .getString(R.string.nc_providers_url)));
                     startActivity(browserIntent);
                 });
-            } else if (AccountUtils.findAccounts(userUtils.getUsers()).size() > 0) {
-                if (!TextUtils.isEmpty(AccountUtils.getAppNameBasedOnPackage(getResources()
+            } else if (AccountUtils.INSTANCE.findAccounts(userUtils.getUsers()).size() > 0) {
+                if (!TextUtils.isEmpty(AccountUtils.INSTANCE.getAppNameBasedOnPackage(getResources()
                         .getString(R.string.nc_import_accounts_from)))) {
-                    if (AccountUtils.findAccounts(userUtils.getUsers()).size() > 1) {
+                    if (AccountUtils.INSTANCE.findAccounts(userUtils.getUsers()).size() > 1) {
                         providersTextView.setText(String.format(getResources().getString(R.string
-                                .nc_server_import_accounts), AccountUtils.getAppNameBasedOnPackage(getResources()
+                                .nc_server_import_accounts), AccountUtils.INSTANCE.getAppNameBasedOnPackage(getResources()
                                 .getString(R.string.nc_import_accounts_from))));
                     } else {
                         providersTextView.setText(String.format(getResources().getString(R.string
-                                .nc_server_import_account), AccountUtils.getAppNameBasedOnPackage(getResources()
+                                .nc_server_import_account), AccountUtils.INSTANCE.getAppNameBasedOnPackage(getResources()
                                 .getString(R.string.nc_import_accounts_from))));
                     }
                 } else {
-                    if (AccountUtils.findAccounts(userUtils.getUsers()).size() > 1) {
+                    if (AccountUtils.INSTANCE.findAccounts(userUtils.getUsers()).size() > 1) {
                         providersTextView.setText(getResources().getString(R.string.nc_server_import_accounts_plain));
                     } else {
                         providersTextView.setText(getResources().getString(R.string
@@ -166,7 +166,7 @@ public class ServerSelectionController extends BaseController {
 
                 providersTextView.setOnClickListener(view13 -> {
                     Bundle bundle = new Bundle();
-                    bundle.putBoolean(BundleKeys.KEY_IS_ACCOUNT_IMPORT, true);
+                    bundle.putBoolean(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT(), true);
                     getRouter().pushController(RouterTransaction.with(
                             new SwitchAccountController(bundle))
                             .pushChangeHandler(new HorizontalChangeHandler())

+ 6 - 8
app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java

@@ -138,8 +138,6 @@ public class SettingsController extends BaseController {
     @BindView(R.id.message_text)
     TextView messageText;
     @Inject
-    EventBus eventBus;
-    @Inject
     AppPreferences appPreferences;
     @Inject
     NcApi ncApi;
@@ -176,7 +174,7 @@ public class SettingsController extends BaseController {
         setHasOptionsMenu(true);
 
         ViewCompat.setTransitionName(avatarImageView, "userAvatar.transitionTag");
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         getCurrentUser();
 
@@ -209,7 +207,7 @@ public class SettingsController extends BaseController {
             licenceButton.setVisibility(View.GONE);
         }
 
-        if (!DoNotDisturbUtils.hasVibrator()) {
+        if (!DoNotDisturbUtils.INSTANCE.hasVibrator()) {
             shouldVibrateSwitchPreference.setVisibility(View.GONE);
         }
 
@@ -251,7 +249,7 @@ public class SettingsController extends BaseController {
 
         settingsCallSound.setOnClickListener(v -> {
             Bundle bundle = new Bundle();
-            bundle.putBoolean(BundleKeys.KEY_ARE_CALL_SOUNDS, true);
+            bundle.putBoolean(BundleKeys.INSTANCE.getKEY_ARE_CALL_SOUNDS(), true);
             getRouter().pushController(RouterTransaction.with(new RingtoneSelectionController(bundle))
                     .pushChangeHandler(new HorizontalChangeHandler())
                     .popChangeHandler(new HorizontalChangeHandler()));
@@ -259,7 +257,7 @@ public class SettingsController extends BaseController {
 
         settingsMessageSound.setOnClickListener(v -> {
             Bundle bundle = new Bundle();
-            bundle.putBoolean(BundleKeys.KEY_ARE_CALL_SOUNDS, false);
+            bundle.putBoolean(BundleKeys.INSTANCE.getKEY_ARE_CALL_SOUNDS(), false);
             getRouter().pushController(RouterTransaction.with(new RingtoneSelectionController(bundle))
                     .pushChangeHandler(new HorizontalChangeHandler())
                     .popChangeHandler(new HorizontalChangeHandler()));
@@ -325,7 +323,7 @@ public class SettingsController extends BaseController {
     @OnClick(R.id.settings_version)
     void sendLogs() {
         if (getResources().getBoolean(R.bool.nc_is_debug)) {
-            LoggingUtils.sendMailWithAttachment(context);
+            LoggingUtils.INSTANCE.sendMailWithAttachment(context);
         }
     }
 
@@ -774,7 +772,7 @@ public class SettingsController extends BaseController {
     private class ThemeChangeListener implements OnPreferenceValueChangedListener<String> {
         @Override
         public void onChanged(String newValue) {
-            NextcloudTalkApplication.setAppTheme(newValue);
+            NextcloudTalkApplication.Companion.setAppTheme(newValue);
         }
     }
 }

+ 9 - 9
app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java

@@ -137,7 +137,7 @@ public class SwitchAccountController extends BaseController {
         super(args);
         setHasOptionsMenu(true);
 
-        if (args.containsKey(BundleKeys.KEY_IS_ACCOUNT_IMPORT)) {
+        if (args.containsKey(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT())) {
             isAccountImport = true;
         }
     }
@@ -161,7 +161,7 @@ public class SwitchAccountController extends BaseController {
     @Override
     protected void onViewBound(@NonNull View view) {
         super.onViewBound(view);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
         swipeRefreshLayout.setEnabled(false);
 
         if (getActionBar() != null) {
@@ -198,9 +198,9 @@ public class SwitchAccountController extends BaseController {
             } else {
                 Account account;
                 ImportAccount importAccount;
-                for (Object accountObject : AccountUtils.findAccounts(userUtils.getUsers())) {
+                for (Object accountObject : AccountUtils.INSTANCE.findAccounts(userUtils.getUsers())) {
                     account = (Account) accountObject;
-                    importAccount = AccountUtils.getInformationFromAccount(account);
+                    importAccount = AccountUtils.INSTANCE.getInformationFromAccount(account);
 
                     participant = new Participant();
                     participant.setName(importAccount.getUsername());
@@ -230,12 +230,12 @@ public class SwitchAccountController extends BaseController {
     }
 
     private void reauthorizeFromImport(Account account) {
-        ImportAccount importAccount = AccountUtils.getInformationFromAccount(account);
+        ImportAccount importAccount = AccountUtils.INSTANCE.getInformationFromAccount(account);
         Bundle bundle = new Bundle();
-        bundle.putString(BundleKeys.KEY_BASE_URL, importAccount.getBaseUrl());
-        bundle.putString(BundleKeys.KEY_USERNAME, importAccount.getUsername());
-        bundle.putString(BundleKeys.KEY_TOKEN, importAccount.getToken());
-        bundle.putBoolean(BundleKeys.KEY_IS_ACCOUNT_IMPORT, true);
+        bundle.putString(BundleKeys.INSTANCE.getKEY_BASE_URL(), importAccount.getBaseUrl());
+        bundle.putString(BundleKeys.INSTANCE.getKEY_USERNAME(), importAccount.getUsername());
+        bundle.putString(BundleKeys.INSTANCE.getKEY_TOKEN(), importAccount.getToken());
+        bundle.putBoolean(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT(), true);
         getRouter().pushController(RouterTransaction.with(new AccountVerificationController(bundle))
                 .pushChangeHandler(new HorizontalChangeHandler())
                 .popChangeHandler(new HorizontalChangeHandler()));

+ 5 - 5
app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.java

@@ -149,7 +149,7 @@ public class WebViewLoginController extends BaseController {
     @Override
     protected void onViewBound(@NonNull View view) {
         super.onViewBound(view);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         if (getActivity() != null) {
             getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
@@ -364,9 +364,9 @@ public class WebViewLoginController extends BaseController {
 
             if (!isPasswordUpdate && finalMessageType == null) {
                 Bundle bundle = new Bundle();
-                bundle.putString(BundleKeys.KEY_USERNAME, loginData.getUsername());
-                bundle.putString(BundleKeys.KEY_TOKEN, loginData.getToken());
-                bundle.putString(BundleKeys.KEY_BASE_URL, loginData.getServerUrl());
+                bundle.putString(BundleKeys.INSTANCE.getKEY_USERNAME(), loginData.getUsername());
+                bundle.putString(BundleKeys.INSTANCE.getKEY_TOKEN(), loginData.getToken());
+                bundle.putString(BundleKeys.INSTANCE.getKEY_BASE_URL(), loginData.getServerUrl());
                 String protocol = "";
 
                 if (baseUrl.startsWith("http://")) {
@@ -376,7 +376,7 @@ public class WebViewLoginController extends BaseController {
                 }
 
                 if (!TextUtils.isEmpty(protocol)) {
-                    bundle.putString(BundleKeys.KEY_ORIGINAL_PROTOCOL, protocol);
+                    bundle.putString(BundleKeys.INSTANCE.getKEY_ORIGINAL_PROTOCOL(), protocol);
                 }
 
                 getRouter().pushController(RouterTransaction.with(new AccountVerificationController

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

@@ -75,7 +75,7 @@ public abstract class BaseController extends ButterKnifeController {
     }
 
     private void cleanTempCertPreference() {
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         List<String> temporaryClassNames = new ArrayList<>();
         temporaryClassNames.add(ServerSelectionController.class.getName());

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

@@ -49,7 +49,7 @@ import com.nextcloud.talk.events.BottomSheetLockEvent;
 import com.nextcloud.talk.interfaces.ConversationMenuInterface;
 import com.nextcloud.talk.jobs.LeaveConversationWorker;
 import com.nextcloud.talk.models.database.UserEntity;
-import com.nextcloud.talk.models.json.rooms.Conversation;
+import com.nextcloud.talk.models.json.conversations.Conversation;
 import com.nextcloud.talk.utils.DisplayUtils;
 import com.nextcloud.talk.utils.ShareUtils;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
@@ -87,17 +87,17 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
 
     public CallMenuController(Bundle args) {
         super(args);
-        this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
-        if (args.containsKey(BundleKeys.KEY_MENU_TYPE)) {
-            this.menuType = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_MENU_TYPE));
+        this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
+        if (args.containsKey(BundleKeys.INSTANCE.getKEY_MENU_TYPE())) {
+            this.menuType = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_MENU_TYPE()));
         }
     }
 
     public CallMenuController(Bundle args, @Nullable ConversationMenuInterface conversationMenuInterface) {
         super(args);
-        this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
-        if (args.containsKey(BundleKeys.KEY_MENU_TYPE)) {
-            this.menuType = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_MENU_TYPE));
+        this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
+        if (args.containsKey(BundleKeys.INSTANCE.getKEY_MENU_TYPE())) {
+            this.menuType = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_MENU_TYPE()));
         }
         this.conversationMenuInterface = conversationMenuInterface;
     }
@@ -110,7 +110,7 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
     @Override
     protected void onViewBound(@NonNull View view) {
         super.onViewBound(view);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
         prepareViews();
     }
 
@@ -218,7 +218,7 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
     @Override
     public boolean onItemClick(View view, int position) {
         Bundle bundle = new Bundle();
-        bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(conversation));
+        bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
 
         if (menuType.equals(MenuType.REGULAR)) {
             MenuItem menuItem = (MenuItem) adapter.getItem(position);
@@ -246,7 +246,7 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
                         }
                         eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
                     } else {
-                        bundle.putInt(BundleKeys.KEY_OPERATION_CODE, tag);
+                        bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), tag);
                         if (tag != 2 && tag != 4 && tag != 6 && tag != 7) {
                             eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
                             getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
@@ -257,7 +257,7 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
                                     .pushChangeHandler(new HorizontalChangeHandler())
                                     .popChangeHandler(new HorizontalChangeHandler()));
                         } else {
-                            bundle.putParcelable(BundleKeys.KEY_MENU_TYPE, Parcels.wrap(MenuType.SHARE));
+                            bundle.putParcelable(BundleKeys.INSTANCE.getKEY_MENU_TYPE(), Parcels.wrap(MenuType.SHARE));
                             getRouter().pushController(RouterTransaction.with(new CallMenuController(bundle, null))
                                     .pushChangeHandler(new HorizontalChangeHandler())
                                     .popChangeHandler(new HorizontalChangeHandler()));
@@ -277,10 +277,10 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
                     eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
                     getActivity().startActivity(intent);
                 } else {
-                    bundle.putInt(BundleKeys.KEY_OPERATION_CODE, 7);
-                    bundle.putParcelable(BundleKeys.KEY_SHARE_INTENT, Parcels.wrap(shareIntent));
-                    bundle.putString(BundleKeys.KEY_APP_ITEM_PACKAGE_NAME, appItem.getPackageName());
-                    bundle.putString(BundleKeys.KEY_APP_ITEM_NAME, appItem.getName());
+                    bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), 7);
+                    bundle.putParcelable(BundleKeys.INSTANCE.getKEY_SHARE_INTENT(), Parcels.wrap(shareIntent));
+                    bundle.putString(BundleKeys.INSTANCE.getKEY_APP_ITEM_PACKAGE_NAME(), appItem.getPackageName());
+                    bundle.putString(BundleKeys.INSTANCE.getKEY_APP_ITEM_NAME(), appItem.getName());
                     getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
                             .pushChangeHandler(new HorizontalChangeHandler())
                             .popChangeHandler(new HorizontalChangeHandler()));
@@ -294,8 +294,8 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
     private Data getWorkerData() {
         if (!TextUtils.isEmpty(conversation.getToken())) {
             Data.Builder data = new Data.Builder();
-            data.putString(BundleKeys.KEY_ROOM_TOKEN, conversation.getToken());
-            data.putLong(BundleKeys.KEY_INTERNAL_USER_ID, currentUser.getId());
+            data.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), conversation.getToken());
+            data.putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), currentUser.getId());
             return data.build();
         }
 
@@ -305,8 +305,8 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
     private Bundle getDeleteConversationBundle() {
         if (!TextUtils.isEmpty(conversation.getToken())) {
             Bundle bundle = new Bundle();
-            bundle.putLong(BundleKeys.KEY_INTERNAL_USER_ID, currentUser.getId());
-            bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(conversation));
+            bundle.putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), currentUser.getId());
+            bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
             return bundle;
         }
 

+ 21 - 21
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.java

@@ -44,7 +44,7 @@ import com.nextcloud.talk.R;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.controllers.base.BaseController;
 import com.nextcloud.talk.events.BottomSheetLockEvent;
-import com.nextcloud.talk.models.json.rooms.Conversation;
+import com.nextcloud.talk.models.json.conversations.Conversation;
 import com.nextcloud.talk.utils.ShareUtils;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
 import com.nextcloud.talk.utils.database.user.UserUtils;
@@ -85,18 +85,18 @@ public class EntryMenuController extends BaseController {
         super(args);
         originalBundle = args;
 
-        this.operationCode = args.getInt(BundleKeys.KEY_OPERATION_CODE);
-        if (args.containsKey(BundleKeys.KEY_ROOM)) {
-            this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
+        this.operationCode = args.getInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE());
+        if (args.containsKey(BundleKeys.INSTANCE.getKEY_ROOM())) {
+            this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
         }
 
-        if (args.containsKey(BundleKeys.KEY_SHARE_INTENT)) {
-            this.shareIntent = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_SHARE_INTENT));
+        if (args.containsKey(BundleKeys.INSTANCE.getKEY_SHARE_INTENT())) {
+            this.shareIntent = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_SHARE_INTENT()));
         }
 
-        this.name = args.getString(BundleKeys.KEY_APP_ITEM_NAME, "");
-        this.packageName = args.getString(BundleKeys.KEY_APP_ITEM_PACKAGE_NAME, "");
-        this.callUrl = args.getString(BundleKeys.KEY_CALL_URL, "");
+        this.name = args.getString(BundleKeys.INSTANCE.getKEY_APP_ITEM_NAME(), "");
+        this.packageName = args.getString(BundleKeys.INSTANCE.getKEY_APP_ITEM_PACKAGE_NAME(), "");
+        this.callUrl = args.getString(BundleKeys.INSTANCE.getKEY_CALL_URL(), "");
     }
 
     @Override
@@ -124,12 +124,12 @@ public class EntryMenuController extends BaseController {
         if (operationCode == 99) {
             eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
             bundle = new Bundle();
-            bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(conversation));
-            bundle.putString(BundleKeys.KEY_CALL_URL, callUrl);
-            bundle.putString(BundleKeys.KEY_CONVERSATION_PASSWORD, editText.getText().toString());
-            bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode);
-            if (originalBundle.containsKey(BundleKeys.KEY_SERVER_CAPABILITIES)) {
-                bundle.putParcelable(BundleKeys.KEY_SERVER_CAPABILITIES, originalBundle.getParcelable(BundleKeys.KEY_SERVER_CAPABILITIES));
+            bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
+            bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), callUrl);
+            bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), editText.getText().toString());
+            bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
+            if (originalBundle.containsKey(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES())) {
+                bundle.putParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES(), originalBundle.getParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES()));
             }
 
             getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
@@ -143,8 +143,8 @@ public class EntryMenuController extends BaseController {
             } else {
                 conversation.setName(editText.getText().toString());
             }
-            bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(conversation));
-            bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode);
+            bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
+            bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
             getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
                     .pushChangeHandler(new HorizontalChangeHandler())
                     .popChangeHandler(new HorizontalChangeHandler()));
@@ -161,15 +161,15 @@ public class EntryMenuController extends BaseController {
         } else if (operationCode != 11) {
             eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
             bundle = new Bundle();
-            bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode);
-            bundle.putString(BundleKeys.KEY_CALL_URL, editText.getText().toString());
+            bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
+            bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), editText.getText().toString());
             getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
                     .pushChangeHandler(new HorizontalChangeHandler())
                     .popChangeHandler(new HorizontalChangeHandler()));
 
         } else if (operationCode == 11) {
             eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
-            originalBundle.putString(BundleKeys.KEY_CONVERSATION_NAME, editText.getText().toString());
+            originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), editText.getText().toString());
             getRouter().pushController(RouterTransaction.with(new OperationsMenuController(originalBundle))
                     .pushChangeHandler(new HorizontalChangeHandler())
                     .popChangeHandler(new HorizontalChangeHandler()));
@@ -180,7 +180,7 @@ public class EntryMenuController extends BaseController {
     @Override
     protected void onViewBound(@NonNull View view) {
         super.onViewBound(view);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         if (conversation != null && operationCode == 2) {
             editText.setText(conversation.getName());

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

@@ -56,8 +56,8 @@ import com.nextcloud.talk.models.json.capabilities.Capabilities;
 import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall;
 import com.nextcloud.talk.models.json.generic.GenericOverall;
 import com.nextcloud.talk.models.json.participants.AddParticipantOverall;
-import com.nextcloud.talk.models.json.rooms.Conversation;
-import com.nextcloud.talk.models.json.rooms.RoomOverall;
+import com.nextcloud.talk.models.json.conversations.Conversation;
+import com.nextcloud.talk.models.json.conversations.RoomOverall;
 import com.nextcloud.talk.utils.ApiUtils;
 import com.nextcloud.talk.utils.ConductorRemapping;
 import com.nextcloud.talk.utils.DisplayUtils;
@@ -126,31 +126,31 @@ public class OperationsMenuController extends BaseController {
 
     public OperationsMenuController(Bundle args) {
         super(args);
-        this.operationCode = args.getInt(BundleKeys.KEY_OPERATION_CODE);
-        if (args.containsKey(BundleKeys.KEY_ROOM)) {
-            this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
+        this.operationCode = args.getInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE());
+        if (args.containsKey(BundleKeys.INSTANCE.getKEY_ROOM())) {
+            this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
         }
 
-        this.callPassword = args.getString(BundleKeys.KEY_CONVERSATION_PASSWORD, "");
-        this.callUrl = args.getString(BundleKeys.KEY_CALL_URL, "");
+        this.callPassword = args.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), "");
+        this.callUrl = args.getString(BundleKeys.INSTANCE.getKEY_CALL_URL(), "");
 
-        if (args.containsKey(BundleKeys.KEY_INVITED_PARTICIPANTS)) {
-            this.invitedUsers = args.getStringArrayList(BundleKeys.KEY_INVITED_PARTICIPANTS);
+        if (args.containsKey(BundleKeys.INSTANCE.getKEY_INVITED_PARTICIPANTS())) {
+            this.invitedUsers = args.getStringArrayList(BundleKeys.INSTANCE.getKEY_INVITED_PARTICIPANTS());
         }
 
-        if (args.containsKey(BundleKeys.KEY_INVITED_GROUP)) {
-            this.invitedGroups = args.getStringArrayList(BundleKeys.KEY_INVITED_GROUP);
+        if (args.containsKey(BundleKeys.INSTANCE.getKEY_INVITED_GROUP())) {
+            this.invitedGroups = args.getStringArrayList(BundleKeys.INSTANCE.getKEY_INVITED_GROUP());
         }
 
-        if (args.containsKey(BundleKeys.KEY_CONVERSATION_TYPE)) {
-            this.conversationType = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_CONVERSATION_TYPE));
+        if (args.containsKey(BundleKeys.INSTANCE.getKEY_CONVERSATION_TYPE())) {
+            this.conversationType = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_CONVERSATION_TYPE()));
         }
 
-        if (args.containsKey(BundleKeys.KEY_SERVER_CAPABILITIES)) {
-            this.serverCapabilities = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_SERVER_CAPABILITIES));
+        if (args.containsKey(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES())) {
+            this.serverCapabilities = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES()));
         }
 
-        this.conversationName = args.getString(BundleKeys.KEY_CONVERSATION_NAME, "");
+        this.conversationName = args.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), "");
 
     }
 
@@ -162,7 +162,7 @@ public class OperationsMenuController extends BaseController {
     @Override
     protected void onViewBound(@NonNull View view) {
         super.onViewBound(view);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         processOperation();
     }
@@ -459,11 +459,11 @@ public class OperationsMenuController extends BaseController {
                                 eventBus.post(new BottomSheetLockEvent(true, 0,
                                         true, false));
                                 Bundle bundle = new Bundle();
-                                bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(conversation));
-                                bundle.putString(BundleKeys.KEY_CALL_URL, callUrl);
-                                bundle.putParcelable(BundleKeys.KEY_SERVER_CAPABILITIES,
+                                bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
+                                bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), callUrl);
+                                bundle.putParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES(),
                                         Parcels.wrap(capabilitiesOverall.getOcs().getData().getCapabilities()));
-                                bundle.putInt(BundleKeys.KEY_OPERATION_CODE, 99);
+                                bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), 99);
                                 getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
                                         .pushChangeHandler(new HorizontalChangeHandler())
                                         .popChangeHandler(new HorizontalChangeHandler()));
@@ -610,9 +610,9 @@ public class OperationsMenuController extends BaseController {
                     true, true, dismissView));
 
             Intent conversationIntent = new Intent(getActivity(), MagicCallActivity.class);
-            bundle.putString(BundleKeys.KEY_ROOM_TOKEN, conversation.getToken());
-            bundle.putString(BundleKeys.KEY_ROOM_ID, conversation.getRoomId());
-            bundle.putString(BundleKeys.KEY_CONVERSATION_NAME, conversation.getDisplayName());
+            bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), conversation.getToken());
+            bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), conversation.getRoomId());
+            bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), conversation.getDisplayName());
             UserEntity conversationUser;
             if (isGuestUser) {
                 conversationUser = new UserEntity();
@@ -627,14 +627,14 @@ public class OperationsMenuController extends BaseController {
                 conversationUser = currentUser;
             }
 
-            bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, conversationUser);
-            bundle.putParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION, Parcels.wrap(conversation));
-            bundle.putString(BundleKeys.KEY_CONVERSATION_PASSWORD, callPassword);
+            bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), conversationUser);
+            bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(), Parcels.wrap(conversation));
+            bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), callPassword);
 
             conversationIntent.putExtras(bundle);
 
             if (getParentController() != null) {
-                ConductorRemapping.remapChatController(getParentController().getRouter(), conversationUser.getId(),
+                ConductorRemapping.INSTANCE.remapChatController(getParentController().getRouter(), conversationUser.getId(),
                         conversation.getToken(), bundle, true);
             }
         } else {
@@ -646,12 +646,12 @@ public class OperationsMenuController extends BaseController {
     private void initiateCall() {
         eventBus.post(new BottomSheetLockEvent(true, 0, true, true));
         Bundle bundle = new Bundle();
-        bundle.putString(BundleKeys.KEY_ROOM_TOKEN, conversation.getToken());
-        bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, currentUser);
+        bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), conversation.getToken());
+        bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), currentUser);
         if (baseUrl != null && !baseUrl.equals(currentUser.getBaseUrl())) {
-            bundle.putString(BundleKeys.KEY_MODIFIED_BASE_URL, baseUrl);
+            bundle.putString(BundleKeys.INSTANCE.getKEY_MODIFIED_BASE_URL(), baseUrl);
         }
-        bundle.putParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION, Parcels.wrap(call));
+        bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(), Parcels.wrap(call));
 
         if (getActivity() != null) {
 

+ 2 - 2
app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java

@@ -159,7 +159,7 @@ public class RestModule {
     Cache provideCache() {
         int cacheSize = 128 * 1024 * 1024; // 128 MB
 
-        return new Cache(NextcloudTalkApplication.getSharedApplication().getCacheDir(), cacheSize);
+        return new Cache(NextcloudTalkApplication.Companion.getSharedApplication().getCacheDir(), cacheSize);
     }
 
     @Singleton
@@ -216,7 +216,7 @@ public class RestModule {
         } else if (context.getResources().getBoolean(R.bool.nc_is_debug)) {
 
             HttpLoggingInterceptor.Logger fileLogger =
-                    s -> LoggingUtils.writeLogEntryToFile(context, s);
+                    s -> LoggingUtils.INSTANCE.writeLogEntryToFile(context, s);
             HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(fileLogger);
             loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
             loggingInterceptor.redactHeader("Authorization");

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

@@ -20,7 +20,7 @@
 
 package com.nextcloud.talk.events;
 
-import com.nextcloud.talk.models.json.rooms.Conversation;
+import com.nextcloud.talk.models.json.conversations.Conversation;
 import lombok.Data;
 
 @Data

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

@@ -30,4 +30,4 @@ public class WebSocketCommunicationEvent {
     public final String type;
     @Nullable
     public final HashMap<String, String> hashMap;
-}
+}

+ 4 - 4
app/src/main/java/com/nextcloud/talk/interfaces/SelectionInterface.java → app/src/main/java/com/nextcloud/talk/interfaces/ClosedInterface.kt

@@ -18,10 +18,10 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-package com.nextcloud.talk.interfaces;
+package com.nextcloud.talk.interfaces
 
-public interface SelectionInterface {
-    void toggleBrowserItemSelection(String path);
+interface ClosedInterface {
 
-    boolean isPathSelected(String path);
+    val isGooglePlayServicesAvailable: Boolean
+    fun providerInstallerInstallIfNeededAsync()
 }

+ 4 - 4
app/src/main/java/com/nextcloud/talk/interfaces/ConversationMenuInterface.java → app/src/main/java/com/nextcloud/talk/interfaces/ConversationMenuInterface.kt

@@ -18,10 +18,10 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-package com.nextcloud.talk.interfaces;
+package com.nextcloud.talk.interfaces
 
-import android.os.Bundle;
+import android.os.Bundle
 
-public interface ConversationMenuInterface {
-    void openLovelyDialogWithIdAndBundle(int dialogId, Bundle bundle);
+interface ConversationMenuInterface {
+    fun openLovelyDialogWithIdAndBundle(dialogId: Int, bundle: Bundle)
 }

+ 4 - 4
app/src/main/java/com/nextcloud/talk/interfaces/ClosedInterface.java → app/src/main/java/com/nextcloud/talk/interfaces/SelectionInterface.kt

@@ -18,10 +18,10 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-package com.nextcloud.talk.interfaces;
+package com.nextcloud.talk.interfaces
 
-public interface ClosedInterface {
-    void providerInstallerInstallIfNeededAsync();
+interface SelectionInterface {
+    fun toggleBrowserItemSelection(path: String)
 
-    boolean isGooglePlayServicesAvailable();
+    fun isPathSelected(path: String): Boolean
 }

+ 1 - 1
app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalWorker.java

@@ -79,7 +79,7 @@ public class AccountRemovalWorker extends Worker {
     @NonNull
     @Override
     public Result doWork() {
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         PushConfigurationState pushConfigurationState;
         String credentials;

+ 2 - 2
app/src/main/java/com/nextcloud/talk/jobs/CapabilitiesWorker.java

@@ -110,11 +110,11 @@ public class CapabilitiesWorker extends Worker {
     @NonNull
     @Override
     public Result doWork() {
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         Data data = getInputData();
 
-        long internalUserId = data.getLong(BundleKeys.KEY_INTERNAL_USER_ID, -1);
+        long internalUserId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1);
 
         UserEntity userEntity;
         List userEntityObjectList = new ArrayList();

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

@@ -63,15 +63,15 @@ public class DeleteConversationWorker extends Worker {
 
     public DeleteConversationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
         super(context, workerParams);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.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);
+        long operationUserId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1);
+        String conversationToken = data.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
         UserEntity operationUser = userUtils.getUserWithId(operationUserId);
 
         if (operationUser != null) {

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

@@ -63,15 +63,15 @@ public class LeaveConversationWorker extends Worker {
 
     public LeaveConversationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
         super(context, workerParams);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.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);
+        long operationUserId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1);
+        String conversationToken = data.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
         UserEntity operationUser = userUtils.getUserWithId(operationUserId);
 
         if (operationUser != null) {

+ 19 - 19
app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java

@@ -71,8 +71,8 @@ import com.nextcloud.talk.models.json.chat.ChatUtils;
 import com.nextcloud.talk.models.json.notifications.NotificationOverall;
 import com.nextcloud.talk.models.json.push.DecryptedPushMessage;
 import com.nextcloud.talk.models.json.push.NotificationUser;
-import com.nextcloud.talk.models.json.rooms.Conversation;
-import com.nextcloud.talk.models.json.rooms.RoomOverall;
+import com.nextcloud.talk.models.json.conversations.Conversation;
+import com.nextcloud.talk.models.json.conversations.RoomOverall;
 import com.nextcloud.talk.utils.*;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
 import com.nextcloud.talk.utils.database.arbitrarystorage.ArbitraryStorageUtils;
@@ -132,13 +132,13 @@ public class NotificationWorker extends Worker {
         boolean muteCalls = false;
 
         if ((arbitraryStorageEntity = arbitraryStorageUtils.getStorageSetting(userEntity.getId(),
-                "mute_calls", intent.getExtras().getString(BundleKeys.KEY_ROOM_TOKEN))) != null) {
+                "mute_calls", intent.getExtras().getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN()))) != null) {
             muteCalls = Boolean.parseBoolean(arbitraryStorageEntity.getValue());
         }
 
         if (!muteCalls) {
             ncApi.getRoom(credentials, ApiUtils.getRoom(userEntity.getBaseUrl(),
-                    intent.getExtras().getString(BundleKeys.KEY_ROOM_TOKEN)))
+                    intent.getExtras().getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN())))
                     .blockingSubscribe(new Observer<RoomOverall>() {
                         @Override
                         public void onSubscribe(Disposable d) {
@@ -149,7 +149,7 @@ public class NotificationWorker extends Worker {
                         public void onNext(RoomOverall roomOverall) {
                             Conversation conversation = roomOverall.getOcs().getData();
 
-                            intent.putExtra(BundleKeys.KEY_ROOM, Parcels.wrap(conversation));
+                            intent.putExtra(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
                             if (conversation.getType().equals(Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) ||
                                     (!TextUtils.isEmpty(conversation.getObjectType()) && "share:password".equals
                                             (conversation.getObjectType()))) {
@@ -308,10 +308,10 @@ public class NotificationWorker extends Worker {
         }
 
         Bundle notificationInfo = new Bundle();
-        notificationInfo.putLong(BundleKeys.KEY_INTERNAL_USER_ID, signatureVerification.getUserEntity().getId());
+        notificationInfo.putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), signatureVerification.getUserEntity().getId());
         // could be an ID or a TOKEN
-        notificationInfo.putString(BundleKeys.KEY_ROOM_TOKEN, decryptedPushMessage.getId());
-        notificationInfo.putLong(BundleKeys.KEY_NOTIFICATION_ID, decryptedPushMessage.getNotificationId());
+        notificationInfo.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), decryptedPushMessage.getId());
+        notificationInfo.putLong(BundleKeys.INSTANCE.getKEY_NOTIFICATION_ID(), decryptedPushMessage.getNotificationId());
         notificationBuilder.setExtras(notificationInfo);
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
@@ -462,7 +462,7 @@ public class NotificationWorker extends Worker {
         }
 
         if (soundUri != null & !ApplicationWideCurrentRoomHolder.getInstance().isInCall() &&
-                DoNotDisturbUtils.shouldPlaySound()) {
+                DoNotDisturbUtils.INSTANCE.shouldPlaySound()) {
             AudioAttributes.Builder audioAttributesBuilder = new AudioAttributes.Builder().setContentType
                     (AudioAttributes.CONTENT_TYPE_SONIFICATION);
 
@@ -487,7 +487,7 @@ public class NotificationWorker extends Worker {
         }
 
 
-        if (DoNotDisturbUtils.shouldVibrate(appPreferences.getShouldVibrateSetting())) {
+        if (DoNotDisturbUtils.INSTANCE.shouldVibrate(appPreferences.getShouldVibrateSetting())) {
             Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
 
             if (vibrator != null) {
@@ -503,12 +503,12 @@ public class NotificationWorker extends Worker {
     @NonNull
     @Override
     public Result doWork() {
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         context = getApplicationContext();
         Data data = getInputData();
-        String subject = data.getString(BundleKeys.KEY_NOTIFICATION_SUBJECT);
-        String signature = data.getString(BundleKeys.KEY_NOTIFICATION_SIGNATURE);
+        String subject = data.getString(BundleKeys.INSTANCE.getKEY_NOTIFICATION_SUBJECT());
+        String signature = data.getString(BundleKeys.INSTANCE.getKEY_NOTIFICATION_SIGNATURE());
 
         try {
             byte[] base64DecodedSubject = Base64.decode(subject, Base64.DEFAULT);
@@ -560,28 +560,28 @@ public class NotificationWorker extends Worker {
 
                             if (!signatureVerification.getUserEntity().hasSpreedFeatureCapability
                                     ("no-ping")) {
-                                bundle.putString(BundleKeys.KEY_ROOM_ID, decryptedPushMessage.getId());
+                                bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), decryptedPushMessage.getId());
                             } else {
-                                bundle.putString(BundleKeys.KEY_ROOM_TOKEN, decryptedPushMessage.getId());
+                                bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), decryptedPushMessage.getId());
                             }
 
-                            bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, signatureVerification.getUserEntity());
+                            bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), signatureVerification.getUserEntity());
 
-                            bundle.putBoolean(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL,
+                            bundle.putBoolean(BundleKeys.INSTANCE.getKEY_FROM_NOTIFICATION_START_CALL(),
                                     startACall);
 
                             intent.putExtras(bundle);
 
                             switch (decryptedPushMessage.getType()) {
                                 case "call":
-                                    if (!bundle.containsKey(BundleKeys.KEY_ROOM_TOKEN)) {
+                                    if (!bundle.containsKey(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN())) {
                                         context.startActivity(intent);
                                     } else {
                                         showNotificationForCallWithNoPing(intent);
                                     }
                                     break;
                                 case "room":
-                                    if (bundle.containsKey(BundleKeys.KEY_ROOM_TOKEN)) {
+                                    if (bundle.containsKey(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN())) {
                                         showNotificationForCallWithNoPing(intent);
                                     }
                                     break;

+ 4 - 4
app/src/main/java/com/nextcloud/talk/jobs/ShareOperationWorker.java

@@ -56,11 +56,11 @@ public class ShareOperationWorker extends Worker {
 
     public ShareOperationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
         super(context, workerParams);
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
         Data data = workerParams.getInputData();
-        userId = data.getLong(BundleKeys.KEY_INTERNAL_USER_ID, 0);
-        roomToken = data.getString(BundleKeys.KEY_ROOM_TOKEN);
-        Collections.addAll(filesArray, data.getStringArray(BundleKeys.KEY_FILE_PATHS));
+        userId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), 0);
+        roomToken = data.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
+        Collections.addAll(filesArray, data.getStringArray(BundleKeys.INSTANCE.getKEY_FILE_PATHS()));
         operationsUser = userUtils.getUserWithId(userId);
         credentials = ApiUtils.getCredentials(operationsUser.getUsername(), operationsUser.getToken());
         baseUrl = operationsUser.getBaseUrl();

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

@@ -64,11 +64,11 @@ public class SignalingSettingsWorker extends Worker {
     @NonNull
     @Override
     public Result doWork() {
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         Data data = getInputData();
 
-        long internalUserId = data.getLong(BundleKeys.KEY_INTERNAL_USER_ID, -1);
+        long internalUserId = data.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), -1);
 
         List<UserEntity> userEntityList = new ArrayList<>();
         UserEntity userEntity;

+ 1 - 1
app/src/main/java/com/nextcloud/talk/jobs/WebsocketConnectionsWorker.java

@@ -55,7 +55,7 @@ public class WebsocketConnectionsWorker extends Worker {
     @NonNull
     @Override
     public Result doWork() {
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         List<UserEntity> userEntityList = userUtils.getUsers();
         UserEntity userEntity;

+ 22 - 19
app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java

@@ -97,7 +97,7 @@ public class ChatMessage implements IMessage, MessageContentType, MessageContent
                 if (individualHashMap.get("type").equals("file")) {
                     selectedIndividualHashMap = individualHashMap;
                     return (ApiUtils.getUrlForFilePreviewWithFileId(getActiveUser().getBaseUrl(),
-                            individualHashMap.get("id"), NextcloudTalkApplication.getSharedApplication().getResources().getDimensionPixelSize(R.dimen.maximum_file_preview_size)));
+                            individualHashMap.get("id"), NextcloudTalkApplication.Companion.getSharedApplication().getResources().getDimensionPixelSize(R.dimen.maximum_file_preview_size)));
                 }
             }
         }
@@ -147,45 +147,45 @@ public class ChatMessage implements IMessage, MessageContentType, MessageContent
                     || getMessageType().equals(MessageType.SINGLE_LINK_TENOR_MESSAGE)
                     || getMessageType().equals(MessageType.SINGLE_LINK_GIF_MESSAGE)) {
                 if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_sent_a_gif_you));
+                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_a_gif_you));
                 } else {
-                    return (String.format(NextcloudTalkApplication.getSharedApplication().getResources().getString(R.string.nc_sent_a_gif),
-                            !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_guest)));
+                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_a_gif),
+                            !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
                 }
             } else if (getMessageType().equals(MessageType.SINGLE_NC_ATTACHMENT_MESSAGE)) {
                 if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_sent_an_attachment_you));
+                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_an_attachment_you));
                 } else {
-                    return (String.format(NextcloudTalkApplication.getSharedApplication().getResources().getString(R.string.nc_sent_an_attachment),
-                            !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_guest)));
+                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_an_attachment),
+                            !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
                 }
             } else if (getMessageType().equals(MessageType.SINGLE_LINK_MESSAGE)) {
                 if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_sent_a_link_you));
+                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_a_link_you));
                 } else {
-                    return (String.format(NextcloudTalkApplication.getSharedApplication().getResources().getString(R.string.nc_sent_a_link),
-                            !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_guest)));
+                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_a_link),
+                            !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
                 }
             } else if (getMessageType().equals(MessageType.SINGLE_LINK_AUDIO_MESSAGE)) {
                 if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_sent_an_audio_you));
+                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_an_audio_you));
                 } else {
-                    return (String.format(NextcloudTalkApplication.getSharedApplication().getResources().getString(R.string.nc_sent_an_audio),
-                            !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_guest)));
+                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_an_audio),
+                            !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
                 }
             } else if (getMessageType().equals(MessageType.SINGLE_LINK_VIDEO_MESSAGE)) {
                 if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_sent_a_video_you));
+                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_a_video_you));
                 } else {
-                    return (String.format(NextcloudTalkApplication.getSharedApplication().getResources().getString(R.string.nc_sent_a_video),
-                            !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_guest)));
+                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_a_video),
+                            !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
                 }
             } else if (getMessageType().equals(MessageType.SINGLE_LINK_IMAGE_MESSAGE)) {
                 if (getActorId().equals(getActiveUser().getUserId())) {
-                    return (NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_sent_an_image_you));
+                    return (NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_sent_an_image_you));
                 } else {
-                    return (String.format(NextcloudTalkApplication.getSharedApplication().getResources().getString(R.string.nc_sent_an_image),
-                            !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_guest)));
+                    return (String.format(NextcloudTalkApplication.Companion.getSharedApplication().getResources().getString(R.string.nc_sent_an_image),
+                            !TextUtils.isEmpty(getActorDisplayName()) ? getActorDisplayName() : NextcloudTalkApplication.Companion.getSharedApplication().getString(R.string.nc_guest)));
                 }
             }
         }
@@ -257,5 +257,8 @@ public class ChatMessage implements IMessage, MessageContentType, MessageContent
         MODERATOR_PROMOTED,
         MODERATOR_DEMOTED,
         FILE_SHARED,
+        LOBBY_NONE,
+        LOBBY_NON_MODERATORS,
+        LOBBY_OPEN_TO_EVERYONE
     }
 }

+ 26 - 6
app/src/main/java/com/nextcloud/talk/models/json/rooms/Conversation.java → app/src/main/java/com/nextcloud/talk/models/json/conversations/Conversation.java

@@ -18,15 +18,19 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-package com.nextcloud.talk.models.json.rooms;
+package com.nextcloud.talk.models.json.conversations;
 
 import android.content.res.Resources;
+
+import androidx.annotation.Nullable;
+
 import com.bluelinelabs.logansquare.annotation.JsonField;
 import com.bluelinelabs.logansquare.annotation.JsonObject;
 import com.nextcloud.talk.R;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.models.database.UserEntity;
 import com.nextcloud.talk.models.json.chat.ChatMessage;
+import com.nextcloud.talk.models.json.converters.EnumLobbyStateConverter;
 import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter;
 import com.nextcloud.talk.models.json.converters.EnumParticipantTypeConverter;
 import com.nextcloud.talk.models.json.converters.EnumReadOnlyConversationConverter;
@@ -79,11 +83,15 @@ public class Conversation {
     @JsonField(name = "lastMessage")
     public ChatMessage lastMessage;
     @JsonField(name = "objectType")
-    String objectType;
+    public String objectType;
     @JsonField(name = "notificationLevel", typeConverter = EnumNotificationLevelConverter.class)
-    NotificationLevel notificationLevel;
+    public NotificationLevel notificationLevel;
     @JsonField(name = "readOnly", typeConverter = EnumReadOnlyConversationConverter.class)
-    ConversationReadOnlyState conversationReadOnlyState;
+    public ConversationReadOnlyState conversationReadOnlyState;
+    @JsonField(name = "lobbyState", typeConverter = EnumLobbyStateConverter.class)
+    public LobbyState lobbyState;
+    @JsonField(name = "lobbyTimer")
+    public Long lobbyTimer;
 
 
     public boolean isPublic() {
@@ -97,7 +105,7 @@ public class Conversation {
 
 
     private boolean isLockedOneToOne(UserEntity conversationUser) {
-        return (getType() == ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL && conversationUser.hasSpreedFeatureCapability("locked-one-to-one-rooms"));
+        return (getType() == ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL && conversationUser.hasSpreedFeatureCapability("locked-one-to-one-conversations"));
     }
 
     public boolean canModerate(UserEntity conversationUser) {
@@ -105,6 +113,13 @@ public class Conversation {
                 || Participant.ParticipantType.MODERATOR.equals(participantType)) && !isLockedOneToOne(conversationUser));
     }
 
+    public boolean shouldShowLobby(UserEntity conversationUser) {
+        return getLobbyState().equals(LobbyState.LOBBY_STATE_MODERATORS_ONLY) && !canModerate(conversationUser);
+    }
+
+    public boolean isLobbyViewApplicable(UserEntity conversationUser) {
+        return !canModerate(conversationUser) && (getType() == ConversationType.ROOM_GROUP_CALL || getType() == ConversationType.ROOM_PUBLIC_CALL);
+    }
     public boolean isNameEditable(UserEntity conversationUser) {
         return (canModerate(conversationUser) && !ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL.equals(type));
     }
@@ -115,7 +130,7 @@ public class Conversation {
     }
 
     public String getDeleteWarningMessage() {
-        Resources resources = NextcloudTalkApplication.getSharedApplication().getResources();
+        Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
         if (getType() == ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
             return String.format(resources.getString(R.string.nc_delete_conversation_one2one),
                     getDisplayName());
@@ -133,6 +148,11 @@ public class Conversation {
         NEVER
     }
 
+    public enum LobbyState {
+        LOBBY_STATE_ALL_PARTICIPANTS,
+        LOBBY_STATE_MODERATORS_ONLY
+    }
+
     public enum ConversationReadOnlyState {
         CONVERSATION_READ_WRITE,
         CONVERSATION_READ_ONLY

+ 2 - 2
app/src/main/java/com/nextcloud/talk/models/json/rooms/RoomOCS.java → app/src/main/java/com/nextcloud/talk/models/json/conversations/RoomOCS.java

@@ -18,7 +18,7 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-package com.nextcloud.talk.models.json.rooms;
+package com.nextcloud.talk.models.json.conversations;
 
 import com.bluelinelabs.logansquare.annotation.JsonField;
 import com.bluelinelabs.logansquare.annotation.JsonObject;
@@ -29,5 +29,5 @@ import lombok.Data;
 @JsonObject
 public class RoomOCS extends GenericOCS {
     @JsonField(name = "data")
-    Conversation data;
+    public Conversation data;
 }

+ 2 - 2
app/src/main/java/com/nextcloud/talk/models/json/rooms/RoomOverall.java → app/src/main/java/com/nextcloud/talk/models/json/conversations/RoomOverall.java

@@ -18,7 +18,7 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-package com.nextcloud.talk.models.json.rooms;
+package com.nextcloud.talk.models.json.conversations;
 
 import com.bluelinelabs.logansquare.annotation.JsonField;
 import com.bluelinelabs.logansquare.annotation.JsonObject;
@@ -28,5 +28,5 @@ import lombok.Data;
 @JsonObject
 public class RoomOverall {
     @JsonField(name = "ocs")
-    RoomOCS ocs;
+    public RoomOCS ocs;
 }

+ 2 - 2
app/src/main/java/com/nextcloud/talk/models/json/rooms/RoomsOCS.java → app/src/main/java/com/nextcloud/talk/models/json/conversations/RoomsOCS.java

@@ -18,7 +18,7 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-package com.nextcloud.talk.models.json.rooms;
+package com.nextcloud.talk.models.json.conversations;
 
 import com.bluelinelabs.logansquare.annotation.JsonField;
 import com.bluelinelabs.logansquare.annotation.JsonObject;
@@ -33,5 +33,5 @@ import java.util.List;
 @JsonObject
 public class RoomsOCS extends GenericOCS {
     @JsonField(name = "data")
-    List<Conversation> data;
+    public List<Conversation> data;
 }

+ 2 - 2
app/src/main/java/com/nextcloud/talk/models/json/rooms/RoomsOverall.java → app/src/main/java/com/nextcloud/talk/models/json/conversations/RoomsOverall.java

@@ -18,7 +18,7 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-package com.nextcloud.talk.models.json.rooms;
+package com.nextcloud.talk.models.json.conversations;
 
 import com.bluelinelabs.logansquare.annotation.JsonField;
 import com.bluelinelabs.logansquare.annotation.JsonObject;
@@ -30,5 +30,5 @@ import org.parceler.Parcel;
 @JsonObject
 public class RoomsOverall {
     @JsonField(name = "ocs")
-    RoomsOCS ocs;
+    public RoomsOCS ocs;
 }

+ 50 - 0
app/src/main/java/com/nextcloud/talk/models/json/converters/EnumLobbyStateConverter.java

@@ -0,0 +1,50 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.models.json.converters;
+
+import com.bluelinelabs.logansquare.typeconverters.IntBasedTypeConverter;
+import com.nextcloud.talk.models.json.conversations.Conversation;
+
+public class EnumLobbyStateConverter extends IntBasedTypeConverter<Conversation.LobbyState> {
+    @Override
+    public Conversation.LobbyState getFromInt(int i) {
+        switch (i) {
+            case 0:
+                return Conversation.LobbyState.LOBBY_STATE_ALL_PARTICIPANTS;
+            case 1:
+                return Conversation.LobbyState.LOBBY_STATE_MODERATORS_ONLY;
+            default:
+                return Conversation.LobbyState.LOBBY_STATE_ALL_PARTICIPANTS;
+        }
+    }
+
+    @Override
+    public int convertToInt(Conversation.LobbyState object) {
+        switch (object) {
+            case LOBBY_STATE_ALL_PARTICIPANTS:
+                return 0;
+            case LOBBY_STATE_MODERATORS_ONLY:
+                return 1;
+            default:
+                return 0;
+        }
+    }
+}

+ 1 - 1
app/src/main/java/com/nextcloud/talk/models/json/converters/EnumNotificationLevelConverter.java

@@ -21,7 +21,7 @@
 package com.nextcloud.talk.models.json.converters;
 
 import com.bluelinelabs.logansquare.typeconverters.IntBasedTypeConverter;
-import com.nextcloud.talk.models.json.rooms.Conversation;
+import com.nextcloud.talk.models.json.conversations.Conversation;
 
 public class EnumNotificationLevelConverter extends IntBasedTypeConverter<Conversation.NotificationLevel> {
     @Override

+ 1 - 1
app/src/main/java/com/nextcloud/talk/models/json/converters/EnumReadOnlyConversationConverter.java

@@ -21,7 +21,7 @@
 package com.nextcloud.talk.models.json.converters;
 
 import com.bluelinelabs.logansquare.typeconverters.IntBasedTypeConverter;
-import com.nextcloud.talk.models.json.rooms.Conversation;
+import com.nextcloud.talk.models.json.conversations.Conversation;
 
 public class EnumReadOnlyConversationConverter extends IntBasedTypeConverter<Conversation.ConversationReadOnlyState> {
     @Override

+ 1 - 1
app/src/main/java/com/nextcloud/talk/models/json/converters/EnumRoomTypeConverter.java

@@ -21,7 +21,7 @@
 package com.nextcloud.talk.models.json.converters;
 
 import com.bluelinelabs.logansquare.typeconverters.IntBasedTypeConverter;
-import com.nextcloud.talk.models.json.rooms.Conversation;
+import com.nextcloud.talk.models.json.conversations.Conversation;
 
 public class EnumRoomTypeConverter extends IntBasedTypeConverter<Conversation.ConversationType> {
     @Override

+ 0 - 126
app/src/main/java/com/nextcloud/talk/models/json/converters/EnumSystemMessageTypeConverter.java

@@ -1,126 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.nextcloud.talk.models.json.converters;
-
-import com.bluelinelabs.logansquare.typeconverters.StringBasedTypeConverter;
-import com.nextcloud.talk.models.json.chat.ChatMessage;
-
-import static com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.*;
-
-/*
-
-    conversation_created - {actor} created the conversation
-    conversation_renamed - {actor} renamed the conversation from "foo" to "bar"
-    call_joined - {actor} joined the call
-    call_left - {actor} left the call
-    call_ended - Call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration 30:23)
-    guests_allowed - {actor} allowed guests in the conversation
-    guests_disallowed - {actor} disallowed guests in the conversation
-    password_set - {actor} set a password for the conversation
-    password_removed - {actor} removed the password for the conversation
-    user_added - {actor} added {user} to the conversation
-    user_removed - {actor} removed {user} from the conversation
-    moderator_promoted - {actor} promoted {user} to moderator
-    moderator_demoted - {actor} demoted {user} from moderator
-
- */
-public class EnumSystemMessageTypeConverter extends StringBasedTypeConverter<ChatMessage.SystemMessageType> {
-    @Override
-    public ChatMessage.SystemMessageType getFromString(String string) {
-        switch (string) {
-            case "conversation_created":
-                return CONVERSATION_CREATED;
-            case "conversation_renamed":
-                return CONVERSATION_RENAMED;
-            case "call_started":
-                return CALL_STARTED;
-            case "call_joined":
-                return CALL_JOINED;
-            case "call_left":
-                return CALL_LEFT;
-            case "call_ended":
-                return CALL_ENDED;
-            case "guests_allowed":
-                return GUESTS_ALLOWED;
-            case "guests_disallowed":
-                return GUESTS_DISALLOWED;
-            case "password_set":
-                return PASSWORD_SET;
-            case "password_removed":
-                return PASSWORD_REMOVED;
-            case "user_added":
-                return USER_ADDED;
-            case "user_removed":
-                return USER_REMOVED;
-            case "moderator_promoted":
-                return MODERATOR_PROMOTED;
-            case "moderator_demoted":
-                return MODERATOR_DEMOTED;
-            case "file_shared":
-                return FILE_SHARED;
-            default:
-                return DUMMY;
-        }
-    }
-
-    @Override
-    public String convertToString(ChatMessage.SystemMessageType object) {
-
-        if (object == null) {
-            return "";
-        }
-
-        switch (object) {
-            case CONVERSATION_CREATED:
-                return "conversation_created";
-            case CONVERSATION_RENAMED:
-                return "conversation_renamed";
-            case CALL_STARTED:
-                return "call_started";
-            case CALL_JOINED:
-                return "call_joined";
-            case CALL_LEFT:
-                return "call_left";
-            case CALL_ENDED:
-                return "call_ended";
-            case GUESTS_ALLOWED:
-                return "guests_allowed";
-            case GUESTS_DISALLOWED:
-                return "guests_disallowed";
-            case PASSWORD_SET:
-                return "password_set";
-            case PASSWORD_REMOVED:
-                return "password_removed";
-            case USER_ADDED:
-                return "user_added";
-            case USER_REMOVED:
-                return "user_removed";
-            case MODERATOR_PROMOTED:
-                return "moderator_promoted";
-            case MODERATOR_DEMOTED:
-                return "moderator_demoted";
-            case FILE_SHARED:
-                return "file_shared";
-            default:
-                return "";
-        }
-    }
-}

+ 98 - 0
app/src/main/java/com/nextcloud/talk/models/json/converters/EnumSystemMessageTypeConverter.kt

@@ -0,0 +1,98 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.models.json.converters
+
+import com.bluelinelabs.logansquare.typeconverters.StringBasedTypeConverter
+import com.nextcloud.talk.models.json.chat.ChatMessage
+
+import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.*
+
+/*
+
+    conversation_created - {actor} created the conversation
+    conversation_renamed - {actor} renamed the conversation from "foo" to "bar"
+    call_joined - {actor} joined the call
+    call_left - {actor} left the call
+    call_ended - Call with {user1}, {user2}, {user3}, {user4} and {user5} (Duration 30:23)
+    guests_allowed - {actor} allowed guests in the conversation
+    guests_disallowed - {actor} disallowed guests in the conversation
+    password_set - {actor} set a password for the conversation
+    password_removed - {actor} removed the password for the conversation
+    user_added - {actor} added {user} to the conversation
+    user_removed - {actor} removed {user} from the conversation
+    moderator_promoted - {actor} promoted {user} to moderator
+    moderator_demoted - {actor} demoted {user} from moderator
+
+ */
+class EnumSystemMessageTypeConverter : StringBasedTypeConverter<ChatMessage.SystemMessageType>() {
+    override fun getFromString(string: String): ChatMessage.SystemMessageType {
+        when (string) {
+            "conversation_created" -> return CONVERSATION_CREATED
+            "conversation_renamed" -> return CONVERSATION_RENAMED
+            "call_started" -> return CALL_STARTED
+            "call_joined" -> return CALL_JOINED
+            "call_left" -> return CALL_LEFT
+            "call_ended" -> return CALL_ENDED
+            "guests_allowed" -> return GUESTS_ALLOWED
+            "guests_disallowed" -> return GUESTS_DISALLOWED
+            "password_set" -> return PASSWORD_SET
+            "password_removed" -> return PASSWORD_REMOVED
+            "user_added" -> return USER_ADDED
+            "user_removed" -> return USER_REMOVED
+            "moderator_promoted" -> return MODERATOR_PROMOTED
+            "moderator_demoted" -> return MODERATOR_DEMOTED
+            "file_shared" -> return FILE_SHARED
+            "lobby_none" -> return LOBBY_NONE
+            "lobby_non_moderators" -> return LOBBY_NON_MODERATORS
+            "lobby_timer_reached" -> return LOBBY_OPEN_TO_EVERYONE
+            else -> return DUMMY
+        }
+    }
+
+    override fun convertToString(`object`: ChatMessage.SystemMessageType?): String {
+
+        if (`object` == null) {
+            return ""
+        }
+
+        when (`object`) {
+            CONVERSATION_CREATED -> return "conversation_created"
+            CONVERSATION_RENAMED -> return "conversation_renamed"
+            CALL_STARTED -> return "call_started"
+            CALL_JOINED -> return "call_joined"
+            CALL_LEFT -> return "call_left"
+            CALL_ENDED -> return "call_ended"
+            GUESTS_ALLOWED -> return "guests_allowed"
+            GUESTS_DISALLOWED -> return "guests_disallowed"
+            PASSWORD_SET -> return "password_set"
+            PASSWORD_REMOVED -> return "password_removed"
+            USER_ADDED -> return "user_added"
+            USER_REMOVED -> return "user_removed"
+            MODERATOR_PROMOTED -> return "moderator_promoted"
+            MODERATOR_DEMOTED -> return "moderator_demoted"
+            FILE_SHARED -> return "file_shared"
+            LOBBY_NONE -> return "lobby_none"
+            LOBBY_NON_MODERATORS -> return "lobby_non_moderators"
+            LOBBY_OPEN_TO_EVERYONE -> return "lobby_timer_reached"
+            else -> return ""
+        }
+    }
+}

+ 3 - 3
app/src/main/java/com/nextcloud/talk/models/json/generic/GenericMeta.java

@@ -30,11 +30,11 @@ import org.parceler.Parcel;
 @JsonObject(serializeNullObjects = true)
 public class GenericMeta {
     @JsonField(name = "status")
-    String status;
+    public String status;
 
     @JsonField(name = "statuscode")
-    int statusCode;
+    public int statusCode;
 
     @JsonField(name = "message")
-    String message;
+    public String message;
 }

+ 1 - 1
app/src/main/java/com/nextcloud/talk/models/json/generic/GenericOCS.java

@@ -30,5 +30,5 @@ import org.parceler.Parcel;
 @JsonObject
 public class GenericOCS {
     @JsonField(name = "meta")
-    GenericMeta meta;
+    public GenericMeta meta;
 }

+ 1 - 1
app/src/main/java/com/nextcloud/talk/models/json/generic/GenericOverall.java

@@ -30,5 +30,5 @@ import org.parceler.Parcel;
 @JsonObject
 public class GenericOverall {
     @JsonField(name = "ocs")
-    GenericOCS ocs;
+    public GenericOCS ocs;
 }

+ 1 - 1
app/src/main/java/com/nextcloud/talk/models/json/participants/AddParticipantOCS.java

@@ -23,7 +23,7 @@ package com.nextcloud.talk.models.json.participants;
 import com.bluelinelabs.logansquare.annotation.JsonField;
 import com.bluelinelabs.logansquare.annotation.JsonObject;
 import com.nextcloud.talk.models.json.generic.GenericOCS;
-import com.nextcloud.talk.models.json.rooms.Conversation;
+import com.nextcloud.talk.models.json.conversations.Conversation;
 
 @JsonObject
 public class AddParticipantOCS extends GenericOCS {

+ 1 - 1
app/src/main/java/com/nextcloud/talk/models/json/participants/AddParticipantOverall.java

@@ -22,7 +22,7 @@ package com.nextcloud.talk.models.json.participants;
 
 import com.bluelinelabs.logansquare.annotation.JsonField;
 import com.bluelinelabs.logansquare.annotation.JsonObject;
-import com.nextcloud.talk.models.json.rooms.RoomsOCS;
+import com.nextcloud.talk.models.json.conversations.RoomsOCS;
 import lombok.Data;
 
 @Data

+ 10 - 10
app/src/main/java/com/nextcloud/talk/models/json/participants/Participant.java

@@ -33,32 +33,32 @@ import org.parceler.ParcelPropertyConverter;
 @JsonObject
 public class Participant {
     @JsonField(name = "userId")
-    String userId;
+    public String userId;
 
     @JsonField(name = {"type", "participantType"}, typeConverter = EnumParticipantTypeConverter.class)
-    ParticipantType type;
+    public ParticipantType type;
 
     @JsonField(name = "name")
-    String name;
+    public String name;
 
     @JsonField(name = "displayName")
-    String displayName;
+    public String displayName;
 
     @JsonField(name = "lastPing")
-    long lastPing;
+    public long lastPing;
 
     @JsonField(name = "sessionId")
-    String sessionId;
+    public String sessionId;
 
     @JsonField(name = "roomId")
-    long roomId;
+    public long roomId;
 
     @ParcelPropertyConverter(ObjectParcelConverter.class)
     @JsonField(name = "inCall")
-    Object inCall;
-    String source;
+    public Object inCall;
+    public String source;
 
-    boolean selected;
+    public boolean selected;
 
 
     public ParticipantFlags getParticipantFlags() {

+ 1 - 1
app/src/main/java/com/nextcloud/talk/models/json/participants/ParticipantsOCS.java

@@ -33,5 +33,5 @@ import java.util.List;
 @JsonObject
 public class ParticipantsOCS extends GenericOCS {
     @JsonField(name = "data")
-    List<Participant> data;
+    public List<Participant> data;
 }

+ 1 - 1
app/src/main/java/com/nextcloud/talk/models/json/participants/ParticipantsOverall.java

@@ -30,5 +30,5 @@ import org.parceler.Parcel;
 @JsonObject
 public class ParticipantsOverall {
     @JsonField(name = "ocs")
-    ParticipantsOCS ocs;
+    public ParticipantsOCS ocs;
 }

+ 1 - 1
app/src/main/java/com/nextcloud/talk/models/json/websocket/RoomPropertiesWebSocketMessage.java

@@ -23,7 +23,7 @@ package com.nextcloud.talk.models.json.websocket;
 import com.bluelinelabs.logansquare.annotation.JsonField;
 import com.bluelinelabs.logansquare.annotation.JsonObject;
 import com.nextcloud.talk.models.json.converters.EnumRoomTypeConverter;
-import com.nextcloud.talk.models.json.rooms.Conversation;
+import com.nextcloud.talk.models.json.conversations.Conversation;
 import lombok.Data;
 import org.parceler.Parcel;
 

+ 2 - 2
app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java

@@ -62,7 +62,7 @@ public class MentionAutocompletePresenter extends RecyclerViewPresenter<Mention>
     public MentionAutocompletePresenter(Context context) {
         super(context);
         this.context = context;
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
         currentUser = userUtils.getCurrentUser();
     }
 
@@ -70,7 +70,7 @@ public class MentionAutocompletePresenter extends RecyclerViewPresenter<Mention>
         super(context);
         this.roomToken = roomToken;
         this.context = context;
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
         currentUser = userUtils.getCurrentUser();
     }
 

+ 1 - 1
app/src/main/java/com/nextcloud/talk/receivers/PackageReplacedReceiver.java

@@ -49,7 +49,7 @@ public class PackageReplacedReceiver extends BroadcastReceiver {
 
     @Override
     public void onReceive(Context context, Intent intent) {
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
         if (intent != null && intent.getAction() != null &&
                 intent.getAction().equals("android.intent.action.MY_PACKAGE_REPLACED")) {

+ 0 - 156
app/src/main/java/com/nextcloud/talk/utils/AccountUtils.java

@@ -1,156 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * Parts related to account import were either copied from or inspired by the great work done by David Luhmer at:
- * https://github.com/nextcloud/ownCloud-Account-Importer
- */
-
-package com.nextcloud.talk.utils;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.Signature;
-import android.util.Log;
-import com.nextcloud.talk.R;
-import com.nextcloud.talk.application.NextcloudTalkApplication;
-import com.nextcloud.talk.models.ImportAccount;
-import com.nextcloud.talk.models.database.UserEntity;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class AccountUtils {
-
-    private static final String TAG = "AccountUtils";
-
-    public static List<Account> findAccounts(List<UserEntity> userEntitiesList) {
-        Context context = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
-        final AccountManager accMgr = AccountManager.get(context);
-        final Account[] accounts = accMgr.getAccountsByType(context.getString(R.string.nc_import_account_type));
-
-        List<Account> accountsAvailable = new ArrayList<>();
-        ImportAccount importAccount;
-        UserEntity internalUserEntity;
-        boolean accountFound;
-        for (Account account : accounts) {
-            accountFound = false;
-
-            for (int i = 0; i < userEntitiesList.size(); i++) {
-                internalUserEntity = userEntitiesList.get(i);
-                importAccount = getInformationFromAccount(account);
-                if (importAccount.getToken() != null) {
-                    if (importAccount.getBaseUrl().startsWith("http://") ||
-                            importAccount.getBaseUrl().startsWith("https://")) {
-                        if (internalUserEntity.getUsername().equals(importAccount.getUsername()) &&
-                                internalUserEntity.getBaseUrl().equals(importAccount.getBaseUrl())) {
-                            accountFound = true;
-                            break;
-                        }
-                    } else {
-                        if (internalUserEntity.getUsername().equals(importAccount.getUsername()) &&
-                                (internalUserEntity.getBaseUrl().equals("http://" + importAccount.getBaseUrl()) ||
-                                        internalUserEntity.getBaseUrl().equals("https://" +
-                                                importAccount.getBaseUrl()))) {
-                            accountFound = true;
-                            break;
-                        }
-
-                    }
-                } else {
-                    accountFound = true;
-                    break;
-                }
-            }
-
-            if (!accountFound) {
-                accountsAvailable.add(account);
-            }
-        }
-
-        return accountsAvailable;
-    }
-
-    public static String getAppNameBasedOnPackage(String packageName) {
-        Context context = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
-        PackageManager packageManager = context.getPackageManager();
-        String appName = "";
-        try {
-            appName = (String) packageManager.getApplicationLabel(packageManager.getApplicationInfo(packageName,
-                    PackageManager.GET_META_DATA));
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.e(TAG, "Failed to get app name based on package");
-        }
-
-        return appName;
-    }
-
-    public static boolean canWeOpenFilesApp(Context context, String accountName) {
-        PackageManager pm = context.getPackageManager();
-        try {
-            PackageInfo packageInfo =
-                    pm.getPackageInfo(context.getString(R.string.nc_import_accounts_from), 0);
-            if (packageInfo.versionCode >= 30060151) {
-                Signature[] ownSignatures = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES).signatures;
-                Signature[] filesAppSignatures = pm.getPackageInfo(context.getString(R.string.nc_import_accounts_from), PackageManager.GET_SIGNATURES).signatures;
-
-                if (Arrays.equals(ownSignatures, filesAppSignatures)) {
-                    final AccountManager accMgr = AccountManager.get(context);
-                    final Account[] accounts = accMgr.getAccountsByType(context.getString(R.string.nc_import_account_type));
-                    for (Account account : accounts) {
-                        if (account.name.equals(accountName)) {
-                            return true;
-                        }
-                    }
-                } else {
-                    return true;
-                }
-            }
-        } catch (PackageManager.NameNotFoundException appNotFoundException) {
-
-        }
-        return false;
-    }
-
-    public static ImportAccount getInformationFromAccount(Account account) {
-        int lastAtPos = account.name.lastIndexOf("@");
-        String urlString = account.name.substring(lastAtPos + 1);
-        String username = account.name.substring(0, lastAtPos);
-
-        Context context = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
-        final AccountManager accMgr = AccountManager.get(context);
-
-        String password = null;
-        try {
-            password = accMgr.getPassword(account);
-        } catch (Exception exception) {
-            Log.e(TAG, "Failed to import account");
-        }
-
-        if (urlString.endsWith("/")) {
-            urlString = urlString.substring(0, urlString.length() - 1);
-        }
-
-        return new ImportAccount(username, password, urlString);
-    }
-}
-

+ 149 - 0
app/src/main/java/com/nextcloud/talk/utils/AccountUtils.kt

@@ -0,0 +1,149 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Parts related to account import were either copied from or inspired by the great work done by David Luhmer at:
+ * https://github.com/nextcloud/ownCloud-Account-Importer
+ */
+
+package com.nextcloud.talk.utils
+
+import android.accounts.Account
+import android.accounts.AccountManager
+import android.content.Context
+import android.content.pm.PackageManager
+import android.util.Log
+import com.nextcloud.talk.R
+import com.nextcloud.talk.application.NextcloudTalkApplication
+import com.nextcloud.talk.models.ImportAccount
+import com.nextcloud.talk.models.database.UserEntity
+import java.util.*
+
+object AccountUtils {
+
+    private val TAG = "AccountUtils"
+
+    fun findAccounts(userEntitiesList: List<UserEntity>): List<Account> {
+        val context = NextcloudTalkApplication.sharedApplication!!.applicationContext
+        val accMgr = AccountManager.get(context)
+        val accounts = accMgr.getAccountsByType(context.getString(R.string.nc_import_account_type))
+
+        val accountsAvailable = ArrayList<Account>()
+        var importAccount: ImportAccount
+        var internalUserEntity: UserEntity
+        var accountFound: Boolean
+        for (account in accounts) {
+            accountFound = false
+
+            for (i in userEntitiesList.indices) {
+                internalUserEntity = userEntitiesList[i]
+                importAccount = getInformationFromAccount(account)
+                if (importAccount.token != null) {
+                    if (importAccount.baseUrl.startsWith("http://") || importAccount.baseUrl.startsWith("https://")) {
+                        if (internalUserEntity.username == importAccount.username && internalUserEntity.baseUrl == importAccount.baseUrl) {
+                            accountFound = true
+                            break
+                        }
+                    } else {
+                        if (internalUserEntity.username == importAccount.username && (internalUserEntity
+                                        .baseUrl == "http://" + importAccount.baseUrl ||
+                                        internalUserEntity.baseUrl == "https://" + importAccount
+                                        .baseUrl)) {
+                            accountFound = true
+                            break
+                        }
+
+                    }
+                } else {
+                    accountFound = true
+                    break
+                }
+            }
+
+            if (!accountFound) {
+                accountsAvailable.add(account)
+            }
+        }
+
+        return accountsAvailable
+    }
+
+    fun getAppNameBasedOnPackage(packageName: String): String {
+        val context = NextcloudTalkApplication.sharedApplication!!.applicationContext
+        val packageManager = context.packageManager
+        var appName = ""
+        try {
+            appName = packageManager.getApplicationLabel(packageManager.getApplicationInfo(packageName,
+                    PackageManager.GET_META_DATA)) as String
+        } catch (e: PackageManager.NameNotFoundException) {
+            Log.e(TAG, "Failed to get app name based on package")
+        }
+
+        return appName
+    }
+
+    fun canWeOpenFilesApp(context: Context, accountName: String): Boolean {
+        val pm = context.packageManager
+        try {
+            val packageInfo = pm.getPackageInfo(context.getString(R.string.nc_import_accounts_from), 0)
+            if (packageInfo.versionCode >= 30060151) {
+                val ownSignatures = pm.getPackageInfo(context.packageName, PackageManager.GET_SIGNATURES).signatures
+                val filesAppSignatures = pm.getPackageInfo(context.getString(R.string.nc_import_accounts_from), PackageManager.GET_SIGNATURES).signatures
+
+                if (Arrays.equals(ownSignatures, filesAppSignatures)) {
+                    val accMgr = AccountManager.get(context)
+                    val accounts = accMgr.getAccountsByType(context.getString(R.string.nc_import_account_type))
+                    for (account in accounts) {
+                        if (account.name == accountName) {
+                            return true
+                        }
+                    }
+                } else {
+                    return true
+                }
+            }
+        } catch (appNotFoundException: PackageManager.NameNotFoundException) {
+
+        }
+
+        return false
+    }
+
+    fun getInformationFromAccount(account: Account): ImportAccount {
+        val lastAtPos = account.name.lastIndexOf("@")
+        var urlString = account.name.substring(lastAtPos + 1)
+        val username = account.name.substring(0, lastAtPos)
+
+        val context = NextcloudTalkApplication.sharedApplication!!.applicationContext
+        val accMgr = AccountManager.get(context)
+
+        var password: String? = null
+        try {
+            password = accMgr.getPassword(account)
+        } catch (exception: Exception) {
+            Log.e(TAG, "Failed to import account")
+        }
+
+        if (urlString.endsWith("/")) {
+            urlString = urlString.substring(0, urlString.length - 1)
+        }
+
+        return ImportAccount(username, password, urlString)
+    }
+}
+

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

@@ -42,6 +42,10 @@ public class ApiUtils {
         return userAgent + BuildConfig.VERSION_NAME;
     }
 
+    public static String getUrlForLobbyForConversation(String baseUrl, String token) {
+        return getRoom(baseUrl, token) + "/webinary/lobby";
+    }
+
     public static RetrofitBucket getRetrofitBucketForContactsSearch(String baseUrl, @Nullable String searchQuery) {
         RetrofitBucket retrofitBucket = new RetrofitBucket();
         retrofitBucket.setUrl(baseUrl + ocsApiVersion + "/apps/files_sharing/api/v1/sharees");
@@ -215,7 +219,7 @@ public class ApiUtils {
 
     public static String getUrlForAvatarWithName(String baseUrl, String name, @DimenRes int avatarSize) {
         avatarSize = Math.round(NextcloudTalkApplication
-                .getSharedApplication().getResources().getDimension(avatarSize));
+                .Companion.getSharedApplication().getResources().getDimension(avatarSize));
 
         return baseUrl + "/index.php/avatar/" + Uri.encode(name) + "/" + avatarSize;
     }
@@ -236,7 +240,7 @@ public class ApiUtils {
     }
 
     public static String getUrlPushProxy() {
-        return NextcloudTalkApplication.getSharedApplication().
+        return NextcloudTalkApplication.Companion.getSharedApplication().
                 getApplicationContext().getResources().getString(R.string.nc_push_server_url) + "/devices";
     }
 

+ 0 - 39
app/src/main/java/com/nextcloud/talk/utils/BottomNavigationUtils.java

@@ -1,39 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * The bottom navigation was taken from a PR to Conductor by Chris6647@gmail.com
- * https://github.com/bluelinelabs/Conductor/pull/316 and https://github.com/chris6647/Conductor/pull/1/files
- * and of course modified by yours truly.
- */
-
-package com.nextcloud.talk.utils;
-
-public class BottomNavigationUtils {
-
-    /**
-     * Copy/paste from {@link java.util.Objects#equals(Object, Object)} to support lower API version
-     *
-     * @param a
-     * @param b
-     * @return
-     */
-    public static boolean equals(Object a, Object b) {
-        return (a == b) || (a != null && a.equals(b));
-    }
-}

+ 0 - 59
app/src/main/java/com/nextcloud/talk/utils/ConductorRemapping.java

@@ -1,59 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.nextcloud.talk.utils;
-
-import android.os.Bundle;
-import com.bluelinelabs.conductor.Router;
-import com.bluelinelabs.conductor.RouterTransaction;
-import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
-import com.nextcloud.talk.controllers.ChatController;
-
-import java.util.List;
-
-public class ConductorRemapping {
-    public static void remapChatController(Router router, long internalUserId, String roomTokenOrId, Bundle bundle, boolean replaceTop) {
-        String tag = internalUserId + "@" + roomTokenOrId;
-        if (router.getControllerWithTag(tag) != null) {
-            List<RouterTransaction> backstack = router.getBackstack();
-            RouterTransaction routerTransaction = null;
-            for (int i = 0; i < router.getBackstackSize(); i++) {
-                if (tag.equals(backstack.get(i).tag())) {
-                    routerTransaction = backstack.get(i);
-                    backstack.remove(routerTransaction);
-                    break;
-                }
-            }
-
-            backstack.add(routerTransaction);
-            router.setBackstack(backstack, new HorizontalChangeHandler());
-        } else {
-            if (!replaceTop) {
-                router.pushController(RouterTransaction.with(new ChatController(bundle))
-                        .pushChangeHandler(new HorizontalChangeHandler())
-                        .popChangeHandler(new HorizontalChangeHandler()).tag(tag));
-            } else {
-                router.replaceTopController(RouterTransaction.with(new ChatController(bundle))
-                        .pushChangeHandler(new HorizontalChangeHandler())
-                        .popChangeHandler(new HorizontalChangeHandler()).tag(tag));
-            }
-        }
-    }
-}

+ 57 - 0
app/src/main/java/com/nextcloud/talk/utils/ConductorRemapping.kt

@@ -0,0 +1,57 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.utils
+
+import android.os.Bundle
+import com.bluelinelabs.conductor.Router
+import com.bluelinelabs.conductor.RouterTransaction
+import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
+import com.nextcloud.talk.controllers.ChatController
+
+object ConductorRemapping {
+    fun remapChatController(router: Router, internalUserId: Long, roomTokenOrId: String, bundle: Bundle, replaceTop: Boolean) {
+        val tag = "$internalUserId@$roomTokenOrId"
+        if (router.getControllerWithTag(tag) != null) {
+            val backstack = router.backstack
+            var routerTransaction: RouterTransaction? = null
+            for (i in 0 until router.backstackSize) {
+                if (tag == backstack[i].tag()) {
+                    routerTransaction = backstack[i]
+                    backstack.remove(routerTransaction)
+                    break
+                }
+            }
+
+            backstack.add(routerTransaction)
+            router.setBackstack(backstack, HorizontalChangeHandler())
+        } else {
+            if (!replaceTop) {
+                router.pushController(RouterTransaction.with(ChatController(bundle))
+                        .pushChangeHandler(HorizontalChangeHandler())
+                        .popChangeHandler(HorizontalChangeHandler()).tag(tag))
+            } else {
+                router.replaceTopController(RouterTransaction.with(ChatController(bundle))
+                        .pushChangeHandler(HorizontalChangeHandler())
+                        .popChangeHandler(HorizontalChangeHandler()).tag(tag))
+            }
+        }
+    }
+}

+ 15 - 15
app/src/main/java/com/nextcloud/talk/utils/DateUtils.java → app/src/main/java/com/nextcloud/talk/utils/DateUtils.kt

@@ -18,26 +18,26 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-package com.nextcloud.talk.utils;
+package com.nextcloud.talk.utils
 
-import android.content.Context;
+import java.text.DateFormat
+import java.util.*
 
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
 
-public class DateUtils {
-    public static String getLocalDateTimeStringFromTimestamp(Context context, long timestamp) {
-        Calendar cal = Calendar.getInstance();
-        TimeZone tz = cal.getTimeZone();
+object DateUtils {
+    fun getLocalDateTimeStringFromTimestamp(timestamp: Long): String {
+        val cal = Calendar.getInstance()
+        val tz = cal.timeZone
 
         /* date formatter in local timezone */
-        Locale currentLocale = context.getResources().getConfiguration().locale;
-        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss", currentLocale);
-        sdf.setTimeZone(tz);
+        val format = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.MEDIUM, Locale
+                .getDefault())
+        format.timeZone = tz
 
-        return sdf.format(new Date(timestamp));
+        return format.format(Date(timestamp))
+    }
+
+    fun getLocalDateStringFromTimestampForLobby(timestamp: Long): String {
+        return getLocalDateTimeStringFromTimestamp(timestamp * 1000);
     }
 }

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

@@ -42,7 +42,7 @@ public class DeviceUtils {
                     Method setApplicationAutoStartMethod = appOpsUtilsClass.getMethod("setApplicationAutoStart", Context
                             .class, String.class, Boolean.TYPE);
                     if (setApplicationAutoStartMethod != null) {
-                        Context applicationContext = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
+                        Context applicationContext = NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext();
                         setApplicationAutoStartMethod.invoke(appOpsUtilsClass, applicationContext, applicationContext
                                 .getPackageName(), Boolean.TRUE);
                     }
@@ -61,7 +61,7 @@ public class DeviceUtils {
                 @SuppressLint("PrivateApi") Class<?> protectAppControlClass = Class.forName("com.huawei.systemmanager.optimize.process" +
                         ".ProtectAppControl");
                 if (protectAppControlClass != null) {
-                    Context applicationContext = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
+                    Context applicationContext = NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext();
 
                     Method getInstanceMethod = protectAppControlClass.getMethod("getInstance", Context.class);
                     // ProtectAppControl instance

+ 3 - 3
app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java

@@ -96,7 +96,7 @@ public class DisplayUtils {
             public void onClick(@Nonnull View widget) {
                 Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                 browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                NextcloudTalkApplication.getSharedApplication().getApplicationContext().startActivity(browserIntent);
+                NextcloudTalkApplication.Companion.getSharedApplication().getApplicationContext().startActivity(browserIntent);
             }
 
             @Override
@@ -344,7 +344,7 @@ public class DisplayUtils {
                 .matcher(spannableString);
 
 
-        int textSize = NextcloudTalkApplication.getSharedApplication().getResources().getDimensionPixelSize(R.dimen
+        int textSize = NextcloudTalkApplication.Companion.getSharedApplication().getResources().getDimensionPixelSize(R.dimen
                 .chat_text_size);
 
         int lastStartIndex = -1;
@@ -364,7 +364,7 @@ public class DisplayUtils {
     public static Drawable getMessageSelector(@ColorInt int normalColor, @ColorInt int selectedColor,
                                               @ColorInt int pressedColor, @DrawableRes int shape) {
 
-        Drawable vectorDrawable = ContextCompat.getDrawable(NextcloudTalkApplication.getSharedApplication()
+        Drawable vectorDrawable = ContextCompat.getDrawable(NextcloudTalkApplication.Companion.getSharedApplication()
                         .getApplicationContext(),
                 shape);
         Drawable drawable = DrawableCompat.wrap(vectorDrawable).mutate();

+ 0 - 79
app/src/main/java/com/nextcloud/talk/utils/DoNotDisturbUtils.java

@@ -1,79 +0,0 @@
-/*
- * 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;
-
-import android.app.NotificationManager;
-import android.content.Context;
-import android.media.AudioManager;
-import android.os.Build;
-import android.os.Vibrator;
-import com.nextcloud.talk.application.NextcloudTalkApplication;
-
-public class DoNotDisturbUtils {
-    private static final String TAG = "DoNotDisturbUtils";
-
-    public static boolean shouldPlaySound() {
-        Context context = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
-
-        NotificationManager notificationManager =
-                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-
-        boolean shouldPlaySound = true;
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && notificationManager != null) {
-            if (notificationManager.getCurrentInterruptionFilter() != NotificationManager.INTERRUPTION_FILTER_ALL) {
-                shouldPlaySound = false;
-            }
-        }
-
-        if (audioManager != null && shouldPlaySound) {
-            if (audioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
-                shouldPlaySound = false;
-            }
-        }
-
-        return shouldPlaySound;
-    }
-
-    public static boolean hasVibrator() {
-        Context context = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
-        Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
-        return (vibrator != null && vibrator.hasVibrator());
-    }
-
-    public static boolean shouldVibrate(boolean vibrate) {
-
-        if (hasVibrator()) {
-            Context context = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
-            AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-
-            if (audioManager != null) {
-                if (vibrate) {
-                    return (audioManager.getRingerMode() != AudioManager.RINGER_MODE_SILENT);
-                } else {
-                    return (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
-                }
-            }
-        }
-
-        return false;
-    }
-}

+ 74 - 0
app/src/main/java/com/nextcloud/talk/utils/DoNotDisturbUtils.kt

@@ -0,0 +1,74 @@
+/*
+ * 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
+
+import android.app.NotificationManager
+import android.content.Context
+import android.media.AudioManager
+import android.os.Build
+import android.os.Vibrator
+import com.nextcloud.talk.application.NextcloudTalkApplication
+
+object DoNotDisturbUtils {
+    fun shouldPlaySound(): Boolean {
+        val context = NextcloudTalkApplication.sharedApplication?.applicationContext
+
+        val notificationManager = context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+        val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
+
+        var shouldPlaySound = true
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (notificationManager.currentInterruptionFilter != NotificationManager.INTERRUPTION_FILTER_ALL) {
+                shouldPlaySound = false
+            }
+        }
+
+        if (shouldPlaySound) {
+            if (audioManager.ringerMode != AudioManager.RINGER_MODE_NORMAL) {
+                shouldPlaySound = false
+            }
+        }
+
+        return shouldPlaySound
+    }
+
+    fun hasVibrator(): Boolean {
+        val context = NextcloudTalkApplication.sharedApplication?.applicationContext
+        val vibrator = context?.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
+        return vibrator.hasVibrator()
+    }
+
+    fun shouldVibrate(vibrate: Boolean): Boolean {
+
+        if (hasVibrator()) {
+            val context = NextcloudTalkApplication.sharedApplication?.applicationContext
+            val audioManager = context?.getSystemService(Context.AUDIO_SERVICE) as AudioManager
+
+            return if (vibrate) {
+                audioManager.ringerMode != AudioManager.RINGER_MODE_SILENT
+            } else {
+                audioManager.ringerMode == AudioManager.RINGER_MODE_VIBRATE
+            }
+        }
+
+        return false
+    }
+}

+ 0 - 161
app/src/main/java/com/nextcloud/talk/utils/DrawableUtils.java

@@ -1,161 +0,0 @@
-/*
- * 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;
-
-import com.nextcloud.talk.R;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class DrawableUtils {
-
-
-    public static int getDrawableResourceIdForMimeType(String mimetype) {
-        Map<String, Integer> drawableMap = new HashMap<>();
-
-        // Initial list of mimetypes was acquired from https://github.com/nextcloud/server/blob/694ba5435b2963e201f6a6d2c775836bde07aaef/core/js/mimetypelist.js
-        drawableMap.put("application/coreldraw", R.drawable.ic_mimetype_image);
-        drawableMap.put("application/epub+zip", R.drawable.ic_mimetype_text);
-        drawableMap.put("application/font-sfnt", R.drawable.ic_mimetype_image);
-        drawableMap.put("application/font-woff", R.drawable.ic_mimetype_image);
-        drawableMap.put("application/gpx+xml", R.drawable.ic_mimetype_location);
-        drawableMap.put("application/illustrator", R.drawable.ic_mimetype_image);
-        drawableMap.put("application/javascript", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("application/json", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("application/msaccess", R.drawable.ic_mimetype_file);
-        drawableMap.put("application/msexcel", R.drawable.ic_mimetype_x_office_spreadsheet);
-        drawableMap.put("application/msonenote", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/mspowerpoint", R.drawable.ic_mimetype_x_office_presentation);
-        drawableMap.put("application/msword", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/octet-stream", R.drawable.ic_mimetype_file);
-        drawableMap.put("application/postscript", R.drawable.ic_mimetype_image);
-        drawableMap.put("application/rss+xml", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("application/vnd.android.package-archive", R.drawable.ic_mimetype_package_x_generic);
-        drawableMap.put("application/vnd.lotus-wordpro", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.garmin.tcx+xml", R.drawable.ic_mimetype_location);
-        drawableMap.put("application/vnd.google-earth.kml+xml", R.drawable.ic_mimetype_location);
-        drawableMap.put("application/vnd.google-earth.kmz", R.drawable.ic_mimetype_location);
-        drawableMap.put("application/vnd.ms-excel", R.drawable.ic_mimetype_x_office_spreadsheet);
-        drawableMap.put("application/vnd.ms-excel.addin.macroEnabled.12", R.drawable.ic_mimetype_x_office_spreadsheet);
-        drawableMap.put("application/vnd.ms-excel.sheet.binary.macroEnabled.12", R.drawable.ic_mimetype_x_office_spreadsheet);
-        drawableMap.put("application/vnd.ms-excel.sheet.macroEnabled.12", R.drawable.ic_mimetype_x_office_spreadsheet);
-        drawableMap.put("application/vnd.ms-excel.template.macroEnabled.12", R.drawable.ic_mimetype_x_office_spreadsheet);
-        drawableMap.put("application/vnd.ms-fontobject", R.drawable.ic_mimetype_image);
-        drawableMap.put("application/vnd.ms-powerpoint", R.drawable.ic_mimetype_x_office_presentation);
-        drawableMap.put("application/vnd.ms-powerpoint.addin.macroEnabled.12", R.drawable.ic_mimetype_x_office_presentation);
-        drawableMap.put("application/vnd.ms-powerpoint.presentation.macroEnabled.12", R.drawable.ic_mimetype_x_office_presentation);
-        drawableMap.put("application/vnd.ms-powerpoint.slideshow.macroEnabled.12", R.drawable.ic_mimetype_x_office_presentation);
-        drawableMap.put("application/vnd.ms-powerpoint.template.macroEnabled.12", R.drawable.ic_mimetype_x_office_presentation);
-        drawableMap.put("application/vnd.ms-visio.drawing.macroEnabled.12", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.ms-visio.drawing", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.ms-visio.stencil.macroEnabled.12", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.ms-visio.stencil", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.ms-visio.template.macroEnabled.12", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.ms-visio.template", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.ms-word.template.macroEnabled.12", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.oasis.opendocument.presentation", R.drawable.ic_mimetype_x_office_presentation);
-        drawableMap.put("application/vnd.oasis.opendocument.presentation-template", R.drawable.ic_mimetype_x_office_presentation);
-        drawableMap.put("application/vnd.oasis.opendocument.spreadsheet", R.drawable.ic_mimetype_x_office_spreadsheet);
-        drawableMap.put("application/vnd.oasis.opendocument.spreadsheet-template", R.drawable.ic_mimetype_x_office_spreadsheet);
-        drawableMap.put("application/vnd.oasis.opendocument.text", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.oasis.opendocument.text-master", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.oasis.opendocument.text-template", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.oasis.opendocument.text-web", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.openxmlformats-officedocument.presentationml.presentation", R.drawable.ic_mimetype_x_office_presentation);
-        drawableMap.put("application/vnd.openxmlformats-officedocument.presentationml.slideshow", R.drawable.ic_mimetype_x_office_presentation);
-        drawableMap.put("application/vnd.openxmlformats-officedocument.presentationml.template", R.drawable.ic_mimetype_x_office_presentation);
-        drawableMap.put("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", R.drawable.ic_mimetype_x_office_spreadsheet);
-        drawableMap.put("application/vnd.openxmlformats-officedocument.spreadsheetml.template", R.drawable.ic_mimetype_x_office_spreadsheet);
-        drawableMap.put("application/vnd.openxmlformats-officedocument.wordprocessingml.document", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.openxmlformats-officedocument.wordprocessingml.template", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.visio", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/vnd.wordperfect", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/x-7z-compressed", R.drawable.ic_mimetype_package_x_generic);
-        drawableMap.put("application/x-bzip2", R.drawable.ic_mimetype_package_x_generic);
-        drawableMap.put("application/x-cbr", R.drawable.ic_mimetype_text);
-        drawableMap.put("application/x-compressed", R.drawable.ic_mimetype_package_x_generic);
-        drawableMap.put("application/x-dcraw", R.drawable.ic_mimetype_image);
-        drawableMap.put("application/x-deb", R.drawable.ic_mimetype_package_x_generic);
-        drawableMap.put("application/x-fictionbook+xml", R.drawable.ic_mimetype_text);
-        drawableMap.put("application/x-font", R.drawable.ic_mimetype_image);
-        drawableMap.put("application/x-gimp", R.drawable.ic_mimetype_image);
-        drawableMap.put("application/x-gzip", R.drawable.ic_mimetype_package_x_generic);
-        drawableMap.put("application/x-iwork-keynote-sffkey", R.drawable.ic_mimetype_x_office_presentation);
-        drawableMap.put("application/x-iwork-numbers-sffnumbers", R.drawable.ic_mimetype_x_office_spreadsheet);
-        drawableMap.put("application/x-iwork-pages-sffpages", R.drawable.ic_mimetype_x_office_document);
-        drawableMap.put("application/x-mobipocket-ebook", R.drawable.ic_mimetype_text);
-        drawableMap.put("application/x-perl", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("application/x-photoshop", R.drawable.ic_mimetype_image);
-        drawableMap.put("application/x-php", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("application/x-rar-compressed", R.drawable.ic_mimetype_package_x_generic);
-        drawableMap.put("application/x-tar", R.drawable.ic_mimetype_package_x_generic);
-        drawableMap.put("application/x-tex", R.drawable.ic_mimetype_text);
-        drawableMap.put("application/xml", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("application/yaml", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("application/zip", R.drawable.ic_mimetype_package_x_generic);
-        drawableMap.put("database", R.drawable.ic_mimetype_file);
-        drawableMap.put("httpd/unix-directory", R.drawable.ic_mimetype_folder);
-        drawableMap.put("text/css", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("text/csv", R.drawable.ic_mimetype_x_office_spreadsheet);
-        drawableMap.put("text/html", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("text/x-c", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("text/x-c++src", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("text/x-h", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("text/x-java-source", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("text/x-ldif", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("text/x-python", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("text/x-shellscript", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("web", R.drawable.ic_mimetype_text_code);
-        drawableMap.put("application/internet-shortcut", R.drawable.ic_mimetype_link);
-
-        drawableMap.put("inode/directory", R.drawable.ic_mimetype_folder);
-        drawableMap.put("unknown", R.drawable.ic_mimetype_file);
-        drawableMap.put("application/pdf", R.drawable.ic_mimetype_application_pdf);
-
-        if ("DIR".equals(mimetype)) {
-            mimetype = "inode/directory";
-            return drawableMap.get(mimetype);
-        }
-
-        if (drawableMap.containsKey(mimetype)) {
-            return drawableMap.get(mimetype);
-        }
-
-        if (mimetype.startsWith("image/")) {
-            return R.drawable.ic_mimetype_image;
-        }
-
-        if (mimetype.startsWith("video/")) {
-            return R.drawable.ic_mimetype_video;
-        }
-
-        if (mimetype.startsWith("text/")) {
-            return R.drawable.ic_mimetype_text;
-        }
-
-        if (mimetype.startsWith("audio")) {
-            return R.drawable.ic_mimetype_audio;
-        }
-
-        return drawableMap.get("unknown");
-    }
-
-}

+ 158 - 0
app/src/main/java/com/nextcloud/talk/utils/DrawableUtils.kt

@@ -0,0 +1,158 @@
+/*
+ * 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
+
+import com.nextcloud.talk.R
+
+import java.util.HashMap
+
+object DrawableUtils {
+
+
+    fun getDrawableResourceIdForMimeType(mimetype: String): Int {
+        var localMimetype = mimetype
+        val drawableMap = HashMap<String, Int>()
+
+        // Initial list of mimetypes was acquired from https://github.com/nextcloud/server/blob/694ba5435b2963e201f6a6d2c775836bde07aaef/core/js/mimetypelist.js
+        drawableMap["application/coreldraw"] = R.drawable.ic_mimetype_image
+        drawableMap["application/epub+zip"] = R.drawable.ic_mimetype_text
+        drawableMap["application/font-sfnt"] = R.drawable.ic_mimetype_image
+        drawableMap["application/font-woff"] = R.drawable.ic_mimetype_image
+        drawableMap["application/gpx+xml"] = R.drawable.ic_mimetype_location
+        drawableMap["application/illustrator"] = R.drawable.ic_mimetype_image
+        drawableMap["application/javascript"] = R.drawable.ic_mimetype_text_code
+        drawableMap["application/json"] = R.drawable.ic_mimetype_text_code
+        drawableMap["application/msaccess"] = R.drawable.ic_mimetype_file
+        drawableMap["application/msexcel"] = R.drawable.ic_mimetype_x_office_spreadsheet
+        drawableMap["application/msonenote"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/mspowerpoint"] = R.drawable.ic_mimetype_x_office_presentation
+        drawableMap["application/msword"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/octet-stream"] = R.drawable.ic_mimetype_file
+        drawableMap["application/postscript"] = R.drawable.ic_mimetype_image
+        drawableMap["application/rss+xml"] = R.drawable.ic_mimetype_text_code
+        drawableMap["application/vnd.android.package-archive"] = R.drawable.ic_mimetype_package_x_generic
+        drawableMap["application/vnd.lotus-wordpro"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.garmin.tcx+xml"] = R.drawable.ic_mimetype_location
+        drawableMap["application/vnd.google-earth.kml+xml"] = R.drawable.ic_mimetype_location
+        drawableMap["application/vnd.google-earth.kmz"] = R.drawable.ic_mimetype_location
+        drawableMap["application/vnd.ms-excel"] = R.drawable.ic_mimetype_x_office_spreadsheet
+        drawableMap["application/vnd.ms-excel.addin.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_spreadsheet
+        drawableMap["application/vnd.ms-excel.sheet.binary.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_spreadsheet
+        drawableMap["application/vnd.ms-excel.sheet.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_spreadsheet
+        drawableMap["application/vnd.ms-excel.template.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_spreadsheet
+        drawableMap["application/vnd.ms-fontobject"] = R.drawable.ic_mimetype_image
+        drawableMap["application/vnd.ms-powerpoint"] = R.drawable.ic_mimetype_x_office_presentation
+        drawableMap["application/vnd.ms-powerpoint.addin.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_presentation
+        drawableMap["application/vnd.ms-powerpoint.presentation.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_presentation
+        drawableMap["application/vnd.ms-powerpoint.slideshow.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_presentation
+        drawableMap["application/vnd.ms-powerpoint.template.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_presentation
+        drawableMap["application/vnd.ms-visio.drawing.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.ms-visio.drawing"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.ms-visio.stencil.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.ms-visio.stencil"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.ms-visio.template.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.ms-visio.template"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.ms-word.template.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.oasis.opendocument.presentation"] = R.drawable.ic_mimetype_x_office_presentation
+        drawableMap["application/vnd.oasis.opendocument.presentation-template"] = R.drawable.ic_mimetype_x_office_presentation
+        drawableMap["application/vnd.oasis.opendocument.spreadsheet"] = R.drawable.ic_mimetype_x_office_spreadsheet
+        drawableMap["application/vnd.oasis.opendocument.spreadsheet-template"] = R.drawable.ic_mimetype_x_office_spreadsheet
+        drawableMap["application/vnd.oasis.opendocument.text"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.oasis.opendocument.text-master"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.oasis.opendocument.text-template"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.oasis.opendocument.text-web"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.openxmlformats-officedocument.presentationml.presentation"] = R.drawable.ic_mimetype_x_office_presentation
+        drawableMap["application/vnd.openxmlformats-officedocument.presentationml.slideshow"] = R.drawable.ic_mimetype_x_office_presentation
+        drawableMap["application/vnd.openxmlformats-officedocument.presentationml.template"] = R.drawable.ic_mimetype_x_office_presentation
+        drawableMap["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"] = R.drawable.ic_mimetype_x_office_spreadsheet
+        drawableMap["application/vnd.openxmlformats-officedocument.spreadsheetml.template"] = R.drawable.ic_mimetype_x_office_spreadsheet
+        drawableMap["application/vnd.openxmlformats-officedocument.wordprocessingml.document"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.openxmlformats-officedocument.wordprocessingml.template"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.visio"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/vnd.wordperfect"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/x-7z-compressed"] = R.drawable.ic_mimetype_package_x_generic
+        drawableMap["application/x-bzip2"] = R.drawable.ic_mimetype_package_x_generic
+        drawableMap["application/x-cbr"] = R.drawable.ic_mimetype_text
+        drawableMap["application/x-compressed"] = R.drawable.ic_mimetype_package_x_generic
+        drawableMap["application/x-dcraw"] = R.drawable.ic_mimetype_image
+        drawableMap["application/x-deb"] = R.drawable.ic_mimetype_package_x_generic
+        drawableMap["application/x-fictionbook+xml"] = R.drawable.ic_mimetype_text
+        drawableMap["application/x-font"] = R.drawable.ic_mimetype_image
+        drawableMap["application/x-gimp"] = R.drawable.ic_mimetype_image
+        drawableMap["application/x-gzip"] = R.drawable.ic_mimetype_package_x_generic
+        drawableMap["application/x-iwork-keynote-sffkey"] = R.drawable.ic_mimetype_x_office_presentation
+        drawableMap["application/x-iwork-numbers-sffnumbers"] = R.drawable.ic_mimetype_x_office_spreadsheet
+        drawableMap["application/x-iwork-pages-sffpages"] = R.drawable.ic_mimetype_x_office_document
+        drawableMap["application/x-mobipocket-ebook"] = R.drawable.ic_mimetype_text
+        drawableMap["application/x-perl"] = R.drawable.ic_mimetype_text_code
+        drawableMap["application/x-photoshop"] = R.drawable.ic_mimetype_image
+        drawableMap["application/x-php"] = R.drawable.ic_mimetype_text_code
+        drawableMap["application/x-rar-compressed"] = R.drawable.ic_mimetype_package_x_generic
+        drawableMap["application/x-tar"] = R.drawable.ic_mimetype_package_x_generic
+        drawableMap["application/x-tex"] = R.drawable.ic_mimetype_text
+        drawableMap["application/xml"] = R.drawable.ic_mimetype_text_code
+        drawableMap["application/yaml"] = R.drawable.ic_mimetype_text_code
+        drawableMap["application/zip"] = R.drawable.ic_mimetype_package_x_generic
+        drawableMap["database"] = R.drawable.ic_mimetype_file
+        drawableMap["httpd/unix-directory"] = R.drawable.ic_mimetype_folder
+        drawableMap["text/css"] = R.drawable.ic_mimetype_text_code
+        drawableMap["text/csv"] = R.drawable.ic_mimetype_x_office_spreadsheet
+        drawableMap["text/html"] = R.drawable.ic_mimetype_text_code
+        drawableMap["text/x-c"] = R.drawable.ic_mimetype_text_code
+        drawableMap["text/x-c++src"] = R.drawable.ic_mimetype_text_code
+        drawableMap["text/x-h"] = R.drawable.ic_mimetype_text_code
+        drawableMap["text/x-java-source"] = R.drawable.ic_mimetype_text_code
+        drawableMap["text/x-ldif"] = R.drawable.ic_mimetype_text_code
+        drawableMap["text/x-python"] = R.drawable.ic_mimetype_text_code
+        drawableMap["text/x-shellscript"] = R.drawable.ic_mimetype_text_code
+        drawableMap["web"] = R.drawable.ic_mimetype_text_code
+        drawableMap["application/internet-shortcut"] = R.drawable.ic_mimetype_link
+
+        drawableMap["inode/directory"] = R.drawable.ic_mimetype_folder
+        drawableMap["unknown"] = R.drawable.ic_mimetype_file
+        drawableMap["application/pdf"] = R.drawable.ic_mimetype_application_pdf
+
+        if ("DIR" == localMimetype) {
+            localMimetype = "inode/directory"
+            return drawableMap[localMimetype]!!
+        }
+
+        if (drawableMap.containsKey(localMimetype)) {
+            return drawableMap[localMimetype]!!
+        }
+
+        if (localMimetype.startsWith("image/")) {
+            return R.drawable.ic_mimetype_image
+        }
+
+        if (localMimetype.startsWith("video/")) {
+            return R.drawable.ic_mimetype_video
+        }
+
+        if (localMimetype.startsWith("text/")) {
+            return R.drawable.ic_mimetype_text
+        }
+
+        return if (localMimetype.startsWith("audio")) {
+            R.drawable.ic_mimetype_audio
+        } else drawableMap["unknown"]!!
+    }
+}

+ 0 - 77
app/src/main/java/com/nextcloud/talk/utils/LoggingUtils.java

@@ -1,77 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.nextcloud.talk.utils;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Build;
-import androidx.core.content.FileProvider;
-import com.nextcloud.talk.BuildConfig;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-public class LoggingUtils {
-    public static void writeLogEntryToFile(Context context, String logEntry) {
-        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
-        Date date = new Date();
-        String logEntryWithDateTime = dateFormat.format(date) + ": " + logEntry + "\n";
-
-        try {
-            FileOutputStream outputStream = context.openFileOutput("nc_log.txt",
-                    Context.MODE_PRIVATE | Context.MODE_APPEND);
-            outputStream.write(logEntryWithDateTime.getBytes());
-            outputStream.flush();
-            outputStream.close();
-        } catch (FileNotFoundException e) {
-            e.printStackTrace();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    public static void sendMailWithAttachment(Context context) {
-        File logFile = context.getFileStreamPath("nc_log.txt");
-        Intent emailIntent = new Intent(Intent.ACTION_SEND);
-        String mailto = "mario@nextcloud.com";
-        emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{mailto});
-        emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Talk logs");
-        emailIntent.setType("text/plain");
-        emailIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-        Uri uri;
-
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
-            uri = Uri.fromFile(logFile);
-        } else {
-            uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, logFile);
-        }
-
-        emailIntent.putExtra(Intent.EXTRA_STREAM, uri);
-        emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        context.startActivity(emailIntent);
-    }
-}

+ 78 - 0
app/src/main/java/com/nextcloud/talk/utils/LoggingUtils.kt

@@ -0,0 +1,78 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.utils
+
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import androidx.core.content.FileProvider
+import com.nextcloud.talk.BuildConfig
+
+import java.io.File
+import java.io.FileNotFoundException
+import java.io.FileOutputStream
+import java.io.IOException
+import java.text.DateFormat
+import java.text.SimpleDateFormat
+import java.util.Date
+
+object LoggingUtils {
+    fun writeLogEntryToFile(context: Context, logEntry: String) {
+        val dateFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
+        val date = Date()
+        val logEntryWithDateTime = dateFormat.format(date) + ": " + logEntry + "\n"
+
+        try {
+            val outputStream = context.openFileOutput("nc_log.txt",
+                    Context.MODE_PRIVATE or Context.MODE_APPEND)
+            outputStream.write(logEntryWithDateTime.toByteArray())
+            outputStream.flush()
+            outputStream.close()
+        } catch (e: FileNotFoundException) {
+            e.printStackTrace()
+        } catch (e: IOException) {
+            e.printStackTrace()
+        }
+
+    }
+
+    fun sendMailWithAttachment(context: Context) {
+        val logFile = context.getFileStreamPath("nc_log.txt")
+        val emailIntent = Intent(Intent.ACTION_SEND)
+        val mailto = "mario@nextcloud.com"
+        emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(mailto))
+        emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Talk logs")
+        emailIntent.type = "text/plain"
+        emailIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
+        val uri: Uri
+
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+            uri = Uri.fromFile(logFile)
+        } else {
+            uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, logFile)
+        }
+
+        emailIntent.putExtra(Intent.EXTRA_STREAM, uri)
+        emailIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+        context.startActivity(emailIntent)
+    }
+}

+ 7 - 7
app/src/main/java/com/nextcloud/talk/utils/MagicMap.java → app/src/main/java/com/nextcloud/talk/utils/MagicMap.kt

@@ -18,14 +18,14 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-package com.nextcloud.talk.utils;
+package com.nextcloud.talk.utils
 
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentHashMap
 
-public class MagicMap extends ConcurrentHashMap<Integer, Object> {
-    public int add(Object element) {
-        int key = System.identityHashCode(element);
-        super.put(key, element);
-        return key;
+class MagicMap : ConcurrentHashMap<Int, Any>() {
+    fun add(element: Any): Int {
+        val key = System.identityHashCode(element)
+        super.put(key, element)
+        return key
     }
 }

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

@@ -96,7 +96,7 @@ public class NotificationUtils {
                     notification = statusBarNotification.getNotification();
 
                     if (notification != null && !notification.extras.isEmpty()) {
-                        if (conversationUser.getId() == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID)) {
+                        if (conversationUser.getId() == notification.extras.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID())) {
                             notificationManager.cancel(statusBarNotification.getId());
                         }
                     }
@@ -120,8 +120,8 @@ public class NotificationUtils {
                     notification = statusBarNotification.getNotification();
 
                     if (notification != null && !notification.extras.isEmpty()) {
-                        if (conversationUser.getId() == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID) &&
-                                notificationId == notification.extras.getLong(BundleKeys.KEY_NOTIFICATION_ID)) {
+                        if (conversationUser.getId() == notification.extras.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID()) &&
+                                notificationId == notification.extras.getLong(BundleKeys.INSTANCE.getKEY_NOTIFICATION_ID())) {
                             notificationManager.cancel(statusBarNotification.getId());
                         }
                     }
@@ -146,8 +146,8 @@ public class NotificationUtils {
                     notification = statusBarNotification.getNotification();
 
                     if (notification != null && !notification.extras.isEmpty()) {
-                        if (conversationUser.getId() == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID) &&
-                                roomTokenOrId.equals(statusBarNotification.getNotification().extras.getString(BundleKeys.KEY_ROOM_TOKEN))) {
+                        if (conversationUser.getId() == notification.extras.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID()) &&
+                                roomTokenOrId.equals(statusBarNotification.getNotification().extras.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN()))) {
                             return statusBarNotification;
                         }
                     }
@@ -173,8 +173,8 @@ public class NotificationUtils {
                     notification = statusBarNotification.getNotification();
 
                     if (notification != null && !notification.extras.isEmpty()) {
-                        if (conversationUser.getId() == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID) &&
-                                roomTokenOrId.equals(statusBarNotification.getNotification().extras.getString(BundleKeys.KEY_ROOM_TOKEN))) {
+                        if (conversationUser.getId() == notification.extras.getLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID()) &&
+                                roomTokenOrId.equals(statusBarNotification.getNotification().extras.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN()))) {
                             notificationManager.cancel(statusBarNotification.getId());
                         }
                     }

+ 5 - 5
app/src/main/java/com/nextcloud/talk/utils/PushUtils.java

@@ -74,15 +74,15 @@ public class PushUtils {
     private String proxyServer;
 
     public PushUtils() {
-        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+        NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
 
-        keysFile = NextcloudTalkApplication.getSharedApplication().getDir("PushKeyStore", Context.MODE_PRIVATE);
+        keysFile = NextcloudTalkApplication.Companion.getSharedApplication().getDir("PushKeyStore", Context.MODE_PRIVATE);
 
-        publicKeyFile = new File(NextcloudTalkApplication.getSharedApplication().getDir("PushKeystore",
+        publicKeyFile = new File(NextcloudTalkApplication.Companion.getSharedApplication().getDir("PushKeystore",
                 Context.MODE_PRIVATE), "push_key.pub");
-        privateKeyFile = new File(NextcloudTalkApplication.getSharedApplication().getDir("PushKeystore",
+        privateKeyFile = new File(NextcloudTalkApplication.Companion.getSharedApplication().getDir("PushKeystore",
                 Context.MODE_PRIVATE), "push_key.priv");
-        proxyServer = NextcloudTalkApplication.getSharedApplication().getResources().
+        proxyServer = NextcloudTalkApplication.Companion.getSharedApplication().getResources().
                 getString(R.string.nc_push_server_url);
     }
 

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

@@ -112,7 +112,7 @@ public class SecurityUtils {
     }
 
     private static int getIntegerFromStringTimeout(String validity) {
-        Resources resources = NextcloudTalkApplication.getSharedApplication().getResources();
+        Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
         List<String> entryValues = Arrays.asList(resources.getStringArray(R.array.screen_lock_timeout_entry_values));
         int[] entryIntValues = resources.getIntArray(R.array.screen_lock_timeout_entry_int_values);
         int indexOfValidity = entryValues.indexOf(validity);

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

@@ -33,7 +33,7 @@ import androidx.annotation.Nullable;
 import com.kennyc.bottomsheet.adapters.AppAdapter;
 import com.nextcloud.talk.R;
 import com.nextcloud.talk.models.database.UserEntity;
-import com.nextcloud.talk.models.json.rooms.Conversation;
+import com.nextcloud.talk.models.json.conversations.Conversation;
 import com.nextcloud.talk.utils.database.user.UserUtils;
 
 import java.util.ArrayList;

+ 0 - 191
app/src/main/java/com/nextcloud/talk/utils/bundle/BundleBuilder.java

@@ -1,191 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * Copyright (C) 2017 Mario Danic
- *
- * 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.bundle;
-
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.util.SparseArray;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-
-public class BundleBuilder {
-
-    private final Bundle bundle;
-
-    public BundleBuilder(Bundle bundle) {
-        this.bundle = bundle;
-    }
-
-    public BundleBuilder putAll(Bundle bundle) {
-        this.bundle.putAll(bundle);
-        return this;
-    }
-
-    public BundleBuilder putBoolean(String key, boolean value) {
-        bundle.putBoolean(key, value);
-        return this;
-    }
-
-    public BundleBuilder putBooleanArray(String key, boolean[] value) {
-        bundle.putBooleanArray(key, value);
-        return this;
-    }
-
-    public BundleBuilder putDouble(String key, double value) {
-        bundle.putDouble(key, value);
-        return this;
-    }
-
-    public BundleBuilder putDoubleArray(String key, double[] value) {
-        bundle.putDoubleArray(key, value);
-        return this;
-    }
-
-    public BundleBuilder putLong(String key, long value) {
-        bundle.putLong(key, value);
-        return this;
-    }
-
-    public BundleBuilder putLongArray(String key, long[] value) {
-        bundle.putLongArray(key, value);
-        return this;
-    }
-
-    public BundleBuilder putString(String key, String value) {
-        bundle.putString(key, value);
-        return this;
-    }
-
-    public BundleBuilder putStringArray(String key, String[] value) {
-        bundle.putStringArray(key, value);
-        return this;
-    }
-
-    public BundleBuilder putBundle(String key, Bundle value) {
-        bundle.putBundle(key, value);
-        return this;
-    }
-
-    public BundleBuilder putByte(String key, byte value) {
-        bundle.putByte(key, value);
-        return this;
-    }
-
-    public BundleBuilder putByteArray(String key, byte[] value) {
-        bundle.putByteArray(key, value);
-        return this;
-    }
-
-    public BundleBuilder putChar(String key, char value) {
-        bundle.putChar(key, value);
-        return this;
-    }
-
-    public BundleBuilder putCharArray(String key, char[] value) {
-        bundle.putCharArray(key, value);
-        return this;
-    }
-
-    public BundleBuilder putCharSequence(String key, CharSequence value) {
-        bundle.putCharSequence(key, value);
-        return this;
-    }
-
-    public BundleBuilder putCharSequenceArray(String key, CharSequence[] value) {
-        bundle.putCharSequenceArray(key, value);
-        return this;
-    }
-
-    public BundleBuilder putCharSequenceArrayList(String key, ArrayList<CharSequence> value) {
-        bundle.putCharSequenceArrayList(key, value);
-        return this;
-    }
-
-    public BundleBuilder putInt(String key, int value) {
-        bundle.putInt(key, value);
-        return this;
-    }
-
-    public BundleBuilder putIntArray(String key, int[] value) {
-        bundle.putIntArray(key, value);
-        return this;
-    }
-
-    public BundleBuilder putFloat(String key, float value) {
-        bundle.putFloat(key, value);
-        return this;
-    }
-
-    public BundleBuilder putFloatArray(String key, float[] value) {
-        bundle.putFloatArray(key, value);
-        return this;
-    }
-
-    public BundleBuilder putIntegerArrayList(String key, ArrayList<Integer> value) {
-        bundle.putIntegerArrayList(key, value);
-        return this;
-    }
-
-    public BundleBuilder putParcelable(String key, Parcelable value) {
-        bundle.putParcelable(key, value);
-        return this;
-    }
-
-    public BundleBuilder putParcelableArray(String key, Parcelable[] value) {
-        bundle.putParcelableArray(key, value);
-        return this;
-    }
-
-    public BundleBuilder putParcelableArrayList(String key, ArrayList<? extends Parcelable> value) {
-        bundle.putParcelableArrayList(key, value);
-        return this;
-    }
-
-    public BundleBuilder putSerializable(String key, Serializable value) {
-        bundle.putSerializable(key, value);
-        return this;
-    }
-
-    public BundleBuilder putShort(String key, short value) {
-        bundle.putShort(key, value);
-        return this;
-    }
-
-    public BundleBuilder putShortArray(String key, short[] value) {
-        bundle.putShortArray(key, value);
-        return this;
-    }
-
-    public BundleBuilder putSparseParcelableArray(String key, SparseArray<? extends Parcelable> value) {
-        bundle.putSparseParcelableArray(key, value);
-        return this;
-    }
-
-    public BundleBuilder putStringArrayList(String key, ArrayList<String> value) {
-        bundle.putStringArrayList(key, value);
-        return this;
-    }
-
-    public Bundle build() {
-        return bundle;
-    }
-
-}

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно