| package com.airbnb.lottie.samples |
| |
| import android.animation.ValueAnimator |
| import android.app.Application |
| import android.net.Uri |
| import com.airbnb.lottie.LottieComposition |
| import com.airbnb.lottie.LottieCompositionFactory |
| import com.airbnb.lottie.LottieTask |
| import com.airbnb.lottie.samples.model.CompositionArgs |
| import com.airbnb.lottie.samples.utils.MvRxViewModel |
| import com.airbnb.mvrx.Async |
| import com.airbnb.mvrx.Fail |
| import com.airbnb.mvrx.MvRxState |
| import com.airbnb.mvrx.MvRxViewModelFactory |
| import com.airbnb.mvrx.Success |
| import com.airbnb.mvrx.Uninitialized |
| import com.airbnb.mvrx.ViewModelContext |
| import java.io.FileInputStream |
| import kotlin.math.max |
| import kotlin.math.min |
| |
| data class PlayerState( |
| val composition: Async<LottieComposition> = Uninitialized, |
| val controlsVisible: Boolean = true, |
| val controlBarVisible: Boolean = true, |
| val renderGraphVisible: Boolean = false, |
| val outlineMasksAndMattes: Boolean = false, |
| val borderVisible: Boolean = false, |
| val backgroundColorVisible: Boolean = false, |
| val speedVisible: Boolean = false, |
| val trimVisible: Boolean = false, |
| val useMergePaths: Boolean = false, |
| val minFrame: Int = 0, |
| val maxFrame: Int = 0, |
| val speed: Float = 1f, |
| val repeatCount: Int = ValueAnimator.INFINITE |
| ) : MvRxState |
| |
| class PlayerViewModel( |
| initialState: PlayerState, |
| private val application: Application |
| ) : MvRxViewModel<PlayerState>(initialState) { |
| |
| fun fetchAnimation(args: CompositionArgs) { |
| val url = args.url ?: args.animationDataV2?.file ?: args.animationData?.lottieLink |
| |
| when { |
| url != null -> LottieCompositionFactory.fromUrl(application, url, null) |
| args.fileUri != null -> taskForUri(args.fileUri) |
| args.asset != null -> LottieCompositionFactory.fromAsset(application, args.asset, null) |
| else -> error("Don't know how to fetch animation for $args") |
| } |
| .addListener { |
| setState { |
| copy(composition = Success(it), minFrame = it.startFrame.toInt(), maxFrame = it.endFrame.toInt()) |
| } |
| } |
| .addFailureListener { setState { copy(composition = Fail(it)) } } |
| } |
| |
| private fun taskForUri(uri: Uri): LottieTask<LottieComposition> { |
| val fis = when (uri.scheme) { |
| "file" -> FileInputStream(uri.path ?: error("File has no path!")) |
| "content" -> application.contentResolver.openInputStream(uri) |
| else -> error("Unknown scheme ${uri.scheme}") |
| } |
| |
| return LottieCompositionFactory.fromJsonInputStream(fis, null) |
| } |
| |
| fun toggleRenderGraphVisible() = setState { copy(renderGraphVisible = !renderGraphVisible) } |
| |
| fun toggleOutlineMasksAndMattes() = setState { copy(outlineMasksAndMattes = !outlineMasksAndMattes) } |
| |
| fun toggleBorderVisible() = setState { copy(borderVisible = !borderVisible) } |
| |
| fun toggleBackgroundColorVisible() = setState { copy(backgroundColorVisible = !backgroundColorVisible) } |
| |
| fun setBackgroundColorVisible(visible: Boolean) = setState { copy(backgroundColorVisible = visible) } |
| |
| fun toggleSpeedVisible() = setState { copy(speedVisible = !speedVisible) } |
| |
| fun setSpeedVisible(visible: Boolean) = setState { copy(speedVisible = visible) } |
| |
| fun toggleTrimVisible() = setState { copy(trimVisible = !trimVisible) } |
| |
| fun setTrimVisible(visible: Boolean) = setState { copy(trimVisible = visible) } |
| |
| fun toggleMergePaths() = setState { copy(useMergePaths = !useMergePaths) } |
| |
| fun setMinFrame(minFrame: Int) = setState { |
| copy(minFrame = max(minFrame, composition()?.startFrame?.toInt() ?: 0)) |
| } |
| |
| fun setMaxFrame(maxFrame: Int) = setState { |
| copy(maxFrame = min(maxFrame, composition()?.endFrame?.toInt() ?: 0)) |
| } |
| |
| fun setSpeed(speed: Float) = setState { copy(speed = speed) } |
| |
| fun toggleLoop() = setState { copy(repeatCount = if (repeatCount == ValueAnimator.INFINITE) 0 else ValueAnimator.INFINITE) } |
| |
| fun setDistractionFree(distractionFree: Boolean) = setState { |
| copy( |
| controlsVisible = !distractionFree, |
| controlBarVisible = !distractionFree, |
| renderGraphVisible = false, |
| borderVisible = false, |
| backgroundColorVisible = false, |
| speedVisible = false, |
| trimVisible = false |
| ) |
| } |
| |
| companion object : MvRxViewModelFactory<PlayerViewModel, PlayerState> { |
| override fun create(viewModelContext: ViewModelContext, state: PlayerState): PlayerViewModel { |
| return PlayerViewModel(state, viewModelContext.app()) |
| } |
| } |
| } |