command.ts 1.8 KB

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