From bb4da1aea99172ff3fc40d1dbf792e3656b5b69b Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Tue, 19 May 2026 14:14:47 +0200 Subject: [PATCH] feat(panel): inline share buttons on desktop, dropdown on mobile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the credentials-copy dropdown with three labeled share buttons (SOCKS5 / HTTP / Telegram), each with a tooltip preview of the full URL. Reverse the URI auth position so the format becomes `scheme://host:port@user:pass` (matches Hiddify-style sharing). Add a Telegram t.me/socks link with URL-encoded user/pass. On viewports <=600px the inline row collapses into a single Copy dropdown to keep the per-account row from wrapping into clutter. RTL panels are unaffected — the share divider uses inline-* logical props. --- .../src/pages/inbounds/InboundInfoModal.vue | 152 ++++++++++++------ 1 file changed, 106 insertions(+), 46 deletions(-) diff --git a/frontend/src/pages/inbounds/InboundInfoModal.vue b/frontend/src/pages/inbounds/InboundInfoModal.vue index 0a0b5b89..4bfef885 100644 --- a/frontend/src/pages/inbounds/InboundInfoModal.vue +++ b/frontend/src/pages/inbounds/InboundInfoModal.vue @@ -19,41 +19,20 @@ import { useDatepicker } from '@/composables/useDatepicker.js'; const { t } = useI18n(); const { datepicker } = useDatepicker(); -// One modal handles every protocol's info / share view because the -// legacy template did the same. The big v-if forks at the top decide -// which sub-block of the body renders: -// • multi-user inbound (VMess/VLess/Trojan/SS-multi/Hysteria) → per- -// client row + share links -// • SS single-user → connection details + share link -// • WireGuard → secret/peers + per-peer config download -// • Mixed/HTTP/Tunnel → connection details only -// -// We display links via QrPanel — each link gets its own QR + copy + -// (for WireGuard configs) download button. - const props = defineProps({ open: { type: Boolean, default: false }, - // Result of inbounds-page checkFallback() so the link-gen sees the - // root inbound's listen/port/security when the dbInbound is a - // domain-socket fallback (`@`). dbInbound: { type: Object, default: null }, - // Index into inbound.clients to focus on for multi-user inbounds. clientIndex: { type: Number, default: 0 }, - // Sidecar config the legacy panel keyed off `app.*`. remarkModel: { type: String, default: '-ieo' }, expireDiff: { type: Number, default: 0 }, trafficDiff: { type: Number, default: 0 }, ipLimitEnable: { type: Boolean, default: false }, tgBotEnable: { type: Boolean, default: false }, - // Address of the node hosting this inbound; '' for local. Wired - // through to share/QR link generation so node-managed inbounds - // produce links that connect to the node, not the central panel. nodeAddress: { type: String, default: '' }, subSettings: { type: Object, default: () => ({ enable: false, subURI: '', subJsonURI: '', subJsonEnable: false }), }, - // Email -> ts (last-online unix-ms) map fetched at the page level. lastOnlineMap: { type: Object, default: () => ({}) }, }); @@ -598,7 +577,8 @@ const showSubscriptionTab = computed(
Gateway
{{ ip }}
+ class="value-tag">{{ + ip }}
DNS
@@ -612,7 +592,8 @@ const showSubscriptionTab = computed(
Auto system routes
{{ cidr }}
+ color="green">{{ + cidr }}
@@ -669,24 +650,53 @@ const showSubscriptionTab = computed( {{ account.user }} {{ account.pass }} - - - - + + + + + + + +
@@ -695,14 +705,47 @@ const showSubscriptionTab = computed(
{{ t('copy') }}
- - - SOCKS5 - - - HTTP - + +
@@ -955,8 +998,25 @@ const showSubscriptionTab = computed( flex-shrink: 0; } -.value-copy-dropdown > :global(.ant-btn):first-child { - padding: 0 4px !important; +.share-buttons, +.share-mobile { + margin-inline-start: 4px; + padding-inline-start: 8px; + border-inline-start: 1px solid rgba(128, 128, 128, 0.25); +} + +.share-mobile { + display: none; +} + +@media (max-width: 600px) { + .share-desktop { + display: none !important; + } + .share-mobile { + display: inline-flex; + align-items: center; + } } .security-line {