Skip to content

Commit 6fd55d6

Browse files
author
epriestley
committedMar 29, 2021
Formally track "initial", "committed", and "active" states for inline comments
Summary: Ref T13559. Various client decisions depend on the "initial" or "committed" states of inline comments. Previously, these were informally constructed from "mostly similar" available values, or glossed over in some cases. On the server, save the initial state when creating a comment. Save the committed state when applying a "save" operation. Send all three states to the client. On the client, load and track all three states explicitly. Test Plan: Created inlines, etc. See followups. Maniphest Tasks: T13559 Differential Revision: https://secure.phabricator.com/D21653
1 parent b755179 commit 6fd55d6

File tree

5 files changed

+158
-71
lines changed

5 files changed

+158
-71
lines changed
 

‎resources/celerity/map.php

+7-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
'core.pkg.js' => '68f29322',
1414
'dark-console.pkg.js' => '187792c2',
1515
'differential.pkg.css' => 'ffb69e3d',
16-
'differential.pkg.js' => 'fbde899f',
16+
'differential.pkg.js' => '59453886',
1717
'diffusion.pkg.css' => '42c75c37',
1818
'diffusion.pkg.js' => '78c9885d',
1919
'maniphest.pkg.css' => '35995d6d',
@@ -385,7 +385,7 @@
385385
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '0116d3e8',
386386
'rsrc/js/application/diff/DiffChangeset.js' => 'd7d3ba75',
387387
'rsrc/js/application/diff/DiffChangesetList.js' => 'cc2c5de5',
388-
'rsrc/js/application/diff/DiffInline.js' => '62fff8eb',
388+
'rsrc/js/application/diff/DiffInline.js' => '26664c24',
389389
'rsrc/js/application/diff/DiffInlineContentState.js' => '68e6339d',
390390
'rsrc/js/application/diff/DiffPathView.js' => '8207abf9',
391391
'rsrc/js/application/diff/DiffTreeView.js' => '5d83623b',
@@ -788,7 +788,7 @@
788788
'phabricator-dashboard-css' => '5a205b9d',
789789
'phabricator-diff-changeset' => 'd7d3ba75',
790790
'phabricator-diff-changeset-list' => 'cc2c5de5',
791-
'phabricator-diff-inline' => '62fff8eb',
791+
'phabricator-diff-inline' => '26664c24',
792792
'phabricator-diff-inline-content-state' => '68e6339d',
793793
'phabricator-diff-path-view' => '8207abf9',
794794
'phabricator-diff-tree-view' => '5d83623b',
@@ -1162,6 +1162,10 @@
11621162
'javelin-json',
11631163
'phabricator-prefab',
11641164
),
1165+
'26664c24' => array(
1166+
'javelin-dom',
1167+
'phabricator-diff-inline-content-state',
1168+
),
11651169
'289bf236' => array(
11661170
'javelin-install',
11671171
'javelin-util',
@@ -1532,10 +1536,6 @@
15321536
'javelin-request',
15331537
'javelin-uri',
15341538
),
1535-
'62fff8eb' => array(
1536-
'javelin-dom',
1537-
'phabricator-diff-inline-content-state',
1538-
),
15391539
'65bb0011' => array(
15401540
'javelin-behavior',
15411541
'javelin-dom',

‎src/infrastructure/diff/PhabricatorInlineCommentController.php

+49-44
Original file line numberDiff line numberDiff line change
@@ -180,56 +180,60 @@ public function processRequest() {
180180
$this->saveComment($inline);
181181

182182
return $this->buildEmptyResponse();
183-
case 'edit':
184183
case 'save':
185184
$inline = $this->loadCommentByIDForEdit($this->getCommentID());
186-
if ($op === 'save') {
187-
$this->updateCommentContentState($inline);
188185

189-
$inline
190-
->setIsEditing(false)
191-
->setIsDeleted(0);
186+
$this->updateCommentContentState($inline);
192187

193-
$this->saveComment($inline);
188+
$inline
189+
->setIsEditing(false)
190+
->setIsDeleted(0);
194191

195-
return $this->buildRenderedCommentResponse(
196-
$inline,
197-
$this->getIsOnRight());
198-
} else {
199-
// NOTE: At time of writing, the "editing" state of inlines is
200-
// preserved by simulating a click on "Edit" when the inline loads.
192+
// Since we're saving the comment, update the committed state.
193+
$active_state = $inline->getContentState();
194+
$inline->setCommittedContentState($active_state);
201195

202-
// In this case, we don't want to "saveComment()", because it
203-
// recalculates object drafts and purges versioned drafts.
196+
$this->saveComment($inline);
204197

205-
// The recalculation is merely unnecessary (state doesn't change)
206-
// but purging drafts means that loading a page and then closing it
207-
// discards your drafts.
198+
return $this->buildRenderedCommentResponse(
199+
$inline,
200+
$this->getIsOnRight());
201+
case 'edit':
202+
$inline = $this->loadCommentByIDForEdit($this->getCommentID());
208203

209-
// To avoid the purge, only invoke "saveComment()" if we actually
210-
// have changes to apply.
204+
// NOTE: At time of writing, the "editing" state of inlines is
205+
// preserved by simulating a click on "Edit" when the inline loads.
211206

212-
$is_dirty = false;
213-
if (!$inline->getIsEditing()) {
214-
$inline
215-
->setIsDeleted(0)
216-
->setIsEditing(true);
207+
// In this case, we don't want to "saveComment()", because it
208+
// recalculates object drafts and purges versioned drafts.
217209

218-
$is_dirty = true;
219-
}
210+
// The recalculation is merely unnecessary (state doesn't change)
211+
// but purging drafts means that loading a page and then closing it
212+
// discards your drafts.
220213

221-
if ($this->hasContentState()) {
222-
$this->updateCommentContentState($inline);
223-
$is_dirty = true;
224-
} else {
225-
PhabricatorInlineComment::loadAndAttachVersionedDrafts(
226-
$viewer,
227-
array($inline));
228-
}
214+
// To avoid the purge, only invoke "saveComment()" if we actually
215+
// have changes to apply.
229216

230-
if ($is_dirty) {
231-
$this->saveComment($inline);
232-
}
217+
$is_dirty = false;
218+
if (!$inline->getIsEditing()) {
219+
$inline
220+
->setIsDeleted(0)
221+
->setIsEditing(true);
222+
223+
$is_dirty = true;
224+
}
225+
226+
if ($this->hasContentState()) {
227+
$this->updateCommentContentState($inline);
228+
$is_dirty = true;
229+
} else {
230+
PhabricatorInlineComment::loadAndAttachVersionedDrafts(
231+
$viewer,
232+
array($inline));
233+
}
234+
235+
if ($is_dirty) {
236+
$this->saveComment($inline);
233237
}
234238

235239
$edit_dialog = $this->buildEditDialog($inline)
@@ -333,7 +337,10 @@ public function processRequest() {
333337
$state = $inline->getContentState();
334338
$default_suggestion = $inline->getDefaultSuggestionText();
335339
$state->setContentSuggestionText($default_suggestion);
340+
341+
$inline->setInitialContentState($state);
336342
$inline->setContentState($state);
343+
337344
$inline->setIsDeleted(0);
338345

339346
$this->saveComment($inline);
@@ -461,6 +468,7 @@ private function newInlineResponse(
461468
PhabricatorInlineComment $inline,
462469
$view,
463470
$is_edit) {
471+
$viewer = $this->getViewer();
464472

465473
if ($inline->getReplyToCommentPHID()) {
466474
$can_suggest = false;
@@ -469,18 +477,15 @@ private function newInlineResponse(
469477
}
470478

471479
if ($is_edit) {
472-
$viewer = $this->getViewer();
473-
$content_state = $inline->getContentStateForEdit($viewer);
480+
$state = $inline->getContentStateMapForEdit($viewer);
474481
} else {
475-
$content_state = $inline->getContentState();
482+
$state = $inline->getContentStateMap();
476483
}
477484

478-
$state_map = $content_state->newStorageMap();
479-
480485
$response = array(
481486
'inline' => array(
482487
'id' => $inline->getID(),
483-
'contentState' => $state_map,
488+
'state' => $state,
484489
'canSuggestEdit' => $can_suggest,
485490
),
486491
'view' => hsprintf('%s', $view),

‎src/infrastructure/diff/interface/PhabricatorInlineComment.php

+80-8
Original file line numberDiff line numberDiff line change
@@ -336,13 +336,29 @@ public function newContentStateFromRequest(AphrontRequest $request) {
336336
return $this->newContentState()->readFromRequest($request);
337337
}
338338

339+
public function getInitialContentState() {
340+
return $this->getNamedContentState('inline.state.initial');
341+
}
342+
343+
public function setInitialContentState(
344+
PhabricatorInlineCommentContentState $state) {
345+
return $this->setNamedContentState('inline.state.initial', $state);
346+
}
347+
348+
public function getCommittedContentState() {
349+
return $this->getNamedContentState('inline.state.committed');
350+
}
351+
352+
public function setCommittedContentState(
353+
PhabricatorInlineCommentContentState $state) {
354+
return $this->setNamedContentState('inline.state.committed', $state);
355+
}
356+
339357
public function getContentState() {
340-
$state = $this->newContentState();
358+
$state = $this->getNamedContentState('inline.state');
341359

342-
$storage = $this->getStorageObject();
343-
$storage_map = $storage->getAttribute('inline.state');
344-
if (is_array($storage_map)) {
345-
$state->readStorageMap($storage_map);
360+
if (!$state) {
361+
$state = $this->newContentState();
346362
}
347363

348364
$state->setContentText($this->getContent());
@@ -351,11 +367,31 @@ public function getContentState() {
351367
}
352368

353369
public function setContentState(PhabricatorInlineCommentContentState $state) {
370+
$this->setContent($state->getContentText());
371+
372+
return $this->setNamedContentState('inline.state', $state);
373+
}
374+
375+
private function getNamedContentState($key) {
354376
$storage = $this->getStorageObject();
355-
$storage_map = $state->newStorageMap();
356-
$storage->setAttribute('inline.state', $storage_map);
357377

358-
$this->setContent($state->getContentText());
378+
$storage_map = $storage->getAttribute($key);
379+
if (!is_array($storage_map)) {
380+
return null;
381+
}
382+
383+
$state = $this->newContentState();
384+
$state->readStorageMap($storage_map);
385+
return $state;
386+
}
387+
388+
private function setNamedContentState(
389+
$key,
390+
PhabricatorInlineCommentContentState $state) {
391+
392+
$storage = $this->getStorageObject();
393+
$storage_map = $state->newStorageMap();
394+
$storage->setAttribute($key, $storage_map);
359395

360396
return $this;
361397
}
@@ -364,6 +400,42 @@ public function getInlineContext() {
364400
return $this->getStorageObject()->getInlineContext();
365401
}
366402

403+
public function getContentStateMapForEdit(PhabricatorUser $viewer) {
404+
return $this->getWireContentStateMap(true, $viewer);
405+
}
406+
407+
public function getContentStateMap() {
408+
return $this->getWireContentStateMap(false, null);
409+
}
410+
411+
private function getWireContentStateMap(
412+
$is_edit,
413+
PhabricatorUser $viewer = null) {
414+
415+
$initial_state = $this->getInitialContentState();
416+
$committed_state = $this->getCommittedContentState();
417+
418+
if ($is_edit) {
419+
$active_state = $this->getContentStateForEdit($viewer);
420+
} else {
421+
$active_state = $this->getContentState();
422+
}
423+
424+
return array(
425+
'initial' => $this->getWireContentState($initial_state),
426+
'committed' => $this->getWireContentState($committed_state),
427+
'active' => $this->getWireContentState($active_state),
428+
);
429+
}
430+
431+
private function getWireContentState($content_state) {
432+
if ($content_state === null) {
433+
return null;
434+
}
435+
436+
return $content_state->newStorageMap();
437+
}
438+
367439
public function getDefaultSuggestionText() {
368440
$context = $this->getInlineContext();
369441

‎src/infrastructure/diff/view/PHUIDiffInlineCommentView.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ protected function getInlineCommentMetadata() {
9393
'startOffset' => $inline->getStartOffset(),
9494
'endOffset' => $inline->getEndOffset(),
9595
'on_right' => $this->getIsOnRight(),
96-
'contentState' => $inline->getContentState()->newStorageMap(),
96+
'state' => $inline->getContentStateMap(),
9797
);
9898
}
9999

‎webroot/rsrc/js/application/diff/DiffInline.js

+21-11
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
JX.install('DiffInline', {
99

1010
construct : function() {
11-
this._activeContentState = new JX.DiffInlineContentState();
12-
this._committedContentState = new JX.DiffInlineContentState();
11+
this._state = {};
1312
},
1413

1514
members: {
@@ -56,8 +55,7 @@ JX.install('DiffInline', {
5655
_isSelected: false,
5756
_canSuggestEdit: false,
5857

59-
_committedContentState: null,
60-
_activeContentState: null,
58+
_state: null,
6159

6260
bindToRow: function(row) {
6361
this._row = row;
@@ -602,15 +600,23 @@ JX.install('DiffInline', {
602600
_readInlineState: function(state) {
603601
this._id = state.id;
604602

605-
// TODO: This is not the correct content state after a reload: it is
606-
// the draft state.
607-
this._getCommittedContentState().readWireFormat(state.contentState);
608-
609-
this._getActiveContentState().readWireFormat(state.contentState);
603+
this._state = {
604+
initial: this._newContentStateFromWireFormat(state.state.initial),
605+
committed: this._newContentStateFromWireFormat(state.state.committed),
606+
active: this._newContentStateFromWireFormat(state.state.active)
607+
};
610608

611609
this._canSuggestEdit = state.canSuggestEdit;
612610
},
613611

612+
_newContentStateFromWireFormat: function(map) {
613+
if (map === null) {
614+
return null;
615+
}
616+
617+
return new JX.DiffInlineContentState().readWireFormat(map);
618+
},
619+
614620
_ondeleteresponse: function() {
615621
// If there's an existing "unedit" undo element, remove it.
616622
if (this._undoRow) {
@@ -787,7 +793,7 @@ JX.install('DiffInline', {
787793
},
788794

789795
_getActiveContentState: function() {
790-
var state = this._activeContentState;
796+
var state = this._state.active;
791797

792798
if (this._editRow) {
793799
state.readForm(this._editRow);
@@ -797,7 +803,11 @@ JX.install('DiffInline', {
797803
},
798804

799805
_getCommittedContentState: function() {
800-
return this._committedContentState;
806+
return this._state.committed;
807+
},
808+
809+
_getInitialContentState: function() {
810+
return this._state.initial;
801811
},
802812

803813
setHasSuggestion: function(has_suggestion) {

0 commit comments

Comments
 (0)
Failed to load comments.