mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
parent
7e9d1ded7f
commit
3cb2196e62
8 changed files with 238 additions and 15 deletions
|
@ -8,7 +8,9 @@ import com.lagradost.cloudstream3.syncproviders.SyncIdName
|
||||||
import com.lagradost.cloudstream3.ui.WatchType
|
import com.lagradost.cloudstream3.ui.WatchType
|
||||||
import com.lagradost.cloudstream3.ui.library.ListSorting
|
import com.lagradost.cloudstream3.ui.library.ListSorting
|
||||||
import com.lagradost.cloudstream3.ui.result.txt
|
import com.lagradost.cloudstream3.ui.result.txt
|
||||||
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.ioWork
|
import com.lagradost.cloudstream3.utils.Coroutines.ioWork
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllFavorites
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllSubscriptions
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllSubscriptions
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllWatchStateIds
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllWatchStateIds
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getBookmarkedData
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getBookmarkedData
|
||||||
|
@ -69,24 +71,47 @@ class LocalList : SyncAPI {
|
||||||
}?.distinctBy { it.first } ?: return null
|
}?.distinctBy { it.first } ?: return null
|
||||||
|
|
||||||
val list = ioWork {
|
val list = ioWork {
|
||||||
watchStatusIds.groupBy {
|
val isTv = isTvSettings()
|
||||||
it.second.stringRes
|
|
||||||
}.mapValues { group ->
|
val baseMap = WatchType.values().filter { it != WatchType.NONE }.associate {
|
||||||
|
// None is not something to display
|
||||||
|
it.stringRes to emptyList<SyncAPI.LibraryItem>()
|
||||||
|
} + mapOf(
|
||||||
|
R.string.favorites_list_name to emptyList()
|
||||||
|
) + if (!isTv) {
|
||||||
|
mapOf(
|
||||||
|
R.string.subscription_list_name to emptyList(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
emptyMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
val watchStatusMap = watchStatusIds.groupBy { it.second.stringRes }.mapValues { group ->
|
||||||
group.value.mapNotNull {
|
group.value.mapNotNull {
|
||||||
getBookmarkedData(it.first)?.toLibraryItem(it.first.toString())
|
getBookmarkedData(it.first)?.toLibraryItem(it.first.toString())
|
||||||
}
|
}
|
||||||
} + mapOf(R.string.subscription_list_name to getAllSubscriptions().mapNotNull {
|
}
|
||||||
|
|
||||||
|
val favoritesMap = mapOf(R.string.favorites_list_name to getAllFavorites().mapNotNull {
|
||||||
it.toLibraryItem()
|
it.toLibraryItem()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Don't show subscriptions or favorites on TV
|
||||||
|
val result = if (isTv) {
|
||||||
|
baseMap + watchStatusMap + favoritesMap
|
||||||
|
} else {
|
||||||
|
val subscriptionsMap = mapOf(R.string.subscription_list_name to getAllSubscriptions().mapNotNull {
|
||||||
|
it.toLibraryItem()
|
||||||
|
})
|
||||||
|
|
||||||
|
baseMap + watchStatusMap + subscriptionsMap + favoritesMap
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
val baseMap = WatchType.values().filter { it != WatchType.NONE }.associate {
|
|
||||||
// None is not something to display
|
|
||||||
it.stringRes to emptyList<SyncAPI.LibraryItem>()
|
|
||||||
} + mapOf(R.string.subscription_list_name to emptyList())
|
|
||||||
|
|
||||||
return SyncAPI.LibraryMetadata(
|
return SyncAPI.LibraryMetadata(
|
||||||
(baseMap + list).map { SyncAPI.LibraryList(txt(it.key), it.value) },
|
list.map { SyncAPI.LibraryList(txt(it.key), it.value) },
|
||||||
setOf(
|
setOf(
|
||||||
ListSorting.AlphabeticalA,
|
ListSorting.AlphabeticalA,
|
||||||
ListSorting.AlphabeticalZ,
|
ListSorting.AlphabeticalZ,
|
||||||
|
|
|
@ -445,6 +445,20 @@ open class ResultFragmentPhone : FullScreenPlayer() {
|
||||||
?: txt(R.string.no_data).asStringNull(context) ?: ""
|
?: txt(R.string.no_data).asStringNull(context) ?: ""
|
||||||
CommonActivity.showToast(txt(message, name), Toast.LENGTH_SHORT)
|
CommonActivity.showToast(txt(message, name), Toast.LENGTH_SHORT)
|
||||||
}
|
}
|
||||||
|
resultFavorite.setOnClickListener {
|
||||||
|
val isFavorite =
|
||||||
|
viewModel.toggleFavoriteStatus() ?: return@setOnClickListener
|
||||||
|
|
||||||
|
val message = if (isFavorite) {
|
||||||
|
R.string.favorite_added
|
||||||
|
} else {
|
||||||
|
R.string.favorite_removed
|
||||||
|
}
|
||||||
|
|
||||||
|
val name = (viewModel.page.value as? Resource.Success)?.value?.title
|
||||||
|
?: txt(R.string.no_data).asStringNull(context) ?: ""
|
||||||
|
CommonActivity.showToast(txt(message, name), Toast.LENGTH_SHORT)
|
||||||
|
}
|
||||||
mediaRouteButton.apply {
|
mediaRouteButton.apply {
|
||||||
val chromecastSupport = api?.hasChromecastSupport == true
|
val chromecastSupport = api?.hasChromecastSupport == true
|
||||||
alpha = if (chromecastSupport) 1f else 0.3f
|
alpha = if (chromecastSupport) 1f else 0.3f
|
||||||
|
@ -564,6 +578,19 @@ open class ResultFragmentPhone : FullScreenPlayer() {
|
||||||
binding?.resultSubscribe?.setImageResource(drawable)
|
binding?.resultSubscribe?.setImageResource(drawable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
observeNullable(viewModel.favoriteStatus) { isFavorite ->
|
||||||
|
binding?.resultFavorite?.isVisible = isFavorite != null
|
||||||
|
if (isFavorite == null) return@observeNullable
|
||||||
|
|
||||||
|
val drawable = if (isFavorite) {
|
||||||
|
R.drawable.ic_baseline_favorite_24
|
||||||
|
} else {
|
||||||
|
R.drawable.ic_baseline_favorite_border_24
|
||||||
|
}
|
||||||
|
|
||||||
|
binding?.resultFavorite?.setImageResource(drawable)
|
||||||
|
}
|
||||||
|
|
||||||
observe(viewModel.trailers) { trailers ->
|
observe(viewModel.trailers) { trailers ->
|
||||||
setTrailers(trailers.flatMap { it.mirros }) // I dont care about subtitles yet!
|
setTrailers(trailers.flatMap { it.mirros }) // I dont care about subtitles yet!
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
@ -17,6 +18,7 @@ import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.lagradost.cloudstream3.APIHolder.updateHasTrailers
|
import com.lagradost.cloudstream3.APIHolder.updateHasTrailers
|
||||||
|
import com.lagradost.cloudstream3.CommonActivity
|
||||||
import com.lagradost.cloudstream3.DubStatus
|
import com.lagradost.cloudstream3.DubStatus
|
||||||
import com.lagradost.cloudstream3.LoadResponse
|
import com.lagradost.cloudstream3.LoadResponse
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent
|
import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent
|
||||||
|
@ -265,6 +267,7 @@ class ResultFragmentTv : Fragment() {
|
||||||
resultEpisodesShow.onFocusChangeListener = rightListener
|
resultEpisodesShow.onFocusChangeListener = rightListener
|
||||||
resultDescription.onFocusChangeListener = leftListener
|
resultDescription.onFocusChangeListener = leftListener
|
||||||
resultBookmarkButton.onFocusChangeListener = leftListener
|
resultBookmarkButton.onFocusChangeListener = leftListener
|
||||||
|
resultFavoriteButton.onFocusChangeListener = leftListener
|
||||||
resultEpisodesShow.setOnClickListener {
|
resultEpisodesShow.setOnClickListener {
|
||||||
// toggle, to make it more touch accessable just in case someone thinks that a
|
// toggle, to make it more touch accessable just in case someone thinks that a
|
||||||
// tv layout is better but is using a touch device
|
// tv layout is better but is using a touch device
|
||||||
|
@ -283,7 +286,8 @@ class ResultFragmentTv : Fragment() {
|
||||||
resultPlaySeries,
|
resultPlaySeries,
|
||||||
resultResumeSeries,
|
resultResumeSeries,
|
||||||
resultPlayTrailer,
|
resultPlayTrailer,
|
||||||
resultBookmarkButton
|
resultBookmarkButton,
|
||||||
|
resultFavoriteButton
|
||||||
)
|
)
|
||||||
for (requestView in views) {
|
for (requestView in views) {
|
||||||
if (!requestView.isVisible) continue
|
if (!requestView.isVisible) continue
|
||||||
|
@ -424,6 +428,7 @@ class ResultFragmentTv : Fragment() {
|
||||||
val aboveCast = listOf(
|
val aboveCast = listOf(
|
||||||
binding?.resultEpisodesShow,
|
binding?.resultEpisodesShow,
|
||||||
binding?.resultBookmarkButton,
|
binding?.resultBookmarkButton,
|
||||||
|
binding?.resultFavoriteButton,
|
||||||
).firstOrNull {
|
).firstOrNull {
|
||||||
it?.isVisible == true
|
it?.isVisible == true
|
||||||
}
|
}
|
||||||
|
@ -532,6 +537,41 @@ class ResultFragmentTv : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
observeNullable(viewModel.favoriteStatus) { isFavorite ->
|
||||||
|
binding?.resultFavoriteButton?.apply {
|
||||||
|
isVisible = isFavorite != null
|
||||||
|
if (isFavorite == null) return@observeNullable
|
||||||
|
|
||||||
|
val drawable = if (isFavorite) {
|
||||||
|
R.drawable.ic_baseline_favorite_24
|
||||||
|
} else {
|
||||||
|
R.drawable.ic_baseline_favorite_border_24
|
||||||
|
}
|
||||||
|
|
||||||
|
val text = if (isFavorite) {
|
||||||
|
R.string.action_remove_from_favorites
|
||||||
|
} else {
|
||||||
|
R.string.action_add_to_favorites
|
||||||
|
}
|
||||||
|
|
||||||
|
setIconResource(drawable)
|
||||||
|
setText(text)
|
||||||
|
setOnClickListener {
|
||||||
|
val isFavorite = viewModel.toggleFavoriteStatus() ?: return@setOnClickListener
|
||||||
|
|
||||||
|
val message = if (isFavorite) {
|
||||||
|
R.string.favorite_added
|
||||||
|
} else {
|
||||||
|
R.string.favorite_removed
|
||||||
|
}
|
||||||
|
|
||||||
|
val name = (viewModel.page.value as? Resource.Success)?.value?.title
|
||||||
|
?: txt(R.string.no_data).asStringNull(context) ?: ""
|
||||||
|
CommonActivity.showToast(txt(message, name), Toast.LENGTH_SHORT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
observeNullable(viewModel.movie) { data ->
|
observeNullable(viewModel.movie) { data ->
|
||||||
binding?.apply {
|
binding?.apply {
|
||||||
resultPlayMovie.isVisible = data is Resource.Success
|
resultPlayMovie.isVisible = data is Resource.Success
|
||||||
|
|
|
@ -51,11 +51,14 @@ import com.lagradost.cloudstream3.utils.Coroutines.ioWork
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.ioWorkSafe
|
import com.lagradost.cloudstream3.utils.Coroutines.ioWorkSafe
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getDub
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getDub
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getFavoritesData
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultEpisode
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultEpisode
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultSeason
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultSeason
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultWatchState
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultWatchState
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.removeFavoritesData
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setDub
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.setDub
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.setFavoritesData
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultEpisode
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultEpisode
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
||||||
|
@ -425,6 +428,9 @@ class ResultViewModel2 : ViewModel() {
|
||||||
private val _subscribeStatus: MutableLiveData<Boolean?> = MutableLiveData(null)
|
private val _subscribeStatus: MutableLiveData<Boolean?> = MutableLiveData(null)
|
||||||
val subscribeStatus: LiveData<Boolean?> = _subscribeStatus
|
val subscribeStatus: LiveData<Boolean?> = _subscribeStatus
|
||||||
|
|
||||||
|
private val _favoriteStatus: MutableLiveData<Boolean?> = MutableLiveData(null)
|
||||||
|
val favoriteStatus: LiveData<Boolean?> = _favoriteStatus
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "RVM2"
|
const val TAG = "RVM2"
|
||||||
//private const val EPISODE_RANGE_SIZE = 20
|
//private const val EPISODE_RANGE_SIZE = 20
|
||||||
|
@ -868,6 +874,40 @@ class ResultViewModel2 : ViewModel() {
|
||||||
return !isSubscribed
|
return !isSubscribed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if added to favorites, false if not. Null if not possible to favorite.
|
||||||
|
**/
|
||||||
|
fun toggleFavoriteStatus(): Boolean? {
|
||||||
|
val isFavorite = _favoriteStatus.value ?: return null
|
||||||
|
val response = currentResponse ?: return null
|
||||||
|
|
||||||
|
val currentId = response.getId()
|
||||||
|
|
||||||
|
if (isFavorite) {
|
||||||
|
removeFavoritesData(currentId)
|
||||||
|
} else {
|
||||||
|
val current = getFavoritesData(currentId)
|
||||||
|
|
||||||
|
setFavoritesData(
|
||||||
|
currentId,
|
||||||
|
DataStoreHelper.FavoritesData(
|
||||||
|
currentId,
|
||||||
|
current?.favoritesTime ?: unixTimeMS,
|
||||||
|
unixTimeMS,
|
||||||
|
response.name,
|
||||||
|
response.url,
|
||||||
|
response.apiName,
|
||||||
|
response.type,
|
||||||
|
response.posterUrl,
|
||||||
|
response.year
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
_favoriteStatus.postValue(!isFavorite)
|
||||||
|
return !isFavorite
|
||||||
|
}
|
||||||
|
|
||||||
private fun startChromecast(
|
private fun startChromecast(
|
||||||
activity: Activity?,
|
activity: Activity?,
|
||||||
result: ResultEpisode,
|
result: ResultEpisode,
|
||||||
|
@ -1750,6 +1790,12 @@ class ResultViewModel2 : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun postFavorites(loadResponse: LoadResponse) {
|
||||||
|
val id = loadResponse.getId()
|
||||||
|
val isFavorite = getFavoritesData(id) != null
|
||||||
|
_favoriteStatus.postValue(isFavorite)
|
||||||
|
}
|
||||||
|
|
||||||
private fun postEpisodeRange(indexer: EpisodeIndexer?, range: EpisodeRange?) {
|
private fun postEpisodeRange(indexer: EpisodeIndexer?, range: EpisodeRange?) {
|
||||||
if (range == null || indexer == null) {
|
if (range == null || indexer == null) {
|
||||||
return
|
return
|
||||||
|
@ -1887,6 +1933,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
currentResponse = loadResponse
|
currentResponse = loadResponse
|
||||||
postPage(loadResponse, apiRepository)
|
postPage(loadResponse, apiRepository)
|
||||||
postSubscription(loadResponse)
|
postSubscription(loadResponse)
|
||||||
|
postFavorites(loadResponse)
|
||||||
if (updateEpisodes)
|
if (updateEpisodes)
|
||||||
postEpisodes(loadResponse, updateFillers)
|
postEpisodes(loadResponse, updateFillers)
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ const val VIDEO_WATCH_STATE = "video_watch_state"
|
||||||
const val RESULT_WATCH_STATE = "result_watch_state"
|
const val RESULT_WATCH_STATE = "result_watch_state"
|
||||||
const val RESULT_WATCH_STATE_DATA = "result_watch_state_data"
|
const val RESULT_WATCH_STATE_DATA = "result_watch_state_data"
|
||||||
const val RESULT_SUBSCRIBED_STATE_DATA = "result_subscribed_state_data"
|
const val RESULT_SUBSCRIBED_STATE_DATA = "result_subscribed_state_data"
|
||||||
|
const val RESULT_FAVORITES_STATE_DATA = "result_favorites_state_data"
|
||||||
const val RESULT_RESUME_WATCHING = "result_resume_watching_2" // changed due to id changes
|
const val RESULT_RESUME_WATCHING = "result_resume_watching_2" // changed due to id changes
|
||||||
const val RESULT_RESUME_WATCHING_OLD = "result_resume_watching"
|
const val RESULT_RESUME_WATCHING_OLD = "result_resume_watching"
|
||||||
const val RESULT_RESUME_WATCHING_HAS_MIGRATED = "result_resume_watching_migrated"
|
const val RESULT_RESUME_WATCHING_HAS_MIGRATED = "result_resume_watching_migrated"
|
||||||
|
@ -406,6 +407,33 @@ object DataStoreHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class FavoritesData(
|
||||||
|
@JsonProperty("id") override var id: Int?,
|
||||||
|
@JsonProperty("favoritesTime") val favoritesTime: Long,
|
||||||
|
@JsonProperty("latestUpdatedTime") val latestUpdatedTime: Long,
|
||||||
|
@JsonProperty("name") override val name: String,
|
||||||
|
@JsonProperty("url") override val url: String,
|
||||||
|
@JsonProperty("apiName") override val apiName: String,
|
||||||
|
@JsonProperty("type") override var type: TvType? = null,
|
||||||
|
@JsonProperty("posterUrl") override var posterUrl: String?,
|
||||||
|
@JsonProperty("year") val year: Int?,
|
||||||
|
@JsonProperty("quality") override var quality: SearchQuality? = null,
|
||||||
|
@JsonProperty("posterHeaders") override var posterHeaders: Map<String, String>? = null,
|
||||||
|
) : SearchResponse {
|
||||||
|
fun toLibraryItem(): SyncAPI.LibraryItem? {
|
||||||
|
return SyncAPI.LibraryItem(
|
||||||
|
name,
|
||||||
|
url,
|
||||||
|
id?.toString() ?: return null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
latestUpdatedTime,
|
||||||
|
apiName, type, posterUrl, posterHeaders, quality, this.id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data class ResumeWatchingResult(
|
data class ResumeWatchingResult(
|
||||||
@JsonProperty("name") override val name: String,
|
@JsonProperty("name") override val name: String,
|
||||||
@JsonProperty("url") override val url: String,
|
@JsonProperty("url") override val url: String,
|
||||||
|
@ -579,6 +607,29 @@ object DataStoreHelper {
|
||||||
return getKey("$currentAccount/$RESULT_SUBSCRIBED_STATE_DATA", id.toString())
|
return getKey("$currentAccount/$RESULT_SUBSCRIBED_STATE_DATA", id.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getAllFavorites(): List<FavoritesData> {
|
||||||
|
return getKeys("$currentAccount/$RESULT_FAVORITES_STATE_DATA")?.mapNotNull {
|
||||||
|
getKey(it)
|
||||||
|
} ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeFavoritesData(id: Int?) {
|
||||||
|
if (id == null) return
|
||||||
|
AccountManager.localListApi.requireLibraryRefresh = true
|
||||||
|
removeKey("$currentAccount/$RESULT_FAVORITES_STATE_DATA", id.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setFavoritesData(id: Int?, data: FavoritesData) {
|
||||||
|
if (id == null) return
|
||||||
|
setKey("$currentAccount/$RESULT_FAVORITES_STATE_DATA", id.toString(), data)
|
||||||
|
AccountManager.localListApi.requireLibraryRefresh = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFavoritesData(id: Int?): FavoritesData? {
|
||||||
|
if (id == null) return null
|
||||||
|
return getKey("$currentAccount/$RESULT_FAVORITES_STATE_DATA", id.toString())
|
||||||
|
}
|
||||||
|
|
||||||
fun setViewPos(id: Int?, pos: Long, dur: Long) {
|
fun setViewPos(id: Int?, pos: Long, dur: Long) {
|
||||||
if (id == null) return
|
if (id == null) return
|
||||||
if (dur < 30_000) return // too short
|
if (dur < 30_000) return // too short
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
android:nextFocusUp="@id/result_back"
|
android:nextFocusUp="@id/result_back"
|
||||||
android:nextFocusDown="@id/result_description"
|
android:nextFocusDown="@id/result_description"
|
||||||
android:nextFocusLeft="@id/result_add_sync"
|
android:nextFocusLeft="@id/result_add_sync"
|
||||||
android:nextFocusRight="@id/result_share"
|
android:nextFocusRight="@id/result_favorite"
|
||||||
|
|
||||||
tools:visibility="visible"
|
tools:visibility="visible"
|
||||||
|
|
||||||
|
@ -89,10 +89,27 @@
|
||||||
android:layout_gravity="end|center_vertical"
|
android:layout_gravity="end|center_vertical"
|
||||||
app:tint="?attr/textColor" />
|
app:tint="?attr/textColor" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:nextFocusUp="@id/result_back"
|
||||||
|
android:nextFocusDown="@id/result_description"
|
||||||
|
android:nextFocusLeft="@id/result_subscribe"
|
||||||
|
android:nextFocusRight="@id/result_share"
|
||||||
|
|
||||||
|
android:id="@+id/result_favorite"
|
||||||
|
android:layout_width="25dp"
|
||||||
|
android:layout_height="25dp"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:elevation="10dp"
|
||||||
|
|
||||||
|
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||||
|
android:src="@drawable/ic_baseline_favorite_border_24"
|
||||||
|
android:layout_gravity="end|center_vertical"
|
||||||
|
app:tint="?attr/textColor" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:nextFocusUp="@id/result_back"
|
android:nextFocusUp="@id/result_back"
|
||||||
android:nextFocusDown="@id/result_description"
|
android:nextFocusDown="@id/result_description"
|
||||||
android:nextFocusLeft="@id/result_subscribe"
|
android:nextFocusLeft="@id/result_favorite"
|
||||||
android:nextFocusRight="@id/result_open_in_browser"
|
android:nextFocusRight="@id/result_open_in_browser"
|
||||||
|
|
||||||
android:id="@+id/result_share"
|
android:id="@+id/result_share"
|
||||||
|
|
|
@ -313,19 +313,30 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
||||||
style="@style/ResultButtonTV"
|
style="@style/ResultButtonTV"
|
||||||
android:nextFocusRight="@id/result_description"
|
android:nextFocusRight="@id/result_description"
|
||||||
android:nextFocusUp="@id/result_play_trailer"
|
android:nextFocusUp="@id/result_play_trailer"
|
||||||
android:nextFocusDown="@id/result_episodes_show"
|
android:nextFocusDown="@id/result_favorite_button"
|
||||||
|
|
||||||
android:text="@string/type_none"
|
android:text="@string/type_none"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
app:icon="@drawable/ic_baseline_bookmark_24" />
|
app:icon="@drawable/ic_baseline_bookmark_24" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/result_favorite_button"
|
||||||
|
style="@style/ResultButtonTV"
|
||||||
|
android:nextFocusRight="@id/result_description"
|
||||||
|
android:nextFocusUp="@id/result_bookmark_button"
|
||||||
|
android:nextFocusDown="@id/result_episodes_show"
|
||||||
|
|
||||||
|
android:text="@string/action_add_to_favorites"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:icon="@drawable/ic_baseline_favorite_border_24" />
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/result_episodes_show"
|
android:id="@+id/result_episodes_show"
|
||||||
style="@style/ResultButtonTV"
|
style="@style/ResultButtonTV"
|
||||||
|
|
||||||
android:nextFocusRight="@id/redirect_to_episodes"
|
android:nextFocusRight="@id/redirect_to_episodes"
|
||||||
android:nextFocusUp="@id/result_bookmark_button"
|
android:nextFocusUp="@id/result_favorite_button"
|
||||||
android:nextFocusDown="@id/result_cast_items"
|
android:nextFocusDown="@id/result_cast_items"
|
||||||
|
|
||||||
android:text="@string/episodes"
|
android:text="@string/episodes"
|
||||||
|
|
|
@ -690,4 +690,9 @@
|
||||||
|
|
||||||
<string name="tv_no_focus_tag" translatable="false">tv_no_focus_tag</string>
|
<string name="tv_no_focus_tag" translatable="false">tv_no_focus_tag</string>
|
||||||
<string name="already_voted">You have already voted</string>
|
<string name="already_voted">You have already voted</string>
|
||||||
|
<string name="favorites_list_name">Favorites</string>
|
||||||
|
<string name="favorite_added">%s added to favorites</string>
|
||||||
|
<string name="favorite_removed">%s removed from favorites</string>
|
||||||
|
<string name="action_add_to_favorites">Add to favorites</string>
|
||||||
|
<string name="action_remove_from_favorites">Remove from favorites</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue