UI Loading and back

This commit is contained in:
LagradOst 2021-06-16 18:54:07 +02:00
parent 93fe31f014
commit 5938d4824d
14 changed files with 593 additions and 291 deletions

View file

@ -156,7 +156,7 @@ class ShiroProvider : MainAPI() {
returnValue.add(AnimeSearchResponse( returnValue.add(AnimeSearchResponse(
i.name.replace("Dubbed", ""), // i.english ?: i.canonicalTitle, i.name.replace("Dubbed", ""), // i.english ?: i.canonicalTitle,
"$mainUrl/${i.slug}", "$mainUrl/anime/${i.slug}",
i.slug, i.slug,
this.name, this.name,
type, type,

View file

@ -26,6 +26,7 @@ sealed class Resource<out T> {
val errorResponse: Any?, //ResponseBody val errorResponse: Any?, //ResponseBody
val errorString: String, val errorString: String,
) : Resource<Nothing>() ) : Resource<Nothing>()
data class Loading(val url : String? = null) : Resource<Nothing>()
} }
suspend fun <T> safeApiCall( suspend fun <T> safeApiCall(

View file

@ -3,8 +3,9 @@ package com.lagradost.cloudstream3.ui
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.View.* import android.view.View.*
import android.widget.ImageView import android.widget.*
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContentProviderCompat.requireContext
import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.json.JsonMapper import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule import com.fasterxml.jackson.module.kotlin.KotlinModule
@ -14,9 +15,13 @@ import com.google.android.gms.cast.framework.CastButtonFactory
import com.google.android.gms.cast.framework.CastSession import com.google.android.gms.cast.framework.CastSession
import com.google.android.gms.cast.framework.media.RemoteMediaClient import com.google.android.gms.cast.framework.media.RemoteMediaClient
import com.google.android.gms.cast.framework.media.uicontroller.UIController import com.google.android.gms.cast.framework.media.uicontroller.UIController
import com.google.android.gms.cast.framework.media.widget.CastSeekBar
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.lagradost.cloudstream3.APIHolder.getApiFromName import com.lagradost.cloudstream3.APIHolder.getApiFromName
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.UIHelper
import com.lagradost.cloudstream3.UIHelper.colorFromAttribute
import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.sortUrls import com.lagradost.cloudstream3.sortUrls
@ -86,23 +91,35 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
init { init {
view.setImageResource(R.drawable.ic_baseline_playlist_play_24) view.setImageResource(R.drawable.ic_baseline_playlist_play_24)
view.setOnClickListener { view.setOnClickListener {
lateinit var dialog: AlertDialog // lateinit var dialog: AlertDialog
val holder = getCurrentMetaData() val holder = getCurrentMetaData()
if (holder != null) { if (holder != null) {
val items = holder.currentLinks val items = holder.currentLinks
if (items.isNotEmpty() && remoteMediaClient?.currentItem != null) { if (items.isNotEmpty() && remoteMediaClient?.currentItem != null) {
val builder = AlertDialog.Builder(view.context, R.style.AlertDialogCustom) // val builder = AlertDialog.Builder(view.context, R.style.AlertDialogCustom)
builder.setTitle("Pick source") /*val builder = BottomSheetDialog(view.context, R.style.AlertDialogCustom)
builder.setTitle("Pick source")*/
val bottomSheetDialog = BottomSheetDialog(view.context)
bottomSheetDialog.setContentView(R.layout.sort_bottom_sheet)
val res = bottomSheetDialog.findViewById<ListView>(R.id.sort_click)!!
//https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.messages.MediaInformation //https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.messages.MediaInformation
val contentUrl = (remoteMediaClient?.currentItem?.media?.contentUrl val contentUrl = (remoteMediaClient?.currentItem?.media?.contentUrl
?: remoteMediaClient?.currentItem?.media?.contentId) ?: remoteMediaClient?.currentItem?.media?.contentId)
builder.setSingleChoiceItems( val sortingMethods = items.map { it.name }.toTypedArray()
items.map { it.name }.toTypedArray(), val sotringIndex = items.indexOfFirst { it.url == contentUrl }
items.indexOfFirst { it.url == contentUrl }
) { _, which -> val arrayAdapter = ArrayAdapter<String>(view.context, R.layout.sort_bottom_single_choice)
arrayAdapter.addAll(sortingMethods.toMutableList())
res.choiceMode = AbsListView.CHOICE_MODE_SINGLE
res.adapter = arrayAdapter
res.setItemChecked(sotringIndex, true)
res.setOnItemClickListener { _, _, which, _ ->
val epData = holder.episodes[holder.currentEpisodeIndex] val epData = holder.episodes[holder.currentEpisodeIndex]
fun loadMirror(index: Int) { fun loadMirror(index: Int) {
@ -144,10 +161,12 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
} }
loadMirror(which) loadMirror(which)
dialog.dismiss() bottomSheetDialog.dismiss()
} }
bottomSheetDialog.show()
/*
dialog = builder.create() dialog = builder.create()
dialog.show() dialog.show()*/
} }
} }
} }
@ -276,5 +295,9 @@ class ControllerActivity : ExpandedControllerActivity() {
uiMediaController.bindViewToUIController(skipBackButton, SkipTimeController(skipBackButton, false)) uiMediaController.bindViewToUIController(skipBackButton, SkipTimeController(skipBackButton, false))
uiMediaController.bindViewToUIController(skipForwardButton, SkipTimeController(skipForwardButton, true)) uiMediaController.bindViewToUIController(skipForwardButton, SkipTimeController(skipForwardButton, true))
uiMediaController.bindViewToUIController(skipOpButton, SkipNextEpisodeController(skipOpButton)) uiMediaController.bindViewToUIController(skipOpButton, SkipNextEpisodeController(skipOpButton))
/* val progressBar: CastSeekBar? = findViewById(R.id.cast_seek_bar)
progressBar?.backgroundTintList = (UIHelper.adjustAlpha(colorFromAttribute(R.attr.colorPrimary), 0.35f))
*/
} }
} }

View file

@ -10,11 +10,14 @@ import android.view.View
import android.view.View.GONE import android.view.View.GONE
import android.view.View.VISIBLE import android.view.View.VISIBLE
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.widget.NestedScrollView import androidx.core.widget.NestedScrollView
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -28,7 +31,9 @@ import com.google.android.material.button.MaterialButton
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.UIHelper.colorFromAttribute import com.lagradost.cloudstream3.UIHelper.colorFromAttribute
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.UIHelper.getStatusBarHeight
import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable
import com.lagradost.cloudstream3.UIHelper.popCurrentPage
import com.lagradost.cloudstream3.UIHelper.popupMenu import com.lagradost.cloudstream3.UIHelper.popupMenu
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons
import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.Resource
@ -137,14 +142,47 @@ class ResultFragment : Fragment() {
} }
} }
/// 0 = LOADING, 1 = ERROR LOADING, 2 = LOADED
fun updateVisStatus(state: Int) {
when (state) {
0 -> {
result_loading.visibility = VISIBLE
result_finish_loading.visibility = GONE
result_reload_connectionerror.visibility = GONE
result_reload_connection_open_in_browser.visibility = GONE
}
1 -> {
result_loading.visibility = GONE
result_finish_loading.visibility = GONE
result_reload_connectionerror.visibility = VISIBLE
result_reload_connection_open_in_browser.visibility = if (url == null) GONE else VISIBLE
}
2 -> {
result_loading.visibility = GONE
result_finish_loading.visibility = VISIBLE
result_reload_connectionerror.visibility = GONE
result_reload_connection_open_in_browser.visibility = GONE
}
}
}
private var currentPoster: String? = null private var currentPoster: String? = null
var url: String? = null
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
activity?.fixPaddingStatusbar(result_scroll) activity?.fixPaddingStatusbar(result_scroll)
activity?.fixPaddingStatusbar(result_barstatus) activity?.fixPaddingStatusbar(result_barstatus)
val backParameter = result_back.layoutParams as CoordinatorLayout.LayoutParams
backParameter.setMargins(backParameter.leftMargin,
backParameter.topMargin + requireContext().getStatusBarHeight(),
backParameter.rightMargin,
backParameter.bottomMargin)
result_back.layoutParams = backParameter
if (activity?.isCastApiAvailable() == true) { if (activity?.isCastApiAvailable() == true) {
CastButtonFactory.setUpMediaRouteButton(activity, media_route_button) CastButtonFactory.setUpMediaRouteButton(activity, media_route_button)
val castContext = CastContext.getSharedInstance(requireActivity().applicationContext) val castContext = CastContext.getSharedInstance(requireActivity().applicationContext)
@ -160,16 +198,20 @@ class ResultFragment : Fragment() {
} }
// activity?.fixPaddingStatusbar(result_toolbar) // activity?.fixPaddingStatusbar(result_toolbar)
val url = arguments?.getString("url") url = arguments?.getString("url")
val slug = arguments?.getString("slug") val slug = arguments?.getString("slug")
val apiName = arguments?.getString("apiName") val apiName = arguments?.getString("apiName")
result_scroll.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, _ -> result_scroll.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, _ ->
if (result_poster_blur == null) return@OnScrollChangeListener if (result_poster_blur == null) return@OnScrollChangeListener
result_poster_blur.alpha = maxOf(0f, (0.7f - scrollY / 1000f)) result_poster_blur.alpha = maxOf(0f, (0.7f - scrollY / 1000f))
val setAlpha = 1f - scrollY / 200f
result_back.alpha = setAlpha
result_poster_blur_holder.translationY = -scrollY.toFloat() result_poster_blur_holder.translationY = -scrollY.toFloat()
// result_back.translationY = -scrollY.toFloat()
//result_barstatus.alpha = scrollY / 200f //result_barstatus.alpha = scrollY / 200f
//result_barstatus.visibility = if (scrollY > 0) View.VISIBLE else View.GONE§ //result_barstatus.visibility = if (scrollY > 0) View.VISIBLE else View.GONE§
result_back.visibility = if (setAlpha > 0) VISIBLE else GONE
}) })
result_toolbar.setNavigationIcon(R.drawable.ic_baseline_arrow_back_24) result_toolbar.setNavigationIcon(R.drawable.ic_baseline_arrow_back_24)
@ -177,77 +219,85 @@ class ResultFragment : Fragment() {
activity?.onBackPressed() activity?.onBackPressed()
} }
result_back.setOnClickListener {
requireActivity().popCurrentPage()
}
fun handleAction(episodeClick: EpisodeClickEvent) {
//val id = episodeClick.data.id
val index = episodeClick.data.index
val buildInPlayer = true
currentLoadingCount++
when (episodeClick.action) {
ACTION_CHROME_CAST_EPISODE -> {
val currentLoad = currentLoadingCount
val builder = AlertDialog.Builder(requireContext(), R.style.AlertDialogCustomTransparent)
val customLayout = layoutInflater.inflate(R.layout.dialog_loading, null)
builder.setView(customLayout)
val dialog = builder.create()
dialog.show()
dialog.setOnDismissListener {
currentLoadingCount++
}
// Toast.makeText(activity, "Loading links", Toast.LENGTH_SHORT).show()
viewModel.loadEpisode(episodeClick.data, true) { data ->
if (currentLoadingCount != currentLoad) return@loadEpisode
dialog.dismiss()
when (data) {
is Resource.Failure -> {
Toast.makeText(activity, "Failed to load links", Toast.LENGTH_SHORT).show()
}
is Resource.Success -> {
val eps = currentEpisodes ?: return@loadEpisode
context?.startCast(
apiName ?: return@loadEpisode,
currentHeaderName,
currentPoster,
episodeClick.data.index,
eps,
sortUrls(data.value),
startTime = episodeClick.data.getRealPosition()
)
}
}
}
}
ACTION_PLAY_EPISODE_IN_PLAYER -> {
if (buildInPlayer) {
(requireActivity() as AppCompatActivity).supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.enter_anim,
R.anim.exit_anim,
R.anim.pop_enter,
R.anim.pop_exit)
.add(R.id.homeRoot,
PlayerFragment.newInstance(PlayerData(index, null, 0),
episodeClick.data.getRealPosition())
)
.commit()
}
}
ACTION_RELOAD_EPISODE -> {
/*viewModel.load(episodeClick.data) { res ->
if (res is Resource.Success) {
playEpisode(allEpisodes[id], index)
}
}*/
}
}
}
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>? = activity?.let { it -> val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>? = activity?.let { it ->
EpisodeAdapter( EpisodeAdapter(
it, it,
ArrayList(), ArrayList(),
result_episodes, result_episodes,
) { episodeClick -> ) { episodeClick ->
//val id = episodeClick.data.id handleAction(episodeClick)
val index = episodeClick.data.index
val buildInPlayer = true
currentLoadingCount++
when (episodeClick.action) {
ACTION_CHROME_CAST_EPISODE -> {
val currentLoad = currentLoadingCount
val builder = AlertDialog.Builder(requireContext(), R.style.AlertDialogCustomTransparent)
val customLayout = layoutInflater.inflate(R.layout.dialog_loading, null)
builder.setView(customLayout)
val dialog = builder.create()
dialog.show()
dialog.setOnDismissListener {
currentLoadingCount++
}
// Toast.makeText(activity, "Loading links", Toast.LENGTH_SHORT).show()
viewModel.loadEpisode(episodeClick.data, true) { data ->
if (currentLoadingCount != currentLoad) return@loadEpisode
dialog.dismiss()
when (data) {
is Resource.Failure -> {
Toast.makeText(activity, "Failed to load links", Toast.LENGTH_SHORT).show()
}
is Resource.Success -> {
val eps = currentEpisodes ?: return@loadEpisode
context?.startCast(
apiName ?: return@loadEpisode,
currentHeaderName,
currentPoster,
episodeClick.data.index,
eps,
sortUrls(data.value),
startTime = episodeClick.data.getRealPosition()
)
}
}
}
}
ACTION_PLAY_EPISODE_IN_PLAYER -> {
if (buildInPlayer) {
(requireActivity() as AppCompatActivity).supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.enter_anim,
R.anim.exit_anim,
R.anim.pop_enter,
R.anim.pop_exit)
.add(R.id.homeRoot,
PlayerFragment.newInstance(PlayerData(index, null, 0),
episodeClick.data.getRealPosition())
)
.commit()
}
}
ACTION_RELOAD_EPISODE -> {
/*viewModel.load(episodeClick.data) { res ->
if (res is Resource.Success) {
playEpisode(allEpisodes[id], index)
}
}*/
}
}
} }
} }
@ -288,6 +338,8 @@ class ResultFragment : Fragment() {
is Resource.Success -> { is Resource.Success -> {
val d = data.value val d = data.value
if (d is LoadResponse) { if (d is LoadResponse) {
updateVisStatus(2)
result_bookmark_button.text = "Watching" result_bookmark_button.text = "Watching"
currentHeaderName = d.name currentHeaderName = d.name
@ -407,6 +459,34 @@ activity?.startActivityForResult(vlcIntent, REQUEST_CODE)
result_tag_holder.visibility = GONE result_tag_holder.visibility = GONE
result_status.visibility = GONE result_status.visibility = GONE
when (d.type) {
TvType.Movie -> {
result_play_movie.visibility = VISIBLE
result_episodes_text.visibility = GONE
result_episodes.visibility = GONE
result_play_movie.setOnClickListener {
val card = currentEpisodes?.first() ?: return@setOnClickListener
if (requireContext().isCastApiAvailable()) {
val castContext = CastContext.getSharedInstance(requireContext())
if (castContext.castState == CastState.CONNECTED) {
handleAction(EpisodeClickEvent(ACTION_CHROME_CAST_EPISODE, card))
} else {
handleAction(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card))
}
} else {
handleAction(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card))
}
}
}
else -> {
result_play_movie.visibility = GONE
result_episodes_text.visibility = VISIBLE
result_episodes.visibility = VISIBLE
}
}
when (d) { when (d) {
is AnimeLoadResponse -> { is AnimeLoadResponse -> {
result_status.visibility = VISIBLE result_status.visibility = VISIBLE
@ -438,15 +518,34 @@ activity?.startActivityForResult(vlcIntent, REQUEST_CODE)
} }
else -> result_title.text = d.name else -> result_title.text = d.name
} }
} else {
updateVisStatus(1)
} }
} }
is Resource.Failure -> { is Resource.Failure -> {
updateVisStatus(1)
}
is Resource.Loading -> {
updateVisStatus(0)
} }
} }
} }
if (viewModel.resultResponse.value == null && apiName != null && slug != null) if (apiName != null && slug != null) {
viewModel.load(requireContext(), slug, apiName) result_reload_connectionerror.setOnClickListener {
viewModel.load(requireContext(), slug, apiName)
}
if (url != null) {
result_reload_connection_open_in_browser.setOnClickListener {
val i = Intent(Intent.ACTION_VIEW)
i.data = Uri.parse(url)
startActivity(i)
}
}
if (viewModel.resultResponse.value == null)
viewModel.load(requireContext(), slug, apiName)
}
} }
} }

View file

@ -56,11 +56,14 @@ class ResultViewModel : ViewModel() {
} }
fun load(context: Context, url: String, apiName: String) = viewModelScope.launch { fun load(context: Context, url: String, apiName: String) = viewModelScope.launch {
_resultResponse.postValue(Resource.Loading(url))
_apiName.postValue(apiName) _apiName.postValue(apiName)
val api = getApiFromName(apiName) val api = getApiFromName(apiName)
val data = safeApiCall { val data = safeApiCall {
api.load(url) api.load(url)
} }
_resultResponse.postValue(data) _resultResponse.postValue(data)
when (data) { when (data) {

View file

@ -114,8 +114,6 @@ class SearchFragment : Fragment() {
main_search.setOnQueryTextListener(object : SearchView.OnQueryTextListener { main_search.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean { override fun onQueryTextSubmit(query: String): Boolean {
search_exit_icon.alpha = 0f
search_loading_bar.alpha = 1f
searchViewModel.search(query) searchViewModel.search(query)
return true return true
} }
@ -128,17 +126,26 @@ class SearchFragment : Fragment() {
observe(searchViewModel.searchResponse) { observe(searchViewModel.searchResponse) {
when (it) { when (it) {
is Resource.Success -> { is Resource.Success -> {
(cardSpace.adapter as SearchAdapter).cardList = it.value it?.value?.let { data ->
(cardSpace.adapter as SearchAdapter).notifyDataSetChanged() (cardSpace.adapter as SearchAdapter).cardList = data
(cardSpace.adapter as SearchAdapter).notifyDataSetChanged()
}
search_exit_icon.alpha = 1f
search_loading_bar.alpha = 0f
} }
is Resource.Failure -> { is Resource.Failure -> {
Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show() Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show()
search_exit_icon.alpha = 1f
search_loading_bar.alpha = 0f
}
is Resource.Loading -> {
search_exit_icon.alpha = 0f
search_loading_bar.alpha = 1f
} }
} }
search_exit_icon.alpha = 1f
search_loading_bar.alpha = 0f
} }
(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro") searchViewModel.search("overlord")
// (activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro")
/* /*
(requireActivity() as AppCompatActivity).supportFragmentManager.beginTransaction() (requireActivity() as AppCompatActivity).supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.enter_anim, .setCustomAnimations(R.anim.enter_anim,

View file

@ -17,6 +17,7 @@ class SearchViewModel : ViewModel() {
val searchResponse: LiveData<Resource<ArrayList<Any>>> get() = _searchResponse val searchResponse: LiveData<Resource<ArrayList<Any>>> get() = _searchResponse
fun search(query: String) = viewModelScope.launch { fun search(query: String) = viewModelScope.launch {
_searchResponse.postValue(Resource.Loading())
val data = safeApiCall { val data = safeApiCall {
api.search(query) api.search(query)
} }

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,6v3l4,-4 -4,-4v3c-4.42,0 -8,3.58 -8,8 0,1.57 0.46,3.03 1.24,4.26L6.7,14.8c-0.45,-0.83 -0.7,-1.79 -0.7,-2.8 0,-3.31 2.69,-6 6,-6zM18.76,7.74L17.3,9.2c0.44,0.84 0.7,1.79 0.7,2.8 0,3.31 -2.69,6 -6,6v-3l-4,4 4,4v-3c4.42,0 8,-3.58 8,-8 0,-1.57 -0.46,-3.03 -1.24,-4.26z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector>

View file

@ -9,241 +9,323 @@
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
> >
<com.google.android.material.appbar.AppBarLayout
<ProgressBar
android:visibility="visible"
tools:visibility="gone"
android:id="@+id/result_loading"
android:layout_gravity="center"
android:layout_width="50dp" android:layout_height="50dp">
</ProgressBar>
<com.google.android.material.button.MaterialButton
android:layout_columnWeight="1"
android:layout_gravity="center"
android:layout_height="50dp"
android:layout_marginBottom="50dp"
app:icon="@drawable/ic_baseline_autorenew_24"
app:iconSize="20dp"
android:text="@string/reload_error"
android:id="@+id/result_reload_connectionerror"
android:textAllCaps="false"
android:textSize="15sp"
app:cornerRadius="5dp"
app:strokeWidth="2dp"
app:strokeColor="@color/colorAccent"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
app:rippleColor="@color/colorPrimary"
android:layout_width="wrap_content"
android:minWidth="200dp"
>
</com.google.android.material.button.MaterialButton>
<com.google.android.material.button.MaterialButton
android:layout_columnWeight="1"
android:layout_gravity="center"
android:layout_height="50dp"
android:layout_marginTop="50dp"
app:icon="@drawable/ic_baseline_public_24"
app:iconSize="20dp"
android:text="@string/result_open_in_browser"
android:id="@+id/result_reload_connection_open_in_browser"
android:textAllCaps="false"
android:textSize="15sp"
app:cornerRadius="5dp"
app:strokeWidth="2dp"
app:strokeColor="@color/colorAccent"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
app:rippleColor="@color/colorPrimary"
android:layout_width="wrap_content"
android:minWidth="200dp"
>
</com.google.android.material.button.MaterialButton>
<FrameLayout
android:visibility="gone" android:visibility="gone"
android:id="@+id/result_barstatus" tools:visibility="visible"
android:background="@color/grayBackground" android:id="@+id/result_finish_loading" android:layout_width="match_parent"
android:layout_width="match_parent" android:layout_height="match_parent">
android:alpha="0" <com.google.android.material.appbar.AppBarLayout
tools:alpha="1" android:visibility="gone"
android:layout_height="wrap_content"> android:id="@+id/result_barstatus"
<com.google.android.material.appbar.MaterialToolbar android:background="@color/grayBackground"
android:id="@+id/result_toolbar"
android:paddingTop="@dimen/navbarHeight"
app:title="Perfect Run"
app:layout_scrollFlags="scroll|enterAlways"
android:layout_width="match_parent" android:layout_height="wrap_content">
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout android:layout_width="match_parent" android:id="@+id/result_poster_blur_holder"
android:layout_height="180dp">
<ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:alpha="0"
android:scaleType="centerCrop" tools:alpha="1"
android:alpha="0.7" android:layout_height="wrap_content">
tools:src="@drawable/example_poster" <com.google.android.material.appbar.MaterialToolbar
android:background="@color/darkBackground" android:id="@+id/result_toolbar"
android:id="@+id/result_poster_blur" android:paddingTop="@dimen/navbarHeight"
android:contentDescription=""/> app:title="Perfect Run"
<ImageView android:src="@drawable/background_shadow" android:layout_gravity="bottom" app:layout_scrollFlags="scroll|enterAlways"
android:layout_width="match_parent" android:layout_height="30dp"> android:layout_width="match_parent" android:layout_height="wrap_content">
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout>
</ImageView> <FrameLayout android:layout_width="match_parent" android:id="@+id/result_poster_blur_holder"
</FrameLayout> android:layout_height="180dp">
<androidx.core.widget.NestedScrollView <ImageView
android:id="@+id/result_scroll" android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="match_parent"
<LinearLayout android:scaleType="centerCrop"
android:orientation="vertical" android:alpha="0.7"
android:layout_marginStart="10dp" tools:src="@drawable/example_poster"
android:layout_marginEnd="10dp" android:background="@color/darkBackground"
android:layout_width="match_parent" android:id="@+id/result_poster_blur"
android:layout_height="match_parent"> android:contentDescription=""/>
<!-- <ImageView android:src="@drawable/background_shadow" android:layout_gravity="bottom"
<LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_width="match_parent" android:layout_height="30dp">
android:layout_height="30dp">
<ImageView android:id="@+id/result_back" android:src="@drawable/ic_baseline_arrow_back_24"
android:layout_width="wrap_content" android:layout_height="match_parent">
</ImageView> </ImageView>
</LinearLayout>--> </FrameLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/result_scroll" android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout <LinearLayout
android:layout_marginTop="10dp" android:orientation="vertical"
android:orientation="horizontal" android:layout_width="match_parent" android:layout_marginStart="10dp"
android:layout_height="wrap_content"> android:layout_marginEnd="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--
<LinearLayout android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="30dp">
<ImageView android:id="@+id/result_back" android:src="@drawable/ic_baseline_arrow_back_24"
android:layout_width="wrap_content" android:layout_height="match_parent">
<androidx.cardview.widget.CardView </ImageView>
app:cardCornerRadius="@dimen/roundedImageRadius" </LinearLayout>-->
android:layout_width="100dp" <LinearLayout
android:layout_height="140dp"> android:layout_marginTop="10dp"
<ImageView android:orientation="horizontal" android:layout_width="match_parent"
android:id="@+id/result_poster" android:layout_height="wrap_content">
android:scaleType="centerCrop"
android:layout_width="match_parent" <androidx.cardview.widget.CardView
android:layout_height="match_parent" app:cardCornerRadius="@dimen/roundedImageRadius"
tools:src="@drawable/example_poster" android:layout_width="100dp"
android:contentDescription="@string/result_poster"/> android:layout_height="140dp">
</androidx.cardview.widget.CardView> <ImageView
android:id="@+id/result_poster"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:src="@drawable/example_poster"
android:contentDescription="@string/result_poster"/>
</androidx.cardview.widget.CardView>
<LinearLayout android:layout_marginLeft="10dp" <LinearLayout
android:gravity="center_vertical" android:layout_marginLeft="10dp"
android:orientation="vertical" android:gravity="center_vertical"
android:layout_width="wrap_content" android:orientation="vertical"
android:layout_height="wrap_content"> android:layout_width="wrap_content"
<TextView
tools:text="The Perfect Run The Perfect Run The Perfect Run"
android:id="@+id/result_title"
android:textSize="20sp"
android:textStyle="bold"
android:textColor="?attr/textColor" android:layout_width="wrap_content"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
</TextView> <TextView
<TextView android:layout_marginRight="50dp"
android:id="@+id/result_year" tools:text="The Perfect Run The Perfect Run The Perfect Run"
tools:text="2021" android:id="@+id/result_title"
android:textStyle="bold" android:textSize="20sp"
android:textSize="15sp" android:textStyle="bold"
android:textColor="?attr/textColor" android:layout_width="wrap_content" android:textColor="?attr/textColor" android:layout_width="wrap_content"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
</TextView> </TextView>
<TextView <TextView
android:id="@+id/result_status" android:id="@+id/result_year"
tools:text="Finished" tools:text="2021"
android:textSize="15sp" android:textStyle="bold"
android:textColor="?attr/textColor" android:layout_width="wrap_content" android:textSize="15sp"
android:layout_height="wrap_content"> android:textColor="?attr/textColor" android:layout_width="wrap_content"
</TextView> android:layout_height="wrap_content">
</TextView>
<TextView
android:id="@+id/result_status"
tools:text="Finished"
android:textSize="15sp"
android:textColor="?attr/textColor" android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
</LinearLayout> </LinearLayout>
<GridLayout android:layout_width="match_parent" android:layout_height="50dp">
<com.google.android.material.button.MaterialButton
android:visibility="visible"
android:layout_gravity="center_vertical"
app:cornerRadius="4dp"
android:id="@+id/result_bookmark_button"
tools:text="Bookmark"
app:rippleColor="?attr/colorPrimary"
android:textColor="?attr/textColor"
app:iconTint="?attr/textColor"
android:textAllCaps="false"
app:icon="@drawable/ic_outline_remove_red_eye_24"
android:backgroundTint="@color/transparent"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="45dp">
</com.google.android.material.button.MaterialButton>
</LinearLayout> <!--<ImageView
<GridLayout android:layout_width="match_parent" android:layout_height="50dp"> android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_bookmark_border_24"
android:layout_width="wrap_content"
android:layout_height="match_parent">
</ImageView>-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/media_route_button_holder"
android:layout_gravity="center_vertical|end"
>
<androidx.mediarouter.app.MediaRouteButton
android:id="@+id/media_route_button"
android:layout_width="50dp"
android:layout_height="50dp"
android:mediaRouteTypes="user"
android:visibility="gone"
/>
<ImageView
android:id="@+id/result_share"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginRight="10dp"
android:elevation="10dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_outline_share_24"
android:layout_gravity="center" android:contentDescription="@string/result_share">
</ImageView>
<ImageView
android:id="@+id/result_openinbrower"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_margin="5dp"
android:elevation="10dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_public_24"
android:layout_gravity="center"
android:contentDescription="@string/result_open_in_browser">
</ImageView>
</LinearLayout>
</GridLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/result_plot"
android:textSize="17sp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textStyle="normal"
android:textColor="?attr/textColor"
/>
<TextView
android:id="@+id/result_descript"
tools:text="Ryan Quicksave Romano is an eccentric adventurer with a strange power: he can create a save-point in time and redo his life whenever he dies. Arriving in New Rome, the glitzy capital of sin of a rebuilding Europe, he finds the city torn between mega-corporations, sponsored heroes, superpowered criminals, and true monsters. It's a time of chaos, where potions can grant the power to rule the world and dangers lurk everywhere. "
android:layout_width="match_parent" android:layout_height="wrap_content">
</TextView>
<TextView
android:id="@+id/result_tag_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/result_tags"
android:textSize="17sp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textStyle="normal"
android:textColor="?attr/textColor"
/>
<com.lagradost.cloudstream3.widget.FlowLayout android:id="@+id/result_tag"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.lagradost.cloudstream3.widget.FlowLayout>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:visibility="visible" android:visibility="visible"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
app:cornerRadius="4dp" app:cornerRadius="4dp"
android:id="@+id/result_bookmark_button" android:id="@+id/result_play_movie"
tools:text="Bookmark" android:text="@string/play_movie_button"
app:rippleColor="?attr/colorPrimary" app:rippleColor="?attr/colorPrimary"
android:textColor="?attr/textColor" android:textColor="?attr/textColor"
app:iconTint="?attr/textColor" app:iconTint="?attr/textColor"
android:textAllCaps="false" android:textAllCaps="false"
app:icon="@drawable/ic_outline_remove_red_eye_24" android:clickable="true"
android:focusable="true"
app:iconGravity="textStart"
app:strokeColor="?attr/textColor"
app:icon="@drawable/ic_baseline_play_arrow_24"
android:backgroundTint="@color/transparent" android:backgroundTint="@color/transparent"
style="@style/Widget.MaterialComponents.Button.OutlinedButton" style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="45dp"> android:layout_height="45dp">
</com.google.android.material.button.MaterialButton> </com.google.android.material.button.MaterialButton>
<TextView
<!--<ImageView
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_bookmark_border_24"
android:layout_width="wrap_content"
android:layout_height="match_parent">
</ImageView>-->
<LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/media_route_button_holder" android:id="@+id/result_episodes_text"
android:layout_gravity="center_vertical|end" tools:text="8 Episodes"
> android:textSize="17sp"
<androidx.mediarouter.app.MediaRouteButton android:layout_marginTop="10dp"
android:id="@+id/media_route_button" android:layout_marginBottom="10dp"
android:layout_width="50dp" android:textStyle="normal"
android:layout_height="50dp" android:textColor="?attr/textColor"
android:mediaRouteTypes="user" />
android:visibility="gone" <androidx.recyclerview.widget.RecyclerView
/> android:layout_marginTop="10dp"
<ImageView android:paddingBottom="100dp"
android:id="@+id/result_share" tools:listitem="@layout/result_episode"
android:layout_width="25dp" android:layout_width="match_parent"
android:layout_height="25dp" android:layout_height="wrap_content"
android:layout_marginRight="10dp" android:id="@+id/result_episodes"
android:elevation="10dp" />
android:background="?android:attr/selectableItemBackgroundBorderless" </LinearLayout>
android:src="@drawable/ic_outline_share_24" </androidx.core.widget.NestedScrollView>
android:layout_gravity="center" android:contentDescription="@string/result_share"> <LinearLayout
</ImageView> android:layout_gravity="bottom"
<ImageView android:layout_width="match_parent"
android:id="@+id/result_openinbrower" android:layout_height="wrap_content">
android:layout_width="25dp" <fragment
android:layout_height="25dp" app:customCastBackgroundColor="?attr/bitDarkerGrayBackground"
android:layout_margin="5dp" app:castControlButtons="@array/cast_mini_controller_control_buttons"
android:elevation="10dp" android:id="@+id/cast_mini_controller"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_public_24"
android:layout_gravity="center" android:contentDescription="@string/result_open_in_browser">
</ImageView>
</LinearLayout>
</GridLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/result_plot"
android:textSize="17sp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textStyle="normal"
android:textColor="?attr/textColor"
/>
<TextView
android:id="@+id/result_descript"
tools:text="Ryan Quicksave Romano is an eccentric adventurer with a strange power: he can create a save-point in time and redo his life whenever he dies. Arriving in New Rome, the glitzy capital of sin of a rebuilding Europe, he finds the city torn between mega-corporations, sponsored heroes, superpowered criminals, and true monsters. It's a time of chaos, where potions can grant the power to rule the world and dangers lurk everywhere. "
android:layout_width="match_parent" android:layout_height="wrap_content">
</TextView>
<TextView
android:id="@+id/result_tag_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/result_tags"
android:textSize="17sp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textStyle="normal"
android:textColor="?attr/textColor"
/>
<com.lagradost.cloudstream3.widget.FlowLayout android:id="@+id/result_tag"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.lagradost.cloudstream3.widget.FlowLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/result_episodes_text"
tools:text="8 Episodes"
android:textSize="17sp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textStyle="normal"
android:textColor="?attr/textColor"
/>
<androidx.recyclerview.widget.RecyclerView
android:layout_marginTop="10dp"
android:paddingBottom="100dp"
tools:listitem="@layout/result_episode"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/result_episodes" android:visibility="gone"
/> class="com.lagradost.cloudstream3.ui.MyMiniControllerFragment"
tools:ignore="FragmentTagUsage">
</fragment>
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </FrameLayout>
<LinearLayout
android:layout_gravity="bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<fragment
app:customCastBackgroundColor="?attr/bitDarkerGrayBackground"
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>
<!-- <!--
@ -264,5 +346,16 @@
android:foreground="?android:attr/selectableItemBackgroundBorderless" android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/search_poster_descript"/> android:contentDescription="@string/search_poster_descript"/>
</androidx.cardview.widget.CardView>--> </androidx.cardview.widget.CardView>-->
<ImageView
android:id="@+id/result_back"
android:clickable="true"
android:focusable="true"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_margin="10dp"
android:layout_gravity="end"
android:tint="?attr/white"
android:src="@drawable/ic_baseline_clear_24"
android:contentDescription="@string/result_go_back">
</ImageView>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:orientation="vertical"
android:layout_width="match_parent"
android:background="@null"
android:layout_height="match_parent">
<!--<androidx.cardview.widget.CardView
app:cardCornerRadius="10dp"
android:backgroundTint="?attr/boxItemBackground"
android:layout_width="match_parent" android:layout_height="wrap_content">
<TextView
style="@style/AppTextViewStyle"
android:gravity="center_vertical"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:layout_gravity="center_vertical"
android:text="@string/pick_source" android:textColor="?attr/textColor" android:textSize="18sp"
android:layout_width="wrap_content" android:layout_height="55dp"
>
</TextView>
</androidx.cardview.widget.CardView>-->
<TextView
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:layout_marginTop="20dp"
android:layout_marginBottom="10dp"
android:textStyle="bold"
android:text="@string/pick_source"
android:textSize="20sp"
android:textColor="?attr/textColor"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</TextView>
<ListView
android:layout_marginTop="-10dp"
android:paddingTop="10dp"
android:id="@+id/sort_click"
android:background="?attr/bitDarkerGrayBackground"
tools:listitem="@layout/sort_bottom_single_choice"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>

View file

@ -0,0 +1,13 @@
<CheckedTextView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:textColor="?attr/textColor"
tools:text="Example Text"
android:background="?attr/bitDarkerGrayBackground"
android:checkMark="?android:attr/listChoiceIndicatorSingle"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"/>

View file

@ -30,4 +30,8 @@
<string name="type_dropped">Dropped</string> <string name="type_dropped">Dropped</string>
<string name="type_plan_to_watch">Plan to Watch</string> <string name="type_plan_to_watch">Plan to Watch</string>
<string name="type_none">None</string> <string name="type_none">None</string>
<string name="play_movie_button">Play Movie</string>
<string name="pick_source">Pick Source</string>
<string name="reload_error">Retry connection…</string>
<string name="result_go_back">Go Back</string>
</resources> </resources>

View file

@ -129,8 +129,8 @@
@array/cast_expanded_controller_control_buttons @array/cast_expanded_controller_control_buttons
</item> </item>
<item name="castButtonColor">@null</item> <item name="castButtonColor">@null</item>
<item name="castSeekBarProgressAndThumbColor">@color/white</item> <item name="castSeekBarProgressAndThumbColor">@color/white</item> <!--@color/white ?attr/colorPrimary-->
<item name="castSeekBarSecondaryProgressColor">?attr/darkBackground</item> <!--CHECK--> <item name="castSeekBarSecondaryProgressColor">?attr/darkBackground</item> <!--CHECK ?attr/darkBackground ?attr/colorPrimary-->
<item name="castBackground">?attr/colorPrimary</item> <item name="castBackground">?attr/colorPrimary</item>
<item name="castProgressBarColor">?attr/colorPrimary</item> <item name="castProgressBarColor">?attr/colorPrimary</item>
<item name="castPlayButtonDrawable">@drawable/ic_baseline_play_arrow_24</item> <item name="castPlayButtonDrawable">@drawable/ic_baseline_play_arrow_24</item>