sflix mirror and phone layout UI update

This commit is contained in:
LagradOst 2021-11-25 23:36:35 +01:00
parent b3cbedcd3a
commit 37d402d7b3
14 changed files with 164 additions and 70 deletions

View file

@ -114,7 +114,7 @@ dependencies {
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation "androidx.leanback:leanback-paging:1.1.0-alpha09" // implementation "androidx.leanback:leanback-paging:1.1.0-alpha09"
// Exoplayer // Exoplayer
implementation 'com.google.android.exoplayer:exoplayer:2.15.1' implementation 'com.google.android.exoplayer:exoplayer:2.15.1'
@ -153,5 +153,5 @@ dependencies {
implementation "com.github.tachiyomiorg:unifile:17bec43" implementation "com.github.tachiyomiorg:unifile:17bec43"
// debugImplementation because LeakCanary should only run in debug builds. // debugImplementation because LeakCanary should only run in debug builds.
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7' // debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
} }

View file

@ -31,7 +31,7 @@
<activity <activity
android:exported="true" android:exported="true"
android:name=".MainActivity" android:name=".MainActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden|navigation" android:configChanges="screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden|navigation"
android:label="@string/app_name" android:label="@string/app_name"
android:resizeableActivity="true" android:resizeableActivity="true"
android:supportsPictureInPicture="true"> android:supportsPictureInPicture="true">

View file

@ -85,6 +85,5 @@ class AcraApplication : Application() {
private set(value) { private set(value) {
_context = WeakReference(value) _context = WeakReference(value)
} }
} }
} }

View file

@ -49,7 +49,9 @@ object APIHolder {
VfSerieProvider(), VfSerieProvider(),
AsianLoadProvider(), AsianLoadProvider(),
SflixProvider(), SflixProvider("https://sflix.to","Sflix"),
SflixProvider("https://dopebox.to","Dopebox"),
ZoroProvider() ZoroProvider()
) )

View file

@ -21,6 +21,7 @@ import androidx.navigation.findNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.android.gms.cast.framework.* import com.google.android.gms.cast.framework.*
import com.google.android.material.navigationrail.NavigationRailView
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
import com.lagradost.cloudstream3.APIHolder.apis import com.lagradost.cloudstream3.APIHolder.apis
import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings
@ -51,8 +52,6 @@ import com.lagradost.cloudstream3.utils.UIHelper.requestRW
import com.lagradost.cloudstream3.utils.UIHelper.shouldShowPIPMode import com.lagradost.cloudstream3.utils.UIHelper.shouldShowPIPMode
import com.lagradost.cloudstream3.utils.UIHelper.toPx import com.lagradost.cloudstream3.utils.UIHelper.toPx
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.activity_main.cast_mini_controller_holder
import kotlinx.android.synthetic.main.activity_main_tv.*
import kotlinx.android.synthetic.main.fragment_result.* import kotlinx.android.synthetic.main.fragment_result.*
import java.util.* import java.util.*
import kotlin.concurrent.thread import kotlin.concurrent.thread
@ -84,7 +83,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
updateLocale() // android fucks me by chaining lang when rotating the phone updateLocale() // android fucks me by chaining lang when rotating the phone
} }
private var mCastSession: CastSession? = null //private var mCastSession: CastSession? = null
lateinit var mSessionManager: SessionManager lateinit var mSessionManager: SessionManager
private val mSessionManagerListener: SessionManagerListener<Session> by lazy { SessionManagerListenerImpl() } private val mSessionManagerListener: SessionManagerListener<Session> by lazy { SessionManagerListenerImpl() }
@ -123,7 +122,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
super.onResume() super.onResume()
try { try {
if (isCastApiAvailable()) { if (isCastApiAvailable()) {
mCastSession = mSessionManager.currentCastSession //mCastSession = mSessionManager.currentCastSession
mSessionManager.addSessionManagerListener(mSessionManagerListener) mSessionManager.addSessionManagerListener(mSessionManagerListener)
} }
} catch (e: Exception) { } catch (e: Exception) {
@ -136,7 +135,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
try { try {
if (isCastApiAvailable()) { if (isCastApiAvailable()) {
mSessionManager.removeSessionManagerListener(mSessionManagerListener) mSessionManager.removeSessionManagerListener(mSessionManagerListener)
mCastSession = null //mCastSession = null
} }
} catch (e: Exception) { } catch (e: Exception) {
logError(e) logError(e)
@ -448,7 +447,8 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
.setPopUpTo(navController.graph.startDestination, false) .setPopUpTo(navController.graph.startDestination, false)
.build()*/ .build()*/
nav_view?.setupWithNavController(navController) nav_view?.setupWithNavController(navController)
nav_rail_view?.setupWithNavController(navController) val navRail = findViewById<NavigationRailView?>(R.id.nav_rail_view)
navRail?.setupWithNavController(navController)
navController.addOnDestinationChangedListener { _, destination, _ -> navController.addOnDestinationChangedListener { _, destination, _ ->
this.hideKeyboard() this.hideKeyboard()
// nav_view.hideKeyboard() // nav_view.hideKeyboard()
@ -473,7 +473,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
).contains(destination.id) ).contains(destination.id)
nav_view?.isVisible = isNavVisible nav_view?.isVisible = isNavVisible
nav_rail_view?.isVisible = isNavVisible navRail?.isVisible = isNavVisible
} }
/*nav_view.setOnNavigationItemSelectedListener { item -> /*nav_view.setOnNavigationItemSelectedListener { item ->
@ -496,7 +496,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
val rippleColor = ColorStateList.valueOf(getResourceColor(R.attr.colorPrimary, 0.1f)) val rippleColor = ColorStateList.valueOf(getResourceColor(R.attr.colorPrimary, 0.1f))
nav_view?.itemRippleColor = rippleColor nav_view?.itemRippleColor = rippleColor
nav_rail_view?.itemRippleColor = rippleColor navRail?.itemRippleColor = rippleColor
if (!checkWrite()) { if (!checkWrite()) {
requestRW() requestRW()

View file

@ -13,11 +13,11 @@ import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.net.URI import java.net.URI
class SflixProvider : MainAPI() { class SflixProvider(private val providerUrl: String, private val providerName: String) : MainAPI() {
override val mainUrl: String override val mainUrl: String
get() = "https://sflix.to" get() = providerUrl
override val name: String override val name: String
get() = "Sflix" get() = providerName
override val hasQuickSearch: Boolean override val hasQuickSearch: Boolean
get() = false get() = false

View file

@ -119,46 +119,6 @@ class HomeFragment : Fragment() {
home_main_holder.isVisible = visible home_main_holder.isVisible = visible
} }
@SuppressLint("SetTextI18n")
private fun chooseRandomMainPage() {
val home = currentHomePage
if (home != null && home.items.isNotEmpty()) {
val currentList =
home.items.shuffled().filter { !it.list.isNullOrEmpty() }.flatMap { it.list }.distinctBy { it.url }
.toList()
if (currentList.isNullOrEmpty()) {
toggleMainVisibility(false)
} else {
val randomItems = currentList.shuffled()
val randomSize = randomItems.size
home_main_poster_recyclerview.adapter =
HomeChildItemAdapter(randomItems, 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)
}
} else {
toggleMainVisibility(false)
}
}
private fun fixGrid() { private fun fixGrid() {
val compactView = activity?.getGridIsCompact() ?: false val compactView = activity?.getGridIsCompact() ?: false
val spanCountLandscape = if (compactView) 2 else 6 val spanCountLandscape = if (compactView) 2 else 6
@ -239,6 +199,40 @@ class HomeFragment : Fragment() {
} }
} }
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)
}
}
observe(homeViewModel.page) { data -> observe(homeViewModel.page) { data ->
when (data) { when (data) {
is Resource.Success -> { is Resource.Success -> {
@ -256,7 +250,6 @@ class HomeFragment : Fragment() {
} }
home_master_recycler?.adapter?.notifyDataSetChanged() home_master_recycler?.adapter?.notifyDataSetChanged()
chooseRandomMainPage()
home_loading.visibility = View.GONE home_loading.visibility = View.GONE
home_loading_error.visibility = View.GONE home_loading_error.visibility = View.GONE

View file

@ -39,6 +39,9 @@ class HomeViewModel : ViewModel() {
private val _page = MutableLiveData<Resource<HomePageResponse>>() private val _page = MutableLiveData<Resource<HomePageResponse>>()
val page: LiveData<Resource<HomePageResponse>> = _page val page: LiveData<Resource<HomePageResponse>> = _page
private val _randomItems = MutableLiveData<List<SearchResponse>?>(null)
val randomItems: LiveData<List<SearchResponse>?> = _randomItems
private fun autoloadRepo(): APIRepository { private fun autoloadRepo(): APIRepository {
return APIRepository(apis.first { it.hasMainPage }) return APIRepository(apis.first { it.hasMainPage })
} }
@ -142,7 +145,29 @@ class HomeViewModel : ViewModel() {
_apiName.postValue(repo?.name) _apiName.postValue(repo?.name)
if (repo?.hasMainPage == true) { if (repo?.hasMainPage == true) {
_page.postValue(Resource.Loading()) _page.postValue(Resource.Loading())
_page.postValue(repo?.getMainPage()) _randomItems.postValue(null)
val data = repo?.getMainPage()
when (data) {
is Resource.Success -> {
val home = data.value
if (home.items.isNotEmpty()) {
val currentList =
home.items.shuffled().filter { !it.list.isNullOrEmpty() }.flatMap { it.list }
.distinctBy { it.url }
.toList()
if (!currentList.isNullOrEmpty()) {
val randomItems = currentList.shuffled()
_randomItems.postValue(randomItems)
}
}
}
else -> {
}
}
_page.postValue(data)
} else { } else {
_page.postValue(Resource.Success(HomePageResponse(emptyList()))) _page.postValue(Resource.Success(HomePageResponse(emptyList())))
} }
@ -153,7 +178,7 @@ class HomeViewModel : ViewModel() {
if (preferredApiName == noneApi.name) if (preferredApiName == noneApi.name)
loadAndCancel(noneApi) loadAndCancel(noneApi)
else if (preferredApiName == randomApi.name || api == null) { else if (preferredApiName == randomApi.name || api == null) {
var validAPIs = AppUtils.filterProviderByPreferredMedia(apis, currentPrefMedia) val validAPIs = AppUtils.filterProviderByPreferredMedia(apis, currentPrefMedia)
val apiRandom = validAPIs.random() val apiRandom = validAPIs.random()
loadAndCancel(apiRandom) loadAndCancel(apiRandom)
context?.setKey(HOMEPAGE_API, apiRandom.name) context?.setKey(HOMEPAGE_API, apiRandom.name)

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/homeRoot"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|keyboard|navigation"
android:paddingTop="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_height="match_parent"
android:layout_width="match_parent">
<com.google.android.material.navigationrail.NavigationRailView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/nav_rail_view"
android:background="?attr/primaryGrayBackground"
app:itemTextColor="@color/item_select_color"
app:itemIconTint="@color/item_select_color"
app:menuGravity="center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:labelVisibilityMode="unlabeled"
app:menu="@menu/bottom_nav_menu">
</com.google.android.material.navigationrail.NavigationRailView>
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/cast_mini_controller_holder"
app:navGraph="@navigation/mobile_navigation"
app:layout_constraintStart_toEndOf="@id/nav_rail_view"
app:layout_constraintEnd_toEndOf="parent"/>
<LinearLayout
app:layout_constraintStart_toEndOf="@+id/nav_rail_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:layout_height="100dp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/cast_mini_controller_holder"
>
<!--com.google.android.gms.cast.framework.media.widget.MiniControllerFragment-->
<fragment
app:customCastBackgroundColor="?attr/primaryGrayBackground"
app:castControlButtons="@array/cast_mini_controller_control_buttons"
android:id="@+id/cast_mini_controller"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
class="com.lagradost.cloudstream3.ui.MyMiniControllerFragment"
tools:ignore="FragmentTagUsage">
</fragment>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View file

@ -31,11 +31,12 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
app:defaultNavHost="true" app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@+id/nav_view" app:layout_constraintBottom_toTopOf="@+id/cast_mini_controller_holder"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/mobile_navigation" app:navGraph="@navigation/mobile_navigation"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent"/>
<LinearLayout <LinearLayout
tools:layout_height="100dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/nav_view" app:layout_constraintBottom_toTopOf="@+id/nav_view"

View file

@ -21,7 +21,7 @@
app:menuGravity="center" app:menuGravity="center"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:labelVisibilityMode="labeled" app:labelVisibilityMode="unlabeled"
app:menu="@menu/bottom_nav_menu"> app:menu="@menu/bottom_nav_menu">
</com.google.android.material.navigationrail.NavigationRailView> </com.google.android.material.navigationrail.NavigationRailView>
@ -30,17 +30,21 @@
android:id="@+id/nav_host_fragment" android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment" android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="0dp"
app:defaultNavHost="true" app:defaultNavHost="true"
app:layout_constraintLeft_toRightOf="@+id/nav_view" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/cast_mini_controller_holder"
app:navGraph="@navigation/mobile_navigation" app:navGraph="@navigation/mobile_navigation"
app:layout_constraintStart_toEndOf="@id/nav_rail_view" app:layout_constraintStart_toEndOf="@id/nav_rail_view"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent"/>
<LinearLayout <LinearLayout
android:layout_width="match_parent" app:layout_constraintStart_toEndOf="@+id/nav_rail_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:layout_height="100dp"
android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/nav_view"
android:id="@+id/cast_mini_controller_holder" android:id="@+id/cast_mini_controller_holder"
> >
<!--com.google.android.gms.cast.framework.media.widget.MiniControllerFragment--> <!--com.google.android.gms.cast.framework.media.widget.MiniControllerFragment-->

View file

@ -301,6 +301,8 @@
</FrameLayout> </FrameLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:paddingHorizontal="5dp"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants" android:descendantFocusability="afterDescendants"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:id="@+id/home_watch_child_recyclerview" android:id="@+id/home_watch_child_recyclerview"
@ -358,6 +360,8 @@
</FrameLayout> </FrameLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:paddingHorizontal="5dp"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants" android:descendantFocusability="afterDescendants"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"

View file

@ -32,6 +32,9 @@
</FrameLayout> </FrameLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:paddingHorizontal="5dp"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants" android:descendantFocusability="afterDescendants"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"

View file

@ -135,9 +135,9 @@
<style name="OverlayPrimaryColorRed"> <style name="OverlayPrimaryColorRed">
<item name="colorPrimary">@color/colorPrimaryRed</item> <item name="colorPrimary">@color/colorPrimaryRed</item>
<item name="android:colorPrimary">@color/colorPrimaryRed</item> <item name="android:colorPrimary">@color/colorPrimaryRed</item>
<item name="colorPrimaryDark">#D53333</item> <item name="colorPrimaryDark">#B62B2B</item>
<item name="colorAccent">#F53B3B</item> <item name="colorAccent">@color/colorPrimaryRed</item> <!--#F53B3B-->
<item name="colorOnPrimary">#EC3838</item> <item name="colorOnPrimary">@color/colorPrimaryRed</item> <!--#EC3838-->
<!-- Needed for leanback fuckery --> <!-- Needed for leanback fuckery -->
<item name="android:colorAccent">@color/colorPrimaryRed</item> <item name="android:colorAccent">@color/colorPrimaryRed</item>
</style> </style>