1 package com.airbnb.lottie.samples 2 3 import android.animation.ValueAnimator 4 import android.app.Application 5 import android.net.Uri 6 import androidx.fragment.app.FragmentActivity 7 import com.airbnb.lottie.LottieComposition 8 import com.airbnb.lottie.LottieCompositionFactory 9 import com.airbnb.lottie.LottieTask 10 import com.airbnb.lottie.model.LottieCompositionCache 11 import com.airbnb.lottie.samples.model.CompositionArgs 12 import com.airbnb.mvrx.* 13 import java.io.FileInputStream 14 import java.io.FileNotFoundException 15 16 data class PlayerState( 17 val composition: Async<LottieComposition> = Uninitialized, 18 val controlsVisible: Boolean = true, 19 val controlBarVisible: Boolean = true, 20 val renderGraphVisible: Boolean = false, 21 val borderVisible: Boolean = false, 22 val backgroundColorVisible: Boolean = false, 23 val scaleVisible: Boolean = false, 24 val speedVisible: Boolean = false, 25 val trimVisible: Boolean = false, 26 val useHardwareAcceleration: Boolean = false, 27 val useMergePaths: Boolean = false, 28 val minFrame: Int = 0, 29 val maxFrame: Int = 0, 30 val speed: Float = 1f, 31 val repeatCount: Int = ValueAnimator.INFINITE 32 ) : MvRxState 33 34 class PlayerViewModel( 35 initialState: PlayerState, 36 private val application: Application 37 ) : MvRxViewModel<PlayerState>(initialState) { 38 fetchAnimationnull39 fun fetchAnimation(args: CompositionArgs) { 40 val url = args.url ?: args.animationData?.lottieLink 41 42 when { 43 url != null -> LottieCompositionFactory.fromUrl(application, url, null) 44 args.fileUri != null -> taskForUri(args.fileUri) 45 args.asset != null -> LottieCompositionFactory.fromAsset(application, args.asset, null) 46 else -> throw IllegalArgumentException("Don't know how to fetch animation for $args") 47 } 48 .addListener { 49 setState { 50 copy(composition = Success(it), minFrame = it.startFrame.toInt(), maxFrame = it.endFrame.toInt()) 51 } 52 } 53 .addFailureListener { setState { copy(composition = Fail(it)) } } 54 } 55 taskForUrinull56 private fun taskForUri(uri: Uri): LottieTask<LottieComposition> { 57 val fis = try { 58 when (uri.scheme) { 59 "file" -> FileInputStream(uri.path) 60 "content" -> application.contentResolver.openInputStream(uri) 61 else -> return LottieTask() { throw IllegalArgumentException("Unknown scheme ${uri.scheme}") } 62 } 63 } catch (e: FileNotFoundException) { 64 return LottieTask { throw e } 65 } 66 67 return LottieCompositionFactory.fromJsonInputStream(fis, null) 68 } 69 <lambda>null70 fun toggleRenderGraphVisible() = setState { copy(renderGraphVisible = !renderGraphVisible) } 71 <lambda>null72 fun toggleBorderVisible() = setState { copy(borderVisible = !borderVisible) } 73 <lambda>null74 fun toggleBackgroundColorVisible() = setState { copy(backgroundColorVisible = !backgroundColorVisible) } 75 <lambda>null76 fun setBackgroundColorVisible(visible: Boolean) = setState { copy(backgroundColorVisible = visible) } 77 <lambda>null78 fun toggleScaleVisible() = setState { copy(scaleVisible = !scaleVisible) } 79 <lambda>null80 fun setScaleVisible(visible: Boolean) = setState { copy(scaleVisible = visible) } 81 <lambda>null82 fun toggleSpeedVisible() = setState { copy(speedVisible = !speedVisible) } 83 <lambda>null84 fun setSpeedVisible(visible: Boolean) = setState { copy(speedVisible = visible) } 85 <lambda>null86 fun toggleTrimVisible() = setState { copy(trimVisible = !trimVisible) } 87 <lambda>null88 fun setTrimVisible(visible: Boolean) = setState { copy(trimVisible = visible) } 89 <lambda>null90 fun toggleHardwareAcceleration() = setState { copy(useHardwareAcceleration = !useHardwareAcceleration) } 91 <lambda>null92 fun toggleMergePaths() = setState { copy(useMergePaths = !useMergePaths) } 93 <lambda>null94 fun setMinFrame(minFrame: Int) = setState { 95 copy(minFrame = Math.max(minFrame, composition()?.startFrame?.toInt() ?: 0)) 96 } 97 <lambda>null98 fun setMaxFrame(maxFrame: Int) = setState { 99 copy(maxFrame = Math.min(maxFrame, composition()?.endFrame?.toInt() ?: 0)) 100 } 101 <lambda>null102 fun setSpeed(speed: Float) = setState { copy(speed = speed) } 103 <lambda>null104 fun toggleLoop() = setState { copy(repeatCount = if (repeatCount == ValueAnimator.INFINITE) 0 else ValueAnimator.INFINITE) } 105 <lambda>null106 fun setDistractionFree(distractionFree: Boolean) = setState { 107 copy( 108 controlsVisible = !distractionFree, 109 controlBarVisible = !distractionFree, 110 renderGraphVisible = false, 111 borderVisible = false, 112 backgroundColorVisible = false, 113 scaleVisible = false, 114 speedVisible = false, 115 trimVisible = false 116 ) 117 } 118 119 companion object : MvRxViewModelFactory<PlayerState> { 120 @JvmStatic createnull121 override fun create(activity: FragmentActivity, state: PlayerState) = PlayerViewModel(state, activity.application) 122 } 123 }