NextChat-U/app/command.ts

80 lines
1.9 KiB
TypeScript
Raw Normal View History

2023-07-06 00:19:54 +09:00
import { useEffect } from "react";
import { useSearchParams } from "react-router-dom";
2023-06-25 00:38:11 +09:00
import Locale from "./locales";
type Command = (param: string) => void;
interface Commands {
fill?: Command;
submit?: Command;
mask?: Command;
code?: Command;
settings?: Command;
}
export function useCommand(commands: Commands = {}) {
const [searchParams, setSearchParams] = useSearchParams();
2023-07-06 00:19:54 +09:00
useEffect(() => {
let shouldUpdate = false;
searchParams.forEach((param, name) => {
const commandName = name as keyof Commands;
if (typeof commands[commandName] === "function") {
commands[commandName]!(param);
searchParams.delete(name);
shouldUpdate = true;
}
});
2023-07-06 00:19:54 +09:00
if (shouldUpdate) {
setSearchParams(searchParams);
}
2023-07-06 00:19:54 +09:00
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchParams, commands]);
}
2023-06-25 00:38:11 +09:00
interface ChatCommands {
new?: Command;
newm?: Command;
next?: Command;
prev?: Command;
clear?: Command;
2024-09-14 15:19:11 +09:00
fork?: Command;
2023-06-25 00:38:11 +09:00
del?: Command;
}
// Compatible with Chinese colon character ""
export const ChatCommandPrefix = /^[:]/;
2023-06-25 00:38:11 +09:00
export function useChatCommand(commands: ChatCommands = {}) {
function extract(userInput: string) {
const match = userInput.match(ChatCommandPrefix);
if (match) {
return userInput.slice(1) as keyof ChatCommands;
}
return userInput as keyof ChatCommands;
2023-06-25 00:38:11 +09:00
}
function search(userInput: string) {
const input = extract(userInput);
const desc = Locale.Chat.Commands;
return Object.keys(commands)
.filter((c) => c.startsWith(input))
.map((c) => ({
title: desc[c as keyof ChatCommands],
content: ":" + c,
2023-06-25 00:38:11 +09:00
}));
}
function match(userInput: string) {
const command = extract(userInput);
const matched = typeof commands[command] === "function";
return {
matched,
invoke: () => matched && commands[command]!(userInput),
};
}
return { match, search };
}