mirror of
https://github.com/MatsuriDayo/NekoBoxForAndroid.git
synced 2025-12-19 14:40:06 +08:00
parent
c286ec35f6
commit
a5cf5b8890
@ -0,0 +1,360 @@
|
|||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 3,
|
||||||
|
"identityHash": "cff00d0142d9e53d2ca24a6a55cd213c",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "proxy_groups",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `userOrder` INTEGER NOT NULL, `ungrouped` INTEGER NOT NULL, `name` TEXT, `type` INTEGER NOT NULL, `subscription` BLOB, `order` INTEGER NOT NULL, `isSelector` INTEGER NOT NULL, `frontProxy` INTEGER NOT NULL, `landingProxy` INTEGER NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "userOrder",
|
||||||
|
"columnName": "userOrder",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "ungrouped",
|
||||||
|
"columnName": "ungrouped",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "subscription",
|
||||||
|
"columnName": "subscription",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "order",
|
||||||
|
"columnName": "order",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "isSelector",
|
||||||
|
"columnName": "isSelector",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "frontProxy",
|
||||||
|
"columnName": "frontProxy",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "landingProxy",
|
||||||
|
"columnName": "landingProxy",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "proxy_entities",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `groupId` INTEGER NOT NULL, `type` INTEGER NOT NULL, `userOrder` INTEGER NOT NULL, `tx` INTEGER NOT NULL, `rx` INTEGER NOT NULL, `status` INTEGER NOT NULL, `ping` INTEGER NOT NULL, `uuid` TEXT NOT NULL, `error` TEXT, `socksBean` BLOB, `httpBean` BLOB, `ssBean` BLOB, `vmessBean` BLOB, `trojanBean` BLOB, `trojanGoBean` BLOB, `mieruBean` BLOB, `naiveBean` BLOB, `hysteriaBean` BLOB, `tuicBean` BLOB, `sshBean` BLOB, `wgBean` BLOB, `shadowTLSBean` BLOB, `chainBean` BLOB, `nekoBean` BLOB, `configBean` BLOB)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "groupId",
|
||||||
|
"columnName": "groupId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "type",
|
||||||
|
"columnName": "type",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "userOrder",
|
||||||
|
"columnName": "userOrder",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "tx",
|
||||||
|
"columnName": "tx",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "rx",
|
||||||
|
"columnName": "rx",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "status",
|
||||||
|
"columnName": "status",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "ping",
|
||||||
|
"columnName": "ping",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uuid",
|
||||||
|
"columnName": "uuid",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "error",
|
||||||
|
"columnName": "error",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "socksBean",
|
||||||
|
"columnName": "socksBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "httpBean",
|
||||||
|
"columnName": "httpBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "ssBean",
|
||||||
|
"columnName": "ssBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "vmessBean",
|
||||||
|
"columnName": "vmessBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "trojanBean",
|
||||||
|
"columnName": "trojanBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "trojanGoBean",
|
||||||
|
"columnName": "trojanGoBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "mieruBean",
|
||||||
|
"columnName": "mieruBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "naiveBean",
|
||||||
|
"columnName": "naiveBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "hysteriaBean",
|
||||||
|
"columnName": "hysteriaBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "tuicBean",
|
||||||
|
"columnName": "tuicBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "sshBean",
|
||||||
|
"columnName": "sshBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "wgBean",
|
||||||
|
"columnName": "wgBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "shadowTLSBean",
|
||||||
|
"columnName": "shadowTLSBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "chainBean",
|
||||||
|
"columnName": "chainBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "nekoBean",
|
||||||
|
"columnName": "nekoBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "configBean",
|
||||||
|
"columnName": "configBean",
|
||||||
|
"affinity": "BLOB",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "groupId",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"groupId"
|
||||||
|
],
|
||||||
|
"orders": [],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `groupId` ON `${TABLE_NAME}` (`groupId`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "rules",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `userOrder` INTEGER NOT NULL, `enabled` INTEGER NOT NULL, `domains` TEXT NOT NULL, `ip` TEXT NOT NULL, `port` TEXT NOT NULL, `sourcePort` TEXT NOT NULL, `network` TEXT NOT NULL, `source` TEXT NOT NULL, `protocol` TEXT NOT NULL, `outbound` INTEGER NOT NULL, `packages` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "userOrder",
|
||||||
|
"columnName": "userOrder",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "enabled",
|
||||||
|
"columnName": "enabled",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "domains",
|
||||||
|
"columnName": "domains",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "ip",
|
||||||
|
"columnName": "ip",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "port",
|
||||||
|
"columnName": "port",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "sourcePort",
|
||||||
|
"columnName": "sourcePort",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "network",
|
||||||
|
"columnName": "network",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "source",
|
||||||
|
"columnName": "source",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "protocol",
|
||||||
|
"columnName": "protocol",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "outbound",
|
||||||
|
"columnName": "outbound",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "packages",
|
||||||
|
"columnName": "packages",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"views": [],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'cff00d0142d9e53d2ca24a6a55cd213c')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -164,6 +164,9 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name="io.nekohasekai.sagernet.ui.profile.TrojanGoSettingsActivity"
|
android:name="io.nekohasekai.sagernet.ui.profile.TrojanGoSettingsActivity"
|
||||||
android:configChanges="uiMode" />
|
android:configChanges="uiMode" />
|
||||||
|
<activity
|
||||||
|
android:name="io.nekohasekai.sagernet.ui.profile.MieruSettingsActivity"
|
||||||
|
android:configChanges="uiMode" />
|
||||||
<activity
|
<activity
|
||||||
android:name="io.nekohasekai.sagernet.ui.profile.NaiveSettingsActivity"
|
android:name="io.nekohasekai.sagernet.ui.profile.NaiveSettingsActivity"
|
||||||
android:configChanges="uiMode" />
|
android:configChanges="uiMode" />
|
||||||
|
|||||||
@ -10,6 +10,8 @@ import io.nekohasekai.sagernet.fmt.ConfigBuildResult
|
|||||||
import io.nekohasekai.sagernet.fmt.buildConfig
|
import io.nekohasekai.sagernet.fmt.buildConfig
|
||||||
import io.nekohasekai.sagernet.fmt.hysteria.HysteriaBean
|
import io.nekohasekai.sagernet.fmt.hysteria.HysteriaBean
|
||||||
import io.nekohasekai.sagernet.fmt.hysteria.buildHysteria1Config
|
import io.nekohasekai.sagernet.fmt.hysteria.buildHysteria1Config
|
||||||
|
import io.nekohasekai.sagernet.fmt.mieru.MieruBean
|
||||||
|
import io.nekohasekai.sagernet.fmt.mieru.buildMieruConfig
|
||||||
import io.nekohasekai.sagernet.fmt.naive.NaiveBean
|
import io.nekohasekai.sagernet.fmt.naive.NaiveBean
|
||||||
import io.nekohasekai.sagernet.fmt.naive.buildNaiveConfig
|
import io.nekohasekai.sagernet.fmt.naive.buildNaiveConfig
|
||||||
import io.nekohasekai.sagernet.fmt.trojan_go.TrojanGoBean
|
import io.nekohasekai.sagernet.fmt.trojan_go.TrojanGoBean
|
||||||
@ -65,6 +67,11 @@ abstract class BoxInstance(
|
|||||||
pluginConfigs[port] = profile.type to bean.buildTrojanGoConfig(port)
|
pluginConfigs[port] = profile.type to bean.buildTrojanGoConfig(port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is MieruBean -> {
|
||||||
|
initPlugin("mieru-plugin")
|
||||||
|
pluginConfigs[port] = profile.type to bean.buildMieruConfig(port)
|
||||||
|
}
|
||||||
|
|
||||||
is NaiveBean -> {
|
is NaiveBean -> {
|
||||||
initPlugin("naive-plugin")
|
initPlugin("naive-plugin")
|
||||||
pluginConfigs[port] = profile.type to bean.buildNaiveConfig(port)
|
pluginConfigs[port] = profile.type to bean.buildNaiveConfig(port)
|
||||||
@ -129,6 +136,25 @@ abstract class BoxInstance(
|
|||||||
processes.start(commands)
|
processes.start(commands)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bean is MieruBean -> {
|
||||||
|
val configFile = File(
|
||||||
|
cacheDir, "mieru_" + SystemClock.elapsedRealtime() + ".json"
|
||||||
|
)
|
||||||
|
|
||||||
|
configFile.parentFile?.mkdirs()
|
||||||
|
configFile.writeText(config)
|
||||||
|
cacheFiles.add(configFile)
|
||||||
|
|
||||||
|
val envMap = mutableMapOf<String, String>()
|
||||||
|
envMap["MIERU_CONFIG_JSON_FILE"] = configFile.absolutePath
|
||||||
|
|
||||||
|
val commands = mutableListOf(
|
||||||
|
initPlugin("mieru-plugin").path, "run",
|
||||||
|
)
|
||||||
|
|
||||||
|
processes.start(commands, envMap)
|
||||||
|
}
|
||||||
|
|
||||||
bean is NaiveBean -> {
|
bean is NaiveBean -> {
|
||||||
val configFile = File(
|
val configFile = File(
|
||||||
cacheDir, "naive_" + SystemClock.elapsedRealtime() + ".json"
|
cacheDir, "naive_" + SystemClock.elapsedRealtime() + ".json"
|
||||||
|
|||||||
@ -11,6 +11,8 @@ import io.nekohasekai.sagernet.fmt.http.HttpBean
|
|||||||
import io.nekohasekai.sagernet.fmt.http.toUri
|
import io.nekohasekai.sagernet.fmt.http.toUri
|
||||||
import io.nekohasekai.sagernet.fmt.hysteria.*
|
import io.nekohasekai.sagernet.fmt.hysteria.*
|
||||||
import io.nekohasekai.sagernet.fmt.internal.ChainBean
|
import io.nekohasekai.sagernet.fmt.internal.ChainBean
|
||||||
|
import io.nekohasekai.sagernet.fmt.mieru.MieruBean
|
||||||
|
import io.nekohasekai.sagernet.fmt.mieru.buildMieruConfig
|
||||||
import io.nekohasekai.sagernet.fmt.naive.NaiveBean
|
import io.nekohasekai.sagernet.fmt.naive.NaiveBean
|
||||||
import io.nekohasekai.sagernet.fmt.naive.buildNaiveConfig
|
import io.nekohasekai.sagernet.fmt.naive.buildNaiveConfig
|
||||||
import io.nekohasekai.sagernet.fmt.naive.toUri
|
import io.nekohasekai.sagernet.fmt.naive.toUri
|
||||||
@ -56,6 +58,7 @@ data class ProxyEntity(
|
|||||||
var vmessBean: VMessBean? = null,
|
var vmessBean: VMessBean? = null,
|
||||||
var trojanBean: TrojanBean? = null,
|
var trojanBean: TrojanBean? = null,
|
||||||
var trojanGoBean: TrojanGoBean? = null,
|
var trojanGoBean: TrojanGoBean? = null,
|
||||||
|
var mieruBean: MieruBean? = null,
|
||||||
var naiveBean: NaiveBean? = null,
|
var naiveBean: NaiveBean? = null,
|
||||||
var hysteriaBean: HysteriaBean? = null,
|
var hysteriaBean: HysteriaBean? = null,
|
||||||
var tuicBean: TuicBean? = null,
|
var tuicBean: TuicBean? = null,
|
||||||
@ -75,6 +78,7 @@ data class ProxyEntity(
|
|||||||
const val TYPE_TROJAN = 6
|
const val TYPE_TROJAN = 6
|
||||||
|
|
||||||
const val TYPE_TROJAN_GO = 7
|
const val TYPE_TROJAN_GO = 7
|
||||||
|
const val TYPE_MIERU = 21
|
||||||
const val TYPE_NAIVE = 9
|
const val TYPE_NAIVE = 9
|
||||||
const val TYPE_HYSTERIA = 15
|
const val TYPE_HYSTERIA = 15
|
||||||
const val TYPE_TUIC = 20
|
const val TYPE_TUIC = 20
|
||||||
@ -161,6 +165,7 @@ data class ProxyEntity(
|
|||||||
TYPE_VMESS -> vmessBean = KryoConverters.vmessDeserialize(byteArray)
|
TYPE_VMESS -> vmessBean = KryoConverters.vmessDeserialize(byteArray)
|
||||||
TYPE_TROJAN -> trojanBean = KryoConverters.trojanDeserialize(byteArray)
|
TYPE_TROJAN -> trojanBean = KryoConverters.trojanDeserialize(byteArray)
|
||||||
TYPE_TROJAN_GO -> trojanGoBean = KryoConverters.trojanGoDeserialize(byteArray)
|
TYPE_TROJAN_GO -> trojanGoBean = KryoConverters.trojanGoDeserialize(byteArray)
|
||||||
|
TYPE_MIERU -> mieruBean = KryoConverters.mieruDeserialize(byteArray)
|
||||||
TYPE_NAIVE -> naiveBean = KryoConverters.naiveDeserialize(byteArray)
|
TYPE_NAIVE -> naiveBean = KryoConverters.naiveDeserialize(byteArray)
|
||||||
TYPE_HYSTERIA -> hysteriaBean = KryoConverters.hysteriaDeserialize(byteArray)
|
TYPE_HYSTERIA -> hysteriaBean = KryoConverters.hysteriaDeserialize(byteArray)
|
||||||
TYPE_SSH -> sshBean = KryoConverters.sshDeserialize(byteArray)
|
TYPE_SSH -> sshBean = KryoConverters.sshDeserialize(byteArray)
|
||||||
@ -180,6 +185,7 @@ data class ProxyEntity(
|
|||||||
TYPE_VMESS -> if (vmessBean!!.isVLESS) "VLESS" else "VMess"
|
TYPE_VMESS -> if (vmessBean!!.isVLESS) "VLESS" else "VMess"
|
||||||
TYPE_TROJAN -> "Trojan"
|
TYPE_TROJAN -> "Trojan"
|
||||||
TYPE_TROJAN_GO -> "Trojan-Go"
|
TYPE_TROJAN_GO -> "Trojan-Go"
|
||||||
|
TYPE_MIERU -> "Mieru"
|
||||||
TYPE_NAIVE -> "Naïve"
|
TYPE_NAIVE -> "Naïve"
|
||||||
TYPE_HYSTERIA -> "Hysteria" + hysteriaBean!!.protocolVersion
|
TYPE_HYSTERIA -> "Hysteria" + hysteriaBean!!.protocolVersion
|
||||||
TYPE_SSH -> "SSH"
|
TYPE_SSH -> "SSH"
|
||||||
@ -203,6 +209,7 @@ data class ProxyEntity(
|
|||||||
TYPE_VMESS -> vmessBean
|
TYPE_VMESS -> vmessBean
|
||||||
TYPE_TROJAN -> trojanBean
|
TYPE_TROJAN -> trojanBean
|
||||||
TYPE_TROJAN_GO -> trojanGoBean
|
TYPE_TROJAN_GO -> trojanGoBean
|
||||||
|
TYPE_MIERU -> mieruBean
|
||||||
TYPE_NAIVE -> naiveBean
|
TYPE_NAIVE -> naiveBean
|
||||||
TYPE_HYSTERIA -> hysteriaBean
|
TYPE_HYSTERIA -> hysteriaBean
|
||||||
TYPE_SSH -> sshBean
|
TYPE_SSH -> sshBean
|
||||||
@ -270,6 +277,11 @@ data class ProxyEntity(
|
|||||||
append(bean.buildTrojanGoConfig(port))
|
append(bean.buildTrojanGoConfig(port))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is MieruBean -> {
|
||||||
|
append("\n\n")
|
||||||
|
append(bean.buildMieruConfig(port))
|
||||||
|
}
|
||||||
|
|
||||||
is NaiveBean -> {
|
is NaiveBean -> {
|
||||||
append("\n\n")
|
append("\n\n")
|
||||||
append(bean.buildNaiveConfig(port))
|
append(bean.buildNaiveConfig(port))
|
||||||
@ -289,6 +301,7 @@ data class ProxyEntity(
|
|||||||
fun needExternal(): Boolean {
|
fun needExternal(): Boolean {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
TYPE_TROJAN_GO -> true
|
TYPE_TROJAN_GO -> true
|
||||||
|
TYPE_MIERU -> true
|
||||||
TYPE_NAIVE -> true
|
TYPE_NAIVE -> true
|
||||||
TYPE_HYSTERIA -> !hysteriaBean!!.canUseSingBox()
|
TYPE_HYSTERIA -> !hysteriaBean!!.canUseSingBox()
|
||||||
TYPE_NEKO -> true
|
TYPE_NEKO -> true
|
||||||
@ -319,6 +332,7 @@ data class ProxyEntity(
|
|||||||
vmessBean = null
|
vmessBean = null
|
||||||
trojanBean = null
|
trojanBean = null
|
||||||
trojanGoBean = null
|
trojanGoBean = null
|
||||||
|
mieruBean = null
|
||||||
naiveBean = null
|
naiveBean = null
|
||||||
hysteriaBean = null
|
hysteriaBean = null
|
||||||
sshBean = null
|
sshBean = null
|
||||||
@ -360,6 +374,11 @@ data class ProxyEntity(
|
|||||||
trojanGoBean = bean
|
trojanGoBean = bean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is MieruBean -> {
|
||||||
|
type = TYPE_MIERU
|
||||||
|
mieruBean = bean
|
||||||
|
}
|
||||||
|
|
||||||
is NaiveBean -> {
|
is NaiveBean -> {
|
||||||
type = TYPE_NAIVE
|
type = TYPE_NAIVE
|
||||||
naiveBean = bean
|
naiveBean = bean
|
||||||
@ -419,6 +438,7 @@ data class ProxyEntity(
|
|||||||
TYPE_VMESS -> VMessSettingsActivity::class.java
|
TYPE_VMESS -> VMessSettingsActivity::class.java
|
||||||
TYPE_TROJAN -> TrojanSettingsActivity::class.java
|
TYPE_TROJAN -> TrojanSettingsActivity::class.java
|
||||||
TYPE_TROJAN_GO -> TrojanGoSettingsActivity::class.java
|
TYPE_TROJAN_GO -> TrojanGoSettingsActivity::class.java
|
||||||
|
TYPE_MIERU -> MieruSettingsActivity::class.java
|
||||||
TYPE_NAIVE -> NaiveSettingsActivity::class.java
|
TYPE_NAIVE -> NaiveSettingsActivity::class.java
|
||||||
TYPE_HYSTERIA -> HysteriaSettingsActivity::class.java
|
TYPE_HYSTERIA -> HysteriaSettingsActivity::class.java
|
||||||
TYPE_SSH -> SSHSettingsActivity::class.java
|
TYPE_SSH -> SSHSettingsActivity::class.java
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import kotlinx.coroutines.launch
|
|||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
entities = [ProxyGroup::class, ProxyEntity::class, RuleEntity::class],
|
entities = [ProxyGroup::class, ProxyEntity::class, RuleEntity::class],
|
||||||
version = 2
|
version = 3
|
||||||
)
|
)
|
||||||
@TypeConverters(value = [KryoConverters::class, GsonConverters::class])
|
@TypeConverters(value = [KryoConverters::class, GsonConverters::class])
|
||||||
@GenerateRoomMigrations
|
@GenerateRoomMigrations
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import io.nekohasekai.sagernet.database.SubscriptionBean;
|
|||||||
import io.nekohasekai.sagernet.fmt.http.HttpBean;
|
import io.nekohasekai.sagernet.fmt.http.HttpBean;
|
||||||
import io.nekohasekai.sagernet.fmt.hysteria.HysteriaBean;
|
import io.nekohasekai.sagernet.fmt.hysteria.HysteriaBean;
|
||||||
import io.nekohasekai.sagernet.fmt.internal.ChainBean;
|
import io.nekohasekai.sagernet.fmt.internal.ChainBean;
|
||||||
|
import io.nekohasekai.sagernet.fmt.mieru.MieruBean;
|
||||||
import io.nekohasekai.sagernet.fmt.naive.NaiveBean;
|
import io.nekohasekai.sagernet.fmt.naive.NaiveBean;
|
||||||
import io.nekohasekai.sagernet.fmt.shadowsocks.ShadowsocksBean;
|
import io.nekohasekai.sagernet.fmt.shadowsocks.ShadowsocksBean;
|
||||||
import moe.matsuri.nb4a.proxy.shadowtls.ShadowTLSBean;
|
import moe.matsuri.nb4a.proxy.shadowtls.ShadowTLSBean;
|
||||||
@ -99,6 +100,12 @@ public class KryoConverters {
|
|||||||
return deserialize(new TrojanGoBean(), bytes);
|
return deserialize(new TrojanGoBean(), bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
public static MieruBean mieruDeserialize(byte[] bytes) {
|
||||||
|
if (JavaUtil.isEmpty(bytes)) return null;
|
||||||
|
return deserialize(new MieruBean(), bytes);
|
||||||
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
public static NaiveBean naiveDeserialize(byte[] bytes) {
|
public static NaiveBean naiveDeserialize(byte[] bytes) {
|
||||||
if (JavaUtil.isEmpty(bytes)) return null;
|
if (JavaUtil.isEmpty(bytes)) return null;
|
||||||
|
|||||||
@ -14,6 +14,16 @@ enum class PluginEntry(
|
|||||||
SagerNet.application.getString(R.string.action_trojan_go),
|
SagerNet.application.getString(R.string.action_trojan_go),
|
||||||
"io.nekohasekai.sagernet.plugin.trojan_go"
|
"io.nekohasekai.sagernet.plugin.trojan_go"
|
||||||
),
|
),
|
||||||
|
MieruProxy(
|
||||||
|
"mieru-plugin",
|
||||||
|
SagerNet.application.getString(R.string.action_mieru),
|
||||||
|
"moe.matsuri.exe.mieru",
|
||||||
|
DownloadSource(
|
||||||
|
playStore = false,
|
||||||
|
fdroid = false,
|
||||||
|
downloadLink = "https://github.com/MatsuriDayo/plugins/releases?q=mieru"
|
||||||
|
)
|
||||||
|
),
|
||||||
NaiveProxy(
|
NaiveProxy(
|
||||||
"naive-plugin",
|
"naive-plugin",
|
||||||
SagerNet.application.getString(R.string.action_naive),
|
SagerNet.application.getString(R.string.action_naive),
|
||||||
|
|||||||
@ -10,6 +10,7 @@ object TypeMap : HashMap<String, Int>() {
|
|||||||
this["vmess"] = ProxyEntity.TYPE_VMESS
|
this["vmess"] = ProxyEntity.TYPE_VMESS
|
||||||
this["trojan"] = ProxyEntity.TYPE_TROJAN
|
this["trojan"] = ProxyEntity.TYPE_TROJAN
|
||||||
this["trojan-go"] = ProxyEntity.TYPE_TROJAN_GO
|
this["trojan-go"] = ProxyEntity.TYPE_TROJAN_GO
|
||||||
|
this["mieru"] = ProxyEntity.TYPE_MIERU
|
||||||
this["naive"] = ProxyEntity.TYPE_NAIVE
|
this["naive"] = ProxyEntity.TYPE_NAIVE
|
||||||
this["hysteria"] = ProxyEntity.TYPE_HYSTERIA
|
this["hysteria"] = ProxyEntity.TYPE_HYSTERIA
|
||||||
this["ssh"] = ProxyEntity.TYPE_SSH
|
this["ssh"] = ProxyEntity.TYPE_SSH
|
||||||
|
|||||||
@ -0,0 +1,89 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2022 by nekohasekai <contact-git@sekai.icu> *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
package io.nekohasekai.sagernet.fmt.mieru;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.esotericsoftware.kryo.io.ByteBufferInput;
|
||||||
|
import com.esotericsoftware.kryo.io.ByteBufferOutput;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import io.nekohasekai.sagernet.fmt.AbstractBean;
|
||||||
|
import io.nekohasekai.sagernet.fmt.KryoConverters;
|
||||||
|
|
||||||
|
public class MieruBean extends AbstractBean {
|
||||||
|
|
||||||
|
public String protocol;
|
||||||
|
public String username;
|
||||||
|
public String password;
|
||||||
|
public Integer mtu;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initializeDefaultValues() {
|
||||||
|
super.initializeDefaultValues();
|
||||||
|
if (protocol == null) protocol = "TCP";
|
||||||
|
if (username == null) username = "";
|
||||||
|
if (password == null) password = "";
|
||||||
|
if (mtu == null) mtu = 1400;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(ByteBufferOutput output) {
|
||||||
|
output.writeInt(0);
|
||||||
|
super.serialize(output);
|
||||||
|
output.writeString(protocol);
|
||||||
|
output.writeString(username);
|
||||||
|
output.writeString(password);
|
||||||
|
if (protocol.equals("UDP")) {
|
||||||
|
output.writeInt(mtu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deserialize(ByteBufferInput input) {
|
||||||
|
int version = input.readInt();
|
||||||
|
super.deserialize(input);
|
||||||
|
protocol = input.readString();
|
||||||
|
username = input.readString();
|
||||||
|
password = input.readString();
|
||||||
|
if (protocol.equals("UDP")) {
|
||||||
|
mtu = input.readInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public MieruBean clone() {
|
||||||
|
return KryoConverters.deserialize(new MieruBean(), KryoConverters.serialize(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<MieruBean> CREATOR = new CREATOR<MieruBean>() {
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public MieruBean newInstance() {
|
||||||
|
return new MieruBean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MieruBean[] newArray(int size) {
|
||||||
|
return new MieruBean[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2022 by nekohasekai <contact-git@sekai.icu> *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
package io.nekohasekai.sagernet.fmt.mieru
|
||||||
|
|
||||||
|
import io.nekohasekai.sagernet.ktx.toStringPretty
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
fun MieruBean.buildMieruConfig(port: Int): String {
|
||||||
|
val serverInfo = JSONArray().apply {
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("ipAddress", finalAddress)
|
||||||
|
put("portBindings", JSONArray().apply {
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("port", finalPort)
|
||||||
|
put("protocol", protocol)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return JSONObject().apply {
|
||||||
|
put("activeProfile", "default")
|
||||||
|
put("socks5Port", port)
|
||||||
|
// TODO: follow NekoBox logging level.
|
||||||
|
put("loggingLevel", "INFO")
|
||||||
|
put("profiles", JSONArray().apply {
|
||||||
|
put(JSONObject().apply {
|
||||||
|
put("profileName", "default")
|
||||||
|
put("user", JSONObject().apply {
|
||||||
|
put("name", username)
|
||||||
|
put("password", password)
|
||||||
|
})
|
||||||
|
put("servers", serverInfo)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}.toStringPretty()
|
||||||
|
}
|
||||||
@ -362,6 +362,10 @@ class ConfigurationFragment @JvmOverloads constructor(
|
|||||||
startActivity(Intent(requireActivity(), TrojanGoSettingsActivity::class.java))
|
startActivity(Intent(requireActivity(), TrojanGoSettingsActivity::class.java))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
R.id.action_new_mieru -> {
|
||||||
|
startActivity(Intent(requireActivity(), MieruSettingsActivity::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
R.id.action_new_naive -> {
|
R.id.action_new_naive -> {
|
||||||
startActivity(Intent(requireActivity(), NaiveSettingsActivity::class.java))
|
startActivity(Intent(requireActivity(), NaiveSettingsActivity::class.java))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,77 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2021 by nekohasekai <contact-sagernet@sekai.icu> *
|
||||||
|
* *
|
||||||
|
* 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 <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
package io.nekohasekai.sagernet.ui.profile
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.preference.EditTextPreference
|
||||||
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
import io.nekohasekai.sagernet.Key
|
||||||
|
import io.nekohasekai.sagernet.R
|
||||||
|
import io.nekohasekai.sagernet.database.DataStore
|
||||||
|
import io.nekohasekai.sagernet.database.preference.EditTextPreferenceModifiers
|
||||||
|
import io.nekohasekai.sagernet.fmt.mieru.MieruBean
|
||||||
|
import io.nekohasekai.sagernet.ktx.applyDefaultValues
|
||||||
|
import moe.matsuri.nb4a.ui.SimpleMenuPreference
|
||||||
|
|
||||||
|
class MieruSettingsActivity : ProfileSettingsActivity<MieruBean>() {
|
||||||
|
|
||||||
|
override fun createEntity() = MieruBean().applyDefaultValues()
|
||||||
|
|
||||||
|
override fun MieruBean.init() {
|
||||||
|
DataStore.profileName = name
|
||||||
|
DataStore.serverAddress = serverAddress
|
||||||
|
DataStore.serverPort = serverPort
|
||||||
|
DataStore.serverProtocol = protocol
|
||||||
|
DataStore.serverUsername = username
|
||||||
|
DataStore.serverPassword = password
|
||||||
|
DataStore.mtu = mtu
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun MieruBean.serialize() {
|
||||||
|
name = DataStore.profileName
|
||||||
|
serverAddress = DataStore.serverAddress
|
||||||
|
serverPort = DataStore.serverPort
|
||||||
|
protocol = DataStore.serverProtocol
|
||||||
|
username = DataStore.serverUsername
|
||||||
|
password = DataStore.serverPassword
|
||||||
|
mtu = DataStore.mtu
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun PreferenceFragmentCompat.createPreferences(
|
||||||
|
savedInstanceState: Bundle?,
|
||||||
|
rootKey: String?,
|
||||||
|
) {
|
||||||
|
addPreferencesFromResource(R.xml.mieru_preferences)
|
||||||
|
findPreference<EditTextPreference>(Key.SERVER_PORT)!!.apply {
|
||||||
|
setOnBindEditTextListener(EditTextPreferenceModifiers.Port)
|
||||||
|
}
|
||||||
|
findPreference<EditTextPreference>(Key.SERVER_PASSWORD)!!.apply {
|
||||||
|
summaryProvider = PasswordSummaryProvider
|
||||||
|
}
|
||||||
|
val protocol = findPreference<SimpleMenuPreference>(Key.SERVER_PROTOCOL)!!
|
||||||
|
val mtu = findPreference<EditTextPreference>(Key.MTU)!!
|
||||||
|
mtu.isVisible = protocol.value.equals("UDP")
|
||||||
|
protocol.setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
mtu.isVisible = newValue.equals("UDP")
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -45,6 +45,9 @@
|
|||||||
<item
|
<item
|
||||||
android:id="@+id/action_new_trojan_go"
|
android:id="@+id/action_new_trojan_go"
|
||||||
android:title="@string/action_trojan_go" />
|
android:title="@string/action_trojan_go" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_new_mieru"
|
||||||
|
android:title="@string/action_mieru" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_new_naive"
|
android:id="@+id/action_new_naive"
|
||||||
android:title="@string/action_naive" />
|
android:title="@string/action_naive" />
|
||||||
|
|||||||
@ -332,6 +332,10 @@
|
|||||||
<item>TPROXY</item>
|
<item>TPROXY</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="mieru_protocol">
|
||||||
|
<item>TCP</item>
|
||||||
|
<item>UDP</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string-array name="naive_proto_entry">
|
<string-array name="naive_proto_entry">
|
||||||
<item>HTTPS</item>
|
<item>HTTPS</item>
|
||||||
|
|||||||
@ -214,6 +214,7 @@
|
|||||||
<string name="action_vmess" translatable="false">VMess</string>
|
<string name="action_vmess" translatable="false">VMess</string>
|
||||||
<string name="action_trojan" translatable="false">Trojan</string>
|
<string name="action_trojan" translatable="false">Trojan</string>
|
||||||
<string name="action_trojan_go" translatable="false">Trojan Go</string>
|
<string name="action_trojan_go" translatable="false">Trojan Go</string>
|
||||||
|
<string name="action_mieru" translatable="false">Mieru</string>
|
||||||
<string name="action_naive" translatable="false">Naïve</string>
|
<string name="action_naive" translatable="false">Naïve</string>
|
||||||
<string name="action_ping_tunnel" translatable="false">Ping Tunnel</string>
|
<string name="action_ping_tunnel" translatable="false">Ping Tunnel</string>
|
||||||
<string name="action_hysteria" translatable="false">Hysteria</string>
|
<string name="action_hysteria" translatable="false">Hysteria</string>
|
||||||
|
|||||||
46
app/src/main/res/xml/mieru_preferences.xml
Normal file
46
app/src/main/res/xml/mieru_preferences.xml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
app:icon="@drawable/ic_social_emoji_symbols"
|
||||||
|
app:key="profileName"
|
||||||
|
app:title="@string/profile_name"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
|
||||||
|
<PreferenceCategory app:title="@string/proxy_cat">
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
app:icon="@drawable/ic_hardware_router"
|
||||||
|
app:key="serverAddress"
|
||||||
|
app:title="@string/server_address"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
<EditTextPreference
|
||||||
|
app:icon="@drawable/ic_maps_directions_boat"
|
||||||
|
app:key="serverPort"
|
||||||
|
app:title="@string/server_port"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
<moe.matsuri.nb4a.ui.SimpleMenuPreference
|
||||||
|
app:defaultValue="TCP"
|
||||||
|
app:entries="@array/mieru_protocol"
|
||||||
|
app:entryValues="@array/mieru_protocol"
|
||||||
|
app:icon="@drawable/ic_baseline_compare_arrows_24"
|
||||||
|
app:key="serverProtocol"
|
||||||
|
app:title="@string/protocol"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
<EditTextPreference
|
||||||
|
app:icon="@drawable/ic_baseline_person_24"
|
||||||
|
app:key="serverUsername"
|
||||||
|
app:title="@string/username"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
<EditTextPreference
|
||||||
|
app:dialogLayout="@layout/layout_password_dialog"
|
||||||
|
app:icon="@drawable/ic_settings_password"
|
||||||
|
app:key="serverPassword"
|
||||||
|
app:title="@string/password" />
|
||||||
|
<EditTextPreference
|
||||||
|
app:icon="@drawable/baseline_public_24"
|
||||||
|
app:key="mtu"
|
||||||
|
app:title="@string/mtu"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
||||||
Loading…
Reference in New Issue
Block a user