Browse Source

extract magic numbers

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Andy Scherzinger 3 years ago
parent
commit
ac703a6ac7
20 changed files with 163 additions and 64 deletions
  1. 6 2
      app/src/androidTest/java/com/nextcloud/talk/utils/ShareUtilsIT.kt
  2. 7 2
      app/src/gplay/java/com/nextcloud/talk/services/firebase/MagicFirebaseMessagingService.kt
  3. 12 4
      app/src/gplay/java/com/nextcloud/talk/utils/ClosedInterfaceImpl.kt
  4. 5 1
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt
  5. 5 1
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt
  6. 8 4
      app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.kt
  7. 6 3
      app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.kt
  8. 29 15
      app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt
  9. 13 7
      app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt
  10. 5 1
      app/src/main/java/com/nextcloud/talk/controllers/RingtoneSelectionController.kt
  11. 2 1
      app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.kt
  12. 2 1
      app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.kt
  13. 10 7
      app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt
  14. 7 1
      app/src/main/java/com/nextcloud/talk/jobs/ContactAddressBookWorker.kt
  15. 9 4
      app/src/main/java/com/nextcloud/talk/jobs/DownloadFileToCacheWorker.kt
  16. 2 1
      app/src/main/java/com/nextcloud/talk/utils/AccountUtils.kt
  17. 30 0
      app/src/main/java/com/nextcloud/talk/utils/DateConstants.kt
  18. 3 7
      app/src/main/java/com/nextcloud/talk/utils/DateUtils.kt
  19. 1 1
      app/src/main/java/com/nextcloud/talk/utils/ssl/SSLSocketFactoryCompat.kt
  20. 1 1
      detekt.yml

+ 6 - 2
app/src/androidTest/java/com/nextcloud/talk/utils/ShareUtilsIT.kt

@@ -12,8 +12,8 @@ import java.util.Locale
 class ShareUtilsIT {
     @Test
     fun date() {
-        assertEquals(1207778138000, parseDate2("Mon, 09 Apr 2008 23:55:38 GMT").time)
-        assertEquals(1207778138000, HttpUtils.parseDate("Mon, 09 Apr 2008 23:55:38 GMT")?.time)
+        assertEquals(TEST_DATE_IN_MILLIS, parseDate2("Mon, 09 Apr 2008 23:55:38 GMT").time)
+        assertEquals(TEST_DATE_IN_MILLIS, HttpUtils.parseDate("Mon, 09 Apr 2008 23:55:38 GMT")?.time)
     }
 
     private fun parseDate2(dateStr: String): Date {
@@ -39,4 +39,8 @@ class ShareUtilsIT {
             "EEE MMM d yyyy HH:mm:ss z"
         )
     }
+
+    companion object {
+        private const val TEST_DATE_IN_MILLIS = 1207778138000
+    }
 }

+ 7 - 2
app/src/gplay/java/com/nextcloud/talk/services/firebase/MagicFirebaseMessagingService.kt

@@ -279,8 +279,8 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
             null
         )
             .repeatWhen { completed ->
-                completed.zipWith(Observable.range(1, 12), { _, i -> i })
-                    .flatMap { Observable.timer(5, TimeUnit.SECONDS) }
+                completed.zipWith(Observable.range(1, OBSERVABLE_COUNT), { _, i -> i })
+                    .flatMap { Observable.timer(OBSERVABLE_DELAY, TimeUnit.SECONDS) }
                     .takeWhile { isServiceInForeground && hasParticipantsInCall && !inCallOnDifferentDevice }
             }
             .subscribeOn(Schedulers.io())
@@ -318,4 +318,9 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
                 }
             })
     }
+
+    companion object {
+        private const val OBSERVABLE_COUNT = 12
+        private const val OBSERVABLE_DELAY: Long = 5
+    }
 }

+ 12 - 4
app/src/gplay/java/com/nextcloud/talk/utils/ClosedInterfaceImpl.kt

@@ -2,9 +2,11 @@
  * Nextcloud Talk application
  *
  * @author Mario Danic
+ * @author Andy Scherzinger
  * @author Marcel Hibbe
  * Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
  * Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
+ * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -97,9 +99,9 @@ class ClosedInterfaceImpl : ClosedInterface, ProviderInstaller.ProviderInstallLi
 
         val periodicTokenRegistration = PeriodicWorkRequest.Builder(
             PushRegistrationWorker::class.java,
-            24,
+            DAILY,
             TimeUnit.HOURS,
-            10,
+            FLEX_INTERVAL,
             TimeUnit.HOURS
         )
             .setInputData(data)
@@ -115,9 +117,9 @@ class ClosedInterfaceImpl : ClosedInterface, ProviderInstaller.ProviderInstallLi
     private fun setUpPeriodicTokenRefreshFromFCM() {
         val periodicTokenRefreshFromFCM = PeriodicWorkRequest.Builder(
             GetFirebasePushTokenWorker::class.java,
-            30,
+            MONTHLY,
             TimeUnit.DAYS,
-            10,
+            FLEX_INTERVAL,
             TimeUnit.DAYS,
         )
             .build()
@@ -128,4 +130,10 @@ class ClosedInterfaceImpl : ClosedInterface, ProviderInstaller.ProviderInstallLi
                 periodicTokenRefreshFromFCM
             )
     }
+
+    companion object {
+        const val DAILY: Long = 24
+        const val MONTHLY: Long = 30
+        const val FLEX_INTERVAL: Long = 10
+    }
 }

+ 5 - 1
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt

@@ -188,7 +188,7 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
                 }
             }
         } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) {
-            textSize = (textSize * 2.5).toFloat()
+            textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat()
             itemView.isSelected = true
             binding.messageAuthor.visibility = View.GONE
         }
@@ -231,4 +231,8 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
 
         itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.isReplyable)
     }
+
+    companion object {
+        const val TEXT_SIZE_MULTIPLIER = 2.5
+    }
 }

+ 5 - 1
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt

@@ -97,7 +97,7 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
                 }
             }
         } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) {
-            textSize = (textSize * 2.5).toFloat()
+            textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat()
             layoutParams.isWrapBefore = true
             binding.messageTime.setTextColor(
                 ResourcesCompat.getColor(context!!.resources, R.color.warm_grey_four, null)
@@ -185,4 +185,8 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
 
         itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.isReplyable)
     }
+
+    companion object {
+        const val TEXT_SIZE_MULTIPLIER = 2.5
+    }
 }

+ 8 - 4
app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.kt

@@ -2,10 +2,12 @@
  *
  *   Nextcloud Talk application
  *
- * @author Mario Danic
  * @author Marcel Hibbe
- * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
+ * @author Andy Scherzinger
+ * @author Mario Danic
  * Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
+ * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
+ * 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
@@ -170,7 +172,7 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
         val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
         val periodicCapabilitiesUpdateWork = PeriodicWorkRequest.Builder(
             CapabilitiesWorker::class.java,
-            12, TimeUnit.HOURS
+            HALF_DAY, TimeUnit.HOURS
         ).build()
         val capabilitiesUpdateWork = OneTimeWorkRequest.Builder(CapabilitiesWorker::class.java).build()
         val signalingSettingsWork = OneTimeWorkRequest.Builder(SignalingSettingsWorker::class.java).build()
@@ -218,7 +220,7 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
 
     private fun buildDefaultImageLoader(): ImageLoader {
         return ImageLoader.Builder(applicationContext)
-            .availableMemoryPercentage(0.5) // Use 50% of the application's available memory.
+            .availableMemoryPercentage(FIFTY_PERCENT) // Use 50% of the application's available memory.
             .crossfade(true) // Show a short crossfade when loading images from network or disk into an ImageView.
             .componentRegistry {
                 if (SDK_INT >= P) {
@@ -234,6 +236,8 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
 
     companion object {
         private val TAG = NextcloudTalkApplication::class.java.simpleName
+        const val FIFTY_PERCENT = 0.5
+        const val HALF_DAY: Long = 12
         //region Singleton
         //endregion
 

+ 6 - 3
app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.kt

@@ -2,6 +2,8 @@
  * Nextcloud Talk application
  *
  * @author Mario Danic
+ * @author Andy Scherzinger
+ * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
  * Copyright (C) 2017 Mario Danic (mario@lovelyhq.com)
  *
  * This program is free software: you can redistribute it and/or modify
@@ -475,7 +477,7 @@ class AccountVerificationController(args: Bundle? = null) :
                         // unused atm
                     }
                     override fun onComplete() {
-                        activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, 7500) }
+                        activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, DELAY_IN_MILLIS) }
                     }
 
                     override fun onError(e: Throwable) {
@@ -483,7 +485,7 @@ class AccountVerificationController(args: Bundle? = null) :
                     }
                 })
             } else {
-                activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, 7500) }
+                activity?.runOnUiThread { Handler().postDelayed({ router.popToRoot() }, DELAY_IN_MILLIS) }
             }
         } else {
             ApplicationWideMessageHolder.getInstance().setMessageType(
@@ -510,13 +512,14 @@ class AccountVerificationController(args: Bundle? = null) :
                             )
                         }
                     }
-                }, 7500)
+                }, DELAY_IN_MILLIS)
             }
         }
     }
 
     companion object {
         const val TAG = "AccountVerificationController"
+        const val DELAY_IN_MILLIS: Long = 7500
     }
 
     init {

+ 29 - 15
app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt

@@ -423,7 +423,7 @@ class ChatController(args: Bundle) :
                     override fun onNewResultImpl(bitmap: Bitmap?) {
                         if (actionBar != null && bitmap != null && resources != null) {
 
-                            val avatarSize = (actionBar?.height!! / 1.5).roundToInt()
+                            val avatarSize = (actionBar?.height!! / TOOLBAR_AVATAR_RATIO).roundToInt()
                             if (avatarSize > 0) {
                                 val bitmapResized = Bitmap.createScaledBitmap(bitmap, avatarSize, avatarSize, false)
 
@@ -1043,7 +1043,7 @@ class ChatController(args: Bundle) :
         binding.messageInputView.audioRecordDuration.start()
 
         val animation: Animation = AlphaAnimation(1.0f, 0.0f)
-        animation.duration = 750
+        animation.duration = ANIMATION_DURATION
         animation.interpolator = LinearInterpolator()
         animation.repeatCount = Animation.INFINITE
         animation.repeatMode = Animation.REVERSE
@@ -1494,7 +1494,7 @@ class ChatController(args: Bundle) :
 
     private fun setupMentionAutocomplete() {
         if (isAlive()) {
-            val elevation = 6f
+            val elevation = MENTION_AUTO_COMPLETE_ELEVATION
             resources?.let {
                 val backgroundDrawable = ColorDrawable(it.getColor(R.color.bg_default))
                 val presenter = MentionAutocompletePresenter(activity, roomToken)
@@ -1691,7 +1691,7 @@ class ChatController(args: Bundle) :
             )
                 ?.subscribeOn(Schedulers.io())
                 ?.observeOn(AndroidSchedulers.mainThread())
-                ?.retry(3)
+                ?.retry(RETRIES)
                 ?.subscribe(object : Observer<RoomOverall> {
                     override fun onSubscribe(d: Disposable) {
                         disposableList.add(d)
@@ -1951,7 +1951,7 @@ class ChatController(args: Bundle) :
         }
 
         val timeout = if (lookingIntoFuture) {
-            30
+            LOOKING_INTO_FUTURE_TIMEOUT
         } else {
             0
         }
@@ -1959,7 +1959,7 @@ class ChatController(args: Bundle) :
         fieldMap["timeout"] = timeout
 
         fieldMap["lookIntoFuture"] = lookIntoFuture
-        fieldMap["limit"] = 100
+        fieldMap["limit"] = MESSAGE_PULL_LIMIT
         fieldMap["setReadMarker"] = setReadMarker
 
         val lastKnown: Int
@@ -1999,10 +1999,10 @@ class ChatController(args: Bundle) :
                         Log.d(TAG, "pullChatMessages - pullChatMessages[lookIntoFuture > 0] - got response")
                         pullChatMessagesPending = false
                         try {
-                            if (response.code() == 304) {
+                            if (response.code() == HTTP_CODE_NOT_MODIFIED) {
                                 Log.d(TAG, "pullChatMessages - quasi recursive call to pullChatMessages")
                                 pullChatMessages(1, setReadMarker, xChatLastCommonRead)
-                            } else if (response.code() == 412) {
+                            } else if (response.code() == HTTP_CODE_PRECONDITION_FAILED) {
                                 futurePreconditionFailed = true
                             } else {
                                 processMessages(response, true, finalTimeout)
@@ -2041,7 +2041,7 @@ class ChatController(args: Bundle) :
                         Log.d(TAG, "pullChatMessages - pullChatMessages[lookIntoFuture <= 0] - got response")
                         pullChatMessagesPending = false
                         try {
-                            if (response.code() == 412) {
+                            if (response.code() == HTTP_CODE_PRECONDITION_FAILED) {
                                 pastPreconditionFailed = true
                             } else {
                                 processMessages(response, false, 0)
@@ -2129,7 +2129,7 @@ class ChatController(args: Bundle) :
                     if (chatMessageList.size > i + 1) {
                         if (isSameDayNonSystemMessages(chatMessageList[i], chatMessageList[i + 1]) &&
                             chatMessageList[i + 1].actorId == chatMessageList[i].actorId &&
-                            countGroupedMessages < 4
+                            countGroupedMessages < GROUPED_MESSAGES_THRESHOLD
                         ) {
                             chatMessageList[i].isGrouped = true
                             countGroupedMessages++
@@ -2210,7 +2210,8 @@ class ChatController(args: Bundle) :
                             adapter!!.isPreviousSameAuthor(
                                 chatMessage.actorId,
                                 -1
-                            ) && adapter!!.getSameAuthorLastMessagesCount(chatMessage.actorId) % 5 > 0
+                            ) && adapter!!.getSameAuthorLastMessagesCount(chatMessage.actorId) %
+                                GROUPED_MESSAGES_SAME_AUTHOR_THRESHOLD > 0
                             )
                         chatMessage.isOneToOneConversation =
                             (currentConversation?.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL)
@@ -2245,7 +2246,7 @@ class ChatController(args: Bundle) :
             if (inConversation) {
                 pullChatMessages(1, 1, xChatLastCommonRead)
             }
-        } else if (response.code() == 304 && !isFromTheFuture) {
+        } else if (response.code() == HTTP_CODE_NOT_MODIFIED && !isFromTheFuture) {
             if (isFirstMessagesProcessing) {
                 cancelNotificationsForCurrentConversation()
 
@@ -2478,7 +2479,7 @@ class ChatController(args: Bundle) :
                             conversationUser?.baseUrl,
                             "1",
                             null,
-                            message?.user?.id?.substring(6),
+                            message?.user?.id?.substring(INVITE_LENGTH),
                             null
                         )
                         ncApi!!.createRoom(
@@ -2600,7 +2601,7 @@ class ChatController(args: Bundle) :
             menu.findItem(R.id.action_reply_privately).isVisible = message.replyable &&
                 conversationUser?.userId?.isNotEmpty() == true && conversationUser.userId != "?" &&
                 message.user.id.startsWith("users/") &&
-                message.user.id.substring(6) != currentConversation?.actorId &&
+                message.user.id.substring(ACTOR_LENGTH) != currentConversation?.actorId &&
                 currentConversation?.type != Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
             menu.findItem(R.id.action_delete_message).isVisible = isShowMessageDeletionButton(message)
             menu.findItem(R.id.action_forward_message).isVisible =
@@ -2642,7 +2643,7 @@ class ChatController(args: Bundle) :
 
                     val px = TypedValue.applyDimension(
                         TypedValue.COMPLEX_UNIT_DIP,
-                        96f,
+                        QUOTED_MESSAGE_IMAGE_MAX_HEIGHT,
                         resources?.displayMetrics
                     )
 
@@ -2860,5 +2861,18 @@ class ChatController(args: Bundle) :
         private const val VOICE_MESSAGE_SEEKBAR_BASE: Int = 1000
         private const val SECOND: Long = 1000
         private const val NO_PREVIOUS_MESSAGE_ID: Int = -1
+        private const val GROUPED_MESSAGES_THRESHOLD = 4
+        private const val GROUPED_MESSAGES_SAME_AUTHOR_THRESHOLD = 5
+        private const val TOOLBAR_AVATAR_RATIO = 1.5
+        private const val HTTP_CODE_NOT_MODIFIED = 304
+        private const val HTTP_CODE_PRECONDITION_FAILED = 412
+        private const val QUOTED_MESSAGE_IMAGE_MAX_HEIGHT = 96f
+        private const val MENTION_AUTO_COMPLETE_ELEVATION = 6f
+        private const val MESSAGE_PULL_LIMIT = 100
+        private const val INVITE_LENGTH = 6
+        private const val ACTOR_LENGTH = 6
+        private const val ANIMATION_DURATION: Long = 750
+        private const val RETRIES: Long = 3
+        private const val LOOKING_INTO_FUTURE_TIMEOUT = 30
     }
 }

+ 13 - 7
app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt

@@ -72,6 +72,7 @@ import com.nextcloud.talk.models.json.participants.Participant.ActorType.GROUPS
 import com.nextcloud.talk.models.json.participants.Participant.ActorType.USERS
 import com.nextcloud.talk.models.json.participants.ParticipantsOverall
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateConstants
 import com.nextcloud.talk.utils.DateUtils
 import com.nextcloud.talk.utils.DisplayUtils
 import com.nextcloud.talk.utils.bundle.BundleKeys
@@ -206,7 +207,7 @@ class ConversationInfoController(args: Bundle) :
                 MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
                     val currentTimeCalendar = Calendar.getInstance()
                     if (conversation!!.lobbyTimer != null && conversation!!.lobbyTimer != 0L) {
-                        currentTimeCalendar.timeInMillis = conversation!!.lobbyTimer * 1000
+                        currentTimeCalendar.timeInMillis = conversation!!.lobbyTimer * DateConstants.SECOND_DIVIDER
                     }
 
                     dateTimePicker(
@@ -238,13 +239,15 @@ class ConversationInfoController(args: Bundle) :
             conversation.type == Conversation.ConversationType.ROOM_PUBLIC_CALL
     }
 
-    fun reconfigureLobbyTimerView(dateTime: Calendar? = null) {
+    private fun reconfigureLobbyTimerView(dateTime: Calendar? = null) {
         val isChecked =
             (binding.webinarInfoView.conversationInfoLobby.findViewById<View>(R.id.mp_checkable) as SwitchCompat)
                 .isChecked
 
         if (dateTime != null && isChecked) {
-            conversation!!.lobbyTimer = (dateTime.timeInMillis - (dateTime.time.seconds * 1000)) / 1000
+            conversation!!.lobbyTimer = (
+                dateTime.timeInMillis - (dateTime.time.seconds * DateConstants.SECOND_DIVIDER)
+                ) / DateConstants.SECOND_DIVIDER
         } else if (!isChecked) {
             conversation!!.lobbyTimer = 0
         }
@@ -683,9 +686,9 @@ class ConversationInfoController(args: Bundle) :
                 if (conversation!!.notificationLevel != Conversation.NotificationLevel.DEFAULT) {
                     val stringValue: String =
                         when (EnumNotificationLevelConverter().convertToInt(conversation!!.notificationLevel)) {
-                            1 -> "always"
-                            2 -> "mention"
-                            3 -> "never"
+                            NOTIFICATION_LEVEL_ALWAYS -> "always"
+                            NOTIFICATION_LEVEL_MENTION -> "mention"
+                            NOTIFICATION_LEVEL_NEVER -> "never"
                             else -> "mention"
                         }
 
@@ -1100,7 +1103,10 @@ class ConversationInfoController(args: Bundle) :
     }
 
     companion object {
-        private const val TAG = "ConversationInfControll"
+        private const val TAG = "ConversationInfo"
+        private const val NOTIFICATION_LEVEL_ALWAYS: Int = 1
+        private const val NOTIFICATION_LEVEL_MENTION: Int = 2
+        private const val NOTIFICATION_LEVEL_NEVER: Int = 3
         private const val ID_DELETE_CONVERSATION_DIALOG = 0
         private const val ID_CLEAR_CHAT_DIALOG = 1
         private val LOW_EMPHASIS_OPACITY: Float = 0.38f

+ 5 - 1
app/src/main/java/com/nextcloud/talk/controllers/RingtoneSelectionController.kt

@@ -191,7 +191,10 @@ class RingtoneSelectionController(args: Bundle) :
             endMediaPlayer()
             mediaPlayer = MediaPlayer.create(activity, ringtoneUri)
             cancelMediaPlayerHandler = Handler()
-            cancelMediaPlayerHandler!!.postDelayed({ endMediaPlayer() }, (mediaPlayer!!.getDuration() + 25).toLong())
+            cancelMediaPlayerHandler!!.postDelayed(
+                { endMediaPlayer() },
+                (mediaPlayer!!.duration + DURATION_EXTENSION).toLong()
+            )
             mediaPlayer!!.start()
         }
         if (adapter!!.selectedPositions.size == 0 || adapter!!.selectedPositions[0] != position) {
@@ -239,6 +242,7 @@ class RingtoneSelectionController(args: Bundle) :
 
     companion object {
         private const val TAG = "RingtoneSelection"
+        private const val DURATION_EXTENSION = 25
     }
 
     init {

+ 2 - 1
app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.kt

@@ -213,7 +213,7 @@ class ServerSelectionController : NewBaseController(R.layout.controller_server_s
                 val productName = resources!!.getString(R.string.nc_server_product_name)
                 val versionString: String = status.getVersion().substring(0, status.getVersion().indexOf("."))
                 val version: Int = versionString.toInt()
-                if (isServerStatusQueryable(status) && version >= 13) {
+                if (isServerStatusQueryable(status) && version >= MIN_SERVER_MAJOR_VERSION) {
                     router.pushController(
                         RouterTransaction.with(
                             WebViewLoginController(
@@ -369,5 +369,6 @@ class ServerSelectionController : NewBaseController(R.layout.controller_server_s
 
     companion object {
         const val TAG = "ServerSelectionController"
+        const val MIN_SERVER_MAJOR_VERSION = 13
     }
 }

+ 2 - 1
app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.kt

@@ -404,7 +404,7 @@ class WebViewLoginController(args: Bundle? = null) : NewBaseController(
         // format is xxx://login/server:xxx&user:xxx&password:xxx
         val data: String = dataString.substring(prefix.length)
         val values: Array<String> = data.split("&").toTypedArray()
-        if (values.size != 3) {
+        if (values.size != PARAMETER_COUNT) {
             return null
         }
         for (value in values) {
@@ -468,5 +468,6 @@ class WebViewLoginController(args: Bundle? = null) : NewBaseController(
         const val TAG = "WebViewLoginController"
         private const val PROTOCOL_SUFFIX = "://"
         private const val LOGIN_URL_DATA_KEY_VALUE_SEPARATOR = ":"
+        private const val PARAMETER_COUNT = 3
     }
 }

+ 10 - 7
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt

@@ -94,7 +94,7 @@ class EntryMenuController(args: Bundle) :
             ApplicationWideMessageHolder.getInstance().setMessageType(null)
             if (binding.okButton.isEnabled) {
                 binding.okButton.isEnabled = false
-                binding.okButton.alpha = 0.7f
+                binding.okButton.alpha = OPACITY_BUTTON_DISABLED
             }
         }
     }
@@ -130,20 +130,20 @@ class EntryMenuController(args: Bundle) :
                         if (conversation!!.getName() == null || !conversation!!.getName().equals(s.toString())) {
                             if (!binding.okButton.isEnabled) {
                                 binding.okButton.isEnabled = true
-                                binding.okButton.alpha = 1.0f
+                                binding.okButton.alpha = OPACITY_ENABLED
                             }
                             binding.textInputLayout.isErrorEnabled = false
                         } else {
                             if (binding.okButton.isEnabled) {
                                 binding.okButton.isEnabled = false
-                                binding.okButton.alpha = 0.38f
+                                binding.okButton.alpha = OPACITY_DISABLED
                             }
                             binding.textInputLayout.error = resources?.getString(R.string.nc_call_name_is_same)
                         }
                     } else if (operation !== ConversationOperationEnum.OPS_CODE_GET_AND_JOIN_ROOM) {
                         if (!binding.okButton.isEnabled) {
                             binding.okButton.isEnabled = true
-                            binding.okButton.alpha = 1.0f
+                            binding.okButton.alpha = OPACITY_ENABLED
                         }
                         binding.textInputLayout.isErrorEnabled = false
                     } else if (
@@ -152,20 +152,20 @@ class EntryMenuController(args: Bundle) :
                     ) {
                         if (!binding.okButton.isEnabled) {
                             binding.okButton.isEnabled = true
-                            binding.okButton.alpha = 1.0f
+                            binding.okButton.alpha = OPACITY_ENABLED
                         }
                         binding.textInputLayout.isErrorEnabled = false
                     } else {
                         if (binding.okButton.isEnabled) {
                             binding.okButton.isEnabled = false
-                            binding.okButton.alpha = 0.38f
+                            binding.okButton.alpha = OPACITY_DISABLED
                         }
                         binding.textInputLayout.error = resources?.getString(R.string.nc_wrong_link)
                     }
                 } else {
                     if (binding.okButton.isEnabled) {
                         binding.okButton.isEnabled = false
-                        binding.okButton.alpha = 0.38f
+                        binding.okButton.alpha = OPACITY_DISABLED
                     }
                     binding.textInputLayout.isErrorEnabled = false
                 }
@@ -334,5 +334,8 @@ class EntryMenuController(args: Bundle) :
                 ConversationOperationEnum.OPS_CODE_SET_PASSWORD,
                 ConversationOperationEnum.OPS_CODE_SHARE_LINK
             )
+        const val OPACITY_DISABLED = 0.38f
+        const val OPACITY_BUTTON_DISABLED = 0.7f
+        const val OPACITY_ENABLED = 1.0f
     }
 }

+ 7 - 1
app/src/main/java/com/nextcloud/talk/jobs/ContactAddressBookWorker.kt

@@ -49,6 +49,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedA
 import com.nextcloud.talk.models.json.search.ContactsByNumberOverall
 import com.nextcloud.talk.utils.ApiUtils
 import com.nextcloud.talk.utils.ContactUtils
+import com.nextcloud.talk.utils.DateConstants
 import com.nextcloud.talk.utils.database.user.UserUtils
 import com.nextcloud.talk.utils.preferences.AppPreferences
 import io.reactivex.Observer
@@ -97,7 +98,12 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
         // Check if run already at the date
         val force = inputData.getBoolean(KEY_FORCE, false)
         if (!force) {
-            if (System.currentTimeMillis() - appPreferences.getPhoneBookIntegrationLastRun(0L) < 24 * 60 * 60 * 1000) {
+            if (System.currentTimeMillis() - appPreferences.getPhoneBookIntegrationLastRun(0L) <
+                DateConstants.DAYS_DIVIDER *
+                DateConstants.HOURS_DIVIDER *
+                DateConstants.MINUTES_DIVIDER *
+                DateConstants.SECOND_DIVIDER
+            ) {
                 Log.d(TAG, "Already run within last 24h")
                 return Result.success()
             }

+ 9 - 4
app/src/main/java/com/nextcloud/talk/jobs/DownloadFileToCacheWorker.kt

@@ -103,8 +103,8 @@ class DownloadFileToCacheWorker(val context: Context, workerParameters: WorkerPa
         }
 
         var count: Int
-        val data = ByteArray(1024 * 4)
-        val bis: InputStream = BufferedInputStream(body.byteStream(), 1024 * 8)
+        val data = ByteArray(BYTE_UNIT_DIVIDER * DATA_BYTES)
+        val bis: InputStream = BufferedInputStream(body.byteStream(), BYTE_UNIT_DIVIDER * DOWNLOAD_STREAM_SIZE)
         val outputFile = File(context.cacheDir, fileName + "_")
         val output: OutputStream = FileOutputStream(outputFile)
         var total: Long = 0
@@ -116,9 +116,9 @@ class DownloadFileToCacheWorker(val context: Context, workerParameters: WorkerPa
         while (count != -1) {
             if (totalFileSize > -1) {
                 total += count.toLong()
-                val progress = (total * 100 / totalFileSize).toInt()
+                val progress = (total * COMPLETE_PERCENTAGE / totalFileSize).toInt()
                 val currentTime = System.currentTimeMillis() - startTime
-                if (currentTime > 50 * timeCount) {
+                if (currentTime > PROGRESS_THRESHOLD * timeCount) {
                     setProgressAsync(Data.Builder().putInt(PROGRESS, progress).build())
                     timeCount++
                 }
@@ -156,5 +156,10 @@ class DownloadFileToCacheWorker(val context: Context, workerParameters: WorkerPa
         const val KEY_FILE_SIZE = "KEY_FILE_SIZE"
         const val PROGRESS = "PROGRESS"
         const val SUCCESS = "SUCCESS"
+        const val BYTE_UNIT_DIVIDER = 1024
+        const val DATA_BYTES = 4
+        const val DOWNLOAD_STREAM_SIZE = 8
+        const val COMPLETE_PERCENTAGE = 100
+        const val PROGRESS_THRESHOLD = 50
     }
 }

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

@@ -38,6 +38,7 @@ import java.util.Arrays
 object AccountUtils {
 
     private const val TAG = "AccountUtils"
+    private const val MIN_SUPPORTED_FILES_APP_VERSION = 30060151
 
     fun findAccounts(userEntitiesList: List<UserEntity>): List<Account> {
         val context = NextcloudTalkApplication.sharedApplication!!.applicationContext
@@ -110,7 +111,7 @@ object AccountUtils {
         val pm = context.packageManager
         try {
             val packageInfo = pm.getPackageInfo(context.getString(R.string.nc_import_accounts_from), 0)
-            if (packageInfo.versionCode >= 30060151) {
+            if (packageInfo.versionCode >= MIN_SUPPORTED_FILES_APP_VERSION) {
                 val ownSignatures = pm.getPackageInfo(context.packageName, PackageManager.GET_SIGNATURES).signatures
                 val filesAppSignatures = pm.getPackageInfo(
                     context.getString(R.string.nc_import_accounts_from),

+ 30 - 0
app/src/main/java/com/nextcloud/talk/utils/DateConstants.kt

@@ -0,0 +1,30 @@
+/*
+ *   Nextcloud Talk application
+ *
+ *   @author Andy Scherzinger
+ *   Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.utils
+
+class DateConstants {
+    companion object {
+        const val SECOND_DIVIDER = 1000
+        const val MINUTES_DIVIDER = 60
+        const val HOURS_DIVIDER = 60
+        const val DAYS_DIVIDER = 24
+    }
+}

+ 3 - 7
app/src/main/java/com/nextcloud/talk/utils/DateUtils.kt

@@ -35,10 +35,6 @@ import kotlin.math.roundToInt
 object DateUtils {
 
     private const val TIMESTAMP_CORRECTION_MULTIPLIER = 1000
-    private const val SECOND_DIVIDER = 1000
-    private const val MINUTES_DIVIDER = 60
-    private const val HOURS_DIVIDER = 60
-    private const val DAYS_DIVIDER = 24
 
     fun getLocalDateTimeStringFromTimestamp(timestamp: Long): String {
         val cal = Calendar.getInstance()
@@ -63,9 +59,9 @@ object DateUtils {
         return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             val fmt = RelativeDateTimeFormatter.getInstance()
             val timeLeftMillis = timestamp * TIMESTAMP_CORRECTION_MULTIPLIER - System.currentTimeMillis()
-            val minutes = timeLeftMillis.toDouble() / SECOND_DIVIDER / MINUTES_DIVIDER
-            val hours = minutes / HOURS_DIVIDER
-            val days = hours / DAYS_DIVIDER
+            val minutes = timeLeftMillis.toDouble() / DateConstants.SECOND_DIVIDER / DateConstants.MINUTES_DIVIDER
+            val hours = minutes / DateConstants.HOURS_DIVIDER
+            val days = hours / DateConstants.DAYS_DIVIDER
 
             val minutesInt = minutes.roundToInt()
             val hoursInt = hours.roundToInt()

+ 1 - 1
app/src/main/java/com/nextcloud/talk/utils/ssl/SSLSocketFactoryCompat.kt

@@ -35,7 +35,7 @@ class SSLSocketFactoryCompat(
         var cipherSuites: Array<String>? = null
 
         init {
-            if (Build.VERSION.SDK_INT >= 23) {
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                 // Since Android 6.0 (API level 23),
                 // - TLSv1.1 and TLSv1.2 is enabled by default
                 // - SSLv3 is disabled by default

+ 1 - 1
detekt.yml

@@ -1,5 +1,5 @@
 build:
-  maxIssues: 150
+  maxIssues: 108
   weights:
     # complexity: 2
     # LongParameterList: 1