fiora/client/modules/Chat/Message/CodeMessage.tsx
2020-03-15 23:34:59 +08:00

91 lines
2.5 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import Style from './CodeMessage.less';
let CodeDialog: any = null;
type LanguageMap = {
[language: string]: string;
}
const languagesMap: LanguageMap = {
javascript: 'javascript',
typescript: 'typescript',
java: 'java',
c_cpp: 'cpp',
python: 'python',
ruby: 'ruby',
php: 'php',
golang: 'go',
csharp: 'csharp',
html: 'html',
css: 'css',
sql: 'sql',
json: 'json',
text: 'text',
};
interface CodeMessageProps {
code: string;
}
function CodeMessage(props: CodeMessageProps) {
const { code } = props;
const [codeDialog, toggleCodeDialog] = useState(false);
const [timestamp, setTimestamp] = useState(0);
useEffect(() => {
(async () => {
if (codeDialog && !CodeDialog) {
// @ts-ignore
const CodeDialogModule = await import(
/* webpackChunkName: "code-dialog" */ './CodeDialog',
);
CodeDialog = CodeDialogModule.default;
setTimestamp(Date.now());
}
})();
}, [codeDialog]);
const parseResult = /@language=([_a-z]+)@/.exec(code);
if (!parseResult) {
return <pre className="code"></pre>;
}
const language = languagesMap[parseResult[1]] || 'text';
const rawCode = code.replace(/@language=[_a-z]+@/, '');
let size = `${rawCode.length}B`;
if (rawCode.length > 1024) {
size = `${Math.ceil((rawCode.length / 1024) * 100) / 100}KB`;
}
return (
<>
<div className={Style.codeMessage} onClick={() => toggleCodeDialog(true)} role="button">
<div className={Style.codeInfo}>
<div className={Style.icon}>
<i className="iconfont icon-code" />
</div>
<div>
<span>{language}</span>
<span className={Style.codeSize}>{size}</span>
</div>
</div>
<p className={Style.codeViewButton}></p>
</div>
{CodeDialog && codeDialog && (
<CodeDialog
visible={codeDialog}
onClose={() => toggleCodeDialog(false)}
language={language}
code={rawCode}
/>
)}
<span className="hide">{timestamp}</span>
</>
);
}
export default CodeMessage;