74 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			74 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
| import { useCallback } from 'react';
 | |
| 
 | |
| import { useHistory } from 'react-router-dom';
 | |
| 
 | |
| import { isFulfilled, isRejected } from '@reduxjs/toolkit';
 | |
| 
 | |
| import { openURL } from 'mastodon/actions/search';
 | |
| import { useAppDispatch } from 'mastodon/store';
 | |
| 
 | |
| const isMentionClick = (element: HTMLAnchorElement) =>
 | |
|   element.classList.contains('mention');
 | |
| 
 | |
| const isHashtagClick = (element: HTMLAnchorElement) =>
 | |
|   element.textContent?.[0] === '#' ||
 | |
|   element.previousSibling?.textContent?.endsWith('#');
 | |
| 
 | |
| export const useLinks = () => {
 | |
|   const history = useHistory();
 | |
|   const dispatch = useAppDispatch();
 | |
| 
 | |
|   const handleHashtagClick = useCallback(
 | |
|     (element: HTMLAnchorElement) => {
 | |
|       const { textContent } = element;
 | |
| 
 | |
|       if (!textContent) return;
 | |
| 
 | |
|       history.push(`/tags/${textContent.replace(/^#/, '')}`);
 | |
|     },
 | |
|     [history],
 | |
|   );
 | |
| 
 | |
|   const handleMentionClick = useCallback(
 | |
|     async (element: HTMLAnchorElement) => {
 | |
|       const result = await dispatch(openURL({ url: element.href }));
 | |
| 
 | |
|       if (isFulfilled(result)) {
 | |
|         if (result.payload.accounts[0]) {
 | |
|           history.push(`/@${result.payload.accounts[0].acct}`);
 | |
|         } else if (result.payload.statuses[0]) {
 | |
|           history.push(
 | |
|             `/@${result.payload.statuses[0].account.acct}/${result.payload.statuses[0].id}`,
 | |
|           );
 | |
|         } else {
 | |
|           window.location.href = element.href;
 | |
|         }
 | |
|       } else if (isRejected(result)) {
 | |
|         window.location.href = element.href;
 | |
|       }
 | |
|     },
 | |
|     [dispatch, history],
 | |
|   );
 | |
| 
 | |
|   const handleClick = useCallback(
 | |
|     (e: React.MouseEvent) => {
 | |
|       const target = (e.target as HTMLElement).closest('a');
 | |
| 
 | |
|       if (!target || e.button !== 0 || e.ctrlKey || e.metaKey) {
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|       if (isMentionClick(target)) {
 | |
|         e.preventDefault();
 | |
|         void handleMentionClick(target);
 | |
|       } else if (isHashtagClick(target)) {
 | |
|         e.preventDefault();
 | |
|         handleHashtagClick(target);
 | |
|       }
 | |
|     },
 | |
|     [handleMentionClick, handleHashtagClick],
 | |
|   );
 | |
| 
 | |
|   return handleClick;
 | |
| };
 |