diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 2355f46174..365b256326 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -437,7 +437,7 @@ return array( 'rsrc/js/application/search/behavior-reorder-profile-menu-items.js' => 'e2e0a072', 'rsrc/js/application/search/behavior-reorder-queries.js' => 'e9581f08', 'rsrc/js/application/slowvote/behavior-slowvote-embed.js' => '887ad43f', - 'rsrc/js/application/transactions/behavior-comment-actions.js' => '06460e71', + 'rsrc/js/application/transactions/behavior-comment-actions.js' => '0300eae6', 'rsrc/js/application/transactions/behavior-reorder-configs.js' => 'd7a74243', 'rsrc/js/application/transactions/behavior-reorder-fields.js' => 'b59e1e96', 'rsrc/js/application/transactions/behavior-show-older-transactions.js' => '94c65b72', @@ -594,7 +594,7 @@ return array( 'javelin-behavior-bulk-job-reload' => 'edf8a145', 'javelin-behavior-calendar-month-view' => 'fe33e256', 'javelin-behavior-choose-control' => '327a00d1', - 'javelin-behavior-comment-actions' => '06460e71', + 'javelin-behavior-comment-actions' => '0300eae6', 'javelin-behavior-config-reorder-fields' => 'b6993408', 'javelin-behavior-conpherence-drag-and-drop-photo' => 'cf86d16a', 'javelin-behavior-conpherence-menu' => '1d45c74d', @@ -931,6 +931,15 @@ return array( 'javelin-dom', 'phabricator-keyboard-shortcut', ), + '0300eae6' => array( + 'javelin-behavior', + 'javelin-stratcom', + 'javelin-workflow', + 'javelin-dom', + 'phuix-form-control-view', + 'phuix-icon-view', + 'javelin-behavior-phabricator-gesture', + ), '05270951' => array( 'javelin-util', 'javelin-magical-init', @@ -945,15 +954,6 @@ return array( 'aphront-typeahead-control-css', 'phui-tag-view-css', ), - '06460e71' => array( - 'javelin-behavior', - 'javelin-stratcom', - 'javelin-workflow', - 'javelin-dom', - 'phuix-form-control-view', - 'phuix-icon-view', - 'javelin-behavior-phabricator-gesture', - ), '065227cc' => array( 'javelin-behavior', 'javelin-dom', diff --git a/src/applications/draft/storage/PhabricatorVersionedDraft.php b/src/applications/draft/storage/PhabricatorVersionedDraft.php index 2840a4249c..0daf13e8c5 100644 --- a/src/applications/draft/storage/PhabricatorVersionedDraft.php +++ b/src/applications/draft/storage/PhabricatorVersionedDraft.php @@ -55,11 +55,27 @@ final class PhabricatorVersionedDraft extends PhabricatorDraftDAO { return $draft; } - return id(new PhabricatorVersionedDraft()) - ->setObjectPHID($object_phid) - ->setAuthorPHID($viewer_phid) - ->setVersion((int)$version) - ->save(); + try { + return id(new self()) + ->setObjectPHID($object_phid) + ->setAuthorPHID($viewer_phid) + ->setVersion((int)$version) + ->save(); + } catch (AphrontDuplicateKeyQueryException $ex) { + $duplicate_exception = $ex; + } + + // In rare cases we can race ourselves, and at one point there was a bug + // which caused the browser to submit two preview requests at exactly + // the same time. If the insert failed with a duplicate key exception, + // try to load the colliding row to recover from it. + + $draft = self::loadDraft($object_phid, $viewer_phid); + if ($draft) { + return $draft; + } + + throw $duplicate_exception; } public static function purgeDrafts( diff --git a/webroot/rsrc/js/application/transactions/behavior-comment-actions.js b/webroot/rsrc/js/application/transactions/behavior-comment-actions.js index 87cb80c74a..a28a6b7ca2 100644 --- a/webroot/rsrc/js/application/transactions/behavior-comment-actions.js +++ b/webroot/rsrc/js/application/transactions/behavior-comment-actions.js @@ -176,17 +176,28 @@ JX.behavior('comment-actions', function(config) { JX.DOM.listen(form_node, 'shouldRefresh', null, always_trigger); request.start(); + var old_device = JX.Device.getDevice(); + var ondevicechange = function() { + var new_device = JX.Device.getDevice(); + var panel = JX.$(config.panelID); - if (JX.Device.getDevice() == 'desktop') { + if (new_device == 'desktop') { request.setRateLimit(500); - always_trigger(); + + // Force an immediate refresh if we switched from another device type + // to desktop. + if (old_device != new_device) { + always_trigger(); + } } else { // On mobile, don't show live previews and only save drafts every // 10 seconds. request.setRateLimit(10000); JX.DOM.hide(panel); } + + old_device = new_device; }; ondevicechange();