android tv layout stuff

This commit is contained in:
LagradOst 2021-10-30 20:14:12 +02:00
parent 0766f04ded
commit 3734871608
14 changed files with 207 additions and 30 deletions

View file

@ -254,11 +254,8 @@ fun sortSubs(urls: List<SubtitleFile>): List<SubtitleFile> {
} }
/** https://www.imdb.com/title/tt2861424/ -> tt2861424 */ /** https://www.imdb.com/title/tt2861424/ -> tt2861424 */
fun imdbUrlToId(url: String): String { fun imdbUrlToId(url: String): String? {
return url return Regex("/title/(tt[0-9]*)").find(url)?.groupValues?.get(1) ?: Regex("tt[0-9]{5,}").find(url)?.groupValues?.get(0)
.removePrefix("https://www.imdb.com/title/")
.removePrefix("https://imdb.com/title/tt2861424/")
.replace("/", "")
} }
fun imdbUrlToIdNullable(url: String?): String? { fun imdbUrlToIdNullable(url: String?): String? {

View file

@ -9,8 +9,10 @@ import android.content.pm.PackageManager
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.content.res.Configuration import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Rect
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.TypedValue
import android.view.* import android.view.*
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
@ -31,6 +33,7 @@ import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver
import com.lagradost.cloudstream3.ui.APIRepository import com.lagradost.cloudstream3.ui.APIRepository
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO
import com.lagradost.cloudstream3.ui.player.PlayerEventType import com.lagradost.cloudstream3.ui.player.PlayerEventType
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable
import com.lagradost.cloudstream3.utils.AppUtils.loadResult import com.lagradost.cloudstream3.utils.AppUtils.loadResult
import com.lagradost.cloudstream3.utils.DataStore.getKey import com.lagradost.cloudstream3.utils.DataStore.getKey
@ -49,6 +52,7 @@ import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.fragment_result.* import kotlinx.android.synthetic.main.fragment_result.*
import java.util.* import java.util.*
import kotlin.concurrent.thread import kotlin.concurrent.thread
import kotlin.math.roundToInt
const val VLC_PACKAGE = "org.videolan.vlc" const val VLC_PACKAGE = "org.videolan.vlc"
@ -136,8 +140,28 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
} }
} }
private fun Activity.getRootView(): View {
return findViewById(android.R.id.content)
}
private fun Context.convertDpToPx(dp: Float): Float {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp,
this.resources.displayMetrics
)
}
private fun Activity.isKeyboardOpen(): Boolean {
val visibleBounds = Rect()
this.getRootView().getWindowVisibleDisplayFrame(visibleBounds)
val heightDiff = getRootView().height - visibleBounds.height()
val marginOfError = this.convertDpToPx(50F).roundToInt()
return heightDiff > marginOfError
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
//println("Keycode: $keyCode") println("Keycode: $keyCode")
//showToast( //showToast(
// this, // this,
// "Got Keycode $keyCode | ${KeyEvent.keyCodeToString(keyCode)} \n ${event?.action}", // "Got Keycode $keyCode | ${KeyEvent.keyCodeToString(keyCode)} \n ${event?.action}",
@ -160,16 +184,16 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_A, KeyEvent.KEYCODE_MEDIA_SKIP_BACKWARD, KeyEvent.KEYCODE_MEDIA_REWIND -> { KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_A, KeyEvent.KEYCODE_MEDIA_SKIP_BACKWARD, KeyEvent.KEYCODE_MEDIA_REWIND -> {
PlayerEventType.SeekBack PlayerEventType.SeekBack
} }
KeyEvent.KEYCODE_MEDIA_NEXT -> { KeyEvent.KEYCODE_MEDIA_NEXT, KeyEvent.KEYCODE_BUTTON_R1 -> {
PlayerEventType.NextEpisode PlayerEventType.NextEpisode
} }
KeyEvent.KEYCODE_MEDIA_PREVIOUS -> { KeyEvent.KEYCODE_MEDIA_PREVIOUS, KeyEvent.KEYCODE_BUTTON_L1 -> {
PlayerEventType.PrevEpisode PlayerEventType.PrevEpisode
} }
KeyEvent.KEYCODE_MEDIA_PAUSE -> { KeyEvent.KEYCODE_MEDIA_PAUSE -> {
PlayerEventType.Pause PlayerEventType.Pause
} }
KeyEvent.KEYCODE_MEDIA_PLAY -> { KeyEvent.KEYCODE_MEDIA_PLAY, KeyEvent.KEYCODE_BUTTON_START -> {
PlayerEventType.Play PlayerEventType.Play
} }
KeyEvent.KEYCODE_L, KeyEvent.KEYCODE_NUMPAD_7 -> { KeyEvent.KEYCODE_L, KeyEvent.KEYCODE_NUMPAD_7 -> {
@ -184,13 +208,13 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
KeyEvent.KEYCODE_S, KeyEvent.KEYCODE_NUMPAD_9 -> { KeyEvent.KEYCODE_S, KeyEvent.KEYCODE_NUMPAD_9 -> {
PlayerEventType.ShowMirrors PlayerEventType.ShowMirrors
} }
KeyEvent.KEYCODE_E, KeyEvent.KEYCODE_NUMPAD_3 -> { KeyEvent.KEYCODE_E, KeyEvent.KEYCODE_NUMPAD_3 -> {
PlayerEventType.ShowSpeed PlayerEventType.ShowSpeed
} }
KeyEvent.KEYCODE_R, KeyEvent.KEYCODE_NUMPAD_0 -> { KeyEvent.KEYCODE_R, KeyEvent.KEYCODE_NUMPAD_0 -> {
PlayerEventType.Resize PlayerEventType.Resize
} }
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_SPACE -> { // space is not captured due to navigation KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_SPACE, KeyEvent.KEYCODE_NUMPAD_ENTER, KeyEvent.KEYCODE_ENTER -> { // space is not captured due to navigation
PlayerEventType.PlayPauseToggle PlayerEventType.PlayPauseToggle
} }
else -> null else -> null
@ -198,6 +222,12 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
playerEventListener?.invoke(playerEvent) playerEventListener?.invoke(playerEvent)
} }
when (keyCode) {
KeyEvent.KEYCODE_DPAD_CENTER -> {
println("DPAD PRESSED ${this.isKeyboardOpen()}")
}
}
return super.onKeyDown(keyCode, event) return super.onKeyDown(keyCode, event)
} }
@ -371,7 +401,12 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
setContentView(R.layout.activity_main) if (isTvSettings()) {
setContentView(R.layout.activity_main_tv)
} else {
setContentView(R.layout.activity_main)
}
// val navView: BottomNavigationView = findViewById(R.id.nav_view) // val navView: BottomNavigationView = findViewById(R.id.nav_view)
//https://stackoverflow.com/questions/52594181/how-to-know-if-user-has-disabled-picture-in-picture-feature-permission //https://stackoverflow.com/questions/52594181/how-to-know-if-user-has-disabled-picture-in-picture-feature-permission

View file

@ -996,7 +996,7 @@ class PlayerFragment : Fragment() {
activity?.unregisterReceiver(it) activity?.unregisterReceiver(it)
} }
activity?.hideSystemUI() activity?.hideSystemUI()
this.view?.let { activity?.hideKeyboard(it) } this.view?.let { hideKeyboard(it) }
} }
} }

View file

@ -35,9 +35,11 @@ import com.lagradost.cloudstream3.utils.SEARCH_PROVIDER_TOGGLE
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
import com.lagradost.cloudstream3.utils.UIHelper.showInputMethod
import kotlinx.android.synthetic.main.fragment_search.* import kotlinx.android.synthetic.main.fragment_search.*
import java.util.concurrent.locks.ReentrantLock import java.util.concurrent.locks.ReentrantLock
class SearchFragment : Fragment() { class SearchFragment : Fragment() {
companion object { companion object {
fun List<SearchResponse>.filterSearchResponse(): List<SearchResponse> { fun List<SearchResponse>.filterSearchResponse(): List<SearchResponse> {
@ -360,18 +362,13 @@ class SearchFragment : Fragment() {
typesActive = it.getApiTypeSettings() typesActive = it.getApiTypeSettings()
} }
/*main_search.setOnQueryTextFocusChangeListener { searchView, b -> main_search.setOnQueryTextFocusChangeListener { searchView, b ->
if (b) { if (b) {
// https://stackoverflow.com/questions/12022715/unable-to-show-keyboard-automatically-in-the-searchview // https://stackoverflow.com/questions/12022715/unable-to-show-keyboard-automatically-in-the-searchview
searchView?.postDelayed({ showInputMethod(view.findFocus())
(activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager?)?.showSoftInput(
view.findFocus(),
0
)
}, 200)
} }
} }
main_search.onActionViewExpanded()*/ //main_search.onActionViewExpanded()*/
val masterAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder> = ParentItemAdapter(listOf(), { callback -> val masterAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder> = ParentItemAdapter(listOf(), { callback ->
SearchHelper.handleSearchClickCallback(activity, callback) SearchHelper.handleSearchClickCallback(activity, callback)

View file

@ -1,5 +1,8 @@
package com.lagradost.cloudstream3.ui.settings package com.lagradost.cloudstream3.ui.settings
import android.app.UiModeManager
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle import android.os.Bundle
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
@ -30,6 +33,22 @@ import kotlin.concurrent.thread
class SettingsFragment : PreferenceFragmentCompat() { class SettingsFragment : PreferenceFragmentCompat() {
companion object {
fun Context.isTvSettings(): Boolean {
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
var value = settingsManager.getInt(this.getString(R.string.app_layout_key), -1)
if (value == -1) {
value = if (isAutoTv()) 1 else 0
}
return value == 1
}
private fun Context.isAutoTv(): Boolean {
val uiModeManager = getSystemService(Context.UI_MODE_SERVICE) as UiModeManager?
return uiModeManager?.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION
}
}
private var beneneCount = 0 private var beneneCount = 0
// idk, if you find a way of automating this it would be great // idk, if you find a way of automating this it would be great
@ -61,6 +80,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
val legalPreference = findPreference<Preference>(getString(R.string.legal_notice_key))!! val legalPreference = findPreference<Preference>(getString(R.string.legal_notice_key))!!
val subdubPreference = findPreference<Preference>(getString(R.string.display_sub_key))!! val subdubPreference = findPreference<Preference>(getString(R.string.display_sub_key))!!
val providerLangPreference = findPreference<Preference>(getString(R.string.provider_lang_key))!! val providerLangPreference = findPreference<Preference>(getString(R.string.provider_lang_key))!!
val allLayoutPreference = findPreference<Preference>(getString(R.string.app_layout_key))!!
legalPreference.setOnPreferenceClickListener { legalPreference.setOnPreferenceClickListener {
val builder: AlertDialog.Builder = AlertDialog.Builder(it.context) val builder: AlertDialog.Builder = AlertDialog.Builder(it.context)
@ -141,6 +161,29 @@ class SettingsFragment : PreferenceFragmentCompat() {
return@setOnPreferenceClickListener true return@setOnPreferenceClickListener true
} }
allLayoutPreference.setOnPreferenceClickListener {
val prefNames = resources.getStringArray(R.array.app_layout)
val prefValues = resources.getIntArray(R.array.app_layout_values)
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
val currentLayout =
settingsManager.getInt(getString(R.string.app_layout_key), -1)
context?.showBottomDialog(
prefNames.toList(),
prefValues.indexOf(currentLayout),
getString(R.string.app_layout),
true,
{}) {
try {
settingsManager.edit().putInt(getString(R.string.app_layout_key), prefValues[it]).apply()
activity?.recreate()
} catch (e : Exception) {
logError(e)
}
}
return@setOnPreferenceClickListener true
}
watchQualityPreference.setOnPreferenceClickListener { watchQualityPreference.setOnPreferenceClickListener {
val prefNames = resources.getStringArray(R.array.quality_pref) val prefNames = resources.getStringArray(R.array.quality_pref)
val prefValues = resources.getIntArray(R.array.quality_pref_values) val prefValues = resources.getIntArray(R.array.quality_pref_values)
@ -193,7 +236,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
settingsManager.edit().putInt(getString(R.string.benene_count), beneneCount).apply() settingsManager.edit().putInt(getString(R.string.benene_count), beneneCount).apply()
it.summary = getString(R.string.benene_count_text).format(beneneCount) it.summary = getString(R.string.benene_count_text).format(beneneCount)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() logError(e)
} }
return@setOnPreferenceClickListener true return@setOnPreferenceClickListener true

View file

@ -36,6 +36,7 @@ import androidx.preference.PreferenceManager
import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.load.model.GlideUrl
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -68,7 +69,7 @@ object UIHelper {
activity?.window?.decorView?.clearFocus() activity?.window?.decorView?.clearFocus()
view.let { view.let {
if (it != null) { if (it != null) {
activity?.hideKeyboard(it) hideKeyboard(it)
} }
} }
} }
@ -202,6 +203,10 @@ object UIHelper {
}*/ }*/
fun Context.getStatusBarHeight(): Int { fun Context.getStatusBarHeight(): Int {
if(isTvSettings()) {
return 0
}
var result = 0 var result = 0
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android") val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
if (resourceId > 0) { if (resourceId > 0) {
@ -285,9 +290,14 @@ object UIHelper {
) == AppOpsManager.MODE_ALLOWED ) == AppOpsManager.MODE_ALLOWED
} }
fun Context.hideKeyboard(view: View) { fun hideKeyboard(view: View) {
val inputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager val inputMethodManager = view.context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager?
inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0) inputMethodManager?.hideSoftInputFromWindow(view.windowToken, 0)
}
fun showInputMethod(view: View) {
val inputMethodManager = view.context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager?
inputMethodManager?.showSoftInput(view, 0)
} }
/**id, stringRes */ /**id, stringRes */

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M21,3L3,3c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h5v2h8v-2h5c1.1,0 1.99,-0.9 1.99,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM21,17L3,17L3,5h18v12z"/>
</vector>

View file

@ -6,7 +6,7 @@
android:id="@+id/homeRoot" android:id="@+id/homeRoot"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden" android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|keyboard|navigation"
android:paddingTop="0dp"> android:paddingTop="0dp">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_height="match_parent" android:layout_height="match_parent"

View file

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/homeRoot"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|keyboard|navigation"
android:paddingTop="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_height="match_parent"
android:layout_width="match_parent">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?attr/darkBackground"
android:outlineSpotShadowColor="@color/transparent"
android:outlineAmbientShadowColor="@color/transparent"
app:layout_constraintTop_toTopOf="parent"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toTopOf="@+id/nav_host_fragment"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu"
/>
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintTop_toBottomOf="@+id/nav_view"
app:layout_constraintBottom_toBottomOf="parent"
app:navGraph="@navigation/mobile_navigation"
app:layout_constraintEnd_toEndOf="parent"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/nav_view"
android:id="@+id/cast_mini_controller_holder"
>
<!--com.google.android.gms.cast.framework.media.widget.MiniControllerFragment-->
<fragment
app:customCastBackgroundColor="?attr/darkBackground"
app:castControlButtons="@array/cast_mini_controller_control_buttons"
android:id="@+id/cast_mini_controller"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
class="com.lagradost.cloudstream3.ui.MyMiniControllerFragment"
tools:ignore="FragmentTagUsage">
</fragment>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View file

@ -103,7 +103,7 @@
android:id="@+id/home_settings_bar" android:id="@+id/home_settings_bar"
android:background="?attr/darkBackground" android:background="?attr/darkBackground"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="60dp"> android:layout_height="70dp">
<LinearLayout <LinearLayout
android:gravity="center" android:gravity="center"

View file

@ -27,6 +27,9 @@
android:nextFocusLeft="@id/search_filter" android:nextFocusLeft="@id/search_filter"
android:nextFocusDown="@id/cardSpace" android:nextFocusDown="@id/cardSpace"
android:imeOptions="actionSearch"
android:inputType="text"
android:id="@+id/main_search" android:id="@+id/main_search"
app:queryBackground="@color/transparent" app:queryBackground="@color/transparent"
app:searchIcon="@drawable/search_icon" app:searchIcon="@drawable/search_icon"
@ -38,7 +41,7 @@
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
app:iconifiedByDefault="false" app:iconifiedByDefault="false"
tools:ignore="RtlSymmetry"> tools:ignore="RtlSymmetry">
<requestFocus/>
<androidx.core.widget.ContentLoadingProgressBar <androidx.core.widget.ContentLoadingProgressBar
android:id="@+id/search_loading_bar" android:id="@+id/search_loading_bar"
@ -70,6 +73,7 @@
android:layout_gravity="end|center_vertical" android:layout_gravity="end|center_vertical"
app:tint="?attr/textColor" app:tint="?attr/textColor"
android:contentDescription="@string/change_providers_img_des"> android:contentDescription="@string/change_providers_img_des">
<requestFocus/>
</ImageView> </ImageView>
</FrameLayout> </FrameLayout>

View file

@ -68,4 +68,16 @@
<item>7</item> <item>7</item>
<item>8</item> <item>8</item>
</array> </array>
<array name="app_layout">
<item>@string/automatic</item>
<item>@string/phone_layout</item>
<item>@string/tv_layout</item>
</array>
<array name="app_layout_values">
<item>-1</item>
<item>0</item>
<item>1</item>
</array>
</resources> </resources>

View file

@ -24,7 +24,7 @@
<string name="show_fillers_key" translatable="false">show_fillers_key</string> <string name="show_fillers_key" translatable="false">show_fillers_key</string>
<string name="provider_lang_key" translatable="false">provider_lang_key</string> <string name="provider_lang_key" translatable="false">provider_lang_key</string>
<string name="dns_key" translatable="false">dns_key</string> <string name="dns_key" translatable="false">dns_key</string>
<string name="app_layout_key" translatable="false">app_layout_key</string>
<!-- FORMAT MIGHT TRANSLATE, WILL CAUSE CRASH IF APPLIED WRONG --> <!-- FORMAT MIGHT TRANSLATE, WILL CAUSE CRASH IF APPLIED WRONG -->
<string name="extra_info_format" translatable="false" formatted="true">%d %s | %sMB</string> <string name="extra_info_format" translatable="false" formatted="true">%d %s | %sMB</string>
@ -294,4 +294,9 @@
</string> </string>
<string name="general">General</string> <string name="general">General</string>
<string name="provider_lang_settings">Provider Languages</string> <string name="provider_lang_settings">Provider Languages</string>
<string name="app_layout">App Layout</string>
<string name="automatic">Auto</string>
<string name="tv_layout">Tv Layout</string>
<string name="phone_layout">Phone Layout</string>
</resources> </resources>

View file

@ -99,6 +99,16 @@
android:summary="@string/dns_pref_summary" android:summary="@string/dns_pref_summary"
android:icon="@drawable/ic_baseline_dns_24"> android:icon="@drawable/ic_baseline_dns_24">
</Preference> </Preference>
<Preference
android:icon="@drawable/ic_baseline_language_24"
android:key="@string/provider_lang_key"
android:title="@string/provider_lang_settings">
</Preference>
<Preference
android:icon="@drawable/ic_baseline_tv_24"
android:key="@string/app_layout_key"
android:title="@string/app_layout">
</Preference>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory
android:key="search" android:key="search"