mirror of https://github.com/cocosolos/ixion.git
Add CodeCard, adjust tooltips
This commit is contained in:
parent
9276118a37
commit
b8ebc61213
|
|
@ -0,0 +1,128 @@
|
||||||
|
import { ContentCopy } from '@mui/icons-material';
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardHeader,
|
||||||
|
IconButton,
|
||||||
|
Tooltip,
|
||||||
|
} from '@mui/material';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
type CodeCardProps = {
|
||||||
|
title: string;
|
||||||
|
file?: string;
|
||||||
|
content?: string;
|
||||||
|
copy?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function CodeCard({
|
||||||
|
title,
|
||||||
|
file,
|
||||||
|
content,
|
||||||
|
copy,
|
||||||
|
}: CodeCardProps) {
|
||||||
|
const [fileContent, setFileContent] = useState<string>('');
|
||||||
|
const [clipboardTooltip, setClipboardTooltip] = useState('Copy contents.');
|
||||||
|
const [clipboardTooltipOpen, setClipboardTooltipOpen] = useState(false);
|
||||||
|
const handleClipboardTooltipClose = () => {
|
||||||
|
setClipboardTooltipOpen(false);
|
||||||
|
};
|
||||||
|
const handleClipboardTooltipOpen = () => {
|
||||||
|
setClipboardTooltipOpen(true);
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
if (file) {
|
||||||
|
fetch(file)
|
||||||
|
.then((response) => response.text())
|
||||||
|
.then((text) => setFileContent(text))
|
||||||
|
.catch((error) => setFileContent(error.toString()));
|
||||||
|
}
|
||||||
|
}, [file]);
|
||||||
|
|
||||||
|
const copyContentsToClipboard = async (text: string) => {
|
||||||
|
try {
|
||||||
|
navigator.clipboard.writeText(text);
|
||||||
|
setClipboardTooltip('Copied contents!');
|
||||||
|
handleClipboardTooltipOpen();
|
||||||
|
setTimeout(() => {
|
||||||
|
handleClipboardTooltipClose();
|
||||||
|
setClipboardTooltip('Copy contents.');
|
||||||
|
}, 3000);
|
||||||
|
} catch (error) {
|
||||||
|
handleClipboardTooltipOpen();
|
||||||
|
if (error instanceof Error) {
|
||||||
|
setClipboardTooltip(error.message);
|
||||||
|
} else {
|
||||||
|
setClipboardTooltip('Something went wrong!');
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
handleClipboardTooltipClose();
|
||||||
|
setClipboardTooltip('Copy contents.');
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card raised className="m-1">
|
||||||
|
<CardHeader
|
||||||
|
disableTypography
|
||||||
|
title={title}
|
||||||
|
action={
|
||||||
|
copy &&
|
||||||
|
window.isSecureContext && (
|
||||||
|
<Tooltip
|
||||||
|
arrow
|
||||||
|
disableInteractive
|
||||||
|
title={clipboardTooltip}
|
||||||
|
open={
|
||||||
|
clipboardTooltip === 'Copied contents!' || clipboardTooltipOpen
|
||||||
|
}
|
||||||
|
onOpen={handleClipboardTooltipOpen}
|
||||||
|
onClose={handleClipboardTooltipClose}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
// size="small"
|
||||||
|
// className="py-0"
|
||||||
|
onClick={(event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
copyContentsToClipboard(content || fileContent);
|
||||||
|
}}
|
||||||
|
disableRipple
|
||||||
|
>
|
||||||
|
<ContentCopy
|
||||||
|
sx={{
|
||||||
|
fontSize: (theme) => theme.typography.subtitle1.fontSize,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
className="py-0"
|
||||||
|
sx={{ backgroundColor: (theme) => theme.palette.background.paper }}
|
||||||
|
/>
|
||||||
|
<CardContent
|
||||||
|
className="px-2 py-0"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: 'rgba(18, 18, 18, 0.12)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{file ? (
|
||||||
|
<pre className="m-0 select-text">
|
||||||
|
<code>{fileContent}</code>
|
||||||
|
</pre>
|
||||||
|
) : (
|
||||||
|
<pre className="m-0 select-text p-2">
|
||||||
|
<code>{content}</code>
|
||||||
|
</pre>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeCard.defaultProps = {
|
||||||
|
file: '',
|
||||||
|
content: '',
|
||||||
|
copy: true,
|
||||||
|
};
|
||||||
|
|
@ -631,7 +631,7 @@ export default function SearchServers({
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
>
|
>
|
||||||
<Box className="flex min-w-full justify-end pt-2">
|
<Box className="flex min-w-full justify-end pt-2">
|
||||||
<Tooltip title="Sort" arrow disableInteractive>
|
<Tooltip title="Sort" arrow disableInteractive placement="top">
|
||||||
<IconButton
|
<IconButton
|
||||||
// onClick={() => {
|
// onClick={() => {
|
||||||
// setSearchState(SearchStateDefaults);
|
// setSearchState(SearchStateDefaults);
|
||||||
|
|
@ -640,7 +640,12 @@ export default function SearchServers({
|
||||||
<Sort />
|
<Sort />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title="Reset filters." arrow disableInteractive>
|
<Tooltip
|
||||||
|
title="Reset filters."
|
||||||
|
arrow
|
||||||
|
disableInteractive
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSearchState(SearchStateDefaults);
|
setSearchState(SearchStateDefaults);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import { AddCircle } from '@mui/icons-material';
|
import { AddCircleTwoTone } from '@mui/icons-material';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
IconButton,
|
IconButton,
|
||||||
ToggleButton,
|
ToggleButton,
|
||||||
ToggleButtonGroup,
|
ToggleButtonGroup,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
|
useTheme,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { ServerData } from '../../data/ServerData';
|
import { ServerData } from '../../data/ServerData';
|
||||||
|
|
||||||
|
|
@ -60,6 +61,7 @@ type ExpansionBarProps = { server: ServerData };
|
||||||
|
|
||||||
export default function ExpansionBar({ server }: ExpansionBarProps) {
|
export default function ExpansionBar({ server }: ExpansionBarProps) {
|
||||||
const { expansions } = server;
|
const { expansions } = server;
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
const addons = ['acp', 'amk', 'asa', 'abyssea', 'voidwatch', 'rov', 'tvr'];
|
const addons = ['acp', 'amk', 'asa', 'abyssea', 'voidwatch', 'rov', 'tvr'];
|
||||||
|
|
||||||
|
|
@ -101,9 +103,10 @@ export default function ExpansionBar({ server }: ExpansionBarProps) {
|
||||||
arrow
|
arrow
|
||||||
>
|
>
|
||||||
<IconButton className="p-0" disableRipple>
|
<IconButton className="p-0" disableRipple>
|
||||||
<AddCircle
|
<AddCircleTwoTone
|
||||||
style={{
|
style={{
|
||||||
maxHeight: '1rem',
|
maxHeight: '1rem',
|
||||||
|
color: theme.palette.text.primary,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|
|
||||||
|
|
@ -318,6 +318,7 @@ export default function ServerCard({ server, children }: ServerCardProps) {
|
||||||
title={`Server allows ${server.login_limit === 0 ? 'unlimited' : server.login_limit} simultaneous game sessions per IP.`}
|
title={`Server allows ${server.login_limit === 0 ? 'unlimited' : server.login_limit} simultaneous game sessions per IP.`}
|
||||||
arrow
|
arrow
|
||||||
disableInteractive
|
disableInteractive
|
||||||
|
placement="top"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={CopyImageIcon}
|
src={CopyImageIcon}
|
||||||
|
|
@ -343,6 +344,7 @@ export default function ServerCard({ server, children }: ServerCardProps) {
|
||||||
}
|
}
|
||||||
arrow
|
arrow
|
||||||
disableInteractive
|
disableInteractive
|
||||||
|
placement="top"
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
component={Link}
|
component={Link}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ export default function SettingsChipCloud({ server }: SettingsChipCloudProps) {
|
||||||
arrow
|
arrow
|
||||||
disableInteractive
|
disableInteractive
|
||||||
title={ServerSettingsInfo[key].description}
|
title={ServerSettingsInfo[key].description}
|
||||||
|
placement="top"
|
||||||
>
|
>
|
||||||
<Chip
|
<Chip
|
||||||
label={`${ServerSettingsInfo[key].name === '' ? key : ServerSettingsInfo[key].name}`}
|
label={`${ServerSettingsInfo[key].name === '' ? key : ServerSettingsInfo[key].name}`}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
xi = xi or {}
|
||||||
|
xi.settings = xi.settings or {}
|
||||||
|
|
||||||
|
xi.settings.api =
|
||||||
|
{
|
||||||
|
WEBSITE = '',
|
||||||
|
DO_NOT_TRACK = false,
|
||||||
|
}
|
||||||
|
|
@ -10,11 +10,37 @@ import {
|
||||||
alpha,
|
alpha,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import Link from '@mui/material/Link';
|
import Link from '@mui/material/Link';
|
||||||
|
import CodeCard from '../components/CodeCard';
|
||||||
import { useThemeModeContext } from '../context/ThemeContext';
|
import { useThemeModeContext } from '../context/ThemeContext';
|
||||||
|
import apiLua from '../data/api.lua?raw';
|
||||||
|
|
||||||
export default function About() {
|
export default function About() {
|
||||||
const { themeMode } = useThemeModeContext();
|
const { themeMode } = useThemeModeContext();
|
||||||
|
|
||||||
|
const recommendedSettings = `MAIN.SERVER_NAME
|
||||||
|
MAIN.MAX_LEVEL
|
||||||
|
LOGIN.LOGIN_LIMIT
|
||||||
|
LOGIN.CLIENT_VER
|
||||||
|
MAIN.ENABLE_TRUST_CASTING
|
||||||
|
MAP.LEVEL_SYNC_ENABLE
|
||||||
|
MAIN.HOMEPOINT_TELEPORT
|
||||||
|
MAIN.ENABLE_SURVIVAL_GUIDE
|
||||||
|
MAIN.ENABLE_FIELD_MANUALS
|
||||||
|
MAIN.ENABLE_GROUNDS_TOMES
|
||||||
|
MAIN.ENABLE_ROE
|
||||||
|
LOGIN.RISE_OF_ZILART
|
||||||
|
LOGIN.CHAINS_OF_PROMATHIA
|
||||||
|
LOGIN.TREASURES_OF_AHT_URGHAN
|
||||||
|
LOGIN.WINGS_OF_THE_GODDESS
|
||||||
|
LOGIN.SEEKERS_OF_ADOULIN
|
||||||
|
MAIN.ENABLE_ACP
|
||||||
|
MAIN.ENABLE_AMK
|
||||||
|
MAIN.ENABLE_ASA
|
||||||
|
MAIN.ENABLE_ABYSSEA
|
||||||
|
MAIN.ENABLE_VOIDWATCH
|
||||||
|
MAIN.ENABLE_ROV
|
||||||
|
MAIN.ENABLE_TVR`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Card className="mb-2" raised={themeMode === 'light'}>
|
<Card className="mb-2" raised={themeMode === 'light'}>
|
||||||
|
|
@ -147,25 +173,28 @@ export default function About() {
|
||||||
>
|
>
|
||||||
Create a new file <b>settings/api.lua</b> in your server
|
Create a new file <b>settings/api.lua</b> in your server
|
||||||
directory.
|
directory.
|
||||||
<Card className="bg-neutral-500/50">
|
<CodeCard title="api.lua" content={apiLua} />
|
||||||
<pre className="m-0 select-text p-2">
|
|
||||||
<code>
|
|
||||||
{`xi = xi or {}
|
|
||||||
xi.settings = xi.settings or {}
|
|
||||||
|
|
||||||
xi.settings.api =
|
|
||||||
{
|
|
||||||
WEBSITE = '',
|
|
||||||
DO_NOT_TRACK = false,
|
|
||||||
}`}
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
</Card>
|
|
||||||
The world server needs to be restarted after any changes to any
|
The world server needs to be restarted after any changes to any
|
||||||
of the settings. If you set <b>DO_NOT_TRACK</b> to <b>true</b>,
|
of the settings. If you set <b>DO_NOT_TRACK</b> to <b>true</b>,
|
||||||
your server will be removed on the next update.
|
your server will be removed on the next update.
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
<Box className="mb-3">
|
||||||
|
<Typography align="center" variant="h6">
|
||||||
|
Which settings are used?
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
component="span"
|
||||||
|
variant="body1"
|
||||||
|
color={(theme) => alpha(theme.palette.text.primary, 0.87)}
|
||||||
|
>
|
||||||
|
Anything that differs from the default LSB settings will be
|
||||||
|
displayed in the "Settings Summary" section for a
|
||||||
|
server. The following settings are always included as part of
|
||||||
|
the UI:
|
||||||
|
<CodeCard title="Settings" content={recommendedSettings} />
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
</AccordionDetails>
|
</AccordionDetails>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ export default defineConfig({
|
||||||
strictPort: true,
|
strictPort: true,
|
||||||
port: 3000,
|
port: 3000,
|
||||||
hmr: {
|
hmr: {
|
||||||
//port: 3010,
|
// port: 3010,
|
||||||
host: 'localhost'
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
test: {
|
test: {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue