Merge pull request #3453 from Chris380/feature/clickable_lit_and_msg_files

Make .lit and .msg files clickable
This commit is contained in:
hydroflame 2022-04-14 11:10:27 -04:00 committed by GitHub
commit 1ce9f5d9d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -9,6 +9,8 @@ import { evaluateDirectoryPath, getFirstParentDirectory, isValidDirectoryPath }
import { IRouter } from "../../ui/Router"; import { IRouter } from "../../ui/Router";
import { ITerminal } from "../ITerminal"; import { ITerminal } from "../ITerminal";
import * as libarg from "arg"; import * as libarg from "arg";
import { showLiterature } from "../../Literature/LiteratureHelpers";
import { MessageFilenames, showMessage } from "../../Message/MessageHelpers";
export function ls( export function ls(
terminal: ITerminal, terminal: ITerminal,
@ -121,13 +123,13 @@ export function ls(
allMessages.sort(); allMessages.sort();
folders.sort(); folders.sort();
interface ClickableScriptRowProps { interface ClickableRowProps {
row: string; row: string;
prefix: string; prefix: string;
hostname: string; hostname: string;
} }
function ClickableScriptRow({ row, prefix, hostname }: ClickableScriptRowProps): React.ReactElement { function ClickableScriptRow({ row, prefix, hostname }: ClickableRowProps): React.ReactElement {
const classes = makeStyles((theme: Theme) => const classes = makeStyles((theme: Theme) =>
createStyles({ createStyles({
scriptLinksWrap: { scriptLinksWrap: {
@ -160,18 +162,82 @@ export function ls(
return ( return (
<span className={classes.scriptLinksWrap}> <span className={classes.scriptLinksWrap}>
{rowSplitArray.map((rowItem) => ( {rowSplitArray.map((rowItem) => (
<span> <span key={"script_" + rowItem[0]}>
<span key={rowItem[0]} className={classes.scriptLink} onClick={() => onScriptLinkClick(rowItem[0])}> <span className={classes.scriptLink} onClick={() => onScriptLinkClick(rowItem[0])}>
{rowItem[0]} {rowItem[0]}
</span> </span>
<span key={"s" + rowItem[0]}>{rowItem[1]}</span> <span>{rowItem[1]}</span>
</span> </span>
))} ))}
</span> </span>
); );
} }
function postSegments(segments: string[], flags: any, style?: any, linked?: boolean): void { function ClickableMessageRow({ row, prefix, hostname }: ClickableRowProps): React.ReactElement {
const classes = makeStyles((theme: Theme) =>
createStyles({
linksWrap: {
display: "inline-flex",
color: theme.palette.primary.main,
},
link: {
cursor: "pointer",
textDecorationLine: "underline",
paddingRight: "1.15em",
"&:last-child": { padding: 0 },
},
}),
)();
const rowSplit = row.split("~");
let rowSplitArray = rowSplit.map((x) => [x.trim(), x.replace(x.trim(), "")]);
rowSplitArray = rowSplitArray.filter((x) => !!x[0]);
function onMessageLinkClick(filename: string): void {
if (player.getCurrentServer().hostname !== hostname) {
return terminal.error(`File is not on this server, connect to ${hostname} and try again`);
}
if (filename.startsWith("/")) filename = filename.slice(1);
const filepath = terminal.getFilepath(`${prefix}${filename}`);
if (filepath.endsWith(".lit")) {
showLiterature(filepath);
} else if (filepath.endsWith(".msg")) {
showMessage(filepath as MessageFilenames);
}
}
return (
<span className={classes.linksWrap}>
{rowSplitArray.map((rowItem) => (
<span key={"text_" + rowItem[0]}>
<span className={classes.link} onClick={() => onMessageLinkClick(rowItem[0])}>
{rowItem[0]}
</span>
<span>{rowItem[1]}</span>
</span>
))}
</span>
);
}
enum FileType {
Folder,
Message,
TextFile,
Program,
Contract,
Script,
}
interface FileGroup {
type: FileType;
segments: string[];
}
function postSegments(group: FileGroup, flags: any): void {
const segments = group.segments;
const linked = group.type === FileType.Script || group.type === FileType.Message;
const maxLength = Math.max(...segments.map((s) => s.length)) + 1; const maxLength = Math.max(...segments.map((s) => s.length)) + 1;
const filesPerRow = flags["-l"] === true ? 1 : Math.ceil(80 / maxLength); const filesPerRow = flags["-l"] === true ? 1 : Math.ceil(80 / maxLength);
for (let i = 0; i < segments.length; i++) { for (let i = 0; i < segments.length; i++) {
@ -186,25 +252,32 @@ export function ls(
i++; i++;
} }
i--; i--;
if (!style) {
terminal.print(row); switch (group.type) {
} else if (linked) { case FileType.Folder:
terminal.printRaw(<ClickableScriptRow row={row} prefix={prefix} hostname={server.hostname} />); terminal.printRaw(<span style={{ color: "cyan" }}>{row}</span>);
} else { break;
terminal.printRaw(<span style={style}>{row}</span>); case FileType.Script:
terminal.printRaw(<ClickableScriptRow row={row} prefix={prefix} hostname={server.hostname} />);
break;
case FileType.Message:
terminal.printRaw(<ClickableMessageRow row={row} prefix={prefix} hostname={server.hostname} />);
break;
default:
terminal.print(row);
} }
} }
} }
const groups = [ const groups: FileGroup[] = [
{ segments: folders, style: { color: "cyan" } }, { type: FileType.Folder, segments: folders },
{ segments: allMessages }, { type: FileType.Message, segments: allMessages },
{ segments: allTextFiles }, { type: FileType.TextFile, segments: allTextFiles },
{ segments: allPrograms }, { type: FileType.Program, segments: allPrograms },
{ segments: allContracts }, { type: FileType.Contract, segments: allContracts },
{ segments: allScripts, style: { color: "yellow", fontStyle: "bold" }, linked: true }, { type: FileType.Script, segments: allScripts },
].filter((g) => g.segments.length > 0); ].filter((g) => g.segments.length > 0);
for (let i = 0; i < groups.length; i++) { for (const group of groups) {
postSegments(groups[i].segments, flags, groups[i].style, groups[i].linked); postSegments(group, flags);
} }
} }