mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 11:39:42 +01:00
when a voice message is played, starts the download of the next ones if any, computes their durations and starts playing the next one at the end of the current. Plays a doodle between them
Signed-off-by: Giacomo Pacini <giacomopacini98@gmail.com>
This commit is contained in:
parent
410b27b72c
commit
6a598357fc
@ -185,6 +185,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleIsPlayingVoiceMessageState(message: ChatMessage) {
|
private fun handleIsPlayingVoiceMessageState(message: ChatMessage) {
|
||||||
|
colorizeMessageBubble(message)
|
||||||
if (message.isPlayingVoiceMessage) {
|
if (message.isPlayingVoiceMessage) {
|
||||||
showPlayButton()
|
showPlayButton()
|
||||||
binding.playPauseBtn.icon = ContextCompat.getDrawable(
|
binding.playPauseBtn.icon = ContextCompat.getDrawable(
|
||||||
@ -199,6 +200,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) :
|
|||||||
binding.seekbar.max = message.voiceMessageDuration * ONE_SEC
|
binding.seekbar.max = message.voiceMessageDuration * ONE_SEC
|
||||||
binding.seekbar.progress = message.voiceMessageSeekbarProgress
|
binding.seekbar.progress = message.voiceMessageSeekbarProgress
|
||||||
} else {
|
} else {
|
||||||
|
showVoiceMessageDuration(message)
|
||||||
binding.playPauseBtn.visibility = View.VISIBLE
|
binding.playPauseBtn.visibility = View.VISIBLE
|
||||||
binding.playPauseBtn.icon = ContextCompat.getDrawable(
|
binding.playPauseBtn.icon = ContextCompat.getDrawable(
|
||||||
context!!,
|
context!!,
|
||||||
|
@ -219,6 +219,7 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleIsPlayingVoiceMessageState(message: ChatMessage) {
|
private fun handleIsPlayingVoiceMessageState(message: ChatMessage) {
|
||||||
|
colorizeMessageBubble(message)
|
||||||
if (message.isPlayingVoiceMessage) {
|
if (message.isPlayingVoiceMessage) {
|
||||||
showPlayButton()
|
showPlayButton()
|
||||||
binding.playPauseBtn.icon = ContextCompat.getDrawable(
|
binding.playPauseBtn.icon = ContextCompat.getDrawable(
|
||||||
@ -233,6 +234,7 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) :
|
|||||||
binding.seekbar.max = message.voiceMessageDuration * ONE_SEC
|
binding.seekbar.max = message.voiceMessageDuration * ONE_SEC
|
||||||
binding.seekbar.progress = message.voiceMessageSeekbarProgress
|
binding.seekbar.progress = message.voiceMessageSeekbarProgress
|
||||||
} else {
|
} else {
|
||||||
|
showVoiceMessageDuration(message)
|
||||||
binding.playPauseBtn.visibility = View.VISIBLE
|
binding.playPauseBtn.visibility = View.VISIBLE
|
||||||
binding.playPauseBtn.icon = ContextCompat.getDrawable(
|
binding.playPauseBtn.icon = ContextCompat.getDrawable(
|
||||||
context!!,
|
context!!,
|
||||||
|
@ -27,6 +27,11 @@ import android.database.Cursor
|
|||||||
import android.graphics.drawable.BitmapDrawable
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.media.AudioFocusRequest
|
||||||
|
import android.media.AudioFormat
|
||||||
|
import android.media.AudioManager
|
||||||
|
import android.media.AudioRecord
|
||||||
|
import android.media.MediaMetadataRetriever
|
||||||
import android.media.MediaPlayer
|
import android.media.MediaPlayer
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
@ -1614,16 +1619,70 @@ class ChatActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun startPlayback(message: ChatMessage, doPlay: Boolean = true) {
|
private fun startPlayback(message: ChatMessage, doPlay: Boolean = true) {
|
||||||
if (!active) {
|
//if (!active) {
|
||||||
// don't begin to play voice message if screen is not visible anymore.
|
// don't begin to play voice message if screen is not visible anymore.
|
||||||
// this situation might happen if file is downloading but user already left the chatview.
|
// this situation might happen if file is downloading but user already left the chatview.
|
||||||
// If user returns to chatview, the old chatview instance is not attached anymore
|
// If user returns to chatview, the old chatview instance is not attached anymore
|
||||||
// and he has to click the play button again (which is considered to be okay)
|
// and he has to click the play button again (which is considered to be okay)
|
||||||
return
|
// return
|
||||||
}
|
//}
|
||||||
|
|
||||||
initMediaPlayer(message)
|
initMediaPlayer(message)
|
||||||
|
|
||||||
|
val id = message.id.toString()
|
||||||
|
val index = adapter?.getMessagePositionById(id) ?: 0
|
||||||
|
|
||||||
|
var nextMessage : ChatMessage? = null
|
||||||
|
for (i in 1..5) {
|
||||||
|
if(index - i < 0){
|
||||||
|
break
|
||||||
|
}
|
||||||
|
val curMsg = adapter?.items?.get(index - i)?.item
|
||||||
|
if(curMsg is ChatMessage) {
|
||||||
|
if(nextMessage == null) {
|
||||||
|
nextMessage = curMsg as ChatMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
if(curMsg.isVoiceMessage){
|
||||||
|
val filename = curMsg.selectedIndividualHashMap!!["name"]
|
||||||
|
val file = File(context.cacheDir, filename!!)
|
||||||
|
if (!file.exists()) {
|
||||||
|
downloadFileToCache(curMsg as ChatMessage, false) {
|
||||||
|
curMsg.isDownloadingVoiceMessage = false
|
||||||
|
curMsg.voiceMessageDuration = try {
|
||||||
|
val retriever = MediaMetadataRetriever()
|
||||||
|
retriever.setDataSource(file.absolutePath) // Set the audio file as the data source
|
||||||
|
val durationStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
|
||||||
|
retriever.release() // Always release the retriever to free resources
|
||||||
|
(durationStr?.toIntOrNull() ?: 0 )/ 1000 // Convert to int (seconds)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
0
|
||||||
|
}
|
||||||
|
adapter?.update(curMsg)
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(curMsg.voiceMessageDuration == 0) {
|
||||||
|
curMsg.voiceMessageDuration = try {
|
||||||
|
val retriever = MediaMetadataRetriever()
|
||||||
|
retriever.setDataSource(file.absolutePath) // Set the audio file as the data source
|
||||||
|
val durationStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
|
||||||
|
retriever.release() // Always release the retriever to free resources
|
||||||
|
(durationStr?.toIntOrNull() ?: 0 )/ 1000 // Convert to int (seconds)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
0
|
||||||
|
}
|
||||||
|
adapter?.update(curMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val hasConsecutiveVoiceMessage = if(nextMessage != null) nextMessage.isVoiceMessage else false
|
||||||
|
|
||||||
|
|
||||||
mediaPlayer?.let {
|
mediaPlayer?.let {
|
||||||
if (!it.isPlaying && doPlay) {
|
if (!it.isPlaying && doPlay) {
|
||||||
chatViewModel.audioRequest(true) {
|
chatViewModel.audioRequest(true) {
|
||||||
@ -1656,6 +1715,15 @@ class ChatActivity :
|
|||||||
message.voiceMessageSeekbarProgress = 0
|
message.voiceMessageSeekbarProgress = 0
|
||||||
adapter?.update(message)
|
adapter?.update(message)
|
||||||
stopMediaPlayer(message)
|
stopMediaPlayer(message)
|
||||||
|
if(hasConsecutiveVoiceMessage){
|
||||||
|
val defaultMediaPlayer = MediaPlayer.create(context, R.raw
|
||||||
|
.next_voice_message_doodle)
|
||||||
|
defaultMediaPlayer.setOnCompletionListener {
|
||||||
|
defaultMediaPlayer.release()
|
||||||
|
setUpWaveform(nextMessage as ChatMessage, doPlay)
|
||||||
|
}
|
||||||
|
defaultMediaPlayer.start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
app/src/main/res/raw/next_voice_message_doodle.ogg
Normal file
BIN
app/src/main/res/raw/next_voice_message_doodle.ogg
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user