forked from recloudstream/cloudstream
bookmarks working
This commit is contained in:
parent
a467060486
commit
5523d6539a
14 changed files with 233 additions and 84 deletions
|
@ -13,8 +13,8 @@ android {
|
|||
applicationId "com.lagradost.cloudstream3"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
versionCode 8
|
||||
versionName "1.1.6"
|
||||
versionCode 9
|
||||
versionName "1.1.7"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ object APIHolder {
|
|||
}
|
||||
|
||||
fun LoadResponse.getId(): Int {
|
||||
return url.replace(getApiFromName(apiName).mainUrl, "").hashCode()
|
||||
return url.replace(getApiFromName(apiName).mainUrl, "").replace("/", "").hashCode()
|
||||
}
|
||||
|
||||
fun Activity.getApiSettings(): HashSet<String> {
|
||||
|
@ -86,7 +86,7 @@ abstract class MainAPI {
|
|||
open val hasMainPage = false
|
||||
open val hasQuickSearch = false
|
||||
|
||||
open fun getMainPage() : HomePageResponse? {
|
||||
open fun getMainPage(): HomePageResponse? {
|
||||
return null
|
||||
}
|
||||
|
||||
|
@ -189,6 +189,7 @@ interface SearchResponse {
|
|||
val type: TvType
|
||||
val posterUrl: String?
|
||||
val year: Int?
|
||||
val id: Int?
|
||||
}
|
||||
|
||||
data class AnimeSearchResponse(
|
||||
|
@ -204,6 +205,7 @@ data class AnimeSearchResponse(
|
|||
val dubStatus: EnumSet<DubStatus>?,
|
||||
val dubEpisodes: Int?,
|
||||
val subEpisodes: Int?,
|
||||
override val id: Int? = null,
|
||||
) : SearchResponse
|
||||
|
||||
data class MovieSearchResponse(
|
||||
|
@ -214,6 +216,7 @@ data class MovieSearchResponse(
|
|||
|
||||
override val posterUrl: String?,
|
||||
override val year: Int?,
|
||||
override val id: Int? = null,
|
||||
) : SearchResponse
|
||||
|
||||
data class TvSeriesSearchResponse(
|
||||
|
@ -225,6 +228,7 @@ data class TvSeriesSearchResponse(
|
|||
override val posterUrl: String?,
|
||||
override val year: Int?,
|
||||
val episodes: Int?,
|
||||
override val id: Int? = null,
|
||||
) : SearchResponse
|
||||
|
||||
interface LoadResponse {
|
||||
|
|
|
@ -13,7 +13,6 @@ import androidx.navigation.NavOptions
|
|||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import com.google.android.gms.cast.framework.CastButtonFactory
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.lagradost.cloudstream3.APIHolder.apis
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.checkWrite
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.getResourceColor
|
||||
|
@ -31,6 +30,7 @@ import com.lagradost.cloudstream3.utils.AppUtils.loadResult
|
|||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||
import com.lagradost.cloudstream3.utils.DataStore.removeKey
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos
|
||||
import com.lagradost.cloudstream3.utils.Event
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.fragment_result.*
|
||||
|
||||
|
@ -59,6 +59,8 @@ class MainActivity : AppCompatActivity() {
|
|||
var isInPlayer: Boolean = false
|
||||
var canShowPipMode: Boolean = false
|
||||
var isInPIPMode: Boolean = false
|
||||
|
||||
val backEvent = Event<Boolean>()
|
||||
lateinit var navOptions: NavOptions
|
||||
}
|
||||
|
||||
|
@ -110,8 +112,10 @@ class MainActivity : AppCompatActivity() {
|
|||
.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit)
|
||||
.remove(currentFragment)
|
||||
.commitAllowingStateLoss()
|
||||
backEvent.invoke(true)
|
||||
return true
|
||||
}
|
||||
backEvent.invoke(false)
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -10,11 +10,14 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_LOAD
|
||||
import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_SHOW_METADATA
|
||||
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
|
||||
import kotlinx.android.synthetic.main.home_result_grid.view.*
|
||||
|
||||
class HomeChildItemAdapter(
|
||||
var cardList: List<Any>,
|
||||
private val clickCallback: (SearchResponse) -> Unit
|
||||
var cardList: List<SearchResponse>,
|
||||
private val clickCallback: (SearchClickCallback) -> Unit
|
||||
) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
|
@ -38,7 +41,7 @@ class HomeChildItemAdapter(
|
|||
}
|
||||
|
||||
class CardViewHolder
|
||||
constructor(itemView: View, private val clickCallback: (SearchResponse) -> Unit) :
|
||||
constructor(itemView: View, private val clickCallback: (SearchClickCallback) -> Unit) :
|
||||
RecyclerView.ViewHolder(itemView) {
|
||||
val cardView: ImageView = itemView.imageView
|
||||
private val cardText: TextView = itemView.imageText
|
||||
|
@ -52,9 +55,7 @@ class HomeChildItemAdapter(
|
|||
//val imageTextProvider: TextView? = itemView.imageTextProvider
|
||||
private val bg: CardView = itemView.backgroundCard
|
||||
|
||||
fun bind(card: Any) {
|
||||
if (card is SearchResponse) { // GENERIC
|
||||
|
||||
fun bind(card: SearchResponse) {
|
||||
textType?.text = when (card.type) {
|
||||
TvType.Anime -> "Anime"
|
||||
TvType.Movie -> "Movie"
|
||||
|
@ -81,8 +82,12 @@ class HomeChildItemAdapter(
|
|||
}
|
||||
|
||||
bg.setOnClickListener {
|
||||
clickCallback.invoke(card)
|
||||
// (activity as AppCompatActivity).loadResult(card.url, card.slug, card.apiName)
|
||||
clickCallback.invoke(SearchClickCallback(SEARCH_ACTION_LOAD, it, card))
|
||||
}
|
||||
|
||||
bg.setOnLongClickListener {
|
||||
clickCallback.invoke(SearchClickCallback(SEARCH_ACTION_SHOW_METADATA, it, card))
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
|
||||
when (card) {
|
||||
|
@ -101,5 +106,4 @@ class HomeChildItemAdapter(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,26 +17,33 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.APIHolder.apis
|
||||
import com.lagradost.cloudstream3.AnimeSearchResponse
|
||||
import com.lagradost.cloudstream3.HomePageResponse
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.SearchResponse
|
||||
import com.lagradost.cloudstream3.MainActivity.Companion.backEvent
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes
|
||||
import com.lagradost.cloudstream3.mvvm.Resource
|
||||
import com.lagradost.cloudstream3.mvvm.observe
|
||||
import com.lagradost.cloudstream3.ui.AutofitRecyclerView
|
||||
import com.lagradost.cloudstream3.ui.WatchType
|
||||
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
|
||||
import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_LOAD
|
||||
import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_SHOW_METADATA
|
||||
import com.lagradost.cloudstream3.ui.search.SearchAdapter
|
||||
import com.lagradost.cloudstream3.ui.search.SearchHelper.handleSearchClickCallback
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||
import com.lagradost.cloudstream3.utils.DataStore.removeKey
|
||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState
|
||||
import com.lagradost.cloudstream3.utils.Event
|
||||
import com.lagradost.cloudstream3.utils.HOMEPAGE_API
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons
|
||||
import kotlinx.android.synthetic.main.fragment_home.*
|
||||
|
||||
const val HOME_BOOKMARK_VALUE = "home_bookmarked_last"
|
||||
|
||||
class HomeFragment : Fragment() {
|
||||
private lateinit var homeViewModel: HomeViewModel
|
||||
|
||||
|
@ -142,6 +149,28 @@ class HomeFragment : Fragment() {
|
|||
fixGrid()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
backEvent += ::handleBack
|
||||
super.onResume()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
backEvent -= ::handleBack
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
private fun reloadStored() {
|
||||
context?.let { ctx ->
|
||||
homeViewModel.loadStoredData(ctx, WatchType.fromInternalId(ctx.getKey(HOME_BOOKMARK_VALUE)))
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleBack(poppedFragment: Boolean) {
|
||||
if (poppedFragment) {
|
||||
reloadStored()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
fixGrid()
|
||||
|
@ -225,9 +254,7 @@ class HomeFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> = ParentItemAdapter(listOf(), { card ->
|
||||
activity.loadSearchResult(card)
|
||||
}, { item ->
|
||||
fun loadHomepageList(item: HomePageList) {
|
||||
val bottomSheetDialogBuilder = BottomSheetDialog(view.context)
|
||||
bottomSheetDialogBuilder.setContentView(R.layout.home_episodes_expanded)
|
||||
val title = bottomSheetDialogBuilder.findViewById<TextView>(R.id.home_expanded_text)!!
|
||||
|
@ -242,9 +269,11 @@ class HomeFragment : Fragment() {
|
|||
// Span settings
|
||||
recycle.spanCount = currentSpan
|
||||
|
||||
recycle.adapter = SearchAdapter(item.list, recycle) { card ->
|
||||
recycle.adapter = SearchAdapter(item.list, recycle) { callback ->
|
||||
handleSearchClickCallback(activity, callback)
|
||||
if (callback.action == SEARCH_ACTION_LOAD) {
|
||||
bottomSheetDialogBuilder.dismiss()
|
||||
activity.loadSearchResult(card)
|
||||
}
|
||||
}
|
||||
|
||||
val spanListener = { span: Int ->
|
||||
|
@ -261,13 +290,66 @@ class HomeFragment : Fragment() {
|
|||
(recycle.adapter as SearchAdapter).notifyDataSetChanged()
|
||||
|
||||
bottomSheetDialogBuilder.show()
|
||||
}
|
||||
|
||||
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> = ParentItemAdapter(listOf(), { callback ->
|
||||
handleSearchClickCallback(activity, callback)
|
||||
}, { item ->
|
||||
loadHomepageList(item)
|
||||
})
|
||||
|
||||
observe(homeViewModel.availableWatchStatusTypes) { availableWatchStatusTypes ->
|
||||
context?.setKey(HOME_BOOKMARK_VALUE, availableWatchStatusTypes.first.internalId)
|
||||
home_bookmark_select?.setOnClickListener {
|
||||
it.popupMenuNoIcons(availableWatchStatusTypes.second.map { type ->
|
||||
Pair(
|
||||
type.internalId,
|
||||
type.stringRes
|
||||
)
|
||||
}) {
|
||||
homeViewModel.loadStoredData(it.context, WatchType.fromInternalId(this.itemId))
|
||||
}
|
||||
}
|
||||
home_bookmarked_parent_item_title?.text = getString(availableWatchStatusTypes.first.stringRes)
|
||||
}
|
||||
|
||||
observe(homeViewModel.bookmarks) { bookmarks ->
|
||||
home_bookmarked_holder.visibility = if (bookmarks.isNotEmpty()) View.VISIBLE else View.GONE
|
||||
(home_bookmarked_child_recyclerview?.adapter as HomeChildItemAdapter?)?.cardList = bookmarks
|
||||
home_bookmarked_child_recyclerview?.adapter?.notifyDataSetChanged()
|
||||
|
||||
home_bookmarked_child_more_info.setOnClickListener {
|
||||
loadHomepageList(
|
||||
HomePageList(
|
||||
home_bookmarked_parent_item_title?.text?.toString() ?: getString(R.string.error_bookmarks_text),
|
||||
bookmarks
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
home_bookmarked_child_recyclerview.adapter = HomeChildItemAdapter(ArrayList()) { callback ->
|
||||
if (callback.action == SEARCH_ACTION_SHOW_METADATA) {
|
||||
val id = callback.card.id
|
||||
if (id != null) {
|
||||
callback.view.popupMenuNoIcons(listOf(Pair(0, R.string.action_remove_from_bookmarks))) {
|
||||
if (itemId == 0) {
|
||||
activity?.setResultWatchState(id, WatchType.NONE.internalId)
|
||||
reloadStored()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handleSearchClickCallback(activity, callback)
|
||||
}
|
||||
}
|
||||
|
||||
context?.fixPaddingStatusbar(home_root)
|
||||
|
||||
home_master_recycler.adapter = adapter
|
||||
home_master_recycler.layoutManager = GridLayoutManager(context, 1)
|
||||
|
||||
reloadStored()
|
||||
homeViewModel.load(context?.getKey<String>(HOMEPAGE_API))
|
||||
}
|
||||
}
|
|
@ -9,11 +9,12 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import com.lagradost.cloudstream3.HomePageList
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.SearchResponse
|
||||
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
|
||||
import kotlinx.android.synthetic.main.homepage_parent.view.*
|
||||
|
||||
class ParentItemAdapter(
|
||||
var items: List<HomePageList>,
|
||||
private val clickCallback: (SearchResponse) -> Unit,
|
||||
private val clickCallback: (SearchClickCallback) -> Unit,
|
||||
private val moreInfoClickCallback: (HomePageList) -> Unit,
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, i: Int): ParentViewHolder {
|
||||
|
@ -38,7 +39,7 @@ class ParentItemAdapter(
|
|||
class ParentViewHolder
|
||||
constructor(
|
||||
itemView: View,
|
||||
private val clickCallback: (SearchResponse) -> Unit,
|
||||
private val clickCallback: (SearchClickCallback) -> Unit,
|
||||
private val moreInfoClickCallback: (HomePageList) -> Unit
|
||||
) :
|
||||
RecyclerView.ViewHolder(itemView) {
|
||||
|
|
|
@ -33,15 +33,17 @@ class HomeViewModel : ViewModel() {
|
|||
return APIRepository(apis.first { it.hasMainPage })
|
||||
}
|
||||
|
||||
private val availableWatchStatusTypes = MutableLiveData<Pair<WatchType, List<WatchType>>>()
|
||||
private val bookmarks = MutableLiveData<List<SearchResponse>>()
|
||||
private val _availableWatchStatusTypes = MutableLiveData<Pair<WatchType, List<WatchType>>>()
|
||||
val availableWatchStatusTypes: LiveData<Pair<WatchType, List<WatchType>>> = _availableWatchStatusTypes
|
||||
private val _bookmarks = MutableLiveData<List<SearchResponse>>()
|
||||
val bookmarks: LiveData<List<SearchResponse>> = _bookmarks
|
||||
|
||||
fun loadStoredData(context: Context, preferredWatchStatus: WatchType?) = viewModelScope.launch {
|
||||
val watchStatusIds = withContext(Dispatchers.IO) {
|
||||
context.getAllWatchStateIds().map { id ->
|
||||
Pair(id, context.getResultWatchState(id))
|
||||
}
|
||||
}
|
||||
}.distinctBy { it.first }
|
||||
val length = WatchType.values().size
|
||||
val currentWatchTypes = HashSet<WatchType>()
|
||||
|
||||
|
@ -52,21 +54,28 @@ class HomeViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
currentWatchTypes.remove(WatchType.NONE)
|
||||
|
||||
if (currentWatchTypes.size <= 0) {
|
||||
bookmarks.postValue(ArrayList())
|
||||
_bookmarks.postValue(ArrayList())
|
||||
return@launch
|
||||
}
|
||||
|
||||
val watchStatus = preferredWatchStatus ?: currentWatchTypes.first()
|
||||
availableWatchStatusTypes.postValue(
|
||||
val watchPrefNotNull = preferredWatchStatus ?: currentWatchTypes.first()
|
||||
val watchStatus =
|
||||
if (currentWatchTypes.contains(watchPrefNotNull)) watchPrefNotNull else currentWatchTypes.first()
|
||||
_availableWatchStatusTypes.postValue(
|
||||
Pair(
|
||||
watchStatus,
|
||||
currentWatchTypes.sortedBy { it.internalId }.toList()
|
||||
)
|
||||
)
|
||||
val list = withContext(Dispatchers.IO) {
|
||||
watchStatusIds.map { context.getBookmarkedData(it.first) }
|
||||
watchStatusIds.filter { it.second == watchStatus }
|
||||
.mapNotNull { context.getBookmarkedData(it.first) }
|
||||
.sortedBy { -it.latestUpdatedTime }
|
||||
}
|
||||
_bookmarks.postValue(list)
|
||||
}
|
||||
|
||||
fun load(api: MainAPI?) = viewModelScope.launch {
|
||||
|
|
|
@ -117,7 +117,7 @@ class EpisodeAdapter(
|
|||
class EpisodeCardViewHolder
|
||||
constructor(
|
||||
itemView: View,
|
||||
val hasDownloadSupport: Boolean,
|
||||
private val hasDownloadSupport: Boolean,
|
||||
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||
private val downloadClickCallback: (DownloadClickEvent) -> Unit,
|
||||
) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder {
|
||||
|
@ -129,8 +129,8 @@ class EpisodeAdapter(
|
|||
private val episodeProgress: ContentLoadingProgressBar? = itemView.episode_progress
|
||||
private val episodePoster: ImageView? = itemView.episode_poster
|
||||
|
||||
val episodeDownloadBar: ContentLoadingProgressBar = itemView.result_episode_progress_downloaded
|
||||
val episodeDownloadImage: ImageView = itemView.result_episode_download
|
||||
private val episodeDownloadBar: ContentLoadingProgressBar = itemView.result_episode_progress_downloaded
|
||||
private val episodeDownloadImage: ImageView = itemView.result_episode_download
|
||||
|
||||
private val episodeHolder = itemView.episode_holder
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.lagradost.cloudstream3.ui.search
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -24,12 +25,16 @@ import kotlinx.android.synthetic.main.search_result_compact.view.imageView
|
|||
import kotlinx.android.synthetic.main.search_result_grid.view.*
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
const val SEARCH_ACTION_LOAD = 0
|
||||
const val SEARCH_ACTION_SHOW_METADATA = 1
|
||||
|
||||
class SearchClickCallback(val action: Int, val view: View, val card: SearchResponse)
|
||||
|
||||
class SearchAdapter(
|
||||
var cardList: List<SearchResponse>,
|
||||
private val resView: AutofitRecyclerView,
|
||||
private val clickCallback: (SearchResponse) -> Unit,
|
||||
) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
private val clickCallback: (SearchClickCallback) -> Unit,
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
val layout = parent.context.getGridFormatId()
|
||||
|
@ -54,7 +59,11 @@ class SearchAdapter(
|
|||
}
|
||||
|
||||
class CardViewHolder
|
||||
constructor(itemView: View, private val clickCallback: (SearchResponse) -> Unit, resView: AutofitRecyclerView) :
|
||||
constructor(
|
||||
itemView: View,
|
||||
private val clickCallback: (SearchClickCallback) -> Unit,
|
||||
resView: AutofitRecyclerView
|
||||
) :
|
||||
RecyclerView.ViewHolder(itemView) {
|
||||
val cardView: ImageView = itemView.imageView
|
||||
private val cardText: TextView = itemView.imageText
|
||||
|
@ -105,7 +114,12 @@ class SearchAdapter(
|
|||
}
|
||||
|
||||
bg.setOnClickListener {
|
||||
clickCallback.invoke(card)
|
||||
clickCallback.invoke(SearchClickCallback(SEARCH_ACTION_LOAD, it, card))
|
||||
}
|
||||
|
||||
bg.setOnLongClickListener {
|
||||
clickCallback.invoke(SearchClickCallback(SEARCH_ACTION_SHOW_METADATA, it, card))
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
|
||||
when (card) {
|
||||
|
@ -121,7 +135,6 @@ class SearchAdapter(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import android.view.ViewGroup
|
|||
import android.view.WindowManager
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.ImageView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -24,11 +23,9 @@ import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
|||
import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact
|
||||
import com.lagradost.cloudstream3.mvvm.Resource
|
||||
import com.lagradost.cloudstream3.mvvm.observe
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult
|
||||
import kotlinx.android.synthetic.main.fragment_search.*
|
||||
|
||||
class SearchFragment : Fragment() {
|
||||
|
||||
private lateinit var searchViewModel: SearchViewModel
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -77,8 +74,8 @@ class SearchFragment : Fragment() {
|
|||
SearchAdapter(
|
||||
ArrayList(),
|
||||
cardSpace,
|
||||
) { card ->
|
||||
activity.loadSearchResult(card)
|
||||
) { callback ->
|
||||
SearchHelper.handleSearchClickCallback(activity, callback)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package com.lagradost.cloudstream3.ui.search
|
||||
|
||||
import android.app.Activity
|
||||
import android.widget.Toast
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult
|
||||
|
||||
object SearchHelper {
|
||||
fun handleSearchClickCallback(activity: Activity?, callback: SearchClickCallback) {
|
||||
val card = callback.card
|
||||
when (callback.action) {
|
||||
SEARCH_ACTION_LOAD -> {
|
||||
activity.loadSearchResult(card)
|
||||
}
|
||||
SEARCH_ACTION_SHOW_METADATA -> {
|
||||
activity?.let { act ->
|
||||
Toast.makeText(act, callback.card.name, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import com.lagradost.cloudstream3.TvType
|
|||
import com.lagradost.cloudstream3.ui.WatchType
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
||||
import com.lagradost.cloudstream3.utils.DataStore.removeKey
|
||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||
|
||||
const val VIDEO_POS_DUR = "video_pos_dur"
|
||||
|
@ -27,9 +28,9 @@ object DataStoreHelper {
|
|||
}
|
||||
|
||||
data class BookmarkedData(
|
||||
val parentId: Int,
|
||||
val bookmarkedTime : Long,
|
||||
val latestUpdatedTime : Long,
|
||||
override val id: Int?,
|
||||
val bookmarkedTime: Long,
|
||||
val latestUpdatedTime: Long,
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
override val apiName: String,
|
||||
|
@ -42,17 +43,19 @@ object DataStoreHelper {
|
|||
|
||||
fun Context.getAllWatchStateIds(): List<Int> {
|
||||
val folder = "$currentAccount/$RESULT_WATCH_STATE"
|
||||
return getKeys(folder).mapNotNull { it.removePrefix(folder).toIntOrNull() }
|
||||
return getKeys(folder).mapNotNull {
|
||||
it.removePrefix("$folder/").toIntOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.setBookmarkedData(id: Int?, data: BookmarkedData) {
|
||||
if (id == null) return
|
||||
setKey("$currentAccount/$RESULT_WATCH_STATE", id.toString(), data)
|
||||
setKey("$currentAccount/$RESULT_WATCH_STATE_DATA", id.toString(), data)
|
||||
}
|
||||
|
||||
fun Context.getBookmarkedData(id: Int?): BookmarkedData? {
|
||||
if (id == null) return null
|
||||
return getKey("$currentAccount/$RESULT_WATCH_STATE", id.toString())
|
||||
return getKey("$currentAccount/$RESULT_WATCH_STATE_DATA", id.toString())
|
||||
}
|
||||
|
||||
fun Context.setViewPos(id: Int?, pos: Long, dur: Long) {
|
||||
|
@ -66,7 +69,13 @@ object DataStoreHelper {
|
|||
|
||||
fun Context.setResultWatchState(id: Int?, status: Int) {
|
||||
if (id == null) return
|
||||
setKey("$currentAccount/$RESULT_WATCH_STATE", id.toString(), status)
|
||||
val folder = "$currentAccount/$RESULT_WATCH_STATE"
|
||||
if (status == WatchType.NONE.internalId) {
|
||||
removeKey(folder, id.toString())
|
||||
removeKey("$currentAccount/$RESULT_WATCH_STATE_DATA", id.toString())
|
||||
} else {
|
||||
setKey(folder, id.toString(), status)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getResultWatchState(id: Int): WatchType {
|
||||
|
|
|
@ -207,6 +207,8 @@
|
|||
<LinearLayout
|
||||
android:id="@+id/home_bookmarked_holder"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
|
@ -217,6 +219,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:id="@+id/home_bookmark_select"
|
||||
android:src="@drawable/ic_baseline_filter_list_24"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
|
@ -232,7 +235,7 @@
|
|||
android:gravity="center_vertical"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:text="Bookmarked"
|
||||
tools:text="Bookmarked"
|
||||
/>
|
||||
<ImageView
|
||||
android:layout_marginEnd="5dp"
|
||||
|
|
|
@ -64,4 +64,6 @@
|
|||
<string name="background_blur">Background blur</string>
|
||||
<string name="background_shadow">Background Shadow</string>
|
||||
<string name="filter_bookmarks">Filter Bookmarks</string>
|
||||
<string name="error_bookmarks_text">Bookmarks</string>
|
||||
<string name="action_remove_from_bookmarks">Remove</string>
|
||||
</resources>
|
Loading…
Reference in a new issue