diff --git a/src/components/common/messaging/Message.tsx b/src/components/common/messaging/Message.tsx index 778e932c..68517fd3 100644 --- a/src/components/common/messaging/Message.tsx +++ b/src/components/common/messaging/Message.tsx @@ -25,6 +25,7 @@ import MessageBase, { } from "./MessageBase"; import Attachment from "./attachments/Attachment"; import { MessageReply } from "./attachments/MessageReply"; +import { MessageOverlayBar } from "./bars/MessageOverlayBar"; import Embed from "./embed/Embed"; import InviteList from "./embed/EmbedInvite"; @@ -86,7 +87,7 @@ const Message = observer( }; // ! FIXME(?): animate on hover - const [animate, setAnimate] = useState(false); + const [mouseHovering, setAnimate] = useState(false); return (
@@ -135,7 +136,7 @@ const Message = observer( size={36} onContextMenu={userContext} onClick={handleUserClick} - animate={animate} + animate={mouseHovering} showServerIdentity /> ) : ( @@ -174,6 +175,12 @@ const Message = observer( {message.embeds?.map((embed, index) => ( ))} + {mouseHovering && !replacement && ( + + )}
diff --git a/src/components/common/messaging/MessageBase.tsx b/src/components/common/messaging/MessageBase.tsx index e970a4ab..33a3471e 100644 --- a/src/components/common/messaging/MessageBase.tsx +++ b/src/components/common/messaging/MessageBase.tsx @@ -195,6 +195,10 @@ export const MessageInfo = styled.div` `; export const MessageContent = styled.div` + // Position relatively so we can put + // the overlay in the right place. + position: relative; + min-width: 0; flex-grow: 1; display: flex; diff --git a/src/components/common/messaging/bars/MessageOverlayBar.tsx b/src/components/common/messaging/bars/MessageOverlayBar.tsx new file mode 100644 index 00000000..848a1bff --- /dev/null +++ b/src/components/common/messaging/bars/MessageOverlayBar.tsx @@ -0,0 +1,117 @@ +import { + DotsHorizontalRounded, + Edit, + Reply, + Trash, +} from "@styled-icons/boxicons-regular"; +import { observer } from "mobx-react-lite"; +import { ChannelPermission } from "revolt.js"; +import { Message as MessageObject } from "revolt.js/dist/maps/Messages"; +import styled from "styled-components"; + +import { openContextMenu } from "preact-context-menu"; + +import { internalEmit } from "../../../../lib/eventEmitter"; + +import { QueuedMessage } from "../../../../mobx/stores/MessageQueue"; + +import { + Screen, + useIntermediate, +} from "../../../../context/intermediate/Intermediate"; +import { useClient } from "../../../../context/revoltjs/RevoltClient"; + +import IconButton from "../../../ui/IconButton"; + +interface Props { + message: MessageObject; + queued?: QueuedMessage; +} + +const OverlayBar = styled.div` + display: inline-flex; + position: absolute; + justify-self: end; + align-self: end; + align-content: center; + justify-content: center; + + right: 0; + top: -18px; + z-index: 0; + overflow: hidden; + + border-radius: 5px; + background: var(--primary-header); + border: 1px sold var(--background); +`; + +const Entry = styled.div` + padding: 4px; + flex-shrink: 0; + cursor: pointer; + transition: 0.2s ease background-color; + + &:hover { + background: var(--secondary-header); + } +`; + +export const MessageOverlayBar = observer(({ message, queued }: Props) => { + const client = useClient(); + const { openScreen } = useIntermediate(); + const isAuthor = message.author_id === client.user!._id; + + return ( + + internalEmit("ReplyBar", "add", message)}> + + + + + {isAuthor && ( + + internalEmit( + "MessageRenderer", + "edit_message", + message._id, + ) + }> + + + + + )} + {isAuthor || + (message.channel && + message.channel.permission & + ChannelPermission.ManageMessages) ? ( + + openScreen({ + id: "special_prompt", + type: "delete_message", + target: message, + } as unknown as Screen) + }> + + + + + ) : undefined} + + openContextMenu("Menu", { + message, + contextualChannel: message.channel_id, + queued, + }) + }> + + + + + + ); +});