// gomuks - A Matrix client written in Go. // Copyright (C) 2024 Tulir Asokan // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . import { use } from "react" import Client from "@/api/client.ts" import { useRoomState } from "@/api/statestore" import { MemDBEvent } from "@/api/types" import { ModalCloseContext, ModalContext } from "../../modal" import { RoomContext, RoomContextData } from "../../roomview/roomcontext.ts" import JSONView from "../../util/JSONView.tsx" import ConfirmWithMessageModal from "./ConfirmWithMessageModal.tsx" import ShareModal from "./ShareModal.tsx" import { getPending, getPowerLevels } from "./util.ts" import ViewSourceIcon from "@/icons/code.svg?react" import DeleteIcon from "@/icons/delete.svg?react" import PinIcon from "@/icons/pin.svg?react" import ReportIcon from "@/icons/report.svg?react" import ShareIcon from "@/icons/share.svg?react" import UnpinIcon from "@/icons/unpin.svg?react" export const useSecondaryItems = ( client: Client, roomCtx: RoomContextData, evt: MemDBEvent, names = true, ) => { const closeModal = use(ModalCloseContext) const openModal = use(ModalContext) const onClickViewSource = () => { openModal({ dimmed: true, boxed: true, content: , }) } const onClickReport = () => { openModal({ dimmed: true, boxed: true, innerBoxClass: "confirm-message-modal", content: { client.rpc.reportEvent(evt.room_id, evt.event_id, reason) .catch(err => window.alert(`Failed to report message: ${err}`)) }} /> , }) } const onClickRedact = () => { openModal({ dimmed: true, boxed: true, innerBoxClass: "confirm-message-modal", content: { client.rpc.redactEvent(evt.room_id, evt.event_id, reason) .catch(err => window.alert(`Failed to redact message: ${err}`)) }} /> , }) } const onClickPin = (pin: boolean) => () => { closeModal() client.pinMessage(roomCtx.store, evt.event_id, pin) .catch(err => window.alert(`Failed to ${pin ? "pin" : "unpin"} message: ${err}`)) } const onClickShareEvent = () => { const generateLink = (useMatrixTo: boolean, includeEvent: boolean) => { const isRoomIDLink = true let generatedURL = useMatrixTo ? "https://matrix.to/#/" : "matrix:roomid/" if (useMatrixTo) { generatedURL += evt.room_id } else { generatedURL += `${evt.room_id.slice(1)}` } if (includeEvent) { if (useMatrixTo) { generatedURL += `/${evt.event_id}` } else { generatedURL += `/e/${evt.event_id.slice(1)}` } } if (isRoomIDLink) { generatedURL += "?" + new URLSearchParams( roomCtx.store.getViaServers().map(server => ["via", server]), ).toString() } return generatedURL } openModal({ dimmed: true, boxed: true, innerBoxClass: "confirm-message-modal", content: { navigator.clipboard.writeText(generateLink(useMatrixTo, includeEvent)).catch( err => window.alert(`Failed to copy link: ${err}`), ) }} generateLink={generateLink} /> , }) } const [isPending, pendingTitle] = getPending(evt) useRoomState(roomCtx.store, "m.room.power_levels", "") // We get pins from getPinnedEvents, but use the hook anyway to subscribe to changes useRoomState(roomCtx.store, "m.room.pinned_events", "") const [pls, ownPL] = getPowerLevels(roomCtx.store, client) const pins = roomCtx.store.getPinnedEvents() const pinPL = pls.events?.["m.room.pinned_events"] ?? pls.state_default ?? 50 const redactEvtPL = pls.events?.["m.room.redaction"] ?? pls.events_default ?? 0 const redactOtherPL = pls.redact ?? 50 const canRedact = !evt.redacted_by && ownPL >= redactEvtPL && (evt.sender === client.userID || ownPL >= redactOtherPL) return <> {ownPL >= pinPL && (pins.includes(evt.event_id) ? : )} {canRedact && } }