1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-25 16:22:43 +01:00

Make the client authoritative for "Save" actions

Summary:
Ref T13559. When you click "Save" on an inline comment and it's empty, we may actually delete the comment.

Currently, the client and server both make decisions about whether the comment should be deleted. These decisions may not agree, causing the client state to fall out of sync.

Make the client authoritative about whether it wants to handle the user clicking the "Save" button as an intent to save or an intent to delete.

Test Plan: Saved empty and nonempty inlines. See followup changes.

Maniphest Tasks: T13559

Differential Revision: https://secure.phabricator.com/D21648
This commit is contained in:
epriestley 2021-03-23 12:24:55 -07:00
parent 0f04d9e584
commit 60e869f411
3 changed files with 73 additions and 55 deletions

View file

@ -13,7 +13,7 @@ return array(
'core.pkg.js' => 'ab3502fe', 'core.pkg.js' => 'ab3502fe',
'dark-console.pkg.js' => '187792c2', 'dark-console.pkg.js' => '187792c2',
'differential.pkg.css' => 'ffb69e3d', 'differential.pkg.css' => 'ffb69e3d',
'differential.pkg.js' => '442567d7', 'differential.pkg.js' => '7747755e',
'diffusion.pkg.css' => '42c75c37', 'diffusion.pkg.css' => '42c75c37',
'diffusion.pkg.js' => '78c9885d', 'diffusion.pkg.js' => '78c9885d',
'maniphest.pkg.css' => '35995d6d', 'maniphest.pkg.css' => '35995d6d',
@ -385,7 +385,7 @@ return array(
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '0116d3e8', 'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '0116d3e8',
'rsrc/js/application/diff/DiffChangeset.js' => 'd7d3ba75', 'rsrc/js/application/diff/DiffChangeset.js' => 'd7d3ba75',
'rsrc/js/application/diff/DiffChangesetList.js' => 'cc2c5de5', 'rsrc/js/application/diff/DiffChangesetList.js' => 'cc2c5de5',
'rsrc/js/application/diff/DiffInline.js' => 'fdebbba6', 'rsrc/js/application/diff/DiffInline.js' => '34ccdeda',
'rsrc/js/application/diff/DiffInlineContentState.js' => '68e6339d', 'rsrc/js/application/diff/DiffInlineContentState.js' => '68e6339d',
'rsrc/js/application/diff/DiffPathView.js' => '8207abf9', 'rsrc/js/application/diff/DiffPathView.js' => '8207abf9',
'rsrc/js/application/diff/DiffTreeView.js' => '5d83623b', 'rsrc/js/application/diff/DiffTreeView.js' => '5d83623b',
@ -788,7 +788,7 @@ return array(
'phabricator-dashboard-css' => '5a205b9d', 'phabricator-dashboard-css' => '5a205b9d',
'phabricator-diff-changeset' => 'd7d3ba75', 'phabricator-diff-changeset' => 'd7d3ba75',
'phabricator-diff-changeset-list' => 'cc2c5de5', 'phabricator-diff-changeset-list' => 'cc2c5de5',
'phabricator-diff-inline' => 'fdebbba6', 'phabricator-diff-inline' => '34ccdeda',
'phabricator-diff-inline-content-state' => '68e6339d', 'phabricator-diff-inline-content-state' => '68e6339d',
'phabricator-diff-path-view' => '8207abf9', 'phabricator-diff-path-view' => '8207abf9',
'phabricator-diff-tree-view' => '5d83623b', 'phabricator-diff-tree-view' => '5d83623b',
@ -1220,6 +1220,10 @@ return array(
'javelin-stratcom', 'javelin-stratcom',
'javelin-workflow', 'javelin-workflow',
), ),
'34ccdeda' => array(
'javelin-dom',
'phabricator-diff-inline-content-state',
),
'34e2a838' => array( '34e2a838' => array(
'aphront-typeahead-control-css', 'aphront-typeahead-control-css',
'phui-tag-view-css', 'phui-tag-view-css',
@ -2231,10 +2235,6 @@ return array(
'fdc13e4e' => array( 'fdc13e4e' => array(
'javelin-install', 'javelin-install',
), ),
'fdebbba6' => array(
'javelin-dom',
'phabricator-diff-inline-content-state',
),
'ff688a7a' => array( 'ff688a7a' => array(
'owners-path-editor', 'owners-path-editor',
'javelin-behavior', 'javelin-behavior',

View file

@ -186,23 +186,15 @@ abstract class PhabricatorInlineCommentController
if ($op === 'save') { if ($op === 'save') {
$this->updateCommentContentState($inline); $this->updateCommentContentState($inline);
$inline->setIsEditing(false); $inline
->setIsEditing(false)
if (!$inline->isVoidComment($viewer)) { ->setIsDeleted(0);
$inline->setIsDeleted(0);
$this->saveComment($inline); $this->saveComment($inline);
return $this->buildRenderedCommentResponse( return $this->buildRenderedCommentResponse(
$inline, $inline,
$this->getIsOnRight()); $this->getIsOnRight());
} else {
$inline->setIsDeleted(1);
$this->saveComment($inline);
return $this->buildEmptyResponse();
}
} else { } else {
// NOTE: At time of writing, the "editing" state of inlines is // NOTE: At time of writing, the "editing" state of inlines is
// preserved by simulating a click on "Edit" when the inline loads. // preserved by simulating a click on "Edit" when the inline loads.

View file

@ -45,6 +45,7 @@ JX.install('DiffInline', {
_undoRow: null, _undoRow: null,
_undoType: null, _undoType: null,
_undoState: null, _undoState: null,
_preventUndo: false,
_draftRequest: null, _draftRequest: null,
_skipFocus: false, _skipFocus: false,
@ -161,6 +162,14 @@ JX.install('DiffInline', {
return this._endOffset; return this._endOffset;
}, },
_setPreventUndo: function(prevent_undo) {
this._preventUndo = prevent_undo;
},
_getPreventUndo: function() {
return this._preventUndo;
},
setIsSelected: function(is_selected) { setIsSelected: function(is_selected) {
this._isSelected = is_selected; this._isSelected = is_selected;
@ -617,7 +626,9 @@ JX.install('DiffInline', {
this._editRow = null; this._editRow = null;
} }
if (!this._getPreventUndo()) {
this._drawUndeleteRows(state); this._drawUndeleteRows(state);
}
this.setLoading(false); this.setLoading(false);
this.setDeleted(true); this.setDeleted(true);
@ -815,17 +826,53 @@ JX.install('DiffInline', {
}, },
save: function() { save: function() {
if (this._shouldDeleteOnSave()) {
this._setPreventUndo(true);
this._applyDelete();
} else {
this._applySave();
}
},
_shouldDeleteOnSave: function() {
var state = this._getActiveContentState(); var state = this._getActiveContentState();
var handler = JX.bind(this, this._onsubmitresponse);
// TODO: This is greatly simplified because we don't track all the
// state we need yet.
return !state.getText().length;
},
_applySave: function() {
var handler = JX.bind(this, this._onsaveresponse);
var state = this._getActiveContentState();
var data = this._newRequestData('save', state.getWireFormat());
this._applyCall(handler, data);
},
_applyDelete: function() {
var handler = JX.bind(this, this._ondeleteresponse);
var data = this._newRequestData('delete');
this._applyCall(handler, data);
},
_applyCall: function(handler, data) {
var uri = this._getInlineURI();
var callback = JX.bind(this, function() {
this.setLoading(false);
handler.apply(null, arguments);
});
this.setLoading(true); this.setLoading(true);
var uri = this._getInlineURI(); new JX.Workflow(uri, data)
var data = this._newRequestData('save', state.getWireFormat()); .setHandler(callback)
.start();
new JX.Request(uri, handler)
.setData(data)
.send();
}, },
undo: function() { undo: function() {
@ -917,7 +964,7 @@ JX.install('DiffInline', {
} }
}, },
_onsubmitresponse: function(response) { _onsaveresponse: function(response) {
if (this._editRow) { if (this._editRow) {
JX.DOM.remove(this._editRow); JX.DOM.remove(this._editRow);
this._editRow = null; this._editRow = null;
@ -927,30 +974,9 @@ JX.install('DiffInline', {
this.setInvisible(false); this.setInvisible(false);
this.setEditing(false); this.setEditing(false);
this._onupdate(response); var new_row = this._drawContentRows(JX.$H(response.view).getNode());
},
_onupdate: function(response) {
var new_row;
if (response.view) {
new_row = this._drawContentRows(JX.$H(response.view).getNode());
}
// TODO: Save the old row so the action it's undo-able if it was a
// delete.
var remove_old = true;
if (remove_old) {
JX.DOM.remove(this._row); JX.DOM.remove(this._row);
}
// If you delete the content on a comment and save it, it acts like a
// delete: the server does not return a new row.
if (new_row) {
this.bindToRow(new_row); this.bindToRow(new_row);
} else {
this.setDeleted(true);
this._row = null;
}
this._didUpdate(); this._didUpdate();
}, },