This commit is contained in:
LagradOst 2021-06-15 18:07:20 +02:00
parent efeb42fd2e
commit 1e01abf929
10 changed files with 140 additions and 101 deletions

View file

@ -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())

View file

@ -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)

View file

@ -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,
) : ) :

View file

@ -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)
} }
} }

View file

@ -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)
} }
} }

View file

@ -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

View file

@ -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)
}
}

View file

@ -8,8 +8,12 @@
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"

View file

@ -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>

View file

@ -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 -->