@@ -24,6 +24,9 @@ import BaseTool, { DevtoolsContext, IDevtoolsProps } from "./BaseTool";
24
24
import MatrixClientContext from "../../../../contexts/MatrixClientContext" ;
25
25
import { EventEditor , EventViewer , eventTypeField , stateKeyField , IEditorProps , stringify } from "./Event" ;
26
26
import FilteredList from "./FilteredList" ;
27
+ import Spinner from "../../elements/Spinner" ;
28
+ import SyntaxHighlight from "../../elements/SyntaxHighlight" ;
29
+ import { useAsyncMemo } from "../../../../hooks/useAsyncMemo" ;
27
30
28
31
export const StateEventEditor : React . FC < IEditorProps > = ( { mxEvent, onBack } ) => {
29
32
const context = useContext ( DevtoolsContext ) ;
@@ -47,6 +50,48 @@ interface StateEventButtonProps {
47
50
onClick ( ) : void ;
48
51
}
49
52
53
+ const RoomStateHistory : React . FC < {
54
+ mxEvent : MatrixEvent ;
55
+ onBack ( ) : void ;
56
+ } > = ( { mxEvent, onBack } ) => {
57
+ const cli = useContext ( MatrixClientContext ) ;
58
+ const events = useAsyncMemo (
59
+ async ( ) => {
60
+ const events = [ mxEvent . event ] ;
61
+ while ( ! ! events [ 0 ] . unsigned ?. replaces_state ) {
62
+ try {
63
+ events . unshift ( await cli . fetchRoomEvent ( mxEvent . getRoomId ( ) ! , events [ 0 ] . unsigned . replaces_state ) ) ;
64
+ } catch ( e ) {
65
+ events . unshift ( {
66
+ event_id : events [ 0 ] . unsigned . replaces_state ,
67
+ unsigned : {
68
+ error : e instanceof Error ? e . message : String ( e ) ,
69
+ } ,
70
+ } ) ;
71
+ }
72
+ }
73
+ return events ;
74
+ } ,
75
+ [ cli , mxEvent ] ,
76
+ null ,
77
+ ) ;
78
+
79
+ let body = < Spinner /> ;
80
+ if ( events !== null ) {
81
+ body = (
82
+ < >
83
+ { events . map ( ( ev ) => (
84
+ < SyntaxHighlight language = "json" key = { ev . event_id } >
85
+ { stringify ( ev ) }
86
+ </ SyntaxHighlight >
87
+ ) ) }
88
+ </ >
89
+ ) ;
90
+ }
91
+
92
+ return < BaseTool onBack = { onBack } > { body } </ BaseTool > ;
93
+ } ;
94
+
50
95
const StateEventButton : React . FC < StateEventButtonProps > = ( { label, onClick } ) => {
51
96
const trimmed = label . trim ( ) ;
52
97
@@ -71,6 +116,7 @@ const RoomStateExplorerEventType: React.FC<IEventTypeProps> = ({ eventType, onBa
71
116
const context = useContext ( DevtoolsContext ) ;
72
117
const [ query , setQuery ] = useState ( "" ) ;
73
118
const [ event , setEvent ] = useState < MatrixEvent | null > ( null ) ;
119
+ const [ history , setHistory ] = useState ( false ) ;
74
120
75
121
const events = context . room . currentState . events . get ( eventType ) ! ;
76
122
@@ -82,6 +128,12 @@ const RoomStateExplorerEventType: React.FC<IEventTypeProps> = ({ eventType, onBa
82
128
}
83
129
} , [ events ] ) ;
84
130
131
+ if ( event && history ) {
132
+ const _onBack = ( ) : void => {
133
+ setHistory ( false ) ;
134
+ } ;
135
+ return < RoomStateHistory mxEvent = { event } onBack = { _onBack } /> ;
136
+ }
85
137
if ( event ) {
86
138
const _onBack = ( ) : void => {
87
139
if ( events ?. size === 1 && events . has ( "" ) ) {
@@ -90,7 +142,11 @@ const RoomStateExplorerEventType: React.FC<IEventTypeProps> = ({ eventType, onBa
90
142
setEvent ( null ) ;
91
143
}
92
144
} ;
93
- return < EventViewer mxEvent = { event } onBack = { _onBack } Editor = { StateEventEditor } /> ;
145
+ const onHistoryClick = ( ) : void => {
146
+ setHistory ( true ) ;
147
+ } ;
148
+ const extraButton = < button onClick = { onHistoryClick } > { _t ( "See history" ) } </ button > ;
149
+ return < EventViewer mxEvent = { event } onBack = { _onBack } Editor = { StateEventEditor } extraButton = { extraButton } /> ;
94
150
}
95
151
96
152
return (
0 commit comments