mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-28 13:00:47 +00:00
Merge pull request #637 from hjubb/fix_voice_update_crash
Fix Voice Message Behavior
This commit is contained in:
commit
d447c5c307
@ -9,12 +9,12 @@ import org.session.libsession.messaging.sending_receiving.attachments.*
|
|||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.session.libsession.utilities.UploadResult
|
import org.session.libsession.utilities.UploadResult
|
||||||
import org.session.libsession.utilities.Util
|
import org.session.libsession.utilities.Util
|
||||||
import org.session.libsignal.utilities.guava.Optional
|
|
||||||
import org.session.libsignal.messages.SignalServiceAttachment
|
import org.session.libsignal.messages.SignalServiceAttachment
|
||||||
import org.session.libsignal.messages.SignalServiceAttachmentPointer
|
import org.session.libsignal.messages.SignalServiceAttachmentPointer
|
||||||
import org.session.libsignal.messages.SignalServiceAttachmentStream
|
import org.session.libsignal.messages.SignalServiceAttachmentStream
|
||||||
import org.session.libsignal.utilities.Base64
|
import org.session.libsignal.utilities.Base64
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
|
import org.session.libsignal.utilities.guava.Optional
|
||||||
import org.thoughtcrime.securesms.database.AttachmentDatabase
|
import org.thoughtcrime.securesms.database.AttachmentDatabase
|
||||||
import org.thoughtcrime.securesms.database.Database
|
import org.thoughtcrime.securesms.database.Database
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
@ -97,12 +97,17 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
|
|||||||
attachmentDatabase.insertAttachmentsForPlaceholder(messageId, attachmentId, stream)
|
attachmentDatabase.insertAttachmentsForPlaceholder(messageId, attachmentId, stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateAudioAttachmentDuration(attachmentId: AttachmentId, durationMs: Long) {
|
override fun updateAudioAttachmentDuration(
|
||||||
DatabaseFactory.getAttachmentDatabase(context).setAttachmentAudioExtras(DatabaseAttachmentAudioExtras(
|
attachmentId: AttachmentId,
|
||||||
|
durationMs: Long,
|
||||||
|
threadId: Long
|
||||||
|
) {
|
||||||
|
val attachmentDb = DatabaseFactory.getAttachmentDatabase(context)
|
||||||
|
attachmentDb.setAttachmentAudioExtras(DatabaseAttachmentAudioExtras(
|
||||||
attachmentId = attachmentId,
|
attachmentId = attachmentId,
|
||||||
visualSamples = byteArrayOf(),
|
visualSamples = byteArrayOf(),
|
||||||
durationMs = durationMs
|
durationMs = durationMs
|
||||||
))
|
), threadId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isOutgoingMessage(timestamp: Long): Boolean {
|
override fun isOutgoingMessage(timestamp: Long): Boolean {
|
||||||
|
@ -4,7 +4,8 @@ import android.content.Context
|
|||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
@ -23,6 +24,10 @@ import kotlin.math.roundToLong
|
|||||||
class VoiceMessageView : LinearLayout, AudioSlidePlayer.Listener {
|
class VoiceMessageView : LinearLayout, AudioSlidePlayer.Listener {
|
||||||
private val cornerMask by lazy { CornerMask(this) }
|
private val cornerMask by lazy { CornerMask(this) }
|
||||||
private var isPlaying = false
|
private var isPlaying = false
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
renderIcon()
|
||||||
|
}
|
||||||
private var progress = 0.0
|
private var progress = 0.0
|
||||||
private var duration = 0L
|
private var duration = 0L
|
||||||
private var player: AudioSlidePlayer? = null
|
private var player: AudioSlidePlayer? = null
|
||||||
@ -44,8 +49,6 @@ class VoiceMessageView : LinearLayout, AudioSlidePlayer.Listener {
|
|||||||
// region Updating
|
// region Updating
|
||||||
fun bind(message: MmsMessageRecord, isStartOfMessageCluster: Boolean, isEndOfMessageCluster: Boolean) {
|
fun bind(message: MmsMessageRecord, isStartOfMessageCluster: Boolean, isEndOfMessageCluster: Boolean) {
|
||||||
val audio = message.slideDeck.audioSlide!!
|
val audio = message.slideDeck.audioSlide!!
|
||||||
val player = AudioSlidePlayer.createFor(context, audio, this)
|
|
||||||
this.player = player
|
|
||||||
voiceMessageViewLoader.isVisible = audio.isPendingDownload
|
voiceMessageViewLoader.isVisible = audio.isPendingDownload
|
||||||
val cornerRadii = MessageBubbleUtilities.calculateRadii(context, isStartOfMessageCluster, isEndOfMessageCluster, message.isOutgoing)
|
val cornerRadii = MessageBubbleUtilities.calculateRadii(context, isStartOfMessageCluster, isEndOfMessageCluster, message.isOutgoing)
|
||||||
cornerMask.setTopLeftRadius(cornerRadii[0])
|
cornerMask.setTopLeftRadius(cornerRadii[0])
|
||||||
@ -54,7 +57,13 @@ class VoiceMessageView : LinearLayout, AudioSlidePlayer.Listener {
|
|||||||
cornerMask.setBottomLeftRadius(cornerRadii[3])
|
cornerMask.setBottomLeftRadius(cornerRadii[3])
|
||||||
|
|
||||||
// only process audio if downloaded
|
// only process audio if downloaded
|
||||||
if (audio.isPendingDownload || audio.isInProgress) return
|
if (audio.isPendingDownload || audio.isInProgress) {
|
||||||
|
this.player = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val player = AudioSlidePlayer.createFor(context, audio, this)
|
||||||
|
this.player = player
|
||||||
|
|
||||||
(audio.asAttachment() as? DatabaseAttachment)?.let { attachment ->
|
(audio.asAttachment() as? DatabaseAttachment)?.let { attachment ->
|
||||||
DatabaseFactory.getAttachmentDatabase(context).getAttachmentAudioExtras(attachment.attachmentId)?.let { audioExtras ->
|
DatabaseFactory.getAttachmentDatabase(context).getAttachmentAudioExtras(attachment.attachmentId)?.let { audioExtras ->
|
||||||
@ -90,20 +99,27 @@ class VoiceMessageView : LinearLayout, AudioSlidePlayer.Listener {
|
|||||||
progressView.layoutParams = layoutParams
|
progressView.layoutParams = layoutParams
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPlayerStop(player: AudioSlidePlayer) { }
|
override fun onPlayerStop(player: AudioSlidePlayer) {
|
||||||
|
Log.d("Loki", "Player stopped")
|
||||||
|
isPlaying = false
|
||||||
|
}
|
||||||
|
|
||||||
override fun dispatchDraw(canvas: Canvas) {
|
override fun dispatchDraw(canvas: Canvas) {
|
||||||
super.dispatchDraw(canvas)
|
super.dispatchDraw(canvas)
|
||||||
cornerMask.mask(canvas)
|
cornerMask.mask(canvas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun renderIcon() {
|
||||||
|
val iconID = if (isPlaying) R.drawable.exo_icon_pause else R.drawable.exo_icon_play
|
||||||
|
voiceMessagePlaybackImageView.setImageResource(iconID)
|
||||||
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Interaction
|
// region Interaction
|
||||||
fun togglePlayback() {
|
fun togglePlayback() {
|
||||||
val player = this.player ?: return
|
val player = this.player ?: return
|
||||||
isPlaying = !isPlaying
|
isPlaying = !isPlaying
|
||||||
val iconID = if (isPlaying) R.drawable.exo_icon_pause else R.drawable.exo_icon_play
|
|
||||||
voiceMessagePlaybackImageView.setImageResource(iconID)
|
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
player.play(progress)
|
player.play(progress)
|
||||||
} else {
|
} else {
|
||||||
|
@ -44,8 +44,8 @@ import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAt
|
|||||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachmentAudioExtras;
|
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachmentAudioExtras;
|
||||||
import org.session.libsession.utilities.MediaTypes;
|
import org.session.libsession.utilities.MediaTypes;
|
||||||
import org.session.libsession.utilities.Util;
|
import org.session.libsession.utilities.Util;
|
||||||
import org.session.libsignal.utilities.JsonUtil;
|
|
||||||
import org.session.libsignal.utilities.ExternalStorageUtil;
|
import org.session.libsignal.utilities.ExternalStorageUtil;
|
||||||
|
import org.session.libsignal.utilities.JsonUtil;
|
||||||
import org.session.libsignal.utilities.Log;
|
import org.session.libsignal.utilities.Log;
|
||||||
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
|
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
|
||||||
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream;
|
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream;
|
||||||
@ -820,7 +820,7 @@ public class AttachmentDatabase extends Database {
|
|||||||
* @return true if the update operation was successful.
|
* @return true if the update operation was successful.
|
||||||
*/
|
*/
|
||||||
@Synchronized
|
@Synchronized
|
||||||
public boolean setAttachmentAudioExtras(@NonNull DatabaseAttachmentAudioExtras extras) {
|
public boolean setAttachmentAudioExtras(@NonNull DatabaseAttachmentAudioExtras extras, long threadId) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(AUDIO_VISUAL_SAMPLES, extras.getVisualSamples());
|
values.put(AUDIO_VISUAL_SAMPLES, extras.getVisualSamples());
|
||||||
values.put(AUDIO_DURATION, extras.getDurationMs());
|
values.put(AUDIO_DURATION, extras.getDurationMs());
|
||||||
@ -830,9 +830,22 @@ public class AttachmentDatabase extends Database {
|
|||||||
PART_ID_WHERE + " AND " + PART_AUDIO_ONLY_WHERE,
|
PART_ID_WHERE + " AND " + PART_AUDIO_ONLY_WHERE,
|
||||||
extras.getAttachmentId().toStrings());
|
extras.getAttachmentId().toStrings());
|
||||||
|
|
||||||
|
if (threadId >= 0) {
|
||||||
|
notifyConversationListeners(threadId);
|
||||||
|
}
|
||||||
|
|
||||||
return alteredRows > 0;
|
return alteredRows > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates audio extra columns for the "audio/*" mime type attachments only.
|
||||||
|
* @return true if the update operation was successful.
|
||||||
|
*/
|
||||||
|
@Synchronized
|
||||||
|
public boolean setAttachmentAudioExtras(@NonNull DatabaseAttachmentAudioExtras extras) {
|
||||||
|
return setAttachmentAudioExtras(extras, -1); // -1 for no update
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
class ThumbnailFetchCallable implements Callable<InputStream> {
|
class ThumbnailFetchCallable implements Callable<InputStream> {
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ interface MessageDataProvider {
|
|||||||
fun getSignalAttachmentPointer(attachmentId: Long): SignalServiceAttachmentPointer?
|
fun getSignalAttachmentPointer(attachmentId: Long): SignalServiceAttachmentPointer?
|
||||||
fun setAttachmentState(attachmentState: AttachmentState, attachmentId: Long, messageID: Long)
|
fun setAttachmentState(attachmentState: AttachmentState, attachmentId: Long, messageID: Long)
|
||||||
fun insertAttachment(messageId: Long, attachmentId: AttachmentId, stream : InputStream)
|
fun insertAttachment(messageId: Long, attachmentId: AttachmentId, stream : InputStream)
|
||||||
fun updateAudioAttachmentDuration(attachmentId: AttachmentId, durationMs: Long)
|
fun updateAudioAttachmentDuration(attachmentId: AttachmentId, durationMs: Long, threadId: Long)
|
||||||
fun isOutgoingMessage(timestamp: Long): Boolean
|
fun isOutgoingMessage(timestamp: Long): Boolean
|
||||||
fun handleSuccessfulAttachmentUpload(attachmentId: Long, attachmentStream: SignalServiceAttachmentStream, attachmentKey: ByteArray, uploadResult: UploadResult)
|
fun handleSuccessfulAttachmentUpload(attachmentId: Long, attachmentStream: SignalServiceAttachmentStream, attachmentKey: ByteArray, uploadResult: UploadResult)
|
||||||
fun handleFailedAttachmentUpload(attachmentId: Long)
|
fun handleFailedAttachmentUpload(attachmentId: Long)
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
package org.session.libsession.messaging.jobs
|
package org.session.libsession.messaging.jobs
|
||||||
|
|
||||||
import android.content.ContentResolver
|
|
||||||
import android.media.MediaDataSource
|
|
||||||
import android.media.MediaExtractor
|
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
|
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
|
||||||
@ -78,7 +75,11 @@ class AttachmentDownloadJob(val attachmentID: Long, val databaseMessageID: Long)
|
|||||||
try {
|
try {
|
||||||
InputStreamMediaDataSource(getInputStream(tempFile, attachment)).use { mediaDataSource ->
|
InputStreamMediaDataSource(getInputStream(tempFile, attachment)).use { mediaDataSource ->
|
||||||
val durationMs = (DecodedAudio.create(mediaDataSource).totalDuration / 1000.0).toLong()
|
val durationMs = (DecodedAudio.create(mediaDataSource).totalDuration / 1000.0).toLong()
|
||||||
messageDataProvider.updateAudioAttachmentDuration(attachment.attachmentId, durationMs)
|
messageDataProvider.updateAudioAttachmentDuration(
|
||||||
|
attachment.attachmentId,
|
||||||
|
durationMs,
|
||||||
|
threadID
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("Loki", "Couldn't process audio attachment", e)
|
Log.e("Loki", "Couldn't process audio attachment", e)
|
||||||
|
@ -14,15 +14,11 @@ import org.session.libsession.messaging.utilities.Data
|
|||||||
import org.session.libsession.utilities.DecodedAudio
|
import org.session.libsession.utilities.DecodedAudio
|
||||||
import org.session.libsession.utilities.InputStreamMediaDataSource
|
import org.session.libsession.utilities.InputStreamMediaDataSource
|
||||||
import org.session.libsession.utilities.UploadResult
|
import org.session.libsession.utilities.UploadResult
|
||||||
import org.session.libsignal.streams.AttachmentCipherOutputStream
|
|
||||||
import org.session.libsignal.messages.SignalServiceAttachmentStream
|
import org.session.libsignal.messages.SignalServiceAttachmentStream
|
||||||
import org.session.libsignal.streams.PaddingInputStream
|
import org.session.libsignal.streams.*
|
||||||
import org.session.libsignal.utilities.PushAttachmentData
|
|
||||||
import org.session.libsignal.streams.AttachmentCipherOutputStreamFactory
|
|
||||||
import org.session.libsignal.streams.DigestingRequestBody
|
|
||||||
import org.session.libsignal.utilities.Util
|
|
||||||
import org.session.libsignal.streams.PlaintextOutputStreamFactory
|
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
|
import org.session.libsignal.utilities.PushAttachmentData
|
||||||
|
import org.session.libsignal.utilities.Util
|
||||||
|
|
||||||
class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val message: Message, val messageSendJobID: String) : Job {
|
class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val message: Message, val messageSendJobID: String) : Job {
|
||||||
override var delegate: JobDelegate? = null
|
override var delegate: JobDelegate? = null
|
||||||
@ -119,7 +115,7 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess
|
|||||||
InputStreamMediaDataSource(inputStream).use { mediaDataSource ->
|
InputStreamMediaDataSource(inputStream).use { mediaDataSource ->
|
||||||
val durationMs = (DecodedAudio.create(mediaDataSource).totalDuration / 1000.0).toLong()
|
val durationMs = (DecodedAudio.create(mediaDataSource).totalDuration / 1000.0).toLong()
|
||||||
messageDataProvider.getDatabaseAttachment(attachmentID)?.attachmentId?.let { attachmentId ->
|
messageDataProvider.getDatabaseAttachment(attachmentID)?.attachmentId?.let { attachmentId ->
|
||||||
messageDataProvider.updateAudioAttachmentDuration(attachmentId, durationMs)
|
messageDataProvider.updateAudioAttachmentDuration(attachmentId, durationMs, threadID.toLong())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user