* Add support for TCP Fast Open * Remove useless echo done line * Check return values before proceeding in TcpFastOpen.enabled
241 lines
9.2 KiB
Scala
241 lines
9.2 KiB
Scala
package com.github.shadowsocks
|
|
|
|
import java.util.Locale
|
|
|
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
|
import android.content.{Intent, SharedPreferences}
|
|
import android.net.Uri
|
|
import android.os.Bundle
|
|
import android.preference.{Preference, PreferenceFragment, SwitchPreference}
|
|
import android.support.v7.app.AlertDialog
|
|
import android.webkit.{WebView, WebViewClient}
|
|
import com.github.shadowsocks.ShadowsocksApplication.app
|
|
import com.github.shadowsocks.database.Profile
|
|
import com.github.shadowsocks.preferences._
|
|
import com.github.shadowsocks.utils.{Key, TcpFastOpen, Utils}
|
|
|
|
object ShadowsocksSettings {
|
|
// Constants
|
|
private final val TAG = "ShadowsocksSettings"
|
|
private val PROXY_PREFS = Array(Key.name, Key.host, Key.remotePort, Key.localPort, Key.password, Key.method,
|
|
Key.auth, Key.kcp, Key.kcpPort, Key.kcpcli)
|
|
private val FEATURE_PREFS = Array(Key.route, Key.proxyApps, Key.udpdns, Key.ipv6)
|
|
|
|
// Helper functions
|
|
def updateDropDownPreference(pref: Preference, value: String) {
|
|
pref.asInstanceOf[DropDownPreference].setValue(value)
|
|
}
|
|
|
|
def updatePasswordEditTextPreference(pref: Preference, value: String) {
|
|
pref.setSummary(value)
|
|
pref.asInstanceOf[PasswordEditTextPreference].setText(value)
|
|
}
|
|
|
|
def updateNumberPickerPreference(pref: Preference, value: Int) {
|
|
pref.asInstanceOf[NumberPickerPreference].setValue(value)
|
|
}
|
|
|
|
def updateSummaryEditTextPreference(pref: Preference, value: String) {
|
|
pref.setSummary(value)
|
|
pref.asInstanceOf[SummaryEditTextPreference].setText(value)
|
|
}
|
|
|
|
def updateSwitchPreference(pref: Preference, value: Boolean) {
|
|
pref.asInstanceOf[SwitchPreference].setChecked(value)
|
|
}
|
|
|
|
def updatePreference(pref: Preference, name: String, profile: Profile) {
|
|
name match {
|
|
case Key.name => updateSummaryEditTextPreference(pref, profile.name)
|
|
case Key.host => updateSummaryEditTextPreference(pref, profile.host)
|
|
case Key.remotePort => updateNumberPickerPreference(pref, profile.remotePort)
|
|
case Key.localPort => updateNumberPickerPreference(pref, profile.localPort)
|
|
case Key.password => updatePasswordEditTextPreference(pref, profile.password)
|
|
case Key.method => updateDropDownPreference(pref, profile.method)
|
|
case Key.route => updateDropDownPreference(pref, profile.route)
|
|
case Key.proxyApps => updateSwitchPreference(pref, profile.proxyApps)
|
|
case Key.udpdns => updateSwitchPreference(pref, profile.udpdns)
|
|
case Key.auth => updateSwitchPreference(pref, profile.auth)
|
|
case Key.ipv6 => updateSwitchPreference(pref, profile.ipv6)
|
|
case Key.kcp => updateSwitchPreference(pref, profile.kcp)
|
|
case Key.kcpPort => updateNumberPickerPreference(pref, profile.kcpPort)
|
|
case Key.kcpcli => updateSummaryEditTextPreference(pref, profile.kcpcli)
|
|
}
|
|
}
|
|
}
|
|
|
|
class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChangeListener {
|
|
import ShadowsocksSettings._
|
|
|
|
private def activity = getActivity.asInstanceOf[Shadowsocks]
|
|
lazy val natSwitch = findPreference(Key.isNAT).asInstanceOf[SwitchPreference]
|
|
|
|
private var isProxyApps: SwitchPreference = _
|
|
|
|
override def onCreate(savedInstanceState: Bundle) {
|
|
super.onCreate(savedInstanceState)
|
|
addPreferencesFromResource(R.xml.pref_all)
|
|
getPreferenceManager.getSharedPreferences.registerOnSharedPreferenceChangeListener(this)
|
|
|
|
findPreference(Key.name).setOnPreferenceChangeListener((_, value) => {
|
|
profile.name = value.asInstanceOf[String]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
findPreference(Key.host).setOnPreferenceChangeListener((_, value) => {
|
|
profile.host = value.asInstanceOf[String]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
findPreference(Key.remotePort).setOnPreferenceChangeListener((_, value) => {
|
|
profile.remotePort = value.asInstanceOf[Int]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
findPreference(Key.localPort).setOnPreferenceChangeListener((_, value) => {
|
|
profile.localPort = value.asInstanceOf[Int]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
findPreference(Key.password).setOnPreferenceChangeListener((_, value) => {
|
|
profile.password = value.asInstanceOf[String]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
findPreference(Key.method).setOnPreferenceChangeListener((_, value) => {
|
|
profile.method = value.asInstanceOf[String]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
findPreference(Key.route).setOnPreferenceChangeListener((_, value) => {
|
|
profile.route = value.asInstanceOf[String]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
|
|
findPreference(Key.kcp).setOnPreferenceChangeListener((_, value) => {
|
|
profile.kcp = value.asInstanceOf[Boolean]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
findPreference(Key.kcpPort).setOnPreferenceChangeListener((_, value) => {
|
|
profile.kcpPort = value.asInstanceOf[Int]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
findPreference(Key.kcpcli).setOnPreferenceChangeListener((_, value) => {
|
|
profile.kcpcli = value.asInstanceOf[String]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
|
|
isProxyApps = findPreference(Key.proxyApps).asInstanceOf[SwitchPreference]
|
|
isProxyApps.setOnPreferenceClickListener(_ => {
|
|
startActivity(new Intent(activity, classOf[AppManager]))
|
|
isProxyApps.setChecked(true)
|
|
false
|
|
})
|
|
isProxyApps.setOnPreferenceChangeListener((_, value) => {
|
|
profile.proxyApps = value.asInstanceOf[Boolean]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
|
|
findPreference(Key.udpdns).setOnPreferenceChangeListener((_, value) => {
|
|
profile.udpdns = value.asInstanceOf[Boolean]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
findPreference(Key.auth).setOnPreferenceChangeListener((_, value) => {
|
|
profile.auth = value.asInstanceOf[Boolean]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
findPreference(Key.ipv6).setOnPreferenceChangeListener((_, value) => {
|
|
profile.ipv6 = value.asInstanceOf[Boolean]
|
|
app.profileManager.updateProfile(profile)
|
|
})
|
|
|
|
val switch = findPreference(Key.isAutoConnect).asInstanceOf[SwitchPreference]
|
|
switch.setOnPreferenceChangeListener((_, value) => {
|
|
BootReceiver.setEnabled(activity, value.asInstanceOf[Boolean])
|
|
true
|
|
})
|
|
if (getPreferenceManager.getSharedPreferences.getBoolean(Key.isAutoConnect, false)) {
|
|
BootReceiver.setEnabled(activity, true)
|
|
getPreferenceManager.getSharedPreferences.edit.remove(Key.isAutoConnect).apply
|
|
}
|
|
switch.setChecked(BootReceiver.getEnabled(activity))
|
|
|
|
val tfo = findPreference("tcp_fastopen").asInstanceOf[SwitchPreference]
|
|
tfo.setChecked(TcpFastOpen.sendEnabled)
|
|
tfo.setOnPreferenceChangeListener((_, v) => {
|
|
val value = v.asInstanceOf[Boolean]
|
|
TcpFastOpen.enabled(value)
|
|
value == TcpFastOpen.sendEnabled
|
|
})
|
|
if (!TcpFastOpen.supported) {
|
|
tfo.setEnabled(false)
|
|
tfo.setSummary(getString(R.string.tcp_fastopen_summary_unsupported, java.lang.System.getProperty("os.version")))
|
|
}
|
|
|
|
findPreference("recovery").setOnPreferenceClickListener((preference: Preference) => {
|
|
app.track(TAG, "reset")
|
|
activity.recovery()
|
|
true
|
|
})
|
|
|
|
findPreference("flush_dnscache").setOnPreferenceClickListener(_ => {
|
|
app.track(TAG, "flush_dnscache")
|
|
activity.flushDnsCache()
|
|
true
|
|
})
|
|
|
|
findPreference("about").setOnPreferenceClickListener((preference: Preference) => {
|
|
app.track(TAG, "about")
|
|
val web = new WebView(activity)
|
|
web.loadUrl("file:///android_asset/pages/about.html")
|
|
web.setWebViewClient(new WebViewClient() {
|
|
override def shouldOverrideUrlLoading(view: WebView, url: String): Boolean = {
|
|
try {
|
|
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)))
|
|
} catch {
|
|
case _: android.content.ActivityNotFoundException => // Ignore
|
|
}
|
|
true
|
|
}
|
|
})
|
|
|
|
new AlertDialog.Builder(activity)
|
|
.setTitle(getString(R.string.about_title).formatLocal(Locale.ENGLISH, app.getVersionName))
|
|
.setNegativeButton(getString(android.R.string.ok), null)
|
|
.setView(web)
|
|
.create()
|
|
.show()
|
|
true
|
|
})
|
|
}
|
|
|
|
def refreshProfile() {
|
|
profile = app.currentProfile.get
|
|
isProxyApps.setChecked(profile.proxyApps)
|
|
}
|
|
|
|
override def onDestroy {
|
|
super.onDestroy()
|
|
app.settings.unregisterOnSharedPreferenceChangeListener(this)
|
|
}
|
|
|
|
def onSharedPreferenceChanged(pref: SharedPreferences, key: String) = key match {
|
|
case Key.isNAT =>
|
|
activity.handler.post(() => {
|
|
activity.detachService
|
|
activity.attachService
|
|
})
|
|
case _ =>
|
|
}
|
|
|
|
private var enabled = true
|
|
def setEnabled(enabled: Boolean) {
|
|
this.enabled = enabled
|
|
for (name <- Key.isNAT #:: PROXY_PREFS.toStream #::: FEATURE_PREFS.toStream) {
|
|
val pref = findPreference(name)
|
|
if (pref != null) pref.setEnabled(enabled &&
|
|
(name != Key.proxyApps || Utils.isLollipopOrAbove || app.isNatEnabled))
|
|
}
|
|
}
|
|
|
|
var profile: Profile = _
|
|
def setProfile(profile: Profile) {
|
|
this.profile = profile
|
|
for (name <- Array(PROXY_PREFS, FEATURE_PREFS).flatten) updatePreference(findPreference(name), name, profile)
|
|
}
|
|
}
|