forked from recloudstream/cloudstream
		
	tv UI fixes
This commit is contained in:
		
							parent
							
								
									01c81fc421
								
							
						
					
					
						commit
						cd119822f2
					
				
					 29 changed files with 393 additions and 167 deletions
				
			
		|  | @ -6,7 +6,6 @@ import android.content.Context | ||||||
| import android.content.pm.PackageManager | import android.content.pm.PackageManager | ||||||
| import android.content.res.Resources | import android.content.res.Resources | ||||||
| import android.os.Build | import android.os.Build | ||||||
| import android.os.Looper |  | ||||||
| import android.util.Log | import android.util.Log | ||||||
| import android.view.* | import android.view.* | ||||||
| import android.widget.TextView | import android.widget.TextView | ||||||
|  | @ -20,12 +19,12 @@ import com.google.android.gms.cast.framework.CastSession | ||||||
| import com.lagradost.cloudstream3.mvvm.logError | import com.lagradost.cloudstream3.mvvm.logError | ||||||
| import com.lagradost.cloudstream3.ui.player.PlayerEventType | import com.lagradost.cloudstream3.ui.player.PlayerEventType | ||||||
| import com.lagradost.cloudstream3.ui.result.UiText | import com.lagradost.cloudstream3.ui.result.UiText | ||||||
|  | import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.updateTv | ||||||
| import com.lagradost.cloudstream3.utils.Event | import com.lagradost.cloudstream3.utils.Event | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper | import com.lagradost.cloudstream3.utils.UIHelper | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.hasPIPPermission | import com.lagradost.cloudstream3.utils.UIHelper.hasPIPPermission | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.shouldShowPIPMode | import com.lagradost.cloudstream3.utils.UIHelper.shouldShowPIPMode | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.toPx | import com.lagradost.cloudstream3.utils.UIHelper.toPx | ||||||
| import kotlinx.coroutines.currentCoroutineContext |  | ||||||
| import org.schabi.newpipe.extractor.NewPipe | import org.schabi.newpipe.extractor.NewPipe | ||||||
| import java.util.* | import java.util.* | ||||||
| 
 | 
 | ||||||
|  | @ -128,7 +127,7 @@ object CommonActivity { | ||||||
|                     act.hasPIPPermission() // CHECK IF FEATURE IS ENABLED IN SETTINGS |                     act.hasPIPPermission() // CHECK IF FEATURE IS ENABLED IN SETTINGS | ||||||
| 
 | 
 | ||||||
|         act.updateLocale() |         act.updateLocale() | ||||||
| 
 |         act.updateTv() | ||||||
|         NewPipe.init(DownloaderTestImpl.getInstance()) |         NewPipe.init(DownloaderTestImpl.getInstance()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -226,7 +226,7 @@ object APIHolder { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun Context.getHasTrailers(): Boolean { |     private fun Context.getHasTrailers(): Boolean { | ||||||
|         if (this.isTvSettings()) return false |         if (isTvSettings()) return false | ||||||
|         val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) |         val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) | ||||||
|         return settingsManager.getBoolean(this.getString(R.string.show_trailers_key), true) |         return settingsManager.getBoolean(this.getString(R.string.show_trailers_key), true) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -175,7 +175,7 @@ class DownloadFragment : Fragment() { | ||||||
| 
 | 
 | ||||||
|         download_list?.adapter = adapter |         download_list?.adapter = adapter | ||||||
|         download_list?.layoutManager = GridLayoutManager(context, 1) |         download_list?.layoutManager = GridLayoutManager(context, 1) | ||||||
|         download_stream_button?.isGone = context?.isTvSettings() == true |         download_stream_button?.isGone = isTvSettings() | ||||||
|         download_stream_button?.setOnClickListener { |         download_stream_button?.setOnClickListener { | ||||||
|             val dialog = |             val dialog = | ||||||
|                 Dialog(it.context ?: return@setOnClickListener, R.style.AlertDialogCustom) |                 Dialog(it.context ?: return@setOnClickListener, R.style.AlertDialogCustom) | ||||||
|  |  | ||||||
|  | @ -400,7 +400,7 @@ class HomeFragment : Fragment() { | ||||||
|         //homeViewModel = |         //homeViewModel = | ||||||
|         //     ViewModelProvider(this).get(HomeViewModel::class.java) |         //     ViewModelProvider(this).get(HomeViewModel::class.java) | ||||||
|         val layout = |         val layout = | ||||||
|             if (context?.isTvSettings() == true) R.layout.fragment_home_tv else R.layout.fragment_home |             if (isTvSettings()) R.layout.fragment_home_tv else R.layout.fragment_home | ||||||
|         return inflater.inflate(layout, container, false) |         return inflater.inflate(layout, container, false) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -568,7 +568,7 @@ class HomeFragment : Fragment() { | ||||||
| 
 | 
 | ||||||
|                 val randomSize = items.size |                 val randomSize = items.size | ||||||
|                 tempAdapter?.updateList(items) |                 tempAdapter?.updateList(items) | ||||||
|                 if (context?.isTvSettings() == false) { |                 if (!isTvSettings()) { | ||||||
|                     home_main_poster_recyclerview?.post { |                     home_main_poster_recyclerview?.post { | ||||||
|                         (home_main_poster_recyclerview?.layoutManager as CenterZoomLayoutManager?)?.let { manager -> |                         (home_main_poster_recyclerview?.layoutManager as CenterZoomLayoutManager?)?.let { manager -> | ||||||
|                             manager.updateSize(forceUpdate = true) |                             manager.updateSize(forceUpdate = true) | ||||||
|  | @ -939,7 +939,7 @@ class HomeFragment : Fragment() { | ||||||
|             } |             } | ||||||
|         } // GridLayoutManager(context, 1).also { it.supportsPredictiveItemAnimations() } |         } // GridLayoutManager(context, 1).also { it.supportsPredictiveItemAnimations() } | ||||||
| 
 | 
 | ||||||
|         if (context?.isTvSettings() == false) { |         if (!isTvSettings()) { | ||||||
|             LinearSnapHelper().attachToRecyclerView(home_main_poster_recyclerview) // snap |             LinearSnapHelper().attachToRecyclerView(home_main_poster_recyclerview) // snap | ||||||
|             val centerLayoutManager = |             val centerLayoutManager = | ||||||
|                 CenterZoomLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) |                 CenterZoomLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) | ||||||
|  | @ -975,7 +975,7 @@ class HomeFragment : Fragment() { | ||||||
|                 home_api_fab?.shrink() // hide |                 home_api_fab?.shrink() // hide | ||||||
|                 home_random?.shrink() |                 home_random?.shrink() | ||||||
|             } else if (dy < -5) { |             } else if (dy < -5) { | ||||||
|                 if (v.context?.isTvSettings() == false) { |                 if (!isTvSettings()) { | ||||||
|                     home_api_fab?.extend() // show |                     home_api_fab?.extend() // show | ||||||
|                     home_random?.extend() |                     home_random?.extend() | ||||||
|                 } |                 } | ||||||
|  | @ -984,12 +984,11 @@ class HomeFragment : Fragment() { | ||||||
| 
 | 
 | ||||||
|         // nice profile pic on homepage |         // nice profile pic on homepage | ||||||
|         home_profile_picture_holder?.isVisible = false |         home_profile_picture_holder?.isVisible = false | ||||||
|         context?.let { ctx -> |  | ||||||
|         // just in case |         // just in case | ||||||
|             if (ctx.isTvSettings()) { |         if (isTvSettings()) { | ||||||
|             home_api_fab?.isVisible = false |             home_api_fab?.isVisible = false | ||||||
|             home_change_api?.isVisible = true |             home_change_api?.isVisible = true | ||||||
|                 if (ctx.isTrueTvSettings()) { |             if (isTrueTvSettings()) { | ||||||
|                 home_change_api_loading?.isVisible = true |                 home_change_api_loading?.isVisible = true | ||||||
|                 home_change_api_loading?.isFocusable = true |                 home_change_api_loading?.isFocusable = true | ||||||
|                 home_change_api_loading?.isFocusableInTouchMode = true |                 home_change_api_loading?.isFocusableInTouchMode = true | ||||||
|  | @ -1018,4 +1017,3 @@ class HomeFragment : Fragment() { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| } |  | ||||||
|  | @ -29,7 +29,7 @@ class ParentItemAdapter( | ||||||
|     override fun onCreateViewHolder(parent: ViewGroup, i: Int): ParentViewHolder { |     override fun onCreateViewHolder(parent: ViewGroup, i: Int): ParentViewHolder { | ||||||
|         //println("onCreateViewHolder $i") |         //println("onCreateViewHolder $i") | ||||||
|         val layout = |         val layout = | ||||||
|             if (parent.context.isTvSettings()) R.layout.homepage_parent_tv else R.layout.homepage_parent |             if (isTvSettings()) R.layout.homepage_parent_tv else R.layout.homepage_parent | ||||||
|         return ParentViewHolder( |         return ParentViewHolder( | ||||||
|             LayoutInflater.from(parent.context).inflate(layout, parent, false), |             LayoutInflater.from(parent.context).inflate(layout, parent, false), | ||||||
|             clickCallback, |             clickCallback, | ||||||
|  |  | ||||||
|  | @ -993,7 +993,7 @@ class GeneratorPlayer : FullScreenPlayer() { | ||||||
|         savedInstanceState: Bundle? |         savedInstanceState: Bundle? | ||||||
|     ): View? { |     ): View? { | ||||||
|         // this is used instead of layout-television to follow the settings and some TV devices are not classified as TV for some reason |         // this is used instead of layout-television to follow the settings and some TV devices are not classified as TV for some reason | ||||||
|         isTv = context?.isTvSettings() == true |         isTv = isTvSettings() | ||||||
|         layout = |         layout = | ||||||
|             if (isTv) R.layout.fragment_player_tv else R.layout.fragment_player |             if (isTv) R.layout.fragment_player_tv else R.layout.fragment_player | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -124,7 +124,7 @@ class PlayerEpisodeAdapter( | ||||||
|                     clickCallback.invoke(PlayerEpisodeClickEvent(0, card)) |                     clickCallback.invoke(PlayerEpisodeClickEvent(0, card)) | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 if (parentView.context.isTrueTvSettings()) { |                 if (isTrueTvSettings()) { | ||||||
|                     parentView.isFocusable = true |                     parentView.isFocusable = true | ||||||
|                     parentView.isFocusableInTouchMode = true |                     parentView.isFocusableInTouchMode = true | ||||||
|                     parentView.touchscreenBlocksFocus = false |                     parentView.touchscreenBlocksFocus = false | ||||||
|  |  | ||||||
|  | @ -166,7 +166,7 @@ class EpisodeAdapter( | ||||||
|         fun bind(card: ResultEpisode) { |         fun bind(card: ResultEpisode) { | ||||||
|             localCard = card |             localCard = card | ||||||
| 
 | 
 | ||||||
|             val isTrueTv = itemView.context?.isTrueTvSettings() == true |             val isTrueTv = isTrueTvSettings() | ||||||
| 
 | 
 | ||||||
|             val (parentView, otherView) = if (card.poster == null) { |             val (parentView, otherView) = if (card.poster == null) { | ||||||
|                 itemView.episode_holder to itemView.episode_holder_large |                 itemView.episode_holder to itemView.episode_holder_large | ||||||
|  |  | ||||||
|  | @ -83,7 +83,7 @@ class ImageAdapter( | ||||||
|                     this.nextFocusUpId = nextFocusUp |                     this.nextFocusUpId = nextFocusUp | ||||||
|                 } |                 } | ||||||
|                 if (clickCallback != null) { |                 if (clickCallback != null) { | ||||||
|                     if (context.isTrueTvSettings()) { |                     if (isTrueTvSettings()) { | ||||||
|                         isClickable = true |                         isClickable = true | ||||||
|                         isLongClickable = true |                         isLongClickable = true | ||||||
|                         isFocusable = true |                         isFocusable = true | ||||||
|  |  | ||||||
|  | @ -293,7 +293,7 @@ open class ResultFragment : ResultTrailerPlayer() { | ||||||
|                 result_reload_connection_open_in_browser?.isVisible = true |                 result_reload_connection_open_in_browser?.isVisible = true | ||||||
|             } |             } | ||||||
|             2 -> { |             2 -> { | ||||||
|                 result_bookmark_fab?.isGone = result_bookmark_fab?.context?.isTvSettings() == true |                 result_bookmark_fab?.isGone = isTvSettings() | ||||||
|                 result_bookmark_fab?.extend() |                 result_bookmark_fab?.extend() | ||||||
|                 //if (result_bookmark_button?.context?.isTrueTvSettings() == true) { |                 //if (result_bookmark_button?.context?.isTrueTvSettings() == true) { | ||||||
|                 //    when { |                 //    when { | ||||||
|  | @ -551,7 +551,7 @@ open class ResultFragment : ResultTrailerPlayer() { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // This is to band-aid FireTV navigation |         // This is to band-aid FireTV navigation | ||||||
|         val isTv = context?.isTvSettings() == true |         val isTv = isTvSettings() | ||||||
|         result_season_button?.isFocusableInTouchMode = isTv |         result_season_button?.isFocusableInTouchMode = isTv | ||||||
|         result_episode_select?.isFocusableInTouchMode = isTv |         result_episode_select?.isFocusableInTouchMode = isTv | ||||||
|         result_dub_select?.isFocusableInTouchMode = isTv |         result_dub_select?.isFocusableInTouchMode = isTv | ||||||
|  | @ -794,7 +794,7 @@ open class ResultFragment : ResultTrailerPlayer() { | ||||||
|                     result_next_airing_time.setText(d.nextAiringDate) |                     result_next_airing_time.setText(d.nextAiringDate) | ||||||
|                     result_poster.setImage(d.posterImage) |                     result_poster.setImage(d.posterImage) | ||||||
| 
 | 
 | ||||||
|                     if (d.posterImage != null && context?.isTrueTvSettings() == false) |                     if (d.posterImage != null && !isTrueTvSettings()) | ||||||
|                         result_poster_holder?.setOnClickListener { |                         result_poster_holder?.setOnClickListener { | ||||||
|                             try { |                             try { | ||||||
|                                 context?.let { ctx -> |                                 context?.let { ctx -> | ||||||
|  | @ -883,7 +883,7 @@ open class ResultFragment : ResultTrailerPlayer() { | ||||||
|                     result_tag_holder?.isVisible = tags.isNotEmpty() |                     result_tag_holder?.isVisible = tags.isNotEmpty() | ||||||
|                     if (tags.isNotEmpty()) { |                     if (tags.isNotEmpty()) { | ||||||
|                         //result_tag_holder?.visibility = VISIBLE |                         //result_tag_holder?.visibility = VISIBLE | ||||||
|                         val isOnTv = context?.isTrueTvSettings() == true |                         val isOnTv = isTrueTvSettings() | ||||||
|                         for ((index, tag) in tags.withIndex()) { |                         for ((index, tag) in tags.withIndex()) { | ||||||
|                             val viewBtt = layoutInflater.inflate(R.layout.result_tag, null) |                             val viewBtt = layoutInflater.inflate(R.layout.result_tag, null) | ||||||
|                             val btt = viewBtt.findViewById<MaterialButton>(R.id.result_tag_card) |                             val btt = viewBtt.findViewById<MaterialButton>(R.id.result_tag_card) | ||||||
|  | @ -941,7 +941,7 @@ open class ResultFragment : ResultTrailerPlayer() { | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 // bloats the navigation on tv |                 // bloats the navigation on tv | ||||||
|                 if (context?.isTrueTvSettings() == false) { |                 if (!isTrueTvSettings()) { | ||||||
|                     result_meta_site?.setOnClickListener { |                     result_meta_site?.setOnClickListener { | ||||||
|                         it.context?.openBrowser(storedData.url) |                         it.context?.openBrowser(storedData.url) | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|  | @ -85,7 +85,7 @@ class SelectAdaptor(val callback: (Any) -> Unit) : RecyclerView.Adapter<Recycler | ||||||
|         fun bind( |         fun bind( | ||||||
|             data: SelectData, isSelected: Boolean, callback: (Any) -> Unit |             data: SelectData, isSelected: Boolean, callback: (Any) -> Unit | ||||||
|         ) { |         ) { | ||||||
|             val isTrueTv = itemView.context?.isTrueTvSettings() == true |             val isTrueTv = isTrueTvSettings() | ||||||
|             if (isTrueTv) { |             if (isTrueTv) { | ||||||
|                 item.isFocusable = true |                 item.isFocusable = true | ||||||
|                 item.isFocusableInTouchMode = true |                 item.isFocusableInTouchMode = true | ||||||
|  |  | ||||||
|  | @ -386,7 +386,7 @@ class SearchFragment : Fragment() { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (context?.isTrueTvSettings() == true) { |         if (isTrueTvSettings()) { | ||||||
|             search_filter.isFocusable = true |             search_filter.isFocusable = true | ||||||
|             search_filter.isFocusableInTouchMode = true |             search_filter.isFocusableInTouchMode = true | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -164,7 +164,7 @@ object SearchResultBuilder { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (bg.context.isTrueTvSettings()) { |         if (isTrueTvSettings()) { | ||||||
|             bg.isFocusable = true |             bg.isFocusable = true | ||||||
|             bg.isFocusableInTouchMode = true |             bg.isFocusableInTouchMode = true | ||||||
|             bg.touchscreenBlocksFocus = false |             bg.touchscreenBlocksFocus = false | ||||||
|  |  | ||||||
|  | @ -117,7 +117,7 @@ class SettingsAccount : PreferenceFragmentCompat() { | ||||||
|                             dialog.login_username_input to api.requiresUsername |                             dialog.login_username_input to api.requiresUsername | ||||||
|                         ) |                         ) | ||||||
| 
 | 
 | ||||||
|                         if (activity.isTvSettings()) { |                         if (isTvSettings()) { | ||||||
|                             visibilityMap.forEach { (input, isVisible) -> |                             visibilityMap.forEach { (input, isVisible) -> | ||||||
|                                 input.isVisible = isVisible |                                 input.isVisible = isVisible | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -30,6 +30,9 @@ class SettingsFragment : Fragment() { | ||||||
|     companion object { |     companion object { | ||||||
|         var beneneCount = 0 |         var beneneCount = 0 | ||||||
| 
 | 
 | ||||||
|  |         private var isTv : Boolean = false | ||||||
|  |         private var isTrueTv : Boolean = false | ||||||
|  | 
 | ||||||
|         fun PreferenceFragmentCompat?.getPref(id: Int): Preference? { |         fun PreferenceFragmentCompat?.getPref(id: Int): Preference? { | ||||||
|             if (this == null) return null |             if (this == null) return null | ||||||
| 
 | 
 | ||||||
|  | @ -45,7 +48,7 @@ class SettingsFragment : Fragment() { | ||||||
|          * On TV you cannot properly scroll to the bottom of settings, this fixes that. |          * On TV you cannot properly scroll to the bottom of settings, this fixes that. | ||||||
|          * */ |          * */ | ||||||
|         fun PreferenceFragmentCompat.setPaddingBottom() { |         fun PreferenceFragmentCompat.setPaddingBottom() { | ||||||
|             if (this.context?.isTvSettings() == true) { |             if (isTvSettings()) { | ||||||
|                 listView?.setPadding(0, 0, 0, 100.toPx) |                 listView?.setPadding(0, 0, 0, 100.toPx) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -93,7 +96,7 @@ class SettingsFragment : Fragment() { | ||||||
|             return settingsManager.getInt(this.getString(R.string.app_layout_key), -1) |             return settingsManager.getInt(this.getString(R.string.app_layout_key), -1) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         fun Context.isTvSettings(): Boolean { |         private fun Context.isTvSettings(): Boolean { | ||||||
|             var value = getLayoutInt() |             var value = getLayoutInt() | ||||||
|             if (value == -1) { |             if (value == -1) { | ||||||
|                 value = if (isAutoTv()) 1 else 0 |                 value = if (isAutoTv()) 1 else 0 | ||||||
|  | @ -101,7 +104,7 @@ class SettingsFragment : Fragment() { | ||||||
|             return value == 1 || value == 2 |             return value == 1 || value == 2 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         fun Context.isTrueTvSettings(): Boolean { |         private fun Context.isTrueTvSettings(): Boolean { | ||||||
|             var value = getLayoutInt() |             var value = getLayoutInt() | ||||||
|             if (value == -1) { |             if (value == -1) { | ||||||
|                 value = if (isAutoTv()) 1 else 0 |                 value = if (isAutoTv()) 1 else 0 | ||||||
|  | @ -109,6 +112,19 @@ class SettingsFragment : Fragment() { | ||||||
|             return value == 1 |             return value == 1 | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         fun Context.updateTv() { | ||||||
|  |             isTrueTv = isTrueTvSettings() | ||||||
|  |             isTv = isTvSettings() | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         fun isTrueTvSettings(): Boolean { | ||||||
|  |             return isTrueTv | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         fun isTvSettings(): Boolean { | ||||||
|  |             return isTv | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         fun Context.isEmulatorSettings(): Boolean { |         fun Context.isEmulatorSettings(): Boolean { | ||||||
|             return getLayoutInt() == 2 |             return getLayoutInt() == 2 | ||||||
|         } |         } | ||||||
|  | @ -136,7 +152,7 @@ class SettingsFragment : Fragment() { | ||||||
|             activity?.navigate(id, Bundle()) |             activity?.navigate(id, Bundle()) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         val isTrueTv = context?.isTrueTvSettings() == true |         val isTrueTv = isTrueTvSettings() | ||||||
| 
 | 
 | ||||||
|         for (syncApi in accountManagers) { |         for (syncApi in accountManagers) { | ||||||
|             val login = syncApi.loginInfo() |             val login = syncApi.loginInfo() | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ import com.lagradost.cloudstream3.ui.search.SearchResultBuilder | ||||||
| import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref | import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref | ||||||
| import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setPaddingBottom | import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setPaddingBottom | ||||||
| import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar | import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar | ||||||
|  | import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.updateTv | ||||||
| import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog | import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog | ||||||
| import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog | import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog | ||||||
| import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog | import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog | ||||||
|  | @ -22,6 +23,7 @@ class SettingsUI : PreferenceFragmentCompat() { | ||||||
|         setUpToolbar(R.string.category_ui) |         setUpToolbar(R.string.category_ui) | ||||||
|         setPaddingBottom() |         setPaddingBottom() | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { |     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { | ||||||
|         hideKeyboard() |         hideKeyboard() | ||||||
|         setPreferencesFromResource(R.xml.settins_ui, rootKey) |         setPreferencesFromResource(R.xml.settins_ui, rootKey) | ||||||
|  | @ -71,6 +73,7 @@ class SettingsUI : PreferenceFragmentCompat() { | ||||||
|                     settingsManager.edit() |                     settingsManager.edit() | ||||||
|                         .putInt(getString(R.string.app_layout_key), prefValues[it]) |                         .putInt(getString(R.string.app_layout_key), prefValues[it]) | ||||||
|                         .apply() |                         .apply() | ||||||
|  |                     context?.updateTv() | ||||||
|                     activity?.recreate() |                     activity?.recreate() | ||||||
|                 } catch (e: Exception) { |                 } catch (e: Exception) { | ||||||
|                     logError(e) |                     logError(e) | ||||||
|  | @ -130,7 +133,10 @@ class SettingsUI : PreferenceFragmentCompat() { | ||||||
| 
 | 
 | ||||||
|         getPref(R.string.pref_filter_search_quality_key)?.setOnPreferenceClickListener { |         getPref(R.string.pref_filter_search_quality_key)?.setOnPreferenceClickListener { | ||||||
|             val names = enumValues<SearchQuality>().sorted().map { it.name } |             val names = enumValues<SearchQuality>().sorted().map { it.name } | ||||||
|             val currentList = settingsManager.getStringSet(getString(R.string.pref_filter_search_quality_key), setOf())?.map { |             val currentList = settingsManager.getStringSet( | ||||||
|  |                 getString(R.string.pref_filter_search_quality_key), | ||||||
|  |                 setOf() | ||||||
|  |             )?.map { | ||||||
|                 it.toInt() |                 it.toInt() | ||||||
|             } ?: listOf() |             } ?: listOf() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ import android.view.ViewGroup | ||||||
| import android.widget.LinearLayout | import android.widget.LinearLayout | ||||||
| import android.widget.Toast | import android.widget.Toast | ||||||
| import androidx.appcompat.app.AlertDialog | import androidx.appcompat.app.AlertDialog | ||||||
|  | import androidx.core.view.isGone | ||||||
| import androidx.core.view.isVisible | import androidx.core.view.isVisible | ||||||
| import androidx.fragment.app.Fragment | import androidx.fragment.app.Fragment | ||||||
| import androidx.fragment.app.activityViewModels | import androidx.fragment.app.activityViewModels | ||||||
|  | @ -23,12 +24,14 @@ import com.lagradost.cloudstream3.mvvm.Some | ||||||
| import com.lagradost.cloudstream3.mvvm.observe | import com.lagradost.cloudstream3.mvvm.observe | ||||||
| import com.lagradost.cloudstream3.plugins.RepositoryManager | import com.lagradost.cloudstream3.plugins.RepositoryManager | ||||||
| import com.lagradost.cloudstream3.ui.result.setText | import com.lagradost.cloudstream3.ui.result.setText | ||||||
|  | import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings | ||||||
| import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings | import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings | ||||||
| import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar | import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar | ||||||
| import com.lagradost.cloudstream3.utils.AppUtils.downloadAllPluginsDialog | import com.lagradost.cloudstream3.utils.AppUtils.downloadAllPluginsDialog | ||||||
| import com.lagradost.cloudstream3.utils.Coroutines.ioSafe | import com.lagradost.cloudstream3.utils.Coroutines.ioSafe | ||||||
| import com.lagradost.cloudstream3.utils.Coroutines.main | import com.lagradost.cloudstream3.utils.Coroutines.main | ||||||
| import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe | import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe | ||||||
|  | import com.lagradost.cloudstream3.widget.LinearRecycleViewLayoutManager | ||||||
| import kotlinx.android.synthetic.main.add_repo_input.* | import kotlinx.android.synthetic.main.add_repo_input.* | ||||||
| import kotlinx.android.synthetic.main.fragment_extensions.* | import kotlinx.android.synthetic.main.fragment_extensions.* | ||||||
| import kotlinx.android.synthetic.main.fragment_extensions.list_repositories | import kotlinx.android.synthetic.main.fragment_extensions.list_repositories | ||||||
|  | @ -119,9 +122,15 @@ class ExtensionsFragment : Fragment() { | ||||||
|             (repo_recycler_view?.adapter as? RepoAdapter)?.updateList(it) |             (repo_recycler_view?.adapter as? RepoAdapter)?.updateList(it) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         repo_recycler_view?.apply { | ||||||
|  |             context?.let { ctx -> | ||||||
|  |                 layoutManager = LinearRecycleViewLayoutManager(ctx, nextFocusUpId, nextFocusDownId) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         list_repositories?.setOnClickListener { |         list_repositories?.setOnClickListener { | ||||||
|             // Open webview on tv if browser fails |             // Open webview on tv if browser fails | ||||||
|             val isTv = it.context.isTvSettings() |             val isTv = isTvSettings() | ||||||
|             openBrowser(PUBLIC_REPOSITORIES_LIST, isTv, this) |             openBrowser(PUBLIC_REPOSITORIES_LIST, isTv, this) | ||||||
| 
 | 
 | ||||||
|             // Set clipboard on TV because the browser might not exist or work properly |             // Set clipboard on TV because the browser might not exist or work properly | ||||||
|  | @ -170,9 +179,9 @@ class ExtensionsFragment : Fragment() { | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         add_repo_button?.setOnClickListener { |         val addRepositoryClick = View.OnClickListener { | ||||||
|             val builder = |             val builder = | ||||||
|                 AlertDialog.Builder(context ?: return@setOnClickListener, R.style.AlertDialogCustom) |                 AlertDialog.Builder(context ?: return@OnClickListener, R.style.AlertDialogCustom) | ||||||
|                     .setView(R.layout.add_repo_input) |                     .setView(R.layout.add_repo_input) | ||||||
| 
 | 
 | ||||||
|             val dialog = builder.create() |             val dialog = builder.create() | ||||||
|  | @ -193,8 +202,7 @@ class ExtensionsFragment : Fragment() { | ||||||
| 
 | 
 | ||||||
|             dialog.list_repositories?.setOnClickListener { |             dialog.list_repositories?.setOnClickListener { | ||||||
|                 // Open webview on tv if browser fails |                 // Open webview on tv if browser fails | ||||||
|                 val isTv = it.context.isTvSettings() |                 openBrowser(PUBLIC_REPOSITORIES_LIST, isTvSettings(), this) | ||||||
|                 openBrowser(PUBLIC_REPOSITORIES_LIST, isTv, this) |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| //            dialog.text2?.text = provider.name | //            dialog.text2?.text = provider.name | ||||||
|  | @ -223,6 +231,12 @@ class ExtensionsFragment : Fragment() { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         val isTv = isTrueTvSettings() | ||||||
|  |         add_repo_button?.isGone = isTv | ||||||
|  |         add_repo_button_imageview_holder?.isVisible = isTv | ||||||
|  |         add_repo_button?.setOnClickListener(addRepositoryClick) | ||||||
|  |         add_repo_button_imageview?.setOnClickListener(addRepositoryClick) | ||||||
|  | 
 | ||||||
|         reloadRepositories() |         reloadRepositories() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -14,6 +14,7 @@ import com.lagradost.cloudstream3.R | ||||||
| import com.lagradost.cloudstream3.plugins.PluginManager | import com.lagradost.cloudstream3.plugins.PluginManager | ||||||
| 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.result.txt | ||||||
|  | import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings | ||||||
| import com.lagradost.cloudstream3.utils.AppUtils.html | import com.lagradost.cloudstream3.utils.AppUtils.html | ||||||
| import com.lagradost.cloudstream3.utils.GlideApp | import com.lagradost.cloudstream3.utils.GlideApp | ||||||
| import com.lagradost.cloudstream3.utils.SubtitleHelper.fromTwoLettersToLanguage | import com.lagradost.cloudstream3.utils.SubtitleHelper.fromTwoLettersToLanguage | ||||||
|  | @ -36,8 +37,9 @@ class PluginAdapter( | ||||||
|     private val plugins: MutableList<PluginViewData> = mutableListOf() |     private val plugins: MutableList<PluginViewData> = mutableListOf() | ||||||
| 
 | 
 | ||||||
|     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 | ||||||
|         return PluginViewHolder( |         return PluginViewHolder( | ||||||
|             LayoutInflater.from(parent.context).inflate(R.layout.repository_item, parent, false) |             LayoutInflater.from(parent.context).inflate(layout, parent, false) | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -123,7 +125,6 @@ class PluginAdapter( | ||||||
|             itemView.action_button?.setOnClickListener { |             itemView.action_button?.setOnClickListener { | ||||||
|                 iconClickCallback.invoke(data.plugin) |                 iconClickCallback.invoke(data.plugin) | ||||||
|             } |             } | ||||||
|             testFindClosestBase2() |  | ||||||
|             //if (itemView.context?.isTrueTvSettings() == false) { |             //if (itemView.context?.isTrueTvSettings() == false) { | ||||||
|             //    val siteUrl = metadata.repositoryUrl |             //    val siteUrl = metadata.repositoryUrl | ||||||
|             //    if (siteUrl != null && siteUrl.isNotBlank() && siteUrl != "NONE") { |             //    if (siteUrl != null && siteUrl.isNotBlank() && siteUrl != "NONE") { | ||||||
|  |  | ||||||
|  | @ -128,7 +128,7 @@ class PluginsFragment : Fragment() { | ||||||
|                 pluginViewModel.handlePluginAction(activity, url, it, isLocal) |                 pluginViewModel.handlePluginAction(activity, url, it, isLocal) | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|         if (context?.isTvSettings() == true) { |         if (isTvSettings()) { | ||||||
|             // Scrolling down does not reveal the whole RecyclerView on TV, add to bypass that. |             // Scrolling down does not reveal the whole RecyclerView on TV, add to bypass that. | ||||||
|             plugin_recycler_view?.setPadding(0, 0, 0, 200.toPx) |             plugin_recycler_view?.setPadding(0, 0, 0, 200.toPx) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ import androidx.recyclerview.widget.DiffUtil | ||||||
| import androidx.recyclerview.widget.RecyclerView | import androidx.recyclerview.widget.RecyclerView | ||||||
| import com.lagradost.cloudstream3.R | import com.lagradost.cloudstream3.R | ||||||
| import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES | import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES | ||||||
|  | import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings | ||||||
| import kotlinx.android.synthetic.main.repository_item.view.* | import kotlinx.android.synthetic.main.repository_item.view.* | ||||||
| 
 | 
 | ||||||
| class RepoAdapter( | class RepoAdapter( | ||||||
|  | @ -19,8 +20,9 @@ class RepoAdapter( | ||||||
|     private val repositories: MutableList<RepositoryData> = mutableListOf() |     private val repositories: MutableList<RepositoryData> = mutableListOf() | ||||||
| 
 | 
 | ||||||
|     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 | ||||||
|         return RepoViewHolder( |         return RepoViewHolder( | ||||||
|             LayoutInflater.from(parent.context).inflate(R.layout.repository_item, parent, false) |             LayoutInflater.from(parent.context).inflate(layout, parent, false) | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -73,8 +73,7 @@ class SetupFragmentExtensions : Fragment() { | ||||||
|             } else { |             } else { | ||||||
|                 list_repositories?.setOnClickListener { |                 list_repositories?.setOnClickListener { | ||||||
|                     // Open webview on tv if browser fails |                     // Open webview on tv if browser fails | ||||||
|                     val isTv = it.context.isTvSettings() |                     openBrowser(PUBLIC_REPOSITORIES_LIST, isTvSettings(), this) | ||||||
|                     openBrowser(PUBLIC_REPOSITORIES_LIST, isTv, this) |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -86,8 +85,7 @@ class SetupFragmentExtensions : Fragment() { | ||||||
|         val isSetup = arguments?.getBoolean(SETUP_EXTENSION_BUNDLE_IS_SETUP) ?: false |         val isSetup = arguments?.getBoolean(SETUP_EXTENSION_BUNDLE_IS_SETUP) ?: false | ||||||
| 
 | 
 | ||||||
|         view_public_repositories_button?.setOnClickListener { |         view_public_repositories_button?.setOnClickListener { | ||||||
|             val isTv = it.context.isTvSettings() |             openBrowser(PUBLIC_REPOSITORIES_LIST, isTvSettings(), this) | ||||||
|             openBrowser(PUBLIC_REPOSITORIES_LIST, isTv, this) |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         with(context) { |         with(context) { | ||||||
|  |  | ||||||
|  | @ -164,7 +164,7 @@ class ChromecastSubtitlesFragment : Fragment() { | ||||||
|         state = getCurrentSavedStyle() |         state = getCurrentSavedStyle() | ||||||
|         context?.updateState() |         context?.updateState() | ||||||
| 
 | 
 | ||||||
|         val isTvSettings = context?.isTvSettings() == true |         val isTvSettings = isTvSettings() | ||||||
| 
 | 
 | ||||||
|         fun View.setFocusableInTv() { |         fun View.setFocusableInTv() { | ||||||
|             this.isFocusableInTouchMode = isTvSettings |             this.isFocusableInTouchMode = isTvSettings | ||||||
|  |  | ||||||
|  | @ -243,7 +243,7 @@ class SubtitlesFragment : Fragment() { | ||||||
|         state = getCurrentSavedStyle() |         state = getCurrentSavedStyle() | ||||||
|         context?.updateState() |         context?.updateState() | ||||||
| 
 | 
 | ||||||
|         val isTvTrueSettings = context?.isTrueTvSettings() == true |         val isTvTrueSettings = isTrueTvSettings() | ||||||
| 
 | 
 | ||||||
|         fun View.setFocusableInTv() { |         fun View.setFocusableInTv() { | ||||||
|             this.isFocusableInTouchMode = isTvTrueSettings |             this.isFocusableInTouchMode = isTvTrueSettings | ||||||
|  |  | ||||||
|  | @ -407,8 +407,8 @@ object AppUtils { | ||||||
| 
 | 
 | ||||||
|     //private val viewModel: ResultViewModel by activityViewModels() |     //private val viewModel: ResultViewModel by activityViewModels() | ||||||
| 
 | 
 | ||||||
|     private fun getResultsId(context: Context): Int { |     private fun getResultsId(): Int { | ||||||
|         return if (context.isTrueTvSettings()) { |         return if (isTrueTvSettings()) { | ||||||
|             R.id.global_to_navigation_results_tv |             R.id.global_to_navigation_results_tv | ||||||
|         } else { |         } else { | ||||||
|             R.id.global_to_navigation_results_phone |             R.id.global_to_navigation_results_phone | ||||||
|  | @ -424,7 +424,7 @@ object AppUtils { | ||||||
|         this.runOnUiThread { |         this.runOnUiThread { | ||||||
|             // viewModelStore.clear() |             // viewModelStore.clear() | ||||||
|             this.navigate( |             this.navigate( | ||||||
|                 getResultsId(this.applicationContext ?: return@runOnUiThread), |                 getResultsId(), | ||||||
|                 ResultFragment.newInstance(url, apiName, startAction, startValue) |                 ResultFragment.newInstance(url, apiName, startAction, startValue) | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|  | @ -438,7 +438,7 @@ object AppUtils { | ||||||
|         this?.runOnUiThread { |         this?.runOnUiThread { | ||||||
|             // viewModelStore.clear() |             // viewModelStore.clear() | ||||||
|             this.navigate( |             this.navigate( | ||||||
|                 getResultsId(this), |                 getResultsId(), | ||||||
|                 ResultFragment.newInstance(card, startAction, startValue) |                 ResultFragment.newInstance(card, startAction, startValue) | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -44,7 +44,7 @@ object SingleSelectionHelper { | ||||||
|     ) { |     ) { | ||||||
|         if (this == null) return |         if (this == null) return | ||||||
| 
 | 
 | ||||||
|         if (this.isTvSettings()) { |         if (isTvSettings()) { | ||||||
|             val builder = |             val builder = | ||||||
|                 AlertDialog.Builder(this, R.style.AlertDialogCustom) |                 AlertDialog.Builder(this, R.style.AlertDialogCustom) | ||||||
|                     .setView(R.layout.options_popup_tv) |                     .setView(R.layout.options_popup_tv) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | package com.lagradost.cloudstream3.widget | ||||||
|  | 
 | ||||||
|  | import android.content.Context | ||||||
|  | import android.view.View | ||||||
|  | import androidx.recyclerview.widget.LinearLayoutManager | ||||||
|  | 
 | ||||||
|  | class LinearRecycleViewLayoutManager( | ||||||
|  |     val context: Context, | ||||||
|  |     val nextFocusUp: Int, | ||||||
|  |     val nextFocusDown: Int | ||||||
|  | ) : LinearLayoutManager(context) { | ||||||
|  |     override fun onInterceptFocusSearch(focused: View, direction: Int): View? { | ||||||
|  |         return try { | ||||||
|  |             val position = getPosition(focused) | ||||||
|  |             val count = itemCount | ||||||
|  |             //println("onInterceptFocusSearch position=$position count=$count focused=$focused direction=$direction") | ||||||
|  | 
 | ||||||
|  |             (if (position == count - 1 && direction == View.FOCUS_DOWN) { | ||||||
|  |                 focused.rootView.findViewById(nextFocusDown) | ||||||
|  |             } else if (position == 0 && direction == View.FOCUS_UP) { | ||||||
|  |                 focused.rootView.findViewById(nextFocusUp) | ||||||
|  |             } else { | ||||||
|  |                 super.onInterceptFocusSearch(focused, direction) | ||||||
|  |             }) ?: super.onInterceptFocusSearch(focused, direction) | ||||||
|  |         } catch (t : Throwable)  { | ||||||
|  |             super.onInterceptFocusSearch(focused, direction) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @ -29,7 +29,10 @@ | ||||||
|             android:textStyle="bold" /> |             android:textStyle="bold" /> | ||||||
| 
 | 
 | ||||||
|         <com.google.android.material.button.MaterialButton |         <com.google.android.material.button.MaterialButton | ||||||
|  |             android:nextFocusDown="@id/repo_name_input" | ||||||
|             android:id="@+id/list_repositories" |             android:id="@+id/list_repositories" | ||||||
|  |             android:nextFocusLeft="@id/apply_btt" | ||||||
|  |             android:nextFocusRight="@id/cancel_btt" | ||||||
|             style="@style/WhiteButton" |             style="@style/WhiteButton" | ||||||
|             android:layout_width="wrap_content" |             android:layout_width="wrap_content" | ||||||
|             android:layout_gravity="center_vertical" |             android:layout_gravity="center_vertical" | ||||||
|  | @ -67,6 +70,7 @@ | ||||||
|             android:autofillHints="username" |             android:autofillHints="username" | ||||||
|             android:hint="@string/repository_name_hint" |             android:hint="@string/repository_name_hint" | ||||||
|             android:inputType="text" |             android:inputType="text" | ||||||
|  |             android:nextFocusUp="@id/list_repositories" | ||||||
|             android:nextFocusLeft="@id/apply_btt" |             android:nextFocusLeft="@id/apply_btt" | ||||||
|             android:nextFocusRight="@id/cancel_btt" |             android:nextFocusRight="@id/cancel_btt" | ||||||
|             android:nextFocusDown="@id/site_url_input" |             android:nextFocusDown="@id/site_url_input" | ||||||
|  |  | ||||||
|  | @ -11,6 +11,8 @@ | ||||||
|     <include layout="@layout/standard_toolbar" /> |     <include layout="@layout/standard_toolbar" /> | ||||||
| 
 | 
 | ||||||
|     <androidx.recyclerview.widget.RecyclerView |     <androidx.recyclerview.widget.RecyclerView | ||||||
|  |         android:nextFocusUp="@id/settings_toolbar" | ||||||
|  |         android:nextFocusDown="@id/plugin_storage_appbar" | ||||||
|         android:id="@+id/repo_recycler_view" |         android:id="@+id/repo_recycler_view" | ||||||
|         android:layout_width="match_parent" |         android:layout_width="match_parent" | ||||||
|         android:layout_height="match_parent" |         android:layout_height="match_parent" | ||||||
|  | @ -23,13 +25,13 @@ | ||||||
|         tools:visibility="visible" /> |         tools:visibility="visible" /> | ||||||
| 
 | 
 | ||||||
|     <LinearLayout |     <LinearLayout | ||||||
|         tools:visibility="gone" |  | ||||||
|         android:id="@+id/blank_repo_screen" |         android:id="@+id/blank_repo_screen" | ||||||
|         android:layout_width="match_parent" |         android:layout_width="match_parent" | ||||||
|         android:layout_height="match_parent" |         android:layout_height="match_parent" | ||||||
|         android:layout_margin="20dp" |         android:layout_margin="20dp" | ||||||
|         android:gravity="center" |         android:gravity="center" | ||||||
|         android:orientation="vertical"> |         android:orientation="vertical" | ||||||
|  |         tools:visibility="gone"> | ||||||
| 
 | 
 | ||||||
|         <ImageView |         <ImageView | ||||||
|             android:layout_width="30dp" |             android:layout_width="30dp" | ||||||
|  | @ -38,36 +40,40 @@ | ||||||
|             android:src="@drawable/ic_baseline_extension_24" /> |             android:src="@drawable/ic_baseline_extension_24" /> | ||||||
| 
 | 
 | ||||||
|         <TextView |         <TextView | ||||||
|             android:layout_marginBottom="20dp" |  | ||||||
|             android:layout_width="wrap_content" |             android:layout_width="wrap_content" | ||||||
|             android:layout_height="wrap_content" |             android:layout_height="wrap_content" | ||||||
|  |             android:layout_marginBottom="20dp" | ||||||
|             android:gravity="center" |             android:gravity="center" | ||||||
|             android:text="@string/blank_repo_message" |             android:text="@string/blank_repo_message" | ||||||
|             android:textSize="16sp" /> |             android:textSize="16sp" /> | ||||||
| 
 | 
 | ||||||
|         <com.google.android.material.button.MaterialButton |         <com.google.android.material.button.MaterialButton | ||||||
|             android:id="@+id/list_repositories" |             android:id="@+id/list_repositories" | ||||||
|             android:nextFocusDown="@id/add_repo_button" |  | ||||||
|             style="@style/WhiteButton" |             style="@style/WhiteButton" | ||||||
|             android:layout_width="wrap_content" |             android:layout_width="wrap_content" | ||||||
|  |             android:nextFocusDown="@id/add_repo_button" | ||||||
|             android:text="@string/view_public_repositories_button" /> |             android:text="@string/view_public_repositories_button" /> | ||||||
|     </LinearLayout> |     </LinearLayout> | ||||||
| 
 | 
 | ||||||
|     <LinearLayout |     <LinearLayout | ||||||
|         android:foreground="@drawable/outline_drawable" |  | ||||||
|         android:nextFocusUp="@id/add_repo_button" |  | ||||||
|         android:id="@+id/plugin_storage_appbar" |         android:id="@+id/plugin_storage_appbar" | ||||||
|  |         android:nextFocusRight="@id/add_repo_button_imageview" | ||||||
|         android:layout_width="match_parent" |         android:layout_width="match_parent" | ||||||
|         android:layout_height="80dp" |         android:layout_height="80dp" | ||||||
|         android:layout_gravity="bottom" |         android:layout_gravity="bottom" | ||||||
|         android:background="?attr/primaryGrayBackground" |         android:background="?attr/primaryGrayBackground" | ||||||
|         android:orientation="vertical" |         android:foreground="@drawable/outline_drawable" | ||||||
|         android:padding="10dp" |         android:padding="10dp" | ||||||
|         android:visibility="visible" |         android:visibility="visible" | ||||||
| 
 | 
 | ||||||
|         app:layout_constraintBottom_toBottomOf="parent" |         android:orientation="horizontal"> | ||||||
|         app:layout_constraintEnd_toEndOf="parent" | 
 | ||||||
|         app:layout_constraintStart_toStartOf="parent"> |         <LinearLayout | ||||||
|  |             android:layout_weight="1" | ||||||
|  |             android:layout_width="0dp" | ||||||
|  |             android:layout_height="wrap_content" | ||||||
|  | 
 | ||||||
|  |             android:orientation="vertical"> | ||||||
| 
 | 
 | ||||||
|             <TextView |             <TextView | ||||||
|                 android:layout_width="wrap_content" |                 android:layout_width="wrap_content" | ||||||
|  | @ -160,12 +166,42 @@ | ||||||
|                     tools:text="Not downloaded 3" /> |                     tools:text="Not downloaded 3" /> | ||||||
|             </LinearLayout> |             </LinearLayout> | ||||||
|         </LinearLayout> |         </LinearLayout> | ||||||
|  |         <LinearLayout | ||||||
|  |             android:id="@+id/add_repo_button_imageview_holder" | ||||||
|  |             android:paddingStart="10dp" | ||||||
|  |             android:paddingEnd="10dp" | ||||||
|  |             android:orientation="vertical" | ||||||
|  |             android:layout_width="wrap_content" | ||||||
|  |             android:layout_height="match_parent"> | ||||||
|  | 
 | ||||||
|  |             <TextView | ||||||
|  |                 android:textColor="?attr/textColor" | ||||||
|  |                 android:layout_gravity="center" | ||||||
|  | 
 | ||||||
|  |                 android:text="@string/add_repository" | ||||||
|  |                 android:layout_width="wrap_content" | ||||||
|  |                 android:layout_height="wrap_content" /> | ||||||
|  |             <ImageView | ||||||
|  |                 android:background="@drawable/outline_drawable" | ||||||
|  |                 android:nextFocusLeft="@id/plugin_storage_appbar" | ||||||
|  |                 android:layout_gravity="center" | ||||||
|  | 
 | ||||||
|  |                 android:id="@+id/add_repo_button_imageview" | ||||||
|  |                 android:layout_width="40dp" | ||||||
|  |                 android:layout_height="40dp" | ||||||
|  |                 android:src="@drawable/ic_baseline_add_24" | ||||||
|  |                 android:contentDescription="@string/add_repository" | ||||||
|  |                 app:tint="?attr/textColor"> | ||||||
|  |             </ImageView> | ||||||
|  |         </LinearLayout> | ||||||
|  | 
 | ||||||
|  |     </LinearLayout> | ||||||
| 
 | 
 | ||||||
|     <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton |     <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton | ||||||
|         android:id="@+id/add_repo_button" |         android:id="@+id/add_repo_button" | ||||||
|  |         style="@style/ExtendedFloatingActionButton" | ||||||
|         android:foreground="@drawable/outline_drawable" |         android:foreground="@drawable/outline_drawable" | ||||||
|         android:nextFocusDown="@id/plugin_storage_appbar" |         android:nextFocusDown="@id/plugin_storage_appbar" | ||||||
|         style="@style/ExtendedFloatingActionButton" |  | ||||||
|         android:text="@string/add_repository" |         android:text="@string/add_repository" | ||||||
|         android:textColor="?attr/textColor" |         android:textColor="?attr/textColor" | ||||||
|         android:translationY="-80dp" |         android:translationY="-80dp" | ||||||
|  |  | ||||||
							
								
								
									
										122
									
								
								app/src/main/res/layout/repository_item_tv.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								app/src/main/res/layout/repository_item_tv.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,122 @@ | ||||||
|  | <?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:id="@+id/repository_item_root" | ||||||
|  |     android:layout_width="match_parent" | ||||||
|  |     android:layout_height="wrap_content" | ||||||
|  |     android:background="@drawable/outline_drawable" | ||||||
|  |     android:nextFocusRight="@id/action_button" | ||||||
|  |     android:orientation="horizontal" | ||||||
|  |     android:padding="12dp"> | ||||||
|  | 
 | ||||||
|  |     <ImageView | ||||||
|  |         android:id="@+id/entry_icon" | ||||||
|  |         android:layout_width="32dp" | ||||||
|  |         android:layout_height="32dp" | ||||||
|  |         android:layout_gravity="start|center_vertical" | ||||||
|  |         android:layout_marginEnd="16dp" | ||||||
|  |         android:scaleType="fitCenter" | ||||||
|  |         app:srcCompat="@drawable/ic_github_logo" /> | ||||||
|  | 
 | ||||||
|  |     <LinearLayout | ||||||
|  |         android:layout_width="0dp" | ||||||
|  |         android:layout_height="wrap_content" | ||||||
|  |         android:layout_gravity="center_vertical" | ||||||
|  |         android:layout_weight="1" | ||||||
|  |         android:orientation="vertical"> | ||||||
|  | 
 | ||||||
|  |         <TextView | ||||||
|  |             android:id="@+id/main_text" | ||||||
|  |             android:layout_width="wrap_content" | ||||||
|  |             android:layout_height="wrap_content" | ||||||
|  |             android:textColor="?attr/textColor" | ||||||
|  |             android:textSize="16sp" | ||||||
|  |             tools:text="Test repository" /> | ||||||
|  | 
 | ||||||
|  |         <LinearLayout | ||||||
|  |             android:layout_width="match_parent" | ||||||
|  |             android:layout_height="match_parent" | ||||||
|  |             android:layout_gravity="center_vertical" | ||||||
|  |             android:orientation="horizontal"> | ||||||
|  | 
 | ||||||
|  |             <TextView | ||||||
|  |                 android:id="@+id/lang_icon" | ||||||
|  |                 android:layout_width="wrap_content" | ||||||
|  |                 android:layout_height="match_parent" | ||||||
|  |                 android:layout_marginEnd="5dp" | ||||||
|  |                 android:text="🇷🇼" | ||||||
|  | 
 | ||||||
|  |                 android:textColor="?attr/grayTextColor" | ||||||
|  |                 android:visibility="gone" | ||||||
|  |                 tools:visibility="visible" /> | ||||||
|  | 
 | ||||||
|  |             <TextView | ||||||
|  |                 android:id="@+id/ext_version" | ||||||
|  |                 android:layout_width="wrap_content" | ||||||
|  |                 android:layout_height="wrap_content" | ||||||
|  |                 android:layout_gravity="center_vertical" | ||||||
|  |                 android:layout_marginEnd="5dp" | ||||||
|  |                 android:text="v1" | ||||||
|  |                 android:textColor="?attr/grayTextColor" | ||||||
|  |                 android:visibility="gone" | ||||||
|  |                 tools:visibility="visible" /> | ||||||
|  | 
 | ||||||
|  |             <TextView | ||||||
|  |                 android:id="@+id/ext_filesize" | ||||||
|  |                 android:layout_width="wrap_content" | ||||||
|  |                 android:layout_height="wrap_content" | ||||||
|  |                 android:layout_gravity="center_vertical" | ||||||
|  |                 android:layout_marginEnd="5dp" | ||||||
|  |                 android:text="100MB" | ||||||
|  |                 android:textColor="?attr/grayTextColor" | ||||||
|  |                 android:visibility="gone" | ||||||
|  |                 tools:visibility="visible" /> | ||||||
|  | 
 | ||||||
|  |             <TextView | ||||||
|  |                 android:id="@+id/nsfw_marker" | ||||||
|  |                 android:layout_width="wrap_content" | ||||||
|  |                 android:layout_height="wrap_content" | ||||||
|  |                 android:text="@string/is_adult" | ||||||
|  |                 android:textColor="@color/adultColor" | ||||||
|  |                 android:visibility="gone" | ||||||
|  |                 tools:visibility="visible" /> | ||||||
|  | 
 | ||||||
|  |         </LinearLayout> | ||||||
|  | 
 | ||||||
|  |         <TextView | ||||||
|  |             android:id="@+id/sub_text" | ||||||
|  |             android:layout_width="wrap_content" | ||||||
|  |             android:layout_height="wrap_content" | ||||||
|  |             android:textColor="?attr/grayTextColor" | ||||||
|  |             android:textSize="12sp" | ||||||
|  |             tools:text="https://github.com/..." /> | ||||||
|  |     </LinearLayout> | ||||||
|  | 
 | ||||||
|  |     <ImageView | ||||||
|  |         android:id="@+id/action_settings" | ||||||
|  |         android:layout_width="wrap_content" | ||||||
|  |         android:layout_height="wrap_content" | ||||||
|  |         android:layout_gravity="center_vertical" | ||||||
|  |         android:padding="12dp" | ||||||
|  |         android:background="@drawable/outline_drawable" | ||||||
|  |         android:contentDescription="@string/title_settings" | ||||||
|  |         android:visibility="gone" | ||||||
|  |         app:srcCompat="@drawable/ic_baseline_tune_24" | ||||||
|  |         tools:visibility="visible" /> | ||||||
|  | 
 | ||||||
|  |     <ImageView | ||||||
|  |         android:id="@+id/action_button" | ||||||
|  |         android:layout_width="wrap_content" | ||||||
|  |         android:layout_height="wrap_content" | ||||||
|  |         android:layout_gravity="center_vertical|end" | ||||||
|  |         android:layout_marginStart="10dp" | ||||||
|  |         android:background="@drawable/outline_drawable" | ||||||
|  |         android:clickable="true" | ||||||
|  |         android:contentDescription="@string/download" | ||||||
|  |         android:focusable="true" | ||||||
|  |         android:nextFocusLeft="@id/repository_item_root" | ||||||
|  |         android:padding="12dp" | ||||||
|  |         tools:src="@drawable/ic_baseline_add_24" /> | ||||||
|  | 
 | ||||||
|  | </LinearLayout> | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue