extract magic numbers

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
This commit is contained in:
Andy Scherzinger 2022-03-10 17:56:47 +01:00
parent 0ac5009242
commit ac703a6ac7
No known key found for this signature in database
GPG Key ID: 6CADC7E3523C308B
20 changed files with 163 additions and 64 deletions

View File

@ -12,8 +12,8 @@ import java.util.Locale
class ShareUtilsIT { class ShareUtilsIT {
@Test @Test
fun date() { fun date() {
assertEquals(1207778138000, parseDate2("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(1207778138000, HttpUtils.parseDate("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 { private fun parseDate2(dateStr: String): Date {
@ -39,4 +39,8 @@ class ShareUtilsIT {
"EEE MMM d yyyy HH:mm:ss z" "EEE MMM d yyyy HH:mm:ss z"
) )
} }
companion object {
private const val TEST_DATE_IN_MILLIS = 1207778138000
}
} }

View File

@ -279,8 +279,8 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
null null
) )
.repeatWhen { completed -> .repeatWhen { completed ->
completed.zipWith(Observable.range(1, 12), { _, i -> i }) completed.zipWith(Observable.range(1, OBSERVABLE_COUNT), { _, i -> i })
.flatMap { Observable.timer(5, TimeUnit.SECONDS) } .flatMap { Observable.timer(OBSERVABLE_DELAY, TimeUnit.SECONDS) }
.takeWhile { isServiceInForeground && hasParticipantsInCall && !inCallOnDifferentDevice } .takeWhile { isServiceInForeground && hasParticipantsInCall && !inCallOnDifferentDevice }
} }
.subscribeOn(Schedulers.io()) .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
}
} }

View File

@ -2,9 +2,11 @@
* Nextcloud Talk application * Nextcloud Talk application
* *
* @author Mario Danic * @author Mario Danic
* @author Andy Scherzinger
* @author Marcel Hibbe * @author Marcel Hibbe
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com> * Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de> * 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 * 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 * 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( val periodicTokenRegistration = PeriodicWorkRequest.Builder(
PushRegistrationWorker::class.java, PushRegistrationWorker::class.java,
24, DAILY,
TimeUnit.HOURS, TimeUnit.HOURS,
10, FLEX_INTERVAL,
TimeUnit.HOURS TimeUnit.HOURS
) )
.setInputData(data) .setInputData(data)
@ -115,9 +117,9 @@ class ClosedInterfaceImpl : ClosedInterface, ProviderInstaller.ProviderInstallLi
private fun setUpPeriodicTokenRefreshFromFCM() { private fun setUpPeriodicTokenRefreshFromFCM() {
val periodicTokenRefreshFromFCM = PeriodicWorkRequest.Builder( val periodicTokenRefreshFromFCM = PeriodicWorkRequest.Builder(
GetFirebasePushTokenWorker::class.java, GetFirebasePushTokenWorker::class.java,
30, MONTHLY,
TimeUnit.DAYS, TimeUnit.DAYS,
10, FLEX_INTERVAL,
TimeUnit.DAYS, TimeUnit.DAYS,
) )
.build() .build()
@ -128,4 +130,10 @@ class ClosedInterfaceImpl : ClosedInterface, ProviderInstaller.ProviderInstallLi
periodicTokenRefreshFromFCM periodicTokenRefreshFromFCM
) )
} }
companion object {
const val DAILY: Long = 24
const val MONTHLY: Long = 30
const val FLEX_INTERVAL: Long = 10
}
} }

View File

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

View File

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

View File

@ -2,10 +2,12 @@
* *
* Nextcloud Talk application * Nextcloud Talk application
* *
* @author Mario Danic
* @author Marcel Hibbe * @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 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 * 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 * 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 accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
val periodicCapabilitiesUpdateWork = PeriodicWorkRequest.Builder( val periodicCapabilitiesUpdateWork = PeriodicWorkRequest.Builder(
CapabilitiesWorker::class.java, CapabilitiesWorker::class.java,
12, TimeUnit.HOURS HALF_DAY, TimeUnit.HOURS
).build() ).build()
val capabilitiesUpdateWork = OneTimeWorkRequest.Builder(CapabilitiesWorker::class.java).build() val capabilitiesUpdateWork = OneTimeWorkRequest.Builder(CapabilitiesWorker::class.java).build()
val signalingSettingsWork = OneTimeWorkRequest.Builder(SignalingSettingsWorker::class.java).build() val signalingSettingsWork = OneTimeWorkRequest.Builder(SignalingSettingsWorker::class.java).build()
@ -218,7 +220,7 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
private fun buildDefaultImageLoader(): ImageLoader { private fun buildDefaultImageLoader(): ImageLoader {
return ImageLoader.Builder(applicationContext) 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. .crossfade(true) // Show a short crossfade when loading images from network or disk into an ImageView.
.componentRegistry { .componentRegistry {
if (SDK_INT >= P) { if (SDK_INT >= P) {
@ -234,6 +236,8 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
companion object { companion object {
private val TAG = NextcloudTalkApplication::class.java.simpleName private val TAG = NextcloudTalkApplication::class.java.simpleName
const val FIFTY_PERCENT = 0.5
const val HALF_DAY: Long = 12
//region Singleton //region Singleton
//endregion //endregion

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -49,6 +49,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedA
import com.nextcloud.talk.models.json.search.ContactsByNumberOverall import com.nextcloud.talk.models.json.search.ContactsByNumberOverall
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.ContactUtils 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.database.user.UserUtils
import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.preferences.AppPreferences
import io.reactivex.Observer import io.reactivex.Observer
@ -97,7 +98,12 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
// Check if run already at the date // Check if run already at the date
val force = inputData.getBoolean(KEY_FORCE, false) val force = inputData.getBoolean(KEY_FORCE, false)
if (!force) { 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") Log.d(TAG, "Already run within last 24h")
return Result.success() return Result.success()
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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