Save edited state when switching rooms

Signed-off-by: Jaiwanth <jaiwanth2011@gmail.com>
pull/21833/head
Jaiwanth 2021-05-09 13:18:01 +05:30
parent c2ae6c279b
commit 6f98aa06c4
2 changed files with 52 additions and 4 deletions

View File

@ -34,6 +34,7 @@ import IRCTimelineProfileResizer from "../views/elements/IRCTimelineProfileResiz
import DMRoomMap from "../../utils/DMRoomMap"; import DMRoomMap from "../../utils/DMRoomMap";
import NewRoomIntro from "../views/rooms/NewRoomIntro"; import NewRoomIntro from "../views/rooms/NewRoomIntro";
import {replaceableComponent} from "../../utils/replaceableComponent"; import {replaceableComponent} from "../../utils/replaceableComponent";
import defaultDispatcher from '../../dispatcher/dispatcher';
const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes
const continuedTypes = ['m.sticker', 'm.room.message']; const continuedTypes = ['m.sticker', 'm.room.message'];
@ -564,15 +565,23 @@ export default class MessagePanel extends React.Component {
return ret; return ret;
} }
_wasEventBeingEdited = (mxEv) => {
return localStorage.getItem(`mx_edit_state_${mxEv.getRoomId()}
_${mxEv.getId()}`) !== null;
}
_getTilesForEvent(prevEvent, mxEv, last, nextEvent, nextEventWithTile) { _getTilesForEvent(prevEvent, mxEv, last, nextEvent, nextEventWithTile) {
const TileErrorBoundary = sdk.getComponent('messages.TileErrorBoundary'); const TileErrorBoundary = sdk.getComponent('messages.TileErrorBoundary');
const EventTile = sdk.getComponent('rooms.EventTile'); const EventTile = sdk.getComponent('rooms.EventTile');
const DateSeparator = sdk.getComponent('messages.DateSeparator'); const DateSeparator = sdk.getComponent('messages.DateSeparator');
const ret = []; const ret = [];
if (!this.props.editState && this._wasEventBeingEdited(mxEv) ) {
defaultDispatcher.dispatch({action: "edit_event", event: mxEv});
}
const isEditing = this.props.editState && const isEditing = this.props.editState &&
this.props.editState.getEvent().getId() === mxEv.getId(); this.props.editState.getEvent().getId() === mxEv.getId();
// local echoes have a fake date, which could even be yesterday. Treat them // local echoes have a fake date, which could even be yesterday. Treat them
// as 'today' for the date separators. // as 'today' for the date separators.
let ts1 = mxEv.getTs(); let ts1 = mxEv.getTs();

View File

@ -34,6 +34,7 @@ import {Action} from "../../../dispatcher/actions";
import CountlyAnalytics from "../../../CountlyAnalytics"; import CountlyAnalytics from "../../../CountlyAnalytics";
import {getKeyBindingsManager, MessageComposerAction} from '../../../KeyBindingsManager'; import {getKeyBindingsManager, MessageComposerAction} from '../../../KeyBindingsManager';
import {replaceableComponent} from "../../../utils/replaceableComponent"; import {replaceableComponent} from "../../../utils/replaceableComponent";
import SendHistoryManager from '../../../SendHistoryManager';
function _isReply(mxEvent) { function _isReply(mxEvent) {
const relatesTo = mxEvent.getContent()["m.relates_to"]; const relatesTo = mxEvent.getContent()["m.relates_to"];
@ -120,6 +121,7 @@ export default class EditMessageComposer extends React.Component {
saveDisabled: true, saveDisabled: true,
}; };
this._createEditorModel(); this._createEditorModel();
window.addEventListener("beforeunload", this._saveStoredEditorState);
} }
_setEditorRef = ref => { _setEditorRef = ref => {
@ -174,10 +176,43 @@ export default class EditMessageComposer extends React.Component {
} }
_cancelEdit = () => { _cancelEdit = () => {
this._clearStoredEditorState();
dis.dispatch({action: "edit_event", event: null}); dis.dispatch({action: "edit_event", event: null});
dis.fire(Action.FocusComposer); dis.fire(Action.FocusComposer);
} }
get _shouldSaveStoredEditorState() {
return localStorage.getItem(`mx_edit_state_${this.props.editState.getEvent().getRoomId()}
_${this.props.editState.getEvent().event.event_id}`) !== null;
}
_restoreStoredEditorState(partCreator) {
const json = localStorage.getItem(this._editorStateKey);
if (json) {
try {
const {parts: serializedParts} = JSON.parse(json);
const parts = serializedParts.map(p => partCreator.deserializePart(p));
return parts;
} catch (e) {
console.error(e);
}
}
}
get _editorStateKey() {
return `mx_edit_state_${this.props.editState.getEvent().getRoomId()}
_${this.props.editState.getEvent().event.event_id}`;
}
_clearStoredEditorState() {
localStorage.removeItem(this._editorStateKey);
}
_saveStoredEditorState() {
const item = SendHistoryManager.createItem(this.model);
localStorage.setItem(this._editorStateKey, JSON.stringify(item));
}
_isContentModified(newContent) { _isContentModified(newContent) {
// if nothing has changed then bail // if nothing has changed then bail
const oldContent = this.props.editState.getEvent().getContent(); const oldContent = this.props.editState.getEvent().getContent();
@ -195,13 +230,13 @@ export default class EditMessageComposer extends React.Component {
const editedEvent = this.props.editState.getEvent(); const editedEvent = this.props.editState.getEvent();
const editContent = createEditContent(this.model, editedEvent); const editContent = createEditContent(this.model, editedEvent);
const newContent = editContent["m.new_content"]; const newContent = editContent["m.new_content"];
// If content is modified then send an updated event into the room // If content is modified then send an updated event into the room
if (this._isContentModified(newContent)) { if (this._isContentModified(newContent)) {
const roomId = editedEvent.getRoomId(); const roomId = editedEvent.getRoomId();
this._cancelPreviousPendingEdit(); this._cancelPreviousPendingEdit();
const prom = this.context.sendMessage(roomId, editContent); const prom = this.context.sendMessage(roomId, editContent);
dis.dispatch({action: "message_sent"}); dis.dispatch({action: "message_sent"});
this._clearStoredEditorState();
CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, true, false, editContent); CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, true, false, editContent);
} }
@ -235,6 +270,10 @@ export default class EditMessageComposer extends React.Component {
// then when mounting the editor again with the same editor state, // then when mounting the editor again with the same editor state,
// it will set the cursor at the end. // it will set the cursor at the end.
this.props.editState.setEditorState(caret, parts); this.props.editState.setEditorState(caret, parts);
window.removeEventListener("beforeunload", this._saveStoredEditorState);
if (this._shouldSaveStoredEditorState) {
this._saveStoredEditorState();
}
} }
_createEditorModel() { _createEditorModel() {
@ -247,10 +286,10 @@ export default class EditMessageComposer extends React.Component {
// restore serialized parts from the state // restore serialized parts from the state
parts = editState.getSerializedParts().map(p => partCreator.deserializePart(p)); parts = editState.getSerializedParts().map(p => partCreator.deserializePart(p));
} else { } else {
// otherwise, parse the body of the event parts = this._restoreStoredEditorState(partCreator) || parseEvent(editState.getEvent(), partCreator);
parts = parseEvent(editState.getEvent(), partCreator);
} }
this.model = new EditorModel(parts, partCreator); this.model = new EditorModel(parts, partCreator);
this._saveStoredEditorState();
} }
_getInitialCaretPosition() { _getInitialCaretPosition() {