@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Allow any EditEngine comment form to be pinned

Summary:
Fixes T12049. This expands "Haunted" comment panels to EditEngine, and by extension to all EditEngine applications.

Eventual goal is to remove custom commenting code in Differential and replace it with EditEngine code.

Changes from current "haunt" mode:

- This only has one mode ("pinned"), not two ("pinned", "pinned with preview"). There's an inline preview and scroll behavior is a little better.
- Now has a UI action button.

Slightly tricky stuff:

- This interacts with "Fullscreen" mode since it doesn't make sense to pin a full-screen comment area.
- This should only be available for comments, not for remarkup fields like "Description" in "Edit Task".

Test Plan:
- Pinned/unpinned in Maniphest.
- Pinned/fullscreened/unfullscreened/unpinned.
- Checked that "Edit Task" doesn't allow pinning for "Description", etc.
- Pressed "?", read about pressing "Z".
- Pressed "Z".

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T12049

Differential Revision: https://secure.phabricator.com/D17105

+135 -23
+18 -18
resources/celerity/map.php
··· 9 9 'names' => array( 10 10 'conpherence.pkg.css' => '0b64e988', 11 11 'conpherence.pkg.js' => '6249a1cf', 12 - 'core.pkg.css' => '55d12594', 13 - 'core.pkg.js' => 'e4260032', 12 + 'core.pkg.css' => '404132bb', 13 + 'core.pkg.js' => '28e8cda8', 14 14 'darkconsole.pkg.js' => 'e7393ebb', 15 15 'differential.pkg.css' => 'a4ba74b5', 16 16 'differential.pkg.js' => '634399e9', ··· 108 108 'rsrc/css/application/tokens/tokens.css' => '3d0f239e', 109 109 'rsrc/css/application/uiexample/example.css' => '528b19de', 110 110 'rsrc/css/core/core.css' => 'd0801452', 111 - 'rsrc/css/core/remarkup.css' => '8606d9c6', 111 + 'rsrc/css/core/remarkup.css' => '43e704eb', 112 112 'rsrc/css/core/syntax.css' => '769d3498', 113 - 'rsrc/css/core/z-index.css' => 'd1270942', 113 + 'rsrc/css/core/z-index.css' => '5e72c4e0', 114 114 'rsrc/css/diviner/diviner-shared.css' => 'aa3656aa', 115 115 'rsrc/css/font/font-aleo.css' => '8bdb2835', 116 116 'rsrc/css/font/font-awesome.css' => '2b7ebbcc', ··· 515 515 'rsrc/js/core/behavior-object-selector.js' => 'e0ec7f2f', 516 516 'rsrc/js/core/behavior-oncopy.js' => '2926fff2', 517 517 'rsrc/js/core/behavior-phabricator-nav.js' => '08675c6d', 518 - 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '116cf19b', 518 + 'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '0c61d4e3', 519 519 'rsrc/js/core/behavior-read-only-warning.js' => 'ba158207', 520 520 'rsrc/js/core/behavior-refresh-csrf.js' => 'ab2f381b', 521 521 'rsrc/js/core/behavior-remarkup-preview.js' => '4b700e9e', ··· 677 677 'javelin-behavior-phabricator-notification-example' => '8ce821c5', 678 678 'javelin-behavior-phabricator-object-selector' => 'e0ec7f2f', 679 679 'javelin-behavior-phabricator-oncopy' => '2926fff2', 680 - 'javelin-behavior-phabricator-remarkup-assist' => '116cf19b', 680 + 'javelin-behavior-phabricator-remarkup-assist' => '0c61d4e3', 681 681 'javelin-behavior-phabricator-reveal-content' => '60821bc7', 682 682 'javelin-behavior-phabricator-search-typeahead' => '06c32383', 683 683 'javelin-behavior-phabricator-show-older-transactions' => '94c65b72', ··· 806 806 'phabricator-object-selector-css' => '85ee8ce6', 807 807 'phabricator-phtize' => 'd254d646', 808 808 'phabricator-prefab' => '8d40ae75', 809 - 'phabricator-remarkup-css' => '8606d9c6', 809 + 'phabricator-remarkup-css' => '43e704eb', 810 810 'phabricator-search-results-css' => '64ad079a', 811 811 'phabricator-shaped-request' => '7cbe244b', 812 812 'phabricator-slowvote-css' => 'a94b7230', ··· 826 826 'phabricator-uiexample-reactor-select' => 'a155550f', 827 827 'phabricator-uiexample-reactor-sendclass' => '1def2711', 828 828 'phabricator-uiexample-reactor-sendproperties' => 'b1f0ccee', 829 - 'phabricator-zindex-css' => 'd1270942', 829 + 'phabricator-zindex-css' => '5e72c4e0', 830 830 'phame-css' => 'aeb61182', 831 831 'pholio-css' => 'ca89d380', 832 832 'pholio-edit-css' => '07676f51', ··· 1005 1005 'javelin-dom', 1006 1006 'javelin-router', 1007 1007 ), 1008 + '0c61d4e3' => array( 1009 + 'javelin-behavior', 1010 + 'javelin-stratcom', 1011 + 'javelin-dom', 1012 + 'phabricator-phtize', 1013 + 'phabricator-textareautils', 1014 + 'javelin-workflow', 1015 + 'javelin-vector', 1016 + 'phuix-autocomplete', 1017 + ), 1008 1018 '0f764c35' => array( 1009 1019 'javelin-install', 1010 1020 'javelin-util', ··· 1014 1024 'javelin-util', 1015 1025 'javelin-dom', 1016 1026 'javelin-typeahead-normalizer', 1017 - ), 1018 - '116cf19b' => array( 1019 - 'javelin-behavior', 1020 - 'javelin-stratcom', 1021 - 'javelin-dom', 1022 - 'phabricator-phtize', 1023 - 'phabricator-textareautils', 1024 - 'javelin-workflow', 1025 - 'javelin-vector', 1026 - 'phuix-autocomplete', 1027 1027 ), 1028 1028 '12884df9' => array( 1029 1029 'javelin-behavior',
+2
src/applications/transactions/view/PhabricatorApplicationTransactionCommentView.php
··· 199 199 $comment_box = id(new PHUIObjectBoxView()) 200 200 ->setFlush(true) 201 201 ->addClass('phui-comment-form-view') 202 + ->addSigil('phui-comment-form') 202 203 ->appendChild($image) 203 204 ->appendChild($wedge) 204 205 ->appendChild($comment); ··· 355 356 ->setID($this->getCommentID()) 356 357 ->addClass('phui-comment-fullwidth-control') 357 358 ->addClass('phui-comment-textarea-control') 359 + ->setCanPin(true) 358 360 ->setName('comment') 359 361 ->setUser($this->getUser()) 360 362 ->setValue($draft_comment))
+28 -5
src/view/form/control/PhabricatorRemarkupControl.php
··· 1 1 <?php 2 2 3 3 final class PhabricatorRemarkupControl extends AphrontFormTextAreaControl { 4 - private $disableMacro = false; 5 4 5 + private $disableMacro = false; 6 6 private $disableFullScreen = false; 7 + private $canPin; 7 8 8 9 public function setDisableMacros($disable) { 9 10 $this->disableMacro = $disable; ··· 13 14 public function setDisableFullScreen($disable) { 14 15 $this->disableFullScreen = $disable; 15 16 return $this; 17 + } 18 + 19 + public function setCanPin($can_pin) { 20 + $this->canPin = $can_pin; 21 + return $this; 22 + } 23 + 24 + public function getCanPin() { 25 + return $this->canPin; 16 26 } 17 27 18 28 protected function renderInput() { ··· 63 73 'data' => pht('data'), 64 74 'name' => pht('name'), 65 75 'URL' => pht('URL'), 76 + 'key-help' => pht('Pin or unpin the comment form.'), 66 77 ), 78 + 'canPin' => $this->getCanPin(), 67 79 'disabled' => $this->getDisabled(), 68 80 'rootID' => $root_id, 69 81 'autocompleteMap' => (object)array( ··· 164 176 'href' => PhabricatorEnv::getDoclink('Remarkup Reference'), 165 177 ); 166 178 179 + $mode_actions = array(); 167 180 168 181 if (!$this->disableFullScreen) { 169 - $actions[] = array( 170 - 'spacer' => true, 182 + $mode_actions['fa-arrows-alt'] = array( 183 + 'tip' => pht('Fullscreen Mode'), 184 + 'align' => 'right', 185 + ); 186 + } 187 + 188 + if ($this->getCanPin()) { 189 + $mode_actions['fa-thumb-tack'] = array( 190 + 'tip' => pht('Pin Form On Screen'), 171 191 'align' => 'right', 172 192 ); 193 + } 173 194 174 - $actions['fa-arrows-alt'] = array( 175 - 'tip' => pht('Fullscreen Mode'), 195 + if ($mode_actions) { 196 + $actions[] = array( 197 + 'spacer' => true, 176 198 'align' => 'right', 177 199 ); 200 + $actions += $mode_actions; 178 201 } 179 202 180 203 $buttons = array();
+20
webroot/rsrc/css/core/remarkup.css
··· 728 728 background: {$sh-bluebackground}; 729 729 color: #000; 730 730 } 731 + 732 + .phui-box.phui-object-box.phui-comment-form-view.remarkup-assist-pinned { 733 + position: fixed; 734 + background-color: #ffffff; 735 + border-top: 1px solid {$lightblueborder}; 736 + box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); 737 + 738 + width: 100%; 739 + bottom: 0; 740 + left: 0; 741 + right: 0; 742 + margin: 0; 743 + 744 + overflow: auto; 745 + max-height: 40vh; 746 + } 747 + 748 + .remarkup-assist-pinned-spacer { 749 + position: relative; 750 + }
+4
webroot/rsrc/css/core/z-index.css
··· 106 106 z-index: 8; 107 107 } 108 108 109 + .remarkup-assist-pinned { 110 + z-index: 8; 111 + } 112 + 109 113 .device-desktop .phabricator-notification-menu { 110 114 z-index: 9; 111 115 }
+63
webroot/rsrc/js/core/behavior-phabricator-remarkup-assist.js
··· 18 18 var edit_mode = 'normal'; 19 19 var edit_root = null; 20 20 var preview = null; 21 + var pinned = false; 22 + 23 + // When we pin the comment area to the bottom of the window, we need to put 24 + // an extra spacer element at the bottom of the document so that it is 25 + // possible to scroll down far enough to see content at the end. Otherwise, 26 + // the last part of the document will be hidden behind the comment area when 27 + // the document is fully scrolled. 28 + var pinned_spacer = JX.$N( 29 + 'div', 30 + {className: 'remarkup-assist-pinned-spacer'}); 21 31 22 32 function set_edit_mode(root, mode) { 23 33 if (mode == edit_mode) { ··· 66 76 JX.DOM.focus(area); 67 77 } 68 78 79 + function set_pinned_mode(root, mode) { 80 + if (mode === pinned) { 81 + return; 82 + } 83 + 84 + pinned = mode; 85 + 86 + var container = get_pinned_container(root); 87 + JX.DOM.alterClass(container, 'remarkup-assist-pinned', pinned); 88 + 89 + if (pinned) { 90 + JX.DOM.appendContent(document.body, pinned_spacer); 91 + } else { 92 + JX.DOM.remove(pinned_spacer); 93 + } 94 + 95 + resizearea(); 96 + 97 + JX.DOM.focus(area); 98 + } 99 + 100 + function get_pinned_container(root) { 101 + return JX.DOM.findAbove(root, 'div', 'phui-comment-form'); 102 + } 103 + 69 104 function resizearea() { 105 + // If we're in the pinned comment mode, resize the pinned spacer to be the 106 + // same size as the pinned form. This allows users to scroll to the bottom 107 + // of the document by creating extra footer space to scroll through. 108 + if (pinned) { 109 + var container = get_pinned_container(root); 110 + var d = JX.Vector.getDim(container); 111 + d.x = null; 112 + d.setDim(pinned_spacer); 113 + } 114 + 70 115 if (!edit_root) { 71 116 return; 72 117 } ··· 98 143 99 144 e.kill(); 100 145 set_edit_mode(edit_root, 'normal'); 146 + set_pinned_mode(root, false); 101 147 }); 102 148 103 149 function update(area, l, m, r) { ··· 211 257 .start(); 212 258 break; 213 259 case 'fa-arrows-alt': 260 + set_pinned_mode(root, false); 214 261 if (edit_mode == 'fa-arrows-alt') { 215 262 set_edit_mode(root, 'normal'); 216 263 } else { ··· 241 288 JX.DOM.alterClass(button, 'preview-active', false); 242 289 } 243 290 break; 291 + case 'fa-thumb-tack': 292 + // If we're pinning, kick us out of fullscreen mode first. 293 + set_edit_mode(edit_root, 'normal'); 294 + 295 + // Now pin or unpin the area. 296 + set_pinned_mode(root, !pinned); 297 + break; 298 + 244 299 } 245 300 } 246 301 ··· 316 371 } 317 372 318 373 autocomplete.start(); 374 + 375 + if (config.canPin) { 376 + new JX.KeyboardShortcut('z', pht('key-help')) 377 + .setHandler(function() { 378 + set_pinned_mode(root, !pinned); 379 + }) 380 + .register(); 381 + } 319 382 320 383 });