useLinks.ts 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import { useCallback } from 'react';
  2. import { useHistory } from 'react-router-dom';
  3. import { openURL } from 'mastodon/actions/search';
  4. import { useAppDispatch } from 'mastodon/store';
  5. const isMentionClick = (element: HTMLAnchorElement) =>
  6. element.classList.contains('mention');
  7. const isHashtagClick = (element: HTMLAnchorElement) =>
  8. element.textContent?.[0] === '#' ||
  9. element.previousSibling?.textContent?.endsWith('#');
  10. export const useLinks = () => {
  11. const history = useHistory();
  12. const dispatch = useAppDispatch();
  13. const handleHashtagClick = useCallback(
  14. (element: HTMLAnchorElement) => {
  15. const { textContent } = element;
  16. if (!textContent) return;
  17. history.push(`/tags/${textContent.replace(/^#/, '')}`);
  18. },
  19. [history],
  20. );
  21. const handleMentionClick = useCallback(
  22. (element: HTMLAnchorElement) => {
  23. dispatch(
  24. openURL(element.href, history, () => {
  25. window.location.href = element.href;
  26. }),
  27. );
  28. },
  29. [dispatch, history],
  30. );
  31. const handleClick = useCallback(
  32. (e: React.MouseEvent) => {
  33. const target = (e.target as HTMLElement).closest('a');
  34. if (!target || e.button !== 0 || e.ctrlKey || e.metaKey) {
  35. return;
  36. }
  37. if (isMentionClick(target)) {
  38. e.preventDefault();
  39. handleMentionClick(target);
  40. } else if (isHashtagClick(target)) {
  41. e.preventDefault();
  42. handleHashtagClick(target);
  43. }
  44. },
  45. [handleMentionClick, handleHashtagClick],
  46. );
  47. return handleClick;
  48. };