AquaStream/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt

437 lines
18 KiB
Kotlin
Raw Normal View History

2021-04-30 17:20:15 +00:00
package com.lagradost.cloudstream3.ui.home
2021-07-29 13:39:57 +00:00
import android.annotation.SuppressLint
2021-08-12 00:04:58 +00:00
import android.app.Activity
2021-07-29 15:16:08 +00:00
import android.content.Intent
2021-07-29 01:46:10 +00:00
import android.content.res.Configuration
2021-07-29 15:16:08 +00:00
import android.net.Uri
2021-04-30 17:20:15 +00:00
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
2021-07-29 13:39:57 +00:00
import android.widget.FrameLayout
2021-07-29 01:46:10 +00:00
import android.widget.TextView
import androidx.core.view.isVisible
2021-04-30 17:20:15 +00:00
import androidx.fragment.app.Fragment
2021-11-05 21:39:56 +00:00
import androidx.fragment.app.activityViewModels
import androidx.preference.PreferenceManager
2021-07-29 00:19:42 +00:00
import androidx.recyclerview.widget.GridLayoutManager
2021-10-22 13:23:48 +00:00
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSnapHelper
2021-07-29 00:19:42 +00:00
import androidx.recyclerview.widget.RecyclerView
2021-07-29 01:46:10 +00:00
import com.google.android.material.bottomsheet.BottomSheetDialog
2021-07-30 23:41:54 +00:00
import com.lagradost.cloudstream3.*
2021-07-29 15:16:08 +00:00
import com.lagradost.cloudstream3.APIHolder.apis
2021-10-22 13:23:48 +00:00
import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
2021-07-29 00:19:42 +00:00
import com.lagradost.cloudstream3.mvvm.Resource
2021-10-10 22:25:49 +00:00
import com.lagradost.cloudstream3.mvvm.logError
2021-07-29 00:19:42 +00:00
import com.lagradost.cloudstream3.mvvm.observe
2021-11-12 16:55:54 +00:00
import com.lagradost.cloudstream3.syncproviders.OAuth2API
2021-09-05 11:56:25 +00:00
import com.lagradost.cloudstream3.ui.APIRepository.Companion.noneApi
import com.lagradost.cloudstream3.ui.APIRepository.Companion.randomApi
2021-07-29 01:46:10 +00:00
import com.lagradost.cloudstream3.ui.AutofitRecyclerView
2021-07-30 23:41:54 +00:00
import com.lagradost.cloudstream3.ui.WatchType
2021-07-29 15:16:08 +00:00
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
2021-08-25 15:28:25 +00:00
import com.lagradost.cloudstream3.ui.search.*
2021-09-12 14:10:22 +00:00
import com.lagradost.cloudstream3.ui.search.SearchFragment.Companion.filterSearchResponse
2021-07-30 23:41:54 +00:00
import com.lagradost.cloudstream3.ui.search.SearchHelper.handleSearchClickCallback
import com.lagradost.cloudstream3.utils.AppUtils
import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult
2021-07-29 00:19:42 +00:00
import com.lagradost.cloudstream3.utils.DataStore.getKey
import com.lagradost.cloudstream3.utils.DataStore.setKey
2021-08-25 15:28:25 +00:00
import com.lagradost.cloudstream3.utils.DataStoreHelper
import com.lagradost.cloudstream3.utils.DataStoreHelper.removeLastWatched
2021-07-30 23:41:54 +00:00
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState
2021-07-29 01:46:10 +00:00
import com.lagradost.cloudstream3.utils.Event
2021-07-29 00:19:42 +00:00
import com.lagradost.cloudstream3.utils.HOMEPAGE_API
2021-08-19 20:05:18 +00:00
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
2021-10-22 13:23:48 +00:00
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbarView
2021-08-19 20:05:18 +00:00
import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact
2021-07-30 23:41:54 +00:00
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons
2021-08-19 20:05:18 +00:00
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes
2021-11-07 22:10:19 +00:00
import com.lagradost.cloudstream3.utils.UIHelper.setImage
2021-10-22 13:23:48 +00:00
import com.lagradost.cloudstream3.widget.CenterZoomLayoutManager
2021-07-29 00:19:42 +00:00
import kotlinx.android.synthetic.main.fragment_home.*
2021-04-30 17:20:15 +00:00
2021-07-30 23:41:54 +00:00
const val HOME_BOOKMARK_VALUE = "home_bookmarked_last"
2021-04-30 17:20:15 +00:00
class HomeFragment : Fragment() {
2021-08-12 00:04:58 +00:00
companion object {
val configEvent = Event<Int>()
var currentSpan = 1
fun Activity.loadHomepageList(item: HomePageList) {
val context = this
val bottomSheetDialogBuilder = BottomSheetDialog(context)
bottomSheetDialogBuilder.setContentView(R.layout.home_episodes_expanded)
val title = bottomSheetDialogBuilder.findViewById<TextView>(R.id.home_expanded_text)!!
title.text = item.name
val recycle = bottomSheetDialogBuilder.findViewById<AutofitRecyclerView>(R.id.home_expanded_recycler)!!
val titleHolder = bottomSheetDialogBuilder.findViewById<FrameLayout>(R.id.home_expanded_drag_down)!!
titleHolder.setOnClickListener {
bottomSheetDialogBuilder.dismiss()
}
// Span settings
recycle.spanCount = currentSpan
recycle.adapter = SearchAdapter(item.list, recycle) { callback ->
handleSearchClickCallback(this, callback)
2021-08-25 15:28:25 +00:00
if (callback.action == SEARCH_ACTION_LOAD || callback.action == SEARCH_ACTION_PLAY_FILE) {
2021-08-12 00:04:58 +00:00
bottomSheetDialogBuilder.dismiss()
}
}
val spanListener = { span: Int ->
recycle.spanCount = span
(recycle.adapter as SearchAdapter).notifyDataSetChanged()
}
configEvent += spanListener
bottomSheetDialogBuilder.setOnDismissListener {
configEvent -= spanListener
}
(recycle.adapter as SearchAdapter).notifyDataSetChanged()
bottomSheetDialogBuilder.show()
}
}
2021-11-05 21:39:56 +00:00
private val homeViewModel: HomeViewModel by activityViewModels()
2021-04-30 17:20:15 +00:00
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
2021-11-05 21:39:56 +00:00
//homeViewModel =
// ViewModelProvider(this).get(HomeViewModel::class.java)
2021-07-29 00:19:42 +00:00
return inflater.inflate(R.layout.fragment_home, container, false)
}
2021-07-29 13:39:57 +00:00
private var currentHomePage: HomePageResponse? = null
private fun toggleMainVisibility(visible: Boolean) {
home_main_holder.isVisible = visible
2021-07-29 13:39:57 +00:00
}
2021-07-29 01:46:10 +00:00
private fun fixGrid() {
val compactView = activity?.getGridIsCompact() ?: false
val spanCountLandscape = if (compactView) 2 else 6
val spanCountPortrait = if (compactView) 1 else 3
val orientation = resources.configuration.orientation
currentSpan = if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
spanCountLandscape
} else {
spanCountPortrait
}
configEvent.invoke(currentSpan)
}
2021-07-29 15:16:08 +00:00
private val apiChangeClickListener = View.OnClickListener { view ->
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
val currentPrefMedia = settingsManager.getInt(getString(R.string.preferred_media_settings), 0)
val validAPIs = AppUtils.filterProviderByPreferredMedia(apis, currentPrefMedia).toMutableList()
2021-09-05 11:56:25 +00:00
validAPIs.add(0, randomApi)
validAPIs.add(0, noneApi)
2021-07-29 15:16:08 +00:00
view.popupMenuNoIconsAndNoStringRes(validAPIs.mapIndexed { index, api -> Pair(index, api.name) }) {
homeViewModel.loadAndCancel(validAPIs[itemId].name, currentPrefMedia)
2021-07-29 15:16:08 +00:00
}
}
2021-07-29 01:46:10 +00:00
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
fixGrid()
}
2021-07-30 23:41:54 +00:00
override fun onResume() {
super.onResume()
2021-09-25 13:00:59 +00:00
reloadStored()
2021-07-30 23:41:54 +00:00
}
2021-09-25 13:00:59 +00:00
/*
2021-07-30 23:41:54 +00:00
override fun onStop() {
backEvent -= ::handleBack
super.onStop()
2021-09-25 13:00:59 +00:00
}*/
2021-07-30 23:41:54 +00:00
private fun reloadStored() {
context?.let { ctx ->
2021-08-25 15:28:25 +00:00
homeViewModel.loadResumeWatching(ctx)
2021-07-30 23:41:54 +00:00
homeViewModel.loadStoredData(ctx, WatchType.fromInternalId(ctx.getKey(HOME_BOOKMARK_VALUE)))
}
}
2021-09-25 13:00:59 +00:00
/*private fun handleBack(poppedFragment: Boolean) {
2021-07-30 23:41:54 +00:00
if (poppedFragment) {
reloadStored()
}
2021-09-25 13:00:59 +00:00
}*/
2021-07-30 23:41:54 +00:00
2021-10-22 13:23:48 +00:00
@SuppressLint("SetTextI18n")
2021-07-29 00:19:42 +00:00
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
2021-07-29 01:46:10 +00:00
fixGrid()
2021-07-29 00:19:42 +00:00
2021-07-29 15:16:08 +00:00
home_change_api.setOnClickListener(apiChangeClickListener)
2021-08-25 15:28:25 +00:00
home_change_api_loading.setOnClickListener(apiChangeClickListener)
2021-07-29 15:16:08 +00:00
2021-10-22 13:23:48 +00:00
observe(homeViewModel.apiName) { apiName ->
context?.setKey(HOMEPAGE_API, apiName)
home_provider_name?.text = apiName
home_provider_meta_info?.isVisible = false
getApiFromNameNull(apiName)?.let { currentApi ->
val typeChoices = listOf(
Pair(R.string.movies, listOf(TvType.Movie)),
Pair(R.string.tv_series, listOf(TvType.TvSeries)),
Pair(R.string.cartoons, listOf(TvType.Cartoon)),
Pair(R.string.anime, listOf(TvType.Anime, TvType.ONA, TvType.AnimeMovie)),
Pair(R.string.torrent, listOf(TvType.Torrent)),
).filter { item -> currentApi.supportedTypes.any { type -> item.second.contains(type) } }
2021-10-27 19:45:15 +00:00
home_provider_meta_info?.text = typeChoices.joinToString(separator = ", ") { getString(it.first) }
2021-10-22 13:23:48 +00:00
home_provider_meta_info?.isVisible = true
}
2021-07-29 00:19:42 +00:00
}
observe(homeViewModel.randomItems) { items ->
if (items.isNullOrEmpty()) {
toggleMainVisibility(false)
} else {
val tempAdapter = home_main_poster_recyclerview.adapter as HomeChildItemAdapter?
// no need to reload if it has the same data
if (tempAdapter != null && tempAdapter.cardList == items) {
toggleMainVisibility(true)
return@observe
}
val randomSize = items.size
home_main_poster_recyclerview.adapter =
HomeChildItemAdapter(items, R.layout.home_result_big_grid) { callback ->
handleSearchClickCallback(activity, callback)
}
home_main_poster_recyclerview.post {
(home_main_poster_recyclerview.layoutManager as CenterZoomLayoutManager?)?.let { manager ->
manager.updateSize(forceUpdate = true)
if (randomSize > 2) {
manager.scrollToPosition(randomSize / 2)
manager.snap { dx ->
home_main_poster_recyclerview?.post {
// this is the best I can do, fuck android for not including instant scroll
home_main_poster_recyclerview?.smoothScrollBy(dx, 0)
}
}
}
}
}
toggleMainVisibility(true)
}
}
2021-07-29 15:16:08 +00:00
observe(homeViewModel.page) { data ->
when (data) {
2021-07-29 00:19:42 +00:00
is Resource.Success -> {
2021-07-29 15:16:08 +00:00
val d = data.value
2021-09-12 14:10:22 +00:00
2021-07-29 13:39:57 +00:00
currentHomePage = d
2021-09-12 14:10:22 +00:00
(home_master_recycler?.adapter as ParentItemAdapter?)?.items =
2021-10-10 22:25:49 +00:00
d.items.mapNotNull {
try {
HomePageList(it.name, it.list.filterSearchResponse())
2021-10-22 13:23:48 +00:00
} catch (e: Exception) {
2021-10-10 22:25:49 +00:00
logError(e)
null
}
}
2021-09-12 14:10:22 +00:00
2021-07-29 00:19:42 +00:00
home_master_recycler?.adapter?.notifyDataSetChanged()
2021-07-29 15:16:08 +00:00
home_loading.visibility = View.GONE
home_loading_error.visibility = View.GONE
home_loaded.visibility = View.VISIBLE
2021-07-29 00:19:42 +00:00
}
is Resource.Failure -> {
2021-07-29 15:16:08 +00:00
result_error_text.text = data.errorString
home_reload_connectionerror.setOnClickListener(apiChangeClickListener)
home_reload_connection_open_in_browser.setOnClickListener { view ->
val validAPIs = apis//.filter { api -> api.hasMainPage }
view.popupMenuNoIconsAndNoStringRes(validAPIs.mapIndexed { index, api ->
Pair(
index,
api.name
)
}) {
val i = Intent(Intent.ACTION_VIEW)
i.data = Uri.parse(validAPIs[itemId].mainUrl)
startActivity(i)
}
}
2021-07-29 00:19:42 +00:00
2021-07-29 15:16:08 +00:00
home_loading.visibility = View.GONE
home_loading_error.visibility = View.VISIBLE
home_loaded.visibility = View.GONE
2021-07-29 00:19:42 +00:00
}
is Resource.Loading -> {
2021-07-29 15:16:08 +00:00
home_loading.visibility = View.VISIBLE
home_loading_error.visibility = View.GONE
home_loaded.visibility = View.GONE
2021-07-29 00:19:42 +00:00
}
}
}
2021-07-30 23:41:54 +00:00
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> = ParentItemAdapter(listOf(), { callback ->
handleSearchClickCallback(activity, callback)
}, { item ->
2021-08-12 00:04:58 +00:00
activity?.loadHomepageList(item)
2021-07-29 00:54:27 +00:00
})
2021-07-30 23:41:54 +00:00
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.isVisible = bookmarks.isNotEmpty()
2021-07-30 23:41:54 +00:00
(home_bookmarked_child_recyclerview?.adapter as HomeChildItemAdapter?)?.cardList = bookmarks
home_bookmarked_child_recyclerview?.adapter?.notifyDataSetChanged()
home_bookmarked_child_more_info.setOnClickListener {
2021-08-12 00:04:58 +00:00
activity?.loadHomepageList(
2021-07-30 23:41:54 +00:00
HomePageList(
home_bookmarked_parent_item_title?.text?.toString() ?: getString(R.string.error_bookmarks_text),
bookmarks
)
)
}
}
2021-08-25 15:28:25 +00:00
observe(homeViewModel.resumeWatching) { resumeWatching ->
home_watch_holder?.isVisible = resumeWatching.isNotEmpty()
2021-08-25 15:28:25 +00:00
(home_watch_child_recyclerview?.adapter as HomeChildItemAdapter?)?.cardList = resumeWatching
home_watch_child_recyclerview?.adapter?.notifyDataSetChanged()
home_watch_child_more_info?.setOnClickListener {
2021-08-25 15:28:25 +00:00
activity?.loadHomepageList(
HomePageList(
home_watch_parent_item_title?.text?.toString() ?: getString(R.string.continue_watching),
resumeWatching
)
)
}
}
2021-07-30 23:41:54 +00:00
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)
}
}
2021-08-25 15:28:25 +00:00
home_watch_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(1, R.string.action_open_watching),
Pair(0, R.string.action_remove_watching)
)
) {
if (itemId == 1) {
handleSearchClickCallback(
activity,
SearchClickCallback(SEARCH_ACTION_LOAD, callback.view, callback.card)
)
reloadStored()
}
if (itemId == 0) {
2021-09-05 11:56:25 +00:00
val card = callback.card
if (card is DataStoreHelper.ResumeWatchingResult) {
2021-08-25 15:28:25 +00:00
context?.removeLastWatched(card.parentId)
reloadStored()
}
}
}
}
} else {
handleSearchClickCallback(activity, callback)
}
}
2021-10-22 13:23:48 +00:00
context?.fixPaddingStatusbarView(home_statusbar)
context?.fixPaddingStatusbar(home_loading_statusbar)
2021-07-29 00:19:42 +00:00
home_master_recycler.adapter = adapter
home_master_recycler.layoutManager = GridLayoutManager(context, 1)
2021-10-22 13:23:48 +00:00
LinearSnapHelper().attachToRecyclerView(home_main_poster_recyclerview) // snap
val centerLayoutManager = CenterZoomLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
centerLayoutManager.setOnSizeListener { index ->
(home_main_poster_recyclerview.adapter as HomeChildItemAdapter?)?.cardList?.get(index)?.let { random ->
home_main_play.setOnClickListener {
activity.loadSearchResult(random, START_ACTION_RESUME_LATEST)
}
home_main_info.setOnClickListener {
activity.loadSearchResult(random)
}
home_main_text.text =
random.name + if (random is AnimeSearchResponse && !random.dubStatus.isNullOrEmpty()) {
random.dubStatus.joinToString(prefix = "", separator = " | ") { it.name }
} else ""
}
}
home_main_poster_recyclerview.layoutManager = centerLayoutManager // scale
2021-07-30 23:41:54 +00:00
reloadStored()
2021-09-20 21:11:36 +00:00
val apiName = context?.getKey<String>(HOMEPAGE_API)
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
val currentPrefMedia = settingsManager.getInt(getString(R.string.preferred_media_settings), 0)
2021-10-22 13:23:48 +00:00
if (homeViewModel.apiName.value != apiName || apiName == null) {
//println("Caught home: " + homeViewModel.apiName.value + " at " + apiName)
homeViewModel.loadAndCancel(apiName, currentPrefMedia)
2021-09-20 21:11:36 +00:00
}
2021-11-07 22:10:19 +00:00
// nice profile pic on homepage
home_profile_picture_holder?.isVisible = false
context?.let { ctx ->
2021-11-12 16:55:54 +00:00
for (syncApi in OAuth2API.OAuth2Apis) {
2021-11-07 22:10:19 +00:00
val login = syncApi.loginInfo(ctx)
val pic = login?.profilePicture
if (pic != null) {
2021-11-07 22:10:19 +00:00
home_profile_picture.setImage(pic)
home_profile_picture_holder.isVisible = true
break
}
}
}
2021-04-30 17:20:15 +00:00
}
}