mirror of
https://github.com/tulir/gomuks.git
synced 2025-04-19 18:13:41 -05:00
Add a button to remove all loaded timeline events from user
This commit is contained in:
parent
fac69d1b63
commit
9814c3a525
1 changed files with 70 additions and 3 deletions
|
@ -15,13 +15,15 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import { use } from "react"
|
||||
import Client from "@/api/client.ts"
|
||||
import { RoomStateStore } from "@/api/statestore"
|
||||
import { RoomStateStore, useRoomTimeline } from "@/api/statestore"
|
||||
import { MemDBEvent, MembershipAction } from "@/api/types"
|
||||
import { useRoomContext } from "@/ui/roomview/roomcontext.ts"
|
||||
import ConfirmWithMessageModal from "../menu/ConfirmWithMessageModal.tsx"
|
||||
import { getPowerLevels } from "../menu/util.ts"
|
||||
import { ModalContext } from "../modal"
|
||||
import StartDMButton from "./StartDMButton.tsx"
|
||||
import UserIgnoreButton from "./UserIgnoreButton.tsx"
|
||||
import DeleteIcon from "@/icons/delete.svg?react"
|
||||
import BanIcon from "@/icons/gavel.svg?react"
|
||||
import InviteIcon from "@/icons/person-add.svg?react"
|
||||
import KickIcon from "@/icons/person-remove.svg?react"
|
||||
|
@ -35,7 +37,9 @@ interface UserModerationProps {
|
|||
|
||||
const UserModeration = ({ userID, client, member, room }: UserModerationProps) => {
|
||||
const openModal = use(ModalContext)
|
||||
const hasPL = (action: "invite" | "kick" | "ban") => {
|
||||
const roomCtx = useRoomContext()
|
||||
const timeline = useRoomTimeline(roomCtx.store)
|
||||
const hasPL = (action: "invite" | "kick" | "ban" | "redact") => {
|
||||
if (!room) {
|
||||
throw new Error("hasPL called without room")
|
||||
}
|
||||
|
@ -44,7 +48,7 @@ const UserModeration = ({ userID, client, member, room }: UserModerationProps) =
|
|||
return ownPL >= (pls.invite ?? 0)
|
||||
}
|
||||
const otherUserPL = pls.users?.[userID] ?? pls.users_default ?? 0
|
||||
return ownPL >= (pls[action] ?? 50) && ownPL > otherUserPL
|
||||
return ownPL >= (pls[action] ?? pls.state_default ?? 50) && ownPL > otherUserPL
|
||||
}
|
||||
|
||||
const runAction = (action: MembershipAction) => {
|
||||
|
@ -76,6 +80,63 @@ const UserModeration = ({ userID, client, member, room }: UserModerationProps) =
|
|||
})
|
||||
}
|
||||
}
|
||||
const calculateRedactions = () => {
|
||||
if (!room) {
|
||||
return []
|
||||
}
|
||||
return timeline.filter(evt => {
|
||||
return evt !== null && evt.room_id == room.roomID && evt.sender === userID && !evt.redacted_by
|
||||
}) as MemDBEvent[] // there's no nulls in this one
|
||||
}
|
||||
const redactRecentMessages = () => {
|
||||
if (!room) {
|
||||
throw new Error("redactRecentMessages called without room")
|
||||
}
|
||||
const callback = async (reason: string) => {
|
||||
const tasks = []
|
||||
for (const evt of calculateRedactions()) {
|
||||
// for(let i=0;i<3;i++) {
|
||||
// try {
|
||||
// await client.rpc.redactEvent(evt.room_id, evt.event_id, reason)
|
||||
// break
|
||||
// } catch (e) {
|
||||
// // If the error is a 429, retry.
|
||||
// // TODO: get the ratelimit from the error and use it for a more precise sleep
|
||||
// if (e instanceof Error && e.message.includes("M_LIMIT_EXCEEDED")) {
|
||||
// const retryAfter = (2 ** i) + Math.random()
|
||||
// console.warn("Rate limited, retrying in %.2f seconds...", retryAfter)
|
||||
// await new Promise(resolve => setTimeout(resolve, retryAfter * 1000))
|
||||
// } else {
|
||||
// throw e
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
tasks.push(client.rpc.redactEvent(evt.room_id, evt.event_id, reason))
|
||||
}
|
||||
Promise.all(tasks).catch((e) => {
|
||||
console.error(e)
|
||||
window.alert(`Failed to redact events: ${e}`)
|
||||
})
|
||||
return true
|
||||
}
|
||||
const evtCount = calculateRedactions().length
|
||||
return () => {
|
||||
openModal({
|
||||
dimmed: true,
|
||||
boxed: true,
|
||||
innerBoxClass: "confirm-message-modal",
|
||||
content: <ConfirmWithMessageModal
|
||||
title={`Redact recent timeline events of ${userID}`}
|
||||
description={
|
||||
<>Are you sure you want to redact all currently loaded timeline events
|
||||
of <code>{userID}</code>? This will remove approximately {evtCount} events.</>}
|
||||
placeholder="Reason (optional)"
|
||||
confirmButton={`Redact ~${evtCount} events`}
|
||||
onConfirm={callback}
|
||||
/>,
|
||||
})
|
||||
}
|
||||
}
|
||||
const membership = member?.content.membership || "leave"
|
||||
|
||||
return <div className="user-moderation">
|
||||
|
@ -111,6 +172,12 @@ const UserModeration = ({ userID, client, member, room }: UserModerationProps) =
|
|||
<span>Unban</span>
|
||||
</button>
|
||||
)}
|
||||
{room && hasPL("redact") && (
|
||||
<button className="moderation-action dangerous" onClick={redactRecentMessages()}>
|
||||
<DeleteIcon />
|
||||
<span>Redact recent messages</span>
|
||||
</button>
|
||||
)}
|
||||
<UserIgnoreButton userID={userID} client={client} />
|
||||
</div>
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue