command.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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. // 匹配用户输入与聊天命令前缀
  43. const match = userInput.match(ChatCommandPrefix);
  44. // 如果匹配成功
  45. if (match) {
  46. // 返回用户输入去掉前缀的部分,并断言其类型为 ChatCommands 的键
  47. return userInput.slice(1) as keyof ChatCommands;
  48. }
  49. // 如果匹配失败,直接返回用户输入,并断言其类型为 ChatCommands 的键
  50. return userInput as keyof ChatCommands;
  51. }
  52. function search(userInput: string) {
  53. const input = extract(userInput);
  54. const desc = Locale.Chat.Commands;
  55. return Object.keys(commands)
  56. .filter((c) => c.startsWith(input))
  57. .map((c) => ({
  58. title: desc[c as keyof ChatCommands],
  59. content: ":" + c,
  60. }));
  61. }
  62. function match(userInput: string) {
  63. const command = extract(userInput);
  64. const matched = typeof commands[command] === "function";
  65. return {
  66. matched,
  67. invoke: () => matched && commands[command]!(userInput),
  68. };
  69. }
  70. return { match, search };
  71. }