Add zh-rCN translate
This commit is contained in:
@@ -11,11 +11,13 @@ import android.net.wifi.WifiManager
|
||||
import android.os.PowerManager
|
||||
import androidx.core.content.getSystemService
|
||||
import go.Seq
|
||||
import io.nekohasekai.libbox.Libbox
|
||||
import io.nekohasekai.sfa.bg.AppChangeReceiver
|
||||
import io.nekohasekai.sfa.bg.UpdateProfileWork
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.Locale
|
||||
import io.nekohasekai.sfa.Application as BoxApplication
|
||||
|
||||
class Application : Application() {
|
||||
@@ -29,6 +31,7 @@ class Application : Application() {
|
||||
super.onCreate()
|
||||
|
||||
Seq.setContext(this)
|
||||
Libbox.setLocale(Locale.getDefault().toLanguageTag().replace("-", "_"))
|
||||
|
||||
@Suppress("OPT_IN_USAGE")
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
|
||||
@@ -1,11 +1,30 @@
|
||||
package io.nekohasekai.sfa.constant
|
||||
|
||||
import android.content.Context
|
||||
import io.nekohasekai.sfa.R
|
||||
|
||||
enum class EnabledType(val boolValue: Boolean) {
|
||||
Enabled(true), Disabled(false);
|
||||
|
||||
fun getString(context: Context): String {
|
||||
return when (this) {
|
||||
Enabled -> context.getString(R.string.enabled)
|
||||
Disabled -> context.getString(R.string.disabled)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
fun from(value: Boolean): EnabledType {
|
||||
return if (value) Enabled else Disabled
|
||||
}
|
||||
|
||||
fun valueOf(context: Context, value: String): EnabledType {
|
||||
return when (value) {
|
||||
context.getString(R.string.enabled) -> Enabled
|
||||
context.getString(R.string.disabled) -> Disabled
|
||||
else -> Disabled
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.nekohasekai.sfa.constant
|
||||
|
||||
import android.content.Context
|
||||
import io.nekohasekai.sfa.R
|
||||
import io.nekohasekai.sfa.database.Settings
|
||||
|
||||
enum class PerAppProxyUpdateType {
|
||||
@@ -11,6 +13,14 @@ enum class PerAppProxyUpdateType {
|
||||
Deselect -> Settings.PER_APP_PROXY_EXCLUDE
|
||||
}
|
||||
|
||||
fun getString(context: Context): String {
|
||||
return when (this) {
|
||||
Disabled -> context.getString(R.string.disabled)
|
||||
Select -> context.getString(R.string.action_select)
|
||||
Deselect -> context.getString(R.string.action_deselect)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun valueOf(value: Int): PerAppProxyUpdateType = when (value) {
|
||||
Settings.PER_APP_PROXY_DISABLED -> Disabled
|
||||
@@ -18,5 +28,14 @@ enum class PerAppProxyUpdateType {
|
||||
Settings.PER_APP_PROXY_EXCLUDE -> Deselect
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
fun valueOf(context: Context, value: String): PerAppProxyUpdateType {
|
||||
return when (value) {
|
||||
context.getString(R.string.disabled) -> Disabled
|
||||
context.getString(R.string.action_select) -> Select
|
||||
context.getString(R.string.action_deselect) -> Deselect
|
||||
else -> Disabled
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
package io.nekohasekai.sfa.database
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import androidx.room.TypeConverter
|
||||
import io.nekohasekai.sfa.R
|
||||
import io.nekohasekai.sfa.database.TypedProfile.Type.values
|
||||
import io.nekohasekai.sfa.ktx.marshall
|
||||
import io.nekohasekai.sfa.ktx.unmarshall
|
||||
import java.util.Date
|
||||
@@ -12,6 +15,13 @@ class TypedProfile() : Parcelable {
|
||||
enum class Type {
|
||||
Local, Remote;
|
||||
|
||||
fun getString(context: Context): String {
|
||||
return when (this) {
|
||||
Local -> context.getString(R.string.profile_type_local)
|
||||
Remote -> context.getString(R.string.profile_type_remote)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun valueOf(value: Int): Type {
|
||||
for (it in values()) {
|
||||
|
||||
@@ -69,7 +69,7 @@ class SettingsFragment : Fragment() {
|
||||
}
|
||||
binding.checkUpdateEnabled.addTextChangedListener {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val newValue = EnabledType.valueOf(it).boolValue
|
||||
val newValue = EnabledType.valueOf(requireContext(), it).boolValue
|
||||
Settings.checkUpdateEnabled = newValue
|
||||
}
|
||||
}
|
||||
@@ -81,13 +81,13 @@ class SettingsFragment : Fragment() {
|
||||
}
|
||||
binding.disableMemoryLimit.addTextChangedListener {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val newValue = EnabledType.valueOf(it).boolValue
|
||||
val newValue = EnabledType.valueOf(requireContext(), it).boolValue
|
||||
Settings.disableMemoryLimit = !newValue
|
||||
}
|
||||
}
|
||||
binding.dynamicNotificationEnabled.addTextChangedListener {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val newValue = EnabledType.valueOf(it).boolValue
|
||||
val newValue = EnabledType.valueOf(requireContext(), it).boolValue
|
||||
Settings.dynamicNotification = newValue
|
||||
}
|
||||
}
|
||||
@@ -136,12 +136,15 @@ class SettingsFragment : Fragment() {
|
||||
val dynamicNotification = Settings.dynamicNotification
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.dataSizeText.text = dataSize
|
||||
binding.checkUpdateEnabled.text = EnabledType.from(checkUpdateEnabled).name
|
||||
binding.checkUpdateEnabled.text =
|
||||
EnabledType.from(checkUpdateEnabled).getString(requireContext())
|
||||
binding.checkUpdateEnabled.setSimpleItems(R.array.enabled)
|
||||
binding.disableMemoryLimit.text = EnabledType.from(!Settings.disableMemoryLimit).name
|
||||
binding.disableMemoryLimit.text =
|
||||
EnabledType.from(!Settings.disableMemoryLimit).getString(requireContext())
|
||||
binding.disableMemoryLimit.setSimpleItems(R.array.enabled)
|
||||
binding.backgroundPermissionCard.isGone = removeBackgroundPermissionPage
|
||||
binding.dynamicNotificationEnabled.text = EnabledType.from(dynamicNotification).name
|
||||
binding.dynamicNotificationEnabled.text =
|
||||
EnabledType.from(dynamicNotification).getString(requireContext())
|
||||
binding.dynamicNotificationEnabled.setSimpleItems(R.array.enabled)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ class EditProfileActivity : AbstractActivity<ActivityEditProfileBinding>() {
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.type.text = profile.typed.type.name
|
||||
binding.type.text = profile.typed.type.getString(this@EditProfileActivity)
|
||||
binding.editButton.setOnClickListener {
|
||||
startActivity(
|
||||
Intent(
|
||||
@@ -89,7 +89,8 @@ class EditProfileActivity : AbstractActivity<ActivityEditProfileBinding>() {
|
||||
binding.remoteURL.text = profile.typed.remoteURL
|
||||
binding.lastUpdated.text =
|
||||
DateFormat.getDateTimeInstance().format(profile.typed.lastUpdated)
|
||||
binding.autoUpdate.text = EnabledType.from(profile.typed.autoUpdate).name
|
||||
binding.autoUpdate.text = EnabledType.from(profile.typed.autoUpdate)
|
||||
.getString(this@EditProfileActivity)
|
||||
binding.autoUpdate.setSimpleItems(R.array.enabled)
|
||||
binding.autoUpdateInterval.isVisible = profile.typed.autoUpdate
|
||||
binding.autoUpdateInterval.text = profile.typed.autoUpdateInterval.toString()
|
||||
@@ -111,7 +112,7 @@ class EditProfileActivity : AbstractActivity<ActivityEditProfileBinding>() {
|
||||
}
|
||||
|
||||
private fun updateAutoUpdate(newValue: String) {
|
||||
val boolValue = EnabledType.valueOf(newValue).boolValue
|
||||
val boolValue = EnabledType.valueOf(this, newValue).boolValue
|
||||
if (profile.typed.autoUpdate == boolValue) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package io.nekohasekai.sfa.ui.profile
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import io.nekohasekai.libbox.Libbox
|
||||
@@ -29,9 +31,13 @@ import java.io.InputStream
|
||||
import java.util.Date
|
||||
|
||||
class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
|
||||
enum class FileSource(val formatted: String) {
|
||||
CreateNew("Create New"),
|
||||
Import("Import");
|
||||
enum class FileSource(@StringRes val formattedRes: Int) {
|
||||
CreateNew(R.string.profile_source_create_new),
|
||||
Import(R.string.profile_source_import);
|
||||
|
||||
fun formatted(context: Context): String {
|
||||
return context.getString(formattedRes)
|
||||
}
|
||||
}
|
||||
|
||||
private val importFile =
|
||||
@@ -49,7 +55,7 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
|
||||
intent.getStringExtra("importName")?.also { importName ->
|
||||
intent.getStringExtra("importURL")?.also { importURL ->
|
||||
binding.name.editText?.setText(importName)
|
||||
binding.type.text = TypedProfile.Type.Remote.name
|
||||
binding.type.text = TypedProfile.Type.Remote.getString(this)
|
||||
binding.remoteURL.editText?.setText(importURL)
|
||||
binding.localFields.isVisible = false
|
||||
binding.remoteFields.isVisible = true
|
||||
@@ -60,12 +66,12 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
|
||||
binding.name.removeErrorIfNotEmpty()
|
||||
binding.type.addTextChangedListener {
|
||||
when (it) {
|
||||
TypedProfile.Type.Local.name -> {
|
||||
TypedProfile.Type.Local.getString(this) -> {
|
||||
binding.localFields.isVisible = true
|
||||
binding.remoteFields.isVisible = false
|
||||
}
|
||||
|
||||
TypedProfile.Type.Remote.name -> {
|
||||
TypedProfile.Type.Remote.getString(this) -> {
|
||||
binding.localFields.isVisible = false
|
||||
binding.remoteFields.isVisible = true
|
||||
if (binding.autoUpdateInterval.text.toIntOrNull() == null) {
|
||||
@@ -76,12 +82,12 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
|
||||
}
|
||||
binding.fileSourceMenu.addTextChangedListener {
|
||||
when (it) {
|
||||
FileSource.CreateNew.formatted -> {
|
||||
FileSource.CreateNew.formatted(this) -> {
|
||||
binding.importFileButton.isVisible = false
|
||||
binding.sourceURL.isVisible = false
|
||||
}
|
||||
|
||||
FileSource.Import.formatted -> {
|
||||
FileSource.Import.formatted(this) -> {
|
||||
binding.importFileButton.isVisible = true
|
||||
binding.sourceURL.isVisible = true
|
||||
}
|
||||
@@ -99,9 +105,9 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
|
||||
return
|
||||
}
|
||||
when (binding.type.text) {
|
||||
TypedProfile.Type.Local.name -> {
|
||||
TypedProfile.Type.Local.getString(this) -> {
|
||||
when (binding.fileSourceMenu.text) {
|
||||
FileSource.Import.formatted -> {
|
||||
FileSource.Import.formatted(this) -> {
|
||||
if (binding.sourceURL.showErrorIfEmpty()) {
|
||||
return
|
||||
}
|
||||
@@ -109,7 +115,7 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
|
||||
}
|
||||
}
|
||||
|
||||
TypedProfile.Type.Remote.name -> {
|
||||
TypedProfile.Type.Remote.getString(this) -> {
|
||||
if (binding.remoteURL.showErrorIfEmpty()) {
|
||||
return
|
||||
}
|
||||
@@ -138,15 +144,15 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
|
||||
typedProfile.path = configFile.path
|
||||
|
||||
when (binding.type.text) {
|
||||
TypedProfile.Type.Local.name -> {
|
||||
TypedProfile.Type.Local.getString(this) -> {
|
||||
typedProfile.type = TypedProfile.Type.Local
|
||||
|
||||
when (binding.fileSourceMenu.text) {
|
||||
FileSource.CreateNew.formatted -> {
|
||||
FileSource.CreateNew.formatted(this) -> {
|
||||
configFile.writeText("{}")
|
||||
}
|
||||
|
||||
FileSource.Import.formatted -> {
|
||||
FileSource.Import.formatted(this) -> {
|
||||
val sourceURL = binding.sourceURL.text
|
||||
val content = if (sourceURL.startsWith("content://")) {
|
||||
val inputStream =
|
||||
@@ -165,7 +171,7 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
|
||||
}
|
||||
}
|
||||
|
||||
TypedProfile.Type.Remote.name -> {
|
||||
TypedProfile.Type.Remote.getString(this) -> {
|
||||
typedProfile.type = TypedProfile.Type.Remote
|
||||
val remoteURL = binding.remoteURL.text
|
||||
val content = HTTPClient().use { it.getString(remoteURL) }
|
||||
@@ -173,7 +179,8 @@ class NewProfileActivity : AbstractActivity<ActivityAddProfileBinding>() {
|
||||
configFile.writeText(content)
|
||||
typedProfile.remoteURL = remoteURL
|
||||
typedProfile.lastUpdated = Date()
|
||||
typedProfile.autoUpdate = EnabledType.valueOf(binding.autoUpdate.text).boolValue
|
||||
typedProfile.autoUpdate =
|
||||
EnabledType.valueOf(this, binding.autoUpdate.text).boolValue
|
||||
binding.autoUpdateInterval.text.toIntOrNull()?.also {
|
||||
typedProfile.autoUpdateInterval = it
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ class PerAppProxyActivity : AbstractActivity<ActivityPerAppProxyBinding>() {
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
menuInflater.inflate(R.menu.per_app_menu0, menu)
|
||||
menuInflater.inflate(R.menu.per_app_menu, menu)
|
||||
|
||||
if (menu != null) {
|
||||
val searchView = menu.findItem(R.id.action_search).actionView as SearchView
|
||||
|
||||
@@ -33,7 +33,8 @@ class ProfileOverrideActivity :
|
||||
|
||||
binding.perAppProxyUpdateOnChange.addTextChangedListener {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
Settings.perAppProxyUpdateOnChange = PerAppProxyUpdateType.valueOf(it).value()
|
||||
Settings.perAppProxyUpdateOnChange =
|
||||
PerAppProxyUpdateType.valueOf(this@ProfileOverrideActivity, it).value()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +50,8 @@ class ProfileOverrideActivity :
|
||||
val perAppUpdateOnChange = Settings.perAppProxyUpdateOnChange
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.perAppProxyUpdateOnChange.text =
|
||||
PerAppProxyUpdateType.valueOf(perAppUpdateOnChange).name
|
||||
PerAppProxyUpdateType.valueOf(perAppUpdateOnChange)
|
||||
.getString(this@ProfileOverrideActivity)
|
||||
binding.perAppProxyUpdateOnChange.setSimpleItems(R.array.per_app_proxy_update_on_change_value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.nekohasekai.libbox.Libbox
|
||||
import io.nekohasekai.sfa.BuildConfig
|
||||
import io.nekohasekai.sfa.ktx.unwrap
|
||||
import java.io.Closeable
|
||||
import java.util.Locale
|
||||
|
||||
class HTTPClient : Closeable {
|
||||
|
||||
@@ -15,6 +16,8 @@ class HTTPClient : Closeable {
|
||||
userAgent += BuildConfig.VERSION_CODE
|
||||
userAgent += "; sing-box "
|
||||
userAgent += Libbox.version()
|
||||
userAgent += "; language "
|
||||
userAgent += Locale.getDefault().toLanguageTag().replace("-", "_")
|
||||
userAgent += ")"
|
||||
userAgent
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user