Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • circles/circles-android
1 result
Show changes
Commits on Source (7)
Showing
with 493 additions and 114 deletions
......@@ -5,9 +5,16 @@ import androidx.media3.exoplayer.ExoPlayer
import org.futo.circles.core.model.Post
import org.futo.circles.core.model.PostContentType
import org.futo.circles.core.model.TimelineLoadingItem
import org.futo.circles.feature.direct.timeline.list.holder.DmMyImageMessageViewHolder
import org.futo.circles.feature.direct.timeline.list.holder.DmMyTextMessageViewHolder
import org.futo.circles.feature.direct.timeline.list.holder.DmMyVideoMessageViewHolder
import org.futo.circles.feature.direct.timeline.list.holder.DmOtherImageMessageViewHolder
import org.futo.circles.feature.direct.timeline.list.holder.DmOtherTextMessageViewHolder
import org.futo.circles.feature.direct.timeline.list.holder.DmOtherVideoMessageViewHolder
import org.futo.circles.feature.timeline.base.BaseTimelineAdapter
import org.futo.circles.feature.timeline.base.TimelineListItemViewHolder
import org.futo.circles.feature.timeline.list.PostOptionsListener
import org.futo.circles.feature.timeline.list.holder.OtherEventPostViewHolder
import org.futo.circles.feature.timeline.list.holder.PostListItemViewHolder
import org.futo.circles.feature.timeline.list.holder.TimelineLoadingViewHolder
private enum class DmTimelineViewType {
......@@ -19,8 +26,8 @@ private enum class DmTimelineViewType {
class DMTimelineAdapter(
private val postOptionsListener: PostOptionsListener,
videoPlayer: ExoPlayer
) : BaseTimelineAdapter<PostListItemViewHolder>(videoPlayer) {
private val videoPlayer: ExoPlayer
) : BaseTimelineAdapter() {
override fun getItemViewType(position: Int): Int = when (val item = getItem(position)) {
......@@ -44,29 +51,24 @@ class DMTimelineAdapter(
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostListItemViewHolder {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TimelineListItemViewHolder {
return when (DmTimelineViewType.entries[viewType]) {
DmTimelineViewType.MY_TEXT -> DmMyTextMessageViewHolder(parent)
DmTimelineViewType.OTHER_TEXT -> DmOtherTextMessageViewHolder(parent)
DmTimelineViewType.MY_IMAGE -> DmMyImageMessageViewHolder(parent)
DmTimelineViewType.OTHER_IMAGE -> DmOtherImageMessageViewHolder(parent)
DmTimelineViewType.MY_VIDEO -> DmMyVideoMessageViewHolder(
parent,
videoPlayer,
this
)
// TimelineViewType.TEXT -> TextPostViewHolder(
// parent, postOptionsListener, isThread
// )
//
// TimelineViewType.IMAGE -> ImagePostViewHolder(parent, postOptionsListener, isThread)
//
// TimelineViewType.VIDEO -> VideoPostViewHolder(
// parent,
// postOptionsListener,
// isThread,
// videoPlayer,
// this
// )
DmTimelineViewType.OTHER_VIDEO -> DmOtherVideoMessageViewHolder(
parent,
videoPlayer,
this
)
DmTimelineViewType.MY_TEXT -> TODO()
DmTimelineViewType.OTHER_TEXT -> TODO()
DmTimelineViewType.MY_IMAGE -> TODO()
DmTimelineViewType.OTHER_IMAGE -> TODO()
DmTimelineViewType.MY_VIDEO -> TODO()
DmTimelineViewType.OTHER_VIDEO -> TODO()
DmTimelineViewType.OTHER -> OtherEventPostViewHolder(parent, postOptionsListener)
DmTimelineViewType.LOADING -> TimelineLoadingViewHolder(parent)
}
......
package org.futo.circles.feature.direct.timeline.list
class DMTimelineViewHolder {
}
\ No newline at end of file
package org.futo.circles.feature.direct.timeline.list.holder
import android.text.format.DateFormat
import android.view.ViewGroup
import org.futo.circles.core.base.list.ViewBindingHolder
import org.futo.circles.core.model.MediaContent
import org.futo.circles.core.model.Post
import org.futo.circles.core.model.PostListItem
import org.futo.circles.databinding.ListItemMyImageDmBinding
import org.futo.circles.feature.timeline.base.TimelineListItemViewHolder
import org.futo.circles.feature.timeline.list.holder.ImageMediaViewHolder
import java.util.Date
class DmMyImageMessageViewHolder(parent: ViewGroup) : TimelineListItemViewHolder(
inflate(parent, ListItemMyImageDmBinding::inflate)
), ImageMediaViewHolder {
private companion object : ViewBindingHolder
private val binding = baseBinding as ListItemMyImageDmBinding
override fun bind(item: PostListItem) {
val post = (item as? Post) ?: return
val content = post.content as? MediaContent ?: return
bindMediaCover(content, binding.ivMediaContent)
binding.tvTime.text =
DateFormat.format("MMM dd, h:mm a", Date(post.postInfo.getLastModifiedTimestamp()))
}
}
\ No newline at end of file
package org.futo.circles.feature.direct.timeline.list.holder
import android.text.format.DateFormat
import android.view.ViewGroup
import android.widget.TextView
import org.futo.circles.core.base.list.ViewBindingHolder
import org.futo.circles.core.model.Post
import org.futo.circles.core.model.PostListItem
import org.futo.circles.core.model.TextContent
import org.futo.circles.databinding.ListItemMyTextDmBinding
import org.futo.circles.feature.timeline.base.TimelineListItemViewHolder
import java.util.Date
class DmMyTextMessageViewHolder(parent: ViewGroup) : TimelineListItemViewHolder(
inflate(parent, ListItemMyTextDmBinding::inflate)
) {
private companion object : ViewBindingHolder
private val binding = baseBinding as ListItemMyTextDmBinding
override fun bind(item: PostListItem) {
val post = (item as? Post) ?: return
val content = post.content as? TextContent ?: return
binding.tvMessage.setText(content.messageSpanned, TextView.BufferType.SPANNABLE)
binding.tvTime.text = DateFormat.format("MMM dd, h:mm a", Date(post.postInfo.getLastModifiedTimestamp()))
}
}
\ No newline at end of file
package org.futo.circles.feature.direct.timeline.list.holder
import android.text.format.DateFormat
import android.view.ViewGroup
import androidx.media3.exoplayer.ExoPlayer
import org.futo.circles.core.base.list.ViewBindingHolder
import org.futo.circles.core.model.MediaContent
import org.futo.circles.core.model.Post
import org.futo.circles.core.model.PostListItem
import org.futo.circles.databinding.LayoutPostVideoPlaybackBinding
import org.futo.circles.databinding.ListItemMyVideoDmBinding
import org.futo.circles.feature.timeline.base.TimelineListItemViewHolder
import org.futo.circles.feature.timeline.list.OnVideoPlayBackStateListener
import org.futo.circles.feature.timeline.list.holder.VideoPlaybackViewHolder
import java.util.Date
class DmMyVideoMessageViewHolder(
parent: ViewGroup,
override val videoPlayer: ExoPlayer,
override val videoPlaybackListener: OnVideoPlayBackStateListener
) : TimelineListItemViewHolder(inflate(parent, ListItemMyVideoDmBinding::inflate)),
VideoPlaybackViewHolder {
private companion object : ViewBindingHolder
private val binding = baseBinding as ListItemMyVideoDmBinding
override val videoPlaybackLayout: LayoutPostVideoPlaybackBinding
get() = binding.videoPlaybackLayout
override fun bind(item: PostListItem) {
val post = (item as? Post) ?: return
val content = post.content as? MediaContent ?: return
with(binding) {
bindMediaCover(content, videoPlaybackLayout.ivMediaContent)
bindVideoView(content)
videoPlaybackLayout.tvDuration.text = content.mediaFileData.duration
tvTime.text =
DateFormat.format("MMM dd, h:mm a", Date(post.postInfo.getLastModifiedTimestamp()))
}
}
}
\ No newline at end of file
package org.futo.circles.feature.direct.timeline.list.holder
import android.text.format.DateFormat
import android.view.ViewGroup
import org.futo.circles.core.base.list.ViewBindingHolder
import org.futo.circles.core.model.MediaContent
import org.futo.circles.core.model.Post
import org.futo.circles.core.model.PostListItem
import org.futo.circles.databinding.ListItemOtherImageDmBinding
import org.futo.circles.feature.timeline.base.TimelineListItemViewHolder
import org.futo.circles.feature.timeline.list.holder.ImageMediaViewHolder
import java.util.Date
class DmOtherImageMessageViewHolder(parent: ViewGroup) : TimelineListItemViewHolder(
inflate(parent, ListItemOtherImageDmBinding::inflate)
), ImageMediaViewHolder {
private companion object : ViewBindingHolder
private val binding = baseBinding as ListItemOtherImageDmBinding
override fun bind(item: PostListItem) {
val post = (item as? Post) ?: return
val content = post.content as? MediaContent ?: return
bindMediaCover(content, binding.ivMediaContent)
binding.tvTime.text =
DateFormat.format("MMM dd, h:mm a", Date(post.postInfo.getLastModifiedTimestamp()))
}
}
\ No newline at end of file
package org.futo.circles.feature.direct.timeline.list.holder
import android.text.format.DateFormat
import android.view.ViewGroup
import android.widget.TextView
import org.futo.circles.core.base.list.ViewBindingHolder
import org.futo.circles.core.model.Post
import org.futo.circles.core.model.PostListItem
import org.futo.circles.core.model.TextContent
import org.futo.circles.databinding.ListItemOtherTextDmBinding
import org.futo.circles.feature.timeline.base.TimelineListItemViewHolder
import java.util.Date
class DmOtherTextMessageViewHolder(parent: ViewGroup) : TimelineListItemViewHolder(
inflate(parent, ListItemOtherTextDmBinding::inflate)
) {
private companion object : ViewBindingHolder
private val binding = baseBinding as ListItemOtherTextDmBinding
override fun bind(item: PostListItem) {
val post = (item as? Post) ?: return
val content = post.content as? TextContent ?: return
binding.tvMessage.setText(content.messageSpanned, TextView.BufferType.SPANNABLE)
binding.tvTime.text =
DateFormat.format("MMM dd, h:mm a", Date(post.postInfo.getLastModifiedTimestamp()))
}
}
\ No newline at end of file
package org.futo.circles.feature.direct.timeline.list.holder
import android.text.format.DateFormat
import android.view.ViewGroup
import androidx.media3.exoplayer.ExoPlayer
import org.futo.circles.core.base.list.ViewBindingHolder
import org.futo.circles.core.model.MediaContent
import org.futo.circles.core.model.Post
import org.futo.circles.core.model.PostListItem
import org.futo.circles.databinding.LayoutPostVideoPlaybackBinding
import org.futo.circles.databinding.ListItemOtherVideoDmBinding
import org.futo.circles.feature.timeline.base.TimelineListItemViewHolder
import org.futo.circles.feature.timeline.list.OnVideoPlayBackStateListener
import org.futo.circles.feature.timeline.list.holder.VideoPlaybackViewHolder
import java.util.Date
class DmOtherVideoMessageViewHolder(
parent: ViewGroup,
override val videoPlayer: ExoPlayer,
override val videoPlaybackListener: OnVideoPlayBackStateListener
) : TimelineListItemViewHolder(inflate(parent, ListItemOtherVideoDmBinding::inflate)),
VideoPlaybackViewHolder {
private companion object : ViewBindingHolder
private val binding = baseBinding as ListItemOtherVideoDmBinding
override val videoPlaybackLayout: LayoutPostVideoPlaybackBinding
get() = binding.videoPlaybackLayout
override fun bind(item: PostListItem) {
val post = (item as? Post) ?: return
val content = post.content as? MediaContent ?: return
with(binding) {
bindMediaCover(content, videoPlaybackLayout.ivMediaContent)
bindVideoView(content)
videoPlaybackLayout.tvDuration.text = content.mediaFileData.duration
tvTime.text =
DateFormat.format("MMM dd, h:mm a", Date(post.postInfo.getLastModifiedTimestamp()))
}
}
}
\ No newline at end of file
package org.futo.circles.feature.direct.timeline.list
package org.futo.circles.feature.timeline.base
import androidx.media3.exoplayer.ExoPlayer
import androidx.recyclerview.widget.RecyclerView
import org.futo.circles.core.base.list.BaseRvAdapter
import org.futo.circles.core.model.Post
import org.futo.circles.core.model.PostListItem
import org.futo.circles.feature.timeline.list.OnVideoPlayBackStateListener
import org.futo.circles.feature.timeline.list.holder.PostViewHolder
import org.futo.circles.feature.timeline.list.holder.VideoPostViewHolder
import org.futo.circles.feature.timeline.list.holder.VideoPlaybackViewHolder
import org.futo.circles.model.PostItemPayload
abstract class BaseTimelineAdapter<VH : RecyclerView.ViewHolder>(
private val videoPlayer: ExoPlayer
) : BaseRvAdapter<PostListItem, VH>(
abstract class BaseTimelineAdapter : BaseRvAdapter<PostListItem, TimelineListItemViewHolder>(
PayloadIdEntityCallback { old, new ->
if (new is Post && old is Post)
PostItemPayload(
......@@ -24,16 +20,16 @@ abstract class BaseTimelineAdapter<VH : RecyclerView.ViewHolder>(
else null
}), OnVideoPlayBackStateListener {
private var currentPlayingVideoHolder: VideoPostViewHolder? = null
private var currentPlayingVideoHolder: VideoPlaybackViewHolder? = null
override fun getItemId(position: Int): Long = getItem(position).id.hashCode().toLong()
override fun onBindViewHolder(holder: VH, position: Int) {
override fun onBindViewHolder(holder: TimelineListItemViewHolder, position: Int) {
holder.bind(getItem(position))
}
override fun onBindViewHolder(
holder: VH,
holder: TimelineListItemViewHolder,
position: Int,
payloads: MutableList<Any>
) {
......@@ -53,12 +49,12 @@ abstract class BaseTimelineAdapter<VH : RecyclerView.ViewHolder>(
}
}
override fun onViewDetachedFromWindow(holder: VH) {
override fun onViewDetachedFromWindow(holder: TimelineListItemViewHolder) {
super.onViewDetachedFromWindow(holder)
if (holder == currentPlayingVideoHolder) stopVideoPlayback()
}
override fun onVideoPlaybackStateChanged(holder: VideoPostViewHolder, isPlaying: Boolean) {
override fun onVideoPlaybackStateChanged(holder: VideoPlaybackViewHolder, isPlaying: Boolean) {
currentPlayingVideoHolder = if (isPlaying) {
stopVideoPlayback(false)
holder
......
package org.futo.circles.feature.timeline.list.holder
package org.futo.circles.feature.timeline.base
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import org.futo.circles.core.model.PostListItem
abstract class PostListItemViewHolder(view: View) : RecyclerView.ViewHolder(view) {
abstract class TimelineListItemViewHolder(view: View) : RecyclerView.ViewHolder(view) {
abstract fun bind(item: PostListItem)
......
package org.futo.circles.feature.timeline.list
import org.futo.circles.feature.timeline.list.holder.VideoPostViewHolder
import org.futo.circles.feature.timeline.list.holder.VideoPlaybackViewHolder
interface OnVideoPlayBackStateListener {
fun onVideoPlaybackStateChanged(holder: VideoPostViewHolder, isPlaying: Boolean)
fun onVideoPlaybackStateChanged(holder: VideoPlaybackViewHolder, isPlaying: Boolean)
}
\ No newline at end of file
......@@ -5,11 +5,11 @@ import androidx.media3.exoplayer.ExoPlayer
import org.futo.circles.core.model.Post
import org.futo.circles.core.model.PostContentType
import org.futo.circles.core.model.TimelineLoadingItem
import org.futo.circles.feature.direct.timeline.list.BaseTimelineAdapter
import org.futo.circles.feature.timeline.base.BaseTimelineAdapter
import org.futo.circles.feature.timeline.base.TimelineListItemViewHolder
import org.futo.circles.feature.timeline.list.holder.ImagePostViewHolder
import org.futo.circles.feature.timeline.list.holder.OtherEventPostViewHolder
import org.futo.circles.feature.timeline.list.holder.PollPostViewHolder
import org.futo.circles.feature.timeline.list.holder.PostListItemViewHolder
import org.futo.circles.feature.timeline.list.holder.TextPostViewHolder
import org.futo.circles.feature.timeline.list.holder.TimelineLoadingViewHolder
import org.futo.circles.feature.timeline.list.holder.VideoPostViewHolder
......@@ -20,7 +20,7 @@ class TimelineAdapter(
private val postOptionsListener: PostOptionsListener,
private val isThread: Boolean,
private val videoPlayer: ExoPlayer
) : BaseTimelineAdapter<PostListItemViewHolder>(videoPlayer) {
) : BaseTimelineAdapter() {
override fun getItemViewType(position: Int): Int = when (val item = getItem(position)) {
......@@ -35,7 +35,7 @@ class TimelineAdapter(
is TimelineLoadingItem -> TimelineViewType.LOADING.ordinal
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostListItemViewHolder {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TimelineListItemViewHolder {
return when (TimelineViewType.entries[viewType]) {
TimelineViewType.TEXT -> TextPostViewHolder(
......
......@@ -7,7 +7,7 @@ import org.futo.circles.core.extensions.loadEncryptedThumbOrFullIntoWithAspect
import org.futo.circles.core.extensions.setIsVisible
import org.futo.circles.core.model.MediaContent
interface MediaViewHolder {
interface ImageMediaViewHolder {
fun bindMediaCaption(content: MediaContent, textView: TextView) {
textView.apply {
......
......@@ -16,7 +16,7 @@ class ImagePostViewHolder(
postOptionsListener: PostOptionsListener,
isThread: Boolean
) : PostViewHolder(inflate(parent, ViewImagePostBinding::inflate), postOptionsListener, isThread),
MediaViewHolder {
ImageMediaViewHolder {
private companion object : ViewBindingHolder
......
......@@ -19,6 +19,7 @@ import org.futo.circles.core.model.PostContent
import org.futo.circles.core.model.PostListItem
import org.futo.circles.core.model.TextContent
import org.futo.circles.feature.timeline.InternalLinkMovementMethod
import org.futo.circles.feature.timeline.base.TimelineListItemViewHolder
import org.futo.circles.feature.timeline.list.OnLinkClickedListener
import org.futo.circles.feature.timeline.list.PostOptionsListener
import org.futo.circles.model.PostItemPayload
......@@ -34,7 +35,7 @@ abstract class PostViewHolder(
view: View,
protected val optionsListener: PostOptionsListener,
private val isThread: Boolean
) : PostListItemViewHolder(view) {
) : TimelineListItemViewHolder(view) {
abstract val postLayout: ViewGroup?
abstract val postFooter: PostFooterView?
......
......@@ -5,10 +5,11 @@ import org.futo.circles.core.base.list.ViewBindingHolder
import org.futo.circles.core.databinding.ListItemTimelineLoadingBinding
import org.futo.circles.core.model.PostListItem
import org.futo.circles.core.model.TimelineLoadingItem
import org.futo.circles.feature.timeline.base.TimelineListItemViewHolder
class TimelineLoadingViewHolder(
parent: ViewGroup,
) : PostListItemViewHolder(inflate(parent, ListItemTimelineLoadingBinding::inflate)) {
) : TimelineListItemViewHolder(inflate(parent, ListItemTimelineLoadingBinding::inflate)) {
private companion object : ViewBindingHolder
......
package org.futo.circles.feature.timeline.list.holder
import android.net.Uri
import androidx.core.view.updateLayoutParams
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer
import org.futo.circles.R
import org.futo.circles.core.extensions.gone
import org.futo.circles.core.extensions.invisible
import org.futo.circles.core.extensions.visible
import org.futo.circles.core.model.MediaContent
import org.futo.circles.core.model.ResLoadingData
import org.futo.circles.databinding.LayoutPostVideoPlaybackBinding
import org.futo.circles.feature.timeline.list.OnVideoPlayBackStateListener
interface VideoPlaybackViewHolder : ImageMediaViewHolder {
val videoPlaybackLayout: LayoutPostVideoPlaybackBinding
val videoPlayer: ExoPlayer
val videoPlaybackListener: OnVideoPlayBackStateListener
fun bindVideoView(content: MediaContent) {
with(videoPlaybackLayout.videoView) {
player = null
post {
val size = content.calculateThumbnailSize(width)
updateLayoutParams {
width = size.width
height = size.height
}
}
}
}
fun playVideo(uri: Uri?) {
uri?.let {
with(videoPlaybackLayout) {
tvDuration.gone()
videoView.visible()
ivVideoIndicator.gone()
ivMediaContent.gone()
}
videoPlaybackListener.onVideoPlaybackStateChanged(this, true)
videoPlaybackLayout.videoView.player = videoPlayer
videoPlayer.setMediaItem(MediaItem.fromUri(it))
videoPlayer.prepare()
videoPlayer.play()
} ?: run {
videoPlaybackLayout.vLoadingView.apply {
visible()
setProgress(ResLoadingData(R.string.downloading))
}
}
}
fun stopVideo(shouldNotify: Boolean = true) {
if (shouldNotify) videoPlaybackListener.onVideoPlaybackStateChanged(this, false)
videoPlayer.stop()
with(videoPlaybackLayout) {
videoView.player = null
tvDuration.visible()
ivVideoIndicator.visible()
ivMediaContent.visible()
videoView.invisible()
}
}
}
\ No newline at end of file
package org.futo.circles.feature.timeline.list.holder
import android.view.ViewGroup
import androidx.core.view.updateLayoutParams
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer
import org.futo.circles.R
import org.futo.circles.core.base.list.ViewBindingHolder
import org.futo.circles.core.extensions.gone
import org.futo.circles.core.extensions.invisible
import org.futo.circles.core.extensions.visible
import org.futo.circles.core.model.ResLoadingData
import org.futo.circles.core.model.MediaContent
import org.futo.circles.core.model.Post
import org.futo.circles.databinding.LayoutPostVideoPlaybackBinding
import org.futo.circles.databinding.ViewVideoPostBinding
import org.futo.circles.feature.timeline.list.OnVideoPlayBackStateListener
import org.futo.circles.feature.timeline.list.PostOptionsListener
......@@ -24,10 +18,10 @@ class VideoPostViewHolder(
parent: ViewGroup,
postOptionsListener: PostOptionsListener,
isThread: Boolean,
private val videoPlayer: ExoPlayer,
private val videoPlaybackListener: OnVideoPlayBackStateListener
override val videoPlayer: ExoPlayer,
override val videoPlaybackListener: OnVideoPlayBackStateListener
) : PostViewHolder(inflate(parent, ViewVideoPostBinding::inflate), postOptionsListener, isThread),
MediaViewHolder {
VideoPlaybackViewHolder {
private companion object : ViewBindingHolder
......@@ -42,77 +36,36 @@ class VideoPostViewHolder(
get() = binding.vPostStatus
override val readMoreTextView: ReadMoreTextView
get() = binding.tvTextContent
override val videoPlaybackLayout: LayoutPostVideoPlaybackBinding
get() = binding.videoPlaybackLayout
init {
setListeners()
binding.ivFullScreen.setOnClickListener {
binding.videoPlaybackLayout.ivFullScreen.setOnClickListener {
post?.let { optionsListener.onShowPreview(it.postInfo.roomId, it.id) }
}
binding.ivMediaContent.apply {
setOnClickListener { playVideo() }
binding.videoPlaybackLayout.ivMediaContent.apply {
setOnClickListener {
val uri = (post?.content as? MediaContent)?.mediaFileData?.videoUri
playVideo(uri)
}
setOnLongClickListener {
postHeader.showMenu()
true
}
}
binding.videoView.setOnClickListener { stopVideo() }
binding.videoPlaybackLayout.videoView.setOnClickListener { stopVideo() }
}
override fun bindHolderSpecific(post: Post) {
with(binding) {
val content = (post.content as? MediaContent) ?: return
bindMediaCaption(content, tvTextContent)
bindMediaCover(content, ivMediaContent)
bindMediaCover(content, videoPlaybackLayout.ivMediaContent)
bindVideoView(content)
tvDuration.text = content.mediaFileData.duration
}
}
private fun bindVideoView(content: MediaContent) {
with(binding) {
videoView.player = null
videoView.post {
val size = content.calculateThumbnailSize(videoView.width)
videoView.updateLayoutParams {
width = size.width
height = size.height
}
}
}
}
private fun playVideo() {
val uri = (post?.content as? MediaContent)?.mediaFileData?.videoUri
uri?.let {
with(binding) {
tvDuration.gone()
videoView.visible()
ivVideoIndicator.gone()
ivMediaContent.gone()
}
videoPlaybackListener.onVideoPlaybackStateChanged(this, true)
binding.videoView.player = videoPlayer
videoPlayer.setMediaItem(MediaItem.fromUri(it))
videoPlayer.prepare()
videoPlayer.play()
} ?: run {
binding.vLoadingView.apply {
visible()
setProgress(ResLoadingData(R.string.downloading))
}
}
}
fun stopVideo(shouldNotify: Boolean = true) {
if (shouldNotify) videoPlaybackListener.onVideoPlaybackStateChanged(this, false)
videoPlayer.stop()
with(binding) {
videoView.player = null
tvDuration.visible()
ivVideoIndicator.visible()
ivMediaContent.visible()
videoView.invisible()
videoPlaybackLayout.tvDuration.text = content.mediaFileData.duration
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<merge 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:layout_width="match_parent"
android:layout_height="wrap_content"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
<androidx.media3.ui.PlayerView
android:id="@+id/videoView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/media_post_background"
android:foreground="?attr/selectableItemBackground"
android:scaleType="fitCenter"
android:soundEffectsEnabled="true"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:resize_mode="fit"
app:shutter_background_color="@android:color/transparent"
app:surface_type="texture_view"
app:use_controller="false"
tools:minHeight="400dp"
tools:visibility="visible" />
<ImageView
android:id="@+id/ivMediaContent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="@color/media_post_background"
android:foreground="?attr/selectableItemBackground"
android:scaleType="fitCenter"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/ivVideoIndicator"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center"
android:background="@color/white"
android:src="@drawable/ic_play_round"
app:layout_constraintBottom_toBottomOf="@id/videoView"
app:layout_constraintDimensionRatio="w,1:1"
app:layout_constraintEnd_toEndOf="@id/videoView"
app:layout_constraintStart_toStartOf="@id/videoView"
app:layout_constraintTop_toTopOf="@id/videoView"
app:layout_constraintWidth_percent="0.15"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent"
app:tint="@color/blue" />
<TextView
android:id="@+id/tvDuration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="4dp"
android:shadowColor="@color/black"
android:shadowDx="1"
android:shadowDy="1"
android:shadowRadius="2"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="@+id/videoView"
app:layout_constraintStart_toStartOf="@id/videoView"
tools:text="00:00" />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/ivFullScreen"
android:layout_width="45dp"
android:layout_height="45dp"
android:background="@color/background_dim"
android:clickable="true"
android:focusable="true"
android:foreground="?selectableItemBackgroundBorderless"
android:padding="8dp"
android:src="@drawable/ic_fullscreen"
app:contentPadding="2dp"
app:layout_constraintBottom_toBottomOf="@+id/videoView"
app:layout_constraintEnd_toEndOf="@id/videoView"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize50Percent"
app:tint="@color/white" />
<org.futo.circles.core.view.LoadingView
android:id="@+id/vLoadingView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginHorizontal="16dp"
android:background="@color/white"
android:padding="16dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/videoView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/videoView"
tools:visibility="visible" />
</merge>
\ No newline at end of file
<?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:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="36dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/ivBackground"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/chip_selected_color"
app:layout_constraintBottom_toBottomOf="@id/tvTime"
app:layout_constraintEnd_toEndOf="@id/ivMediaContent"
app:layout_constraintStart_toStartOf="@id/ivMediaContent"
app:layout_constraintTop_toTopOf="@id/ivMediaContent"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.Message.My" />
<ImageView
android:id="@+id/ivMediaContent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/media_post_background"
android:foreground="?attr/selectableItemBackground"
android:padding="8dp"
android:scaleType="fitCenter"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvTime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:paddingBottom="4dp"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/ivMediaContent"
tools:text="sadasdasdasdasdasdasdasdasdasd" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file