Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 120f269

Browse files
committed
Track replyToEvent along with CIDER state & history
Signed-off-by: Michael Telatynski <[email protected]>
1 parent 45fa647 commit 120f269

File tree

4 files changed

+70
-32
lines changed

4 files changed

+70
-32
lines changed

src/SendHistoryManager.ts

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,18 @@ limitations under the License.
1616
*/
1717

1818
import {clamp} from "lodash";
19+
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
20+
1921
import {SerializedPart} from "./editor/parts";
2022
import EditorModel from "./editor/model";
2123

24+
interface IHistoryItem {
25+
parts: SerializedPart[];
26+
replyEventId?: string;
27+
}
28+
2229
export default class SendHistoryManager {
23-
history: Array<SerializedPart[]> = [];
30+
history: Array<IHistoryItem> = [];
2431
prefix: string;
2532
lastIndex = 0; // used for indexing the storage
2633
currentIndex = 0; // used for indexing the loaded validated history Array
@@ -34,8 +41,7 @@ export default class SendHistoryManager {
3441

3542
while (itemJSON = sessionStorage.getItem(`${this.prefix}[${index}]`)) {
3643
try {
37-
const serializedParts = JSON.parse(itemJSON);
38-
this.history.push(serializedParts);
44+
this.history.push(SendHistoryManager.parseItem(JSON.parse(itemJSON)));
3945
} catch (e) {
4046
console.warn("Throwing away unserialisable history", e);
4147
break;
@@ -47,15 +53,32 @@ export default class SendHistoryManager {
4753
this.currentIndex = this.lastIndex + 1;
4854
}
4955

50-
save(editorModel: EditorModel) {
51-
const serializedParts = editorModel.serializeParts();
52-
this.history.push(serializedParts);
56+
static createItem(model: EditorModel, replyEvent?: MatrixEvent): IHistoryItem {
57+
return {
58+
parts: model.serializeParts(),
59+
replyEventId: replyEvent ? replyEvent.getId() : undefined,
60+
};
61+
}
62+
63+
static parseItem(item: IHistoryItem | SerializedPart[]): IHistoryItem {
64+
if (Array.isArray(item)) {
65+
// XXX: migrate from old format already in Storage
66+
return {
67+
parts: item,
68+
};
69+
}
70+
return item;
71+
}
72+
73+
save(editorModel: EditorModel, replyEvent?: MatrixEvent) {
74+
const item = SendHistoryManager.createItem(editorModel, replyEvent);
75+
this.history.push(item);
5376
this.currentIndex = this.history.length;
5477
this.lastIndex += 1;
55-
sessionStorage.setItem(`${this.prefix}[${this.lastIndex}]`, JSON.stringify(serializedParts));
78+
sessionStorage.setItem(`${this.prefix}[${this.lastIndex}]`, JSON.stringify(item));
5679
}
5780

58-
getItem(offset: number): SerializedPart[] {
81+
getItem(offset: number): IHistoryItem {
5982
this.currentIndex = clamp(this.currentIndex + offset, 0, this.history.length - 1);
6083
return this.history[this.currentIndex];
6184
}

src/components/views/rooms/BasicMessageComposer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ interface IProps {
9292
label?: string;
9393
initialCaret?: DocumentOffset;
9494

95-
onChange();
95+
onChange?();
9696
onPaste?(event: ClipboardEvent<HTMLDivElement>, model: EditorModel): boolean;
9797
}
9898

src/components/views/rooms/MessageComposer.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ export default class MessageComposer extends React.Component {
257257
this._dispatcherRef = null;
258258

259259
this.state = {
260-
isQuoting: Boolean(RoomViewStore.getQuotingEvent()),
260+
replyToEvent: RoomViewStore.getQuotingEvent(),
261261
tombstone: this._getRoomTombstone(),
262262
canSendMessages: this.props.room.maySendMessage(),
263263
showCallButtons: SettingsStore.getValue("showCallButtonsInComposer"),
@@ -337,9 +337,9 @@ export default class MessageComposer extends React.Component {
337337
}
338338

339339
_onRoomViewStoreUpdate() {
340-
const isQuoting = Boolean(RoomViewStore.getQuotingEvent());
341-
if (this.state.isQuoting === isQuoting) return;
342-
this.setState({ isQuoting });
340+
const replyToEvent = RoomViewStore.getQuotingEvent();
341+
if (this.state.replyToEvent === replyToEvent) return;
342+
this.setState({ replyToEvent });
343343
}
344344

345345
onInputStateChanged(inputState) {
@@ -378,7 +378,7 @@ export default class MessageComposer extends React.Component {
378378
}
379379

380380
renderPlaceholderText() {
381-
if (this.state.isQuoting) {
381+
if (this.state.replyToEvent) {
382382
if (this.props.e2eStatus) {
383383
return _t('Send an encrypted reply…');
384384
} else {
@@ -423,7 +423,9 @@ export default class MessageComposer extends React.Component {
423423
room={this.props.room}
424424
placeholder={this.renderPlaceholderText()}
425425
resizeNotifier={this.props.resizeNotifier}
426-
permalinkCreator={this.props.permalinkCreator} />,
426+
permalinkCreator={this.props.permalinkCreator}
427+
replyToEvent={this.state.replyToEvent}
428+
/>,
427429
<UploadButton key="controls_upload" roomId={this.props.room.roomId} />,
428430
<EmojiButton key="emoji_button" addEmoji={this.addEmoji} />,
429431
);

src/components/views/rooms/SendMessageComposer.js

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import {
2929
} from '../../../editor/serialize';
3030
import {CommandPartCreator} from '../../../editor/parts';
3131
import BasicMessageComposer from "./BasicMessageComposer";
32-
import RoomViewStore from '../../../stores/RoomViewStore';
3332
import ReplyThread from "../elements/ReplyThread";
3433
import {parseEvent} from '../../../editor/deserialize';
3534
import {findEditableEvent} from '../../../utils/EventUtils';
@@ -61,7 +60,7 @@ function addReplyToMessageContent(content, repliedToEvent, permalinkCreator) {
6160
}
6261

6362
// exported for tests
64-
export function createMessageContent(model, permalinkCreator) {
63+
export function createMessageContent(model, permalinkCreator, replyToEvent) {
6564
const isEmote = containsEmote(model);
6665
if (isEmote) {
6766
model = stripEmoteCommand(model);
@@ -70,21 +69,20 @@ export function createMessageContent(model, permalinkCreator) {
7069
model = stripPrefix(model, "/");
7170
}
7271
model = unescapeMessage(model);
73-
const repliedToEvent = RoomViewStore.getQuotingEvent();
7472

7573
const body = textSerialize(model);
7674
const content = {
7775
msgtype: isEmote ? "m.emote" : "m.text",
7876
body: body,
7977
};
80-
const formattedBody = htmlSerializeIfNeeded(model, {forceHTML: !!repliedToEvent});
78+
const formattedBody = htmlSerializeIfNeeded(model, {forceHTML: !!replyToEvent});
8179
if (formattedBody) {
8280
content.format = "org.matrix.custom.html";
8381
content.formatted_body = formattedBody;
8482
}
8583

86-
if (repliedToEvent) {
87-
addReplyToMessageContent(content, repliedToEvent, permalinkCreator);
84+
if (replyToEvent) {
85+
addReplyToMessageContent(content, replyToEvent, permalinkCreator);
8886
}
8987

9088
return content;
@@ -95,6 +93,7 @@ export default class SendMessageComposer extends React.Component {
9593
room: PropTypes.object.isRequired,
9694
placeholder: PropTypes.string,
9795
permalinkCreator: PropTypes.object.isRequired,
96+
replyToEvent: PropTypes.object,
9897
};
9998

10099
static contextType = MatrixClientContext;
@@ -110,6 +109,8 @@ export default class SendMessageComposer extends React.Component {
110109
cli.prepareToEncrypt(this.props.room);
111110
}, 60000);
112111
}
112+
113+
window.addEventListener("beforeunload", this._saveStoredEditorState);
113114
}
114115

115116
_setEditorRef = ref => {
@@ -145,7 +146,7 @@ export default class SendMessageComposer extends React.Component {
145146
if (e.shiftKey || e.metaKey) return;
146147

147148
const shouldSelectHistory = e.altKey && e.ctrlKey;
148-
const shouldEditLastMessage = !e.altKey && !e.ctrlKey && up && !RoomViewStore.getQuotingEvent();
149+
const shouldEditLastMessage = !e.altKey && !e.ctrlKey && up && !this.props.replyToEvent;
149150

150151
if (shouldSelectHistory) {
151152
// Try select composer history
@@ -187,9 +188,13 @@ export default class SendMessageComposer extends React.Component {
187188
this.sendHistoryManager.currentIndex = this.sendHistoryManager.history.length;
188189
return;
189190
}
190-
const serializedParts = this.sendHistoryManager.getItem(delta);
191-
if (serializedParts) {
192-
this.model.reset(serializedParts);
191+
const {parts, replyEventId} = this.sendHistoryManager.getItem(delta);
192+
dis.dispatch({
193+
action: 'reply_to_event',
194+
event: replyEventId ? this.props.room.findEventById(replyEventId) : null,
195+
});
196+
if (parts) {
197+
this.model.reset(parts);
193198
this._editorRef.focus();
194199
}
195200
}
@@ -299,12 +304,12 @@ export default class SendMessageComposer extends React.Component {
299304
}
300305
}
301306

307+
const replyToEvent = this.props.replyToEvent;
302308
if (shouldSend) {
303-
const isReply = !!RoomViewStore.getQuotingEvent();
304309
const {roomId} = this.props.room;
305-
const content = createMessageContent(this.model, this.props.permalinkCreator);
310+
const content = createMessageContent(this.model, this.props.permalinkCreator, replyToEvent);
306311
this.context.sendMessage(roomId, content);
307-
if (isReply) {
312+
if (replyToEvent) {
308313
// Clear reply_to_event as we put the message into the queue
309314
// if the send fails, retry will handle resending.
310315
dis.dispatch({
@@ -315,7 +320,7 @@ export default class SendMessageComposer extends React.Component {
315320
dis.dispatch({action: "message_sent"});
316321
}
317322

318-
this.sendHistoryManager.save(this.model);
323+
this.sendHistoryManager.save(this.model, replyToEvent);
319324
// clear composer
320325
this.model.reset([]);
321326
this._editorRef.clearUndoHistory();
@@ -325,6 +330,8 @@ export default class SendMessageComposer extends React.Component {
325330

326331
componentWillUnmount() {
327332
dis.unregister(this.dispatcherRef);
333+
window.removeEventListener("beforeunload", this._saveStoredEditorState);
334+
this._saveStoredEditorState();
328335
}
329336

330337
// TODO: [REACT-WARNING] Move this to constructor
@@ -347,8 +354,14 @@ export default class SendMessageComposer extends React.Component {
347354
_restoreStoredEditorState(partCreator) {
348355
const json = localStorage.getItem(this._editorStateKey);
349356
if (json) {
350-
const serializedParts = JSON.parse(json);
357+
const {parts: serializedParts, replyEventId} = SendHistoryManager.parseItem(JSON.parse(json));
351358
const parts = serializedParts.map(p => partCreator.deserializePart(p));
359+
if (replyEventId) {
360+
dis.dispatch({
361+
action: 'reply_to_event',
362+
event: this.props.room.findEventById(replyEventId),
363+
});
364+
}
352365
return parts;
353366
}
354367
}
@@ -357,7 +370,8 @@ export default class SendMessageComposer extends React.Component {
357370
if (this.model.isEmpty) {
358371
this._clearStoredEditorState();
359372
} else {
360-
localStorage.setItem(this._editorStateKey, JSON.stringify(this.model.serializeParts()));
373+
const item = SendHistoryManager.createItem(this.model, this.props.replyToEvent);
374+
localStorage.setItem(this._editorStateKey, JSON.stringify(item));
361375
}
362376
}
363377

@@ -449,7 +463,6 @@ export default class SendMessageComposer extends React.Component {
449463
room={this.props.room}
450464
label={this.props.placeholder}
451465
placeholder={this.props.placeholder}
452-
onChange={this._saveStoredEditorState}
453466
onPaste={this._onPaste}
454467
/>
455468
</div>

0 commit comments

Comments
 (0)