mirror of
https://github.com/openlibrecommunity/olcng.git
synced 2026-07-03 14:05:17 +02:00
Enable double column display
The profile list is displayed in double columns, allowing more content to be displayed on the screen. You need to restart the application to take effect.
This commit is contained in:
@@ -42,6 +42,7 @@ object AppConfig {
|
||||
const val PREF_SPEED_ENABLED = "pref_speed_enabled"
|
||||
const val PREF_CONFIRM_REMOVE = "pref_confirm_remove"
|
||||
const val PREF_START_SCAN_IMMEDIATE = "pref_start_scan_immediate"
|
||||
const val PREF_DOUBLE_COLUMN_DISPLAY = "pref_double_column_display"
|
||||
const val PREF_LANGUAGE = "pref_language"
|
||||
const val PREF_UI_MODE_NIGHT = "pref_ui_mode_night"
|
||||
const val PREF_PREFER_IPV6 = "pref_prefer_ipv6"
|
||||
|
||||
@@ -21,8 +21,8 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.GravityCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.navigation.NavigationView
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.v2ray.ang.AppConfig
|
||||
@@ -162,7 +162,11 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
}
|
||||
|
||||
binding.recyclerView.setHasFixedSize(true)
|
||||
binding.recyclerView.layoutManager = LinearLayoutManager(this)
|
||||
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_DOUBLE_COLUMN_DISPLAY, false)) {
|
||||
binding.recyclerView.layoutManager = GridLayoutManager(this, 2)
|
||||
} else {
|
||||
binding.recyclerView.layoutManager = GridLayoutManager(this, 1)
|
||||
}
|
||||
addCustomDividerToRecyclerView(binding.recyclerView, this, R.drawable.custom_divider)
|
||||
binding.recyclerView.adapter = adapter
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.helper.ItemTouchHelperAdapter
|
||||
import com.v2ray.ang.helper.ItemTouchHelperViewHolder
|
||||
import com.v2ray.ang.service.V2RayServiceManager
|
||||
import com.v2ray.ang.util.Utils
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -38,7 +37,11 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
|
||||
private val share_method: Array<out String> by lazy {
|
||||
mActivity.resources.getStringArray(R.array.share_method)
|
||||
}
|
||||
private val share_method_more: Array<out String> by lazy {
|
||||
mActivity.resources.getStringArray(R.array.share_method_more)
|
||||
}
|
||||
var isRunning = false
|
||||
private val doubleColumnDisplay = MmkvManager.decodeSettingsBool(AppConfig.PREF_DOUBLE_COLUMN_DISPLAY, false)
|
||||
|
||||
override fun getItemCount() = mActivity.mainViewModel.serversCache.size + 1
|
||||
|
||||
@@ -46,109 +49,115 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
|
||||
if (holder is MainViewHolder) {
|
||||
val guid = mActivity.mainViewModel.serversCache[position].guid
|
||||
val profile = mActivity.mainViewModel.serversCache[position].profile
|
||||
// //filter
|
||||
// if (mActivity.mainViewModel.subscriptionId.isNotEmpty()
|
||||
// && mActivity.mainViewModel.subscriptionId != config.subscriptionId
|
||||
// ) {
|
||||
// holder.itemMainBinding.cardView.visibility = View.GONE
|
||||
// } else {
|
||||
// holder.itemMainBinding.cardView.visibility = View.VISIBLE
|
||||
// }
|
||||
val isCustom = profile.configType == EConfigType.CUSTOM
|
||||
|
||||
val aff = MmkvManager.decodeServerAffiliationInfo(guid)
|
||||
|
||||
holder.itemMainBinding.tvName.text = profile.remarks
|
||||
holder.itemView.setBackgroundColor(Color.TRANSPARENT)
|
||||
|
||||
//Name address
|
||||
holder.itemMainBinding.tvName.text = profile.remarks
|
||||
holder.itemMainBinding.tvStatistics.text = getAddress(profile)
|
||||
holder.itemMainBinding.tvType.text = profile.configType.name
|
||||
|
||||
//TestResult
|
||||
val aff = MmkvManager.decodeServerAffiliationInfo(guid)
|
||||
holder.itemMainBinding.tvTestResult.text = aff?.getTestDelayString().orEmpty()
|
||||
if ((aff?.testDelayMillis ?: 0L) < 0L) {
|
||||
holder.itemMainBinding.tvTestResult.setTextColor(ContextCompat.getColor(mActivity, R.color.colorPingRed))
|
||||
} else {
|
||||
holder.itemMainBinding.tvTestResult.setTextColor(ContextCompat.getColor(mActivity, R.color.colorPing))
|
||||
}
|
||||
|
||||
//layoutIndicator
|
||||
if (guid == MmkvManager.getSelectServer()) {
|
||||
holder.itemMainBinding.layoutIndicator.setBackgroundResource(R.color.colorAccent)
|
||||
} else {
|
||||
holder.itemMainBinding.layoutIndicator.setBackgroundResource(0)
|
||||
}
|
||||
holder.itemMainBinding.tvSubscription.text =
|
||||
if (mActivity.mainViewModel.subscriptionId.isEmpty())
|
||||
MmkvManager.decodeSubscription(profile.subscriptionId)?.remarks.orEmpty()
|
||||
else
|
||||
""
|
||||
|
||||
var shareOptions = share_method.asList()
|
||||
when (profile.configType) {
|
||||
EConfigType.CUSTOM -> {
|
||||
holder.itemMainBinding.tvType.text = mActivity.getString(R.string.server_customize_config)
|
||||
shareOptions = shareOptions.takeLast(1)
|
||||
//subscription remarks
|
||||
val subRemarks = getSubscriptionRemarks(profile)
|
||||
holder.itemMainBinding.tvSubscription.text = subRemarks
|
||||
holder.itemMainBinding.layoutSubscription.visibility = if (subRemarks.isEmpty()) View.GONE else View.VISIBLE
|
||||
|
||||
//layout
|
||||
if (doubleColumnDisplay) {
|
||||
holder.itemMainBinding.layoutShare.visibility = View.GONE
|
||||
holder.itemMainBinding.layoutEdit.visibility = View.GONE
|
||||
holder.itemMainBinding.layoutRemove.visibility = View.GONE
|
||||
holder.itemMainBinding.layoutMore.visibility = View.VISIBLE
|
||||
|
||||
//share method
|
||||
val shareOptions = if (isCustom) share_method_more.asList().takeLast(3) else share_method_more.asList()
|
||||
|
||||
holder.itemMainBinding.layoutMore.setOnClickListener {
|
||||
shareServer(guid, profile, position, shareOptions, if (isCustom) 2 else 0)
|
||||
}
|
||||
} else {
|
||||
holder.itemMainBinding.layoutShare.visibility = View.VISIBLE
|
||||
holder.itemMainBinding.layoutEdit.visibility = View.VISIBLE
|
||||
holder.itemMainBinding.layoutRemove.visibility = View.VISIBLE
|
||||
holder.itemMainBinding.layoutMore.visibility = View.GONE
|
||||
|
||||
//share method
|
||||
val shareOptions = if (isCustom) share_method.asList().takeLast(1) else share_method.asList()
|
||||
|
||||
holder.itemMainBinding.layoutShare.setOnClickListener {
|
||||
shareServer(guid, profile, position, shareOptions, if (isCustom) 2 else 0)
|
||||
}
|
||||
|
||||
else -> {
|
||||
holder.itemMainBinding.tvType.text = profile.configType.name
|
||||
holder.itemMainBinding.layoutEdit.setOnClickListener {
|
||||
editServer(guid, profile)
|
||||
}
|
||||
}
|
||||
|
||||
// Hide xxx:xxx:***/xxx.xxx.xxx.***
|
||||
val strState = "${
|
||||
profile.server?.let {
|
||||
if (it.contains(":"))
|
||||
it.split(":").take(2).joinToString(":", postfix = ":***")
|
||||
else
|
||||
it.split('.').dropLast(1).joinToString(".", postfix = ".***")
|
||||
holder.itemMainBinding.layoutRemove.setOnClickListener {
|
||||
removeServer(guid, position)
|
||||
}
|
||||
} : ${profile.serverPort}"
|
||||
|
||||
holder.itemMainBinding.tvStatistics.text = strState
|
||||
|
||||
holder.itemMainBinding.layoutShare.setOnClickListener {
|
||||
shareServer(guid, profile, shareOptions)
|
||||
}
|
||||
|
||||
holder.itemMainBinding.layoutEdit.setOnClickListener {
|
||||
editServer(guid, profile)
|
||||
}
|
||||
holder.itemMainBinding.layoutRemove.setOnClickListener {
|
||||
removeServer(guid, position)
|
||||
}
|
||||
|
||||
holder.itemMainBinding.infoContainer.setOnClickListener {
|
||||
setSelectServer(guid)
|
||||
}
|
||||
}
|
||||
if (holder is FooterViewHolder) {
|
||||
if (true) {
|
||||
holder.itemFooterBinding.layoutEdit.visibility = View.INVISIBLE
|
||||
} else {
|
||||
holder.itemFooterBinding.layoutEdit.setOnClickListener {
|
||||
Utils.openUri(mActivity, "${Utils.decode(AppConfig.PromotionUrl)}?t=${System.currentTimeMillis()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (holder is FooterViewHolder) {
|
||||
// if (true) {
|
||||
// holder.itemFooterBinding.layoutEdit.visibility = View.INVISIBLE
|
||||
// } else {
|
||||
// holder.itemFooterBinding.layoutEdit.setOnClickListener {
|
||||
// Utils.openUri(mActivity, "${Utils.decode(AppConfig.PromotionUrl)}?t=${System.currentTimeMillis()}")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private fun shareServer(guid: String, profile: ProfileItem, shareOptions: List<String>) {
|
||||
private fun getAddress(profile: ProfileItem): String {
|
||||
// Hide xxx:xxx:***/xxx.xxx.xxx.***
|
||||
return "${
|
||||
profile.server?.let {
|
||||
if (it.contains(":"))
|
||||
it.split(":").take(2).joinToString(":", postfix = ":***")
|
||||
else
|
||||
it.split('.').dropLast(1).joinToString(".", postfix = ".***")
|
||||
}
|
||||
} : ${profile.serverPort}"
|
||||
}
|
||||
|
||||
private fun getSubscriptionRemarks(profile: ProfileItem): String {
|
||||
val subRemarks =
|
||||
if (mActivity.mainViewModel.subscriptionId.isEmpty())
|
||||
MmkvManager.decodeSubscription(profile.subscriptionId)?.remarks?.firstOrNull()
|
||||
else
|
||||
null
|
||||
return subRemarks?.toString() ?: ""
|
||||
}
|
||||
|
||||
private fun shareServer(guid: String, profile: ProfileItem, position: Int, shareOptions: List<String>, skip: Int) {
|
||||
AlertDialog.Builder(mActivity).setItems(shareOptions.toTypedArray()) { _, i ->
|
||||
try {
|
||||
when (i) {
|
||||
0 -> {
|
||||
if (profile.configType == EConfigType.CUSTOM) {
|
||||
shareFullContent(guid)
|
||||
} else {
|
||||
val ivBinding = ItemQrcodeBinding.inflate(LayoutInflater.from(mActivity))
|
||||
ivBinding.ivQcode.setImageBitmap(AngConfigManager.share2QRCode(guid))
|
||||
AlertDialog.Builder(mActivity).setView(ivBinding.root).show()
|
||||
}
|
||||
}
|
||||
|
||||
1 -> {
|
||||
if (AngConfigManager.share2Clipboard(mActivity, guid) == 0) {
|
||||
mActivity.toast(R.string.toast_success)
|
||||
} else {
|
||||
mActivity.toast(R.string.toast_failure)
|
||||
}
|
||||
}
|
||||
|
||||
when (i + skip) {
|
||||
0 -> showQRCode(guid)
|
||||
1 -> share2Clipboard(guid)
|
||||
2 -> shareFullContent(guid)
|
||||
3 -> editServer(guid, profile)
|
||||
4 -> removeServer(guid, position)
|
||||
else -> mActivity.toast("else")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
@@ -157,6 +166,20 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
|
||||
}.show()
|
||||
}
|
||||
|
||||
private fun showQRCode(guid: String) {
|
||||
val ivBinding = ItemQrcodeBinding.inflate(LayoutInflater.from(mActivity))
|
||||
ivBinding.ivQcode.setImageBitmap(AngConfigManager.share2QRCode(guid))
|
||||
AlertDialog.Builder(mActivity).setView(ivBinding.root).show()
|
||||
}
|
||||
|
||||
private fun share2Clipboard(guid: String) {
|
||||
if (AngConfigManager.share2Clipboard(mActivity, guid) == 0) {
|
||||
mActivity.toast(R.string.toast_success)
|
||||
} else {
|
||||
mActivity.toast(R.string.toast_failure)
|
||||
}
|
||||
}
|
||||
|
||||
private fun shareFullContent(guid: String) {
|
||||
if (AngConfigManager.shareFullContent2Clipboard(mActivity, guid) == 0) {
|
||||
mActivity.toast(R.string.toast_success)
|
||||
|
||||
@@ -238,6 +238,7 @@ class SettingsActivity : BaseActivity() {
|
||||
AppConfig.PREF_SPEED_ENABLED,
|
||||
AppConfig.PREF_CONFIRM_REMOVE,
|
||||
AppConfig.PREF_START_SCAN_IMMEDIATE,
|
||||
AppConfig.PREF_DOUBLE_COLUMN_DISPLAY,
|
||||
AppConfig.PREF_PREFER_IPV6,
|
||||
AppConfig.PREF_PROXY_SHARING,
|
||||
AppConfig.PREF_ALLOW_INSECURE
|
||||
|
||||
@@ -55,6 +55,8 @@ class SubSettingRecyclerAdapter(val activity: SubSettingActivity) : RecyclerView
|
||||
holder.itemSubSettingBinding.layoutShare.visibility = View.INVISIBLE
|
||||
holder.itemSubSettingBinding.chkEnable.visibility = View.INVISIBLE
|
||||
} else {
|
||||
holder.itemSubSettingBinding.layoutShare.visibility = View.VISIBLE
|
||||
holder.itemSubSettingBinding.chkEnable.visibility = View.VISIBLE
|
||||
holder.itemSubSettingBinding.layoutShare.setOnClickListener {
|
||||
AlertDialog.Builder(mActivity)
|
||||
.setItems(share_method.asList().toTypedArray()) { _, i ->
|
||||
|
||||
@@ -73,6 +73,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
|
||||
AppConfig.PREF_BYPASS_APPS,
|
||||
AppConfig.PREF_CONFIRM_REMOVE,
|
||||
AppConfig.PREF_START_SCAN_IMMEDIATE,
|
||||
AppConfig.PREF_DOUBLE_COLUMN_DISPLAY,
|
||||
AppConfig.SUBSCRIPTION_AUTO_UPDATE,
|
||||
AppConfig.PREF_FRAGMENT_ENABLED,
|
||||
AppConfig.PREF_MUX_ENABLED,
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z" />
|
||||
|
||||
</vector>
|
||||
@@ -0,0 +1,7 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="@color/divider_color_light" />
|
||||
<size
|
||||
android:width="48dp"
|
||||
android:height="48dp"/>
|
||||
</shape>
|
||||
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z" />
|
||||
|
||||
</vector>
|
||||
@@ -83,7 +83,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scrollbars="vertical"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
tools:context=".ui.PerAppProxyActivity" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -11,6 +11,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:visibility="invisible"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/padding_spacing_dp16">
|
||||
|
||||
|
||||
@@ -19,154 +19,186 @@
|
||||
android:nextFocusRight="@+id/layout_share"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="@dimen/padding_spacing_dp8"
|
||||
android:paddingEnd="@dimen/padding_spacing_dp8"
|
||||
android:paddingEnd="@dimen/padding_spacing_dp4"
|
||||
android:paddingStart="@dimen/padding_spacing_dp4"
|
||||
android:paddingBottom="@dimen/padding_spacing_dp8">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_indicator"
|
||||
android:layout_width="6dp"
|
||||
android:layout_width="@dimen/padding_spacing_dp4"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/padding_spacing_dp8"
|
||||
android:paddingEnd="@dimen/padding_spacing_dp8">
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:minLines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_statistics"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:lines="1"
|
||||
android:paddingTop="@dimen/padding_spacing_dp8"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_type"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:lines="1"
|
||||
android:paddingTop="@dimen/padding_spacing_dp8"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="@color/colorConfigType"
|
||||
android:textSize="11sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingEnd="@dimen/padding_spacing_dp8"
|
||||
android:paddingStart="@dimen/padding_spacing_dp8">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_subscription"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:lines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="@color/color_secondary"
|
||||
android:textSize="11sp"
|
||||
tools:text="Sub" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_share"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:nextFocusLeft="@+id/info_container"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/padding_spacing_dp8">
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/image_size_dp24"
|
||||
app:srcCompat="@drawable/ic_share_24dp" />
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/padding_spacing_dp8">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:minLines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="@dimen/padding_spacing_dp8">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/layout_subscription"
|
||||
android:layout_width="@dimen/image_size_dp24"
|
||||
android:layout_height="@dimen/image_size_dp24"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginEnd="@dimen/padding_spacing_dp4"
|
||||
android:background="@drawable/ic_circle">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_subscription"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textSize="11sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_statistics"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:lines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_edit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/padding_spacing_dp8">
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/image_size_dp24"
|
||||
android:layout_height="@dimen/image_size_dp24"
|
||||
app:srcCompat="@drawable/ic_edit_24dp" />
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_share"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:nextFocusLeft="@+id/info_container"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/padding_spacing_dp8">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/image_size_dp24"
|
||||
app:srcCompat="@drawable/ic_share_24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_edit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/padding_spacing_dp8">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/image_size_dp24"
|
||||
android:layout_height="@dimen/image_size_dp24"
|
||||
app:srcCompat="@drawable/ic_edit_24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_remove"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/padding_spacing_dp8">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/image_size_dp24"
|
||||
android:layout_height="@dimen/image_size_dp24"
|
||||
app:srcCompat="@drawable/ic_delete_24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_more"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/padding_spacing_dp8">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/image_size_dp24"
|
||||
android:layout_height="@dimen/image_size_dp24"
|
||||
app:srcCompat="@drawable/ic_more_vert_24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_remove"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/padding_spacing_dp8">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/image_size_dp24"
|
||||
android:layout_height="@dimen/image_size_dp24"
|
||||
app:srcCompat="@drawable/ic_delete_24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:orientation="vertical">
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/padding_spacing_dp8"
|
||||
android:paddingTop="@dimen/padding_spacing_dp8"
|
||||
android:paddingEnd="@dimen/padding_spacing_dp8">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_type"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:lines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="@color/colorConfigType"
|
||||
android:textSize="11sp"
|
||||
tools:text="VLESS" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_test_result"
|
||||
@@ -181,6 +213,7 @@
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -216,6 +216,9 @@
|
||||
<string name="title_pref_append_http_proxy">Append HTTP Proxy to VPN</string>
|
||||
<string name="summary_pref_append_http_proxy">HTTP proxy will be used directly from (browser/ some supported apps), without going through the virtual NIC device (Android 10+)</string>
|
||||
|
||||
<string name="title_pref_double_column_display">Enable double column display</string>
|
||||
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen. You need to restart the application to take effect.</string>
|
||||
|
||||
<!-- AboutActivity -->
|
||||
<string name="title_pref_feedback">ملاحظات</string>
|
||||
<string name="summary_pref_feedback">ملاحظات التحسينات أو الأخطاء إلى GitHub</string>
|
||||
@@ -317,6 +320,14 @@
|
||||
<item>تصدير التكوين الكامل إلى الحافظة</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_method_more">
|
||||
<item>QRcode</item>
|
||||
<item>Export to clipboard</item>
|
||||
<item>Export full configuration to clipboard</item>
|
||||
<item>Edit</item>
|
||||
<item>Delete</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_sub_method">
|
||||
<item>رمز استجابة سريعة (QRcode)</item>
|
||||
<item>تصدير إلى الحافظة</item>
|
||||
|
||||
@@ -216,6 +216,9 @@
|
||||
<string name="title_pref_append_http_proxy">Append HTTP Proxy to VPN</string>
|
||||
<string name="summary_pref_append_http_proxy">HTTP proxy will be used directly from (browser/ some supported apps), without going through the virtual NIC device (Android 10+)</string>
|
||||
|
||||
<string name="title_pref_double_column_display">Enable double column display</string>
|
||||
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen. You need to restart the application to take effect.</string>
|
||||
|
||||
<!-- AboutActivity -->
|
||||
<string name="title_pref_feedback">মতামত</string>
|
||||
<string name="summary_pref_feedback">মতামত উন্নয়ন বা বাগগুলি GitHub-এ পাঠান</string>
|
||||
@@ -309,12 +312,21 @@
|
||||
<string name="title_pref_fragment_length">ফ্র্যাগমেন্ট দৈর্ঘ্য (ন্যূনতম-সর্বাধিক)</string>
|
||||
<string name="title_pref_fragment_interval">ফ্র্যাগমেন্ট ইন্টারভ্যাল (ন্যূনতম-সর্বাধিক)</string>
|
||||
<string name="title_pref_fragment_enabled">ফ্র্যাগমেন্ট সক্রিয় করুন</string>
|
||||
|
||||
<string-array name="share_method">
|
||||
<item>QR কোড</item>
|
||||
<item>ক্লিপবোর্ডে রপ্তানি করুন</item>
|
||||
<item>পূর্ণ কনফিগারেশন ক্লিপবোর্ডে রপ্তানি করুন</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_method_more">
|
||||
<item>QRcode</item>
|
||||
<item>Export to clipboard</item>
|
||||
<item>Export full configuration to clipboard</item>
|
||||
<item>Edit</item>
|
||||
<item>Delete</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_sub_method">
|
||||
<item>QR কোড</item>
|
||||
<item>ক্লিপবোর্ডে রপ্তানি করুন</item>
|
||||
|
||||
@@ -216,6 +216,9 @@
|
||||
<string name="title_pref_append_http_proxy">پروکسی HTTP ن و VPN ازاف کۊنین</string>
|
||||
<string name="summary_pref_append_http_proxy">پروکسی HTTP ن موسقیمن ز (مۊرۊرگر/ی قرد ز برنومیل لادراری بیڌه)، بؽ استفاڌه ز دسگا NIC مجازی (Android 10+) استفاڌه ابۊ.</string>
|
||||
|
||||
<string name="title_pref_double_column_display">Enable double column display</string>
|
||||
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen. You need to restart the application to take effect.</string>
|
||||
|
||||
<!-- AboutActivity -->
|
||||
<string name="title_pref_feedback">فشناڌن منشڌ</string>
|
||||
<string name="summary_pref_feedback">فشناڌن منشڌ یا داسوو موشکلا من Github</string>
|
||||
@@ -325,6 +328,14 @@
|
||||
<item>و در کشیڌن پوی کانفیگ من کلیپ بورد</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_method_more">
|
||||
<item>QRcode</item>
|
||||
<item>Export to clipboard</item>
|
||||
<item>Export full configuration to clipboard</item>
|
||||
<item>Edit</item>
|
||||
<item>Delete</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_sub_method">
|
||||
<item>QRcode</item>
|
||||
<item>و در کشیڌن من کلیپ بورد</item>
|
||||
|
||||
@@ -214,6 +214,9 @@
|
||||
<string name="title_pref_append_http_proxy">پروکسی HTTP را به VPN اضافه کنید</string>
|
||||
<string name="summary_pref_append_http_proxy">پروکسی HTTP مستقیماً از (مرورگر/برخی برنامههای پشتیبانیشده)، بدون استفاده از دستگاه NIC مجازی (Android 10+) استفاده میشود.</string>
|
||||
|
||||
<string name="title_pref_double_column_display">Enable double column display</string>
|
||||
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen. You need to restart the application to take effect.</string>
|
||||
|
||||
<!-- AboutActivity -->
|
||||
<string name="title_pref_feedback">بازخورد</string>
|
||||
<string name="summary_pref_feedback">بازخورد یا گزارش اشکالات در گیت هاب</string>
|
||||
@@ -315,12 +318,21 @@
|
||||
<string name="title_pref_fragment_length">طول بسته های فرگمنت (حداقل-حداکثر)</string>
|
||||
<string name="title_pref_fragment_interval">فاصله بین بسته های فرگمنت (حداقل-حداکثر)</string>
|
||||
<string name="title_pref_fragment_enabled">فعال کردن فرگمنت</string>
|
||||
|
||||
<string-array name="share_method">
|
||||
<item>QRcode</item>
|
||||
<item>خروجی گرفتن در کلیپ بورد</item>
|
||||
<item>خروجی گرفتن کانفیگ کامل در کلیپ بورد</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_method_more">
|
||||
<item>QRcode</item>
|
||||
<item>Export to clipboard</item>
|
||||
<item>Export full configuration to clipboard</item>
|
||||
<item>Edit</item>
|
||||
<item>Delete</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_sub_method">
|
||||
<item>QRcode</item>
|
||||
<item>خروجی گرفتن در کلیپ بورد</item>
|
||||
|
||||
@@ -215,6 +215,9 @@
|
||||
<string name="title_pref_append_http_proxy">Дополнительный HTTP-прокси</string>
|
||||
<string name="summary_pref_append_http_proxy">HTTP-прокси будет использоваться напрямую (из браузера и других поддерживающих приложений), минуя виртуальный сетевой адаптер (Android 10+)</string>
|
||||
|
||||
<string name="title_pref_double_column_display">Enable double column display</string>
|
||||
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen. You need to restart the application to take effect.</string>
|
||||
|
||||
<!-- AboutActivity -->
|
||||
<string name="title_pref_feedback">Обратная связь</string>
|
||||
<string name="summary_pref_feedback">Предложить улучшение или сообщить об ошибке на GitHub</string>
|
||||
@@ -324,6 +327,14 @@
|
||||
<item>Экспорт всей конфигурации в буфер обмена</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_method_more">
|
||||
<item>QRcode</item>
|
||||
<item>Export to clipboard</item>
|
||||
<item>Export full configuration to clipboard</item>
|
||||
<item>Edit</item>
|
||||
<item>Delete</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_sub_method">
|
||||
<item>QR-код</item>
|
||||
<item>Экспорт в буфер обмена</item>
|
||||
|
||||
@@ -216,6 +216,9 @@
|
||||
<string name="title_pref_append_http_proxy">Append HTTP Proxy to VPN</string>
|
||||
<string name="summary_pref_append_http_proxy">HTTP proxy will be used directly from (browser/ some supported apps), without going through the virtual NIC device (Android 10+)</string>
|
||||
|
||||
<string name="title_pref_double_column_display">Enable double column display</string>
|
||||
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen. You need to restart the application to take effect.</string>
|
||||
|
||||
<!-- AboutActivity -->
|
||||
<string name="title_pref_feedback">Phản hồi lỗi</string>
|
||||
<string name="summary_pref_feedback">Phản hồi cải tiến hoặc lỗi lên GitHub</string>
|
||||
@@ -312,6 +315,14 @@
|
||||
<item>Sao chép thành cấu hình tùy chỉnh</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_method_more">
|
||||
<item>QRcode</item>
|
||||
<item>Export to clipboard</item>
|
||||
<item>Export full configuration to clipboard</item>
|
||||
<item>Edit</item>
|
||||
<item>Delete</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_sub_method">
|
||||
<item>Xuất gói ra mã QR (Chụp màn hình để lưu)</item>
|
||||
<item>Xuất gói vào Clipboard</item>
|
||||
|
||||
@@ -213,6 +213,9 @@
|
||||
<string name="title_pref_append_http_proxy">追加 HTTP 代理至 VPN</string>
|
||||
<string name="summary_pref_append_http_proxy">浏览器 / 一些支持的应用 将直接使用 HTTP 代理, 而不经过虚拟网卡设备 (Android 10+)</string>
|
||||
|
||||
<string name="title_pref_double_column_display">启用双列显示</string>
|
||||
<string name="summary_pref_double_column_display">配置文件列表以双列显示,允许在屏幕上显示更多内容。需要重启应用生效。</string>
|
||||
|
||||
<!-- AboutActivity -->
|
||||
<string name="title_pref_feedback">反馈</string>
|
||||
<string name="summary_pref_feedback">反馈改进或漏洞至 GitHub</string>
|
||||
@@ -316,6 +319,14 @@
|
||||
<item>导出完整配置至剪贴板</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_method_more">
|
||||
<item>二维码</item>
|
||||
<item>导出至剪贴板</item>
|
||||
<item>导出完整配置至剪贴板</item>
|
||||
<item>编辑</item>
|
||||
<item>删除</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_sub_method">
|
||||
<item>二维码</item>
|
||||
<item>导出至剪贴板</item>
|
||||
|
||||
@@ -214,6 +214,9 @@
|
||||
<string name="title_pref_append_http_proxy">追加 HTTP 代理至 VPN</string>
|
||||
<string name="summary_pref_append_http_proxy">瀏覽器 / 一些支援的應用 將直接使用 HTTP 代理, 而不經過虛擬網卡設備 (Android 10+)</string>
|
||||
|
||||
<string name="title_pref_double_column_display">啟用雙列顯示</string>
|
||||
<string name="summary_pref_double_column_display">設定檔清單以雙列顯示,允許在螢幕上顯示更多內容。需要重啟應用生效。</string>
|
||||
|
||||
<!-- AboutActivity -->
|
||||
<string name="title_pref_feedback">意見回饋</string>
|
||||
<string name="summary_pref_feedback">前往 GitHub 回報錯誤</string>
|
||||
@@ -316,6 +319,14 @@
|
||||
<item>匯出完整設定至剪貼簿</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_method_more">
|
||||
<item>QR Code</item>
|
||||
<item>匯出至剪貼簿</item>
|
||||
<item>匯出完整設定至剪貼簿</item>
|
||||
<item>編輯</item>
|
||||
<item>刪除</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_sub_method">
|
||||
<item>QR Code</item>
|
||||
<item>匯出至剪貼簿</item>
|
||||
|
||||
@@ -217,6 +217,9 @@
|
||||
<string name="title_pref_append_http_proxy">Append HTTP Proxy to VPN</string>
|
||||
<string name="summary_pref_append_http_proxy">HTTP proxy will be used directly from (browser/ some supported apps), without going through the virtual NIC device (Android 10+)</string>
|
||||
|
||||
<string name="title_pref_double_column_display">Enable double column display</string>
|
||||
<string name="summary_pref_double_column_display">The profile list is displayed in double columns, allowing more content to be displayed on the screen. You need to restart the application to take effect.</string>
|
||||
|
||||
<!-- AboutActivity -->
|
||||
<string name="title_pref_feedback">Feedback</string>
|
||||
<string name="summary_pref_feedback">Feedback enhancements or bugs to GitHub</string>
|
||||
@@ -326,6 +329,14 @@
|
||||
<item>Export full configuration to clipboard</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_method_more">
|
||||
<item>QRcode</item>
|
||||
<item>Export to clipboard</item>
|
||||
<item>Export full configuration to clipboard</item>
|
||||
<item>Edit</item>
|
||||
<item>Delete</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="share_sub_method">
|
||||
<item>QRcode</item>
|
||||
<item>Export to clipboard</item>
|
||||
|
||||
@@ -75,6 +75,11 @@
|
||||
android:summary="@string/summary_pref_start_scan_immediate"
|
||||
android:title="@string/title_pref_start_scan_immediate" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="pref_double_column_display"
|
||||
android:summary="@string/summary_pref_double_column_display"
|
||||
android:title="@string/title_pref_double_column_display" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="auto"
|
||||
android:entries="@array/language_select"
|
||||
|
||||
Reference in New Issue
Block a user