From 34f1e6f984b0f15150154e28addbef7f28cb7a08 Mon Sep 17 00:00:00 2001 From: djoeni Date: Thu, 16 Jun 2022 14:32:16 +0700 Subject: [PATCH] add setting meta features --- app/src/main/AndroidManifest.xml | 5 + .../clash/MetaFeatureSettingsActivity.kt | 49 +++++ .../github/kr328/clash/SettingsActivity.kt | 2 + .../clash/core/model/ConfigurationOverride.kt | 48 +++++ .../github/kr328/clash/design/HelpDesign.kt | 67 ++---- .../clash/design/MetaFeatureSettingsDesign.kt | 198 ++++++++++++++++++ .../kr328/clash/design/SettingsDesign.kt | 2 +- .../main/res/drawable/ic_baseline_meta.xml | 10 + .../src/main/res/layout/design_settings.xml | 7 + .../layout/design_settings_meta_feature.xml | 66 ++++++ design/src/main/res/values-zh-rHK/strings.xml | 10 +- design/src/main/res/values-zh-rTW/strings.xml | 10 +- design/src/main/res/values-zh/strings.xml | 10 +- design/src/main/res/values/strings.xml | 44 +++- 14 files changed, 454 insertions(+), 74 deletions(-) create mode 100644 app/src/main/java/com/github/kr328/clash/MetaFeatureSettingsActivity.kt create mode 100644 design/src/main/java/com/github/kr328/clash/design/MetaFeatureSettingsDesign.kt create mode 100644 design/src/main/res/drawable/ic_baseline_meta.xml create mode 100644 design/src/main/res/layout/design_settings_meta_feature.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5caa7e89..17ec8eeb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -136,6 +136,11 @@ android:configChanges="uiMode" android:exported="false" android:label="@string/override" /> + () { + override suspend fun main() { + val configuration = withClash { queryOverride(Clash.OverrideSlot.Persist) } + + defer { + withClash { + patchOverride(Clash.OverrideSlot.Persist, configuration) + } + } + + val design = MetaFeatureSettingsDesign( + this, + configuration + ) + + setContentDesign(design) + + while (isActive) { + select { + events.onReceive { + + } + design.requests.onReceive { + when (it) { + MetaFeatureSettingsDesign.Request.ResetOverride -> { + if (design.requestResetConfirm()) { + defer { + withClash { + clearOverride(Clash.OverrideSlot.Persist) + } + } + + finish() + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/kr328/clash/SettingsActivity.kt b/app/src/main/java/com/github/kr328/clash/SettingsActivity.kt index 0d5fcb9b..95a03933 100644 --- a/app/src/main/java/com/github/kr328/clash/SettingsActivity.kt +++ b/app/src/main/java/com/github/kr328/clash/SettingsActivity.kt @@ -24,6 +24,8 @@ class SettingsActivity : BaseActivity() { startActivity(NetworkSettingsActivity::class.intent) SettingsDesign.Request.StartOverride -> startActivity(OverrideSettingsActivity::class.intent) + SettingsDesign.Request.StartMetaFeature -> + startActivity(MetaFeatureSettingsActivity::class.intent) } } } diff --git a/core/src/main/java/com/github/kr328/clash/core/model/ConfigurationOverride.kt b/core/src/main/java/com/github/kr328/clash/core/model/ConfigurationOverride.kt index 43a4ab23..f82da9a8 100644 --- a/core/src/main/java/com/github/kr328/clash/core/model/ConfigurationOverride.kt +++ b/core/src/main/java/com/github/kr328/clash/core/model/ConfigurationOverride.kt @@ -44,11 +44,32 @@ data class ConfigurationOverride( @SerialName("hosts") var hosts: Map? = null, + @SerialName("force-cert-verify") + var forceCertVeriy: Boolean? = null, + + @SerialName("unified-delay") + var unifiedDelay: Boolean? = null, + + @SerialName("geodata-mode") + var geodataMode: Boolean? = null, + + @SerialName("tcp-concurrent") + var tcpConcurrent: Boolean? = null, + + @SerialName("enable-process") + var enableProcess: Boolean? = null, + @SerialName("dns") val dns: Dns = Dns(), @SerialName("clash-for-android") val app: App = App(), + + @SerialName("sniffer") + val sniffer: Sniffer = Sniffer(), + + @SerialName("geox-url") + val geoxurl: GeoXUrl = GeoXUrl(), ) : Parcelable { @Serializable data class Dns( @@ -119,6 +140,33 @@ data class ConfigurationOverride( FakeIp, } + @Serializable + data class Sniffer( + @SerialName("enable") + var enable: Boolean? = null, + + @SerialName("sniffing") + var sniffing: List? = null, + + @SerialName("force-domain") + var forceDomain: List? = null, + + @SerialName("skip-domain") + var skipDomain: List? = null, + ) + + @Serializable + data class GeoXUrl( + @SerialName("geoip") + var geoip: String? = null, + + @SerialName("mmdb") + var mmdb: String? = null, + + @SerialName("geosite") + var geosite: String? = null, + ) + override fun writeToParcel(parcel: Parcel, flags: Int) { Parcelizer.encodeToParcel(serializer(), parcel, this) } diff --git a/design/src/main/java/com/github/kr328/clash/design/HelpDesign.kt b/design/src/main/java/com/github/kr328/clash/design/HelpDesign.kt index 047eb3d1..552ff3f3 100644 --- a/design/src/main/java/com/github/kr328/clash/design/HelpDesign.kt +++ b/design/src/main/java/com/github/kr328/clash/design/HelpDesign.kt @@ -3,7 +3,6 @@ package com.github.kr328.clash.design import android.content.Context import android.net.Uri import android.view.View -import com.github.kr328.clash.common.compat.preferredLocale import com.github.kr328.clash.design.databinding.DesignSettingsCommonBinding import com.github.kr328.clash.design.preference.category import com.github.kr328.clash.design.preference.clickable @@ -45,60 +44,32 @@ class HelpDesign( } } - category(R.string.feedback) + clickable( + title = R.string.clash_meta_wiki, + summary = R.string.clash_meta_wiki_url + ) { + clicked { + openLink(Uri.parse(context.getString(R.string.clash_meta_wiki_url))) + } + } - if (BuildConfig.PREMIUM) { - clickable( - title = R.string.google_play, - summary = R.string.google_play_url - ) { - clicked { - openLink(Uri.parse(context.getString(R.string.google_play_url))) - } + category(R.string.sources) + + clickable( + title = R.string.clash_meta_for_android, + summary = R.string.meta_github_url + ) { + clicked { + openLink(Uri.parse(context.getString(R.string.meta_github_url))) } } clickable( - title = R.string.github_issues, - summary = R.string.github_issues_url + title = R.string.clash_meta_core, + summary = R.string.clash_meta_core_url ) { clicked { - openLink(Uri.parse(context.getString(R.string.github_issues_url))) - } - } - - if (!BuildConfig.PREMIUM) { - category(R.string.sources) - - clickable( - title = R.string.clash_for_android, - summary = R.string.github_url - ) { - clicked { - openLink(Uri.parse(context.getString(R.string.github_url))) - } - } - - clickable( - title = R.string.clash_core, - summary = R.string.clash_core_url - ) { - clicked { - openLink(Uri.parse(context.getString(R.string.clash_core_url))) - } - } - } - - if (context.resources.configuration.preferredLocale.language == "zh") { - category(R.string.donate) - - clickable( - title = R.string.donate, - summary = R.string.donate_url - ) { - clicked { - openLink(Uri.parse(context.getString(R.string.donate_url))) - } + openLink(Uri.parse(context.getString(R.string.clash_meta_core_url))) } } } diff --git a/design/src/main/java/com/github/kr328/clash/design/MetaFeatureSettingsDesign.kt b/design/src/main/java/com/github/kr328/clash/design/MetaFeatureSettingsDesign.kt new file mode 100644 index 00000000..b9dd6dac --- /dev/null +++ b/design/src/main/java/com/github/kr328/clash/design/MetaFeatureSettingsDesign.kt @@ -0,0 +1,198 @@ +package com.github.kr328.clash.design + +import android.content.Context +import android.view.View +import com.github.kr328.clash.core.model.ConfigurationOverride +import com.github.kr328.clash.design.databinding.DesignSettingsMetaFeatureBinding +import com.github.kr328.clash.design.preference.* +import com.github.kr328.clash.design.util.* +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlin.coroutines.resume + +class MetaFeatureSettingsDesign( + context: Context, + configuration: ConfigurationOverride +) : Design(context) { + enum class Request { + ResetOverride + } + + private val binding = DesignSettingsMetaFeatureBinding + .inflate(context.layoutInflater, context.root, false) + + override val root: View + get() = binding.root + + suspend fun requestResetConfirm(): Boolean { + return suspendCancellableCoroutine { ctx -> + val dialog = MaterialAlertDialogBuilder(context) + .setTitle(R.string.reset_override_settings) + .setMessage(R.string.reset_override_settings_message) + .setPositiveButton(R.string.ok) { _, _ -> ctx.resume(true) } + .setNegativeButton(R.string.cancel) { _, _ -> } + .show() + + dialog.setOnDismissListener { + if (!ctx.isCompleted) + ctx.resume(false) + } + + ctx.invokeOnCancellation { + dialog.dismiss() + } + } + } + + init { + binding.self = this + + binding.activityBarLayout.applyFrom(context) + + binding.scrollRoot.bindAppBarElevation(binding.activityBarLayout) + + val booleanValues: Array = arrayOf( + null, + true, + false + ) + val booleanValuesText: Array = arrayOf( + R.string.dont_modify, + R.string.enabled, + R.string.disabled + ) + + val screen = preferenceScreen(context) { + category(R.string.meta_features) + + selectableList( + value = configuration::forceCertVeriy, + values = booleanValues, + valuesText = booleanValuesText, + title = R.string.force_cert_verify, + ) + + selectableList( + value = configuration::unifiedDelay, + values = booleanValues, + valuesText = booleanValuesText, + title = R.string.unified_delay, + ) + + selectableList( + value = configuration::geodataMode, + values = booleanValues, + valuesText = booleanValuesText, + title = R.string.geodata_mode, + ) + + selectableList( + value = configuration::tcpConcurrent, + values = booleanValues, + valuesText = booleanValuesText, + title = R.string.tcp_concurrent, + ) + + selectableList( + value = configuration::enableProcess, + values = booleanValues, + valuesText = booleanValuesText, + title = R.string.enable_process, + ) + + category(R.string.sniffer_setting) + + val snifferDependencies: MutableList = mutableListOf() + + val sniffer = selectableList( + value = configuration.sniffer::enable, + values = arrayOf( + null, + true, + false + ), + valuesText = arrayOf( + R.string.sniffer_config, + R.string.sniffer_override, + R.string.disable_sniffer, + ), + title = R.string.strategy + ) { + listener = OnChangedListener { + if (configuration.sniffer.enable == false) { + snifferDependencies.forEach { + it.enabled = false + } + } else { + snifferDependencies.forEach { + it.enabled = true + } + } + } + } + + editableTextList( + value = configuration.sniffer::sniffing, + adapter = TextAdapter.String, + title = R.string.sniffing, + placeholder = R.string.dont_modify, + configure = snifferDependencies::add, + ) + + editableTextList( + value = configuration.sniffer::forceDomain, + adapter = TextAdapter.String, + title = R.string.force_domain, + placeholder = R.string.dont_modify, + configure = snifferDependencies::add, + ) + + editableTextList( + value = configuration.sniffer::skipDomain, + adapter = TextAdapter.String, + title = R.string.skip_domain, + placeholder = R.string.dont_modify, + configure = snifferDependencies::add, + ) + + sniffer.listener?.onChanged() + + category(R.string.geox_url_setting) + + val geoxurlDependencies: MutableList = mutableListOf() + + editableText( + value = configuration.geoxurl::geoip, + adapter = NullableTextAdapter.String, + title = R.string.geox_geoip, + placeholder = R.string.dont_modify, + empty = R.string.geoip_url, + configure = geoxurlDependencies::add, + ) + + editableText( + value = configuration.geoxurl::geoip, + adapter = NullableTextAdapter.String, + title = R.string.geox_mmdb, + placeholder = R.string.dont_modify, + empty = R.string.mmdb_url, + configure = geoxurlDependencies::add, + ) + + editableText( + value = configuration.geoxurl::geoip, + adapter = NullableTextAdapter.String, + title = R.string.geox_geosite, + placeholder = R.string.dont_modify, + empty = R.string.geosite_url, + configure = geoxurlDependencies::add, + ) + } + + binding.content.addView(screen.root) + } + + fun requestClear() { + requests.trySend(Request.ResetOverride) + } +} diff --git a/design/src/main/java/com/github/kr328/clash/design/SettingsDesign.kt b/design/src/main/java/com/github/kr328/clash/design/SettingsDesign.kt index d6f6c190..0536a587 100644 --- a/design/src/main/java/com/github/kr328/clash/design/SettingsDesign.kt +++ b/design/src/main/java/com/github/kr328/clash/design/SettingsDesign.kt @@ -10,7 +10,7 @@ import com.github.kr328.clash.design.util.root class SettingsDesign(context: Context) : Design(context) { enum class Request { - StartApp, StartNetwork, StartOverride, + StartApp, StartNetwork, StartOverride, StartMetaFeature, } private val binding = DesignSettingsBinding diff --git a/design/src/main/res/drawable/ic_baseline_meta.xml b/design/src/main/res/drawable/ic_baseline_meta.xml new file mode 100644 index 00000000..51125abc --- /dev/null +++ b/design/src/main/res/drawable/ic_baseline_meta.xml @@ -0,0 +1,10 @@ + + + diff --git a/design/src/main/res/layout/design_settings.xml b/design/src/main/res/layout/design_settings.xml index b36cf5f1..885ec4a5 100644 --- a/design/src/main/res/layout/design_settings.xml +++ b/design/src/main/res/layout/design_settings.xml @@ -49,6 +49,13 @@ app:icon="@drawable/ic_baseline_extension" app:text="@string/override" /> + + diff --git a/design/src/main/res/layout/design_settings_meta_feature.xml b/design/src/main/res/layout/design_settings_meta_feature.xml new file mode 100644 index 00000000..50c869f7 --- /dev/null +++ b/design/src/main/res/layout/design_settings_meta_feature.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/design/src/main/res/values-zh-rHK/strings.xml b/design/src/main/res/values-zh-rHK/strings.xml index 2c8a7c20..d1d2bc0e 100644 --- a/design/src/main/res/values-zh-rHK/strings.xml +++ b/design/src/main/res/values-zh-rHK/strings.xml @@ -6,7 +6,7 @@ 訪問控制應用包列表 追加系統 DNS 應用損壞 - Clash for Android + Clash Meta for Android 自動更新 行為 繞過私有網絡 @@ -43,7 +43,7 @@ 從 URL 導入 界面 無效的 URL - Clash + Clash Meta for Android Logcat 日誌 模式 @@ -79,12 +79,11 @@ 更新時間 應用包名稱 安裝時間 - Clash for Android 反饋 Github Issues Clash 配置文件(包含代理/規則)]]> 載入中 - 免費軟件並且我們為其提供任何服務, 請務必不要反饋非應用自身引起的問題]]> + 免費軟件並且我們為其提供任何服務, 請務必不要反饋非應用自身引起的問題]]> 捐贈 允許所有應用 僅允許已選擇的應用 @@ -209,8 +208,9 @@ 僅在本次會話中有效 導入 源代碼 - Clash 核心 + Clash 核心 Name Server 策略 阻止本地迴環 阻止本地迴環連接 + Clash Meta for Android \ No newline at end of file diff --git a/design/src/main/res/values-zh-rTW/strings.xml b/design/src/main/res/values-zh-rTW/strings.xml index 765556c6..b96b6bcf 100644 --- a/design/src/main/res/values-zh-rTW/strings.xml +++ b/design/src/main/res/values-zh-rTW/strings.xml @@ -6,7 +6,7 @@ 存取控制應用程式套件清單 附加作業系統 DNS 應用程式損毀 - Clash for Android + Clash Meta for Android 自動更新 行為 略過私有網路 @@ -43,7 +43,7 @@ 從 URL 匯入 介面 無效 URL - Clash + Clash Meta for Android Logcat 日誌 模式 @@ -79,12 +79,11 @@ 更新時間 套件名稱 安裝時間 - Clash for Android 回饋 Github Issues Clash 設定檔 (包含Proxy /規則)]]> 載入中 - 免費應用程式並且我們為其提供任何服務, 請務必不要回報非應用程式自身引起的問題]]> + 免費應用程式並且我們為其提供任何服務, 請務必不要回報非應用程式自身引起的問題]]> 捐助 允許所有應用 僅允許已選擇的應用 @@ -209,8 +208,9 @@ 僅在本次工作階段中有效 匯入 原始碼 - Clash 核心 + Clash 核心 Name Server 政策 攔截本地回送 攔截本地回送連結 + Clash Meta for Android diff --git a/design/src/main/res/values-zh/strings.xml b/design/src/main/res/values-zh/strings.xml index 3233e568..63b2bb5f 100644 --- a/design/src/main/res/values-zh/strings.xml +++ b/design/src/main/res/values-zh/strings.xml @@ -6,7 +6,7 @@ 访问控制应用包列表 追加系统 DNS 应用损坏 - Clash for Android + Clash Meta for Android 自动更新 行为 绕过私有网络 @@ -43,7 +43,7 @@ 从 URL 导入 界面 无效的 URL - Clash + Clash Meta for Android Logcat 日志 模式 @@ -79,12 +79,12 @@ 更新时间 应用包名称 安装时间 - Clash for Android + Clash Meta for Android 反馈 Github Issues Clash 配置文件(包含代理/规则)]]> 载入中 - 免费软件并且我们为其提供任何服务, 请务必不要反馈非应用自身引起的问题]]> + 免费软件并且我们为其提供任何服务, 请务必不要反馈非应用自身引起的问题]]> 捐赠 允许所有应用 仅允许已选择的应用 @@ -209,7 +209,7 @@ 仅在本次会话中有效 导入 源代码 - Clash 核心 + Clash Meta 核心 Name Server 策略 阻止本地回环 阻止本地回环连接 diff --git a/design/src/main/res/values/strings.xml b/design/src/main/res/values/strings.xml index 5f44ad29..3f277cf3 100644 --- a/design/src/main/res/values/strings.xml +++ b/design/src/main/res/values/strings.xml @@ -1,6 +1,6 @@ - Clash - Clash for Android + Clash Meta for Android + Clash Meta for Android Stopped Tap to start @@ -49,7 +49,6 @@ App lacks the necessary runtime components, which is usually caused by downloading an incomplete apk. Reinstall Github Releases - https://github.com/kr328/clashforandroid/releases Profile Name @@ -196,7 +195,7 @@ Import from Clipboard Export to Clipboard - Clash for Android + Clash Meta for Android Document Feedback @@ -205,15 +204,13 @@ Clash Wiki Github Issues Google Play - Clash Core + Clash Meta Core https://github.com/Dreamacro/clash/wiki - https://github.com/Kr328/ClashForAndroid/issues - https://donate.kr328.app - https://github.com/Kr328/ClashForAndroid - https://github.com/Dreamacro/clash + https://github.com/MetaCubeX/ClashMetaForAndroid + https://github.com/MetaCubeX/Clash.Meta Clash Config(including Proxy/Rules)]]> - freeware and we do NOT provide any service for it]]> + freeware and we do NOT provide any service for it]]> https://play.google.com/store/apps/details?id=com.github.kr328.clash @@ -278,4 +275,31 @@ The settings have been reseted and the old profiles needs to be saved again. Valid only for current session + + Clash Meta Wiki + https://docs.metacubex.one/ + + Meta Features + Force Cert Verify + Unified Delay + Geodata Mode + TCP Concurrent + Enable Process + + Sniffer Setting + Sniffer + Sniffer Mode + Force Domain + Skip Domain + Disable Sniffer + Load Sniffer From Config + Override Sniffer Config + + GeoX Url Setting + GeoIp Url + MMDB Url + Geosite Url + https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geoip.dat + https://raw.githubusercontent.com/Loyalsoldier/geoip/release/Country.mmdb + https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geosite.dat