web/timeline: remove edit/reply/react buttons based on power levels

This commit is contained in:
Tulir Asokan 2024-11-12 14:18:01 +02:00
parent 465d7c3524
commit 8097d5056b

View file

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import { CSSProperties, use, useCallback, useRef } from "react" import { CSSProperties, use, useCallback, useRef } from "react"
import { MemDBEvent } from "@/api/types" import { MemDBEvent, PowerLevelEventContent } from "@/api/types"
import { emojiToReactionContent } from "@/util/emoji" import { emojiToReactionContent } from "@/util/emoji"
import { useEventAsState } from "@/util/eventdispatcher.ts" import { useEventAsState } from "@/util/eventdispatcher.ts"
import ClientContext from "../../ClientContext.ts" import ClientContext from "../../ClientContext.ts"
@ -86,15 +86,32 @@ const EventMenu = ({ evt, setForceOpen }: EventHoverMenuProps) => {
const isEditing = useEventAsState(roomCtx.isEditing) const isEditing = useEventAsState(roomCtx.isEditing)
const isPending = evt.event_id.startsWith("~") const isPending = evt.event_id.startsWith("~")
const pendingTitle = isPending ? "Can't action messages that haven't been sent yet" : undefined const pendingTitle = isPending ? "Can't action messages that haven't been sent yet" : undefined
// TODO should these subscribe to the store?
const plEvent = roomCtx.store.getStateEvent("m.room.power_levels", "")
const encryptionEvent = roomCtx.store.getStateEvent("m.room.encryption", "")
const isEncrypted = encryptionEvent?.content?.algorithm === "m.megolm.v1.aes-sha2"
const pls = (plEvent?.content ?? {}) as PowerLevelEventContent
const ownPL = pls.users?.[userID] ?? pls.users_default ?? 0
const reactPL = pls.events?.["m.reaction"] ?? pls.events_default ?? 0
const evtSendType = isEncrypted ? "m.room.encrypted" : evt.type === "m.sticker" ? "m.sticker" : "m.room.message"
const messageSendPL = pls.events?.[evtSendType] ?? pls.events_default ?? 0
const canSend = ownPL >= messageSendPL
const canEdit = canSend
&& evt.sender === userID
&& evt.type === "m.room.message"
&& evt.relation_type !== "m.replace"
&& !evt.redacted_by
const canReact = ownPL >= reactPL
return <div className="event-hover-menu" ref={contextMenuRef}> return <div className="event-hover-menu" ref={contextMenuRef}>
<button disabled={isPending} title={pendingTitle} onClick={onClickReact}><ReactIcon/></button> {canReact && <button disabled={isPending} title={pendingTitle} onClick={onClickReact}><ReactIcon/></button>}
<button {canSend && <button
disabled={isEditing || isPending} disabled={isEditing || isPending}
title={isEditing ? "Can't reply to messages while editing a message" : pendingTitle} title={isEditing ? "Can't reply to messages while editing a message" : pendingTitle}
onClick={onClickReply} onClick={onClickReply}
><ReplyIcon/></button> ><ReplyIcon/></button>}
{evt.sender === userID && evt.type === "m.room.message" && evt.relation_type !== "m.replace" && !evt.redacted_by {canEdit && <button onClick={onClickEdit} disabled={isPending} title={pendingTitle}><EditIcon/></button>}
&& <button onClick={onClickEdit} disabled={isPending} title={pendingTitle}><EditIcon/></button>}
<button onClick={onClickMore}><MoreIcon/></button> <button onClick={onClickMore}><MoreIcon/></button>
</div> </div>
} }