diff --git a/frontend/src/pages/clients/ClientsPage.tsx b/frontend/src/pages/clients/ClientsPage.tsx
index 42e21bef..dfb155a3 100644
--- a/frontend/src/pages/clients/ClientsPage.tsx
+++ b/frontend/src/pages/clients/ClientsPage.tsx
@@ -783,28 +783,25 @@ export default function ClientsPage() {
hoverable
title={
- } onClick={onAdd}>
- {!isMobile && t('pages.clients.addClients')}
-
- {selectedRowKeys.length > 0 && (
+ {selectedRowKeys.length === 0 ? (
+ } onClick={onAdd}>
+ {!isMobile && t('pages.clients.addClients')}
+
+ ) : (
<>
- } onClick={() => setBulkAdjustOpen(true)}>
- {t('pages.clients.adjustSelected', { count: selectedRowKeys.length })}
-
- } onClick={() => setBulkGroupOpen(true)}>
- {t('pages.clients.assignGroupSelected', { count: selectedRowKeys.length })}
-
+ setSelectedRowKeys([])}
+ style={{ marginInlineEnd: 0, padding: '4px 8px', fontSize: 13 }}
+ >
+ {t('pages.clients.selectedCount', { count: selectedRowKeys.length })}
+
} onClick={() => setBulkAttachOpen(true)}>
- {t('pages.clients.attachSelected', { count: selectedRowKeys.length })}
+ {!isMobile && t('pages.clients.attach')}
} onClick={() => setBulkDetachOpen(true)}>
- {t('pages.clients.detachSelected', { count: selectedRowKeys.length })}
-
- } onClick={() => setSubLinksOpen(true)}>
- {t('pages.clients.subLinksSelected', { count: selectedRowKeys.length })}
-
- } onClick={onBulkDelete}>
- {t('pages.clients.deleteSelected', { count: selectedRowKeys.length })}
+ {!isMobile && t('pages.clients.detach')}
>
)}
@@ -812,33 +809,64 @@ export default function ClientsPage() {
trigger={['click']}
placement="bottomRight"
menu={{
- items: [
- {
- key: 'bulk',
- icon: ,
- label: t('pages.clients.bulk'),
- onClick: () => setBulkAddOpen(true),
- },
- {
- key: 'resetAll',
- icon: ,
- label: t('pages.clients.resetAllTraffics'),
- onClick: onResetAllTraffics,
- },
- {
- key: 'delDepleted',
- icon: ,
- label: t('pages.clients.delDepleted'),
- danger: true,
- onClick: onDelDepleted,
- },
- ],
+ items: selectedRowKeys.length > 0
+ ? [
+ {
+ key: 'adjust',
+ icon: ,
+ label: t('pages.clients.adjust'),
+ onClick: () => setBulkAdjustOpen(true),
+ },
+ {
+ key: 'group',
+ icon: ,
+ label: t('pages.clients.group'),
+ onClick: () => setBulkGroupOpen(true),
+ },
+ {
+ key: 'subLinks',
+ icon: ,
+ label: t('pages.clients.subLinks'),
+ onClick: () => setSubLinksOpen(true),
+ },
+ ]
+ : [
+ {
+ key: 'bulk',
+ icon: ,
+ label: t('pages.clients.bulk'),
+ onClick: () => setBulkAddOpen(true),
+ },
+ {
+ key: 'resetAll',
+ icon: ,
+ label: t('pages.clients.resetAllTraffics'),
+ onClick: onResetAllTraffics,
+ },
+ {
+ key: 'delDepleted',
+ icon: ,
+ label: t('pages.clients.delDepleted'),
+ danger: true,
+ onClick: onDelDepleted,
+ },
+ ],
}}
>
}>
{!isMobile && t('more')}
+ {selectedRowKeys.length > 0 && (
+ }
+ onClick={onBulkDelete}
+ style={{ marginInlineStart: 'auto' }}
+ >
+ {!isMobile && t('delete')}
+
+ )}
}
>
diff --git a/web/translation/en-US.json b/web/translation/en-US.json
index db2db99e..1f1ac320 100644
--- a/web/translation/en-US.json
+++ b/web/translation/en-US.json
@@ -542,6 +542,10 @@
"assignGroupPlaceholder": "Group name (leave blank to clear)",
"assignGroupAssignedToast": "Assigned {count} client(s) to {group}",
"assignGroupClearedToast": "Cleared group from {count} client(s)",
+ "attach": "Attach",
+ "adjust": "Adjust",
+ "subLinks": "Sub links",
+ "selectedCount": "{count} selected",
"attachSelected": "Attach ({count})",
"attachToInboundsTitle": "Attach {count} client(s) to inbound(s)",
"attachToInboundsDesc": "Attaches the selected {count} client(s) (same UUID/password and shared traffic) to the chosen inbound(s). They keep their existing attachments too.",
diff --git a/web/translation/fa-IR.json b/web/translation/fa-IR.json
index 23779bab..e4e60c4f 100644
--- a/web/translation/fa-IR.json
+++ b/web/translation/fa-IR.json
@@ -513,6 +513,10 @@
"deleteConfirmContent": "این کلاینت از تمام اینباندهای متصل حذف و سابقه ترافیک آن پاک میشود. این عمل غیرقابل بازگشت است.",
"deleteSelected": "حذف ({count})",
"adjustSelected": "تنظیم ({count})",
+ "attach": "اتصال",
+ "adjust": "تنظیم",
+ "subLinks": "لینکهای ساب",
+ "selectedCount": "{count} انتخابشده",
"attachSelected": "اتصال ({count})",
"attachToInboundsTitle": "اتصال {count} کلاینت به اینباند(ها)",
"attachToInboundsDesc": "{count} کلاینت انتخابشده (با همان UUID/پسورد و ترافیک مشترک) به اینباند(های) انتخابی متصل میشوند. روی اینباندهای فعلی هم باقی میمانند.",