Commit 78f021cd authored by Mygod's avatar Mygod

Update dependencies

parent 6f355ed1
...@@ -32,7 +32,7 @@ buildscript { ...@@ -32,7 +32,7 @@ buildscript {
classpath 'com.android.tools.build:gradle:3.3.0' classpath 'com.android.tools.build:gradle:3.3.0'
classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0' classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0'
classpath 'com.google.gms:google-services:4.2.0' classpath 'com.google.gms:google-services:4.2.0'
classpath 'io.fabric.tools:gradle:1.27.0' classpath 'io.fabric.tools:gradle:1.27.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
} }
} }
......
...@@ -56,7 +56,7 @@ class ProfileConfigActivity : AppCompatActivity() { ...@@ -56,7 +56,7 @@ class ProfileConfigActivity : AppCompatActivity() {
menuInflater.inflate(R.menu.profile_config_menu, menu) menuInflater.inflate(R.menu.profile_config_menu, menu)
return true return true
} }
override fun onOptionsItemSelected(item: MenuItem?) = child.onOptionsItemSelected(item) override fun onOptionsItemSelected(item: MenuItem) = child.onOptionsItemSelected(item)
override fun onBackPressed() { override fun onBackPressed() {
if (DataStore.dirty) AlertDialog.Builder(this) if (DataStore.dirty) AlertDialog.Builder(this)
......
...@@ -179,7 +179,7 @@ class ProfileConfigFragment : PreferenceFragmentCompat(), ...@@ -179,7 +179,7 @@ class ProfileConfigFragment : PreferenceFragmentCompat(),
} else super.onActivityResult(requestCode, resultCode, data) } else super.onActivityResult(requestCode, resultCode, data)
} }
override fun onOptionsItemSelected(item: MenuItem?) = when (item?.itemId) { override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.action_delete -> { R.id.action_delete -> {
val activity = requireActivity() val activity = requireActivity()
AlertDialog.Builder(activity) AlertDialog.Builder(activity)
......
...@@ -99,7 +99,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -99,7 +99,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
return image return image
} }
override fun onAttach(context: Context?) { override fun onAttach(context: Context) {
super.onAttach(context) super.onAttach(context)
val adapter = NfcAdapter.getDefaultAdapter(context) val adapter = NfcAdapter.getDefaultAdapter(context)
adapter?.setNdefPushMessage(NdefMessage(arrayOf( adapter?.setNdefPushMessage(NdefMessage(arrayOf(
......
...@@ -25,7 +25,7 @@ android { ...@@ -25,7 +25,7 @@ android {
dependencies { dependencies {
api "androidx.core:core-ktx:1.0.1" api "androidx.core:core-ktx:1.0.1"
api "com.google.android.material:material:1.1.0-alpha02" api "com.google.android.material:material:1.1.0-alpha03"
api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
testImplementation "junit:junit:$junitVersion" testImplementation "junit:junit:$junitVersion"
androidTestImplementation "androidx.test:runner:$androidTestVersion" androidTestImplementation "androidx.test:runner:$androidTestVersion"
......
...@@ -54,7 +54,7 @@ android { ...@@ -54,7 +54,7 @@ android {
dependencies { dependencies {
implementation project(':core') implementation project(':core')
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "androidx.leanback:leanback-preference:1.0.0" implementation "androidx.leanback:leanback-preference:1.1.0-alpha01"
} }
apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.gms.google-services'
......
...@@ -21,26 +21,26 @@ ...@@ -21,26 +21,26 @@
package com.github.shadowsocks.tv package com.github.shadowsocks.tv
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.leanback.preference.LeanbackPreferenceDialogFragment import androidx.leanback.preference.LeanbackPreferenceDialogFragmentCompat
import androidx.leanback.preference.LeanbackSettingsFragment import androidx.leanback.preference.LeanbackSettingsFragmentCompat
import androidx.preference.* import androidx.preference.*
import com.github.shadowsocks.bg.BaseService import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.tv.preference.LeanbackSingleListPreferenceDialogFragment import com.github.shadowsocks.tv.preference.LeanbackSingleListPreferenceDialogFragment
import com.github.shadowsocks.utils.Key import com.github.shadowsocks.utils.Key
class MainFragment : LeanbackSettingsFragment() { class MainFragment : LeanbackSettingsFragmentCompat() {
override fun onPreferenceStartInitialScreen() = startPreferenceFragment(MainPreferenceFragment()) override fun onPreferenceStartInitialScreen() = startPreferenceFragment(MainPreferenceFragment())
override fun onPreferenceStartScreen(caller: PreferenceFragment?, pref: PreferenceScreen?): Boolean { override fun onPreferenceStartScreen(caller: PreferenceFragmentCompat?, pref: PreferenceScreen?): Boolean {
onPreferenceStartInitialScreen() onPreferenceStartInitialScreen()
return true return true
} }
override fun onPreferenceStartFragment(caller: PreferenceFragment?, pref: Preference?) = false override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat?, pref: Preference?) = false
override fun onPreferenceDisplayDialog(caller: PreferenceFragment, pref: Preference?): Boolean { override fun onPreferenceDisplayDialog(caller: PreferenceFragmentCompat, pref: Preference?): Boolean {
if (pref?.key == Key.id) { if (pref?.key == Key.id) {
if ((childFragmentManager.findFragmentById(R.id.settings_preference_fragment_container) if ((childFragmentManager.findFragmentById(R.id.settings_preference_fragment_container)
as MainPreferenceFragment).state == BaseService.STOPPED) { as MainPreferenceFragment).state == BaseService.STOPPED) {
startPreferenceFragment(ProfilesDialogFragment().apply { startPreferenceFragment(ProfilesDialogFragment().apply {
arguments = bundleOf(Pair(LeanbackPreferenceDialogFragment.ARG_KEY, Key.id)) arguments = bundleOf(Pair(LeanbackPreferenceDialogFragmentCompat.ARG_KEY, Key.id))
setTargetFragment(caller, 0) setTargetFragment(caller, 0)
}) })
} }
...@@ -48,7 +48,7 @@ class MainFragment : LeanbackSettingsFragment() { ...@@ -48,7 +48,7 @@ class MainFragment : LeanbackSettingsFragment() {
} }
if (pref is ListPreference && pref !is MultiSelectListPreference) { if (pref is ListPreference && pref !is MultiSelectListPreference) {
startPreferenceFragment(LeanbackSingleListPreferenceDialogFragment().apply { startPreferenceFragment(LeanbackSingleListPreferenceDialogFragment().apply {
arguments = bundleOf(Pair(LeanbackPreferenceDialogFragment.ARG_KEY, pref.key)) arguments = bundleOf(Pair(LeanbackPreferenceDialogFragmentCompat.ARG_KEY, pref.key))
setTargetFragment(caller, 0) setTargetFragment(caller, 0)
}) })
return true return true
......
...@@ -32,8 +32,7 @@ import android.text.format.Formatter ...@@ -32,8 +32,7 @@ import android.text.format.Formatter
import android.util.Log import android.util.Log
import android.util.LongSparseArray import android.util.LongSparseArray
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.FragmentActivity import androidx.leanback.preference.LeanbackPreferenceFragmentCompat
import androidx.leanback.preference.LeanbackPreferenceFragment
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders import androidx.lifecycle.ViewModelProviders
import androidx.lifecycle.get import androidx.lifecycle.get
...@@ -55,10 +54,12 @@ import com.github.shadowsocks.net.HttpsTest ...@@ -55,10 +54,12 @@ import com.github.shadowsocks.net.HttpsTest
import com.github.shadowsocks.net.TcpFastOpen import com.github.shadowsocks.net.TcpFastOpen
import com.github.shadowsocks.preference.DataStore import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.preference.OnPreferenceDataStoreChangeListener import com.github.shadowsocks.preference.OnPreferenceDataStoreChangeListener
import com.github.shadowsocks.utils.* import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.datas
import com.github.shadowsocks.utils.printLog
import org.json.JSONArray import org.json.JSONArray
class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnection.Callback, class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksConnection.Callback,
OnPreferenceDataStoreChangeListener { OnPreferenceDataStoreChangeListener {
companion object { companion object {
private const val REQUEST_CONNECT = 1 private const val REQUEST_CONNECT = 1
...@@ -94,11 +95,13 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti ...@@ -94,11 +95,13 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti
private set private set
override fun stateChanged(state: Int, profileName: String?, msg: String?) = changeState(state, msg) override fun stateChanged(state: Int, profileName: String?, msg: String?) = changeState(state, msg)
override fun trafficUpdated(profileId: Long, stats: TrafficStats) { override fun trafficUpdated(profileId: Long, stats: TrafficStats) {
if (profileId == 0L) this@MainPreferenceFragment.stats.summary = getString(R.string.stat_summary, if (profileId == 0L) requireContext().let { context ->
getString(R.string.speed, Formatter.formatFileSize(activity, stats.txRate)), this.stats.summary = getString(R.string.stat_summary,
getString(R.string.speed, Formatter.formatFileSize(activity, stats.rxRate)), getString(R.string.speed, Formatter.formatFileSize(context, stats.txRate)),
Formatter.formatFileSize(activity, stats.txTotal), getString(R.string.speed, Formatter.formatFileSize(context, stats.rxRate)),
Formatter.formatFileSize(activity, stats.rxTotal)) Formatter.formatFileSize(context, stats.txTotal),
Formatter.formatFileSize(context, stats.rxTotal))
}
} }
private fun changeState(state: Int, msg: String? = null) { private fun changeState(state: Int, msg: String? = null) {
...@@ -111,15 +114,14 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti ...@@ -111,15 +114,14 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti
}) })
stats.setTitle(R.string.connection_test_pending) stats.setTitle(R.string.connection_test_pending)
stats.isVisible = state == BaseService.CONNECTED stats.isVisible = state == BaseService.CONNECTED
val owner = activity as FragmentActivity // TODO: change to this when refactored to androidx
if (state != BaseService.CONNECTED) { if (state != BaseService.CONNECTED) {
trafficUpdated(0, TrafficStats()) trafficUpdated(0, TrafficStats())
tester.status.removeObservers(owner) tester.status.removeObservers(this)
if (state != BaseService.IDLE) tester.invalidate() if (state != BaseService.IDLE) tester.invalidate()
} else tester.status.observe(owner, Observer { } else tester.status.observe(this, Observer {
it.retrieve(stats::setTitle) { Toast.makeText(activity, it, Toast.LENGTH_LONG).show() } it.retrieve(stats::setTitle) { Toast.makeText(requireContext(), it, Toast.LENGTH_LONG).show() }
}) })
if (msg != null) Toast.makeText(activity, getString(R.string.vpn_error, msg), Toast.LENGTH_SHORT).show() if (msg != null) Toast.makeText(requireContext(), getString(R.string.vpn_error, msg), Toast.LENGTH_SHORT).show()
this.state = state this.state = state
if (state == BaseService.STOPPED) { if (state == BaseService.STOPPED) {
controlImport.isEnabled = true controlImport.isEnabled = true
...@@ -148,9 +150,9 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti ...@@ -148,9 +150,9 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti
}) })
override fun onServiceDisconnected() = changeState(BaseService.IDLE) override fun onServiceDisconnected() = changeState(BaseService.IDLE)
override fun onBinderDied() { override fun onBinderDied() {
connection.disconnect(activity) connection.disconnect(requireContext())
Executable.killAll() Executable.killAll()
connection.connect(activity, this) connection.connect(requireContext(), this)
} }
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
...@@ -176,7 +178,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti ...@@ -176,7 +178,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti
if (value as Boolean && !TcpFastOpen.sendEnabled) { if (value as Boolean && !TcpFastOpen.sendEnabled) {
val result = TcpFastOpen.enable()?.trim() val result = TcpFastOpen.enable()?.trim()
if (TcpFastOpen.sendEnabled) true else { if (TcpFastOpen.sendEnabled) true else {
Toast.makeText(activity, if (result.isNullOrEmpty()) Toast.makeText(requireContext(), if (result.isNullOrEmpty())
getText(R.string.tcp_fastopen_failure) else result, Toast.LENGTH_SHORT).show() getText(R.string.tcp_fastopen_failure) else result, Toast.LENGTH_SHORT).show()
false false
} }
...@@ -196,14 +198,14 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti ...@@ -196,14 +198,14 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti
findPreference(Key.about).apply { findPreference(Key.about).apply {
summary = getString(R.string.about_title, BuildConfig.VERSION_NAME) summary = getString(R.string.about_title, BuildConfig.VERSION_NAME)
setOnPreferenceClickListener { setOnPreferenceClickListener {
Toast.makeText(activity, "https://shadowsocks.org/android", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), "https://shadowsocks.org/android", Toast.LENGTH_SHORT).show()
true true
} }
} }
tester = ViewModelProviders.of(activity as FragmentActivity).get() tester = ViewModelProviders.of(this).get()
changeState(BaseService.IDLE) // reset everything to init state changeState(BaseService.IDLE) // reset everything to init state
connection.connect(activity, this) connection.connect(requireContext(), this)
DataStore.publicStore.registerChangeListener(this) DataStore.publicStore.registerChangeListener(this)
} }
...@@ -229,7 +231,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti ...@@ -229,7 +231,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti
when { when {
state != BaseService.STOPPED -> return state != BaseService.STOPPED -> return
DataStore.serviceMode == Key.modeVpn -> { DataStore.serviceMode == Key.modeVpn -> {
val intent = VpnService.prepare(activity) val intent = VpnService.prepare(requireContext())
if (intent != null) startActivityForResult(intent, REQUEST_CONNECT) if (intent != null) startActivityForResult(intent, REQUEST_CONNECT)
else onActivityResult(REQUEST_CONNECT, Activity.RESULT_OK, null) else onActivityResult(REQUEST_CONNECT, Activity.RESULT_OK, null)
} }
...@@ -240,8 +242,8 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti ...@@ -240,8 +242,8 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti
override fun onPreferenceDataStoreChanged(store: PreferenceDataStore, key: String?) { override fun onPreferenceDataStoreChanged(store: PreferenceDataStore, key: String?) {
when (key) { when (key) {
Key.serviceMode -> handler.post { Key.serviceMode -> handler.post {
connection.disconnect(activity) connection.disconnect(requireContext())
connection.connect(activity, this) connection.connect(requireContext(), this)
} }
} }
} }
...@@ -284,13 +286,13 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti ...@@ -284,13 +286,13 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti
startActivityForResult(intent, requestCode) startActivityForResult(intent, requestCode)
return return
} catch (_: ActivityNotFoundException) { } catch (_: SecurityException) { } } catch (_: ActivityNotFoundException) { } catch (_: SecurityException) { }
Toast.makeText(activity, R.string.file_manager_missing, Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), R.string.file_manager_missing, Toast.LENGTH_SHORT).show()
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) { when (requestCode) {
REQUEST_CONNECT -> if (resultCode == Activity.RESULT_OK) Core.startService() else { REQUEST_CONNECT -> if (resultCode == Activity.RESULT_OK) Core.startService() else {
Toast.makeText(activity, R.string.vpn_permission_denied, Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), R.string.vpn_permission_denied, Toast.LENGTH_SHORT).show()
Crashlytics.log(Log.ERROR, TAG, "Failed to start VpnService from onActivityResult: $data") Crashlytics.log(Log.ERROR, TAG, "Failed to start VpnService from onActivityResult: $data")
} }
REQUEST_IMPORT_PROFILES -> { REQUEST_IMPORT_PROFILES -> {
...@@ -298,8 +300,9 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti ...@@ -298,8 +300,9 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti
val profiles = ProfileManager.getAllProfiles()?.associateBy { it.formattedAddress } val profiles = ProfileManager.getAllProfiles()?.associateBy { it.formattedAddress }
val feature = profiles?.values?.singleOrNull { it.id == DataStore.profileId } val feature = profiles?.values?.singleOrNull { it.id == DataStore.profileId }
val lazyClear = lazy { ProfileManager.clear() } val lazyClear = lazy { ProfileManager.clear() }
val context = requireContext()
for (uri in data!!.datas) try { for (uri in data!!.datas) try {
Profile.parseJson(activity.contentResolver.openInputStream(uri)!!.bufferedReader().readText(), Profile.parseJson(context.contentResolver.openInputStream(uri)!!.bufferedReader().readText(),
feature) { feature) {
lazyClear.value lazyClear.value
// if two profiles has the same address, treat them as the same profile and copy stats over // if two profiles has the same address, treat them as the same profile and copy stats over
...@@ -311,21 +314,22 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti ...@@ -311,21 +314,22 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti
} }
} catch (e: Exception) { } catch (e: Exception) {
printLog(e) printLog(e)
Toast.makeText(activity, e.localizedMessage, Toast.LENGTH_SHORT).show() Toast.makeText(context, e.localizedMessage, Toast.LENGTH_SHORT).show()
} }
populateProfiles() populateProfiles()
} }
REQUEST_EXPORT_PROFILES -> { REQUEST_EXPORT_PROFILES -> {
if (resultCode != Activity.RESULT_OK) return if (resultCode != Activity.RESULT_OK) return
val profiles = ProfileManager.getAllProfiles() val profiles = ProfileManager.getAllProfiles()
val context = requireContext()
if (profiles != null) try { if (profiles != null) try {
val lookup = LongSparseArray<Profile>(profiles.size).apply { profiles.forEach { put(it.id, it) } } val lookup = LongSparseArray<Profile>(profiles.size).apply { profiles.forEach { put(it.id, it) } }
activity.contentResolver.openOutputStream(data?.data!!)!!.bufferedWriter().use { context.contentResolver.openOutputStream(data?.data!!)!!.bufferedWriter().use {
it.write(JSONArray(profiles.map { it.toJson(lookup) }.toTypedArray()).toString(2)) it.write(JSONArray(profiles.map { it.toJson(lookup) }.toTypedArray()).toString(2))
} }
} catch (e: Exception) { } catch (e: Exception) {
printLog(e) printLog(e)
Toast.makeText(activity, e.localizedMessage, Toast.LENGTH_SHORT).show() Toast.makeText(context, e.localizedMessage, Toast.LENGTH_SHORT).show()
} }
} }
else -> super.onActivityResult(requestCode, resultCode, data) else -> super.onActivityResult(requestCode, resultCode, data)
...@@ -335,7 +339,8 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti ...@@ -335,7 +339,8 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
DataStore.publicStore.unregisterChangeListener(this) DataStore.publicStore.unregisterChangeListener(this)
connection.disconnect(activity) val context = requireContext()
BackupManager(activity).dataChanged() connection.disconnect(context)
BackupManager(context).dataChanged()
} }
} }
...@@ -25,22 +25,40 @@ import android.text.format.Formatter ...@@ -25,22 +25,40 @@ import android.text.format.Formatter
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.CompoundButton
import android.widget.TextView import android.widget.TextView
import androidx.leanback.preference.LeanbackListPreferenceDialogFragment import androidx.leanback.preference.LeanbackListPreferenceDialogFragmentCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.shadowsocks.Core import com.github.shadowsocks.Core
import com.github.shadowsocks.database.ProfileManager import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.plugin.PluginConfiguration import com.github.shadowsocks.plugin.PluginConfiguration
import com.github.shadowsocks.preference.DataStore import com.github.shadowsocks.preference.DataStore
class ProfilesDialogFragment : LeanbackListPreferenceDialogFragment() { class ProfilesDialogFragment : LeanbackListPreferenceDialogFragmentCompat() {
inner class ProfilesAdapter : RecyclerView.Adapter<ViewHolder>(), ViewHolder.OnItemClickListener { private inner class ProfileViewHolder(view: View) : RecyclerView.ViewHolder(view), View.OnClickListener {
private val profiles = ProfileManager.getAllProfiles()!! val widgetView = view.findViewById<CompoundButton>(R.id.button)
val titleView = view.findViewById<TextView>(android.R.id.title)
init {
view.findViewById<ViewGroup>(R.id.container).setOnClickListener(this)
}
override fun onClick(v: View) {
val index = adapterPosition
if (index == RecyclerView.NO_POSITION) return
Core.switchProfile(adapter.profiles[index].id)
(targetFragment as MainPreferenceFragment).startService()
fragmentManager?.popBackStack()
adapter.notifyDataSetChanged()
}
}
private inner class ProfilesAdapter : RecyclerView.Adapter<ProfileViewHolder>() {
val profiles = ProfileManager.getAllProfiles()!!
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(LayoutInflater override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ProfileViewHolder(
.from(parent.context).inflate(R.layout.leanback_list_preference_item_single_2, parent, false), this) LayoutInflater.from(parent.context).inflate(R.layout.leanback_list_preference_item_single_2,
parent, false))
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ProfileViewHolder, position: Int) {
val profile = profiles[position] val profile = profiles[position]
holder.widgetView.isChecked = profile.id == DataStore.profileId holder.widgetView.isChecked = profile.id == DataStore.profileId
holder.titleView.text = profile.formattedName holder.titleView.text = profile.formattedName
...@@ -54,24 +72,15 @@ class ProfilesDialogFragment : LeanbackListPreferenceDialogFragment() { ...@@ -54,24 +72,15 @@ class ProfilesDialogFragment : LeanbackListPreferenceDialogFragment() {
} }
override fun getItemCount() = profiles.size override fun getItemCount() = profiles.size
override fun onItemClick(viewHolder: ViewHolder) {
val index = viewHolder.adapterPosition
if (index == RecyclerView.NO_POSITION) return
Core.switchProfile(profiles[index].id)
(targetFragment as MainPreferenceFragment).startService()
fragmentManager?.popBackStack()
notifyDataSetChanged()
} }
val selectedIndex = profiles.indexOfFirst { it.id == DataStore.profileId } private val adapter = ProfilesAdapter()
}
override fun onCreateAdapter() = ProfilesAdapter() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View {
return super.onCreateView(inflater, container, savedInstanceState)!!.also { return super.onCreateView(inflater, container, savedInstanceState)!!.also {
val list = it.findViewById<RecyclerView>(android.R.id.list) val list = it.findViewById<RecyclerView>(android.R.id.list)
list.layoutManager!!.scrollToPosition((list.adapter as ProfilesAdapter).selectedIndex) list.adapter = adapter
list.layoutManager!!.scrollToPosition(adapter.profiles.indexOfFirst { it.id == DataStore.profileId })
} }
} }
} }
...@@ -24,21 +24,21 @@ import android.os.Bundle ...@@ -24,21 +24,21 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.leanback.preference.LeanbackListPreferenceDialogFragment import androidx.leanback.preference.LeanbackListPreferenceDialogFragmentCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
/** /**
* Fix: scroll to selected item. * Fix: scroll to selected item.
*/ */
open class LeanbackSingleListPreferenceDialogFragment : LeanbackListPreferenceDialogFragment() { open class LeanbackSingleListPreferenceDialogFragment : LeanbackListPreferenceDialogFragmentCompat() {
companion object { companion object {
private val mEntryValues = LeanbackListPreferenceDialogFragment::class.java private val mEntryValues = LeanbackListPreferenceDialogFragmentCompat::class.java
.getDeclaredField("mEntryValues").apply { isAccessible = true } .getDeclaredField("mEntryValues").apply { isAccessible = true }
private val mInitialSelection = LeanbackListPreferenceDialogFragment::class.java private val mInitialSelection = LeanbackListPreferenceDialogFragmentCompat::class.java
.getDeclaredField("mInitialSelection").apply { isAccessible = true } .getDeclaredField("mInitialSelection").apply { isAccessible = true }
} }
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val selected = mInitialSelection.get(this) as? String val selected = mInitialSelection.get(this) as? String
val index = (mEntryValues.get(this) as? Array<CharSequence?>)?.indexOfFirst { it == selected } val index = (mEntryValues.get(this) as? Array<CharSequence?>)?.indexOfFirst { it == selected }
return super.onCreateView(inflater, container, savedInstanceState)!!.also { return super.onCreateView(inflater, container, savedInstanceState)!!.also {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment