TP-76171 | Video view renderer in UiTron (#527)
Co-authored-by: soumya-ranjan_navi <soumya.ranjan@navi.com> Co-authored-by: Shivam Goyal <shivam.goyal@navi.com>
This commit is contained in:
@@ -13,6 +13,9 @@ import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.text.font.Font
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.media3.database.StandaloneDatabaseProvider
|
||||
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
|
||||
import androidx.media3.datasource.cache.SimpleCache
|
||||
import com.navi.alfred.AlfredManager
|
||||
import com.navi.uitron.IUiTronDependencyProvider
|
||||
import com.navi.uitron.model.UiTronConfig
|
||||
@@ -20,8 +23,19 @@ import com.navi.uitron.model.ui.OutlinedTextFieldValueTransformation
|
||||
import com.navi.uitron.model.ui.UiTronShape
|
||||
import com.navi.uitron.utils.EMPTY
|
||||
import com.navi.uitron.utils.SPACE
|
||||
import java.io.File
|
||||
|
||||
class UiTronDependencyProvider : IUiTronDependencyProvider {
|
||||
|
||||
private val media3SimpleCache by lazy {
|
||||
val downloadContentDirectory = File(getContext().getExternalFilesDir(null), "downloads")
|
||||
SimpleCache(
|
||||
downloadContentDirectory,
|
||||
LeastRecentlyUsedCacheEvictor(100_000_000),
|
||||
StandaloneDatabaseProvider(getContext())
|
||||
)
|
||||
}
|
||||
|
||||
private val ttFontFamily =
|
||||
FontFamily(
|
||||
Font(
|
||||
@@ -218,6 +232,10 @@ class UiTronDependencyProvider : IUiTronDependencyProvider {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getMedia3SimpleCache(): SimpleCache {
|
||||
return media3SimpleCache
|
||||
}
|
||||
|
||||
override fun maskSensitiveUiTronComposable(
|
||||
id: String,
|
||||
left: Float?,
|
||||
|
||||
@@ -1,5 +1,37 @@
|
||||
{
|
||||
"movingBoxes":{
|
||||
"videoMock": {
|
||||
"data": {
|
||||
"productIcon": {
|
||||
"videoUrl": "https://public-assets.prod.navi-sa.in/shivam/video-view/coverr-close-up-of-unboxing-iphone-15-1080p.mp4",
|
||||
"viewType": "Video"
|
||||
}
|
||||
},
|
||||
"view": [
|
||||
{
|
||||
"property": {
|
||||
"width": "MATCH_PARENT",
|
||||
"height": "MATCH_PARENT",
|
||||
"layoutId": "productIcon",
|
||||
"viewType": "Video",
|
||||
"placeHolderView": {
|
||||
"data": {},
|
||||
"view": [
|
||||
{
|
||||
"property": {
|
||||
"width": "MATCH_PARENT",
|
||||
"height": "MATCH_PARENT",
|
||||
"layoutId": "placeHolderView",
|
||||
"viewType": "Box",
|
||||
"backgroundColor": "#000000"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"movingBoxes": {
|
||||
"view": [
|
||||
{
|
||||
"property": {
|
||||
@@ -1504,7 +1536,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"spannableV2": {
|
||||
"spannableV2": {
|
||||
"view": [
|
||||
{
|
||||
"property": {
|
||||
@@ -4635,7 +4667,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"cardShadowTemplate":{
|
||||
"cardShadowTemplate": {
|
||||
"parentComposeView": [
|
||||
{
|
||||
"property": {
|
||||
@@ -4659,7 +4691,6 @@
|
||||
},
|
||||
"repeatMode": "Repeat"
|
||||
},
|
||||
|
||||
"targetColor": "#011627"
|
||||
}
|
||||
],
|
||||
@@ -10981,7 +11012,6 @@
|
||||
"width": "MATCH_PARENT",
|
||||
"height": "WRAP_CONTENT",
|
||||
"layoutId": "parent_container",
|
||||
|
||||
"borderStrokeData": {
|
||||
"brushData": {
|
||||
"brushType": "LINEAR",
|
||||
@@ -18245,7 +18275,7 @@
|
||||
],
|
||||
"data": {
|
||||
"simple_text": {
|
||||
"text":"NAVI",
|
||||
"text": "NAVI",
|
||||
"viewType": "Text"
|
||||
},
|
||||
"click_me_trigger": {
|
||||
|
||||
@@ -9,6 +9,7 @@ androidx-constraintlayoutCompose = "1.1.0-alpha10"
|
||||
androidx-core-ktx = "1.8.0"
|
||||
androidx-hilt = "1.0.0"
|
||||
androidx-lifecycle = "2.6.1"
|
||||
androidx-media3 = "1.4.1"
|
||||
androidx-pagingCompose = "3.2.0"
|
||||
androidx-pagingRuntimeKtx = "3.1.1"
|
||||
androidx-profileinstaller = "1.3.1"
|
||||
@@ -65,6 +66,9 @@ androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-ru
|
||||
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecycle" }
|
||||
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidx-lifecycle" }
|
||||
|
||||
androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "androidx-media3" }
|
||||
androidx-media3-ui = { module = "androidx.media3:media3-ui", version.ref = "androidx-media3" }
|
||||
|
||||
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigation-compose" }
|
||||
|
||||
androidx-paging-compose = { module = "androidx.paging:paging-compose", version.ref = "androidx-pagingCompose" }
|
||||
|
||||
6
lint.xml
Normal file
6
lint.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<lint>
|
||||
<issue id="UnsafeOptInUsageError">
|
||||
<option name="opt-in" value="androidx.media3.common.util.UnstableApi" />
|
||||
</issue>
|
||||
</lint>
|
||||
@@ -84,6 +84,12 @@ publishing {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.androidx.media3.exoplayer) {
|
||||
exclude group: "com.google.guava", module: "guava"
|
||||
}
|
||||
api(libs.androidx.media3.ui) {
|
||||
exclude group: "com.google.guava", module: "guava"
|
||||
}
|
||||
api libs.coil.compose
|
||||
|
||||
implementation platform(libs.androidx.compose.bom)
|
||||
|
||||
@@ -12,6 +12,7 @@ import android.view.View
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.media3.datasource.cache.SimpleCache
|
||||
import com.navi.uitron.model.UiTronConfig
|
||||
import com.navi.uitron.model.ui.OutlinedTextFieldValueTransformation
|
||||
import com.navi.uitron.model.ui.UiTronShape
|
||||
@@ -60,4 +61,6 @@ interface IUiTronDependencyProvider {
|
||||
fun getUiTronConfig(): UiTronConfig
|
||||
|
||||
fun getShape(shape: UiTronShape?): Shape?
|
||||
|
||||
fun getMedia3SimpleCache(): SimpleCache
|
||||
}
|
||||
|
||||
@@ -162,6 +162,9 @@ open class ComposePropertyDeserializer : JsonDeserializer<BaseProperty> {
|
||||
LinearProgressIndicatorWithThumbProperty::class.java
|
||||
)
|
||||
}
|
||||
ComposeViewType.Video.name -> {
|
||||
context?.deserialize(jsonObject, VideoProperty::class.java)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.navi.uitron.model.data.TextData
|
||||
import com.navi.uitron.model.data.ToastData
|
||||
import com.navi.uitron.model.data.UiTronData
|
||||
import com.navi.uitron.model.data.UiTronSliderData
|
||||
import com.navi.uitron.model.data.VideoData
|
||||
import com.navi.uitron.model.ui.ComposeViewType
|
||||
import java.lang.reflect.Type
|
||||
|
||||
@@ -162,6 +163,9 @@ open class UiTronDataDeserializer : JsonDeserializer<UiTronData> {
|
||||
LinearProgressIndicatorWithThumbData::class.java
|
||||
)
|
||||
}
|
||||
ComposeViewType.Video.name -> {
|
||||
context?.deserialize(jsonObject, VideoData::class.java)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.uitron.model.data
|
||||
|
||||
data class VideoData(
|
||||
val videoUrl: String? = null,
|
||||
) : UiTronData()
|
||||
@@ -37,6 +37,7 @@ import com.navi.uitron.model.data.TextData
|
||||
import com.navi.uitron.model.data.ToastData
|
||||
import com.navi.uitron.model.data.UiTronData
|
||||
import com.navi.uitron.model.data.UiTronSliderData
|
||||
import com.navi.uitron.model.data.VideoData
|
||||
import com.navi.uitron.model.ui.ComposeViewType
|
||||
|
||||
class UiTronDataProviderFactory {
|
||||
@@ -73,6 +74,7 @@ class UiTronDataProviderFactory {
|
||||
ComposeViewType.RadioGroup.name -> RadioGroupData()
|
||||
ComposeViewType.LinearProgressIndicatorWithThumb.name ->
|
||||
LinearProgressIndicatorWithThumbData()
|
||||
ComposeViewType.Video.name -> VideoData()
|
||||
else -> EmptyData()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,7 +261,8 @@ enum class ComposeViewType {
|
||||
FloatingActionButton,
|
||||
ToolTipPopUp,
|
||||
RadioGroup,
|
||||
LinearProgressIndicatorWithThumb
|
||||
LinearProgressIndicatorWithThumb,
|
||||
Video
|
||||
}
|
||||
|
||||
val containerRenderers =
|
||||
@@ -314,7 +315,8 @@ val elementRenderers =
|
||||
ComposeViewType.CustomTextField.name,
|
||||
ComposeViewType.OtpBox.name,
|
||||
ComposeViewType.SlideToActButton.name,
|
||||
ComposeViewType.LinearProgressIndicatorWithThumb.name
|
||||
ComposeViewType.LinearProgressIndicatorWithThumb.name,
|
||||
ComposeViewType.Video.name
|
||||
)
|
||||
|
||||
enum class HorizontalArrangementType {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.uitron.model.ui
|
||||
|
||||
import com.navi.uitron.model.UiTronResponse
|
||||
|
||||
data class VideoProperty(
|
||||
var placeHolderView: UiTronResponse? = null,
|
||||
) : BaseProperty() {
|
||||
|
||||
override fun copyNonNullFrom(property: BaseProperty?) {
|
||||
super.copyNonNullFrom(property)
|
||||
val videoProperty = property as? VideoProperty
|
||||
videoProperty?.placeHolderView?.let { placeHolderView = it }
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import com.navi.uitron.provider.element.SpacerViewRenderer
|
||||
import com.navi.uitron.provider.element.SpannableTextViewRenderer
|
||||
import com.navi.uitron.provider.element.SwitchViewRenderer
|
||||
import com.navi.uitron.provider.element.TextViewRenderer
|
||||
import com.navi.uitron.provider.element.VideoViewRenderer
|
||||
|
||||
class ElementRendererProviderImpl : IUiTronRendererProvider {
|
||||
|
||||
@@ -61,6 +62,7 @@ class ElementRendererProviderImpl : IUiTronRendererProvider {
|
||||
ComposeViewType.SlideToActButton.name -> SlideToActButtonViewRenderer()
|
||||
ComposeViewType.LinearProgressIndicatorWithThumb.name ->
|
||||
LinearProgressIndicatorWithThumbViewRenderer()
|
||||
ComposeViewType.Video.name -> VideoViewRenderer()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.uitron.provider.element
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.navi.uitron.model.UiTronRenderConfig
|
||||
import com.navi.uitron.model.ui.VideoProperty
|
||||
import com.navi.uitron.provider.IUiTronRenderer
|
||||
import com.navi.uitron.render.VideoRenderer
|
||||
|
||||
class VideoViewRenderer : IUiTronRenderer {
|
||||
|
||||
@Composable
|
||||
override fun RenderUiTronView(uiTronRenderConfig: UiTronRenderConfig) {
|
||||
(uiTronRenderConfig.composeView.property as? VideoProperty)?.let {
|
||||
VideoRenderer(uiTronRenderer = uiTronRenderConfig.uiTronRenderer)
|
||||
.Render(
|
||||
property = it,
|
||||
uiTronData =
|
||||
uiTronRenderConfig.dataMap?.getOrElse(it.layoutId.orEmpty()) { null },
|
||||
uiTronViewModel = uiTronRenderConfig.uiTronViewModel,
|
||||
modifier = uiTronRenderConfig.modifier
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.uitron.render
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.Player.STATE_READY
|
||||
import androidx.media3.datasource.DefaultDataSource
|
||||
import androidx.media3.datasource.DefaultHttpDataSource
|
||||
import androidx.media3.datasource.FileDataSource
|
||||
import androidx.media3.datasource.cache.CacheDataSink
|
||||
import androidx.media3.datasource.cache.CacheDataSource
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import androidx.media3.exoplayer.source.MediaSource
|
||||
import androidx.media3.exoplayer.source.ProgressiveMediaSource
|
||||
import androidx.media3.ui.AspectRatioFrameLayout.RESIZE_MODE_ZOOM
|
||||
import androidx.media3.ui.PlayerView
|
||||
import com.navi.uitron.UiTronSdkManager
|
||||
import com.navi.uitron.model.data.UiTronData
|
||||
import com.navi.uitron.model.data.VideoData
|
||||
import com.navi.uitron.model.ui.VideoProperty
|
||||
import com.navi.uitron.utils.clip
|
||||
import com.navi.uitron.utils.customClickable
|
||||
import com.navi.uitron.utils.customCombinedClick
|
||||
import com.navi.uitron.utils.customOffset
|
||||
import com.navi.uitron.utils.orTrue
|
||||
import com.navi.uitron.utils.setBackground
|
||||
import com.navi.uitron.utils.setBlur
|
||||
import com.navi.uitron.utils.setHeight
|
||||
import com.navi.uitron.utils.setHeightRange
|
||||
import com.navi.uitron.utils.setPadding
|
||||
import com.navi.uitron.utils.setTag
|
||||
import com.navi.uitron.utils.setWidth
|
||||
import com.navi.uitron.utils.setWidthRange
|
||||
import com.navi.uitron.viewmodel.UiTronViewModel
|
||||
|
||||
class VideoRenderer(private val uiTronRenderer: UiTronRenderer) : Renderer<VideoProperty> {
|
||||
|
||||
@Composable
|
||||
override fun Render(
|
||||
property: VideoProperty,
|
||||
uiTronData: UiTronData?,
|
||||
uiTronViewModel: UiTronViewModel,
|
||||
modifier: Modifier?
|
||||
) {
|
||||
super.Render(property, uiTronData, uiTronViewModel, modifier)
|
||||
val videoData = uiTronData as? VideoData
|
||||
|
||||
if (property.visible.orTrue()) {
|
||||
val viewModifier =
|
||||
(modifier ?: Modifier)
|
||||
.setTag(property)
|
||||
.layoutId(property.layoutId.orEmpty())
|
||||
.customOffset(property.offset)
|
||||
.setWidth(property.width)
|
||||
.setHeight(property.height)
|
||||
.setWidthRange(property.widthRange)
|
||||
.setHeightRange(property.heightRange)
|
||||
.setPadding(property.margin)
|
||||
.setBackground(
|
||||
property.backgroundColor,
|
||||
property.shape,
|
||||
property.backGroundBrushData
|
||||
)
|
||||
.clip(property.clipShape)
|
||||
.setPadding(property.padding)
|
||||
.customClickable(
|
||||
{ uiTronViewModel.handleActions(uiTronData?.onClick) },
|
||||
actions = uiTronData?.onClick?.actions,
|
||||
property = property
|
||||
)
|
||||
.customCombinedClick(property, uiTronData) { uiTronViewModel.handleActions(it) }
|
||||
.graphicsLayer { alpha = property.alpha ?: 1.0f }
|
||||
.setBlur(property.blurData)
|
||||
|
||||
val localContext = LocalContext.current
|
||||
|
||||
val mediaUrl = remember(videoData?.videoUrl) { videoData?.videoUrl.orEmpty() }
|
||||
|
||||
val placeholderVisibility = remember { mutableStateOf(true) }
|
||||
|
||||
exoPlayer =
|
||||
remember(mediaUrl) {
|
||||
ExoPlayer.Builder(localContext).build().apply {
|
||||
setMediaSource(getProgressiveMediaSource(localContext, mediaUrl))
|
||||
repeatMode = ExoPlayer.REPEAT_MODE_ALL
|
||||
volume = 0f
|
||||
prepare()
|
||||
addListener(
|
||||
object : Player.Listener {
|
||||
override fun onPlaybackStateChanged(playbackState: Int) {
|
||||
super.onPlaybackStateChanged(playbackState)
|
||||
if (playbackState == STATE_READY) {
|
||||
play()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRenderedFirstFrame() {
|
||||
super.onRenderedFirstFrame()
|
||||
if (placeholderVisibility.value) {
|
||||
placeholderVisibility.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val playerView =
|
||||
remember(exoPlayer) {
|
||||
PlayerView(localContext).apply {
|
||||
useController = false
|
||||
player = exoPlayer
|
||||
resizeMode = RESIZE_MODE_ZOOM
|
||||
}
|
||||
}
|
||||
|
||||
Box {
|
||||
AndroidView(modifier = viewModifier, factory = { playerView })
|
||||
if (placeholderVisibility.value) {
|
||||
property.placeHolderView?.let {
|
||||
UiTronRenderer(
|
||||
it.data,
|
||||
uiTronViewModel,
|
||||
uiTronRenderer.customUiTronRenderer,
|
||||
)
|
||||
.Render(
|
||||
composeViews = it.parentComposeView.orEmpty(),
|
||||
modifier = viewModifier
|
||||
)
|
||||
} ?: run { Box(viewModifier.background(Color.White)) }
|
||||
}
|
||||
}
|
||||
|
||||
val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)
|
||||
|
||||
DisposableEffect(lifecycleOwner.value) { onDispose { releasePlayer() } }
|
||||
}
|
||||
}
|
||||
|
||||
private var exoPlayer: ExoPlayer? = null
|
||||
|
||||
private fun releasePlayer() {
|
||||
exoPlayer?.apply {
|
||||
playWhenReady = false
|
||||
release()
|
||||
}
|
||||
exoPlayer = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun getProgressiveMediaSource(context: Context, mediaUrl: String): MediaSource {
|
||||
val downloadCache = UiTronSdkManager.getDependencyProvider().getMedia3SimpleCache()
|
||||
val cacheSink = CacheDataSink.Factory().setCache(downloadCache)
|
||||
val downstreamFactory = FileDataSource.Factory()
|
||||
val upstreamFactory =
|
||||
DefaultDataSource.Factory(context, DefaultHttpDataSource.Factory())
|
||||
|
||||
val dataSourceFactory =
|
||||
CacheDataSource.Factory()
|
||||
.setCache(downloadCache)
|
||||
.setCacheWriteDataSinkFactory(cacheSink)
|
||||
.setCacheReadDataSourceFactory(downstreamFactory)
|
||||
.setUpstreamDataSourceFactory(upstreamFactory)
|
||||
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)
|
||||
|
||||
return ProgressiveMediaSource.Factory(dataSourceFactory)
|
||||
.createMediaSource(MediaItem.fromUri(Uri.parse(mediaUrl)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,6 +177,9 @@ open class ComposePropertySerializer : JsonSerializer<BaseProperty> {
|
||||
LinearProgressIndicatorWithThumbProperty::class.java
|
||||
)
|
||||
}
|
||||
ComposeViewType.Video.name -> {
|
||||
context?.serialize(src as VideoProperty, VideoProperty::class.java)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.navi.uitron.model.data.TextData
|
||||
import com.navi.uitron.model.data.ToastData
|
||||
import com.navi.uitron.model.data.UiTronData
|
||||
import com.navi.uitron.model.data.UiTronSliderData
|
||||
import com.navi.uitron.model.data.VideoData
|
||||
import com.navi.uitron.model.ui.ComposeViewType
|
||||
import java.lang.reflect.Type
|
||||
|
||||
@@ -154,6 +155,9 @@ open class UiTronDataSerializer : JsonSerializer<UiTronData> {
|
||||
LinearProgressIndicatorWithThumbData::class.java
|
||||
)
|
||||
}
|
||||
ComposeViewType.Video.name -> {
|
||||
context?.serialize(src as VideoData, VideoData::class.java)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user