package com.out.rn_video import android.view.View import android.widget.FrameLayout import com.facebook.react.bridge.ReactContext import com.facebook.react.uimanager.events.RCTEventEmitter import com.google.android.exoplayer2.ExoPlayer import com.google.android.exoplayer2.MediaItem import com.google.android.exoplayer2.Player import com.google.android.exoplayer2.video.VideoSize import com.out.rn_video.custom_player.ExoPlayerView import kotlinx.android.synthetic.main.player_controls.view.* import kotlinx.android.synthetic.main.playerview.view.* class RNVideoPlayerView(context: ReactContext) : FrameLayout(context), Player.Listener { var showBuffering = BUFFERING_DEFAULT var controls = CONTROLS_DEFAULT var controlsTimeout = CONTROLS_TIMEOUT_MS var canGoBack = true private val playerContainer by lazy { View.inflate(context, R.layout.playerview, this) } val playerView: ExoPlayerView by lazy { playerContainer.playerView } val player by lazy { ExoPlayer.Builder(context).build() } init { player.addListener(this) playerView.setPlayer(player) updateUi() } private fun updateUi() { playerView.setOnClickListener { if (!controls) return@setOnClickListener handler.removeCallbacks(controlsRunnable) if (playerControls.visibility == View.VISIBLE) { handler.postDelayed(controlsRunnable, 0) } else { playerControls.visible() handler.postDelayed(controlsRunnable, controlsTimeout.toLong()) } } playerContainer.iconBack.setOnClickListener { sendEvent("onBack") } playerContainer.iconFullscreen.setOnClickListener { handler.postDelayed(controlsRunnable, controlsTimeout.toLong()) sendEvent("onFullScreen") } playerContainer.iconPlayPause.setOnClickListener { handler.postDelayed(controlsRunnable, controlsTimeout.toLong()) if (player.isPlaying) { player.pause() } else { player.play() } } if (canGoBack) playerContainer.iconBack.visible() else playerContainer.iconBack.hide() } override fun onDetachedFromWindow() { super.onDetachedFromWindow() player.stop() player.release() player.removeListener(this) handler.removeCallbacks(controlsRunnable) } fun prepareMedia(videoUri: String) { player.addListener(this) val mediaItem = MediaItem.fromUri(videoUri) player.setMediaItem(mediaItem) player.prepare() } override fun onVideoSizeChanged(size: VideoSize) { playerView.onVideoSizeChanged(size) } override fun onPlaybackStateChanged(state: Int) { when (state) { Player.STATE_READY -> { playerContainer.loader?.hide() } Player.STATE_BUFFERING -> { if (showBuffering) playerContainer.loader?.visible() } Player.STATE_ENDED -> { } Player.STATE_IDLE -> { } } } override fun onIsPlayingChanged(isPlaying: Boolean) { val resource = if (isPlaying) { R.drawable.icon_pause } else { R.drawable.icon_play } playerContainer.iconPlayPause.setImageResource(resource) } override fun onRenderedFirstFrame() { playerView.onRenderedFirstFrame() } private val controlsRunnable = Runnable { playerControls.hide() } private fun View.hide() { animate()?.alpha(0.0f)?.duration = 500 visibility = View.GONE } private fun View.visible(opacity: Float = 1.0f) { animate()?.alpha(opacity)?.duration = 1000 visibility = View.VISIBLE } private fun sendEvent(eventName: String) { if (context is ReactContext) { (context as ReactContext).getJSModule(RCTEventEmitter::class.java) .receiveEvent( id, eventName, null ) } } }