Fix voice note playback and wave form generation in CFv2.

This commit is contained in:
Cody Henthorne
2023-07-18 12:53:20 -04:00
committed by Nicholas
parent b8effba497
commit e6c9449e3c
8 changed files with 146 additions and 38 deletions

View File

@@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.identity.UnverifiedBannerView
import org.thoughtcrime.securesms.components.reminder.Reminder
import org.thoughtcrime.securesms.components.reminder.ReminderView
import org.thoughtcrime.securesms.components.voice.VoiceNotePlayerView
import org.thoughtcrime.securesms.database.identity.IdentityRecordList
import org.thoughtcrime.securesms.database.model.IdentityRecord
import org.thoughtcrime.securesms.groups.GroupId
@@ -52,6 +53,7 @@ class ConversationBannerView @JvmOverloads constructor(
private val unverifiedBannerStub: Stub<UnverifiedBannerView> by lazy { ViewUtil.findStubById(this, R.id.unverified_banner_stub) }
private val reminderStub: Stub<ReminderView> by lazy { ViewUtil.findStubById(this, R.id.reminder_stub) }
private val reviewBannerStub: Stub<ReviewBannerView> by lazy { ViewUtil.findStubById(this, R.id.review_banner_stub) }
private val voiceNotePlayerStub: Stub<View> by lazy { ViewUtil.findStubById(this, R.id.voice_note_player_stub) }
var listener: Listener? = null
@@ -140,6 +142,20 @@ class ConversationBannerView @JvmOverloads constructor(
hide(reviewBannerStub)
}
fun showVoiceNotePlayer(state: VoiceNotePlayerView.State, voiceNotePlayerViewListener: VoiceNotePlayerView.Listener) {
show(
stub = voiceNotePlayerStub
) {
val playerView: VoiceNotePlayerView = findViewById(R.id.voice_note_player_view)
playerView.listener = voiceNotePlayerViewListener
playerView.setState(state)
}
}
fun clearVoiceNotePlayer() {
hide(voiceNotePlayerStub)
}
private fun <V : View> show(stub: Stub<V>, bind: V.() -> Unit = {}) {
TransitionManager.beginDelayedTransition(this, Slide(Gravity.TOP))
stub.get().bind()

View File

@@ -125,6 +125,7 @@ import org.thoughtcrime.securesms.components.settings.conversation.ConversationS
import org.thoughtcrime.securesms.components.voice.VoiceNoteDraft
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaControllerOwner
import org.thoughtcrime.securesms.components.voice.VoiceNotePlaybackState
import org.thoughtcrime.securesms.components.voice.VoiceNotePlayerView
import org.thoughtcrime.securesms.contacts.paged.ContactSearchKey.RecipientSearchKey
import org.thoughtcrime.securesms.contactshare.Contact
import org.thoughtcrime.securesms.contactshare.ContactUtil
@@ -416,6 +417,10 @@ class ConversationFragment :
)
}
private val voiceNotePlayerListener: VoiceNotePlayerView.Listener by lazy {
VoiceNotePlayerViewListener()
}
private val conversationTooltips = ConversationTooltips(this)
private val colorizer = Colorizer()
private val textDraftSaveDebouncer = Debouncer(500)
@@ -930,6 +935,18 @@ class ConversationFragment :
.addTo(disposables)
presentTypingIndicator()
getVoiceNoteMediaController().finishPostpone()
getVoiceNoteMediaController()
.voiceNotePlayerViewState
.observe(viewLifecycleOwner) { state: Optional<VoiceNotePlayerView.State> ->
if (state.isPresent) {
binding.conversationBanner.showVoiceNotePlayer(state.get(), voiceNotePlayerListener)
} else {
binding.conversationBanner.clearVoiceNotePlayer()
}
}
}
private fun initializeInlineSearch() {
@@ -3793,4 +3810,39 @@ class ConversationFragment :
draftViewModel.saveEphemeralVoiceNoteDraft(draft.asDraft())
}
}
private inner class VoiceNotePlayerViewListener : VoiceNotePlayerView.Listener {
override fun onCloseRequested(uri: Uri) {
getVoiceNoteMediaController().stopPlaybackAndReset(uri)
}
override fun onSpeedChangeRequested(uri: Uri, speed: Float) {
getVoiceNoteMediaController().setPlaybackSpeed(uri, speed)
}
override fun onPlay(uri: Uri, messageId: Long, position: Double) {
getVoiceNoteMediaController().startSinglePlayback(uri, messageId, position)
}
override fun onPause(uri: Uri) {
getVoiceNoteMediaController().pausePlayback(uri)
}
override fun onNavigateToMessage(threadId: Long, threadRecipientId: RecipientId, senderId: RecipientId, messageTimestamp: Long, messagePositionInThread: Long) {
if (threadId != viewModel.threadId) {
startActivity(
ConversationIntents.createBuilderSync(requireActivity(), threadRecipientId, threadId)
.withStartingPosition(messagePositionInThread.toInt())
.build()
)
} else {
viewModel
.moveToMessage(messageTimestamp, senderId)
.subscribeBy {
moveToPosition(it)
}
.addTo(disposables)
}
}
}
}

View File

@@ -320,9 +320,9 @@ class ConversationRepository(
}.subscribeOn(Schedulers.io())
}
fun getMessagePosition(threadId: Long, messageRecord: MessageRecord): Single<Int> {
fun getMessagePosition(threadId: Long, dateReceived: Long, authorId: RecipientId): Single<Int> {
return Single.fromCallable {
SignalDatabase.messages.getMessagePositionInConversation(threadId, messageRecord.dateReceived)
SignalDatabase.messages.getMessagePositionInConversation(threadId, dateReceived, authorId)
}.subscribeOn(Schedulers.io())
}

View File

@@ -262,8 +262,13 @@ class ConversationViewModel(
return repository.getNextMentionPosition(threadId)
}
fun moveToMessage(dateReceived: Long, author: RecipientId): Single<Int> {
return repository.getMessagePosition(threadId, dateReceived, author)
.observeOn(AndroidSchedulers.mainThread())
}
fun moveToMessage(messageRecord: MessageRecord): Single<Int> {
return repository.getMessagePosition(threadId, messageRecord)
return repository.getMessagePosition(threadId, messageRecord.dateReceived, messageRecord.fromRecipient.id)
.observeOn(AndroidSchedulers.mainThread())
}