Convert several internal maps to real maps
							parent
							
								
									aace3a8c28
								
							
						
					
					
						commit
						37a527c61f
					
				|  | @ -59,11 +59,30 @@ export interface IOperableEventTile { | |||
|     getEventTileOps(): IEventTileOps; | ||||
| } | ||||
| 
 | ||||
| const baseBodyTypes = new Map<string, typeof React.Component>([ | ||||
|     [MsgType.Text, TextualBody], | ||||
|     [MsgType.Notice, TextualBody], | ||||
|     [MsgType.Emote, TextualBody], | ||||
|     [MsgType.Image, MImageBody], | ||||
|     [MsgType.File, MFileBody], | ||||
|     [MsgType.Audio, MVoiceOrAudioBody], | ||||
|     [MsgType.Video, MVideoBody], | ||||
| ]); | ||||
| const baseEvTypes = new Map<string, React.ComponentType<Partial<IBodyProps>>>([ | ||||
|     [EventType.Sticker, MStickerBody], | ||||
|     [M_POLL_START.name, MPollBody], | ||||
|     [M_POLL_START.altName, MPollBody], | ||||
|     [M_BEACON_INFO.name, MBeaconBody], | ||||
|     [M_BEACON_INFO.altName, MBeaconBody], | ||||
| ]); | ||||
| 
 | ||||
| export default class MessageEvent extends React.Component<IProps> implements IMediaBody, IOperableEventTile { | ||||
|     private body: React.RefObject<React.Component | IOperableEventTile> = createRef(); | ||||
|     private mediaHelper: MediaEventHelper; | ||||
|     private bodyTypes = new Map<string, typeof React.Component>(baseBodyTypes.entries()); | ||||
|     private evTypes = new Map<string, React.ComponentType<Partial<IBodyProps>>>(baseEvTypes.entries()); | ||||
| 
 | ||||
|     static contextType = MatrixClientContext; | ||||
|     public static contextType = MatrixClientContext; | ||||
|     public context!: React.ContextType<typeof MatrixClientContext>; | ||||
| 
 | ||||
|     public constructor(props: IProps, context: React.ContextType<typeof MatrixClientContext>) { | ||||
|  | @ -72,6 +91,8 @@ export default class MessageEvent extends React.Component<IProps> implements IMe | |||
|         if (MediaEventHelper.isEligible(this.props.mxEvent)) { | ||||
|             this.mediaHelper = new MediaEventHelper(this.props.mxEvent); | ||||
|         } | ||||
| 
 | ||||
|         this.updateComponentMaps(); | ||||
|     } | ||||
| 
 | ||||
|     public componentDidMount(): void { | ||||
|  | @ -88,32 +109,20 @@ export default class MessageEvent extends React.Component<IProps> implements IMe | |||
|             this.mediaHelper?.destroy(); | ||||
|             this.mediaHelper = new MediaEventHelper(this.props.mxEvent); | ||||
|         } | ||||
| 
 | ||||
|         this.updateComponentMaps(); | ||||
|     } | ||||
| 
 | ||||
|     private get bodyTypes(): Record<string, typeof React.Component> { | ||||
|         return { | ||||
|             [MsgType.Text]: TextualBody, | ||||
|             [MsgType.Notice]: TextualBody, | ||||
|             [MsgType.Emote]: TextualBody, | ||||
|             [MsgType.Image]: MImageBody, | ||||
|             [MsgType.File]: MFileBody, | ||||
|             [MsgType.Audio]: MVoiceOrAudioBody, | ||||
|             [MsgType.Video]: MVideoBody, | ||||
|     private updateComponentMaps() { | ||||
|         this.bodyTypes = new Map<string, typeof React.Component>(baseBodyTypes.entries()); | ||||
|         for (const [bodyType, bodyComponent] of Object.entries(this.props.overrideBodyTypes ?? {})) { | ||||
|             this.bodyTypes.set(bodyType, bodyComponent); | ||||
|         } | ||||
| 
 | ||||
|             ...(this.props.overrideBodyTypes || {}), | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     private get evTypes(): Record<string, React.ComponentType<Partial<IBodyProps>>> { | ||||
|         return { | ||||
|             [EventType.Sticker]: MStickerBody, | ||||
|             [M_POLL_START.name]: MPollBody, | ||||
|             [M_POLL_START.altName]: MPollBody, | ||||
|             [M_BEACON_INFO.name]: MBeaconBody, | ||||
|             [M_BEACON_INFO.altName]: MBeaconBody, | ||||
| 
 | ||||
|             ...(this.props.overrideEventTypes || {}), | ||||
|         }; | ||||
|         this.evTypes = new Map<string, React.ComponentType<Partial<IBodyProps>>>(baseEvTypes.entries()); | ||||
|         for (const [evType, evComponent] of Object.entries(this.props.overrideEventTypes ?? {})) { | ||||
|             this.evTypes.set(evType, evComponent); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public getEventTileOps = () => { | ||||
|  | @ -143,13 +152,13 @@ export default class MessageEvent extends React.Component<IProps> implements IMe | |||
|         let BodyType: React.ComponentType<Partial<IBodyProps>> | ReactAnyComponent = RedactedBody; | ||||
|         if (!this.props.mxEvent.isRedacted()) { | ||||
|             // only resolve BodyType if event is not redacted
 | ||||
|             if (type && this.evTypes[type]) { | ||||
|                 BodyType = this.evTypes[type]; | ||||
|             } else if (msgtype && this.bodyTypes[msgtype]) { | ||||
|                 BodyType = this.bodyTypes[msgtype]; | ||||
|             if (type && this.evTypes.has(type)) { | ||||
|                 BodyType = this.evTypes.get(type); | ||||
|             } else if (msgtype && this.bodyTypes.has(msgtype)) { | ||||
|                 BodyType = this.bodyTypes.get(msgtype); | ||||
|             } else if (content.url) { | ||||
|                 // Fallback to MFileBody if there's a content URL
 | ||||
|                 BodyType = this.bodyTypes[MsgType.File]; | ||||
|                 BodyType = this.bodyTypes.get(MsgType.File); | ||||
|             } else { | ||||
|                 // Fallback to UnknownBody otherwise if not redacted
 | ||||
|                 BodyType = UnknownBody; | ||||
|  |  | |||
|  | @ -67,7 +67,6 @@ export interface EventTileTypeProps { | |||
| 
 | ||||
| type FactoryProps = Omit<EventTileTypeProps, "ref">; | ||||
| type Factory<X = FactoryProps> = (ref: Optional<React.RefObject<any>>, props: X) => JSX.Element; | ||||
| type FactoryMap = Record<string, Factory>; | ||||
| 
 | ||||
| const MessageEventFactory: Factory = (ref, props) => <MessageEvent ref={ref} {...props} />; | ||||
| const KeyVerificationConclFactory: Factory = (ref, props) => <MKeyVerificationConclusion ref={ref} {...props} />; | ||||
|  | @ -82,40 +81,40 @@ const HiddenEventFactory: Factory = (ref, props) => <HiddenBody ref={ref} {...pr | |||
| export const JitsiEventFactory: Factory = (ref, props) => <MJitsiWidgetEvent ref={ref} {...props} />; | ||||
| export const JSONEventFactory: Factory = (ref, props) => <ViewSourceEvent ref={ref} {...props} />; | ||||
| 
 | ||||
| const EVENT_TILE_TYPES: FactoryMap = { | ||||
|     [EventType.RoomMessage]: MessageEventFactory, // note that verification requests are handled in pickFactory()
 | ||||
|     [EventType.Sticker]: MessageEventFactory, | ||||
|     [M_POLL_START.name]: MessageEventFactory, | ||||
|     [M_POLL_START.altName]: MessageEventFactory, | ||||
|     [EventType.KeyVerificationCancel]: KeyVerificationConclFactory, | ||||
|     [EventType.KeyVerificationDone]: KeyVerificationConclFactory, | ||||
|     [EventType.CallInvite]: CallEventFactory, // note that this requires a special factory type
 | ||||
| }; | ||||
| const EVENT_TILE_TYPES = new Map<string, Factory>([ | ||||
|     [EventType.RoomMessage, MessageEventFactory], // note that verification requests are handled in pickFactory()
 | ||||
|     [EventType.Sticker, MessageEventFactory], | ||||
|     [M_POLL_START.name, MessageEventFactory], | ||||
|     [M_POLL_START.altName, MessageEventFactory], | ||||
|     [EventType.KeyVerificationCancel, KeyVerificationConclFactory], | ||||
|     [EventType.KeyVerificationDone, KeyVerificationConclFactory], | ||||
|     [EventType.CallInvite, CallEventFactory], // note that this requires a special factory type
 | ||||
| ]); | ||||
| 
 | ||||
| const STATE_EVENT_TILE_TYPES: FactoryMap = { | ||||
|     [EventType.RoomEncryption]: (ref, props) => <EncryptionEvent ref={ref} {...props} />, | ||||
|     [EventType.RoomCanonicalAlias]: TextualEventFactory, | ||||
|     [EventType.RoomCreate]: (ref, props) => <RoomCreate ref={ref} {...props} />, | ||||
|     [EventType.RoomMember]: TextualEventFactory, | ||||
|     [EventType.RoomName]: TextualEventFactory, | ||||
|     [EventType.RoomAvatar]: (ref, props) => <RoomAvatarEvent ref={ref} {...props} />, | ||||
|     [EventType.RoomThirdPartyInvite]: TextualEventFactory, | ||||
|     [EventType.RoomHistoryVisibility]: TextualEventFactory, | ||||
|     [EventType.RoomTopic]: TextualEventFactory, | ||||
|     [EventType.RoomPowerLevels]: TextualEventFactory, | ||||
|     [EventType.RoomPinnedEvents]: TextualEventFactory, | ||||
|     [EventType.RoomServerAcl]: TextualEventFactory, | ||||
| const STATE_EVENT_TILE_TYPES = new Map<string, Factory>([ | ||||
|     [EventType.RoomEncryption, (ref, props) => <EncryptionEvent ref={ref} {...props} />], | ||||
|     [EventType.RoomCanonicalAlias, TextualEventFactory], | ||||
|     [EventType.RoomCreate, (ref, props) => <RoomCreate ref={ref} {...props} />], | ||||
|     [EventType.RoomMember, TextualEventFactory], | ||||
|     [EventType.RoomName, TextualEventFactory], | ||||
|     [EventType.RoomAvatar, (ref, props) => <RoomAvatarEvent ref={ref} {...props} />], | ||||
|     [EventType.RoomThirdPartyInvite, TextualEventFactory], | ||||
|     [EventType.RoomHistoryVisibility, TextualEventFactory], | ||||
|     [EventType.RoomTopic, TextualEventFactory], | ||||
|     [EventType.RoomPowerLevels, TextualEventFactory], | ||||
|     [EventType.RoomPinnedEvents, TextualEventFactory], | ||||
|     [EventType.RoomServerAcl, TextualEventFactory], | ||||
|     // TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
 | ||||
|     'im.vector.modular.widgets': TextualEventFactory, // note that Jitsi widgets are special in pickFactory()
 | ||||
|     [WIDGET_LAYOUT_EVENT_TYPE]: TextualEventFactory, | ||||
|     [EventType.RoomTombstone]: TextualEventFactory, | ||||
|     [EventType.RoomJoinRules]: TextualEventFactory, | ||||
|     [EventType.RoomGuestAccess]: TextualEventFactory, | ||||
| }; | ||||
|     ['im.vector.modular.widgets', TextualEventFactory], // note that Jitsi widgets are special in pickFactory()
 | ||||
|     [WIDGET_LAYOUT_EVENT_TYPE, TextualEventFactory], | ||||
|     [EventType.RoomTombstone, TextualEventFactory], | ||||
|     [EventType.RoomJoinRules, TextualEventFactory], | ||||
|     [EventType.RoomGuestAccess, TextualEventFactory], | ||||
| ]); | ||||
| 
 | ||||
| // Add all the Mjolnir stuff to the renderer too
 | ||||
| for (const evType of ALL_RULE_TYPES) { | ||||
|     STATE_EVENT_TILE_TYPES[evType] = TextualEventFactory; | ||||
|     STATE_EVENT_TILE_TYPES.set(evType, TextualEventFactory); | ||||
| } | ||||
| 
 | ||||
| // These events should be recorded in the STATE_EVENT_TILE_TYPES
 | ||||
|  | @ -225,11 +224,11 @@ export function pickFactory( | |||
|             return noEventFactoryFactory(); // improper event type to render
 | ||||
|         } | ||||
| 
 | ||||
|         if (STATE_EVENT_TILE_TYPES[evType] === TextualEventFactory && !hasText(mxEvent, showHiddenEvents)) { | ||||
|         if (STATE_EVENT_TILE_TYPES.get(evType) === TextualEventFactory && !hasText(mxEvent, showHiddenEvents)) { | ||||
|             return noEventFactoryFactory(); | ||||
|         } | ||||
| 
 | ||||
|         return STATE_EVENT_TILE_TYPES[evType] ?? noEventFactoryFactory(); | ||||
|         return STATE_EVENT_TILE_TYPES.get(evType) ?? noEventFactoryFactory(); | ||||
|     } | ||||
| 
 | ||||
|     // Blanket override for all events. The MessageEvent component handles redacted states for us.
 | ||||
|  | @ -241,7 +240,7 @@ export function pickFactory( | |||
|         return noEventFactoryFactory(); | ||||
|     } | ||||
| 
 | ||||
|     return EVENT_TILE_TYPES[evType] ?? noEventFactoryFactory(); | ||||
|     return EVENT_TILE_TYPES.get(evType) ?? noEventFactoryFactory(); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  | @ -391,7 +390,7 @@ export function haveRendererForEvent(mxEvent: MatrixEvent, showHiddenEvents: boo | |||
|     if (!handler) return false; | ||||
|     if (handler === TextualEventFactory) { | ||||
|         return hasText(mxEvent, showHiddenEvents); | ||||
|     } else if (handler === STATE_EVENT_TILE_TYPES[EventType.RoomCreate]) { | ||||
|     } else if (handler === STATE_EVENT_TILE_TYPES.get(EventType.RoomCreate)) { | ||||
|         return Boolean(mxEvent.getContent()['predecessor']); | ||||
|     } else if (handler === JSONEventFactory) { | ||||
|         return false; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Travis Ralston
						Travis Ralston