mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-05 20:54:14 +00:00
fix(frontend): route remaining copy buttons through ClipboardManager
Direct navigator.clipboard calls fail in non-secure contexts (HTTP on a
LAN IP), making the API-docs code copy and security-tab token copy
silently broken. Both now go through ClipboardManager which falls back
to document.execCommand('copy') when navigator.clipboard is unavailable.
This commit is contained in:
parent
5af8153e94
commit
b5fb9e9fe0
2 changed files with 8 additions and 16 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
import { CheckOutlined, CopyOutlined } from '@ant-design/icons';
|
import { CheckOutlined, CopyOutlined } from '@ant-design/icons';
|
||||||
|
import { ClipboardManager } from '@/utils';
|
||||||
import './CodeBlock.css';
|
import './CodeBlock.css';
|
||||||
|
|
||||||
interface CodeBlockProps {
|
interface CodeBlockProps {
|
||||||
|
|
@ -37,12 +38,12 @@ export default function CodeBlock({ code = '', lang = 'json' }: CodeBlockProps)
|
||||||
);
|
);
|
||||||
|
|
||||||
async function copyCode() {
|
async function copyCode() {
|
||||||
try {
|
const ok = await ClipboardManager.copyText(code);
|
||||||
await navigator.clipboard.writeText(code);
|
if (ok) {
|
||||||
setCopied(true);
|
setCopied(true);
|
||||||
messageApi.success('Copied');
|
messageApi.success('Copied');
|
||||||
window.setTimeout(() => setCopied(false), 2000);
|
window.setTimeout(() => setCopied(false), 2000);
|
||||||
} catch {
|
} else {
|
||||||
messageApi.error('Copy failed');
|
messageApi.error('Copy failed');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import {
|
||||||
Switch,
|
Switch,
|
||||||
message,
|
message,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { HttpUtil, RandomUtil } from '@/utils';
|
import { ClipboardManager, HttpUtil, RandomUtil } from '@/utils';
|
||||||
import type { AllSetting } from '@/models/setting';
|
import type { AllSetting } from '@/models/setting';
|
||||||
import SettingListItem from '@/components/SettingListItem';
|
import SettingListItem from '@/components/SettingListItem';
|
||||||
import TwoFactorModal from './TwoFactorModal';
|
import TwoFactorModal from './TwoFactorModal';
|
||||||
|
|
@ -143,18 +143,9 @@ export default function SecurityTab({ allSetting, updateSetting }: SecurityTabPr
|
||||||
|
|
||||||
async function copyToken(token: string) {
|
async function copyToken(token: string) {
|
||||||
if (!token) return;
|
if (!token) return;
|
||||||
try {
|
const ok = await ClipboardManager.copyText(token);
|
||||||
await navigator.clipboard.writeText(token);
|
if (ok) messageApi.success(t('copySuccess'));
|
||||||
messageApi.success(t('copySuccess'));
|
else messageApi.error(t('copyFail') ?? 'Copy failed');
|
||||||
} catch {
|
|
||||||
const ta = document.createElement('textarea');
|
|
||||||
ta.value = token;
|
|
||||||
document.body.appendChild(ta);
|
|
||||||
ta.select();
|
|
||||||
document.execCommand('copy');
|
|
||||||
document.body.removeChild(ta);
|
|
||||||
messageApi.success(t('copySuccess'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function openCreateModal() {
|
function openCreateModal() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue