mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
UI stuff
This commit is contained in:
parent
efeb42fd2e
commit
1e01abf929
10 changed files with 140 additions and 101 deletions
|
@ -50,7 +50,7 @@ private fun RemoteMediaClient.getItemIndex(): Int? {
|
||||||
|
|
||||||
class SkipNextEpisodeController(val view: ImageView) : UIController() {
|
class SkipNextEpisodeController(val view: ImageView) : UIController() {
|
||||||
init {
|
init {
|
||||||
view.setImageResource(R.drawable.exo_controls_fastforward)
|
view.setImageResource(R.drawable.ic_baseline_skip_next_24)
|
||||||
view.setOnClickListener {
|
view.setOnClickListener {
|
||||||
remoteMediaClient?.let {
|
remoteMediaClient?.let {
|
||||||
it.queueNext(JSONObject())
|
it.queueNext(JSONObject())
|
||||||
|
|
|
@ -81,6 +81,8 @@ import com.lagradost.cloudstream3.ui.result.ResultViewModel
|
||||||
import com.lagradost.cloudstream3.utils.CastHelper.startCast
|
import com.lagradost.cloudstream3.utils.CastHelper.startCast
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStoreHelper
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.saveViewPos
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.getId
|
import com.lagradost.cloudstream3.utils.getId
|
||||||
import kotlinx.android.synthetic.main.fragment_player.*
|
import kotlinx.android.synthetic.main.fragment_player.*
|
||||||
|
@ -544,11 +546,15 @@ class PlayerFragment : Fragment() {
|
||||||
private lateinit var volumeObserver: SettingsContentObserver
|
private lateinit var volumeObserver: SettingsContentObserver
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance(data: PlayerData) =
|
fun newInstance(data: PlayerData, startPos: Long? = null) =
|
||||||
PlayerFragment().apply {
|
PlayerFragment().apply {
|
||||||
arguments = Bundle().apply {
|
arguments = Bundle().apply {
|
||||||
//println(data)
|
//println(data)
|
||||||
putString("data", mapper.writeValueAsString(data))
|
putString("data", mapper.writeValueAsString(data))
|
||||||
|
println("PUT START: " + startPos)
|
||||||
|
if (startPos != null) {
|
||||||
|
putLong(STATE_RESUME_POSITION, startPos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -556,8 +562,7 @@ class PlayerFragment : Fragment() {
|
||||||
private fun savePos() {
|
private fun savePos() {
|
||||||
if (this::exoPlayer.isInitialized) {
|
if (this::exoPlayer.isInitialized) {
|
||||||
if (exoPlayer.duration > 0 && exoPlayer.currentPosition > 0) {
|
if (exoPlayer.duration > 0 && exoPlayer.currentPosition > 0) {
|
||||||
//TODO FIX SAVE POS
|
context?.saveViewPos(getEpisode()?.id, exoPlayer.currentPosition, exoPlayer.duration)
|
||||||
// setViewPosDur(data!!, exoPlayer.currentPosition, exoPlayer.duration)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -610,7 +615,7 @@ class PlayerFragment : Fragment() {
|
||||||
private var resizeMode = 0
|
private var resizeMode = 0
|
||||||
private var playbackSpeed = 0f
|
private var playbackSpeed = 0f
|
||||||
private var allEpisodes: HashMap<Int, ArrayList<ExtractorLink>> = HashMap()
|
private var allEpisodes: HashMap<Int, ArrayList<ExtractorLink>> = HashMap()
|
||||||
private var episodes: ArrayList<ResultEpisode> = ArrayList()
|
private var episodes: List<ResultEpisode> = ArrayList()
|
||||||
var currentPoster: String? = null
|
var currentPoster: String? = null
|
||||||
var currentHeaderName: String? = null
|
var currentHeaderName: String? = null
|
||||||
|
|
||||||
|
@ -795,6 +800,14 @@ class PlayerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arguments?.getString("data")?.let {
|
||||||
|
playerData = mapper.readValue(it, PlayerData::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments?.getLong(STATE_RESUME_POSITION)?.let {
|
||||||
|
playbackPosition = it
|
||||||
|
}
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
currentWindow = savedInstanceState.getInt(STATE_RESUME_WINDOW)
|
currentWindow = savedInstanceState.getInt(STATE_RESUME_WINDOW)
|
||||||
playbackPosition = savedInstanceState.getLong(STATE_RESUME_POSITION)
|
playbackPosition = savedInstanceState.getLong(STATE_RESUME_POSITION)
|
||||||
|
@ -819,9 +832,7 @@ class PlayerFragment : Fragment() {
|
||||||
)
|
)
|
||||||
|
|
||||||
viewModel = ViewModelProvider(requireActivity()).get(ResultViewModel::class.java)
|
viewModel = ViewModelProvider(requireActivity()).get(ResultViewModel::class.java)
|
||||||
arguments?.getString("data")?.let {
|
|
||||||
playerData = mapper.readValue(it, PlayerData::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
observeDirectly(viewModel.episodes) { _episodes ->
|
observeDirectly(viewModel.episodes) { _episodes ->
|
||||||
episodes = _episodes
|
episodes = _episodes
|
||||||
|
@ -1175,6 +1186,8 @@ class PlayerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
savePos()
|
||||||
|
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
isInPlayer = false
|
isInPlayer = false
|
||||||
releasePlayer()
|
releasePlayer()
|
||||||
|
@ -1184,6 +1197,7 @@ class PlayerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
|
savePos()
|
||||||
super.onPause()
|
super.onPause()
|
||||||
if (Util.SDK_INT <= 23) {
|
if (Util.SDK_INT <= 23) {
|
||||||
if (player_view != null) player_view.onPause()
|
if (player_view != null) player_view.onPause()
|
||||||
|
@ -1192,6 +1206,7 @@ class PlayerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
|
savePos()
|
||||||
super.onStop()
|
super.onStop()
|
||||||
if (Util.SDK_INT > 23) {
|
if (Util.SDK_INT > 23) {
|
||||||
if (player_view != null) player_view.onPause()
|
if (player_view != null) player_view.onPause()
|
||||||
|
@ -1200,6 +1215,8 @@ class PlayerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
savePos()
|
||||||
|
|
||||||
if (this::exoPlayer.isInitialized) {
|
if (this::exoPlayer.isInitialized) {
|
||||||
outState.putInt(STATE_RESUME_WINDOW, exoPlayer.currentWindowIndex)
|
outState.putInt(STATE_RESUME_WINDOW, exoPlayer.currentWindowIndex)
|
||||||
outState.putLong(STATE_RESUME_POSITION, exoPlayer.currentPosition)
|
outState.putLong(STATE_RESUME_POSITION, exoPlayer.currentPosition)
|
||||||
|
@ -1209,7 +1226,6 @@ class PlayerFragment : Fragment() {
|
||||||
outState.putInt(RESIZE_MODE_KEY, resizeMode)
|
outState.putInt(RESIZE_MODE_KEY, resizeMode)
|
||||||
outState.putFloat(PLAYBACK_SPEED, playbackSpeed)
|
outState.putFloat(PLAYBACK_SPEED, playbackSpeed)
|
||||||
outState.putString("data", mapper.writeValueAsString(playerData))
|
outState.putString("data", mapper.writeValueAsString(playerData))
|
||||||
savePos()
|
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1305,6 +1321,7 @@ class PlayerFragment : Fragment() {
|
||||||
.setTrackSelector(trackSelector)
|
.setTrackSelector(trackSelector)
|
||||||
|
|
||||||
_exoPlayer.setMediaSourceFactory(DefaultMediaSourceFactory(CustomFactory()))
|
_exoPlayer.setMediaSourceFactory(DefaultMediaSourceFactory(CustomFactory()))
|
||||||
|
println("START POS: " + playbackPosition)
|
||||||
exoPlayer = _exoPlayer.build().apply {
|
exoPlayer = _exoPlayer.build().apply {
|
||||||
playWhenReady = isPlayerPlaying
|
playWhenReady = isPlayerPlaying
|
||||||
seekTo(currentWindow, playbackPosition)
|
seekTo(currentWindow, playbackPosition)
|
||||||
|
|
|
@ -22,7 +22,7 @@ data class EpisodeClickEvent(val action: Int, val data: ResultEpisode)
|
||||||
|
|
||||||
class EpisodeAdapter(
|
class EpisodeAdapter(
|
||||||
private var activity: Activity,
|
private var activity: Activity,
|
||||||
var cardList: ArrayList<ResultEpisode>,
|
var cardList: List<ResultEpisode>,
|
||||||
private val resView: RecyclerView,
|
private val resView: RecyclerView,
|
||||||
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||||
) :
|
) :
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.lagradost.cloudstream3.ui.result
|
package com.lagradost.cloudstream3.ui.result
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -20,18 +21,9 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.load.model.GlideUrl
|
import com.bumptech.glide.load.model.GlideUrl
|
||||||
import com.bumptech.glide.request.RequestOptions.bitmapTransform
|
import com.bumptech.glide.request.RequestOptions.bitmapTransform
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
|
||||||
import com.google.android.exoplayer2.ext.cast.CastPlayer
|
|
||||||
import com.google.android.exoplayer2.util.MimeTypes
|
|
||||||
import com.google.android.gms.cast.MediaInfo
|
|
||||||
import com.google.android.gms.cast.MediaMetadata
|
|
||||||
import com.google.android.gms.cast.MediaQueueItem
|
|
||||||
import com.google.android.gms.cast.MediaStatus.REPEAT_MODE_REPEAT_OFF
|
|
||||||
import com.google.android.gms.cast.MediaStatus.REPEAT_MODE_REPEAT_SINGLE
|
|
||||||
import com.google.android.gms.cast.framework.CastButtonFactory
|
import com.google.android.gms.cast.framework.CastButtonFactory
|
||||||
import com.google.android.gms.cast.framework.CastContext
|
import com.google.android.gms.cast.framework.CastContext
|
||||||
import com.google.android.gms.cast.framework.CastState
|
import com.google.android.gms.cast.framework.CastState
|
||||||
import com.google.android.gms.common.images.WebImage
|
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
||||||
|
@ -41,11 +33,10 @@ import com.lagradost.cloudstream3.mvvm.observe
|
||||||
import com.lagradost.cloudstream3.ui.player.PlayerData
|
import com.lagradost.cloudstream3.ui.player.PlayerData
|
||||||
import com.lagradost.cloudstream3.ui.player.PlayerFragment
|
import com.lagradost.cloudstream3.ui.player.PlayerFragment
|
||||||
import com.lagradost.cloudstream3.utils.CastHelper.startCast
|
import com.lagradost.cloudstream3.utils.CastHelper.startCast
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import jp.wasabeef.glide.transformations.BlurTransformation
|
import jp.wasabeef.glide.transformations.BlurTransformation
|
||||||
import kotlinx.android.synthetic.main.fragment_result.*
|
import kotlinx.android.synthetic.main.fragment_result.*
|
||||||
import org.json.JSONArray
|
|
||||||
import org.json.JSONObject
|
|
||||||
|
|
||||||
|
|
||||||
const val MAX_SYNO_LENGH = 300
|
const val MAX_SYNO_LENGH = 300
|
||||||
|
@ -59,12 +50,42 @@ data class ResultEpisode(
|
||||||
val apiName: String,
|
val apiName: String,
|
||||||
val id: Int,
|
val id: Int,
|
||||||
val index: Int,
|
val index: Int,
|
||||||
val progress: Long, // time in MS
|
val position: Long, // time in MS
|
||||||
val duration: Long, // duration in MS
|
val duration: Long, // duration in MS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun ResultEpisode.getRealPosition(): Long {
|
||||||
|
if (duration <= 0) return 0
|
||||||
|
val percentage = position * 100 / duration
|
||||||
|
if (percentage <= 5 || percentage >= 95) return 0
|
||||||
|
return position
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.buildResultEpisode(
|
||||||
|
name: String?,
|
||||||
|
poster: String?,
|
||||||
|
episode: Int,
|
||||||
|
season: Int?,
|
||||||
|
data: String,
|
||||||
|
apiName: String,
|
||||||
|
id: Int,
|
||||||
|
index: Int,
|
||||||
|
): ResultEpisode {
|
||||||
|
val posDur = getViewPos(id)
|
||||||
|
return ResultEpisode(name,
|
||||||
|
poster,
|
||||||
|
episode,
|
||||||
|
season,
|
||||||
|
data,
|
||||||
|
apiName,
|
||||||
|
id,
|
||||||
|
index,
|
||||||
|
posDur?.position ?: 0,
|
||||||
|
posDur?.duration ?: 0)
|
||||||
|
}
|
||||||
|
|
||||||
fun ResultEpisode.getWatchProgress(): Float {
|
fun ResultEpisode.getWatchProgress(): Float {
|
||||||
return progress.toFloat() / duration
|
return position.toFloat() / duration
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResultFragment : Fragment() {
|
class ResultFragment : Fragment() {
|
||||||
|
@ -79,11 +100,11 @@ class ResultFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var currentLoadingCount = 0 // THIS IS USED TO PREVENT LATE EVENTS, AFTER DISMISS WAS CLICKED
|
||||||
private lateinit var viewModel: ResultViewModel
|
private lateinit var viewModel: ResultViewModel
|
||||||
private var allEpisodes: HashMap<Int, ArrayList<ExtractorLink>> = HashMap()
|
private var allEpisodes: HashMap<Int, ArrayList<ExtractorLink>> = HashMap()
|
||||||
var currentHeaderName: String? = null
|
private var currentHeaderName: String? = null
|
||||||
var currentEpisodes: ArrayList<ResultEpisode>? = null
|
private var currentEpisodes: List<ResultEpisode>? = null
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
|
@ -100,7 +121,7 @@ class ResultFragment : Fragment() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentPoster: String? = null
|
private var currentPoster: String? = null
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
@ -149,17 +170,24 @@ class ResultFragment : Fragment() {
|
||||||
//val id = episodeClick.data.id
|
//val id = episodeClick.data.id
|
||||||
val index = episodeClick.data.index
|
val index = episodeClick.data.index
|
||||||
val buildInPlayer = true
|
val buildInPlayer = true
|
||||||
|
currentLoadingCount++
|
||||||
when (episodeClick.action) {
|
when (episodeClick.action) {
|
||||||
ACTION_CHROME_CAST_EPISODE -> {
|
ACTION_CHROME_CAST_EPISODE -> {
|
||||||
val builder = AlertDialog.Builder(requireContext(), R.style.AlertDialogCustom)
|
val currentLoad = currentLoadingCount
|
||||||
val customLayout = layoutInflater.inflate(R.layout.dialog_loading, null);
|
val builder = AlertDialog.Builder(requireContext(), R.style.AlertDialogCustomTransparent)
|
||||||
|
val customLayout = layoutInflater.inflate(R.layout.dialog_loading, null)
|
||||||
builder.setView(customLayout)
|
builder.setView(customLayout)
|
||||||
|
|
||||||
val dialog = builder.create()
|
val dialog = builder.create()
|
||||||
|
|
||||||
dialog.show()
|
dialog.show()
|
||||||
Toast.makeText(activity, "Loading links", Toast.LENGTH_SHORT).show()
|
dialog.setOnDismissListener {
|
||||||
|
currentLoadingCount++
|
||||||
|
}
|
||||||
|
// Toast.makeText(activity, "Loading links", Toast.LENGTH_SHORT).show()
|
||||||
|
|
||||||
viewModel.loadEpisode(episodeClick.data, true) { data ->
|
viewModel.loadEpisode(episodeClick.data, true) { data ->
|
||||||
|
if(currentLoadingCount != currentLoad) return@loadEpisode
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
when (data) {
|
when (data) {
|
||||||
is Resource.Failure -> {
|
is Resource.Failure -> {
|
||||||
|
@ -173,52 +201,9 @@ class ResultFragment : Fragment() {
|
||||||
currentPoster,
|
currentPoster,
|
||||||
episodeClick.data.index,
|
episodeClick.data.index,
|
||||||
eps,
|
eps,
|
||||||
sortUrls(data.value))
|
sortUrls(data.value),
|
||||||
/*
|
startTime = episodeClick.data.getRealPosition()
|
||||||
val epData = episodeClick.data
|
|
||||||
val links = sortUrls(data.value)
|
|
||||||
|
|
||||||
val castContext = CastContext.getSharedInstance(requireContext())
|
|
||||||
|
|
||||||
val customData =
|
|
||||||
links.map { JSONObject().put("name", it.name) }
|
|
||||||
val jsonArray = JSONArray()
|
|
||||||
for (item in customData) {
|
|
||||||
jsonArray.put(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
val mediaItems = links.map {
|
|
||||||
val movieMetadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE)
|
|
||||||
movieMetadata.putString(MediaMetadata.KEY_SUBTITLE,
|
|
||||||
epData.name ?: "Episode ${epData.episode}")
|
|
||||||
|
|
||||||
if (currentHeaderName != null)
|
|
||||||
movieMetadata.putString(MediaMetadata.KEY_TITLE, currentHeaderName)
|
|
||||||
|
|
||||||
val srcPoster = epData.poster ?: currentPoster
|
|
||||||
if (srcPoster != null) {
|
|
||||||
movieMetadata.addImage(WebImage(Uri.parse(srcPoster)))
|
|
||||||
}
|
|
||||||
MediaQueueItem.Builder(
|
|
||||||
MediaInfo.Builder(it.url)
|
|
||||||
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
|
|
||||||
.setContentType(MimeTypes.VIDEO_UNKNOWN)
|
|
||||||
.setCustomData(JSONObject().put("data", jsonArray))
|
|
||||||
.setMetadata(movieMetadata)
|
|
||||||
.build()
|
|
||||||
)
|
)
|
||||||
.build()
|
|
||||||
}.toTypedArray()
|
|
||||||
|
|
||||||
val castPlayer = CastPlayer(castContext)
|
|
||||||
|
|
||||||
castPlayer.loadItems(
|
|
||||||
mediaItems,
|
|
||||||
0,
|
|
||||||
epData.progress,
|
|
||||||
REPEAT_MODE_REPEAT_SINGLE
|
|
||||||
//REPEAT_MODE_REPEAT_SINGLE
|
|
||||||
)*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,7 +216,10 @@ class ResultFragment : Fragment() {
|
||||||
R.anim.exit_anim,
|
R.anim.exit_anim,
|
||||||
R.anim.pop_enter,
|
R.anim.pop_enter,
|
||||||
R.anim.pop_exit)
|
R.anim.pop_exit)
|
||||||
.add(R.id.homeRoot, PlayerFragment.newInstance(PlayerData(index, null, 0)))
|
.add(R.id.homeRoot,
|
||||||
|
PlayerFragment.newInstance(PlayerData(index, null, 0),
|
||||||
|
episodeClick.data.getRealPosition())
|
||||||
|
)
|
||||||
.commit()
|
.commit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,10 +276,10 @@ class ResultFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d.year != null) {
|
if (d.year != null) {
|
||||||
result_year.visibility = View.VISIBLE
|
result_year.visibility = VISIBLE
|
||||||
result_year.text = d.year.toString()
|
result_year.text = d.year.toString()
|
||||||
} else {
|
} else {
|
||||||
result_year.visibility = View.GONE
|
result_year.visibility = GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d.posterUrl != null) {
|
if (d.posterUrl != null) {
|
||||||
|
@ -383,12 +371,12 @@ activity?.startActivityForResult(vlcIntent, REQUEST_CODE)
|
||||||
}
|
}
|
||||||
|
|
||||||
result_tag.removeAllViews()
|
result_tag.removeAllViews()
|
||||||
result_tag_holder.visibility = View.GONE
|
result_tag_holder.visibility = GONE
|
||||||
result_status.visibility = View.GONE
|
result_status.visibility = GONE
|
||||||
|
|
||||||
when (d) {
|
when (d) {
|
||||||
is AnimeLoadResponse -> {
|
is AnimeLoadResponse -> {
|
||||||
result_status.visibility = View.VISIBLE
|
result_status.visibility = VISIBLE
|
||||||
result_status.text = when (d.showStatus) {
|
result_status.text = when (d.showStatus) {
|
||||||
null -> ""
|
null -> ""
|
||||||
ShowStatus.Ongoing -> "Ongoing"
|
ShowStatus.Ongoing -> "Ongoing"
|
||||||
|
@ -402,9 +390,9 @@ activity?.startActivityForResult(vlcIntent, REQUEST_CODE)
|
||||||
result_toolbar.title = titleName
|
result_toolbar.title = titleName
|
||||||
|
|
||||||
if (d.tags == null) {
|
if (d.tags == null) {
|
||||||
result_tag_holder.visibility = View.GONE
|
result_tag_holder.visibility = GONE
|
||||||
} else {
|
} else {
|
||||||
result_tag_holder.visibility = View.VISIBLE
|
result_tag_holder.visibility = VISIBLE
|
||||||
|
|
||||||
for ((index, tag) in d.tags.withIndex()) {
|
for ((index, tag) in d.tags.withIndex()) {
|
||||||
val viewBtt = layoutInflater.inflate(R.layout.result_tag, null)
|
val viewBtt = layoutInflater.inflate(R.layout.result_tag, null)
|
||||||
|
@ -426,6 +414,6 @@ activity?.startActivityForResult(vlcIntent, REQUEST_CODE)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewModel.resultResponse.value == null && apiName != null && slug != null)
|
if (viewModel.resultResponse.value == null && apiName != null && slug != null)
|
||||||
viewModel.load(slug, apiName)
|
viewModel.load(requireContext(), slug, apiName)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package com.lagradost.cloudstream3.ui.result
|
package com.lagradost.cloudstream3.ui.result
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
@ -8,17 +9,27 @@ import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.APIHolder.getApiFromName
|
import com.lagradost.cloudstream3.APIHolder.getApiFromName
|
||||||
import com.lagradost.cloudstream3.mvvm.Resource
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class ResultViewModel : ViewModel() {
|
class ResultViewModel : ViewModel() {
|
||||||
private val _resultResponse: MutableLiveData<Resource<Any?>> = MutableLiveData()
|
private val _resultResponse: MutableLiveData<Resource<Any?>> = MutableLiveData()
|
||||||
private val _episodes: MutableLiveData<ArrayList<ResultEpisode>> = MutableLiveData()
|
private val _episodes: MutableLiveData<List<ResultEpisode>> = MutableLiveData()
|
||||||
val resultResponse: LiveData<Resource<Any?>> get() = _resultResponse
|
val resultResponse: LiveData<Resource<Any?>> get() = _resultResponse
|
||||||
val episodes: LiveData<ArrayList<ResultEpisode>> get() = _episodes
|
val episodes: LiveData<List<ResultEpisode>> get() = _episodes
|
||||||
private val dubStatus: MutableLiveData<DubStatus> = MutableLiveData()
|
private val dubStatus: MutableLiveData<DubStatus> = MutableLiveData()
|
||||||
|
|
||||||
fun load(url: String, apiName: String) = viewModelScope.launch {
|
fun reloadEpisodes(context: Context) {
|
||||||
|
val current = _episodes.value ?: return
|
||||||
|
val copy = current.map {
|
||||||
|
val posDur = context.getViewPos(it.id)
|
||||||
|
it.copy(position = posDur?.position ?: 0, duration = posDur?.duration ?: 0)
|
||||||
|
}
|
||||||
|
_episodes.postValue(copy)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun load(context: Context, url: String, apiName: String) = viewModelScope.launch {
|
||||||
_apiName.postValue(apiName)
|
_apiName.postValue(apiName)
|
||||||
val data = safeApiCall {
|
val data = safeApiCall {
|
||||||
getApiFromName(apiName).load(url)
|
getApiFromName(apiName).load(url)
|
||||||
|
@ -39,7 +50,7 @@ class ResultViewModel : ViewModel() {
|
||||||
if (dataList != null) {
|
if (dataList != null) {
|
||||||
val episodes = ArrayList<ResultEpisode>()
|
val episodes = ArrayList<ResultEpisode>()
|
||||||
for ((index, i) in dataList.withIndex()) {
|
for ((index, i) in dataList.withIndex()) {
|
||||||
episodes.add(ResultEpisode(
|
episodes.add(context.buildResultEpisode(
|
||||||
null, // TODO ADD NAMES
|
null, // TODO ADD NAMES
|
||||||
null,
|
null,
|
||||||
index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE
|
index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE
|
||||||
|
@ -48,8 +59,6 @@ class ResultViewModel : ViewModel() {
|
||||||
apiName,
|
apiName,
|
||||||
(d.url + index).hashCode(),
|
(d.url + index).hashCode(),
|
||||||
index,
|
index,
|
||||||
0,//(index * 0.1f),//TODO TEST; REMOVE
|
|
||||||
0,
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
_episodes.postValue(episodes)
|
_episodes.postValue(episodes)
|
||||||
|
@ -59,7 +68,7 @@ class ResultViewModel : ViewModel() {
|
||||||
is TvSeriesLoadResponse -> {
|
is TvSeriesLoadResponse -> {
|
||||||
val episodes = ArrayList<ResultEpisode>()
|
val episodes = ArrayList<ResultEpisode>()
|
||||||
for ((index, i) in d.episodes.withIndex()) {
|
for ((index, i) in d.episodes.withIndex()) {
|
||||||
episodes.add(ResultEpisode(
|
episodes.add(context.buildResultEpisode(
|
||||||
null, // TODO ADD NAMES
|
null, // TODO ADD NAMES
|
||||||
null,
|
null,
|
||||||
index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE
|
index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE
|
||||||
|
@ -68,21 +77,19 @@ class ResultViewModel : ViewModel() {
|
||||||
apiName,
|
apiName,
|
||||||
(d.url + index).hashCode(),
|
(d.url + index).hashCode(),
|
||||||
index,
|
index,
|
||||||
0,//(index * 0.1f),//TODO TEST; REMOVE
|
|
||||||
0,
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
_episodes.postValue(episodes)
|
_episodes.postValue(episodes)
|
||||||
}
|
}
|
||||||
is MovieLoadResponse -> {
|
is MovieLoadResponse -> {
|
||||||
_episodes.postValue(arrayListOf(ResultEpisode(null,
|
_episodes.postValue(arrayListOf(context.buildResultEpisode(
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
0, null,
|
0, null,
|
||||||
d.movieUrl,
|
d.movieUrl,
|
||||||
d.apiName,
|
d.apiName,
|
||||||
(d.url).hashCode(),
|
(d.url).hashCode(),
|
||||||
0,
|
0,
|
||||||
0, 0,
|
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,5 +148,4 @@ class ResultViewModel : ViewModel() {
|
||||||
fun loadIndex(index: Int): ResultEpisode? {
|
fun loadIndex(index: Int): ResultEpisode? {
|
||||||
return episodes.value?.get(index)
|
return episodes.value?.get(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
package com.lagradost.cloudstream3.utils
|
package com.lagradost.cloudstream3.utils
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.lagradost.cloudstream3.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||||
|
|
||||||
|
const val VIDEO_POS_DUR = "video_pos_dur"
|
||||||
|
|
||||||
|
data class PosDur(val position: Long, val duration: Long)
|
||||||
|
|
||||||
|
object DataStoreHelper {
|
||||||
|
var currentAccount: String = "0" //TODO ACCOUNT IMPLEMENTATION
|
||||||
|
|
||||||
|
fun Context.saveViewPos(id: Int?, pos: Long, dur: Long) {
|
||||||
|
if(id == null) return
|
||||||
|
setKey("$currentAccount/$VIDEO_POS_DUR", id.toString(), PosDur(pos, dur))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.getViewPos(id: Int): PosDur? {
|
||||||
|
return getKey<PosDur>("$currentAccount/$VIDEO_POS_DUR", id.toString(), null)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,19 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent" >
|
||||||
<!--
|
<!--
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
|
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||||
android:text="Loading..." android:textColor="?attr/textColor" android:textSize="20sp"
|
android:text="Loading..." android:textColor="?attr/textColor" android:textSize="20sp"
|
||||||
android:textStyle="bold" android:layout_margin="10dp"/>-->
|
android:textStyle="bold" android:layout_margin="10dp"/>-->
|
||||||
<!-- style="@android:style/Widget.Material.ProgressBar.Horizontal"
|
<!-- style="@android:style/Widget.Material.ProgressBar.Horizontal"
|
||||||
-->
|
-->
|
||||||
|
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||||
|
android:text="@string/loading_chromecast" android:layout_gravity="center" android:textColor="?attr/textColor" android:textSize="20sp"
|
||||||
|
android:textStyle="bold" android:layout_margin="10dp" />
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:layout_margin="10dp"
|
|
||||||
|
android:layout_margin="20dp"
|
||||||
|
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
|
|
|
@ -22,4 +22,5 @@
|
||||||
<string name="result_share">Share</string>
|
<string name="result_share">Share</string>
|
||||||
<string name="result_open_in_browser">Open In Browser</string>
|
<string name="result_open_in_browser">Open In Browser</string>
|
||||||
<string name="skip_loading">Skip Loading</string>
|
<string name="skip_loading">Skip Loading</string>
|
||||||
|
<string name="loading_chromecast">Loading...</string>
|
||||||
</resources>
|
</resources>
|
|
@ -114,7 +114,9 @@
|
||||||
<item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
|
<item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
|
||||||
<item name="android:windowBackground">@drawable/dialog__window_background</item>
|
<item name="android:windowBackground">@drawable/dialog__window_background</item>
|
||||||
</style>
|
</style>
|
||||||
|
<style name="AlertDialogCustomTransparent" parent="Theme.AppCompat.Dialog.Alert">
|
||||||
|
<item name="android:windowBackground">@color/transparent</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
<!-- CHROMECAST -->
|
<!-- CHROMECAST -->
|
||||||
|
|
Loading…
Reference in a new issue