From f97fb3c4848bb91953842f88f9952cd4eb743b48 Mon Sep 17 00:00:00 2001 From: Jace <54625750+Jacekun@users.noreply.github.com> Date: Sat, 27 Nov 2021 21:54:43 +0800 Subject: [PATCH 1/3] add main page to HDM provider (#276) --- .../movieproviders/HDMProvider.kt | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/HDMProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/HDMProvider.kt index b0dff497..8ea7852c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/HDMProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/HDMProvider.kt @@ -17,6 +17,8 @@ class HDMProvider : MainAPI() { get() = setOf( TvType.Movie, ) + override val hasMainPage: Boolean + get() = true override fun search(query: String): List { val url = "$mainUrl/search/$query" @@ -74,4 +76,49 @@ class HDMProvider : MainAPI() { "$mainUrl/src/player/?v=$data", poster, year, descript, null ) } + + override fun getMainPage(): HomePageResponse { + val html = get("$mainUrl", timeout = 25).text + val document = Jsoup.parse(html) + val all = ArrayList() + + val mainbody = document.getElementsByTag("body") + ?.select("div.homeContentOuter > section > div.container > div") + // Fetch row title + val inner = mainbody?.select("div.col-md-2.col-sm-2.mrgb") + val title = mainbody?.select("div > div")?.firstOrNull()?.select("div.title.titleBar")?.text() ?: "Unnamed Row" + // Fetch list of items and map + if (inner != null) { + val elements: List = inner.map { + + val aa = it.select("a").firstOrNull() + val item = aa?.select("div.item") + val href = aa?.attr("href") + val link = when (href != null) { + true -> fixUrl(href) + false -> "" + } + val name = item?.select("div.movie-details")?.text() ?: "" + var image = item?.select("img")?.get(1)?.attr("src") ?: "" + val year = null + + MovieSearchResponse( + name, + link, + this.name, + TvType.Movie, + image, + year, + null, + ) + } + + all.add( + HomePageList( + title, elements + ) + ) + } + return HomePageResponse(all) + } } \ No newline at end of file From 6c42fbbacb54bd7654d9213727e7dd16ef731f2e Mon Sep 17 00:00:00 2001 From: LagradOst Date: Sat, 27 Nov 2021 19:49:51 +0100 Subject: [PATCH 2/3] UI fix and android TV fix --- .../lagradost/cloudstream3/MainActivity.kt | 7 +- .../cloudstream3/ui/home/HomeViewModel.kt | 3 +- .../cloudstream3/ui/player/PlayerFragment.kt | 105 ++++-- app/src/main/res/drawable/dub_bg_color.xml | 2 +- .../drawable/ic_baseline_fast_forward_24.xml | 5 + app/src/main/res/drawable/sub_bg_color.xml | 2 +- app/src/main/res/drawable/type_bg_color.xml | 2 +- app/src/main/res/drawable/video_locked.xml | 4 +- app/src/main/res/drawable/video_unlocked.xml | 4 +- .../res/layout/download_child_episode.xml | 4 +- .../res/layout/download_header_episode.xml | 2 +- .../res/layout/fragment_child_downloads.xml | 2 +- .../main/res/layout/fragment_downloads.xml | 1 + app/src/main/res/layout/fragment_home.xml | 11 +- app/src/main/res/layout/fragment_result.xml | 2 +- app/src/main/res/layout/fragment_search.xml | 8 +- .../main/res/layout/home_result_big_grid.xml | 2 +- app/src/main/res/layout/home_result_grid.xml | 2 +- .../main/res/layout/player_custom_layout.xml | 303 ++---------------- app/src/main/res/layout/result_episode.xml | 2 +- .../main/res/layout/result_episode_large.xml | 2 +- .../main/res/layout/search_result_compact.xml | 4 +- .../main/res/layout/search_result_grid.xml | 2 +- .../layout/search_result_super_compact.xml | 4 +- app/src/main/res/values/array.xml | 4 +- app/src/main/res/values/colors.xml | 4 +- app/src/main/res/values/dimens.xml | 4 +- app/src/main/res/values/styles.xml | 22 ++ 28 files changed, 187 insertions(+), 332 deletions(-) create mode 100644 app/src/main/res/drawable/ic_baseline_fast_forward_24.xml diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index 6eedee5e..0c446f72 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -169,6 +169,9 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { } } + if(keyEventListener?.invoke(event) == true) { + return true + } return super.dispatchKeyEvent(event) } @@ -257,6 +260,8 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { val onDialogDismissedEvent = Event() var playerEventListener: ((PlayerEventType) -> Unit)? = null + var keyEventListener: ((KeyEvent?) -> Boolean)? = null + var currentToast: Toast? = null @@ -411,7 +416,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) - val currentTheme = when (settingsManager.getString(getString(R.string.app_theme_key), "Black")) { + val currentTheme = when (settingsManager.getString(getString(R.string.app_theme_key), "AmoledLight")) { "Black" -> R.style.AppTheme "Light" -> R.style.LightMode "Amoled" -> R.style.AmoledMode diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt index d6fb7508..df367e8a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt @@ -143,9 +143,10 @@ class HomeViewModel : ViewModel() { } _apiName.postValue(repo?.name) + _randomItems.postValue(listOf()) + if (repo?.hasMainPage == true) { _page.postValue(Resource.Loading()) - _randomItems.postValue(null) val data = repo?.getMainPage() when (data) { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt index cd8d99cf..7d1dae83 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt @@ -9,6 +9,7 @@ import android.app.RemoteAction import android.content.* import android.content.Context.AUDIO_SERVICE import android.content.pm.ActivityInfo +import android.content.res.ColorStateList import android.content.res.Resources import android.database.ContentObserver import android.graphics.Color @@ -19,11 +20,8 @@ import android.net.Uri import android.os.* import android.provider.Settings import android.util.TypedValue -import android.view.LayoutInflater -import android.view.MotionEvent -import android.view.View +import android.view.* import android.view.View.* -import android.view.ViewGroup import android.view.WindowManager.LayoutParams.* import android.view.animation.AccelerateInterpolator import android.view.animation.AlphaAnimation @@ -32,6 +30,9 @@ import android.view.animation.AnimationUtils import android.widget.* import android.widget.Toast.LENGTH_SHORT import androidx.appcompat.app.AlertDialog +import androidx.core.graphics.blue +import androidx.core.graphics.green +import androidx.core.graphics.red import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -119,8 +120,8 @@ const val PLAYBACK_SPEED = "playback_speed" const val RESIZE_MODE_KEY = "resize_mode" // Last used resize mode const val PLAYBACK_SPEED_KEY = "playback_speed" // Last used playback speed -const val OPENING_PRECENTAGE = 50 -const val AUTOLOAD_NEXT_EPISODE_PRECENTAGE = 80 +const val OPENING_PERCENTAGE = 50 +const val AUTOLOAD_NEXT_EPISODE_PERCENTAGE = 80 enum class PlayerEventType(val value: Int) { Stop(-1), @@ -266,8 +267,8 @@ class PlayerFragment : Fragment() { private var simpleCache: SimpleCache? = null /** Layout */ - private var width = Resources.getSystem().displayMetrics.heightPixels - private var height = Resources.getSystem().displayMetrics.widthPixels + private var width = Resources.getSystem().displayMetrics.widthPixels + private var height = Resources.getSystem().displayMetrics.heightPixels private var statusBarHeight by Delegates.notNull() private var navigationBarHeight by Delegates.notNull() @@ -670,7 +671,7 @@ class PlayerFragment : Fragment() { val percentage = ((position ?: exoPlayer.currentPosition) * 100 / exoPlayer.contentDuration).toInt() val hasNext = hasNextEpisode() - if (percentage >= AUTOLOAD_NEXT_EPISODE_PRECENTAGE && hasNext) { + if (percentage >= AUTOLOAD_NEXT_EPISODE_PERCENTAGE && hasNext) { val ep = episodes[playerData.episodeIndex + 1] @@ -680,7 +681,7 @@ class PlayerFragment : Fragment() { } } } - val nextEp = percentage >= OPENING_PRECENTAGE + val nextEp = percentage >= OPENING_PERCENTAGE val isAnime = data.isAnimeBased()//(data is AnimeLoadResponse && (data.type == TvType.Anime || data.type == TvType.ONA)) @@ -868,13 +869,21 @@ class PlayerFragment : Fragment() { } private fun updateLock() { - video_locked_img?.setImageResource(if (isLocked) R.drawable.video_locked else R.drawable.video_unlocked) - val color = if (isLocked) context?.colorFromAttribute(R.attr.colorPrimary) + lock_player?.setIconResource(if (isLocked) R.drawable.video_locked else R.drawable.video_unlocked) + var color = if (isLocked) context?.colorFromAttribute(R.attr.colorPrimary) else Color.WHITE - if (color != null) { - video_locked_text?.setTextColor(color) - video_locked_img?.setColorFilter(color) + lock_player?.setTextColor(color) + lock_player?.iconTint = ColorStateList.valueOf(color) + color = Color.argb(50, color.red, color.green, color.blue) + lock_player?.rippleColor = ColorStateList.valueOf(color) + //if(isLocked) { + // lock_player?.iconTint = ContextCompat.getColorStateList(lock_player.context, R.color.white) +// + //} else { + // lock_player?.iconTint = context?.colorFromAttribute(R.attr.colorPrimary) + //} + //lock_player?.setColorFilter(color) } val isClick = !isLocked @@ -1007,6 +1016,45 @@ class PlayerFragment : Fragment() { handlePlayerEvent(event.value) } + private fun handleKeyEvent(event: KeyEvent): Boolean { + event.keyCode.let { keyCode -> + when (event.action) { + // don't allow dpad move when hidden + KeyEvent.KEYCODE_DPAD_LEFT, + KeyEvent.KEYCODE_DPAD_DOWN, + KeyEvent.KEYCODE_DPAD_UP, + KeyEvent.KEYCODE_DPAD_RIGHT, + KeyEvent.KEYCODE_DPAD_DOWN_LEFT, + KeyEvent.KEYCODE_DPAD_DOWN_RIGHT, + KeyEvent.KEYCODE_DPAD_UP_LEFT, + KeyEvent.KEYCODE_DPAD_UP_RIGHT -> { + if (!isShowing) { + return true + } + } + KeyEvent.ACTION_DOWN -> { + when (keyCode) { + KeyEvent.KEYCODE_DPAD_CENTER -> { + if (!isShowing) { + onClickChange() + return true + } + } + } + + //println("Keycode: $keyCode") + //showToast( + // this, + // "Got Keycode $keyCode | ${KeyEvent.keyCodeToString(keyCode)} \n ${event?.action}", + // Toast.LENGTH_LONG + //) + } + } + } + + return false + } + var lastMuteVolume = 0f private fun handlePlayerEvent(event: Int) { @@ -1069,7 +1117,7 @@ class PlayerFragment : Fragment() { requireContext().setKey(PLAYBACK_SPEED_KEY, playbackSpeed) val param = PlaybackParameters(playbackSpeed) exoPlayer.playbackParameters = param - player_speed_text?.text = + playback_speed_btt?.text = getString(R.string.player_speed_text_format).format(playbackSpeed).replace(".0x", "x") } } @@ -1720,6 +1768,7 @@ class PlayerFragment : Fragment() { override fun onDestroy() { MainActivity.playerEventListener = null + MainActivity.keyEventListener = null /* val lp = activity?.window?.attributes @@ -1845,7 +1894,7 @@ class PlayerFragment : Fragment() { player_torrent_info?.isVisible = false //player_torrent_info?.alpha = 0f - println("LOADED: ${uri} or ${currentUrl}") + println("LOADED: $uri or $currentUrl") isCurrentlyPlaying = true hasUsedFirstRender = false @@ -1993,7 +2042,7 @@ class PlayerFragment : Fragment() { player_view?.player = exoPlayer // Sets the speed exoPlayer.playbackParameters = PlaybackParameters(playbackSpeed) - player_speed_text?.text = + playback_speed_btt?.text = getString(R.string.player_speed_text_format).format(playbackSpeed).replace(".0x", "x") var hName: String? = null @@ -2058,19 +2107,27 @@ class PlayerFragment : Fragment() { handlePlayerEvent(eventType) } + MainActivity.keyEventListener = { keyEvent -> + if (keyEvent != null) { + handleKeyEvent(keyEvent) + } else { + false + } + } + exoPlayer.addListener(object : Player.Listener { override fun onRenderedFirstFrame() { super.onRenderedFirstFrame() isCurrentlySkippingEp = false - val height = exoPlayer.videoFormat?.height - val width = exoPlayer.videoFormat?.width + val playerHeight = exoPlayer.videoFormat?.height + val playerWidth = exoPlayer.videoFormat?.width video_title_rez?.text = - if (height == null || width == null) currentUrl?.name + if (playerHeight == null || playerWidth == null) currentUrl?.name ?: "" else // if (isTorrent) "${width}x${height}" else - if (isDownloadedFile || currentUrl?.name == null) "${width}x${height}" else "${currentUrl.name} - ${width}x${height}" + if (isDownloadedFile || currentUrl?.name == null) "${playerWidth}x${playerHeight}" else "${currentUrl.name} - ${playerWidth}x${playerHeight}" if (!hasUsedFirstRender) { // DON'T WANT TO SET MULTIPLE MESSAGES //&& !isTorrent @@ -2084,7 +2141,7 @@ class PlayerFragment : Fragment() { changeSkip() } .setLooper(Looper.getMainLooper()) - .setPosition( /* positionMs= */exoPlayer.contentDuration * OPENING_PRECENTAGE / 100) + .setPosition( /* positionMs= */exoPlayer.contentDuration * OPENING_PERCENTAGE / 100) // .setPayload(customPayloadData) .setDeleteAfterDelivery(false) .send() @@ -2093,7 +2150,7 @@ class PlayerFragment : Fragment() { changeSkip() } .setLooper(Looper.getMainLooper()) - .setPosition( /* positionMs= */exoPlayer.contentDuration * AUTOLOAD_NEXT_EPISODE_PRECENTAGE / 100) + .setPosition( /* positionMs= */exoPlayer.contentDuration * AUTOLOAD_NEXT_EPISODE_PERCENTAGE / 100) // .setPayload(customPayloadData) .setDeleteAfterDelivery(false) diff --git a/app/src/main/res/drawable/dub_bg_color.xml b/app/src/main/res/drawable/dub_bg_color.xml index f2ecfe82..16807981 100644 --- a/app/src/main/res/drawable/dub_bg_color.xml +++ b/app/src/main/res/drawable/dub_bg_color.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_baseline_fast_forward_24.xml b/app/src/main/res/drawable/ic_baseline_fast_forward_24.xml new file mode 100644 index 00000000..91e27cdb --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_fast_forward_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/sub_bg_color.xml b/app/src/main/res/drawable/sub_bg_color.xml index f12d5335..6e55d47e 100644 --- a/app/src/main/res/drawable/sub_bg_color.xml +++ b/app/src/main/res/drawable/sub_bg_color.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/type_bg_color.xml b/app/src/main/res/drawable/type_bg_color.xml index c6ca4367..40d221bb 100644 --- a/app/src/main/res/drawable/type_bg_color.xml +++ b/app/src/main/res/drawable/type_bg_color.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/video_locked.xml b/app/src/main/res/drawable/video_locked.xml index fe0be191..f6bc458c 100644 --- a/app/src/main/res/drawable/video_locked.xml +++ b/app/src/main/res/drawable/video_locked.xml @@ -1,6 +1,6 @@ + android:layout_marginTop="@dimen/navbar_height"> - - - - - - - - - - + style="@style/VideoButton"/> - - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - + - - - - - - - - + - - - - - - - + android:text="@string/next_episode" + app:icon="@drawable/ic_baseline_skip_next_24" + style="@style/VideoButton" + /> - diff --git a/app/src/main/res/layout/search_result_super_compact.xml b/app/src/main/res/layout/search_result_super_compact.xml index 68bb2c46..0ce156db 100644 --- a/app/src/main/res/layout/search_result_super_compact.xml +++ b/app/src/main/res/layout/search_result_super_compact.xml @@ -15,14 +15,14 @@ android:layout_height="match_parent" android:layout_marginBottom="10dp" android:elevation="0dp" - app:cardCornerRadius="@dimen/roundedImageRadius" + app:cardCornerRadius="@dimen/rounded_image_radius" app:cardBackgroundColor="?attr/boxItemBackground" android:clickable="true" android:focusable="true" > diff --git a/app/src/main/res/values/array.xml b/app/src/main/res/values/array.xml index d7d09a87..990d3b98 100644 --- a/app/src/main/res/values/array.xml +++ b/app/src/main/res/values/array.xml @@ -114,14 +114,14 @@ - Normal Dark + Gray Amoled Flashbang - Black AmoledLight + Black Amoled Light diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 4a26a4d1..7a9e4d43 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -30,7 +30,9 @@ #3BF585 #803BF585 - #73FFFFFF + #80FFFFFF + #32FFFFFF + #66000000 #C0121212 #121212 diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index ae146164..c00bb6d1 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -2,8 +2,8 @@ 16dp 16dp - 5dp - 0dp + 5dp + 0dp 2dp 15dp \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index f85e961f..5c60c163 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -311,6 +311,28 @@ wrap_content + + From b13c1eac01f2ddd7818fa1a5ba886892c5597053 Mon Sep 17 00:00:00 2001 From: LagradOst Date: Sun, 28 Nov 2021 13:18:01 +0100 Subject: [PATCH 3/3] android TV fix --- .../lagradost/cloudstream3/MainActivity.kt | 80 +++++++++++++++++-- .../ui/home/HomeChildItemAdapter.kt | 20 +++-- .../cloudstream3/ui/home/HomeFragment.kt | 32 +++++++- .../ui/home/HomeParentItemAdapter.kt | 7 +- .../cloudstream3/ui/player/PlayerFragment.kt | 13 ++- .../cloudstream3/ui/search/SearchAdaptor.kt | 6 +- .../ui/search/SearchResultBuilder.kt | 12 ++- app/src/main/res/layout/fragment_search.xml | 2 +- app/src/main/res/layout/homepage_parent.xml | 3 +- 9 files changed, 150 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index 0c446f72..494d00fc 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -145,20 +145,84 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { } } + enum class FocusDirection { + Left, + Right, + Up, + Down, + } + + private fun getNextFocus(view: View?, direction: FocusDirection, depth: Int = 0): Int? { + if (view == null || depth >= 10) { + return null + } + + val nextId = when (direction) { + FocusDirection.Left -> { + view.nextFocusLeftId + } + FocusDirection.Up -> { + view.nextFocusUpId + } + FocusDirection.Right -> { + view.nextFocusRightId + } + FocusDirection.Down -> { + view.nextFocusDownId + } + } + + return if (nextId != -1) { + val next = findViewById(nextId) + //println("NAME: ${next.accessibilityClassName} | ${next?.isShown}" ) + + if (next?.isShown == false) { + getNextFocus(next, direction, depth + 1) + } else { + if (depth == 0) { + null + } else { + nextId + } + } + } else { + null + } + } + override fun dispatchKeyEvent(event: KeyEvent?): Boolean { event?.keyCode?.let { keyCode -> when (event.action) { ACTION_DOWN -> { - when (keyCode) { - KeyEvent.KEYCODE_DPAD_CENTER -> { - println("DPAD PRESSED $currentFocus") - if (currentFocus is SearchView || currentFocus is SearchView.SearchAutoComplete) { - println("current PRESSED") - showInputMethod(currentFocus?.findFocus()) + if (currentFocus != null) { + val next = when (keyCode) { + KeyEvent.KEYCODE_DPAD_LEFT -> getNextFocus(currentFocus, FocusDirection.Left) + KeyEvent.KEYCODE_DPAD_RIGHT -> getNextFocus(currentFocus, FocusDirection.Right) + KeyEvent.KEYCODE_DPAD_UP -> getNextFocus(currentFocus, FocusDirection.Up) + KeyEvent.KEYCODE_DPAD_DOWN -> getNextFocus(currentFocus, FocusDirection.Down) + + else -> null + } + + if (next != null && next != -1) { + val nextView = findViewById(next) + if(nextView != null) { + nextView.requestFocus() + return true + } + } + + when (keyCode) { + + KeyEvent.KEYCODE_DPAD_CENTER -> { + println("DPAD PRESSED $currentFocus") + if (currentFocus is SearchView || currentFocus is SearchView.SearchAutoComplete) { + println("current PRESSED") + showInputMethod(currentFocus?.findFocus()) + } } } } - //println("Keycode: $keyCode") //showToast( // this, @@ -169,7 +233,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { } } - if(keyEventListener?.invoke(event) == true) { + if (keyEventListener?.invoke(event) == true) { return true } return super.dispatchKeyEvent(event) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeChildItemAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeChildItemAdapter.kt index 0fbc8156..74abedf7 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeChildItemAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeChildItemAdapter.kt @@ -12,13 +12,19 @@ import com.lagradost.cloudstream3.ui.search.SearchResultBuilder class HomeChildItemAdapter( var cardList: List, val layout: Int = R.layout.home_result_grid, - private val clickCallback: (SearchClickCallback) -> Unit + private val nextFocusUp: Int? = null, + private val nextFocusDown: Int? = null, + private val clickCallback: (SearchClickCallback) -> Unit, ) : RecyclerView.Adapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return CardViewHolder( - LayoutInflater.from(parent.context).inflate(layout, parent, false), clickCallback, itemCount + LayoutInflater.from(parent.context).inflate(layout, parent, false), + clickCallback, + itemCount, + nextFocusUp, + nextFocusDown ) } @@ -39,19 +45,23 @@ class HomeChildItemAdapter( } class CardViewHolder - constructor(itemView: View, private val clickCallback: (SearchClickCallback) -> Unit, val itemCount: Int) : + constructor( + itemView: View, private val clickCallback: (SearchClickCallback) -> Unit, private val itemCount: Int, + private val nextFocusUp: Int? = null, + private val nextFocusDown: Int? = null, + ) : RecyclerView.ViewHolder(itemView) { fun bind(card: SearchResponse, index: Int) { // TV focus fixing - val nextFocusBehavior = when(index){ + val nextFocusBehavior = when (index) { 0 -> true itemCount - 1 -> false else -> null } - SearchResultBuilder.bind(clickCallback, card, itemView, nextFocusBehavior) + SearchResultBuilder.bind(clickCallback, card, itemView, nextFocusBehavior, nextFocusUp, nextFocusDown) itemView.tag = index //val ani = ScaleAnimation(0.9f, 1.0f, 0.9f, 1f) //ani.fillAfter = true diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index da514a36..5c7fb5a8 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -35,6 +35,7 @@ import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST import com.lagradost.cloudstream3.ui.search.* import com.lagradost.cloudstream3.ui.search.SearchFragment.Companion.filterSearchResponse import com.lagradost.cloudstream3.ui.search.SearchHelper.handleSearchClickCallback +import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.utils.AppUtils import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult import com.lagradost.cloudstream3.utils.DataStore.getKey @@ -212,7 +213,12 @@ class HomeFragment : Fragment() { val randomSize = items.size home_main_poster_recyclerview.adapter = - HomeChildItemAdapter(items, R.layout.home_result_big_grid) { callback -> + HomeChildItemAdapter( + items, + R.layout.home_result_big_grid, + nextFocusUp = home_main_poster_recyclerview.nextFocusUpId, + nextFocusDown = home_main_poster_recyclerview.nextFocusDownId + ) { callback -> handleSearchClickCallback(activity, callback) } home_main_poster_recyclerview.post { @@ -339,7 +345,11 @@ class HomeFragment : Fragment() { } } - home_bookmarked_child_recyclerview.adapter = HomeChildItemAdapter(ArrayList()) { callback -> + home_bookmarked_child_recyclerview.adapter = HomeChildItemAdapter( + ArrayList(), + nextFocusUp = home_bookmarked_child_recyclerview?.nextFocusUpId, + nextFocusDown = home_bookmarked_child_recyclerview?.nextFocusDownId + ) { callback -> if (callback.action == SEARCH_ACTION_SHOW_METADATA) { val id = callback.card.id if (id != null) { @@ -355,7 +365,11 @@ class HomeFragment : Fragment() { } } - home_watch_child_recyclerview.adapter = HomeChildItemAdapter(ArrayList()) { callback -> + home_watch_child_recyclerview.adapter = HomeChildItemAdapter( + ArrayList(), + nextFocusUp = home_watch_child_recyclerview?.nextFocusUpId, + nextFocusDown = home_watch_child_recyclerview?.nextFocusDownId + ) { callback -> if (callback.action == SEARCH_ACTION_SHOW_METADATA) { val id = callback.card.id if (id != null) { @@ -423,6 +437,16 @@ class HomeFragment : Fragment() { // nice profile pic on homepage home_profile_picture_holder?.isVisible = false context?.let { ctx -> + // just in case + if (ctx.isTvSettings()) { + home_change_api_loading?.isFocusable = true + home_change_api_loading?.isFocusableInTouchMode = true + home_change_api?.isFocusable = true + home_change_api?.isFocusableInTouchMode = true + home_bookmark_select?.isFocusable = true + home_bookmark_select?.isFocusableInTouchMode = true + } + for (syncApi in OAuth2API.OAuth2Apis) { val login = syncApi.loginInfo(ctx) val pic = login?.profilePicture @@ -433,5 +457,7 @@ class HomeFragment : Fragment() { } } } + + } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapter.kt index 5ea32286..adc53da5 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapter.kt @@ -47,7 +47,12 @@ class ParentItemAdapter( private val moreInfo: FrameLayout = itemView.home_child_more_info fun bind(info: HomePageList) { title.text = info.name - recyclerView.adapter = HomeChildItemAdapter(info.list, clickCallback = clickCallback) + recyclerView.adapter = HomeChildItemAdapter( + info.list, + clickCallback = clickCallback, + nextFocusUp = recyclerView.nextFocusUpId, + nextFocusDown = recyclerView.nextFocusDownId + ) (recyclerView.adapter as HomeChildItemAdapter).notifyDataSetChanged() moreInfo.setOnClickListener { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt index 7d1dae83..840455ad 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt @@ -1018,7 +1018,7 @@ class PlayerFragment : Fragment() { private fun handleKeyEvent(event: KeyEvent): Boolean { event.keyCode.let { keyCode -> - when (event.action) { + when (keyCode) { // don't allow dpad move when hidden KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_DOWN, @@ -1032,6 +1032,17 @@ class PlayerFragment : Fragment() { return true } } + + // netflix capture back and hide ~monke + KeyEvent.KEYCODE_BACK -> { + if (isShowing) { + onClickChange() + return true + } + } + } + + when (event.action) { KeyEvent.ACTION_DOWN -> { when (keyCode) { KeyEvent.KEYCODE_DPAD_CENTER -> { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt index 90d2e611..6936fbd1 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt @@ -38,7 +38,7 @@ class SearchAdapter( override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { when (holder) { is CardViewHolder -> { - holder.bind(cardList[position]) + holder.bind(cardList[position], position) } } } @@ -59,7 +59,7 @@ class SearchAdapter( private val compactView = itemView.context.getGridIsCompact() private val coverHeight: Int = if (compactView) 80.toPx else (resView.itemWidth / 0.68).roundToInt() - fun bind(card: SearchResponse) { + fun bind(card: SearchResponse, position: Int) { if (!compactView) { cardView.apply { layoutParams = FrameLayout.LayoutParams( @@ -69,7 +69,7 @@ class SearchAdapter( } } - SearchResultBuilder.bind(clickCallback, card, itemView,) + SearchResultBuilder.bind(clickCallback, card, itemView) } } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchResultBuilder.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchResultBuilder.kt index efc45a14..b5878f29 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchResultBuilder.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchResultBuilder.kt @@ -22,7 +22,9 @@ object SearchResultBuilder { clickCallback: (SearchClickCallback) -> Unit, card: SearchResponse, itemView: View, - nextFocusBehavior: Boolean? = null + nextFocusBehavior: Boolean? = null, + nextFocusUp: Int? = null, + nextFocusDown: Int? = null, ) { val cardView: ImageView = itemView.imageView val cardText: TextView? = itemView.imageText @@ -57,6 +59,14 @@ object SearchResultBuilder { ) } + if(nextFocusUp != null) { + bg.nextFocusUpId = nextFocusUp + } + + if(nextFocusDown != null) { + bg.nextFocusDownId = nextFocusDown + } + when (nextFocusBehavior) { true -> bg.nextFocusLeftId = bg.id false -> bg.nextFocusRightId = bg.id diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index d6827e9e..3aeb0c02 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -43,6 +43,7 @@ android:layout_gravity="center_vertical" app:iconifiedByDefault="false" tools:ignore="RtlSymmetry"> + - diff --git a/app/src/main/res/layout/homepage_parent.xml b/app/src/main/res/layout/homepage_parent.xml index 006b1d98..c80ceb09 100644 --- a/app/src/main/res/layout/homepage_parent.xml +++ b/app/src/main/res/layout/homepage_parent.xml @@ -8,8 +8,6 @@ android:layout_height="wrap_content">