____ _ _______ __
/ __ \ | /| / / __/ |/ /
/ /_/ / |/ |/ / _// /
\____/|__/|__/___/_||_/
owenclave / app/src/main/java/com/github/shadowsocks/plugin/v2ray/ConfigFragment.kt
/*******************************************************************************
* *
* Copyright (C) 2019 by Max Lv *
* Copyright (C) 2019 by Mygod Studio *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see . *
* *
*******************************************************************************/
package com.github.shadowsocks.plugin.v2ray
import android.os.Bundle
import android.text.InputFilter
import android.text.InputType
import android.view.View
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.preference.EditTextPreference
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.github.shadowsocks.plugin.PluginOptions
import io.nekohasekai.sagernet.R
class ConfigFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChangeListener {
private val mode by lazy { findPreference("mode")!! }
private val host by lazy { findPreference("host")!! }
private val path by lazy { findPreference("path")!! }
private val mux by lazy { findPreference("mux")!! }
private val certRaw by lazy { findPreference("certRaw")!! }
private val loglevel by lazy { findPreference("loglevel")!! }
private fun readMode(value: String = mode.value) = when (value) {
"websocket-http" -> Pair(null, false)
"websocket-tls" -> Pair(null, true)
"quic-tls" -> Pair("quic", false)
else -> {
check(false)
Pair(null, false)
}
}
val options get() = PluginOptions().apply {
val (mode, tls) = readMode()
putWithDefault("mode", mode)
if (tls) this["tls"] = null
putWithDefault("host", host.text, "cloudfront.com")
putWithDefault("path", path.text, "/")
putWithDefault("mux", mux.text, "1")
putWithDefault("certRaw", certRaw.text?.replace("\n", ""), "")
putWithDefault("loglevel", loglevel.value, "warning")
}
fun onInitializePluginOptions(options: PluginOptions) {
mode.value = when (options["mode"] ?: "websocket") {
"quic" -> "quic-tls"
"websocket" if "tls" in options -> "websocket-tls"
else -> "websocket-http"
}.also { onModeChange(it) }
host.text = options["host"] ?: "cloudfront.com"
path.text = options["path"] ?: "/"
mux.text = options["mux"] ?: "1"
certRaw.text = options["certRaw"]
loglevel.value = options["loglevel"] ?: "warning"
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.v2ray_plugin_config)
mode.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { preference, newValue ->
onModeChange(newValue as String)
if ((preference as ListPreference).value != newValue) {
(requireActivity() as? ConfigActivity)?.let {
it.dirty = true
it.onBackPressedCallback.isEnabled = true
}
}
true
}
host.setOnBindEditTextListener {
it.inputType = InputType.TYPE_TEXT_VARIATION_URI
it.setSelection(it.text.length)
}
host.onPreferenceChangeListener = this
path.setOnBindEditTextListener {
it.inputType = InputType.TYPE_TEXT_VARIATION_URI
it.setSelection(it.text.length)
}
path.onPreferenceChangeListener = this
mux.setOnBindEditTextListener {
it.inputType = InputType.TYPE_CLASS_NUMBER
it.filters = arrayOf(InputFilter.LengthFilter(4))
it.setSelection(it.text.length)
}
mux.onPreferenceChangeListener = this
certRaw.setOnBindEditTextListener {
it.setSelection(it.text.length)
}
certRaw.onPreferenceChangeListener = this
loglevel.onPreferenceChangeListener = this
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
ViewCompat.setOnApplyWindowInsetsListener(listView) { v, insets ->
val bars = insets.getInsets(
WindowInsetsCompat.Type.systemBars()
or WindowInsetsCompat.Type.displayCutout()
)
v.updatePadding(
left = bars.left,
right = bars.right,
bottom = bars.bottom,
)
insets
}
}
private fun onModeChange(modeValue: String) {
val (mode, tls) = readMode(modeValue)
path.isEnabled = mode == null
mux.isEnabled = mode == null
certRaw.isEnabled = (mode == null && tls) || (mode == "quic")
}
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
val oldValue = when (preference) {
is EditTextPreference -> preference.text
is ListPreference -> preference.value
else -> null
}
if (oldValue != newValue) {
(requireActivity() as? ConfigActivity)?.let {
it.dirty = true
it.onBackPressedCallback.isEnabled = true
}
}
return true
}
}