feat(desktop): pin/unpin from message context menu + side panel

This commit is contained in:
byGalax
2026-05-16 17:51:01 +02:00
parent 6bff163f09
commit 3dbeabd268
2 changed files with 65 additions and 1 deletions
@@ -31,6 +31,7 @@ import {
PencilIcon,
PhoneIcon,
PhoneOffIcon,
PinIcon,
ReplyIcon,
SmileIcon,
SpinnerIcon,
@@ -76,6 +77,10 @@ interface Props {
onAvatarClick?: (userId: string, ev: React.MouseEvent) => void;
/** Highlighted state — set briefly after a jump. */
highlighted?: boolean;
/** True iff this message is currently pinned (parent maintains the set). */
isPinned?: boolean;
/** Right-click menu → toggle pin/unpin for this message id. */
onTogglePin?: (messageId: string) => void;
}
export function MessageBubble({
@@ -97,6 +102,8 @@ export function MessageBubble({
onForward,
onAvatarClick,
highlighted = false,
isPinned = false,
onTogglePin,
}: Props) {
const { t } = useTranslation(['app']);
const { session } = useAuth();
@@ -642,6 +649,15 @@ export function MessageBubble({
setContextMenu(null);
void handleDelete();
}}
isPinned={isPinned}
{...(onTogglePin
? {
onTogglePin: () => {
setContextMenu(null);
onTogglePin(message.id);
},
}
: {})}
/>
)}
</div>
@@ -739,6 +755,8 @@ function MessageContextMenu({
onEdit,
onCopy,
onDelete,
isPinned,
onTogglePin,
}: {
x: number;
y: number;
@@ -753,6 +771,8 @@ function MessageContextMenu({
onEdit: () => void;
onCopy: () => void;
onDelete: () => void;
isPinned?: boolean;
onTogglePin?: () => void;
}) {
useEffect(() => {
function onKey(e: KeyboardEvent) {
@@ -819,6 +839,13 @@ function MessageContextMenu({
tone="danger"
/>
)}
{onTogglePin && (
<MenuItem
label={isPinned ? 'Anheftung entfernen' : 'Anpinnen'}
icon={<PinIcon className="h-4 w-4" />}
onClick={onTogglePin}
/>
)}
</div>,
document.body,
);