Merge pull request #4775 from h3poteto/iss-4653/actions

refs #4653 Impelment block, mute, and domain block
This commit is contained in:
AkiraFukushima 2024-01-13 22:07:41 +09:00 committed by GitHub
commit 06b5228c9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 132 additions and 4 deletions

View File

@ -16,7 +16,8 @@
"show_more": "Show more", "show_more": "Show more",
"show_less": "Show less", "show_less": "Show less",
"cw": "Media hidden", "cw": "Media hidden",
"report": "Report {user}" "report": "Report {user}",
"open_original": "Open original page"
} }
}, },
"accounts": { "accounts": {
@ -121,6 +122,12 @@
"follow": "Follow", "follow": "Follow",
"unfollow": "Unfollow", "unfollow": "Unfollow",
"open_original": "Open original page", "open_original": "Open original page",
"block": "Block",
"unblock": "Unblock",
"mute": "Mute",
"unmute": "Unmute",
"block_domain": "Block domain {server}",
"unblock_domain": "Unblock domain {server}",
"timeline": "Timeline", "timeline": "Timeline",
"followers": "Followers", "followers": "Followers",
"followings": "Followings" "followings": "Followings"

View File

@ -23,6 +23,7 @@ import {
TabsBody, TabsBody,
TabsHeader TabsHeader
} from '@material-tailwind/react' } from '@material-tailwind/react'
import { domainFromAcct } from '@/utils/domain'
type Props = { type Props = {
client: MegalodonInterface client: MegalodonInterface
@ -35,19 +36,25 @@ export default function Profile(props: Props) {
const [user, setUser] = useState<Entity.Account | null>(null) const [user, setUser] = useState<Entity.Account | null>(null)
const [relationship, setRelationship] = useState<Entity.Relationship | null>(null) const [relationship, setRelationship] = useState<Entity.Relationship | null>(null)
const [popoverDetail, setPopoverDetail] = useState(false) const [popoverDetail, setPopoverDetail] = useState(false)
const [domain, setDomain] = useState<string | null>(null)
useEffect(() => { useEffect(() => {
const f = async () => { const f = async () => {
if (props.user_id) { if (props.user_id) {
const res = await props.client.getAccount(props.user_id) const res = await props.client.getAccount(props.user_id)
setUser(res.data) setUser(res.data)
const rel = await props.client.getRelationship(props.user_id) setDomain(domainFromAcct(res.data.acct))
setRelationship(rel.data) await refresh()
} }
} }
f() f()
}, [props.user_id, props.client]) }, [props.user_id, props.client])
const refresh = async () => {
const rel = await props.client.getRelationship(props.user_id)
setRelationship(rel.data)
}
const follow = async (id: string) => { const follow = async (id: string) => {
const rel = await props.client.followAccount(id) const rel = await props.client.followAccount(id)
setRelationship(rel.data) setRelationship(rel.data)
@ -62,6 +69,48 @@ export default function Profile(props: Props) {
global.ipc.invoke('open-browser', url) global.ipc.invoke('open-browser', url)
} }
const block = async () => {
if (user) {
await props.client.blockAccount(user.id)
await refresh()
}
}
const unblock = async () => {
if (user) {
await props.client.unblockAccount(user.id)
await refresh()
}
}
const mute = async () => {
if (user) {
await props.client.muteAccount(user.id, false)
await refresh()
}
}
const unmute = async () => {
if (user) {
await props.client.unmuteAccount(user.id)
await refresh()
}
}
const blockDomain = async () => {
if (user && domain) {
await props.client.blockDomain(domain)
await refresh()
}
}
const unblockDomain = async () => {
if (user && domain) {
await props.client.unblockDomain(domain)
await refresh()
}
}
const profileClicked: MouseEventHandler<HTMLDivElement> = async e => { const profileClicked: MouseEventHandler<HTMLDivElement> = async e => {
const url = findLink(e.target as HTMLElement, 'profile') const url = findLink(e.target as HTMLElement, 'profile')
if (url) { if (url) {
@ -107,6 +156,63 @@ export default function Profile(props: Props) {
> >
<FormattedMessage id="profile.open_original" /> <FormattedMessage id="profile.open_original" />
</ListItem> </ListItem>
{relationship.blocking ? (
<ListItem
onClick={() => {
unblock()
setPopoverDetail(false)
}}
>
<FormattedMessage id="profile.unblock" />
</ListItem>
) : (
<ListItem
onClick={() => {
block()
setPopoverDetail(false)
}}
>
<FormattedMessage id="profile.block" />
</ListItem>
)}
{relationship.muting ? (
<ListItem
onClick={() => {
unmute()
setPopoverDetail(false)
}}
>
<FormattedMessage id="profile.unmute" />
</ListItem>
) : (
<ListItem
onClick={() => {
mute()
setPopoverDetail(false)
}}
>
<FormattedMessage id="profile.mute" />
</ListItem>
)}
{relationship.domain_blocking ? (
<ListItem
onClick={() => {
blockDomain()
setPopoverDetail(false)
}}
>
<FormattedMessage id="profile.unblock_domain" values={{ server: domain }} />
</ListItem>
) : (
<ListItem
onClick={() => {
unblockDomain()
setPopoverDetail(false)
}}
>
<FormattedMessage id="profile.block_domain" values={{ server: domain }} />
</ListItem>
)}
</List> </List>
</PopoverContent> </PopoverContent>
</Popover> </Popover>

View File

@ -53,10 +53,15 @@ export default function Actions(props: Props) {
const onEmojiSelect = async emoji => { const onEmojiSelect = async emoji => {
await props.client.createEmojiReaction(props.status.id, emoji.native) await props.client.createEmojiReaction(props.status.id, emoji.native)
setPopoverDetail(false) setPopoverEmoji(false)
props.onRefresh() props.onRefresh()
} }
const original = () => {
setPopoverDetail(false)
global.ipc.invoke('open-browser', props.status.url)
}
const report = () => { const report = () => {
setPopoverDetail(false) setPopoverDetail(false)
router.push({ query: { id: router.query.id, timeline: router.query.timeline, report_target_id: props.status.id, modal: true } }) router.push({ query: { id: router.query.id, timeline: router.query.timeline, report_target_id: props.status.id, modal: true } })
@ -97,6 +102,9 @@ export default function Actions(props: Props) {
</PopoverHandler> </PopoverHandler>
<PopoverContent className="z-10"> <PopoverContent className="z-10">
<List className="py-2 px-0"> <List className="py-2 px-0">
<ListItem onClick={original} className="rounded-none">
<FormattedMessage id="timeline.status.open_original" />
</ListItem>
<ListItem onClick={report} className="rounded-none"> <ListItem onClick={report} className="rounded-none">
<FormattedMessage id="timeline.status.report" values={{ user: `@${props.status.account.acct}` }} /> <FormattedMessage id="timeline.status.report" values={{ user: `@${props.status.account.acct}` }} />
</ListItem> </ListItem>

7
renderer/utils/domain.ts Normal file
View File

@ -0,0 +1,7 @@
export const domainFromAcct = (acct: string): string | null => {
const [_account, server] = acct.split('@')
if (server) {
return server
}
return null
}