Use typed server menu actions and explicit delete dialogs (#5975)

* Use typed server actions and explicit dialogs

* Add ConfirmDialog

---------

Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
This commit is contained in:
eliotcougarand2dust authored and GitHub committed 2026-07-31 10:34:05 +08:00
1 parent aacc8e091f
commit e549000e5a
25 files changed
+343 -248

No files matched your search

@@ -10,11 +10,13 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.text.selection.TextSelectionColors
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
@@ -22,37 +24,87 @@ import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import com.v2ray.ang.R
@Composable
fun ConfirmDialog(
title: String? = null,
message: String,
confirmText: String,
dismissText: String,
confirmText: String = stringResource(android.R.string.ok),
dismissText: String? = stringResource(android.R.string.cancel),
confirmIcon: @Composable (() -> Unit)? = null,
onConfirm: () -> Unit,
onDismiss: () -> Unit
) {
val confirmFocusRequester = remember { FocusRequester() }
val dismissFocusRequester = remember { FocusRequester() }
LaunchedEffect(dismissText) {
if (dismissText != null) dismissFocusRequester.requestFocus()
else confirmFocusRequester.requestFocus()
}
AlertDialog(
onDismissRequest = onDismiss,
title = title?.let { { Text(it) } },
text = { Text(message, style = MaterialTheme.typography.bodyMedium) },
confirmButton = {
TextButton(onClick = { onConfirm(); onDismiss() }) { Text(confirmText) }
TextButton(
onClick = { onConfirm(); onDismiss() },
modifier = Modifier.focusRequester(confirmFocusRequester)
) {
confirmIcon?.invoke()
if (confirmIcon != null) Spacer(Modifier.width(8.dp))
Text(confirmText)
}
},
dismissButton = {
TextButton(onClick = onDismiss) { Text(dismissText) }
dismissButton = dismissText?.let { text ->
{
TextButton(
onClick = onDismiss,
modifier = Modifier.focusRequester(dismissFocusRequester)
) {
Text(text)
}
}
},
containerColor = MaterialTheme.colorScheme.surface
)
}
@Composable
fun DeleteConfirmDialog(
message: String,
onConfirm: () -> Unit,
onDismiss: () -> Unit,
) {
ConfirmDialog(
message = message,
confirmText = stringResource(R.string.action_delete),
confirmIcon = {
Icon(
painter = painterResource(R.drawable.ic_delete_24dp),
contentDescription = null,
modifier = Modifier.size(18.dp)
)
},
onConfirm = onConfirm,
onDismiss = onDismiss
)
}
data class InputField(
val label: String,
val value: String,
@@ -121,14 +173,14 @@ fun QRCodeDialog(
text = {
Image(
bitmap = bitmap.asImageBitmap(),
contentDescription = "QR Code",
contentDescription = stringResource(R.string.title_qr_code),
modifier = Modifier
.fillMaxWidth()
.aspectRatio(1f)
)
},
confirmButton = {
TextButton(onClick = onDismiss) { Text(stringResource(android.R.string.ok)) }
TextButton(onClick = onDismiss) { Text(stringResource(R.string.action_close)) }
},
containerColor = MaterialTheme.colorScheme.surface
)
@@ -118,8 +118,6 @@ class MainActivity : HelperBaseComponentActivity() {
}
},
onNavigate = { route -> navigateTo(route) },
shareMethodEntries = resources.getStringArray(R.array.share_method).toList(),
shareMethodMoreEntries = resources.getStringArray(R.array.share_method_more).toList()
)
}
@@ -3,7 +3,7 @@ package com.v2ray.ang.ui.main
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import com.v2ray.ang.R
import com.v2ray.ang.compose.ConfirmDialog
import com.v2ray.ang.compose.DeleteConfirmDialog
@Composable
fun MainDialogs(
@@ -21,38 +21,30 @@ fun MainDialogs(
onConfirmRemove: (String) -> Unit,
) {
if (showDelAllConfirm) {
ConfirmDialog(
message = stringResource(R.string.del_config_comfirm),
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_visible_profiles),
onConfirm = onConfirmDelAll,
onDismiss = onDismissDelAll
)
}
if (showDelDuplicateConfirm) {
ConfirmDialog(
message = stringResource(R.string.del_config_comfirm),
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_duplicate_profiles),
onConfirm = onConfirmDelDuplicate,
onDismiss = onDismissDelDuplicate
)
}
if (showDelInvalidConfirm) {
ConfirmDialog(
message = stringResource(R.string.del_invalid_config_comfirm),
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_invalid_profiles),
onConfirm = onConfirmDelInvalid,
onDismiss = onDismissDelInvalid
)
}
if (showRemoveConfirm != null) {
val guid = showRemoveConfirm
ConfirmDialog(
message = stringResource(R.string.del_config_comfirm),
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_profile),
onConfirm = { onConfirmRemove(guid) },
onDismiss = onDismissRemove
)
@@ -1,5 +1,6 @@
package com.v2ray.ang.ui.main
import androidx.annotation.StringRes
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -10,6 +11,25 @@ import com.v2ray.ang.dto.entities.ProfileItem
import com.v2ray.ang.enums.EConfigType
import com.v2ray.ang.extension.isComplexType
internal enum class ServerMenuAction(
@StringRes val labelRes: Int,
val isShareAction: Boolean,
val supportsComplexProfiles: Boolean,
) {
ShareQRCode(R.string.share_method_qrcode, isShareAction = true, supportsComplexProfiles = false),
ShareClipboard(R.string.share_method_clipboard, isShareAction = true, supportsComplexProfiles = false),
ShareFullContent(R.string.share_method_full_content, isShareAction = true, supportsComplexProfiles = true),
Edit(R.string.action_edit, isShareAction = false, supportsComplexProfiles = true),
Delete(R.string.action_delete, isShareAction = false, supportsComplexProfiles = true),
}
internal fun serverMenuActions(
isComplexProfile: Boolean,
includeManagementActions: Boolean,
): List<ServerMenuAction> = ServerMenuAction.entries.filter { action ->
(includeManagementActions || action.isShareAction) && (!isComplexProfile || action.supportsComplexProfiles)
}
@Composable
fun ImportMenuContent(
onAction: (MainAction) -> Unit
@@ -122,29 +142,24 @@ fun ShareMethodDialog(
guid: String,
profile: ProfileItem,
more: Boolean,
shareMethodEntries: List<String>,
shareMethodMoreEntries: List<String>,
onDismiss: () -> Unit,
onAction: (MainAction) -> Unit
onAction: (MainAction) -> Unit,
onRemove: (String) -> Unit,
) {
val isCustom = profile.configType.isComplexType()
val (shareOptions, skip) = if (more) {
val options = if (isCustom) shareMethodMoreEntries.takeLast(3) else shareMethodMoreEntries
options to if (isCustom) 2 else 0
} else {
val options = if (isCustom) shareMethodEntries.takeLast(1) else shareMethodEntries
options to if (isCustom) 2 else 0
}
val menuActions = serverMenuActions(
isComplexProfile = profile.configType.isComplexType(),
includeManagementActions = more,
)
SelectListDialog(
options = shareOptions,
options = menuActions.map { stringResource(it.labelRes) },
onSelected = { index, _ ->
onDismiss()
when (index + skip) {
0 -> onAction(MainAction.ShareQRCode(guid))
1 -> onAction(MainAction.ShareClipboard(guid))
2 -> onAction(MainAction.ShareFullContent(guid))
3 -> onAction(MainAction.EditServer(guid, profile))
4 -> onAction(MainAction.RemoveServer(guid))
when (menuActions[index]) {
ServerMenuAction.ShareQRCode -> onAction(MainAction.ShareQRCode(guid))
ServerMenuAction.ShareClipboard -> onAction(MainAction.ShareClipboard(guid))
ServerMenuAction.ShareFullContent -> onAction(MainAction.ShareFullContent(guid))
ServerMenuAction.Edit -> onAction(MainAction.EditServer(guid, profile))
ServerMenuAction.Delete -> onRemove(guid)
}
},
onDismiss = onDismiss
@@ -41,8 +41,6 @@ fun MainScreen(
mainViewModel: MainViewModel,
onAction: (MainAction) -> Unit,
onNavigate: (String) -> Unit,
shareMethodEntries: List<String>,
shareMethodMoreEntries: List<String>
) {
val uiState by mainViewModel.uiState.collectAsStateWithLifecycle()
val groups = uiState.groups
@@ -65,6 +63,9 @@ fun MainScreen(
var showRemoveConfirm by remember { mutableStateOf<String?>(null) }
var shareTarget by remember { mutableStateOf<Triple<String, ProfileItem, Boolean>?>(null) }
val removeServer: (String) -> Unit = { guid ->
if (confirmRemove) showRemoveConfirm = guid else onAction(MainAction.RemoveServer(guid))
}
val pagerState = rememberPagerState(
initialPage = 0,
@@ -177,10 +178,9 @@ fun MainScreen(
guid = guid,
profile = profile,
more = more,
shareMethodEntries = shareMethodEntries,
shareMethodMoreEntries = shareMethodMoreEntries,
onDismiss = { shareTarget = null },
onAction = onAction
onAction = onAction,
onRemove = removeServer,
)
}
if (shareQRCodeBitmap != null) {
@@ -282,10 +282,7 @@ fun MainScreen(
onMoreServer = { guid, profile ->
shareTarget = Triple(guid, profile, true)
},
onRemoveServer = { guid ->
if (confirmRemove) showRemoveConfirm = guid
else onAction(MainAction.RemoveServer(guid))
},
onRemoveServer = removeServer,
contentPadding = PaddingValues(
start = 0.dp,
top = 0.dp,
@@ -35,7 +35,7 @@ import com.v2ray.ang.AppConfig.BUILTIN_OUTBOUND_TAGS
import com.v2ray.ang.AppConfig.TAG_PROXY
import com.v2ray.ang.R
import com.v2ray.ang.compose.AppTopBar
import com.v2ray.ang.compose.ConfirmDialog
import com.v2ray.ang.compose.DeleteConfirmDialog
import com.v2ray.ang.compose.FormDropdownField
import com.v2ray.ang.compose.FormTextField
import com.v2ray.ang.compose.SettingsSwitchItem
@@ -293,10 +293,8 @@ fun RoutingEditScreen(
}
if (showDeleteConfirm) {
ConfirmDialog(
message = stringResource(R.string.del_config_comfirm),
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_routing_rule),
onConfirm = onDelete,
onDismiss = { showDeleteConfirm = false }
)
@@ -33,7 +33,7 @@ import com.v2ray.ang.AppConfig.REALITY
import com.v2ray.ang.AppConfig.TLS
import com.v2ray.ang.R
import com.v2ray.ang.compose.AppTopBar
import com.v2ray.ang.compose.ConfirmDialog
import com.v2ray.ang.compose.DeleteConfirmDialog
import com.v2ray.ang.compose.FormDropdownField
import com.v2ray.ang.compose.FormTextField
import com.v2ray.ang.compose.SettingsSwitchItem
@@ -474,10 +474,8 @@ abstract class BaseServerActivity : BaseComponentActivity() {
)
}
if (showDeleteDialog) {
ConfirmDialog(
message = stringResource(R.string.del_config_comfirm),
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_profile),
onConfirm = {
showDeleteDialog = false
deleteServer(editGuid)
@@ -35,7 +35,7 @@ import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_ADDRESS_V4
import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_MTU
import com.v2ray.ang.R
import com.v2ray.ang.compose.AppTopBar
import com.v2ray.ang.compose.ConfirmDialog
import com.v2ray.ang.compose.DeleteConfirmDialog
import com.v2ray.ang.compose.FormDropdownField
import com.v2ray.ang.compose.FormTextField
import com.v2ray.ang.compose.SettingsSwitchItem
@@ -515,10 +515,8 @@ fun ServerScreen(
}
}
if (showDeleteDialog) {
ConfirmDialog(
message = stringResource(R.string.del_config_comfirm),
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_profile),
onConfirm = { showDeleteDialog = false; onDelete() },
onDismiss = { showDeleteDialog = false }
)
@@ -56,7 +56,7 @@ import androidx.compose.ui.unit.sp
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.compose.AppTopBar
import com.v2ray.ang.compose.ConfirmDialog
import com.v2ray.ang.compose.DeleteConfirmDialog
import com.v2ray.ang.compose.FormTextField
import com.v2ray.ang.compose.horizontalScrollbar
import com.v2ray.ang.compose.verticalScrollbar
@@ -477,10 +477,8 @@ fun ServerCustomConfigScreen(
}
if (showDeleteConfirm) {
ConfirmDialog(
message = stringResource(R.string.del_config_comfirm),
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_profile),
onConfirm = {
showDeleteConfirm = false
onDelete()
@@ -27,7 +27,7 @@ import com.v2ray.ang.AppConfig.BUILTIN_OUTBOUND_TAGS
import com.v2ray.ang.AppConfig.TAG_PROXY
import com.v2ray.ang.R
import com.v2ray.ang.compose.AppTopBar
import com.v2ray.ang.compose.ConfirmDialog
import com.v2ray.ang.compose.DeleteConfirmDialog
import com.v2ray.ang.compose.FormDropdownField
import com.v2ray.ang.compose.FormTextField
import com.v2ray.ang.compose.SettingsSwitchItem
@@ -302,10 +302,8 @@ fun ServerGroupScreen(
}
if (showDeleteConfirm) {
ConfirmDialog(
message = stringResource(R.string.del_config_comfirm),
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_policy_group),
onConfirm = onDelete,
onDismiss = { showDeleteConfirm = false }
)
@@ -36,7 +36,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.v2ray.ang.R
import com.v2ray.ang.compose.AppTopBar
import com.v2ray.ang.compose.ConfirmDialog
import com.v2ray.ang.compose.DeleteConfirmDialog
import com.v2ray.ang.compose.FormDropdownField
import com.v2ray.ang.compose.FormTextField
import com.v2ray.ang.compose.reorderableDragHandle
@@ -198,10 +198,9 @@ fun ProxyChainScreen(
onDelete: () -> Unit
) {
var remarks by rememberSaveable { mutableStateOf(initialRemarks) }
var members by rememberSaveable { mutableStateOf(initialMembers.toList()) }
// Member remarks may be blank or duplicated, so they cannot serve as stable Compose keys.
var memberKeys by rememberSaveable { mutableStateOf(List(initialMembers.size) { UUID.randomUUID().toString() }) }
var showDeleteConfirm by remember { mutableStateOf(false) }
var members by rememberSaveable { mutableStateOf(initialMembers.toMutableList()) }
var showProfileDeleteConfirm by remember { mutableStateOf(false) }
var memberToDeleteIndex by rememberSaveable { mutableStateOf<Int?>(null) }
val showDelete = editGuid.isNotEmpty() && !isRunning
val lazyListState = rememberLazyListState()
@@ -225,7 +224,7 @@ fun ProxyChainScreen(
onBackClick = onBackClick,
actions = {
if (showDelete) {
IconButton(onClick = { showDeleteConfirm = true }) {
IconButton(onClick = { showProfileDeleteConfirm = true }) {
Icon(painterResource(R.drawable.ic_delete_24dp), contentDescription = stringResource(R.string.menu_item_del_config))
}
}
@@ -309,8 +308,8 @@ fun ProxyChainScreen(
modifier = Modifier.weight(1f)
)
IconButton(onClick = {
members = members.toMutableList().also { it.removeAt(index) }
memberKeys = memberKeys.toMutableList().also { it.removeAt(index) }
if (member.isBlank()) members = members.toMutableList().also { it.removeAt(index) }
else memberToDeleteIndex = index
}) {
Icon(
painterResource(R.drawable.ic_delete_24dp),
@@ -324,13 +323,21 @@ fun ProxyChainScreen(
}
}
if (showDeleteConfirm) {
ConfirmDialog(
message = stringResource(R.string.del_config_comfirm),
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
onConfirm = { showDeleteConfirm = false; onDelete() },
onDismiss = { showDeleteConfirm = false }
if (showProfileDeleteConfirm) {
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_profile),
onConfirm = { showProfileDeleteConfirm = false; onDelete() },
onDismiss = { showProfileDeleteConfirm = false }
)
}
memberToDeleteIndex?.let { index ->
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_proxy_chain_member),
onConfirm = {
members = members.toMutableList().also { it.removeAt(index) }
memberToDeleteIndex = null
},
onDismiss = { memberToDeleteIndex = null }
)
}
}
@@ -27,7 +27,7 @@ import androidx.lifecycle.lifecycleScope
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.compose.AppTopBar
import com.v2ray.ang.compose.ConfirmDialog
import com.v2ray.ang.compose.DeleteConfirmDialog
import com.v2ray.ang.compose.FormDropdownField
import com.v2ray.ang.compose.FormTextField
import com.v2ray.ang.compose.SettingsSwitchItem
@@ -241,10 +241,8 @@ fun SubEditScreen(
}
if (showDeleteConfirm) {
ConfirmDialog(
message = stringResource(R.string.del_config_comfirm),
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_subscription_group),
onConfirm = onDelete,
onDismiss = { showDeleteConfirm = false }
)
@@ -41,7 +41,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.compose.AppTopBar
import com.v2ray.ang.compose.ConfirmDialog
import com.v2ray.ang.compose.DeleteConfirmDialog
import com.v2ray.ang.compose.ItemDivider
import com.v2ray.ang.compose.QRCodeDialog
import com.v2ray.ang.compose.ReorderableListItem
@@ -274,10 +274,8 @@ fun SubSettingScreen(
}
if (removeTarget != null) {
ConfirmDialog(
message = stringResource(R.string.del_config_comfirm),
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_subscription_group),
onConfirm = {
onRemoveSub(removeTarget!!)
removeTarget = null
@@ -46,7 +46,7 @@ import androidx.lifecycle.lifecycleScope
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.compose.AppTopBar
import com.v2ray.ang.compose.ConfirmDialog
import com.v2ray.ang.compose.DeleteConfirmDialog
import com.v2ray.ang.compose.ItemDivider
import com.v2ray.ang.compose.SettingsListItem
import com.v2ray.ang.compose.verticalScrollbar
@@ -344,10 +344,8 @@ fun UserAssetScreen(
if (deleteTargetGuid != null) {
val guid = deleteTargetGuid!!
val assetName = assets.find { it.guid == guid }?.assetUrl?.remarks ?: ""
ConfirmDialog(
message = stringResource(R.string.del_config_comfirm) + "\n$assetName",
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_asset_file, assetName),
onConfirm = { onRemoveAsset(guid) },
onDismiss = { deleteTargetGuid = null }
)
@@ -21,7 +21,7 @@ import androidx.compose.ui.unit.dp
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.compose.AppTopBar
import com.v2ray.ang.compose.ConfirmDialog
import com.v2ray.ang.compose.DeleteConfirmDialog
import com.v2ray.ang.compose.FormTextField
import com.v2ray.ang.dto.entities.AssetUrlItem
import com.v2ray.ang.extension.toast
@@ -186,10 +186,8 @@ fun UserAssetUrlScreen(
}
if (showDeleteConfirm) {
ConfirmDialog(
message = stringResource(R.string.del_config_comfirm),
confirmText = stringResource(android.R.string.ok),
dismissText = stringResource(android.R.string.cancel),
DeleteConfirmDialog(
message = stringResource(R.string.confirm_delete_asset_source),
onConfirm = onDelete,
onDismiss = { showDeleteConfirm = false }
)
+16 -15
View File
@@ -39,8 +39,16 @@
<string name="menu_item_import_config_manually_trojan">الكتابة يدويًا [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">الكتابة يدويًا [Wireguard]</string>
<string name="menu_item_import_config_manually_hysteria2">Type manually[Hysteria2]</string>
<string name="del_config_comfirm">تأكيد الحذف؟</string>
<string name="del_invalid_config_comfirm">Please test before deleting! Confirm delete ?</string>
<string name="confirm_delete_visible_profiles">هل أنت متأكد من أنك تريد حذف جميع ملفات التعريف المعروضة حاليًا؟</string>
<string name="confirm_delete_duplicate_profiles">هل أنت متأكد من أنك تريد حذف جميع ملفات التعريف المكررة المعروضة حاليًا؟</string>
<string name="confirm_delete_invalid_profiles">يرجى اختبار ملفات التعريف أولًا. هل أنت متأكد من أنك تريد حذف جميع ملفات التعريف غير الصالحة المعروضة حاليًا؟</string>
<string name="confirm_delete_profile">هل أنت متأكد من أنك تريد حذف ملف التعريف هذا؟</string>
<string name="confirm_delete_policy_group">هل أنت متأكد من أنك تريد حذف مجموعة السياسات هذه؟</string>
<string name="confirm_delete_proxy_chain_member">هل أنت متأكد من أنك تريد حذف هذا العضو من سلسلة الوكلاء؟</string>
<string name="confirm_delete_routing_rule">هل أنت متأكد من أنك تريد حذف قاعدة التوجيه هذه؟</string>
<string name="confirm_delete_subscription_group">هل أنت متأكد من أنك تريد حذف مجموعة الاشتراك هذه؟</string>
<string name="confirm_delete_asset_file">هل أنت متأكد من أنك تريد حذف ملف الأصول \"%1$s\"؟</string>
<string name="confirm_delete_asset_source">هل أنت متأكد من أنك تريد حذف مصدر الأصول هذا؟</string>
<string name="server_lab_remarks">ملاحظات</string>
<string name="server_lab_address">العنوان</string>
<string name="server_lab_port">المنفذ</string>
@@ -408,19 +416,12 @@
<string name="title_webdav_pass">Password</string>
<string name="title_webdav_remote_path">Remote directory (optional)</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 name="share_method_qrcode">رمز استجابة سريعة (QRcode)</string>
<string name="share_method_clipboard">تصدير إلى الحافظة</string>
<string name="share_method_full_content">تصدير التكوين الكامل إلى الحافظة</string>
<string name="action_edit">تعديل</string>
<string name="action_delete">حذف</string>
<string name="action_close">إغلاق</string>
<string-array name="share_sub_method">
<item>رمز استجابة سريعة (QRcode)</item>
+16 -15
View File
@@ -39,8 +39,16 @@
<string name="menu_item_import_config_manually_trojan">ম্যানুয়ালি টাইপ করুন [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">ম্যানুয়ালি টাইপ করুন [Wireguard]</string>
<string name="menu_item_import_config_manually_hysteria2">Type manually[Hysteria2]</string>
<string name="del_config_comfirm">মুছে ফেলুন নিশ্চিত করুন?</string>
<string name="del_invalid_config_comfirm">Please test before deleting! Confirm delete ?</string>
<string name="confirm_delete_visible_profiles">আপনি কি বর্তমানে প্রদর্শিত সব প্রোফাইল মুছে ফেলতে চান?</string>
<string name="confirm_delete_duplicate_profiles">আপনি কি বর্তমানে প্রদর্শিত সব সদৃশ প্রোফাইল মুছে ফেলতে চান?</string>
<string name="confirm_delete_invalid_profiles">প্রথমে প্রোফাইলগুলো পরীক্ষা করুন। আপনি কি বর্তমানে প্রদর্শিত সব অবৈধ প্রোফাইল মুছে ফেলতে চান?</string>
<string name="confirm_delete_profile">আপনি কি এই প্রোফাইলটি মুছে ফেলতে চান?</string>
<string name="confirm_delete_policy_group">আপনি কি এই পলিসি গ্রুপটি মুছে ফেলতে চান?</string>
<string name="confirm_delete_proxy_chain_member">আপনি কি এই প্রক্সি চেইন সদস্যটিকে মুছে ফেলতে চান?</string>
<string name="confirm_delete_routing_rule">আপনি কি এই রাউটিং নিয়মটি মুছে ফেলতে চান?</string>
<string name="confirm_delete_subscription_group">আপনি কি এই সাবস্ক্রিপশন গ্রুপটি মুছে ফেলতে চান?</string>
<string name="confirm_delete_asset_file">আপনি কি \"%1$s\" অ্যাসেট ফাইলটি মুছে ফেলতে চান?</string>
<string name="confirm_delete_asset_source">আপনি কি এই অ্যাসেট উৎসটি মুছে ফেলতে চান?</string>
<string name="server_lab_remarks">মন্তব্য</string>
<string name="server_lab_address">ঠিকানা</string>
<string name="server_lab_port">পোর্ট</string>
@@ -407,19 +415,12 @@
<string name="title_webdav_pass">Password</string>
<string name="title_webdav_remote_path">Remote directory (optional)</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 name="share_method_qrcode">QR কোড</string>
<string name="share_method_clipboard">ক্লিপবোর্ডে রপ্তানি করুন</string>
<string name="share_method_full_content">পূর্ণ কনফিগারেশন ক্লিপবোর্ডে রপ্তানি করুন</string>
<string name="action_edit">সম্পাদনা</string>
<string name="action_delete">মুছুন</string>
<string name="action_close">বন্ধ করুন</string>
<string-array name="share_sub_method">
<item>QR কোড</item>
@@ -39,8 +39,16 @@
<string name="menu_item_import_config_manually_trojan">ٱووردن [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">ٱووردن [Wireguard]</string>
<string name="menu_item_import_config_manually_hysteria2">ٱووردن [Hysteria2]</string>
<string name="del_config_comfirm">پاک بۊ؟</string>
<string name="del_invalid_config_comfirm">پؽش ز پاک کردن، پینگ بگرین! الن اخۊین پاک کۊنین؟</string>
<string name="confirm_delete_visible_profiles">آیا مطمئن هستید که می‌خواهید همه پروفایل‌های نمایش‌داده‌شده را حذف کنید؟</string>
<string name="confirm_delete_duplicate_profiles">آیا مطمئن هستید که می‌خواهید همه پروفایل‌های تکراری نمایش‌داده‌شده را حذف کنید؟</string>
<string name="confirm_delete_invalid_profiles">لطفاً ابتدا پروفایل‌ها را آزمایش کنید. آیا مطمئن هستید که می‌خواهید همه پروفایل‌های نامعتبر نمایش‌داده‌شده را حذف کنید؟</string>
<string name="confirm_delete_profile">آیا مطمئن هستید که می‌خواهید این پروفایل را حذف کنید؟</string>
<string name="confirm_delete_policy_group">آیا مطمئن هستید که می‌خواهید این گروه سیاست را حذف کنید؟</string>
<string name="confirm_delete_proxy_chain_member">آیا مطمئن هستید که می‌خواهید این عضو زنجیره پراکسی را حذف کنید؟</string>
<string name="confirm_delete_routing_rule">آیا مطمئن هستید که می‌خواهید این قانون مسیریابی را حذف کنید؟</string>
<string name="confirm_delete_subscription_group">آیا مطمئن هستید که می‌خواهید این گروه اشتراک را حذف کنید؟</string>
<string name="confirm_delete_asset_file">آیا مطمئن هستید که می‌خواهید فایل دارایی \"%1$s\" را حذف کنید؟</string>
<string name="confirm_delete_asset_source">آیا مطمئن هستید که می‌خواهید این منبع دارایی را حذف کنید؟</string>
<string name="server_lab_remarks">نیشتنا</string>
<string name="server_lab_address">نشۊوی</string>
<string name="server_lab_port">پورت</string>
@@ -413,19 +421,12 @@
<string name="title_webdav_pass">رزم</string>
<string name="title_webdav_remote_path">دایرکتوری ره دیر (اختیاری)</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>و در کشیڌن من کلیپ بورد</item>
<item>و در کشیڌن پوی کانفیگ من کلیپ بورد</item>
<item>آلشت</item>
<item>پاک کردن</item>
</string-array>
<string name="share_method_qrcode">QRcode</string>
<string name="share_method_clipboard">و در کشیڌن من کلیپ بورد</string>
<string name="share_method_full_content">و در کشیڌن پوی کانفیگ من کلیپ بورد</string>
<string name="action_edit">آلشتکاری</string>
<string name="action_delete">پاک کردن</string>
<string name="action_close">بستن</string>
<string-array name="share_sub_method">
<item>QRcode</item>
+16 -15
View File
@@ -39,8 +39,16 @@
<string name="menu_item_import_config_manually_trojan">افزودن [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">افزودن [Wireguard]</string>
<string name="menu_item_import_config_manually_hysteria2">افزودن [Hysteria2]</string>
<string name="del_config_comfirm">از حذف این کانفیگ اطمینان دارید؟</string>
<string name="del_invalid_config_comfirm">لطفاً قبل از حذف، پینگ بگیرید! آیا از حذف اطمینان دارید؟</string>
<string name="confirm_delete_visible_profiles">آیا مطمئن هستید که می‌خواهید همه پروفایل‌های نمایش‌داده‌شده را حذف کنید؟</string>
<string name="confirm_delete_duplicate_profiles">آیا مطمئن هستید که می‌خواهید همه پروفایل‌های تکراری نمایش‌داده‌شده را حذف کنید؟</string>
<string name="confirm_delete_invalid_profiles">لطفاً ابتدا پروفایل‌ها را آزمایش کنید. آیا مطمئن هستید که می‌خواهید همه پروفایل‌های نامعتبر نمایش‌داده‌شده را حذف کنید؟</string>
<string name="confirm_delete_profile">آیا مطمئن هستید که می‌خواهید این پروفایل را حذف کنید؟</string>
<string name="confirm_delete_policy_group">آیا مطمئن هستید که می‌خواهید این گروه سیاست را حذف کنید؟</string>
<string name="confirm_delete_proxy_chain_member">آیا مطمئن هستید که می‌خواهید این عضو زنجیره پراکسی را حذف کنید؟</string>
<string name="confirm_delete_routing_rule">آیا مطمئن هستید که می‌خواهید این قانون مسیریابی را حذف کنید؟</string>
<string name="confirm_delete_subscription_group">آیا مطمئن هستید که می‌خواهید این گروه اشتراک را حذف کنید؟</string>
<string name="confirm_delete_asset_file">آیا مطمئن هستید که می‌خواهید فایل دارایی \"%1$s\" را حذف کنید؟</string>
<string name="confirm_delete_asset_source">آیا مطمئن هستید که می‌خواهید این منبع دارایی را حذف کنید؟</string>
<string name="server_lab_remarks">ملاحظات</string>
<string name="server_lab_address">نشانی</string>
<string name="server_lab_port">پورت</string>
@@ -404,19 +412,12 @@
<string name="title_webdav_pass">پسورد</string>
<string name="title_webdav_remote_path">دایرکتوری راه دور (اختیاری)</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>صادر کردن به کلیپ بورد</item>
<item>صادر کردن پیکربندی کامل به کلیپ بورد</item>
<item>ویرایش کردن</item>
<item>حذف کردن</item>
</string-array>
<string name="share_method_qrcode">QRcode</string>
<string name="share_method_clipboard">خروجی گرفتن در کلیپ‌ بورد</string>
<string name="share_method_full_content">خروجی گرفتن کانفیگ کامل در کلیپ بورد</string>
<string name="action_edit">ویرایش</string>
<string name="action_delete">حذف</string>
<string name="action_close">بستن</string>
<string-array name="share_sub_method">
<item>QRcode</item>
+16 -15
View File
@@ -39,8 +39,16 @@
<string name="menu_item_import_config_manually_trojan">Добавить Trojan</string>
<string name="menu_item_import_config_manually_wireguard">Добавить WireGuard</string>
<string name="menu_item_import_config_manually_hysteria2">Добавить Hysteria2</string>
<string name="del_config_comfirm">Подтверждаете удаление?</string>
<string name="del_invalid_config_comfirm">Выполните проверку перед удалением! Подтверждаете удаление?</string>
<string name="confirm_delete_visible_profiles">Вы уверены, что хотите удалить все отображаемые профили?</string>
<string name="confirm_delete_duplicate_profiles">Вы уверены, что хотите удалить все отображаемые дубликаты профилей?</string>
<string name="confirm_delete_invalid_profiles">Сначала проверьте профили. Вы уверены, что хотите удалить все отображаемые недействительные профили?</string>
<string name="confirm_delete_profile">Вы уверены, что хотите удалить этот профиль?</string>
<string name="confirm_delete_policy_group">Вы уверены, что хотите удалить эту группу политик?</string>
<string name="confirm_delete_proxy_chain_member">Вы уверены, что хотите удалить этот элемент цепочки прокси?</string>
<string name="confirm_delete_routing_rule">Вы уверены, что хотите удалить это правило маршрутизации?</string>
<string name="confirm_delete_subscription_group">Вы уверены, что хотите удалить эту группу подписки?</string>
<string name="confirm_delete_asset_file">Вы уверены, что хотите удалить файл ресурсов \"%1$s\"?</string>
<string name="confirm_delete_asset_source">Вы уверены, что хотите удалить этот источник ресурсов?</string>
<string name="server_lab_remarks">Название</string>
<string name="server_lab_address">Адрес</string>
<string name="server_lab_port">Порт</string>
@@ -420,19 +428,12 @@
<string name="title_webdav_pass">Пароль</string>
<string name="title_webdav_remote_path">Удалённый путь (необязательно)</string>
<string-array name="share_method">
<item>QR-код</item>
<item>Экспорт в буфер обмена</item>
<item>Экспорт конфигурации в буфер обмена</item>
</string-array>
<string-array name="share_method_more">
<item>QR-код</item>
<item>Экспорт в буфер обмена</item>
<item>Экспорт конфигурации в буфер обмена</item>
<item>Изменить</item>
<item>Удалить</item>
</string-array>
<string name="share_method_qrcode">QR-код</string>
<string name="share_method_clipboard">Экспорт в буфер обмена</string>
<string name="share_method_full_content">Экспорт конфигурации в буфер обмена</string>
<string name="action_edit">Изменить</string>
<string name="action_delete">Удалить</string>
<string name="action_close">Закрыть</string>
<string-array name="share_sub_method">
<item>QR-код</item>
+16 -15
View File
@@ -39,8 +39,16 @@
<string name="menu_item_import_config_manually_trojan">Nhập thủ công [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">Nhập thủ công [WireGuard]</string>
<string name="menu_item_import_config_manually_hysteria2">Type manually[Hysteria2]</string>
<string name="del_config_comfirm">Xác nhận xóa?</string>
<string name="del_invalid_config_comfirm">Please test before deleting! Confirm delete ?</string>
<string name="confirm_delete_visible_profiles">Bạn có chắc muốn xóa tất cả cấu hình đang hiển thị không?</string>
<string name="confirm_delete_duplicate_profiles">Bạn có chắc muốn xóa tất cả cấu hình trùng lặp đang hiển thị không?</string>
<string name="confirm_delete_invalid_profiles">Vui lòng kiểm tra các cấu hình trước. Bạn có chắc muốn xóa tất cả cấu hình không hợp lệ đang hiển thị không?</string>
<string name="confirm_delete_profile">Bạn có chắc muốn xóa cấu hình này không?</string>
<string name="confirm_delete_policy_group">Bạn có chắc muốn xóa nhóm chính sách này không?</string>
<string name="confirm_delete_proxy_chain_member">Bạn có chắc muốn xóa thành viên này khỏi chuỗi proxy không?</string>
<string name="confirm_delete_routing_rule">Bạn có chắc muốn xóa quy tắc định tuyến này không?</string>
<string name="confirm_delete_subscription_group">Bạn có chắc muốn xóa nhóm đăng ký này không?</string>
<string name="confirm_delete_asset_file">Bạn có chắc muốn xóa tệp tài nguyên \"%1$s\" không?</string>
<string name="confirm_delete_asset_source">Bạn có chắc muốn xóa nguồn tài nguyên này không?</string>
<string name="server_lab_remarks">Tên cấu hình</string>
<string name="server_lab_address">Địa chỉ</string>
<string name="server_lab_port">Cổng</string>
@@ -409,19 +417,12 @@
<string name="title_webdav_pass">Password</string>
<string name="title_webdav_remote_path">Remote directory (optional)</string>
<string-array name="share_method">
<item>Xuất ra mã QR (Chụp màn hình để lưu)</item>
<item>Sao chép vào Clipboard</item>
<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 name="share_method_qrcode">Xuất ra mã QR (Chụp màn hình để lưu)</string>
<string name="share_method_clipboard">Sao chép vào Clipboard</string>
<string name="share_method_full_content">Sao chép thành cấu hình tùy chỉnh</string>
<string name="action_edit">Chỉnh sửa</string>
<string name="action_delete">Xoá</string>
<string name="action_close">Đóng</string>
<string-array name="share_sub_method">
<item>Xuất gói ra mã QR (Chụp màn hình để lưu)</item>
@@ -39,8 +39,16 @@
<string name="menu_item_import_config_manually_trojan">添加 [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">添加 [Wireguard]</string>
<string name="menu_item_import_config_manually_hysteria2">添加 [Hysteria2]</string>
<string name="del_config_comfirm">确认删除?</string>
<string name="del_invalid_config_comfirm">删除前请先测试!确认删除?</string>
<string name="confirm_delete_visible_profiles">确定要删除当前显示的所有配置吗?</string>
<string name="confirm_delete_duplicate_profiles">确定要删除当前显示的所有重复配置吗?</string>
<string name="confirm_delete_invalid_profiles">请先测试配置。确定要删除当前显示的所有无效配置吗?</string>
<string name="confirm_delete_profile">确定要删除此配置吗?</string>
<string name="confirm_delete_policy_group">确定要删除此策略组吗?</string>
<string name="confirm_delete_proxy_chain_member">确定要删除此代理链成员吗?</string>
<string name="confirm_delete_routing_rule">确定要删除此路由规则吗?</string>
<string name="confirm_delete_subscription_group">确定要删除此订阅组吗?</string>
<string name="confirm_delete_asset_file">确定要删除资源文件“%1$s”吗?</string>
<string name="confirm_delete_asset_source">确定要删除此资源来源吗?</string>
<string name="server_lab_remarks">别名 (remarks)</string>
<string name="server_lab_address">地址 (address)</string>
<string name="server_lab_port">端口 (port)</string>
@@ -423,19 +431,12 @@
<string name="title_webdav_pass">密码</string>
<string name="title_webdav_remote_path">远程文件夹名(可选)</string>
<string-array name="share_method">
<item>二维码</item>
<item>导出至剪贴板</item>
<item>导出完整配置至剪贴板</item>
</string-array>
<string-array name="share_method_more">
<item>二维码</item>
<item>导出至剪贴板</item>
<item>导出完整配置至剪贴板</item>
<item>编辑</item>
<item>删除</item>
</string-array>
<string name="share_method_qrcode">二维码</string>
<string name="share_method_clipboard">导出至剪贴板</string>
<string name="share_method_full_content">导出完整配置至剪贴板</string>
<string name="action_edit">编辑</string>
<string name="action_delete">删除</string>
<string name="action_close">关闭</string>
<string-array name="share_sub_method">
<item>二维码</item>
@@ -39,8 +39,16 @@
<string name="menu_item_import_config_manually_trojan">新增 [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">新增 [Wireguard]</string>
<string name="menu_item_import_config_manually_hysteria2">新增 [Hysteria2]</string>
<string name="del_config_comfirm">確定刪除?</string>
<string name="del_invalid_config_comfirm">刪除前請先測試!確認刪除?</string>
<string name="confirm_delete_visible_profiles">確定要刪除目前顯示的所有設定檔嗎?</string>
<string name="confirm_delete_duplicate_profiles">確定要刪除目前顯示的所有重複設定檔嗎?</string>
<string name="confirm_delete_invalid_profiles">請先測試設定檔。確定要刪除目前顯示的所有無效設定檔嗎?</string>
<string name="confirm_delete_profile">確定要刪除此設定檔嗎?</string>
<string name="confirm_delete_policy_group">確定要刪除此策略組嗎?</string>
<string name="confirm_delete_proxy_chain_member">確定要刪除此代理鏈成員嗎?</string>
<string name="confirm_delete_routing_rule">確定要刪除此路由規則嗎?</string>
<string name="confirm_delete_subscription_group">確定要刪除此訂閱群組嗎?</string>
<string name="confirm_delete_asset_file">確定要刪除資源檔案「%1$s」嗎?</string>
<string name="confirm_delete_asset_source">確定要刪除此資源來源嗎?</string>
<string name="server_lab_remarks">備註</string>
<string name="server_lab_address">位址</string>
<string name="server_lab_port">埠</string>
@@ -421,19 +429,12 @@
<string name="title_webdav_pass">密碼</string>
<string name="title_webdav_remote_path">遠端目錄(可選)</string>
<string-array name="share_method">
<item>二維碼</item>
<item>匯出至剪貼簿</item>
<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 name="share_method_qrcode">二維碼</string>
<string name="share_method_clipboard">匯出至剪貼簿</string>
<string name="share_method_full_content">匯出完整設定至剪貼簿</string>
<string name="action_edit">編輯</string>
<string name="action_delete">刪除</string>
<string name="action_close">關閉</string>
<string-array name="share_sub_method">
<item>二維碼</item>
+16 -15
View File
@@ -40,8 +40,16 @@
<string name="menu_item_import_config_manually_trojan">Add [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">Add [Wireguard]</string>
<string name="menu_item_import_config_manually_hysteria2">Add [Hysteria2]</string>
<string name="del_config_comfirm">Confirm delete ?</string>
<string name="del_invalid_config_comfirm">Please test before deleting! Confirm delete ?</string>
<string name="confirm_delete_visible_profiles">Are you sure you want to delete all profiles currently shown?</string>
<string name="confirm_delete_duplicate_profiles">Are you sure you want to delete all duplicate profiles currently shown?</string>
<string name="confirm_delete_invalid_profiles">Please test the profiles first. Are you sure you want to delete all invalid profiles currently shown?</string>
<string name="confirm_delete_profile">Are you sure you want to delete this profile?</string>
<string name="confirm_delete_policy_group">Are you sure you want to delete this policy group?</string>
<string name="confirm_delete_proxy_chain_member">Are you sure you want to delete this chain member?</string>
<string name="confirm_delete_routing_rule">Are you sure you want to delete this routing rule?</string>
<string name="confirm_delete_subscription_group">Are you sure you want to delete this subscription group?</string>
<string name="confirm_delete_asset_file">Are you sure you want to delete the asset file \"%1$s\"?</string>
<string name="confirm_delete_asset_source">Are you sure you want to delete this asset source?</string>
<string name="server_lab_remarks">remarks</string>
<string name="server_lab_address">address</string>
<string name="server_lab_port">port</string>
@@ -429,19 +437,12 @@
<string name="title_webdav_pass">Password</string>
<string name="title_webdav_remote_path">Remote directory (optional)</string>
<string-array name="share_method">
<item>QRcode</item>
<item>Export to clipboard</item>
<item>Export full config to clipboard</item>
</string-array>
<string-array name="share_method_more">
<item>QRcode</item>
<item>Export to clipboard</item>
<item>Export full config to clipboard</item>
<item>Edit</item>
<item>Delete</item>
</string-array>
<string name="share_method_qrcode">QRcode</string>
<string name="share_method_clipboard">Export to clipboard</string>
<string name="share_method_full_content">Export full config to clipboard</string>
<string name="action_edit">Edit</string>
<string name="action_delete">Delete</string>
<string name="action_close">Close</string>
<string-array name="share_sub_method">
<item>QRcode</item>
@@ -0,0 +1,43 @@
package com.v2ray.ang.ui.main
import org.junit.Assert.assertEquals
import org.junit.Test
class MainImportMenuTest {
@Test
fun regularShareMenuContainsOnlyShareActions() {
val expected = listOf(
ServerMenuAction.ShareQRCode,
ServerMenuAction.ShareClipboard,
ServerMenuAction.ShareFullContent,
)
assertEquals(expected, serverMenuActions(isComplexProfile = false, includeManagementActions = false))
}
@Test
fun regularMoreMenuContainsEveryActionInDisplayOrder() {
assertEquals(
ServerMenuAction.entries,
serverMenuActions(isComplexProfile = false, includeManagementActions = true),
)
}
@Test
fun complexShareMenuContainsOnlyFullContent() {
assertEquals(
listOf(ServerMenuAction.ShareFullContent),
serverMenuActions(isComplexProfile = true, includeManagementActions = false),
)
}
@Test
fun complexMoreMenuRetainsManagementActions() {
val expected = listOf(
ServerMenuAction.ShareFullContent,
ServerMenuAction.Edit,
ServerMenuAction.Delete,
)
assertEquals(expected, serverMenuActions(isComplexProfile = true, includeManagementActions = true))
}
}