diff --git a/renderer/components/timelines/notification/Notification.tsx b/renderer/components/timelines/notification/Notification.tsx index 22ff5194..a0cb3109 100644 --- a/renderer/components/timelines/notification/Notification.tsx +++ b/renderer/components/timelines/notification/Notification.tsx @@ -41,7 +41,15 @@ export default function Notification(props: Props) { case 'emoji_reaction': case 'reaction': { if (props.notification.status) { - return + return ( + + ) } else { return null } diff --git a/renderer/components/timelines/notification/Reaction.tsx b/renderer/components/timelines/notification/Reaction.tsx index 9a894e3a..9374507e 100644 --- a/renderer/components/timelines/notification/Reaction.tsx +++ b/renderer/components/timelines/notification/Reaction.tsx @@ -5,15 +5,19 @@ import Body from '../status/Body' import Poll from '../status/Poll' import Card from '../status/Card' import Media from '../status/Media' +import { findAccount, findLink, ParsedAccount, accountMatch, findTag } from '@/utils/statusParser' import { FaBarsProgress, FaHouse, FaPenToSquare, FaRetweet, FaStar } from 'react-icons/fa6' import { FormattedMessage, useIntl } from 'react-intl' import { MouseEventHandler, useState } from 'react' import { Avatar, List, ListItem, Card as MaterialCard } from '@material-tailwind/react' import { useRouter } from 'next/router' +import { invoke } from '@/utils/invoke' +import { Account } from '@/db' type Props = { notification: Entity.Notification client: MegalodonInterface + account: Account onRefresh: (status: Entity.Status) => void openMedia: (media: Array, index: number) => void } @@ -37,6 +41,37 @@ export default function Reaction(props: Props) { router.push({ query: { id: router.query.id, timeline: router.query.timeline, user_id: id, detail: true } }) } + const statusClicked: MouseEventHandler = async e => { + const parsedAccount = findAccount(e.target as HTMLElement, 'status-body') + if (parsedAccount) { + e.preventDefault() + e.stopPropagation() + + const account = await searchAccount(parsedAccount, status, props.client, props.account.domain) + if (account) { + router.push({ query: { id: router.query.id, timeline: router.query.timeline, user_id: account.id, detail: true } }) + } else { + console.warn('account not found', parsedAccount) + } + return + } + + const parsedTag = findTag(e.target as HTMLElement, 'status-body') + if (parsedTag) { + e.preventDefault() + e.stopPropagation() + router.push({ query: { id: router.query.id, timeline: router.query.timeline, tag: parsedTag, detail: true } }) + return + } + + const url = findLink(e.target as HTMLElement, 'status-body') + if (url) { + invoke('open-browser', url) + e.preventDefault() + e.stopPropagation() + } + } + const onContextMenu: MouseEventHandler = e => { e.preventDefault() hideOthers() @@ -116,7 +151,15 @@ export default function Reaction(props: Props) { - +
+ +
{!spoilered && ( <> {status.poll && } @@ -210,3 +253,26 @@ const actionId = (notification: Entity.Notification) => { return '' } } + +async function searchAccount(account: ParsedAccount, status: Entity.Status, client: MegalodonInterface, domain: string) { + if (status.in_reply_to_account_id) { + const res = await client.getAccount(status.in_reply_to_account_id) + if (res.status === 200) { + const user = accountMatch([res.data], account, domain) + if (user) return user + } + } + if (status.in_reply_to_id) { + const res = await client.getStatusContext(status.id) + if (res.status === 200) { + const accounts: Array = res.data.ancestors.map(s => s.account).concat(res.data.descendants.map(s => s.account)) + const user = accountMatch(accounts, account, domain) + if (user) return user + } + } + const res = await client.searchAccount(account.url, { resolve: true }) + if (res.data.length === 0) return null + const user = accountMatch(res.data, account, domain) + if (user) return user + return null +}