mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
more views + MainActivity viewbindings
This commit is contained in:
parent
166a21f74e
commit
647e91bc4b
11 changed files with 237 additions and 128 deletions
|
@ -208,7 +208,7 @@ dependencies {
|
||||||
|
|
||||||
implementation("com.github.discord:OverlappingPanels:0.1.3")
|
implementation("com.github.discord:OverlappingPanels:0.1.3")
|
||||||
// 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")
|
||||||
|
|
||||||
// for shimmer when loading
|
// for shimmer when loading
|
||||||
implementation("com.facebook.shimmer:shimmer:0.5.0")
|
implementation("com.facebook.shimmer:shimmer:0.5.0")
|
||||||
|
@ -228,7 +228,7 @@ dependencies {
|
||||||
// Library/extensions searching with Levenshtein distance
|
// Library/extensions searching with Levenshtein distance
|
||||||
implementation("me.xdrop:fuzzywuzzy:1.4.0")
|
implementation("me.xdrop:fuzzywuzzy:1.4.0")
|
||||||
|
|
||||||
// color pallette for images -> colors
|
// color palette for images -> colors
|
||||||
implementation("androidx.palette:palette-ktx:1.0.0")
|
implementation("androidx.palette:palette-ktx:1.0.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,8 @@ class CustomReportSender : ReportSender {
|
||||||
thread { // to not run it on main thread
|
thread { // to not run it on main thread
|
||||||
runBlocking {
|
runBlocking {
|
||||||
suspendSafeApiCall {
|
suspendSafeApiCall {
|
||||||
val post = app.post(url, data = data)
|
app.post(url, data = data)
|
||||||
println("Report response: $post")
|
//println("Report response: $post")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
import com.google.android.gms.cast.framework.*
|
import com.google.android.gms.cast.framework.*
|
||||||
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.navigationrail.NavigationRailView
|
import com.google.android.material.navigationrail.NavigationRailView
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
@ -49,6 +50,9 @@ import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent
|
||||||
import com.lagradost.cloudstream3.CommonActivity.onUserLeaveHint
|
import com.lagradost.cloudstream3.CommonActivity.onUserLeaveHint
|
||||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||||
import com.lagradost.cloudstream3.CommonActivity.updateLocale
|
import com.lagradost.cloudstream3.CommonActivity.updateLocale
|
||||||
|
import com.lagradost.cloudstream3.databinding.ActivityMainBinding
|
||||||
|
import com.lagradost.cloudstream3.databinding.ActivityMainTvBinding
|
||||||
|
import com.lagradost.cloudstream3.databinding.BottomResultviewPreviewBinding
|
||||||
import com.lagradost.cloudstream3.mvvm.*
|
import com.lagradost.cloudstream3.mvvm.*
|
||||||
import com.lagradost.cloudstream3.network.initClient
|
import com.lagradost.cloudstream3.network.initClient
|
||||||
import com.lagradost.cloudstream3.plugins.PluginManager
|
import com.lagradost.cloudstream3.plugins.PluginManager
|
||||||
|
@ -74,6 +78,7 @@ import com.lagradost.cloudstream3.ui.result.ResultViewModel2
|
||||||
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
|
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
|
||||||
import com.lagradost.cloudstream3.ui.result.setImage
|
import com.lagradost.cloudstream3.ui.result.setImage
|
||||||
import com.lagradost.cloudstream3.ui.result.setText
|
import com.lagradost.cloudstream3.ui.result.setText
|
||||||
|
import com.lagradost.cloudstream3.ui.result.txt
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchFragment
|
import com.lagradost.cloudstream3.ui.search.SearchFragment
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchResultBuilder
|
import com.lagradost.cloudstream3.ui.search.SearchResultBuilder
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings
|
||||||
|
@ -110,9 +115,6 @@ import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
||||||
import com.lagradost.nicehttp.Requests
|
import com.lagradost.nicehttp.Requests
|
||||||
import com.lagradost.nicehttp.ResponseParser
|
import com.lagradost.nicehttp.ResponseParser
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
|
||||||
import kotlinx.android.synthetic.main.bottom_resultview_preview.*
|
|
||||||
import kotlinx.android.synthetic.main.fragment_result_swipe.*
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
@ -334,8 +336,10 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
|
|
||||||
// Use both navigation views to support both layouts.
|
// Use both navigation views to support both layouts.
|
||||||
// It might be better to use the QuickSearch.
|
// It might be better to use the QuickSearch.
|
||||||
nav_view?.selectedItemId = R.id.navigation_search
|
activity?.findViewById<BottomNavigationView>(R.id.nav_view)?.selectedItemId =
|
||||||
nav_rail_view?.selectedItemId = R.id.navigation_search
|
R.id.navigation_search
|
||||||
|
activity?.findViewById<NavigationRailView>(R.id.nav_rail_view)?.selectedItemId =
|
||||||
|
R.id.navigation_search
|
||||||
} else if (safeURI(str)?.scheme == appStringPlayer) {
|
} else if (safeURI(str)?.scheme == appStringPlayer) {
|
||||||
val uri = Uri.parse(str)
|
val uri = Uri.parse(str)
|
||||||
val name = uri.getQueryParameter("name")
|
val name = uri.getQueryParameter("name")
|
||||||
|
@ -412,7 +416,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
this.hideKeyboard()
|
this.hideKeyboard()
|
||||||
|
|
||||||
// Fucks up anime info layout since that has its own layout
|
// Fucks up anime info layout since that has its own layout
|
||||||
cast_mini_controller_holder?.isVisible =
|
binding?.castMiniControllerHolder?.isVisible =
|
||||||
!listOf(
|
!listOf(
|
||||||
R.id.navigation_results_phone,
|
R.id.navigation_results_phone,
|
||||||
R.id.navigation_results_tv,
|
R.id.navigation_results_tv,
|
||||||
|
@ -448,7 +452,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
R.id.navigation_player,
|
R.id.navigation_player,
|
||||||
).contains(destination.id)
|
).contains(destination.id)
|
||||||
|
|
||||||
nav_host_fragment?.apply {
|
binding?.navHostFragment?.apply {
|
||||||
val params = layoutParams as ConstraintLayout.LayoutParams
|
val params = layoutParams as ConstraintLayout.LayoutParams
|
||||||
|
|
||||||
params.setMargins(
|
params.setMargins(
|
||||||
|
@ -464,21 +468,24 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
Configuration.ORIENTATION_LANDSCAPE -> {
|
Configuration.ORIENTATION_LANDSCAPE -> {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
Configuration.ORIENTATION_PORTRAIT -> {
|
Configuration.ORIENTATION_PORTRAIT -> {
|
||||||
false
|
isTvSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
binding?.apply {
|
||||||
|
navView.isVisible = isNavVisible && !landscape
|
||||||
|
navRailView.isVisible = isNavVisible && landscape
|
||||||
|
|
||||||
nav_view?.isVisible = isNavVisible && !landscape
|
// Hide library on TV since it is not supported yet :(
|
||||||
nav_rail_view?.isVisible = isNavVisible && landscape
|
val isTrueTv = isTrueTvSettings()
|
||||||
|
navView.menu.findItem(R.id.navigation_library)?.isVisible = !isTrueTv
|
||||||
// Hide library on TV since it is not supported yet :(
|
navRailView.menu.findItem(R.id.navigation_library)?.isVisible = !isTrueTv
|
||||||
val isTrueTv = isTrueTvSettings()
|
}
|
||||||
nav_view?.menu?.findItem(R.id.navigation_library)?.isVisible = !isTrueTv
|
|
||||||
nav_rail_view?.menu?.findItem(R.id.navigation_library)?.isVisible = !isTrueTv
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//private var mCastSession: CastSession? = null
|
//private var mCastSession: CastSession? = null
|
||||||
|
@ -691,28 +698,37 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hidePreviewPopupDialog() {
|
private fun hidePreviewPopupDialog() {
|
||||||
viewModel.clear()
|
|
||||||
bottomPreviewPopup.dismissSafe(this)
|
bottomPreviewPopup.dismissSafe(this)
|
||||||
|
bottomPreviewPopup = null
|
||||||
|
bottomPreviewBinding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
var bottomPreviewPopup: BottomSheetDialog? = null
|
private var bottomPreviewPopup: BottomSheetDialog? = null
|
||||||
private fun showPreviewPopupDialog(): BottomSheetDialog {
|
private var bottomPreviewBinding: BottomResultviewPreviewBinding? = null
|
||||||
val ret = (bottomPreviewPopup ?: run {
|
private fun showPreviewPopupDialog(): BottomResultviewPreviewBinding {
|
||||||
|
val ret = (bottomPreviewBinding ?: run {
|
||||||
val builder =
|
val builder =
|
||||||
BottomSheetDialog(this)
|
BottomSheetDialog(this)
|
||||||
builder.setContentView(R.layout.bottom_resultview_preview)
|
val binding: BottomResultviewPreviewBinding =
|
||||||
|
BottomResultviewPreviewBinding.inflate(builder.layoutInflater, null, false)
|
||||||
|
bottomPreviewBinding = binding
|
||||||
|
builder.setContentView(binding.root)
|
||||||
builder.setOnDismissListener {
|
builder.setOnDismissListener {
|
||||||
bottomPreviewPopup = null
|
bottomPreviewPopup = null
|
||||||
|
bottomPreviewBinding = null
|
||||||
viewModel.clear()
|
viewModel.clear()
|
||||||
}
|
}
|
||||||
builder.setCanceledOnTouchOutside(true)
|
builder.setCanceledOnTouchOutside(true)
|
||||||
builder.show()
|
builder.show()
|
||||||
builder
|
bottomPreviewPopup = builder
|
||||||
|
binding
|
||||||
})
|
})
|
||||||
bottomPreviewPopup = ret
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var binding: ActivityMainBinding? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
app.initClient(this)
|
app.initClient(this)
|
||||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
@ -744,10 +760,20 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
|
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
|
||||||
updateTv()
|
updateTv()
|
||||||
|
|
||||||
if (isTvSettings()) {
|
// just in case, MAIN SHOULD *NEVER* BOOT LOOP CRASH
|
||||||
setContentView(R.layout.activity_main_tv)
|
binding = try {
|
||||||
} else {
|
if (isTvSettings()) {
|
||||||
setContentView(R.layout.activity_main)
|
val newLocalBinding = ActivityMainTvBinding.inflate(layoutInflater, null, false)
|
||||||
|
setContentView(newLocalBinding.root)
|
||||||
|
ActivityMainBinding.bind(newLocalBinding.root) // this may crash
|
||||||
|
} else {
|
||||||
|
val newLocalBinding = ActivityMainBinding.inflate(layoutInflater, null, false)
|
||||||
|
setContentView(newLocalBinding.root)
|
||||||
|
newLocalBinding
|
||||||
|
}
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
showToast(this, txt(R.string.unable_to_inflate, t.message ?: ""), Toast.LENGTH_LONG)
|
||||||
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
changeStatusBarState(isEmulatorSettings())
|
changeStatusBarState(isEmulatorSettings())
|
||||||
|
@ -832,41 +858,44 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
|
|
||||||
observeNullable(viewModel.page) { resource ->
|
observeNullable(viewModel.page) { resource ->
|
||||||
if (resource == null) {
|
if (resource == null) {
|
||||||
bottomPreviewPopup.dismissSafe(this)
|
hidePreviewPopupDialog()
|
||||||
return@observeNullable
|
return@observeNullable
|
||||||
}
|
}
|
||||||
when (resource) {
|
when (resource) {
|
||||||
is Resource.Failure -> {
|
is Resource.Failure -> {
|
||||||
showToast(this, R.string.error)
|
showToast(this, R.string.error)
|
||||||
|
viewModel.clear()
|
||||||
hidePreviewPopupDialog()
|
hidePreviewPopupDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
is Resource.Loading -> {
|
is Resource.Loading -> {
|
||||||
showPreviewPopupDialog().apply {
|
showPreviewPopupDialog().apply {
|
||||||
resultview_preview_loading?.isVisible = true
|
resultviewPreviewLoading.isVisible = true
|
||||||
resultview_preview_result?.isVisible = false
|
resultviewPreviewResult.isVisible = false
|
||||||
resultview_preview_loading_shimmer?.startShimmer()
|
resultviewPreviewLoadingShimmer.startShimmer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
val d = resource.value
|
val d = resource.value
|
||||||
showPreviewPopupDialog().apply {
|
showPreviewPopupDialog().apply {
|
||||||
resultview_preview_loading?.isVisible = false
|
resultviewPreviewLoading.isVisible = false
|
||||||
resultview_preview_result?.isVisible = true
|
resultviewPreviewResult.isVisible = true
|
||||||
resultview_preview_loading_shimmer?.stopShimmer()
|
resultviewPreviewLoadingShimmer.stopShimmer()
|
||||||
|
|
||||||
resultview_preview_title?.text = d.title
|
resultviewPreviewTitle.text = d.title
|
||||||
|
|
||||||
resultview_preview_meta_type.setText(d.typeText)
|
resultviewPreviewMetaType.setText(d.typeText)
|
||||||
resultview_preview_meta_year.setText(d.yearText)
|
resultviewPreviewMetaYear.setText(d.yearText)
|
||||||
resultview_preview_meta_duration.setText(d.durationText)
|
resultviewPreviewMetaDuration.setText(d.durationText)
|
||||||
resultview_preview_meta_rating.setText(d.ratingText)
|
resultviewPreviewMetaRating.setText(d.ratingText)
|
||||||
|
|
||||||
resultview_preview_description?.setText(d.plotText)
|
resultviewPreviewDescription.setText(d.plotText)
|
||||||
resultview_preview_poster?.setImage(
|
resultviewPreviewPoster.setImage(
|
||||||
d.posterImage ?: d.posterBackgroundImage
|
d.posterImage ?: d.posterBackgroundImage
|
||||||
)
|
)
|
||||||
|
|
||||||
resultview_preview_poster?.setOnClickListener {
|
resultviewPreviewPoster.setOnClickListener {
|
||||||
//viewModel.updateWatchStatus(WatchType.PLANTOWATCH)
|
//viewModel.updateWatchStatus(WatchType.PLANTOWATCH)
|
||||||
val value = viewModel.watchStatus.value ?: WatchType.NONE
|
val value = viewModel.watchStatus.value ?: WatchType.NONE
|
||||||
|
|
||||||
|
@ -882,7 +911,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isTvSettings()) // dont want this clickable on tv layout
|
if (!isTvSettings()) // dont want this clickable on tv layout
|
||||||
resultview_preview_description?.setOnClickListener { view ->
|
resultviewPreviewDescription.setOnClickListener { view ->
|
||||||
view.context?.let { ctx ->
|
view.context?.let { ctx ->
|
||||||
val builder: AlertDialog.Builder =
|
val builder: AlertDialog.Builder =
|
||||||
AlertDialog.Builder(ctx, R.style.AlertDialogCustom)
|
AlertDialog.Builder(ctx, R.style.AlertDialogCustom)
|
||||||
|
@ -892,7 +921,8 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resultview_preview_more_info?.setOnClickListener {
|
resultviewPreviewMoreInfo.setOnClickListener {
|
||||||
|
viewModel.clear()
|
||||||
hidePreviewPopupDialog()
|
hidePreviewPopupDialog()
|
||||||
lastPopup?.let {
|
lastPopup?.let {
|
||||||
loadSearchResult(it)
|
loadSearchResult(it)
|
||||||
|
@ -964,22 +994,22 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
.setPopExitAnim(R.anim.nav_pop_exit)
|
.setPopExitAnim(R.anim.nav_pop_exit)
|
||||||
.setPopUpTo(navController.graph.startDestination, false)
|
.setPopUpTo(navController.graph.startDestination, false)
|
||||||
.build()*/
|
.build()*/
|
||||||
nav_view?.setupWithNavController(navController)
|
binding?.navView?.setupWithNavController(navController)
|
||||||
val nav_rail = findViewById<NavigationRailView?>(R.id.nav_rail_view)
|
val navRail = findViewById<NavigationRailView?>(R.id.nav_rail_view)
|
||||||
nav_rail?.setupWithNavController(navController)
|
navRail?.setupWithNavController(navController)
|
||||||
if (isTvSettings()) {
|
if (isTvSettings()) {
|
||||||
nav_rail?.background?.alpha = 200
|
navRail?.background?.alpha = 200
|
||||||
} else {
|
} else {
|
||||||
nav_rail?.background?.alpha = 255
|
navRail?.background?.alpha = 255
|
||||||
|
|
||||||
}
|
}
|
||||||
nav_rail?.setOnItemSelectedListener { item ->
|
navRail?.setOnItemSelectedListener { item ->
|
||||||
onNavDestinationSelected(
|
onNavDestinationSelected(
|
||||||
item,
|
item,
|
||||||
navController
|
navController
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
nav_view?.setOnItemSelectedListener { item ->
|
binding?.navView?.setOnItemSelectedListener { item ->
|
||||||
onNavDestinationSelected(
|
onNavDestinationSelected(
|
||||||
item,
|
item,
|
||||||
navController
|
navController
|
||||||
|
@ -1010,16 +1040,16 @@ 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
|
binding?.navView?.itemRippleColor = rippleColor
|
||||||
nav_rail?.itemRippleColor = rippleColor
|
navRail?.itemRippleColor = rippleColor
|
||||||
nav_rail?.itemActiveIndicatorColor = rippleColor
|
navRail?.itemActiveIndicatorColor = rippleColor
|
||||||
nav_view?.itemActiveIndicatorColor = rippleColor
|
binding?.navView?.itemActiveIndicatorColor = rippleColor
|
||||||
|
|
||||||
if (!checkWrite()) {
|
if (!checkWrite()) {
|
||||||
requestRW()
|
requestRW()
|
||||||
if (checkWrite()) return
|
if (checkWrite()) return
|
||||||
}
|
}
|
||||||
CastButtonFactory.setUpMediaRouteButton(this, media_route_button)
|
//CastButtonFactory.setUpMediaRouteButton(this, media_route_button)
|
||||||
|
|
||||||
// THIS IS CURRENTLY REMOVED BECAUSE HIGHER VERS OF ANDROID NEEDS A NOTIFICATION
|
// THIS IS CURRENTLY REMOVED BECAUSE HIGHER VERS OF ANDROID NEEDS A NOTIFICATION
|
||||||
//if (!VideoDownloadManager.isMyServiceRunning(this, VideoDownloadKeepAliveService::class.java)) {
|
//if (!VideoDownloadManager.isMyServiceRunning(this, VideoDownloadKeepAliveService::class.java)) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import com.lagradost.cloudstream3.APIHolder.apis
|
||||||
import com.lagradost.cloudstream3.APIHolder.filterProviderByPreferredMedia
|
import com.lagradost.cloudstream3.APIHolder.filterProviderByPreferredMedia
|
||||||
import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings
|
import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||||
|
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent
|
import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.bookmarksUpdatedEvent
|
import com.lagradost.cloudstream3.MainActivity.Companion.bookmarksUpdatedEvent
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.mainPluginsLoadedEvent
|
import com.lagradost.cloudstream3.MainActivity.Companion.mainPluginsLoadedEvent
|
||||||
|
@ -45,6 +46,7 @@ import com.lagradost.cloudstream3.ui.APIRepository.Companion.noneApi
|
||||||
import com.lagradost.cloudstream3.ui.APIRepository.Companion.randomApi
|
import com.lagradost.cloudstream3.ui.APIRepository.Companion.randomApi
|
||||||
import com.lagradost.cloudstream3.ui.WatchType
|
import com.lagradost.cloudstream3.ui.WatchType
|
||||||
import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment
|
import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment
|
||||||
|
import com.lagradost.cloudstream3.ui.result.txt
|
||||||
import com.lagradost.cloudstream3.ui.search.*
|
import com.lagradost.cloudstream3.ui.search.*
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchHelper.handleSearchClickCallback
|
import com.lagradost.cloudstream3.ui.search.SearchHelper.handleSearchClickCallback
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||||
|
@ -431,22 +433,20 @@ class HomeFragment : Fragment() {
|
||||||
): View? {
|
): View? {
|
||||||
//homeViewModel =
|
//homeViewModel =
|
||||||
// ViewModelProvider(this).get(HomeViewModel::class.java)
|
// ViewModelProvider(this).get(HomeViewModel::class.java)
|
||||||
|
|
||||||
bottomSheetDialog?.ownShow()
|
bottomSheetDialog?.ownShow()
|
||||||
val layout =
|
val layout =
|
||||||
if (isTvSettings()) R.layout.fragment_home_tv else R.layout.fragment_home
|
if (isTvSettings()) R.layout.fragment_home_tv else R.layout.fragment_home
|
||||||
|
|
||||||
/* val binding = FragmentHomeTvBinding.inflate(layout, container, false)
|
|
||||||
binding.homeLoadingError
|
|
||||||
|
|
||||||
val binding2 = FragmentHomeBinding.inflate(layout, container, false)
|
|
||||||
binding2.homeLoadingError*/
|
|
||||||
val root = inflater.inflate(layout, container, false)
|
val root = inflater.inflate(layout, container, false)
|
||||||
binding = FragmentHomeBinding.bind(root)
|
binding = try {
|
||||||
//val localBinding = FragmentHomeBinding.inflate(inflater)
|
FragmentHomeBinding.bind(root)
|
||||||
//binding = localBinding
|
} catch (t : Throwable) {
|
||||||
return root
|
showToast(activity, txt(R.string.unable_to_inflate, t.message ?: ""), Toast.LENGTH_LONG)
|
||||||
|
logError(t)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
//return inflater.inflate(layout, container, false)
|
return root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -2,13 +2,13 @@ package com.lagradost.cloudstream3.ui.library
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import kotlinx.android.synthetic.main.library_viewpager_page.view.*
|
import com.lagradost.cloudstream3.R
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class LibraryScrollTransformer : ViewPager2.PageTransformer {
|
class LibraryScrollTransformer : ViewPager2.PageTransformer {
|
||||||
override fun transformPage(page: View, position: Float) {
|
override fun transformPage(page: View, position: Float) {
|
||||||
val padding = (-position * page.width).roundToInt()
|
val padding = (-position * page.width).roundToInt()
|
||||||
page.page_recyclerview.setPadding(
|
page.findViewById<View>(R.id.page_recyclerview).setPadding(
|
||||||
padding, 0,
|
padding, 0,
|
||||||
-padding, 0
|
-padding, 0
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,24 +2,18 @@ package com.lagradost.cloudstream3.ui.player.source_priority
|
||||||
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.View
|
import android.view.LayoutInflater
|
||||||
import android.widget.EditText
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.annotation.StyleRes
|
import androidx.annotation.StyleRes
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.fragment.app.FragmentActivity
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import androidx.work.impl.constraints.controllers.ConstraintController
|
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.PlayerSelectSourcePriorityBinding
|
||||||
import com.lagradost.cloudstream3.ui.result.txt
|
import com.lagradost.cloudstream3.ui.result.txt
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.Qualities
|
import com.lagradost.cloudstream3.utils.Qualities
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
|
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
|
||||||
import kotlinx.android.synthetic.main.player_select_source_priority.*
|
|
||||||
|
|
||||||
class SourcePriorityDialog(
|
class SourcePriorityDialog(
|
||||||
ctx: Context,
|
val ctx: Context,
|
||||||
@StyleRes themeRes: Int,
|
@StyleRes themeRes: Int,
|
||||||
val links: List<ExtractorLink>,
|
val links: List<ExtractorLink>,
|
||||||
private val profile: QualityDataHelper.QualityProfile,
|
private val profile: QualityDataHelper.QualityProfile,
|
||||||
|
@ -30,13 +24,14 @@ class SourcePriorityDialog(
|
||||||
private val updatedCallback: () -> Unit
|
private val updatedCallback: () -> Unit
|
||||||
) : Dialog(ctx, themeRes) {
|
) : Dialog(ctx, themeRes) {
|
||||||
override fun show() {
|
override fun show() {
|
||||||
setContentView(R.layout.player_select_source_priority)
|
val binding = PlayerSelectSourcePriorityBinding.inflate(LayoutInflater.from(ctx), null, false)
|
||||||
val sourcesRecyclerView: RecyclerView = sort_sources
|
setContentView(binding.root)
|
||||||
val qualitiesRecyclerView: RecyclerView = sort_qualities
|
val sourcesRecyclerView = binding.sortSources
|
||||||
val profileText: EditText = profile_text_editable
|
val qualitiesRecyclerView = binding.sortQualities
|
||||||
val saveBtt: View = save_btt
|
val profileText = binding.profileTextEditable
|
||||||
val exitBtt: View = close_btt
|
val saveBtt = binding.saveBtt
|
||||||
val helpBtt: View = help_btt
|
val exitBtt = binding.closeBtt
|
||||||
|
val helpBtt = binding.helpBtt
|
||||||
|
|
||||||
profileText.setText(QualityDataHelper.getProfileName(profile.id).asString(context))
|
profileText.setText(QualityDataHelper.getProfileName(profile.id).asString(context))
|
||||||
profileText.hint = txt(R.string.profile_number, profile.id).asString(context)
|
profileText.hint = txt(R.string.profile_number, profile.id).asString(context)
|
||||||
|
|
|
@ -38,15 +38,15 @@ class SearchAdapter(
|
||||||
var hasNext: Boolean = false
|
var hasNext: Boolean = false
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
|
val inflater = LayoutInflater.from(parent.context)
|
||||||
|
|
||||||
val layout =
|
val layout =
|
||||||
if (parent.context.IsBottomLayout()) SearchResultGridExpandedBinding.inflate(
|
if (parent.context.IsBottomLayout()) SearchResultGridExpandedBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
inflater,
|
||||||
parent,
|
parent,
|
||||||
false
|
false
|
||||||
) else SearchResultGridBinding.inflate(
|
) else SearchResultGridBinding.inflate(
|
||||||
LayoutInflater.from(parent.context),
|
inflater,
|
||||||
parent,
|
parent,
|
||||||
false
|
false
|
||||||
) //R.layout.search_result_grid_expanded else R.layout.search_result_grid
|
) //R.layout.search_result_grid_expanded else R.layout.search_result_grid
|
||||||
|
@ -95,9 +95,15 @@ class SearchAdapter(
|
||||||
private val coverHeight: Int =
|
private val coverHeight: Int =
|
||||||
if (compactView) 80.toPx else (resView.itemWidth / 0.68).roundToInt()
|
if (compactView) 80.toPx else (resView.itemWidth / 0.68).roundToInt()
|
||||||
|
|
||||||
|
private val cardView = when(binding) {
|
||||||
|
is SearchResultGridExpandedBinding -> binding.imageView
|
||||||
|
is SearchResultGridBinding -> binding.imageView
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
fun bind(card: SearchResponse, position: Int) {
|
fun bind(card: SearchResponse, position: Int) {
|
||||||
if (!compactView) {
|
if (!compactView) {
|
||||||
binding.root.apply {
|
cardView?.apply {
|
||||||
layoutParams = FrameLayout.LayoutParams(
|
layoutParams = FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
coverHeight
|
coverHeight
|
||||||
|
|
|
@ -3,7 +3,6 @@ package com.lagradost.cloudstream3.ui.settings.extensions
|
||||||
import android.text.format.Formatter.formatShortFileSize
|
import android.text.format.Formatter.formatShortFileSize
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
|
@ -13,6 +12,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getActivity
|
import com.lagradost.cloudstream3.AcraApplication.Companion.getActivity
|
||||||
import com.lagradost.cloudstream3.PROVIDER_STATUS_DOWN
|
import com.lagradost.cloudstream3.PROVIDER_STATUS_DOWN
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.RepositoryItemBinding
|
||||||
import com.lagradost.cloudstream3.plugins.PluginManager
|
import com.lagradost.cloudstream3.plugins.PluginManager
|
||||||
import com.lagradost.cloudstream3.plugins.VotingApi.getVotes
|
import com.lagradost.cloudstream3.plugins.VotingApi.getVotes
|
||||||
import com.lagradost.cloudstream3.ui.result.setText
|
import com.lagradost.cloudstream3.ui.result.setText
|
||||||
|
@ -26,10 +26,11 @@ import com.lagradost.cloudstream3.utils.SubtitleHelper.fromTwoLettersToLanguage
|
||||||
import com.lagradost.cloudstream3.utils.SubtitleHelper.getFlagFromIso
|
import com.lagradost.cloudstream3.utils.SubtitleHelper.getFlagFromIso
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
||||||
import kotlinx.android.synthetic.main.repository_item.view.*
|
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
|
import kotlin.math.floor
|
||||||
|
import kotlin.math.log10
|
||||||
|
|
||||||
|
|
||||||
data class PluginViewData(
|
data class PluginViewData(
|
||||||
|
@ -45,8 +46,10 @@ class PluginAdapter(
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
val layout = if(isTrueTvSettings()) R.layout.repository_item_tv else R.layout.repository_item
|
val layout = if(isTrueTvSettings()) R.layout.repository_item_tv else R.layout.repository_item
|
||||||
|
val inflated = LayoutInflater.from(parent.context).inflate(layout, parent, false)
|
||||||
|
|
||||||
return PluginViewHolder(
|
return PluginViewHolder(
|
||||||
LayoutInflater.from(parent.context).inflate(layout, parent, false)
|
RepositoryItemBinding.bind(inflated) // may crash
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,8 +85,10 @@ class PluginAdapter(
|
||||||
|
|
||||||
// Clear glide image because setImageResource doesn't override
|
// Clear glide image because setImageResource doesn't override
|
||||||
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
|
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
|
||||||
holder.itemView.entry_icon?.let { pluginIcon ->
|
if (holder is PluginViewHolder) {
|
||||||
GlideApp.with(pluginIcon).clear(pluginIcon)
|
holder.binding.entryIcon.let { pluginIcon ->
|
||||||
|
GlideApp.with(pluginIcon).clear(pluginIcon)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
super.onViewRecycled(holder)
|
super.onViewRecycled(holder)
|
||||||
}
|
}
|
||||||
|
@ -112,7 +117,7 @@ class PluginAdapter(
|
||||||
fun prettyCount(number: Number): String? {
|
fun prettyCount(number: Number): String? {
|
||||||
val suffix = charArrayOf(' ', 'k', 'M', 'B', 'T', 'P', 'E')
|
val suffix = charArrayOf(' ', 'k', 'M', 'B', 'T', 'P', 'E')
|
||||||
val numValue = number.toLong()
|
val numValue = number.toLong()
|
||||||
val value = Math.floor(Math.log10(numValue.toDouble())).toInt()
|
val value = floor(log10(numValue.toDouble())).toInt()
|
||||||
val base = value / 3
|
val base = value / 3
|
||||||
return if (value >= 3 && base < suffix.size) {
|
return if (value >= 3 && base < suffix.size) {
|
||||||
DecimalFormat("#0.00").format(
|
DecimalFormat("#0.00").format(
|
||||||
|
@ -127,8 +132,8 @@ class PluginAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class PluginViewHolder(itemView: View) :
|
inner class PluginViewHolder(val binding: RepositoryItemBinding) :
|
||||||
RecyclerView.ViewHolder(itemView) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
fun bind(
|
fun bind(
|
||||||
data: PluginViewData,
|
data: PluginViewData,
|
||||||
|
@ -138,17 +143,17 @@ class PluginAdapter(
|
||||||
val name = metadata.name.removeSuffix("Provider")
|
val name = metadata.name.removeSuffix("Provider")
|
||||||
val alpha = if (disabled) 0.6f else 1f
|
val alpha = if (disabled) 0.6f else 1f
|
||||||
val isLocal = !data.plugin.second.url.startsWith("http")
|
val isLocal = !data.plugin.second.url.startsWith("http")
|
||||||
itemView.main_text?.alpha = alpha
|
binding.mainText.alpha = alpha
|
||||||
itemView.sub_text?.alpha = alpha
|
binding.subText.alpha = alpha
|
||||||
|
|
||||||
val drawableInt = if (data.isDownloaded)
|
val drawableInt = if (data.isDownloaded)
|
||||||
R.drawable.ic_baseline_delete_outline_24
|
R.drawable.ic_baseline_delete_outline_24
|
||||||
else R.drawable.netflix_download
|
else R.drawable.netflix_download
|
||||||
|
|
||||||
itemView.nsfw_marker?.isVisible = metadata.tvTypes?.contains("NSFW") ?: false
|
binding.nsfwMarker.isVisible = metadata.tvTypes?.contains("NSFW") ?: false
|
||||||
itemView.action_button?.setImageResource(drawableInt)
|
binding.actionButton.setImageResource(drawableInt)
|
||||||
|
|
||||||
itemView.action_button?.setOnClickListener {
|
binding.actionButton.setOnClickListener {
|
||||||
iconClickCallback.invoke(data.plugin)
|
iconClickCallback.invoke(data.plugin)
|
||||||
}
|
}
|
||||||
itemView.setOnClickListener {
|
itemView.setOnClickListener {
|
||||||
|
@ -169,10 +174,11 @@ class PluginAdapter(
|
||||||
|
|
||||||
if (data.isDownloaded) {
|
if (data.isDownloaded) {
|
||||||
// On local plugins page the filepath is provided instead of url.
|
// On local plugins page the filepath is provided instead of url.
|
||||||
val plugin = PluginManager.urlPlugins[metadata.url] ?: PluginManager.plugins[metadata.url]
|
val plugin =
|
||||||
|
PluginManager.urlPlugins[metadata.url] ?: PluginManager.plugins[metadata.url]
|
||||||
if (plugin?.openSettings != null) {
|
if (plugin?.openSettings != null) {
|
||||||
itemView.action_settings?.isVisible = true
|
binding.actionSettings.isVisible = true
|
||||||
itemView.action_settings.setOnClickListener {
|
binding.actionSettings.setOnClickListener {
|
||||||
try {
|
try {
|
||||||
plugin.openSettings!!.invoke(itemView.context)
|
plugin.openSettings!!.invoke(itemView.context)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
|
@ -185,13 +191,13 @@ class PluginAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
itemView.action_settings?.isVisible = false
|
binding.actionSettings.isVisible = false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
itemView.action_settings?.isVisible = false
|
binding.actionSettings.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemView.entry_icon?.setImage(//itemView.entry_icon?.height ?:
|
if (!binding.entryIcon.setImage(//itemView.entry_icon?.height ?:
|
||||||
metadata.iconUrl?.replace(
|
metadata.iconUrl?.replace(
|
||||||
"%size%",
|
"%size%",
|
||||||
"$iconSize"
|
"$iconSize"
|
||||||
|
@ -201,41 +207,47 @@ class PluginAdapter(
|
||||||
),
|
),
|
||||||
null,
|
null,
|
||||||
errorImageDrawable = R.drawable.ic_baseline_extension_24
|
errorImageDrawable = R.drawable.ic_baseline_extension_24
|
||||||
) != true
|
)
|
||||||
) {
|
) {
|
||||||
itemView.entry_icon?.setImageResource(R.drawable.ic_baseline_extension_24)
|
binding.entryIcon.setImageResource(R.drawable.ic_baseline_extension_24)
|
||||||
}
|
}
|
||||||
|
|
||||||
itemView.ext_version?.isVisible = true
|
binding.extVersion.isVisible = true
|
||||||
itemView.ext_version?.text = "v${metadata.version}"
|
binding.extVersion.text = "v${metadata.version}"
|
||||||
|
|
||||||
if (metadata.language.isNullOrBlank()) {
|
if (metadata.language.isNullOrBlank()) {
|
||||||
itemView.lang_icon?.isVisible = false
|
binding.langIcon.isVisible = false
|
||||||
} else {
|
} else {
|
||||||
itemView.lang_icon?.isVisible = true
|
binding.langIcon.isVisible = true
|
||||||
itemView.lang_icon.text = "${getFlagFromIso(metadata.language)} ${fromTwoLettersToLanguage(metadata.language)}"
|
binding.langIcon.text =
|
||||||
|
"${getFlagFromIso(metadata.language)} ${fromTwoLettersToLanguage(metadata.language)}"
|
||||||
}
|
}
|
||||||
|
|
||||||
itemView.ext_votes?.isVisible = false
|
binding.extVotes.isVisible = false
|
||||||
if (!isLocal) {
|
if (!isLocal) {
|
||||||
ioSafe {
|
ioSafe {
|
||||||
metadata.getVotes().main {
|
metadata.getVotes().main {
|
||||||
itemView.ext_votes?.setText(txt(R.string.extension_rating, prettyCount(it)))
|
binding.extVotes.setText(txt(R.string.extension_rating, prettyCount(it)))
|
||||||
itemView.ext_votes?.isVisible = true
|
binding.extVotes.isVisible = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (metadata.fileSize != null) {
|
if (metadata.fileSize != null) {
|
||||||
itemView.ext_filesize?.isVisible = true
|
binding.extFilesize.isVisible = true
|
||||||
itemView.ext_filesize?.text = formatShortFileSize(itemView.context, metadata.fileSize)
|
binding.extFilesize.text = formatShortFileSize(itemView.context, metadata.fileSize)
|
||||||
} else {
|
} else {
|
||||||
itemView.ext_filesize?.isVisible = false
|
binding.extFilesize.isVisible = false
|
||||||
}
|
}
|
||||||
itemView.main_text.setText(if(disabled) txt(R.string.single_plugin_disabled, name) else txt(name))
|
binding.mainText.setText(
|
||||||
itemView.sub_text?.isGone = metadata.description.isNullOrBlank()
|
if (disabled) txt(
|
||||||
itemView.sub_text?.text = metadata.description.html()
|
R.string.single_plugin_disabled,
|
||||||
|
name
|
||||||
|
) else txt(name)
|
||||||
|
)
|
||||||
|
binding.subText.isGone = metadata.description.isNullOrBlank()
|
||||||
|
binding.subText.text = metadata.description.html()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,6 +181,50 @@ object UIHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*inline fun <reified T : ViewBinding> bindViewBinding(
|
||||||
|
inflater: LayoutInflater?,
|
||||||
|
container: ViewGroup?,
|
||||||
|
layout: Int
|
||||||
|
): Pair<T?, UiText?> {
|
||||||
|
return try {
|
||||||
|
val localInflater = inflater ?: container?.context?.let { LayoutInflater.from(it) }
|
||||||
|
?: return null to txt(
|
||||||
|
R.string.unable_to_inflate,
|
||||||
|
"Requires inflater OR container"
|
||||||
|
)//throw IllegalArgumentException("Requires inflater OR container"))
|
||||||
|
|
||||||
|
//println("methods: ${T::class.java.methods.map { it.name }}")
|
||||||
|
val bind = T::class.java.methods.first { it.name == "bind" }
|
||||||
|
//val inflate = T::class.java.methods.first { it.name == "inflate" }
|
||||||
|
val root = localInflater.inflate(layout, container, false)
|
||||||
|
bind.invoke(null, root) as T to null
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
logError(t)
|
||||||
|
val message = txt(R.string.unable_to_inflate, t.message ?: "Primary constructor")
|
||||||
|
// if the desired layout is not found then we inflate the casted layout
|
||||||
|
/*try {
|
||||||
|
val localInflater = inflater ?: container?.context?.let { LayoutInflater.from(it) }
|
||||||
|
?: return null to txt(
|
||||||
|
R.string.unable_to_inflate,
|
||||||
|
"Requires inflater OR container"
|
||||||
|
)//throw IllegalArgumentException("Requires inflater OR container"))
|
||||||
|
|
||||||
|
// we don't know what method to use as there are 2, but first *should* always be true
|
||||||
|
return try {
|
||||||
|
val inflate = T::class.java.methods.first { it.name == "inflate" }
|
||||||
|
inflate.invoke(null, localInflater, container, false) as T
|
||||||
|
} catch (_: Throwable) {
|
||||||
|
val inflate = T::class.java.methods.last { it.name == "inflate" }
|
||||||
|
inflate.invoke(null, localInflater, container, false) as T
|
||||||
|
} to message
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
logError(t)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
null to message
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
fun ImageView?.setImage(
|
fun ImageView?.setImage(
|
||||||
url: String?,
|
url: String?,
|
||||||
headers: Map<String, String>? = null,
|
headers: Map<String, String>? = null,
|
||||||
|
@ -190,7 +234,12 @@ object UIHelper {
|
||||||
colorCallback: ((Palette) -> Unit)? = null
|
colorCallback: ((Palette) -> Unit)? = null
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (url.isNullOrBlank()) return false
|
if (url.isNullOrBlank()) return false
|
||||||
this.setImage(UiImage.Image(url, headers, errorImageDrawable), errorImageDrawable, fadeIn, colorCallback)
|
this.setImage(
|
||||||
|
UiImage.Image(url, headers, errorImageDrawable),
|
||||||
|
errorImageDrawable,
|
||||||
|
fadeIn,
|
||||||
|
colorCallback
|
||||||
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,22 @@
|
||||||
|
|
||||||
</com.google.android.material.navigationrail.NavigationRailView>
|
</com.google.android.material.navigationrail.NavigationRailView>
|
||||||
|
|
||||||
|
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
|
android:id="@+id/nav_view"
|
||||||
|
android:layout_height="70dp"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
app:labelVisibilityMode="unlabeled"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:background="?attr/primaryGrayBackground"
|
||||||
|
|
||||||
|
app:itemIconTint="@color/item_select_color"
|
||||||
|
app:itemTextColor="@color/item_select_color"
|
||||||
|
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:menu="@menu/bottom_nav_menu" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/cast_mini_controller_holder"
|
android:id="@+id/cast_mini_controller_holder"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
|
|
@ -677,4 +677,5 @@
|
||||||
</string>
|
</string>
|
||||||
<string name="qualities">Qualities</string>
|
<string name="qualities">Qualities</string>
|
||||||
<string name="profile_background_des">Profile background</string>
|
<string name="profile_background_des">Profile background</string>
|
||||||
|
<string name="unable_to_inflate">UI was unable to be created correctly, this is a MAJOR BUG and should be reported immediately %s</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue