@@ -140,6 +140,7 @@ import com.nextcloud.talk.adapters.messages.VoiceMessageInterface
140140import com.nextcloud.talk.api.NcApi
141141import com.nextcloud.talk.application.NextcloudTalkApplication
142142import com.nextcloud.talk.chat.data.model.ChatMessage
143+ import com.nextcloud.talk.chat.ui.model.MessageTypeContent
143144import com.nextcloud.talk.chat.viewmodels.ChatViewModel
144145import com.nextcloud.talk.chat.viewmodels.MessageInputViewModel
145146import com.nextcloud.talk.contextchat.ContextChatView
@@ -664,12 +665,76 @@ class ChatActivity :
664665 updateRemoteLastReadMessageIfNeeded = { updateRemoteLastReadMessageIfNeeded() },
665666 onLongClick = { openMessageActionsDialog(it) },
666667 onFileClick = { downloadAndOpenFile(it) },
667- onPollClick = { pollId, pollName -> openPollDialog(pollId, pollName) }
668+ onPollClick = { pollId, pollName -> openPollDialog(pollId, pollName) },
669+ onVoicePlayPauseClick = { onVoicePlayPauseClickCompose(it) },
670+ onVoiceSeek = { _, progress -> chatViewModel.seekToMediaPlayer(progress) },
671+ onVoiceSpeedClick = { onVoiceSpeedClickCompose(it) }
668672 )
669673 }
670674 }
671675 }
672676
677+ private fun onVoicePlayPauseClickCompose (messageId : Int ) {
678+ lifecycleScope.launch {
679+ val isCurrentlyPlaying = chatViewModel.uiState.value.items
680+ .mapNotNull { (it as ? ChatViewModel .ChatItem .MessageItem )?.uiMessage }
681+ .firstOrNull { it.id == messageId }
682+ ?.content
683+ ?.let { it as ? MessageTypeContent .Voice }
684+ ?.isPlaying ? : false
685+
686+ val message = chatViewModel.getMessageById(messageId.toLong()).first()
687+ val filename = message.fileParameters.name
688+ if (filename.isEmpty()) {
689+ return @launch
690+ }
691+
692+ val file = File (context.cacheDir, filename)
693+ if (file.exists()) {
694+ if (isCurrentlyPlaying) {
695+ chatViewModel.pauseMediaPlayer(true )
696+ chatViewModel.pauseVoiceMessageUiState(messageId)
697+ } else {
698+ val uiSpeed = chatViewModel.uiState.value.items
699+ .mapNotNull { (it as ? ChatViewModel .ChatItem .MessageItem )?.uiMessage }
700+ .firstOrNull { it.id == messageId }
701+ ?.content
702+ ?.let { it as ? MessageTypeContent .Voice }
703+ ?.playbackSpeed ? : PlaybackSpeed .NORMAL
704+ chatViewModel.setPlayBack(uiSpeed)
705+
706+ val retrieved = appPreferences.getWaveFormFromFile(filename)
707+ if (retrieved.isEmpty()) {
708+ setUpWaveform(message)
709+ } else {
710+ if (message.voiceMessageFloatArray == null || message.voiceMessageFloatArray!! .isEmpty()) {
711+ message.voiceMessageFloatArray = retrieved.toFloatArray()
712+ chatViewModel.syncVoiceMessageUiState(message)
713+ }
714+ startPlayback(file, message)
715+ }
716+ }
717+ } else {
718+ downloadFileToCache(message, true ) {
719+ setUpWaveform(message)
720+ }
721+ }
722+ }
723+ }
724+
725+ private fun onVoiceSpeedClickCompose (messageId : Int ) {
726+ val currentSpeed = chatViewModel.uiState.value.items
727+ .mapNotNull { (it as ? ChatViewModel .ChatItem .MessageItem )?.uiMessage }
728+ .firstOrNull { it.id == messageId }
729+ ?.content
730+ ?.let { it as ? MessageTypeContent .Voice }
731+ ?.playbackSpeed ? : PlaybackSpeed .NORMAL
732+ val nextSpeed = currentSpeed.next()
733+ chatViewModel.setPlayBack(nextSpeed)
734+ appPreferences.savePreferredPlayback(conversationUser!! .userId, nextSpeed)
735+ chatViewModel.setVoiceMessageSpeed(messageId, nextSpeed)
736+ }
737+
673738 fun downloadAndOpenFile (messageId : Int ) {
674739 lifecycleScope.launch {
675740 val chatMessage = chatViewModel.getMessageById(messageId.toLong()).first()
@@ -1734,12 +1799,15 @@ class ChatActivity :
17341799 val file = File (context.cacheDir, filename!! )
17351800 if (file.exists() && message.voiceMessageFloatArray == null ) {
17361801 message.isDownloadingVoiceMessage = true
1802+ chatViewModel.syncVoiceMessageUiState(message)
17371803 adapter?.update(message)
17381804 CoroutineScope (Dispatchers .Default ).launch {
17391805 val r = AudioUtils .audioFileToFloatArray(file)
17401806 appPreferences.saveWaveFormForFile(filename, r.toTypedArray())
17411807 message.voiceMessageFloatArray = r
17421808 withContext(Dispatchers .Main ) {
1809+ message.isDownloadingVoiceMessage = false
1810+ chatViewModel.syncVoiceMessageUiState(message)
17431811 startPlayback(file, message)
17441812 }
17451813 }
@@ -1753,6 +1821,7 @@ class ChatActivity :
17531821 chatViewModel.queueInMediaPlayer(file.canonicalPath, message)
17541822 chatViewModel.startCyclingMediaPlayer()
17551823 message.isPlayingVoiceMessage = true
1824+ chatViewModel.syncVoiceMessageUiState(message)
17561825 adapter?.update(message)
17571826
17581827 var pos = adapter?.getMessagePositionById(message.id)?.minus(1 ) ? : - 1
@@ -2211,13 +2280,14 @@ class ChatActivity :
22112280 funToCallWhenDownloadSuccessful : (() -> Unit )
22122281 ) {
22132282 message.isDownloadingVoiceMessage = true
2283+ chatViewModel.syncVoiceMessageUiState(message)
22142284 message.openWhenDownloaded = openWhenDownloaded
22152285 adapter?.update(message)
22162286
2217- val baseUrl = message.activeUser !! .baseUrl
2218- val userId = message.activeUser !! .userId
2287+ val baseUrl = conversationUser .baseUrl
2288+ val userId = conversationUser .userId
22192289 val attachmentFolder = CapabilitiesUtil .getAttachmentFolder(
2220- message.activeUser !! .capabilities!!
2290+ conversationUser .capabilities!!
22212291 .spreedCapability!!
22222292 )
22232293 val fileName = message.fileParameters.name
0 commit comments