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-12-26 00:05:10 +00:00
import android.content.Context
2022-07-29 15:51:28 +00:00
import android.content.DialogInterface
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
2022-12-09 17:20:10 +00:00
import android.os.Build
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-12-26 00:05:10 +00:00
import android.widget.*
2022-07-29 15:51:28 +00:00
import androidx.appcompat.app.AlertDialog
2022-07-25 01:18:27 +00:00
import androidx.core.view.isGone
2021-09-03 22:46:29 +00:00
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
2023-01-06 16:51:34 +00:00
import androidx.lifecycle.*
2022-04-18 17:55:21 +00:00
import androidx.preference.PreferenceManager
2022-07-30 15:30:23 +00:00
import androidx.recyclerview.widget.RecyclerView
2022-10-14 18:18:32 +00:00
import com.google.android.material.bottomsheet.BottomSheetBehavior
2021-07-29 01:46:10 +00:00
import com.google.android.material.bottomsheet.BottomSheetDialog
2021-12-26 00:05:10 +00:00
import com.google.android.material.button.MaterialButton
2022-10-28 01:51:27 +00:00
import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup
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-12-16 23:45:20 +00:00
import com.lagradost.cloudstream3.APIHolder.filterProviderByPreferredMedia
2022-04-06 15:16:08 +00:00
import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings
2021-12-16 23:45:20 +00:00
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
2023-07-14 19:43:46 +00:00
import com.lagradost.cloudstream3.CommonActivity.showToast
2022-08-14 21:34:47 +00:00
import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent
2023-01-21 22:22:48 +00:00
import com.lagradost.cloudstream3.MainActivity.Companion.bookmarksUpdatedEvent
2022-08-21 01:44:49 +00:00
import com.lagradost.cloudstream3.MainActivity.Companion.mainPluginsLoadedEvent
2023-07-13 21:18:37 +00:00
import com.lagradost.cloudstream3.databinding.FragmentHomeBinding
import com.lagradost.cloudstream3.databinding.HomeEpisodesExpandedBinding
import com.lagradost.cloudstream3.databinding.HomeSelectMainpageBinding
import com.lagradost.cloudstream3.databinding.TvtypesChipsBinding
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
2023-07-17 01:32:41 +00:00
import com.lagradost.cloudstream3.mvvm.observeNullable
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-30 23:41:54 +00:00
import com.lagradost.cloudstream3.ui.WatchType
2022-04-25 18:00:25 +00:00
import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment
2023-07-14 19:43:46 +00:00
import com.lagradost.cloudstream3.ui.result.txt
2021-08-25 15:28:25 +00:00
import com.lagradost.cloudstream3.ui.search.*
2021-07-30 23:41:54 +00:00
import com.lagradost.cloudstream3.ui.search.SearchHelper.handleSearchClickCallback
2022-02-18 19:29:48 +00:00
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
2021-11-28 12:18:01 +00:00
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
2022-12-09 17:20:10 +00:00
import com.lagradost.cloudstream3.utils.AppUtils.addProgramsToContinueWatching
2022-08-02 16:26:16 +00:00
import com.lagradost.cloudstream3.utils.AppUtils.isRecyclerScrollable
2022-10-28 01:51:27 +00:00
import com.lagradost.cloudstream3.utils.AppUtils.loadResult
2021-07-30 01:14:53 +00:00
import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult
2023-01-06 16:51:34 +00:00
import com.lagradost.cloudstream3.utils.AppUtils.ownHide
import com.lagradost.cloudstream3.utils.AppUtils.ownShow
2023-01-20 00:16:05 +00:00
import com.lagradost.cloudstream3.utils.AppUtils.setDefaultFocus
2022-07-30 15:30:23 +00:00
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
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
2021-07-29 01:46:10 +00:00
import com.lagradost.cloudstream3.utils.Event
2022-04-06 15:16:08 +00:00
import com.lagradost.cloudstream3.utils.SubtitleHelper.getFlagFromIso
2021-12-12 02:33:17 +00:00
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
2021-08-19 20:05:18 +00:00
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
2021-12-13 18:41:33 +00:00
import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount
2021-08-19 20:05:18 +00:00
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes
2022-08-21 01:44:49 +00:00
import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API
2023-07-13 21:18:37 +00:00
2021-12-09 21:20:27 +00:00
import java.util.*
2021-04-30 17:20:15 +00:00
2022-10-28 16:43:14 +00:00
2021-12-09 21:20:27 +00:00
const val HOME _BOOKMARK _VALUE _LIST = " home_bookmarked_last_list "
2021-12-26 00:05:10 +00:00
const val HOME _PREF _HOMEPAGE = " home_pref_homepage "
2021-07-30 23:41:54 +00:00
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
2022-04-18 17:55:21 +00:00
val listHomepageItems = mutableListOf < SearchResponse > ( )
2021-08-12 00:04:58 +00:00
2022-04-26 13:52:30 +00:00
private val errorProfilePics = listOf (
R . drawable . monke _benene ,
R . drawable . monke _burrito ,
R . drawable . monke _coco ,
R . drawable . monke _cookie ,
R . drawable . monke _flusdered ,
R . drawable . monke _funny ,
R . drawable . monke _like ,
R . drawable . monke _party ,
R . drawable . monke _sob ,
R . drawable . monke _drink ,
)
val errorProfilePic = errorProfilePics . random ( )
2023-01-06 16:51:34 +00:00
//fun Activity.loadHomepageList(
// item: HomePageList,
// deleteCallback: (() -> Unit)? = null,
//) {
// loadHomepageList(
// expand = HomeViewModel.ExpandableHomepageList(item, 1, false),
// deleteCallback = deleteCallback,
// expandCallback = null
// )
//}
// returns a BottomSheetDialog that will be hidden with OwnHidden upon hide, and must be saved to be able call ownShow in onCreateView
2022-07-30 15:30:23 +00:00
fun Activity . loadHomepageList (
expand : HomeViewModel . ExpandableHomepageList ,
deleteCallback : ( ( ) -> Unit ) ? = null ,
2023-01-06 16:51:34 +00:00
expandCallback : ( suspend ( String ) -> HomeViewModel . ExpandableHomepageList ? ) ? = null ,
2023-07-13 21:18:37 +00:00
dismissCallback : ( ( ) -> Unit ) ,
2023-01-06 16:51:34 +00:00
) : BottomSheetDialog {
2021-08-12 00:04:58 +00:00
val context = this
val bottomSheetDialogBuilder = BottomSheetDialog ( context )
2023-07-13 21:18:37 +00:00
val binding : HomeEpisodesExpandedBinding = HomeEpisodesExpandedBinding . inflate (
bottomSheetDialogBuilder . layoutInflater ,
null ,
false
)
bottomSheetDialogBuilder . setContentView ( binding . root )
//val title = bottomSheetDialogBuilder.findViewById<TextView>(R.id.home_expanded_text)!!
2023-01-06 16:51:34 +00:00
//title.findViewTreeLifecycleOwner().lifecycle.addObserver()
2022-07-30 15:30:23 +00:00
val item = expand . list
2023-07-13 21:18:37 +00:00
binding . homeExpandedText . text = item . name
// val recycle =
// bottomSheetDialogBuilder.findViewById<AutofitRecyclerView>(R.id.home_expanded_recycler)!!
//val titleHolder =
// bottomSheetDialogBuilder.findViewById<FrameLayout>(R.id.home_expanded_drag_down)!!
2021-08-12 00:04:58 +00:00
2023-01-06 16:51:34 +00:00
// main {
//(bottomSheetDialogBuilder.ownerActivity as androidx.fragment.app.FragmentActivity?)?.supportFragmentManager?.fragments?.lastOrNull()?.viewLifecycleOwner?.apply {
// println("GOT LIFE: lifecycle $this")
// this.lifecycle.addObserver(object : DefaultLifecycleObserver {
// override fun onResume(owner: LifecycleOwner) {
// super.onResume(owner)
// println("onResume!!!!")
// bottomSheetDialogBuilder?.ownShow()
// }
// override fun onStop(owner: LifecycleOwner) {
// super.onStop(owner)
// bottomSheetDialogBuilder?.ownHide()
// }
// })
//}
// }
2023-07-13 21:18:37 +00:00
//val delete = bottomSheetDialogBuilder.home_expanded_delete
binding . homeExpandedDelete . isGone = deleteCallback == null
2022-07-29 15:51:28 +00:00
if ( deleteCallback != null ) {
2023-07-13 21:18:37 +00:00
binding . homeExpandedDelete . setOnClickListener {
2022-07-29 15:51:28 +00:00
try {
val builder : AlertDialog . Builder = AlertDialog . Builder ( context )
val dialogClickListener =
DialogInterface . OnClickListener { _ , which ->
when ( which ) {
DialogInterface . BUTTON _POSITIVE -> {
deleteCallback . invoke ( )
bottomSheetDialogBuilder . dismissSafe ( this )
}
2023-07-13 21:18:37 +00:00
2022-07-29 15:51:28 +00:00
DialogInterface . BUTTON _NEGATIVE -> { }
}
}
builder . setTitle ( R . string . delete _file )
. setMessage (
context . getString ( R . string . delete _message ) . format (
item . name
)
)
. setPositiveButton ( R . string . delete , dialogClickListener )
. setNegativeButton ( R . string . cancel , dialogClickListener )
2023-01-20 00:16:05 +00:00
. show ( ) . setDefaultFocus ( )
2022-07-29 15:51:28 +00:00
} catch ( e : Exception ) {
logError ( e )
// ye you somehow fucked up formatting did you?
}
}
}
2023-07-13 21:18:37 +00:00
binding . homeExpandedDragDown . setOnClickListener {
2021-12-12 02:33:17 +00:00
bottomSheetDialogBuilder . dismissSafe ( this )
2021-08-12 00:04:58 +00:00
}
2022-07-29 15:51:28 +00:00
2021-08-12 00:04:58 +00:00
// Span settings
2023-07-13 21:18:37 +00:00
binding . homeExpandedRecycler . spanCount = currentSpan
binding . homeExpandedRecycler . adapter =
SearchAdapter ( item . list . toMutableList ( ) , binding . homeExpandedRecycler ) { callback ->
2023-07-17 01:32:41 +00:00
handleSearchClickCallback ( callback )
2023-07-13 21:18:37 +00:00
if ( callback . action == SEARCH _ACTION _LOAD || callback . action == SEARCH _ACTION _PLAY _FILE ) {
bottomSheetDialogBuilder . ownHide ( ) // we hide here because we want to resume it later
//bottomSheetDialogBuilder.dismissSafe(this)
}
} . apply {
hasNext = expand . hasNext
2021-08-12 00:04:58 +00:00
}
2023-07-13 21:18:37 +00:00
binding . homeExpandedRecycler . addOnScrollListener ( object :
RecyclerView . OnScrollListener ( ) {
2022-07-30 15:30:23 +00:00
var expandCount = 0
val name = expand . list . name
override fun onScrollStateChanged ( recyclerView : RecyclerView , newState : Int ) {
super . onScrollStateChanged ( recyclerView , newState )
val adapter = recyclerView . adapter
if ( adapter !is SearchAdapter ) return
val count = adapter . itemCount
val currentHasNext = adapter . hasNext
2022-08-02 16:26:16 +00:00
//!recyclerView.canScrollVertically(1)
if ( ! recyclerView . isRecyclerScrollable ( ) && currentHasNext && expandCount != count ) {
2022-07-30 15:30:23 +00:00
expandCount = count
ioSafe {
expandCallback ?. invoke ( name ) ?. let { newExpand ->
( recyclerView . adapter as ? SearchAdapter ? ) ?. apply {
hasNext = newExpand . hasNext
updateList ( newExpand . list . list )
}
}
}
}
}
} )
2021-08-12 00:04:58 +00:00
val spanListener = { span : Int ->
2023-07-13 21:18:37 +00:00
binding . homeExpandedRecycler . spanCount = span
2022-02-13 00:53:40 +00:00
//(recycle.adapter as SearchAdapter).notifyDataSetChanged()
2021-08-12 00:04:58 +00:00
}
configEvent += spanListener
bottomSheetDialogBuilder . setOnDismissListener {
2023-01-06 16:51:34 +00:00
dismissCallback . invoke ( )
2021-08-12 00:04:58 +00:00
configEvent -= spanListener
}
2022-02-13 00:53:40 +00:00
//(recycle.adapter as SearchAdapter).notifyDataSetChanged()
2021-08-12 00:04:58 +00:00
bottomSheetDialogBuilder . show ( )
2023-01-06 16:51:34 +00:00
return bottomSheetDialogBuilder
2021-08-12 00:04:58 +00:00
}
2021-12-26 00:05:10 +00:00
2022-01-29 21:25:12 +00:00
fun getPairList (
2022-10-28 01:51:27 +00:00
anime : Chip ? ,
cartoons : Chip ? ,
tvs : Chip ? ,
docs : Chip ? ,
movies : Chip ? ,
asian : Chip ? ,
livestream : Chip ? ,
nsfw : Chip ? ,
others : Chip ? ,
) : List < Pair < Chip ? , List < TvType > > > {
2022-09-24 22:50:14 +00:00
// This list should be same order as home screen to aid navigation
2022-01-29 21:25:12 +00:00
return listOf (
2022-09-24 22:50:14 +00:00
Pair ( movies , listOf ( TvType . Movie , TvType . Torrent ) ) ,
Pair ( tvs , listOf ( TvType . TvSeries ) ) ,
2022-01-31 20:47:59 +00:00
Pair ( anime , listOf ( TvType . Anime , TvType . OVA , TvType . AnimeMovie ) ) ,
2022-09-24 22:50:14 +00:00
Pair ( asian , listOf ( TvType . AsianDrama ) ) ,
2022-01-29 21:25:12 +00:00
Pair ( cartoons , listOf ( TvType . Cartoon ) ) ,
Pair ( docs , listOf ( TvType . Documentary ) ) ,
2022-07-19 20:24:55 +00:00
Pair ( livestream , listOf ( TvType . Live ) ) ,
2022-08-14 14:00:10 +00:00
Pair ( nsfw , listOf ( TvType . NSFW ) ) ,
2022-08-14 11:49:14 +00:00
Pair ( others , listOf ( TvType . Others ) ) ,
2022-01-29 21:25:12 +00:00
)
}
2023-07-13 21:18:37 +00:00
private fun getPairList ( header : TvtypesChipsBinding ) = getPairList (
header . homeSelectAnime ,
header . homeSelectCartoons ,
header . homeSelectTvSeries ,
header . homeSelectDocumentaries ,
header . homeSelectMovies ,
header . homeSelectAsian ,
header . homeSelectLivestreams ,
header . homeSelectNsfw ,
header . homeSelectOthers
2022-10-28 01:51:27 +00:00
)
2023-07-13 21:18:37 +00:00
fun validateChips ( header : TvtypesChipsBinding ? , validTypes : List < TvType > ) {
2022-10-28 01:51:27 +00:00
if ( header == null ) return
val pairList = getPairList ( header )
for ( ( button , types ) in pairList ) {
val isValid = validTypes . any { types . contains ( it ) }
button ?. isVisible = isValid
}
}
2023-07-13 21:18:37 +00:00
fun updateChips ( header : TvtypesChipsBinding ? , selectedTypes : List < TvType > ) {
2022-10-28 01:51:27 +00:00
if ( header == null ) return
val pairList = getPairList ( header )
for ( ( button , types ) in pairList ) {
button ?. isChecked =
button ?. isVisible == true && selectedTypes . any { types . contains ( it ) }
}
}
fun bindChips (
2023-07-13 21:18:37 +00:00
header : TvtypesChipsBinding ? ,
2022-10-28 01:51:27 +00:00
selectedTypes : List < TvType > ,
validTypes : List < TvType > ,
callback : ( List < TvType > ) -> Unit
2023-08-04 03:37:41 +00:00
) {
bindChips ( header , selectedTypes , validTypes , callback , null , null )
}
fun bindChips (
header : TvtypesChipsBinding ? ,
selectedTypes : List < TvType > ,
validTypes : List < TvType > ,
callback : ( List < TvType > ) -> Unit ,
nextFocusDown : Int ? ,
nextFocusUp : Int ?
2022-10-28 01:51:27 +00:00
) {
if ( header == null ) return
val pairList = getPairList ( header )
for ( ( button , types ) in pairList ) {
val isValid = validTypes . any { types . contains ( it ) }
button ?. isVisible = isValid
button ?. isChecked = isValid && selectedTypes . any { types . contains ( it ) }
2023-08-04 03:37:41 +00:00
button ?. isFocusable = true
if ( isTrueTvSettings ( ) ) {
button ?. isFocusableInTouchMode = true
}
if ( nextFocusDown != null )
button ?. nextFocusDownId = nextFocusDown
if ( nextFocusUp != null )
button ?. nextFocusUpId = nextFocusUp
2022-10-28 01:51:27 +00:00
button ?. setOnCheckedChangeListener { _ , _ ->
val list = ArrayList < TvType > ( )
for ( ( sbutton , vvalidTypes ) in pairList ) {
if ( sbutton ?. isChecked == true )
list . addAll ( vvalidTypes )
}
callback ( list )
}
}
}
2021-12-26 00:05:10 +00:00
fun Context . selectHomepage ( selectedApiName : String ? , callback : ( String ) -> Unit ) {
val validAPIs = filterProviderByPreferredMedia ( ) . toMutableList ( )
validAPIs . add ( 0 , randomApi )
validAPIs . add ( 0 , noneApi )
//val builder: AlertDialog.Builder = AlertDialog.Builder(this)
//builder.setView(R.layout.home_select_mainpage)
val builder =
BottomSheetDialog ( this )
2022-10-14 18:18:32 +00:00
builder . behavior . state = BottomSheetBehavior . STATE _EXPANDED
2023-07-13 21:18:37 +00:00
val binding : HomeSelectMainpageBinding = HomeSelectMainpageBinding . inflate (
builder . layoutInflater ,
null ,
false
)
builder . setContentView ( binding . root )
2021-12-26 00:05:10 +00:00
builder . show ( )
builder . let { dialog ->
2022-10-31 21:09:56 +00:00
val isMultiLang = getApiProviderLangSettings ( ) . let { set ->
set . size > 1 || set . contains ( AllLanguagesName )
}
2021-12-26 00:05:10 +00:00
//dialog.window?.setGravity(Gravity.BOTTOM)
var currentApiName = selectedApiName
var currentValidApis : MutableList < MainAPI > = mutableListOf ( )
val preSelectedTypes = this . getKey < List < String > > ( HOME _PREF _HOMEPAGE )
2022-01-24 20:39:22 +00:00
?. mapNotNull { listName -> TvType . values ( ) . firstOrNull { it . name == listName } }
?. toMutableList ( )
2021-12-26 00:05:10 +00:00
?: mutableListOf ( TvType . Movie , TvType . TvSeries )
2023-07-18 20:18:14 +00:00
binding . cancelBtt . setOnClickListener {
2021-12-26 00:05:10 +00:00
dialog . dismissSafe ( )
}
2023-07-18 20:18:14 +00:00
binding . applyBtt . setOnClickListener {
2021-12-26 00:05:10 +00:00
if ( currentApiName != selectedApiName ) {
currentApiName ?. let ( callback )
}
dialog . dismissSafe ( )
}
val listView = dialog . findViewById < ListView > ( R . id . listview1 )
val arrayAdapter = ArrayAdapter < String > ( this , R . layout . sort _bottom _single _choice )
listView ?. adapter = arrayAdapter
listView ?. choiceMode = AbsListView . CHOICE _MODE _SINGLE
listView ?. setOnItemClickListener { _ , _ , i , _ ->
2022-06-02 22:51:41 +00:00
if ( currentValidApis . isNotEmpty ( ) ) {
2021-12-26 00:05:10 +00:00
currentApiName = currentValidApis [ i ] . name
//to switch to apply simply remove this
currentApiName ?. let ( callback )
dialog . dismissSafe ( )
}
}
fun updateList ( ) {
this . setKey ( HOME _PREF _HOMEPAGE , preSelectedTypes )
arrayAdapter . clear ( )
currentValidApis = validAPIs . filter { api ->
api . hasMainPage && api . supportedTypes . any {
preSelectedTypes . contains ( it )
}
2022-04-06 15:16:08 +00:00
} . sortedBy { it . name . lowercase ( ) } . toMutableList ( )
2021-12-26 00:05:10 +00:00
currentValidApis . addAll ( 0 , validAPIs . subList ( 0 , 2 ) )
2022-04-25 18:00:25 +00:00
val names =
currentValidApis . map { if ( isMultiLang ) " ${getFlagFromIso(it.lang)?.plus(" ") ?: ""} ${it.name} " else it . name }
2022-04-08 22:13:09 +00:00
val index = currentValidApis . map { it . name } . indexOf ( currentApiName )
2021-12-26 00:05:10 +00:00
listView ?. setItemChecked ( index , true )
arrayAdapter . addAll ( names )
arrayAdapter . notifyDataSetChanged ( )
}
2022-10-28 01:51:27 +00:00
bindChips (
2023-07-13 21:18:37 +00:00
binding . tvtypesChipsScroll . tvtypesChips ,
2022-10-28 01:51:27 +00:00
preSelectedTypes ,
validAPIs . flatMap { it . supportedTypes } . distinct ( )
) { list ->
preSelectedTypes . clear ( )
preSelectedTypes . addAll ( list )
updateList ( )
2021-12-26 00:05:10 +00:00
}
updateList ( )
}
}
2021-08-12 00:04:58 +00:00
}
2021-11-05 21:39:56 +00:00
private val homeViewModel : HomeViewModel by activityViewModels ( )
2021-04-30 17:20:15 +00:00
2023-07-13 21:18:37 +00:00
var binding : FragmentHomeBinding ? = null
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 =
2021-11-09 21:15:11 +00:00
// ViewModelProvider(this).get(HomeViewModel::class.java)
2023-07-14 19:43:46 +00:00
2023-01-06 16:51:34 +00:00
bottomSheetDialog ?. ownShow ( )
2022-01-24 20:39:22 +00:00
val layout =
2022-08-28 23:52:15 +00:00
if ( isTvSettings ( ) ) R . layout . fragment _home _tv else R . layout . fragment _home
2023-07-13 21:18:37 +00:00
val root = inflater . inflate ( layout , container , false )
2023-07-14 19:43:46 +00:00
binding = try {
FragmentHomeBinding . bind ( root )
2023-07-17 01:32:41 +00:00
} catch ( t : Throwable ) {
showToast ( txt ( R . string . unable _to _inflate , t . message ?: " " ) , Toast . LENGTH _LONG )
2023-07-14 19:43:46 +00:00
logError ( t )
null
}
2023-07-13 21:18:37 +00:00
2023-07-14 19:43:46 +00:00
return root
2021-07-29 00:19:42 +00:00
}
2023-01-21 22:22:48 +00:00
override fun onDestroyView ( ) {
bottomSheetDialog ?. ownHide ( )
2023-07-13 21:18:37 +00:00
binding = null
2023-01-21 22:22:48 +00:00
super . onDestroyView ( )
}
2021-07-29 01:46:10 +00:00
private fun fixGrid ( ) {
2021-12-13 18:41:33 +00:00
activity ?. getSpanCount ( ) ?. let {
currentSpan = it
2021-07-29 01:46:10 +00:00
}
configEvent . invoke ( currentSpan )
}
2021-07-29 15:16:08 +00:00
private val apiChangeClickListener = View . OnClickListener { view ->
2021-12-26 00:05:10 +00:00
view . context . selectHomepage ( currentApiName ) { api ->
2023-08-04 03:37:41 +00:00
homeViewModel . loadAndCancel ( api , forceReload = true , fromUI = true )
2021-12-26 00:05:10 +00:00
}
/ * val validAPIs = view . context ?. filterProviderByPreferredMedia ( ) ?. toMutableList ( ) ?: mutableListOf ( )
2021-10-31 17:51:39 +00:00
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 ) } ) {
2021-12-16 23:45:20 +00:00
homeViewModel . loadAndCancel ( validAPIs [ itemId ] . name )
2021-12-26 00:05:10 +00:00
} * /
2021-07-29 15:16:08 +00:00
}
2021-07-29 01:46:10 +00:00
override fun onConfigurationChanged ( newConfig : Configuration ) {
super . onConfigurationChanged ( newConfig )
2022-12-28 11:51:55 +00:00
//(home_preview_viewpager?.adapter as? HomeScrollAdapter)?.notifyDataSetChanged()
2021-07-29 01:46:10 +00:00
fixGrid ( )
}
2022-01-24 20:39:22 +00:00
private var currentApiName : String ? = null
2022-04-18 17:55:21 +00:00
private var toggleRandomButton = false
2021-12-26 00:05:10 +00:00
2023-01-06 16:51:34 +00:00
private var bottomSheetDialog : BottomSheetDialog ? = null
2023-07-13 21:18:37 +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
2023-07-18 20:18:14 +00:00
binding ?. apply {
homeChangeApiLoading . setOnClickListener ( apiChangeClickListener )
//homeChangeApiLoading.setOnClickListener(apiChangeClickListener)
homeApiFab . setOnClickListener ( apiChangeClickListener )
homeRandom . setOnClickListener {
if ( listHomepageItems . isNotEmpty ( ) ) {
activity . loadSearchResult ( listHomepageItems . random ( ) )
}
}
homeMasterRecycler . adapter =
HomeParentItemAdapterPreview (
mutableListOf ( ) ,
homeViewModel
)
fixPaddingStatusbar ( homeLoadingStatusbar )
if ( isTvSettings ( ) ) {
homeApiFab . isVisible = false
if ( isTrueTvSettings ( ) ) {
homeChangeApiLoading . isVisible = true
homeChangeApiLoading . isFocusable = true
homeChangeApiLoading . isFocusableInTouchMode = true
}
// home_bookmark_select?.isFocusable = true
// home_bookmark_select?.isFocusableInTouchMode = true
} else {
homeApiFab . isVisible = true
homeChangeApiLoading . isVisible = false
2022-04-18 17:55:21 +00:00
}
2023-07-18 20:18:14 +00:00
homeMasterRecycler . addOnScrollListener ( object : RecyclerView . OnScrollListener ( ) {
override fun onScrolled ( recyclerView : RecyclerView , dx : Int , dy : Int ) {
if ( dy > 0 ) { //check for scroll down
homeApiFab . shrink ( ) // hide
homeRandom . shrink ( )
} else if ( dy < - 5 ) {
if ( !is TvSettings ( ) ) {
homeApiFab . extend ( ) // show
homeRandom . extend ( )
}
}
super . onScrolled ( recyclerView , dx , dy )
}
} )
2022-04-18 17:55:21 +00:00
}
2023-07-18 20:18:14 +00:00
2022-10-08 20:34:41 +00:00
//Load value for toggling Random button. Hide at startup
2022-04-18 17:55:21 +00:00
context ?. let {
val settingsManager = PreferenceManager . getDefaultSharedPreferences ( it )
2022-04-25 18:00:25 +00:00
toggleRandomButton =
2023-07-13 21:18:37 +00:00
settingsManager . getBoolean (
getString ( R . string . random _button _key ) ,
false
) && !is TvSettings ( )
binding ?. homeRandom ?. visibility = View . GONE
2022-04-18 17:55:21 +00:00
}
2021-07-29 15:16:08 +00:00
2021-10-22 13:23:48 +00:00
observe ( homeViewModel . apiName ) { apiName ->
2021-12-26 00:05:10 +00:00
currentApiName = apiName
2023-07-13 21:18:37 +00:00
binding ?. homeApiFab ?. text = apiName
2021-11-25 22:36:35 +00:00
}
2021-07-29 15:16:08 +00:00
observe ( homeViewModel . page ) { data ->
2023-07-13 21:18:37 +00:00
binding ?. apply {
when ( data ) {
is Resource . Success -> {
homeLoadingShimmer . stopShimmer ( )
val d = data . value
val mutableListOfResponse = mutableListOf < SearchResponse > ( )
listHomepageItems . clear ( )
( homeMasterRecycler . adapter as ? ParentItemAdapter ) ?. updateList (
d . values . toMutableList ( ) ,
homeMasterRecycler
)
homeLoading . isVisible = false
homeLoadingError . isVisible = false
homeMasterRecycler . isVisible = true
//home_loaded?.isVisible = true
if ( toggleRandomButton ) {
//Flatten list
d . values . forEach { dlist ->
mutableListOfResponse . addAll ( dlist . list . list )
}
listHomepageItems . addAll ( mutableListOfResponse . distinctBy { it . url } )
homeRandom . isVisible = listHomepageItems . isNotEmpty ( )
} else {
homeRandom . isGone = true
2022-10-08 20:34:41 +00:00
}
2022-04-18 17:55:21 +00:00
}
2021-12-10 23:57:11 +00:00
2023-07-13 21:18:37 +00:00
is Resource . Failure -> {
homeLoadingShimmer . stopShimmer ( )
resultErrorText . text = data . errorString
homeReloadConnectionerror . setOnClickListener ( apiChangeClickListener )
homeReloadConnectionOpenInBrowser . setOnClickListener { view ->
val validAPIs = apis //.filter { api -> api.hasMainPage }
view . popupMenuNoIconsAndNoStringRes ( validAPIs . mapIndexed { index , api ->
Pair (
index ,
api . name
)
} ) {
try {
val i = Intent ( Intent . ACTION _VIEW )
i . data = Uri . parse ( validAPIs [ itemId ] . mainUrl )
startActivity ( i )
} catch ( e : Exception ) {
logError ( e )
}
2022-01-30 22:02:57 +00:00
}
2021-07-29 15:16:08 +00:00
}
2023-07-13 21:18:37 +00:00
homeLoading . isVisible = false
homeLoadingError . isVisible = true
homeMasterRecycler . isVisible = false
//home_loaded?.isVisible = false
2021-07-29 15:16:08 +00:00
}
2021-07-29 00:19:42 +00:00
2023-07-13 21:18:37 +00:00
is Resource . Loading -> {
( homeMasterRecycler . adapter as ? ParentItemAdapter ) ?. updateList ( listOf ( ) )
homeLoadingShimmer . startShimmer ( )
homeLoading . isVisible = true
homeLoadingError . isVisible = false
homeMasterRecycler . isVisible = false
//home_loaded?.isVisible = false
}
2021-07-29 00:19:42 +00:00
}
}
}
2021-12-09 21:20:27 +00:00
2023-07-17 01:32:41 +00:00
//context?.fixPaddingStatusbarView(home_statusbar)
//context?.fixPaddingStatusbar(home_padding)
2021-12-09 21:20:27 +00:00
2023-07-17 01:32:41 +00:00
observeNullable ( homeViewModel . popup ) { item ->
if ( item == null ) {
bottomSheetDialog ?. dismissSafe ( )
bottomSheetDialog = null
return @observeNullable
2022-12-09 17:20:10 +00:00
}
2022-02-03 21:23:00 +00:00
2023-07-17 01:32:41 +00:00
// don't recreate
if ( bottomSheetDialog != null ) {
return @observeNullable
}
2021-08-25 15:28:25 +00:00
2023-07-17 01:32:41 +00:00
bottomSheetDialog = activity ?. loadHomepageList ( item , expandCallback = {
homeViewModel . expandAndReturn ( it )
} , dismissCallback = {
homeViewModel . popup ( null )
bottomSheetDialog = null
} )
}
2021-07-29 00:19:42 +00:00
2023-07-17 01:32:41 +00:00
homeViewModel . reloadStored ( )
2023-07-30 03:05:13 +00:00
homeViewModel . loadAndCancel ( getKey ( USER _SELECTED _HOMEPAGE _API ) , false )
2023-07-17 01:32:41 +00:00
//loadHomePage(false)
2022-12-28 12:09:00 +00:00
2021-11-07 22:10:19 +00:00
// nice profile pic on homepage
2022-12-28 11:51:55 +00:00
//home_profile_picture_holder?.isVisible = false
2022-08-28 23:52:15 +00:00
// just in case
2023-07-18 20:18:14 +00:00
2022-12-28 12:29:23 +00:00
//TODO READD THIS
2022-12-28 11:51:55 +00:00
/ * for ( syncApi in OAuth2Apis ) {
2022-08-28 23:52:15 +00:00
val login = syncApi . loginInfo ( )
val pic = login ?. profilePicture
if ( home _profile _picture ?. setImage (
pic ,
errorImageDrawable = errorProfilePic
) == true
) {
home _profile _picture _holder ?. isVisible = true
break
2021-11-07 22:10:19 +00:00
}
2022-12-28 11:51:55 +00:00
} * /
2021-04-30 17:20:15 +00:00
}
2022-10-08 20:34:41 +00:00
}