94 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			94 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { createAppSelector } from 'mastodon/store';
 | |
| 
 | |
| export const getAncestorsIds = createAppSelector(
 | |
|   [(_, id: string) => id, (state) => state.contexts.inReplyTos],
 | |
|   (statusId, inReplyTos) => {
 | |
|     const ancestorsIds: string[] = [];
 | |
| 
 | |
|     let currentId: string | undefined = statusId;
 | |
| 
 | |
|     while (currentId && !ancestorsIds.includes(currentId)) {
 | |
|       ancestorsIds.unshift(currentId);
 | |
|       currentId = inReplyTos[currentId];
 | |
|     }
 | |
| 
 | |
|     return ancestorsIds;
 | |
|   },
 | |
| );
 | |
| 
 | |
| export const getDescendantsIds = createAppSelector(
 | |
|   [
 | |
|     (_, id: string) => id,
 | |
|     (state) => state.contexts.replies,
 | |
|     (state) => state.statuses,
 | |
|   ],
 | |
|   (statusId, contextReplies, statuses) => {
 | |
|     const descendantsIds: string[] = [];
 | |
| 
 | |
|     const visitIds = [statusId];
 | |
| 
 | |
|     while (visitIds.length > 0) {
 | |
|       const id = visitIds.pop();
 | |
| 
 | |
|       if (!id) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       const replies = contextReplies[id];
 | |
| 
 | |
|       if (statusId !== id) {
 | |
|         descendantsIds.push(id);
 | |
|       }
 | |
| 
 | |
|       if (replies) {
 | |
|         replies.toReversed().forEach((replyId) => {
 | |
|           if (
 | |
|             !visitIds.includes(replyId) &&
 | |
|             !descendantsIds.includes(replyId) &&
 | |
|             statusId !== replyId
 | |
|           ) {
 | |
|             visitIds.push(replyId);
 | |
|           }
 | |
|         });
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     let insertAt = descendantsIds.findIndex((id) => {
 | |
|       const status = statuses.get(id);
 | |
| 
 | |
|       if (!status) {
 | |
|         return false;
 | |
|       }
 | |
| 
 | |
|       const inReplyToAccountId = status.get('in_reply_to_account_id') as
 | |
|         | string
 | |
|         | null;
 | |
|       const accountId = status.get('account') as string;
 | |
| 
 | |
|       return inReplyToAccountId !== accountId;
 | |
|     });
 | |
| 
 | |
|     if (insertAt !== -1) {
 | |
|       descendantsIds.forEach((id, idx) => {
 | |
|         const status = statuses.get(id);
 | |
| 
 | |
|         if (!status) {
 | |
|           return;
 | |
|         }
 | |
| 
 | |
|         const inReplyToAccountId = status.get('in_reply_to_account_id') as
 | |
|           | string
 | |
|           | null;
 | |
|         const accountId = status.get('account') as string;
 | |
| 
 | |
|         if (idx > insertAt && inReplyToAccountId === accountId) {
 | |
|           descendantsIds.splice(idx, 1);
 | |
|           descendantsIds.splice(insertAt, 0, id);
 | |
|           insertAt += 1;
 | |
|         }
 | |
|       });
 | |
|     }
 | |
| 
 | |
|     return descendantsIds;
 | |
|   },
 | |
| );
 |