Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: copy fails in http environment #43

Merged
merged 2 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions web/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@400;500;600;700&family=Roboto:wght@400;500;700&display=swap"
rel="stylesheet"
media="print" onload="this.media='all'"
/>
</head>

Expand Down
8 changes: 7 additions & 1 deletion web/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import NavigationScroll from 'layout/NavigationScroll';
import UserProvider from 'contexts/UserContext';
import StatusProvider from 'contexts/StatusContext';
import { SnackbarProvider } from 'notistack';
import CopySnackbar from 'ui-component/Snackbar';

// ==============================|| APP ||============================== //

Expand All @@ -27,7 +28,12 @@ const App = () => {
<ThemeProvider theme={themes(customization)}>
<CssBaseline />
<NavigationScroll>
<SnackbarProvider autoHideDuration={5000} maxSnack={3} anchorOrigin={{ vertical: 'top', horizontal: 'right' }}>
<SnackbarProvider
autoHideDuration={5000}
maxSnack={3}
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
Components={{ copy: CopySnackbar }}
>
<UserProvider>
<StatusProvider>
<Routes />
Expand Down
Binary file removed web/src/assets/images/invite/cover.jpg
Binary file not shown.
Binary file added web/src/assets/images/invite/cover.webp
Binary file not shown.
21 changes: 16 additions & 5 deletions web/src/constants/SnackbarConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,34 @@ export const snackbarConstants = {
Common: {
ERROR: {
variant: 'error',
autoHideDuration: 5000
autoHideDuration: 5000,
preventDuplicate: true
},
WARNING: {
variant: 'warning',
autoHideDuration: 10000
autoHideDuration: 10000,
preventDuplicate: true
},
SUCCESS: {
variant: 'success',
autoHideDuration: 1500
autoHideDuration: 1500,
preventDuplicate: true
},
INFO: {
variant: 'info',
autoHideDuration: 3000
autoHideDuration: 3000,
preventDuplicate: true
},
NOTICE: {
variant: 'info',
autoHideDuration: 20000
autoHideDuration: 20000,
preventDuplicate: true
},
COPY: {
variant: 'copy',
persist: true,
preventDuplicate: true,
allowDownload: true
}
},
Mobile: {
Expand Down
33 changes: 33 additions & 0 deletions web/src/ui-component/Snackbar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import PropTypes from 'prop-types';
import { forwardRef } from 'react';
import { SnackbarContent, useSnackbar } from 'notistack';
import { Alert } from '@mui/material';

const CopySnackbar = forwardRef((props, ref) => {
const { closeSnackbar } = useSnackbar();

return (
<SnackbarContent ref={ref}>
<Alert
severity="info"
variant="filled"
sx={{ width: '100%', whiteSpace: 'normal', overflowWrap: 'break-word' }}
onClose={() => {
closeSnackbar(props.id);
}}
>
{props.message}
</Alert>
</SnackbarContent>
);
});

CopySnackbar.displayName = 'ReportComplete';

CopySnackbar.propTypes = {
props: PropTypes.object,
id: PropTypes.number.isRequired, // 添加 id 的验证
message: PropTypes.any.isRequired // 添加 message 的验证
};

export default CopySnackbar;
2 changes: 1 addition & 1 deletion web/src/ui-component/cards/UserCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { Box, Avatar } from '@mui/material';
import { alpha } from '@mui/material/styles';
import Card from '@mui/material/Card';
import shapeAvatar from 'assets/images/icons/shape-avatar.svg';
import coverAvatar from 'assets/images/invite/cover.jpg';
import coverAvatar from 'assets/images/invite/cover.webp';
import userAvatar from 'assets/images/users/user-round.svg';
import SvgColor from 'ui-component/SvgColor';

Expand Down
11 changes: 11 additions & 0 deletions web/src/utils/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ export function showInfo(message) {
enqueueSnackbar(message, getSnackbarOptions('INFO'));
}

export function copy(text, name = '') {
try {
navigator.clipboard.writeText(text);
} catch (error) {
text = `复制${name}失败,请手动复制:<br /><br />${text}`;
enqueueSnackbar(<SnackbarHTMLContent htmlContent={text} />, getSnackbarOptions('COPY'));
return;
}
showSuccess(`复制${name}成功!`);
}

export async function getOAuthState() {
try {
const res = await API.get('/api/oauth/state');
Expand Down
4 changes: 2 additions & 2 deletions web/src/views/Authentication/AuthForms/AuthLogin.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ const LoginForm = ({ ...others }) => {
submit: null
}}
validationSchema={Yup.object().shape({
username: Yup.string().max(255).required('Username is required'),
password: Yup.string().max(255).required('Password is required')
username: Yup.string().max(255).required('用户名/邮箱是必填项'),
password: Yup.string().max(255).required('密码是必填项')
})}
onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => {
const { success, message } = await login(values.username, values.password);
Expand Down
2 changes: 1 addition & 1 deletion web/src/views/Authentication/AuthForms/AuthRegister.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ const RegisterForm = ({ ...others }) => {
<Box sx={{ mt: 2 }}>
<AnimateButton>
<Button disableElevation disabled={isSubmitting} fullWidth size="large" type="submit" variant="contained" color="primary">
Sign up
注册
</Button>
</AnimateButton>
</Box>
Expand Down
5 changes: 2 additions & 3 deletions web/src/views/Authentication/AuthForms/ResetPasswordForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useSearchParams } from 'react-router-dom';
import { Button, Stack, Typography, Alert } from '@mui/material';

// assets
import { showError, showInfo } from 'utils/common';
import { showError, copy } from 'utils/common';
import { API } from 'utils/api';

// ===========================|| FIREBASE - REGISTER ||=========================== //
Expand All @@ -25,8 +25,7 @@ const ResetPasswordForm = () => {
if (success) {
let password = res.data.data;
setNewPassword(password);
navigator.clipboard.writeText(password);
showInfo(`新密码已复制到剪贴板:${password}`);
copy(password, '新密码');
} else {
showError(message);
}
Expand Down
5 changes: 2 additions & 3 deletions web/src/views/Channel/component/NameLabel.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import { Tooltip, Stack, Container } from '@mui/material';
import Label from 'ui-component/Label';
import { styled } from '@mui/material/styles';
import { showSuccess } from 'utils/common';
import { copy } from 'utils/common';

const TooltipContainer = styled(Container)({
maxHeight: '250px',
Expand All @@ -28,8 +28,7 @@ const NameLabel = ({ name, models }) => {
variant="ghost"
key={index}
onClick={() => {
navigator.clipboard.writeText(item);
showSuccess('复制模型名称成功!');
copy(item, '模型名称');
}}
>
{item}
Expand Down
5 changes: 2 additions & 3 deletions web/src/views/Dashboard/component/SupportModels.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState, useEffect } from 'react';
import SubCard from 'ui-component/cards/SubCard';
// import { gridSpacing } from 'store/constant';
import { API } from 'utils/api';
import { showError, showSuccess } from 'utils/common';
import { showError, copy } from 'utils/common';
import { Typography, Accordion, AccordionSummary, AccordionDetails, Box, Stack } from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import Label from 'ui-component/Label';
Expand Down Expand Up @@ -50,8 +50,7 @@ const SupportModels = () => {
color="primary"
key={model}
onClick={() => {
navigator.clipboard.writeText(model);
showSuccess('复制模型名称成功!');
copy(model, '模型名称');
}}
>
{model}
Expand Down
6 changes: 2 additions & 4 deletions web/src/views/Profile/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ import SubCard from 'ui-component/cards/SubCard';
import { IconBrandWechat, IconBrandGithub, IconMail } from '@tabler/icons-react';
import Label from 'ui-component/Label';
import { API } from 'utils/api';
import { showError, showSuccess } from 'utils/common';
import { onGitHubOAuthClicked } from 'utils/common';
import { showError, showSuccess, onGitHubOAuthClicked, copy } from 'utils/common';
import * as Yup from 'yup';
import WechatModal from 'views/Authentication/AuthForms/WechatModal';
import { useSelector } from 'react-redux';
Expand Down Expand Up @@ -93,8 +92,7 @@ export default function Profile() {
const { success, message, data } = res.data;
if (success) {
setInputs((inputs) => ({ ...inputs, access_token: data }));
navigator.clipboard.writeText(data);
showSuccess(`令牌已重置并已复制到剪贴板`);
copy(data, '令牌');
} else {
showError(message);
}
Expand Down
5 changes: 2 additions & 3 deletions web/src/views/Redemption/component/TableRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {

import Label from 'ui-component/Label';
import TableSwitch from 'ui-component/Switch';
import { timestamp2string, renderQuota, showSuccess } from 'utils/common';
import { timestamp2string, renderQuota, copy } from 'utils/common';

import { IconDotsVertical, IconEdit, IconTrash } from '@tabler/icons-react';

Expand Down Expand Up @@ -83,8 +83,7 @@ export default function RedemptionTableRow({ item, manageRedemption, handleOpenM
variant="contained"
color="primary"
onClick={() => {
navigator.clipboard.writeText(item.key);
showSuccess('已复制到剪贴板!');
copy(item.key, '兑换码');
}}
>
复制
Expand Down
8 changes: 3 additions & 5 deletions web/src/views/Token/component/TableRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
} from '@mui/material';

import TableSwitch from 'ui-component/Switch';
import { renderQuota, showSuccess, timestamp2string } from 'utils/common';
import { renderQuota, timestamp2string, copy } from 'utils/common';

import { IconDotsVertical, IconEdit, IconTrash, IconCaretDownFilled } from '@tabler/icons-react';

Expand Down Expand Up @@ -141,8 +141,7 @@ export default function TokensTableRow({ item, manageToken, handleOpenModal, set
if (type === 'link') {
window.open(text);
} else {
navigator.clipboard.writeText(text);
showSuccess('已复制到剪贴板!');
copy(text, '链接');
}
handleCloseMenu();
};
Expand Down Expand Up @@ -211,8 +210,7 @@ export default function TokensTableRow({ item, manageToken, handleOpenModal, set
<Button
color="primary"
onClick={() => {
navigator.clipboard.writeText(`sk-${item.key}`);
showSuccess('已复制到剪贴板!');
copy(`sk-${item.key}`, '令牌');
}}
>
复制
Expand Down
8 changes: 3 additions & 5 deletions web/src/views/Topup/component/InviteCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ import SubCard from 'ui-component/cards/SubCard';
import inviteImage from 'assets/images/invite/cwok_casual_19.webp';
import { useState } from 'react';
import { API } from 'utils/api';
import { showError, showSuccess } from 'utils/common';
import { showError, copy } from 'utils/common';

const InviteCard = () => {
const theme = useTheme();
const [inviteUl, setInviteUrl] = useState('');

const handleInviteUrl = async () => {
if (inviteUl) {
navigator.clipboard.writeText(inviteUl);
showSuccess(`邀请链接已复制到剪切板`);
copy(inviteUl, '邀请链接');
return;
}

Expand All @@ -23,8 +22,7 @@ const InviteCard = () => {
if (success) {
let link = `${window.location.origin}/register?aff=${data}`;
setInviteUrl(link);
navigator.clipboard.writeText(link);
showSuccess(`邀请链接已复制到剪切板`);
copy(link, '邀请链接');
} else {
showError(message);
}
Expand Down