command.ts 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import { useSearchParams } from "react-router-dom";
  2. import Locale from "./locales";
  3. type Command = (param: string) => void;
  4. interface Commands {
  5. fill?: Command;
  6. submit?: Command;
  7. mask?: Command;
  8. }
  9. export function useCommand(commands: Commands = {}) {
  10. const [searchParams, setSearchParams] = useSearchParams();
  11. if (commands === undefined) return;
  12. let shouldUpdate = false;
  13. searchParams.forEach((param, name) => {
  14. const commandName = name as keyof Commands;
  15. if (typeof commands[commandName] === "function") {
  16. commands[commandName]!(param);
  17. searchParams.delete(name);
  18. shouldUpdate = true;
  19. }
  20. });
  21. if (shouldUpdate) {
  22. setSearchParams(searchParams);
  23. }
  24. }
  25. interface ChatCommands {
  26. new?: Command;
  27. newm?: Command;
  28. next?: Command;
  29. prev?: Command;
  30. clear?: Command;
  31. del?: Command;
  32. }
  33. export const ChatCommandPrefix = ":";
  34. export function useChatCommand(commands: ChatCommands = {}) {
  35. function extract(userInput: string) {
  36. return (
  37. userInput.startsWith(ChatCommandPrefix) ? userInput.slice(1) : userInput
  38. ) as keyof ChatCommands;
  39. }
  40. function search(userInput: string) {
  41. const input = extract(userInput);
  42. const desc = Locale.Chat.Commands;
  43. return Object.keys(commands)
  44. .filter((c) => c.startsWith(input))
  45. .map((c) => ({
  46. title: desc[c as keyof ChatCommands],
  47. content: ChatCommandPrefix + c,
  48. }));
  49. }
  50. function match(userInput: string) {
  51. const command = extract(userInput);
  52. const matched = typeof commands[command] === "function";
  53. return {
  54. matched,
  55. invoke: () => matched && commands[command]!(userInput),
  56. };
  57. }
  58. return { match, search };
  59. }