diff --git a/web/src/ui/timeline/menu/EventMenu.tsx b/web/src/ui/timeline/menu/EventMenu.tsx index 8864bb8..3f26808 100644 --- a/web/src/ui/timeline/menu/EventMenu.tsx +++ b/web/src/ui/timeline/menu/EventMenu.tsx @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . import { CSSProperties, use, useCallback, useRef } from "react" -import { MemDBEvent } from "@/api/types" +import { MemDBEvent, PowerLevelEventContent } from "@/api/types" import { emojiToReactionContent } from "@/util/emoji" import { useEventAsState } from "@/util/eventdispatcher.ts" import ClientContext from "../../ClientContext.ts" @@ -86,15 +86,32 @@ const EventMenu = ({ evt, setForceOpen }: EventHoverMenuProps) => { const isEditing = useEventAsState(roomCtx.isEditing) const isPending = evt.event_id.startsWith("~") 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
- - } + {canSend && - {evt.sender === userID && evt.type === "m.room.message" && evt.relation_type !== "m.replace" && !evt.redacted_by - && } + >} + {canEdit && }
}