command.ts 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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. // Compatible with Chinese colon character ":"
  39. export const ChatCommandPrefix = /^[::]/;
  40. export function useChatCommand(commands: ChatCommands = {}) {
  41. function extract(userInput: string) {
  42. const match = userInput.match(ChatCommandPrefix);
  43. if (match) {
  44. return userInput.slice(1) as keyof ChatCommands;
  45. }
  46. return userInput as keyof ChatCommands;
  47. }
  48. function search(userInput: string) {
  49. const input = extract(userInput);
  50. const desc = Locale.Chat.Commands;
  51. return Object.keys(commands)
  52. .filter((c) => c.startsWith(input))
  53. .map((c) => ({
  54. title: desc[c as keyof ChatCommands],
  55. content: ":" + c,
  56. }));
  57. }
  58. function match(userInput: string) {
  59. const command = extract(userInput);
  60. const matched = typeof commands[command] === "function";
  61. return {
  62. matched,
  63. invoke: () => matched && commands[command]!(userInput),
  64. };
  65. }
  66. return { match, search };
  67. }