17
17
import React , { JSX , useEffect , useMemo , useState } from "react" ;
18
18
import { Icon as PinIcon } from "@vector-im/compound-design-tokens/icons/pin-solid.svg" ;
19
19
import { Button } from "@vector-im/compound-web" ;
20
- import { Room } from "matrix-js-sdk/src/matrix" ;
20
+ import { M_POLL_START , MatrixEvent , MsgType , Room } from "matrix-js-sdk/src/matrix" ;
21
21
import classNames from "classnames" ;
22
22
23
23
import { usePinnedEvents , useSortedFetchedPinnedEvents } from "../../../hooks/usePinnedEvents" ;
@@ -59,16 +59,10 @@ export function PinnedMessageBanner({ room, permalinkCreator }: PinnedMessageBan
59
59
const [ currentEventIndex , setCurrentEventIndex ] = useState ( eventCount - 1 ) ;
60
60
// When the number of pinned messages changes, we want to display the last message
61
61
useEffect ( ( ) => {
62
- setCurrentEventIndex ( ( currentEventIndex ) => eventCount - 1 ) ;
62
+ setCurrentEventIndex ( ( ) => eventCount - 1 ) ;
63
63
} , [ eventCount ] ) ;
64
64
65
65
const pinnedEvent = pinnedEvents [ currentEventIndex ] ;
66
- // Generate a preview for the pinned event
67
- const eventPreview = useMemo ( ( ) => {
68
- if ( ! pinnedEvent || pinnedEvent . isRedacted ( ) || pinnedEvent . isDecryptionFailure ( ) ) return null ;
69
- return MessagePreviewStore . instance . generatePreviewForEvent ( pinnedEvent ) ;
70
- } , [ pinnedEvent ] ) ;
71
-
72
66
if ( ! pinnedEvent ) return null ;
73
67
74
68
const shouldUseMessageEvent = pinnedEvent . isRedacted ( ) || pinnedEvent . isDecryptionFailure ( ) ;
@@ -116,7 +110,7 @@ export function PinnedMessageBanner({ room, permalinkCreator }: PinnedMessageBan
116
110
) }
117
111
</ div >
118
112
) }
119
- { eventPreview && < span className = "mx_PinnedMessageBanner_message" > { eventPreview } </ span > }
113
+ < EventPreview pinnedEvent = { pinnedEvent } />
120
114
{ /* In case of redacted event, we want to display the nice sentence of the message event like in the timeline or in the pinned message list */ }
121
115
{ shouldUseMessageEvent && (
122
116
< div className = "mx_PinnedMessageBanner_redactedMessage" >
@@ -135,6 +129,84 @@ export function PinnedMessageBanner({ room, permalinkCreator }: PinnedMessageBan
135
129
) ;
136
130
}
137
131
132
+ /**
133
+ * The props for the {@link EventPreview} component.
134
+ */
135
+ interface EventPreviewProps {
136
+ /**
137
+ * The pinned event to display the preview for
138
+ */
139
+ pinnedEvent : MatrixEvent ;
140
+ }
141
+
142
+ /**
143
+ * A component that displays a preview for the pinned event.
144
+ */
145
+ function EventPreview ( { pinnedEvent } : EventPreviewProps ) : JSX . Element | null {
146
+ const preview = useEventPreview ( pinnedEvent ) ;
147
+ if ( ! preview ) return null ;
148
+
149
+ const prefix = getPreviewPrefix ( pinnedEvent . getType ( ) , pinnedEvent . getContent ( ) . msgtype as MsgType ) ;
150
+ if ( ! prefix )
151
+ return (
152
+ < span className = "mx_PinnedMessageBanner_message" data-testid = "banner-message" >
153
+ { preview }
154
+ </ span >
155
+ ) ;
156
+
157
+ return (
158
+ < span className = "mx_PinnedMessageBanner_message" data-testid = "banner-message" >
159
+ { _t (
160
+ "room|pinned_message_banner|preview" ,
161
+ {
162
+ prefix,
163
+ preview,
164
+ } ,
165
+ {
166
+ bold : ( sub ) => < span className = "mx_PinnedMessageBanner_prefix" > { sub } </ span > ,
167
+ } ,
168
+ ) }
169
+ </ span >
170
+ ) ;
171
+ }
172
+
173
+ /**
174
+ * Hooks to generate a preview for the pinned event.
175
+ * @param pinnedEvent
176
+ */
177
+ function useEventPreview ( pinnedEvent : MatrixEvent | null ) : string | null {
178
+ return useMemo ( ( ) => {
179
+ if ( ! pinnedEvent || pinnedEvent . isRedacted ( ) || pinnedEvent . isDecryptionFailure ( ) ) return null ;
180
+ return MessagePreviewStore . instance . generatePreviewForEvent ( pinnedEvent ) ;
181
+ } , [ pinnedEvent ] ) ;
182
+ }
183
+
184
+ /**
185
+ * Get the prefix for the preview based on the type and the message type.
186
+ * @param type
187
+ * @param msgType
188
+ */
189
+ function getPreviewPrefix ( type : string , msgType : MsgType ) : string | null {
190
+ switch ( type ) {
191
+ case M_POLL_START . name :
192
+ return _t ( "room|pinned_message_banner|prefix|poll" ) ;
193
+ default :
194
+ }
195
+
196
+ switch ( msgType ) {
197
+ case MsgType . Audio :
198
+ return _t ( "room|pinned_message_banner|prefix|audio" ) ;
199
+ case MsgType . Image :
200
+ return _t ( "room|pinned_message_banner|prefix|image" ) ;
201
+ case MsgType . Video :
202
+ return _t ( "room|pinned_message_banner|prefix|video" ) ;
203
+ case MsgType . File :
204
+ return _t ( "room|pinned_message_banner|prefix|file" ) ;
205
+ default :
206
+ return null ;
207
+ }
208
+ }
209
+
138
210
const MAX_INDICATORS = 3 ;
139
211
140
212
/**
0 commit comments