Changeset View
Changeset View
Standalone View
Standalone View
lib/shared/markdown.js
// @flow | // @flow | ||||
import invariant from 'invariant'; | import invariant from 'invariant'; | ||||
import * as React from 'react'; | |||||
import { | import { | ||||
markdownUserMentionRegex, | markdownUserMentionRegex, | ||||
decodeChatMentionText, | decodeChatMentionText, | ||||
} from './mention-utils.js'; | } from './mention-utils.js'; | ||||
import { useENSNames } from '../hooks/ens-cache.js'; | |||||
import type { | import type { | ||||
ChatMentionCandidates, | ChatMentionCandidates, | ||||
RelativeMemberInfo, | RelativeMemberInfo, | ||||
ResolvedThreadInfo, | ResolvedThreadInfo, | ||||
} from '../types/thread-types.js'; | } from '../types/thread-types.js'; | ||||
// simple-markdown types | // simple-markdown types | ||||
export type State = { | export type State = { | ||||
▲ Show 20 Lines • Show All 175 Lines • ▼ Show 20 Lines | ): UnTypedASTNode { | ||||
return { | return { | ||||
ordered: ordered, | ordered: ordered, | ||||
start: start, | start: start, | ||||
items: itemContent, | items: itemContent, | ||||
}; | }; | ||||
} | } | ||||
function createMemberMapForUserMentions( | const useENSNamesOptions = { allAtOnce: true }; | ||||
function useMemberMapForUserMentions( | |||||
members: $ReadOnlyArray<RelativeMemberInfo>, | members: $ReadOnlyArray<RelativeMemberInfo>, | ||||
): $ReadOnlyMap<string, string> { | ): $ReadOnlyMap<string, string> { | ||||
const membersMap = new Map<string, string>(); | const membersWithRole = React.useMemo( | ||||
members.forEach(member => { | () => members.filter(member => member.role), | ||||
if (member.role && member.username) { | [members], | ||||
membersMap.set(member.username.toLowerCase(), member.id); | ); | ||||
const resolvedMembers = useENSNames(membersWithRole, useENSNamesOptions); | |||||
const resolvedMembersMap: $ReadOnlyMap<string, RelativeMemberInfo> = | |||||
React.useMemo( | |||||
() => new Map(resolvedMembers.map(member => [member.id, member])), | |||||
[resolvedMembers], | |||||
); | |||||
const membersMap = React.useMemo(() => { | |||||
const map = new Map<string, string>(); | |||||
for (const member of membersWithRole) { | |||||
const rawUsername = member.username; | |||||
if (rawUsername) { | |||||
map.set(rawUsername.toLowerCase(), member.id); | |||||
} | } | ||||
}); | |||||
const resolvedMember = resolvedMembersMap.get(member.id); | |||||
const resolvedUsername = resolvedMember?.username; | |||||
if (resolvedUsername && resolvedUsername !== rawUsername) { | |||||
map.set(resolvedUsername.toLowerCase(), member.id); | |||||
} | |||||
} | |||||
return map; | |||||
}, [membersWithRole, resolvedMembersMap]); | |||||
return membersMap; | return membersMap; | ||||
} | } | ||||
function matchUserMentions( | function matchUserMentions( | ||||
membersMap: $ReadOnlyMap<string, string>, | membersMap: $ReadOnlyMap<string, string>, | ||||
): MatchFunction { | ): MatchFunction { | ||||
const match = (source: string, state: State) => { | const match = (source: string, state: State) => { | ||||
▲ Show 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | export { | ||||
fenceStripTrailingNewlineRegex, | fenceStripTrailingNewlineRegex, | ||||
spoilerRegex, | spoilerRegex, | ||||
matchBlockQuote, | matchBlockQuote, | ||||
parseBlockQuote, | parseBlockQuote, | ||||
jsonMatch, | jsonMatch, | ||||
jsonPrint, | jsonPrint, | ||||
matchList, | matchList, | ||||
parseList, | parseList, | ||||
createMemberMapForUserMentions, | useMemberMapForUserMentions, | ||||
matchUserMentions, | matchUserMentions, | ||||
parseUserMentions, | parseUserMentions, | ||||
stripSpoilersFromNotifications, | stripSpoilersFromNotifications, | ||||
stripSpoilersFromMarkdownAST, | stripSpoilersFromMarkdownAST, | ||||
parseChatMention, | parseChatMention, | ||||
ensRegex, | ensRegex, | ||||
}; | }; |