Fixed MicInputCloud + Detekt issues

Signed-off-by: Julius Linus <julius.linus@nextcloud.com>
This commit is contained in:
rapterjet2004 2023-07-19 10:12:43 -05:00
parent 26c86f0240
commit 21dbd65870
2 changed files with 98 additions and 67 deletions

View File

@ -245,8 +245,6 @@ import javax.inject.Inject
import kotlin.collections.set import kotlin.collections.set
import kotlin.math.roundToInt import kotlin.math.roundToInt
private const val l = 50
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
class ChatActivity : class ChatActivity :
BaseActivity(), BaseActivity(),
@ -337,8 +335,8 @@ class ChatActivity :
private lateinit var micInputAudioRecorder: AudioRecord private lateinit var micInputAudioRecorder: AudioRecord
private var micInputAudioRecordThread: Thread? = null private var micInputAudioRecordThread: Thread? = null
private var isMicInputAudioThreadRunning: Boolean = false private var isMicInputAudioThreadRunning: Boolean = false
private val BUFFER_SIZE = AudioRecord.getMinBufferSize( private val bufferSize = AudioRecord.getMinBufferSize(
8000, SAMPLE_RATE,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT AudioFormat.ENCODING_PCM_16BIT
) )
@ -617,41 +615,7 @@ class ChatActivity :
initSmileyKeyboardToggler() initSmileyKeyboardToggler()
binding.messageInputView.findViewById<ImageButton>(R.id.cancelReplyButton)?.setOnClickListener { themeMessageInputView()
cancelReply()
}
binding.messageInputView.findViewById<ImageButton>(R.id.cancelReplyButton)?.let {
viewThemeUtils.platform
.themeImageButton(it)
}
binding.messageInputView.findViewById<MaterialButton>(R.id.playPauseBtn)?.let {
viewThemeUtils.material.colorMaterialButtonText(it)
}
binding.messageInputView.findViewById<SeekBar>(R.id.seekbar)?.let {
viewThemeUtils.platform.themeHorizontalSeekBar(it)
}
binding.messageInputView.findViewById<ImageView>(R.id.deleteVoiceRecording)?.let {
viewThemeUtils.platform.colorImageView(it, ColorRole.PRIMARY)
}
binding.messageInputView.findViewById<ImageView>(R.id.sendVoiceRecording)?.let {
viewThemeUtils.platform.colorImageView(it, ColorRole.PRIMARY)
}
binding.messageInputView.findViewById<ImageView>(R.id.microphoneEnabledInfo)?.let {
viewThemeUtils.platform.colorImageView(it, ColorRole.PRIMARY)
}
binding.messageInputView.findViewById<LinearLayout>(R.id.voice_preview_container)?.let {
viewThemeUtils.talk.themeOutgoingMessageBubble(it, true, false)
}
binding.messageInputView.findViewById<MicInputCloud>(R.id.micInputCloud)?.let {
viewThemeUtils.talk.themeMicInputCloud(it)
}
cancelNotificationsForCurrentConversation() cancelNotificationsForCurrentConversation()
@ -716,6 +680,15 @@ class ChatActivity :
} }
}) })
initMessageInputView()
loadAvatarForStatusBar()
setActionBarTitle()
viewThemeUtils.material.colorToolbarOverflowIcon(binding.chatToolbar)
}
private fun initMessageInputView() {
val filters = arrayOfNulls<InputFilter>(1) val filters = arrayOfNulls<InputFilter>(1)
val lengthFilter = CapabilitiesUtilNew.getMessageMaxLength(conversationUser) val lengthFilter = CapabilitiesUtilNew.getMessageMaxLength(conversationUser)
@ -796,13 +769,46 @@ class ChatActivity :
binding.messageInputView.button?.contentDescription = binding.messageInputView.button?.contentDescription =
resources?.getString(R.string.nc_description_send_message_button) resources?.getString(R.string.nc_description_send_message_button)
}
private fun themeMessageInputView() {
binding.messageInputView.button?.let { viewThemeUtils.platform.colorImageView(it, ColorRole.PRIMARY) } binding.messageInputView.button?.let { viewThemeUtils.platform.colorImageView(it, ColorRole.PRIMARY) }
loadAvatarForStatusBar() binding.messageInputView.findViewById<ImageButton>(R.id.cancelReplyButton)?.setOnClickListener {
setActionBarTitle() cancelReply()
}
viewThemeUtils.material.colorToolbarOverflowIcon(binding.chatToolbar) binding.messageInputView.findViewById<ImageButton>(R.id.cancelReplyButton)?.let {
viewThemeUtils.platform
.themeImageButton(it)
}
binding.messageInputView.findViewById<MaterialButton>(R.id.playPauseBtn)?.let {
viewThemeUtils.material.colorMaterialButtonText(it)
}
binding.messageInputView.findViewById<SeekBar>(R.id.seekbar)?.let {
viewThemeUtils.platform.themeHorizontalSeekBar(it)
}
binding.messageInputView.findViewById<ImageView>(R.id.deleteVoiceRecording)?.let {
viewThemeUtils.platform.colorImageView(it, ColorRole.PRIMARY)
}
binding.messageInputView.findViewById<ImageView>(R.id.sendVoiceRecording)?.let {
viewThemeUtils.platform.colorImageView(it, ColorRole.PRIMARY)
}
binding.messageInputView.findViewById<ImageView>(R.id.microphoneEnabledInfo)?.let {
viewThemeUtils.platform.colorImageView(it, ColorRole.PRIMARY)
}
binding.messageInputView.findViewById<LinearLayout>(R.id.voice_preview_container)?.let {
viewThemeUtils.talk.themeOutgoingMessageBubble(it, true, false)
}
binding.messageInputView.findViewById<MicInputCloud>(R.id.micInputCloud)?.let {
viewThemeUtils.talk.themeMicInputCloud(it)
}
} }
private fun setupActionBar() { private fun setupActionBar() {
@ -1275,7 +1281,7 @@ class ChatActivity :
) )
binding.voiceRecordingLock.alpha = 1f binding.voiceRecordingLock.alpha = 1f
binding.voiceRecordingLock.animate().alpha(0f).setDuration(500) binding.voiceRecordingLock.animate().alpha(0f).setDuration(VOICE_RECORDING_LOCK_ANIMATION_DURATION.toLong())
.setInterpolator(AccelerateInterpolator()).start() .setInterpolator(AccelerateInterpolator()).start()
} else { } else {
binding.voiceRecordingLock.setImageDrawable( binding.voiceRecordingLock.setImageDrawable(
@ -1461,7 +1467,7 @@ class ChatActivity :
fun updateOwnTypingStatus(typedText: CharSequence) { fun updateOwnTypingStatus(typedText: CharSequence) {
fun sendStartTypingSignalingMessage() { fun sendStartTypingSignalingMessage() {
for ((sessionId, participant) in webSocketInstance?.getUserMap()!!) { for ((sessionId, _) in webSocketInstance?.getUserMap()!!) {
val ncSignalingMessage = NCSignalingMessage() val ncSignalingMessage = NCSignalingMessage()
ncSignalingMessage.to = sessionId ncSignalingMessage.to = sessionId
ncSignalingMessage.type = TYPING_STARTED_SIGNALING_MESSAGE_TYPE ncSignalingMessage.type = TYPING_STARTED_SIGNALING_MESSAGE_TYPE
@ -1505,7 +1511,7 @@ class ChatActivity :
typingTimer = null typingTimer = null
typedWhileTypingTimerIsRunning = false typedWhileTypingTimerIsRunning = false
for ((sessionId, participant) in webSocketInstance?.getUserMap()!!) { for ((sessionId, _) in webSocketInstance?.getUserMap()!!) {
val ncSignalingMessage = NCSignalingMessage() val ncSignalingMessage = NCSignalingMessage()
ncSignalingMessage.to = sessionId ncSignalingMessage.to = sessionId
ncSignalingMessage.type = TYPING_STOPPED_SIGNALING_MESSAGE_TYPE ncSignalingMessage.type = TYPING_STOPPED_SIGNALING_MESSAGE_TYPE
@ -1913,25 +1919,25 @@ class ChatActivity :
Log.d(TAG, "Mic Animation Started") Log.d(TAG, "Mic Animation Started")
micInputAudioRecorder = AudioRecord( micInputAudioRecorder = AudioRecord(
MediaRecorder.AudioSource.MIC, MediaRecorder.AudioSource.MIC,
8000, SAMPLE_RATE,
AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, AudioFormat.ENCODING_PCM_16BIT,
BUFFER_SIZE bufferSize
) )
isMicInputAudioThreadRunning = true isMicInputAudioThreadRunning = true
micInputAudioRecorder.startRecording() micInputAudioRecorder.startRecording()
micInputAudioRecordThread = Thread( micInputAudioRecordThread = Thread(
Runnable { Runnable {
while (isMicInputAudioThreadRunning) { while (isMicInputAudioThreadRunning) {
val byteArr = ByteArray(BUFFER_SIZE / 2) val byteArr = ByteArray(bufferSize / 2)
micInputAudioRecorder.read(byteArr, 0, byteArr.size) micInputAudioRecorder.read(byteArr, 0, byteArr.size)
val d = Math.abs(byteArr[0].toDouble()) val d = Math.abs(byteArr[0].toDouble())
if (d > 40) { if (d > AUDIO_VALUE_MAX) {
binding.messageInputView.micInputCloud.setRotationSpeed( binding.messageInputView.micInputCloud.setRotationSpeed(
Math.log10(d).toFloat(), Math.log10(d).toFloat(),
MicInputCloud.MAXIMUM_RADIUS MicInputCloud.MAXIMUM_RADIUS
) )
} else if (d > 20) { } else if (d > AUDIO_VALUE_MIN) {
binding.messageInputView.micInputCloud.setRotationSpeed( binding.messageInputView.micInputCloud.setRotationSpeed(
Math.log10(d).toFloat(), Math.log10(d).toFloat(),
MicInputCloud.EXTENDED_RADIUS MicInputCloud.EXTENDED_RADIUS
@ -1942,7 +1948,7 @@ class ChatActivity :
MicInputCloud.DEFAULT_RADIUS MicInputCloud.DEFAULT_RADIUS
) )
} }
Thread.sleep(50) Thread.sleep(AUDIO_VALUE_SLEEP)
} }
} }
) )
@ -2033,8 +2039,8 @@ class ChatActivity :
release() release()
isVoiceRecordingInProgress = false isVoiceRecordingInProgress = false
Log.d(TAG, "stopped recorder. isVoiceRecordingInProgress = false") Log.d(TAG, "stopped recorder. isVoiceRecordingInProgress = false")
} catch (e: RuntimeException) { } catch (e: java.lang.IllegalStateException) {
Log.w(TAG, "error while stopping recorder!") error("error while stopping recorder!" + e)
} }
VibrationUtils.vibrateShort(context) VibrationUtils.vibrateShort(context)
@ -2331,7 +2337,7 @@ class ChatActivity :
filesToUpload.add(videoURI.toString()) filesToUpload.add(videoURI.toString())
videoURI = null videoURI = null
} else { } else {
throw IllegalStateException("Failed to get data from intent and uri") error("Failed to get data from intent and uri")
} }
if (permissionUtil.isFilesPermissionGranted()) { if (permissionUtil.isFilesPermissionGranted()) {
@ -2642,8 +2648,9 @@ class ChatActivity :
if (currentConversation?.displayName != null) { if (currentConversation?.displayName != null) {
try { try {
" " + EmojiCompat.get().process(currentConversation?.displayName as CharSequence).toString() " " + EmojiCompat.get().process(currentConversation?.displayName as CharSequence).toString()
} catch (e: IllegalStateException) { } catch (e: java.lang.IllegalStateException) {
" " + currentConversation?.displayName " " + currentConversation?.displayName
error(e)
} }
} else { } else {
"" ""
@ -4104,7 +4111,6 @@ class ChatActivity :
private const val CONTENT_TYPE_POLL: Byte = 5 private const val CONTENT_TYPE_POLL: Byte = 5
private const val CONTENT_TYPE_LINK_PREVIEW: Byte = 6 private const val CONTENT_TYPE_LINK_PREVIEW: Byte = 6
private const val NEW_MESSAGES_POPUP_BUBBLE_DELAY: Long = 200 private const val NEW_MESSAGES_POPUP_BUBBLE_DELAY: Long = 200
private const val POP_CURRENT_CONTROLLER_DELAY: Long = 100
private const val GET_ROOM_INFO_DELAY_NORMAL: Long = 30000 private const val GET_ROOM_INFO_DELAY_NORMAL: Long = 30000
private const val GET_ROOM_INFO_DELAY_LOBBY: Long = 5000 private const val GET_ROOM_INFO_DELAY_LOBBY: Long = 5000
private const val HTTP_CODE_OK: Int = 200 private const val HTTP_CODE_OK: Int = 200
@ -4148,11 +4154,14 @@ class ChatActivity :
private const val INVITE_LENGTH = 6 private const val INVITE_LENGTH = 6
private const val ACTOR_LENGTH = 6 private const val ACTOR_LENGTH = 6
private const val ANIMATION_DURATION: Long = 750 private const val ANIMATION_DURATION: Long = 750
private const val RETRIES: Long = 3
private const val LOOKING_INTO_FUTURE_TIMEOUT = 30 private const val LOOKING_INTO_FUTURE_TIMEOUT = 30
private const val CHUNK_SIZE: Int = 10 private const val CHUNK_SIZE: Int = 10
private const val ONE_SECOND_IN_MILLIS = 1000 private const val ONE_SECOND_IN_MILLIS = 1000
private const val SAMPLE_RATE = 8000
private const val VOICE_RECORDING_LOCK_ANIMATION_DURATION = 500
private const val AUDIO_VALUE_MAX = 40
private const val AUDIO_VALUE_MIN = 20
private const val AUDIO_VALUE_SLEEP: Long = 50
private const val WHITESPACE = " " private const val WHITESPACE = " "
private const val COMMA = ", " private const val COMMA = ", "
private const val TYPING_INDICATOR_ANIMATION_DURATION = 200L private const val TYPING_INDICATOR_ANIMATION_DURATION = 200L

View File

@ -40,11 +40,18 @@ import kotlin.math.roundToInt
class MicInputCloud(context: Context, attrs: AttributeSet) : View(context, attrs) { class MicInputCloud(context: Context, attrs: AttributeSet) : View(context, attrs) {
/** /**
* State Descriptions: * State Descriptions:
* - PAUSED_STATE: Animation speed is set to zero * - PAUSED_STATE: Animation speed is set to zero.
* - PLAY_STATE: Animation speed is set to default, but can be overridden * - PLAY_STATE: Animation speed is set to default, but can be overridden.
*/ */
enum class ViewState { enum class ViewState {
/**
* Animation speed is set to zero.
*/
PAUSED_STATE, PAUSED_STATE,
/**
* Animation speed is set to default, but can be overridden.
*/
PLAY_STATE PLAY_STATE
} }
@ -97,6 +104,7 @@ class MicInputCloud(context: Context, attrs: AttributeSet) : View(context, attrs
} }
private val topCircleBounds = Rect(0, 0, 0, 0) private val topCircleBounds = Rect(0, 0, 0, 0)
private val iconBounds = topCircleBounds
override fun onVisibilityChanged(changedView: View, visibility: Int) { override fun onVisibilityChanged(changedView: View, visibility: Int) {
super.onVisibilityChanged(changedView, visibility) super.onVisibilityChanged(changedView, visibility)
@ -285,10 +293,23 @@ class MicInputCloud(context: Context, attrs: AttributeSet) : View(context, attrs
centerX = (width / 2).toFloat() centerX = (width / 2).toFloat()
centerY = (height / 2).toFloat() centerY = (height / 2).toFloat()
topCircleBounds.left = (centerX - DEFAULT_RADIUS).toInt() topCircleBounds.apply {
topCircleBounds.top = (centerY - DEFAULT_RADIUS).toInt() left = (centerX - DEFAULT_RADIUS).toInt()
topCircleBounds.right = (centerX + DEFAULT_RADIUS).toInt() top = (centerY - DEFAULT_RADIUS).toInt()
topCircleBounds.bottom = (centerY + DEFAULT_RADIUS).toInt() right = (centerX + DEFAULT_RADIUS).toInt()
bottom = (centerY + DEFAULT_RADIUS).toInt()
}
/**
* Drawables are drawn the same way as the canvas is drawn, as both originate from the top-left corner.
* Because of this, the icon's width = (right - left) and height = (bottom - top).
*/
iconBounds.apply {
left = (centerX - DEFAULT_RADIUS + ICON_SIZE.dp).toInt()
top = (centerY - DEFAULT_RADIUS + ICON_SIZE.dp).toInt()
right = (centerX + DEFAULT_RADIUS - ICON_SIZE.dp).toInt()
bottom = (centerY + DEFAULT_RADIUS - ICON_SIZE.dp).toInt()
}
setMeasuredDimension(width, height) setMeasuredDimension(width, height)
} }
@ -310,7 +331,7 @@ class MicInputCloud(context: Context, attrs: AttributeSet) : View(context, attrs
} }
/** /**
* Sets the color of the cloud to the parameter, opacity is still set to 50% * Sets the color of the cloud to the parameter, opacity is still set to 50%.
*/ */
fun setColor(primary: Int) { fun setColor(primary: Int) {
primaryColor = primary primaryColor = primary
@ -323,7 +344,7 @@ class MicInputCloud(context: Context, attrs: AttributeSet) : View(context, attrs
} }
/** /**
* Sets state of the component to the parameter * Sets state of the component to the parameter, must be of type MicInputCloud.ViewState.
*/ */
fun setState(s: ViewState) { fun setState(s: ViewState) {
state = s state = s
@ -331,7 +352,7 @@ class MicInputCloud(context: Context, attrs: AttributeSet) : View(context, attrs
} }
/** /**
* Sets the rotation speed and radius to the parameters, defaults are left unchanged * Sets the rotation speed and radius to the parameters, defaults are left unchanged.
*/ */
fun setRotationSpeed(speed: Float, r: Float) { fun setRotationSpeed(speed: Float, r: Float) {
rotationSpeedMultiplier = speed rotationSpeedMultiplier = speed
@ -344,6 +365,7 @@ class MicInputCloud(context: Context, attrs: AttributeSet) : View(context, attrs
const val DEFAULT_RADIUS: Float = 70f const val DEFAULT_RADIUS: Float = 70f
const val EXTENDED_RADIUS: Float = 75f const val EXTENDED_RADIUS: Float = 75f
const val MAXIMUM_RADIUS: Float = 80f const val MAXIMUM_RADIUS: Float = 80f
const val ICON_SIZE: Int = 9 // Converted to dp this equals about 24dp
private const val DEFAULT_SIZE: Int = 110 private const val DEFAULT_SIZE: Int = 110
private const val DEFAULT_OPACITY: Int = 108 private const val DEFAULT_OPACITY: Int = 108
private const val DEFAULT_ROTATION_SPEED_MULTIPLIER: Float = 0.5f private const val DEFAULT_ROTATION_SPEED_MULTIPLIER: Float = 0.5f