diff --git a/src/app/components/event-action-button/EventActionButton.css.ts b/src/app/components/event-action-button/EventActionButton.css.ts
new file mode 100644
index 00000000..20189ee4
--- /dev/null
+++ b/src/app/components/event-action-button/EventActionButton.css.ts
@@ -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',
+ },
+});
diff --git a/src/app/components/event-action-button/EventActionButton.tsx b/src/app/components/event-action-button/EventActionButton.tsx
new file mode 100644
index 00000000..f15d7073
--- /dev/null
+++ b/src/app/components/event-action-button/EventActionButton.tsx
@@ -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) => (
+
+ )
+);
diff --git a/src/app/components/message/MessageJumpLink.css.ts b/src/app/components/message/MessageJumpLink.css.ts
deleted file mode 100644
index f506af33..00000000
--- a/src/app/components/message/MessageJumpLink.css.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { style } from '@vanilla-extract/css';
-
-export const messageJumpLink = style({
- ':hover': {
- cursor: 'pointer',
- textDecoration: 'underline',
- },
-});
diff --git a/src/app/components/message/MessageJumpLink.tsx b/src/app/components/message/MessageJumpLink.tsx
deleted file mode 100644
index 3af4513f..00000000
--- a/src/app/components/message/MessageJumpLink.tsx
+++ /dev/null
@@ -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 (
-
- );
-}
\ No newline at end of file
diff --git a/src/app/hooks/usePinnedEventParser.tsx b/src/app/hooks/usePinnedEventParser.tsx
index 48b69648..5ea12eff 100644
--- a/src/app/hooks/usePinnedEventParser.tsx
+++ b/src/app/hooks/usePinnedEventParser.tsx
@@ -1,54 +1,67 @@
import { MatrixEvent } from 'matrix-js-sdk';
-import React, { ReactNode } from 'react';
-import { IRoomPinnedEventsContent } from '../../types/matrix/room';
+import React, { ReactNode, useCallback } from 'react';
+import { RoomPinnedEventsEventContent } from 'matrix-js-sdk/lib/types';
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 => {
+ const { navigateRoom } = useRoomNavigate();
+
+ const navigate = useCallback(
+ (eventId: string) => {
+ navigateRoom(roomId, eventId);
+ },
+ [navigateRoom, roomId]
+ );
+
const pinnedEventParser = (mEvent: MatrixEvent) => {
- const { pinned } = mEvent.getContent();
- const prevPinned = (mEvent.getPrevContent() as Partial).pinned;
+ const { pinned } = mEvent.getContent();
+ const prevPinned = (mEvent.getPrevContent() as Partial).pinned;
const senderId = mEvent.getSender() ?? '';
const senderName = getMxIdLocalPart(senderId);
- const addedPins = pinned.filter((pdu) => !(prevPinned?.includes(pdu) ?? false));
- const removedPins = prevPinned?.filter((pdu) => !pinned.includes(pdu)) ?? [];
+ const addedPins = pinned.filter((event) => !(prevPinned?.includes(event) ?? false));
+ 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 (
<>
{senderName}
- {addedPins.length === 0 && removedPins.length === 0 ? (
- ' made no changes to the pinned messages'
- ) : (
- <>
- {addedPins.length > 0 && (
- <>
- {' pinned '}
-
- {addedPins.length === 1 ? (
-
- ) : (
- `${addedPins.length} messages`
- )}
-
- >
- )}
- {addedPins.length > 0 && removedPins.length > 0 && 'and'}
- {removedPins.length > 0 && (
- <>
- {' unpinned '}
-
- {removedPins.length === 1 ? (
-
- ) : (
- `${removedPins.length} messages`
- )}
-
- >
- )}
- >
+ {` ${bodyMessages.join(' and ')}. `}
+ {jumpTarget && (
+ navigate(jumpTarget)}>
+ View Message
+
)}
>
);
diff --git a/src/app/utils/common.ts b/src/app/utils/common.ts
index 678f1b6e..5594c7cf 100644
--- a/src/app/utils/common.ts
+++ b/src/app/utils/common.ts
@@ -138,3 +138,5 @@ export const splitWithSpace = (content: string): string[] => {
if (trimmedContent === '') return [];
return trimmedContent.split(' ');
};
+
+export const singleOrNull = (array: T[]): T | null => (array.length === 1 ? array[0] : null);
diff --git a/src/types/matrix/room.ts b/src/types/matrix/room.ts
index ce907cb4..b866fd77 100644
--- a/src/types/matrix/room.ts
+++ b/src/types/matrix/room.ts
@@ -77,10 +77,6 @@ export type IRoomCreateContent = {
};
};
-export type IRoomPinnedEventsContent = {
- pinned: string[];
-};
-
export type GetContentCallback = () => T;
export type RoomToParents = Map>;