Apply requested changes

This commit is contained in:
Ginger 2025-09-26 10:11:03 -04:00
parent bd6c164804
commit 52fde65973
No known key found for this signature in database
7 changed files with 105 additions and 63 deletions

View file

@ -0,0 +1,38 @@
import { ComplexStyleRule } from '@vanilla-extract/css';
import { recipe } from '@vanilla-extract/recipes';
import { color, DefaultReset, MainColor } from 'folds';
const getVariant = (variant: MainColor): ComplexStyleRule => ({
vars: {
color: color[variant].Main,
},
selectors: {
'&:hover': {
color: color[variant].MainHover,
},
},
});
export const EventActionButton = recipe({
base: [
DefaultReset,
{
':hover': {
textDecoration: 'underline',
},
cursor: 'pointer',
},
],
variants: {
variant: {
Primary: getVariant('Primary'),
Secondary: getVariant('Secondary'),
Success: getVariant('Success'),
Warning: getVariant('Warning'),
Critical: getVariant('Critical'),
},
},
defaultVariants: {
variant: 'Primary',
},
});

View file

@ -0,0 +1,14 @@
import React from "react";
import { as, MainColor } from "folds";
import classNames from "classnames";
import * as css from "./EventActionButton.css";
export const EventActionButton = as<'button', { variant?: MainColor }>(
({ as: AsCutoutCard = 'button', className, variant = 'Primary', ...props }, ref) => (
<AsCutoutCard
className={classNames(css.EventActionButton({ variant }), className)}
{...props}
ref={ref}
/>
)
);

View file

@ -1,8 +0,0 @@
import { style } from '@vanilla-extract/css';
export const messageJumpLink = style({
':hover': {
cursor: 'pointer',
textDecoration: 'underline',
},
});

View file

@ -1,13 +0,0 @@
import React from "react";
import { messageJumpLink } from "./MessageJumpLink.css";
import { useRoomNavigate } from "../../hooks/useRoomNavigate";
export function MessageJumpLink({ roomId, eventId }: { roomId: string, eventId: string }) {
const { navigateRoom } = useRoomNavigate();
return (
<button type="button" className={messageJumpLink} onClick={() => navigateRoom(roomId, eventId)}>
a message
</button>
);
}

View file

@ -1,54 +1,67 @@
import { MatrixEvent } from 'matrix-js-sdk'; import { MatrixEvent } from 'matrix-js-sdk';
import React, { ReactNode } from 'react'; import React, { ReactNode, useCallback } from 'react';
import { IRoomPinnedEventsContent } from '../../types/matrix/room'; import { RoomPinnedEventsEventContent } from 'matrix-js-sdk/lib/types';
import { getMxIdLocalPart } from '../utils/matrix'; import { getMxIdLocalPart } from '../utils/matrix';
import { MessageJumpLink } from '../components/message/MessageJumpLink'; import { EventActionButton } from '../components/event-action-button/EventActionButton';
import { useRoomNavigate } from './useRoomNavigate';
import { singleOrNull } from '../utils/common';
export type PinnedEventParser = (mEvent: MatrixEvent) => ReactNode; export type PinnedEventParser = (mEvent: MatrixEvent) => ReactNode | null;
export const usePinnedEventParser = (roomId: string): PinnedEventParser => { export const usePinnedEventParser = (roomId: string): PinnedEventParser => {
const { navigateRoom } = useRoomNavigate();
const navigate = useCallback(
(eventId: string) => {
navigateRoom(roomId, eventId);
},
[navigateRoom, roomId]
);
const pinnedEventParser = (mEvent: MatrixEvent) => { const pinnedEventParser = (mEvent: MatrixEvent) => {
const { pinned } = mEvent.getContent<IRoomPinnedEventsContent>(); const { pinned } = mEvent.getContent<RoomPinnedEventsEventContent>();
const prevPinned = (mEvent.getPrevContent() as Partial<IRoomPinnedEventsContent>).pinned; const prevPinned = (mEvent.getPrevContent() as Partial<RoomPinnedEventsEventContent>).pinned;
const senderId = mEvent.getSender() ?? ''; const senderId = mEvent.getSender() ?? '';
const senderName = getMxIdLocalPart(senderId); const senderName = getMxIdLocalPart(senderId);
const addedPins = pinned.filter((pdu) => !(prevPinned?.includes(pdu) ?? false)); const addedPins = pinned.filter((event) => !(prevPinned?.includes(event) ?? false));
const removedPins = prevPinned?.filter((pdu) => !pinned.includes(pdu)) ?? []; const removedPins = prevPinned?.filter((event) => !pinned.includes(event)) ?? [];
const bodyMessages: string[] = [];
// if only one event was added/removed total, show a link to jump to it
const jumpTarget = singleOrNull(addedPins.concat(removedPins));
// if this event didn't change anything, don't show the message at all
if (addedPins.length === 0 && removedPins.length === 0) {
return null;
}
// check for added pins
if (addedPins.length > 0) {
if (addedPins.length === 1) {
bodyMessages.push('pinned a message');
} else {
bodyMessages.push(`pinned ${addedPins.length} messages`);
}
}
// check for removed pins
if (removedPins.length > 0) {
if (removedPins.length === 1) {
bodyMessages.push('unpinned a message');
} else {
bodyMessages.push(`unpinned ${removedPins.length} messages`);
}
}
return ( return (
<> <>
<b>{senderName}</b> <b>{senderName}</b>
{addedPins.length === 0 && removedPins.length === 0 ? ( {` ${bodyMessages.join(' and ')}. `}
' made no changes to the pinned messages' {jumpTarget && (
) : ( <EventActionButton onClick={() => navigate(jumpTarget)}>
<> <b>View Message</b>
{addedPins.length > 0 && ( </EventActionButton>
<>
{' pinned '}
<b>
{addedPins.length === 1 ? (
<MessageJumpLink roomId={roomId} eventId={addedPins[0]} />
) : (
`${addedPins.length} messages`
)}
</b>
</>
)}
{addedPins.length > 0 && removedPins.length > 0 && 'and'}
{removedPins.length > 0 && (
<>
{' unpinned '}
<b>
{removedPins.length === 1 ? (
<MessageJumpLink roomId={roomId} eventId={removedPins[0]} />
) : (
`${removedPins.length} messages`
)}
</b>
</>
)}
</>
)} )}
</> </>
); );

View file

@ -138,3 +138,5 @@ export const splitWithSpace = (content: string): string[] => {
if (trimmedContent === '') return []; if (trimmedContent === '') return [];
return trimmedContent.split(' '); return trimmedContent.split(' ');
}; };
export const singleOrNull = <T>(array: T[]): T | null => (array.length === 1 ? array[0] : null);

View file

@ -77,10 +77,6 @@ export type IRoomCreateContent = {
}; };
}; };
export type IRoomPinnedEventsContent = {
pinned: string[];
};
export type GetContentCallback = <T>() => T; export type GetContentCallback = <T>() => T;
export type RoomToParents = Map<string, Set<string>>; export type RoomToParents = Map<string, Set<string>>;