diff --git a/build.gradle.kts b/build.gradle.kts index f1d59d4c..2caf1702 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -70,10 +70,6 @@ subprojects { versionName = buildVersionName versionCode = buildVersionCode - if (!isApp) { - consumerProguardFiles("consumer-rules.pro") - } - resValue("string", "release_name", "v$buildVersionName") resValue("integer", "release_code", "$buildVersionCode") @@ -82,6 +78,10 @@ subprojects { abiFilters("arm64-v8a", "armeabi-v7a", "x86", "x86_64") } } + + if (!isApp) { + consumerProguardFiles("consumer-rules.pro") + } } if (isApp) { @@ -108,6 +108,8 @@ subprojects { dimension = defaultDimension versionNameSuffix = ".foss" + buildConfigField("boolean", "PREMIUM", "Boolean.parseBoolean(\"false\")") + if (isApp) { applicationIdSuffix = ".foss" } @@ -116,6 +118,8 @@ subprojects { dimension = defaultDimension versionNameSuffix = ".premium" + buildConfigField("boolean", "PREMIUM", "Boolean.parseBoolean(\"true\")") + val trackFile = rootProject.file("track.properties") if (trackFile.exists()) { val track = Properties().apply { diff --git a/design/src/foss/java/com/github/kr328/clash/design/OverrideSettingsDesign.kt b/design/src/foss/java/com/github/kr328/clash/design/OverrideSettingsDesign.kt deleted file mode 100644 index ae0a592f..00000000 --- a/design/src/foss/java/com/github/kr328/clash/design/OverrideSettingsDesign.kt +++ /dev/null @@ -1,399 +0,0 @@ -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.core.model.LogMessage -import com.github.kr328.clash.core.model.TunnelState -import com.github.kr328.clash.design.adapter.SideloadProviderAdapter -import com.github.kr328.clash.design.databinding.DesignSettingsOverideBinding -import com.github.kr328.clash.design.databinding.DialogPreferenceListBinding -import com.github.kr328.clash.design.dialog.FullScreenDialog -import com.github.kr328.clash.design.model.AppInfo -import com.github.kr328.clash.design.preference.* -import com.github.kr328.clash.design.util.* -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.suspendCancellableCoroutine -import kotlinx.coroutines.withContext -import kotlin.coroutines.resume - -class OverrideSettingsDesign( - context: Context, - configuration: ConfigurationOverride -) : Design(context) { - enum class Request { - ResetOverride, EditSideloadGeoip - } - - private val binding = DesignSettingsOverideBinding - .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() - } - } - } - - suspend fun requestSelectSideload(initial: String, apps: List): String = - withContext(Dispatchers.Main) { - suspendCancellableCoroutine { ctx -> - val binding = DialogPreferenceListBinding - .inflate(context.layoutInflater, context.root, false) - val adapter = SideloadProviderAdapter(context, apps, initial) - val dialog = FullScreenDialog(context) - - dialog.setContentView(binding.root) - - binding.surface = dialog.surface - - binding.titleView.text = context.getString(R.string.sideload_geoip) - - binding.newView.visibility = View.INVISIBLE - - binding.mainList.applyLinearAdapter(context, adapter) - - binding.resetView.setOnClickListener { - ctx.resume("") - - dialog.dismiss() - } - - binding.cancelView.setOnClickListener { - dialog.dismiss() - } - - binding.okView.setOnClickListener { - ctx.resume(adapter.selectedPackageName) - - dialog.dismiss() - } - - dialog.setOnDismissListener { - if (!ctx.isCompleted) - ctx.resume(initial) - } - - dialog.show() - } - } - - 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.general) - - editableText( - value = configuration::httpPort, - adapter = NullableTextAdapter.Port, - title = R.string.http_port, - placeholder = R.string.dont_modify, - empty = R.string.disabled, - ) - - editableText( - value = configuration::socksPort, - adapter = NullableTextAdapter.Port, - title = R.string.socks_port, - placeholder = R.string.dont_modify, - empty = R.string.disabled, - ) - - editableText( - value = configuration::redirectPort, - adapter = NullableTextAdapter.Port, - title = R.string.redirect_port, - placeholder = R.string.dont_modify, - empty = R.string.disabled, - ) - - editableText( - value = configuration::tproxyPort, - adapter = NullableTextAdapter.Port, - title = R.string.tproxy_port, - placeholder = R.string.dont_modify, - empty = R.string.disabled, - ) - - editableText( - value = configuration::mixedPort, - adapter = NullableTextAdapter.Port, - title = R.string.mixed_port, - placeholder = R.string.dont_modify, - empty = R.string.disabled, - ) - - editableTextList( - value = configuration::authentication, - adapter = TextAdapter.String, - title = R.string.authentication, - placeholder = R.string.dont_modify, - ) - - selectableList( - value = configuration::allowLan, - values = booleanValues, - valuesText = booleanValuesText, - title = R.string.allow_lan, - ) - - selectableList( - value = configuration::ipv6, - values = booleanValues, - valuesText = booleanValuesText, - title = R.string.ipv6, - ) - - editableText( - value = configuration::bindAddress, - adapter = NullableTextAdapter.String, - title = R.string.bind_address, - placeholder = R.string.dont_modify, - empty = R.string.default_ - ) - - selectableList( - value = configuration::mode, - values = arrayOf( - null, - TunnelState.Mode.Direct, - TunnelState.Mode.Global, - TunnelState.Mode.Rule, - ), - valuesText = arrayOf( - R.string.dont_modify, - R.string.direct_mode, - R.string.global_mode, - R.string.rule_mode, - ), - title = R.string.mode - ) - - selectableList( - value = configuration::logLevel, - values = arrayOf( - null, - LogMessage.Level.Info, - LogMessage.Level.Warning, - LogMessage.Level.Error, - LogMessage.Level.Debug, - LogMessage.Level.Silent, - ), - valuesText = arrayOf( - R.string.dont_modify, - R.string.info, - R.string.warning, - R.string.error, - R.string.debug, - R.string.silent, - ), - title = R.string.log_level, - ) - - editableTextMap( - value = configuration::hosts, - keyAdapter = TextAdapter.String, - valueAdapter = TextAdapter.String, - title = R.string.hosts, - placeholder = R.string.dont_modify, - ) - - clickable( - title = R.string.sideload_geoip, - summary = R.string.sideload_geoip_summary - ) { - clicked { - requests.trySend(Request.EditSideloadGeoip) - } - } - - category(R.string.dns) - - val dnsDependencies: MutableList = mutableListOf() - - val dns = selectableList( - value = configuration.dns::enable, - values = arrayOf( - null, - true, - false - ), - valuesText = arrayOf( - R.string.dont_modify, - R.string.force_enable, - R.string.use_built_in, - ), - title = R.string.strategy - ) { - listener = OnChangedListener { - if (configuration.dns.enable == false) { - dnsDependencies.forEach { - it.enabled = false - } - } else { - dnsDependencies.forEach { - it.enabled = true - } - } - } - } - - editableText( - value = configuration.dns::listen, - adapter = NullableTextAdapter.String, - title = R.string.listen, - placeholder = R.string.dont_modify, - empty = R.string.disabled, - configure = dnsDependencies::add, - ) - - selectableList( - value = configuration.app::appendSystemDns, - values = booleanValues, - valuesText = booleanValuesText, - title = R.string.append_system_dns, - configure = dnsDependencies::add, - ) - - selectableList( - value = configuration.dns::ipv6, - values = booleanValues, - valuesText = booleanValuesText, - title = R.string.ipv6, - configure = dnsDependencies::add, - ) - - selectableList( - value = configuration.dns::useHosts, - values = booleanValues, - valuesText = booleanValuesText, - title = R.string.use_hosts, - configure = dnsDependencies::add, - ) - - selectableList( - value = configuration.dns::enhancedMode, - values = arrayOf( - null, - ConfigurationOverride.DnsEnhancedMode.None, - ConfigurationOverride.DnsEnhancedMode.FakeIp, - ConfigurationOverride.DnsEnhancedMode.Mapping - ), - valuesText = arrayOf( - R.string.dont_modify, - R.string.disabled, - R.string.fakeip, - R.string.mapping - ), - title = R.string.enhanced_mode, - configure = dnsDependencies::add, - ) - - editableTextList( - value = configuration.dns::nameServer, - adapter = TextAdapter.String, - title = R.string.name_server, - placeholder = R.string.dont_modify, - configure = dnsDependencies::add, - ) - - editableTextList( - value = configuration.dns::fallback, - adapter = TextAdapter.String, - title = R.string.fallback, - placeholder = R.string.dont_modify, - configure = dnsDependencies::add, - ) - - editableTextList( - value = configuration.dns::defaultServer, - adapter = TextAdapter.String, - title = R.string.default_name_server, - placeholder = R.string.dont_modify, - configure = dnsDependencies::add, - ) - - editableTextList( - value = configuration.dns::fakeIpFilter, - adapter = TextAdapter.String, - title = R.string.fakeip_filter, - placeholder = R.string.dont_modify, - configure = dnsDependencies::add, - ) - - selectableList( - value = configuration.dns.fallbackFilter::geoIp, - values = booleanValues, - valuesText = booleanValuesText, - title = R.string.geoip_fallback, - configure = dnsDependencies::add, - ) - - editableTextList( - value = configuration.dns.fallbackFilter::domain, - adapter = TextAdapter.String, - title = R.string.domain_fallback, - placeholder = R.string.dont_modify, - configure = dnsDependencies::add, - ) - - editableTextList( - value = configuration.dns.fallbackFilter::ipcidr, - adapter = TextAdapter.String, - title = R.string.ipcidr_fallback, - placeholder = R.string.dont_modify, - configure = dnsDependencies::add, - ) - - editableTextMap( - value = configuration.dns::nameserverPolicy, - keyAdapter = TextAdapter.String, - valueAdapter = TextAdapter.String, - title = R.string.name_server_policy, - placeholder = R.string.dont_modify, - configure = dnsDependencies::add, - ) - - dns.listener?.onChanged() - } - - binding.content.addView(screen.root) - } - - fun requestClear() { - requests.trySend(Request.ResetOverride) - } -} \ No newline at end of file diff --git a/design/src/foss/java/com/github/kr328/clash/design/component/ProxyMenu.kt b/design/src/foss/java/com/github/kr328/clash/design/component/ProxyMenu.kt deleted file mode 100644 index 017601f9..00000000 --- a/design/src/foss/java/com/github/kr328/clash/design/component/ProxyMenu.kt +++ /dev/null @@ -1,113 +0,0 @@ -package com.github.kr328.clash.design.component - -import android.content.Context -import android.view.MenuItem -import android.view.View -import androidx.appcompat.widget.PopupMenu -import com.github.kr328.clash.core.model.ProxySort -import com.github.kr328.clash.core.model.TunnelState -import com.github.kr328.clash.design.ProxyDesign -import com.github.kr328.clash.design.R -import com.github.kr328.clash.design.store.UiStore -import kotlinx.coroutines.channels.Channel - -class ProxyMenu( - context: Context, - menuView: View, - mode: TunnelState.Mode?, - private val uiStore: UiStore, - private val requests: Channel, - private val updateConfig: () -> Unit, -) : PopupMenu.OnMenuItemClickListener { - private val menu = PopupMenu(context, menuView) - - fun show() { - menu.show() - } - - override fun onMenuItemClick(item: MenuItem): Boolean { - item.isChecked = !item.isChecked - - when (item.itemId) { - R.id.not_selectable -> { - uiStore.proxyExcludeNotSelectable = item.isChecked - - requests.trySend(ProxyDesign.Request.ReLaunch) - } - R.id.single -> { - uiStore.proxySingleLine = true - - updateConfig() - - requests.trySend(ProxyDesign.Request.ReloadAll) - } - R.id.multiple -> { - uiStore.proxySingleLine = false - - updateConfig() - - requests.trySend(ProxyDesign.Request.ReloadAll) - } - R.id.default_ -> { - uiStore.proxySort = ProxySort.Default - - requests.trySend(ProxyDesign.Request.ReloadAll) - } - R.id.name -> { - uiStore.proxySort = ProxySort.Title - - requests.trySend(ProxyDesign.Request.ReloadAll) - } - R.id.delay -> { - uiStore.proxySort = ProxySort.Delay - - requests.trySend(ProxyDesign.Request.ReloadAll) - } - R.id.dont_modify -> { - requests.trySend(ProxyDesign.Request.PatchMode(null)) - } - R.id.direct_mode -> { - requests.trySend(ProxyDesign.Request.PatchMode(TunnelState.Mode.Direct)) - } - R.id.global_mode -> { - requests.trySend(ProxyDesign.Request.PatchMode(TunnelState.Mode.Global)) - } - R.id.rule_mode -> { - requests.trySend(ProxyDesign.Request.PatchMode(TunnelState.Mode.Rule)) - } - else -> return false - } - - return true - } - - init { - menu.menuInflater.inflate(R.menu.menu_proxy, menu.menu) - - menu.menu.apply { - findItem(R.id.not_selectable).isChecked = uiStore.proxyExcludeNotSelectable - - if (uiStore.proxySingleLine) { - findItem(R.id.single).isChecked = true - } else { - findItem(R.id.multiple).isChecked = true - } - - when (uiStore.proxySort) { - ProxySort.Default -> findItem(R.id.default_).isChecked = true - ProxySort.Title -> findItem(R.id.name).isChecked = true - ProxySort.Delay -> findItem(R.id.delay).isChecked = true - } - - when (mode) { - null -> findItem(R.id.dont_modify).isChecked = true - TunnelState.Mode.Direct -> findItem(R.id.direct_mode).isChecked = true - TunnelState.Mode.Global -> findItem(R.id.global_mode).isChecked = true - TunnelState.Mode.Rule -> findItem(R.id.rule_mode).isChecked = true - TunnelState.Mode.Script -> throw IllegalStateException("invalid mode") - } - } - - menu.setOnMenuItemClickListener(this) - } -} \ No newline at end of file diff --git a/design/src/foss/res/menu/menu_proxy.xml b/design/src/foss/res/menu/menu_proxy.xml deleted file mode 100644 index aefb5f93..00000000 --- a/design/src/foss/res/menu/menu_proxy.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/design/src/foss/java/com/github/kr328/clash/design/HelpDesign.kt b/design/src/main/java/com/github/kr328/clash/design/HelpDesign.kt similarity index 70% rename from design/src/foss/java/com/github/kr328/clash/design/HelpDesign.kt rename to design/src/main/java/com/github/kr328/clash/design/HelpDesign.kt index 4522fc03..047eb3d1 100644 --- a/design/src/foss/java/com/github/kr328/clash/design/HelpDesign.kt +++ b/design/src/main/java/com/github/kr328/clash/design/HelpDesign.kt @@ -47,6 +47,17 @@ class HelpDesign( category(R.string.feedback) + 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))) + } + } + } + clickable( title = R.string.github_issues, summary = R.string.github_issues_url @@ -56,23 +67,25 @@ class HelpDesign( } } - category(R.string.sources) + 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_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))) + clickable( + title = R.string.clash_core, + summary = R.string.clash_core_url + ) { + clicked { + openLink(Uri.parse(context.getString(R.string.clash_core_url))) + } } } diff --git a/design/src/premium/java/com/github/kr328/clash/design/OverrideSettingsDesign.kt b/design/src/main/java/com/github/kr328/clash/design/OverrideSettingsDesign.kt similarity index 90% rename from design/src/premium/java/com/github/kr328/clash/design/OverrideSettingsDesign.kt rename to design/src/main/java/com/github/kr328/clash/design/OverrideSettingsDesign.kt index 6bfd597e..118744c5 100644 --- a/design/src/premium/java/com/github/kr328/clash/design/OverrideSettingsDesign.kt +++ b/design/src/main/java/com/github/kr328/clash/design/OverrideSettingsDesign.kt @@ -185,24 +185,43 @@ class OverrideSettingsDesign( empty = R.string.default_ ) - selectableList( - value = configuration::mode, - values = arrayOf( - null, - TunnelState.Mode.Direct, - TunnelState.Mode.Global, - TunnelState.Mode.Rule, - TunnelState.Mode.Script - ), - valuesText = arrayOf( - R.string.dont_modify, - R.string.direct_mode, - R.string.global_mode, - R.string.rule_mode, - R.string.script_mode - ), - title = R.string.mode - ) + if (BuildConfig.PREMIUM) { + selectableList( + value = configuration::mode, + values = arrayOf( + null, + TunnelState.Mode.Direct, + TunnelState.Mode.Global, + TunnelState.Mode.Rule, + TunnelState.Mode.Script + ), + valuesText = arrayOf( + R.string.dont_modify, + R.string.direct_mode, + R.string.global_mode, + R.string.rule_mode, + R.string.script_mode + ), + title = R.string.mode + ) + } else { + selectableList( + value = configuration::mode, + values = arrayOf( + null, + TunnelState.Mode.Direct, + TunnelState.Mode.Global, + TunnelState.Mode.Rule + ), + valuesText = arrayOf( + R.string.dont_modify, + R.string.direct_mode, + R.string.global_mode, + R.string.rule_mode + ), + title = R.string.mode + ) + } selectableList( value = configuration::logLevel, diff --git a/design/src/premium/java/com/github/kr328/clash/design/component/ProxyMenu.kt b/design/src/main/java/com/github/kr328/clash/design/component/ProxyMenu.kt similarity index 96% rename from design/src/premium/java/com/github/kr328/clash/design/component/ProxyMenu.kt rename to design/src/main/java/com/github/kr328/clash/design/component/ProxyMenu.kt index 89c81f40..bd05cdfc 100644 --- a/design/src/premium/java/com/github/kr328/clash/design/component/ProxyMenu.kt +++ b/design/src/main/java/com/github/kr328/clash/design/component/ProxyMenu.kt @@ -6,6 +6,7 @@ import android.view.View import androidx.appcompat.widget.PopupMenu import com.github.kr328.clash.core.model.ProxySort import com.github.kr328.clash.core.model.TunnelState +import com.github.kr328.clash.design.BuildConfig import com.github.kr328.clash.design.ProxyDesign import com.github.kr328.clash.design.R import com.github.kr328.clash.design.store.UiStore @@ -88,6 +89,8 @@ class ProxyMenu( menu.menuInflater.inflate(R.menu.menu_proxy, menu.menu) menu.menu.apply { + findItem(R.id.script_mode).isVisible = BuildConfig.PREMIUM + findItem(R.id.not_selectable).isChecked = uiStore.proxyExcludeNotSelectable if (uiStore.proxySingleLine) { diff --git a/design/src/premium/res/menu/menu_proxy.xml b/design/src/main/res/menu/menu_proxy.xml similarity index 100% rename from design/src/premium/res/menu/menu_proxy.xml rename to design/src/main/res/menu/menu_proxy.xml diff --git a/design/src/premium/java/com/github/kr328/clash/design/HelpDesign.kt b/design/src/premium/java/com/github/kr328/clash/design/HelpDesign.kt deleted file mode 100644 index d81ce885..00000000 --- a/design/src/premium/java/com/github/kr328/clash/design/HelpDesign.kt +++ /dev/null @@ -1,84 +0,0 @@ -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 -import com.github.kr328.clash.design.preference.preferenceScreen -import com.github.kr328.clash.design.preference.tips -import com.github.kr328.clash.design.util.applyFrom -import com.github.kr328.clash.design.util.bindAppBarElevation -import com.github.kr328.clash.design.util.layoutInflater -import com.github.kr328.clash.design.util.root - -class HelpDesign( - context: Context, - openLink: (Uri) -> Unit, -) : Design(context) { - private val binding = DesignSettingsCommonBinding - .inflate(context.layoutInflater, context.root, false) - - override val root: View - get() = binding.root - - init { - binding.surface = surface - - binding.activityBarLayout.applyFrom(context) - - binding.scrollRoot.bindAppBarElevation(binding.activityBarLayout) - - val screen = preferenceScreen(context) { - tips(R.string.tips_help) - - category(R.string.document) - - clickable( - title = R.string.clash_wiki, - summary = R.string.clash_wiki_url - ) { - clicked { - openLink(Uri.parse(context.getString(R.string.clash_wiki_url))) - } - } - - category(R.string.feedback) - - clickable( - title = R.string.github_issues, - summary = R.string.github_issues_url - ) { - clicked { - openLink(Uri.parse(context.getString(R.string.github_issues_url))) - } - } - - clickable( - title = R.string.google_play, - summary = R.string.google_play_url - ) { - clicked { - openLink(Uri.parse(context.getString(R.string.google_play_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))) - } - } - } - } - - binding.content.addView(screen.root) - } -} \ No newline at end of file