command.ts 1.9 KB

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