Add basic timeline voice broadcast item

This commit is contained in:
Florian Renaud 2022-09-29 10:29:08 +02:00
parent bcc84c8025
commit daf4fc0f6d
4 changed files with 149 additions and 22 deletions

View File

@ -55,6 +55,8 @@ import im.vector.app.features.home.room.detail.timeline.item.MessageLocationItem
import im.vector.app.features.home.room.detail.timeline.item.MessageLocationItem_
import im.vector.app.features.home.room.detail.timeline.item.MessageTextItem
import im.vector.app.features.home.room.detail.timeline.item.MessageTextItem_
import im.vector.app.features.home.room.detail.timeline.item.MessageVoiceBroadcastItem
import im.vector.app.features.home.room.detail.timeline.item.MessageVoiceBroadcastItem_
import im.vector.app.features.home.room.detail.timeline.item.MessageVoiceItem
import im.vector.app.features.home.room.detail.timeline.item.MessageVoiceItem_
import im.vector.app.features.home.room.detail.timeline.item.PollItem
@ -200,7 +202,7 @@ class MessageItemFactory @Inject constructor(
is MessagePollContent -> buildPollItem(messageContent, informationData, highlight, callback, attributes)
is MessageLocationContent -> buildLocationItem(messageContent, informationData, highlight, attributes)
is MessageBeaconInfoContent -> liveLocationShareMessageItemFactory.create(params.event, highlight, attributes)
is MessageVoiceBroadcastInfoContent -> buildVoiceBroadcastItem(messageContent, informationData, highlight, callback, attributes)
is MessageVoiceBroadcastInfoContent -> buildVoiceBroadcastItem(messageContent, highlight, callback, attributes)
else -> buildNotHandledMessageItem(messageContent, informationData, highlight, callback, attributes)
}
return messageItem?.apply {
@ -723,32 +725,16 @@ class MessageItemFactory @Inject constructor(
private fun buildVoiceBroadcastItem(
messageContent: MessageVoiceBroadcastInfoContent,
@Suppress("UNUSED_PARAMETER")
informationData: MessageInformationData,
highlight: Boolean,
callback: TimelineEventController.Callback?,
attributes: AbsMessageItem.Attributes,
): MessageTextItem? {
val htmlBody = "voice broadcast state: ${messageContent.voiceBroadcastState}"
val formattedBody = span {
text = htmlBody
textColor = colorProvider.getColorFromAttribute(R.attr.vctr_content_secondary)
textStyle = "italic"
}
val bindingOptions = spanUtils.getBindingOptions(htmlBody)
val message = formattedBody.linkify(callback)
return MessageTextItem_()
.leftGuideline(avatarSizeProvider.leftGuideline)
.previewUrlRetriever(callback?.getPreviewUrlRetriever())
.imageContentRenderer(imageContentRenderer)
.previewUrlCallback(callback)
): MessageVoiceBroadcastItem? {
return MessageVoiceBroadcastItem_()
.attributes(attributes)
.message(message.toEpoxyCharSequence())
.bindingOptions(bindingOptions)
.highlighted(highlight)
.movementMethod(createLinkMovementMethod(callback))
.playingState(messageContent.voiceBroadcastStateStr.toEpoxyCharSequence())
.leftGuideline(avatarSizeProvider.leftGuideline)
.callback(callback)
}
private fun List<Int?>?.toFft(): List<Int>? {

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.home.room.detail.timeline.item
import android.annotation.SuppressLint
import android.widget.ImageButton
import android.widget.TextView
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
import im.vector.app.features.home.room.detail.RoomDetailAction
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState
import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence
@EpoxyModelClass
abstract class MessageVoiceBroadcastItem : AbsMessageItem<MessageVoiceBroadcastItem.Holder>() {
@EpoxyAttribute
var callback: TimelineEventController.Callback? = null
@EpoxyAttribute
var playingState: EpoxyCharSequence? = null
override fun bind(holder: Holder) {
super.bind(holder)
bindVoiceBroadcastItem(holder)
}
@SuppressLint("SetTextI18n") // Temporary text
private fun bindVoiceBroadcastItem(holder: Holder) {
with(holder) {
currentStateText.text = "Voice Broadcast state: ${playingState?.charSequence ?: "None"}"
val voiceBroadcastState = VoiceBroadcastState.values().find { it.value == playingState?.charSequence }
playButton.isEnabled = voiceBroadcastState == VoiceBroadcastState.PAUSED
pauseButton.isEnabled = voiceBroadcastState == VoiceBroadcastState.STARTED || voiceBroadcastState == VoiceBroadcastState.RESUMED
stopButton.isEnabled = voiceBroadcastState == VoiceBroadcastState.STARTED ||
voiceBroadcastState == VoiceBroadcastState.RESUMED ||
voiceBroadcastState == VoiceBroadcastState.PAUSED
playButton.setOnClickListener { attributes.callback?.onTimelineItemAction(RoomDetailAction.VoiceBroadcastAction.Resume) }
pauseButton.setOnClickListener { attributes.callback?.onTimelineItemAction(RoomDetailAction.VoiceBroadcastAction.Pause) }
stopButton.setOnClickListener { attributes.callback?.onTimelineItemAction(RoomDetailAction.VoiceBroadcastAction.Stop) }
}
}
override fun getViewStubId() = STUB_ID
class Holder : AbsMessageLocationItem.Holder(STUB_ID) {
val currentStateText by bind<TextView>(R.id.currentStateText)
val playButton by bind<ImageButton>(R.id.playButton)
val pauseButton by bind<ImageButton>(R.id.pauseButton)
val stopButton by bind<ImageButton>(R.id.stopButton)
}
companion object {
private val STUB_ID = R.id.messageVoiceBroadcastStub
}
}

View File

@ -47,6 +47,13 @@
android:layout="@layout/item_timeline_event_audio_stub"
tools:visibility="gone" />
<ViewStub
android:id="@+id/messageVoiceBroadcastStub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout="@layout/item_timeline_event_voice_broadcast_stub"
tools:visibility="gone" />
<ViewStub
android:id="@+id/messageContentPollStub"
android:layout_width="match_parent"

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/messageRootLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/layout_vertical_margin"
tools:viewBindingIgnore="true">
<TextView
android:id="@+id/currentStateText"
style="@style/Widget.Vector.TextView.HeadlineMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/playButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Voice Broadcast state: STARTED" />
<ImageButton
android:id="@+id/playButton"
android:layout_width="@dimen/item_event_message_media_button_size"
android:layout_height="@dimen/item_event_message_media_button_size"
android:layout_marginTop="@dimen/layout_vertical_margin"
android:background="?android:attr/selectableItemBackground"
android:contentDescription="@string/a11y_play_voice_message"
android:src="@drawable/ic_play_pause_play"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/pauseButton"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/currentStateText"
app:tint="@color/vector_content_primary_tint_selector" />
<ImageButton
android:id="@+id/pauseButton"
android:layout_width="@dimen/item_event_message_media_button_size"
android:layout_height="@dimen/item_event_message_media_button_size"
android:background="?android:attr/selectableItemBackground"
android:contentDescription="@string/a11y_pause_voice_message"
android:src="@drawable/ic_play_pause_pause"
app:layout_constraintBottom_toBottomOf="@id/playButton"
app:layout_constraintEnd_toStartOf="@id/stopButton"
app:layout_constraintStart_toEndOf="@id/playButton"
app:layout_constraintTop_toTopOf="@id/playButton"
app:tint="@color/vector_content_primary_tint_selector" />
<ImageButton
android:id="@+id/stopButton"
android:layout_width="@dimen/item_event_message_media_button_size"
android:layout_height="@dimen/item_event_message_media_button_size"
android:background="?android:attr/selectableItemBackground"
android:contentDescription="@string/a11y_stop_voice_message"
android:src="@drawable/ic_close_24dp"
app:layout_constraintBottom_toBottomOf="@id/pauseButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/pauseButton"
app:layout_constraintTop_toTopOf="@id/playButton"
app:tint="@color/vector_content_primary_tint_selector" />
</androidx.constraintlayout.widget.ConstraintLayout>