@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.

Add options for hidding inlines to the Differential header banner

Summary:
Fixes T8909. Ref T12733.

UI attempts to follow the mock, but is a bit rough since PHUIXButtonView without text in this menu gets weird spacing, we don't have circular buttons yet, and PHUIXActionView without an icon also gets odd spacing.

Test Plan: {F5003125}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T12733, T8909

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

+294 -70
+25 -25
resources/celerity/map.php
··· 13 13 'core.pkg.js' => '1475bd91', 14 14 'darkconsole.pkg.js' => '1f9a31bc', 15 15 'differential.pkg.css' => '4ec4a37a', 16 - 'differential.pkg.js' => '3442216b', 16 + 'differential.pkg.js' => 'a55a2c13', 17 17 'diffusion.pkg.css' => 'b93d9b8c', 18 18 'diffusion.pkg.js' => '6134c5a1', 19 19 'favicon.ico' => '30672e08', ··· 395 395 'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => '408bf173', 396 396 'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '453c5375', 397 397 'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => 'd4eecc63', 398 - 'rsrc/js/application/diff/DiffChangeset.js' => 'cdc5fa19', 399 - 'rsrc/js/application/diff/DiffChangesetList.js' => '4ca11264', 400 - 'rsrc/js/application/diff/DiffInline.js' => '27b6d01f', 398 + 'rsrc/js/application/diff/DiffChangeset.js' => '99abf4cd', 399 + 'rsrc/js/application/diff/DiffChangesetList.js' => 'd442be4a', 400 + 'rsrc/js/application/diff/DiffInline.js' => '1bfa31c7', 401 401 'rsrc/js/application/diff/behavior-preview-link.js' => '051c7832', 402 402 'rsrc/js/application/differential/behavior-comment-preview.js' => '51c5ad07', 403 403 'rsrc/js/application/differential/behavior-diff-radios.js' => 'e1ff79b1', ··· 774 774 'phabricator-darklog' => 'c8e1ffe3', 775 775 'phabricator-darkmessage' => 'c48cccdd', 776 776 'phabricator-dashboard-css' => 'fe5b1869', 777 - 'phabricator-diff-changeset' => 'cdc5fa19', 778 - 'phabricator-diff-changeset-list' => '4ca11264', 779 - 'phabricator-diff-inline' => '27b6d01f', 777 + 'phabricator-diff-changeset' => '99abf4cd', 778 + 'phabricator-diff-changeset-list' => 'd442be4a', 779 + 'phabricator-diff-inline' => '1bfa31c7', 780 780 'phabricator-drag-and-drop-file-upload' => '58dea2fa', 781 781 'phabricator-draggable-list' => 'bea6e7f4', 782 782 'phabricator-fatal-config-template-css' => '8f18fa41', ··· 1016 1016 'javelin-request', 1017 1017 'javelin-uri', 1018 1018 ), 1019 + '1bfa31c7' => array( 1020 + 'javelin-dom', 1021 + ), 1019 1022 '1e911d0f' => array( 1020 1023 'javelin-stratcom', 1021 1024 'javelin-request', ··· 1056 1059 'phabricator-drag-and-drop-file-upload', 1057 1060 'javelin-workboard-board', 1058 1061 ), 1059 - '27b6d01f' => array( 1060 - 'javelin-dom', 1061 - ), 1062 1062 '2926fff2' => array( 1063 1063 'javelin-behavior', 1064 1064 'javelin-dom', ··· 1233 1233 'javelin-behavior', 1234 1234 'javelin-uri', 1235 1235 'phabricator-notification', 1236 - ), 1237 - '4ca11264' => array( 1238 - 'javelin-install', 1239 - 'phuix-button-view', 1240 1236 ), 1241 1237 '4d863052' => array( 1242 1238 'javelin-dom', ··· 1626 1622 'javelin-mask', 1627 1623 'phabricator-drag-and-drop-file-upload', 1628 1624 ), 1625 + '99abf4cd' => array( 1626 + 'javelin-dom', 1627 + 'javelin-util', 1628 + 'javelin-stratcom', 1629 + 'javelin-install', 1630 + 'javelin-workflow', 1631 + 'javelin-router', 1632 + 'javelin-behavior-device', 1633 + 'javelin-vector', 1634 + 'phabricator-diff-inline', 1635 + ), 1629 1636 '9a6dd75c' => array( 1630 1637 'javelin-behavior', 1631 1638 'javelin-stratcom', ··· 1956 1963 'cd2b9b77' => array( 1957 1964 'phui-oi-list-view-css', 1958 1965 ), 1959 - 'cdc5fa19' => array( 1960 - 'javelin-dom', 1961 - 'javelin-util', 1962 - 'javelin-stratcom', 1963 - 'javelin-install', 1964 - 'javelin-workflow', 1965 - 'javelin-router', 1966 - 'javelin-behavior-device', 1967 - 'javelin-vector', 1968 - 'phabricator-diff-inline', 1969 - ), 1970 1966 'd0a99ab4' => array( 1971 1967 'javelin-behavior', 1972 1968 'javelin-typeahead-ondemand-source', ··· 1990 1986 ), 1991 1987 'd254d646' => array( 1992 1988 'javelin-util', 1989 + ), 1990 + 'd442be4a' => array( 1991 + 'javelin-install', 1992 + 'phuix-button-view', 1993 1993 ), 1994 1994 'd4505101' => array( 1995 1995 'javelin-stratcom',
+6
src/applications/differential/view/DifferentialChangesetListView.php
··· 279 279 'Unsaved' => pht('Unsaved'), 280 280 'Unsubmitted' => pht('Unsubmitted'), 281 281 'Comments' => pht('Comments'), 282 + 283 + 'Hide "Done" Inlines' => pht('Hide "Done" Inlines'), 284 + 'Hide Collapsed Inlines' => pht('Hide Collapsed Inlines'), 285 + 'Hide Older Inlines' => pht('Hide Older Inlines'), 286 + 'Hide All Inlines' => pht('Hide All Inlines'), 287 + 'Show All Inlines' => pht('Show All Inlines'), 282 288 ), 283 289 )); 284 290
+1
webroot/rsrc/js/application/diff/DiffChangeset.js
··· 446 446 type: block.type, 447 447 changeset: this, 448 448 target: inline, 449 + hidden: inline.isHidden(), 449 450 collapsed: inline.isCollapsed(), 450 451 deleted: !inline.getID() && !inline.isEditing(), 451 452 nodes: {
+244 -43
webroot/rsrc/js/application/diff/DiffChangesetList.js
··· 117 117 _doneButton: null, 118 118 _doneMode: null, 119 119 120 + _dropdownMenu: null, 121 + _menuButton: null, 122 + _menuItems: null, 123 + 120 124 sleep: function() { 121 125 this._asleep = true; 122 126 ··· 458 462 var collapsed = options.collapsed || false; 459 463 var wrap = options.wrap || false; 460 464 var attribute = options.attribute || null; 465 + var show = options.show || false; 461 466 462 467 var cursor = state.cursor; 463 468 var items = state.items; ··· 527 532 if (!(items[cursor].attributes || {})[attribute]) { 528 533 continue; 529 534 } 535 + } 536 + 537 + // If this item is a hidden inline but we're clicking a button which 538 + // selects inlines of a particular type, make it visible again. 539 + if (items[cursor].hidden) { 540 + if (!show) { 541 + continue; 542 + } 543 + items[cursor].target.setHidden(false); 530 544 } 531 545 532 546 // Otherwise, we've found a valid item to select. ··· 1314 1328 }, 1315 1329 1316 1330 _redrawBanner: function() { 1331 + // If the inline comment menu is open and we've done a redraw, close it. 1332 + // In particular, this makes it close when you scroll the document: 1333 + // otherwise, it stays open but the banner moves underneath it. 1334 + if (this._dropdownMenu) { 1335 + this._dropdownMenu.close(); 1336 + } 1337 + 1317 1338 var node = this._getBannerNode(); 1318 1339 var changeset = this._getVisibleChangeset(); 1319 1340 ··· 1329 1350 return; 1330 1351 } 1331 1352 1332 - var changesets = this._changesets; 1333 - var unsaved = []; 1334 - var unsubmitted = []; 1335 - var draft_done = []; 1336 - var undone = []; 1337 - var done = []; 1353 + var inlines = this._getInlinesByType(); 1338 1354 1339 - for (var ii = 0; ii < changesets.length; ii++) { 1340 - var inlines = changesets[ii].getInlines(); 1341 - for (var jj = 0; jj < inlines.length; jj++) { 1342 - var inline = inlines[jj]; 1343 - 1344 - if (inline.isDeleted()) { 1345 - continue; 1346 - } 1347 - 1348 - if (inline.isSynthetic()) { 1349 - continue; 1350 - } 1351 - 1352 - if (inline.isEditing()) { 1353 - unsaved.push(inline); 1354 - } else if (!inline.getID()) { 1355 - // These are new comments which have been cancelled, and do not 1356 - // count as anything. 1357 - continue; 1358 - } else if (inline.isDraft()) { 1359 - unsubmitted.push(inline); 1360 - } else { 1361 - // NOTE: Unlike other states, an inline may be marked with a 1362 - // draft checkmark and still be a "done" or "undone" comment. 1363 - if (inline.isDraftDone()) { 1364 - draft_done.push(inline); 1365 - } 1366 - 1367 - if (!inline.isDone()) { 1368 - undone.push(inline); 1369 - } else { 1370 - done.push(inline); 1371 - } 1372 - } 1373 - } 1374 - } 1355 + var unsaved = inlines.unsaved; 1356 + var unsubmitted = inlines.unsubmitted; 1357 + var undone = inlines.undone; 1358 + var done = inlines.done; 1359 + var draft_done = inlines.draftDone; 1375 1360 1376 1361 JX.DOM.alterClass( 1377 1362 node, ··· 1392 1377 var unsaved_button = this._getUnsavedButton(); 1393 1378 var unsubmitted_button = this._getUnsubmittedButton(); 1394 1379 var done_button = this._getDoneButton(); 1380 + var menu_button = this._getMenuButton(); 1395 1381 1396 1382 if (unsaved.length) { 1397 1383 unsaved_button.setText(unsaved.length + ' ' + pht('Unsaved')); ··· 1457 1443 var buttons_list = [ 1458 1444 unsaved_button.getNode(), 1459 1445 unsubmitted_button.getNode(), 1460 - done_button.getNode() 1446 + done_button.getNode(), 1447 + menu_button.getNode() 1461 1448 ]; 1462 1449 1463 1450 var buttons_view = JX.$N('div', buttons_attrs, buttons_list); ··· 1470 1457 document.body.appendChild(node); 1471 1458 }, 1472 1459 1460 + _getInlinesByType: function() { 1461 + var changesets = this._changesets; 1462 + var unsaved = []; 1463 + var unsubmitted = []; 1464 + var undone = []; 1465 + var done = []; 1466 + var draft_done = []; 1467 + 1468 + var visible_done = []; 1469 + var visible_collapsed = []; 1470 + var visible_ghosts = []; 1471 + var visible = []; 1472 + var hidden = []; 1473 + 1474 + for (var ii = 0; ii < changesets.length; ii++) { 1475 + var inlines = changesets[ii].getInlines(); 1476 + var inline; 1477 + var jj; 1478 + for (jj = 0; jj < inlines.length; jj++) { 1479 + inline = inlines[jj]; 1480 + 1481 + if (inline.isDeleted()) { 1482 + continue; 1483 + } 1484 + 1485 + if (inline.isSynthetic()) { 1486 + continue; 1487 + } 1488 + 1489 + if (inline.isEditing()) { 1490 + unsaved.push(inline); 1491 + } else if (!inline.getID()) { 1492 + // These are new comments which have been cancelled, and do not 1493 + // count as anything. 1494 + continue; 1495 + } else if (inline.isDraft()) { 1496 + unsubmitted.push(inline); 1497 + } else { 1498 + // NOTE: Unlike other states, an inline may be marked with a 1499 + // draft checkmark and still be a "done" or "undone" comment. 1500 + if (inline.isDraftDone()) { 1501 + draft_done.push(inline); 1502 + } 1503 + 1504 + if (!inline.isDone()) { 1505 + undone.push(inline); 1506 + } else { 1507 + done.push(inline); 1508 + } 1509 + } 1510 + } 1511 + 1512 + for (jj = 0; jj < inlines.length; jj++) { 1513 + inline = inlines[jj]; 1514 + if (inline.isDeleted()) { 1515 + continue; 1516 + } 1517 + 1518 + if (inline.isEditing()) { 1519 + continue; 1520 + } 1521 + 1522 + if (inline.isHidden()) { 1523 + hidden.push(inline); 1524 + continue; 1525 + } 1526 + 1527 + visible.push(inline); 1528 + 1529 + if (inline.isDone()) { 1530 + visible_done.push(inline); 1531 + } 1532 + 1533 + if (inline.isCollapsed()) { 1534 + visible_collapsed.push(inline); 1535 + } 1536 + 1537 + if (inline.isGhost()) { 1538 + visible_ghosts.push(inline); 1539 + } 1540 + } 1541 + } 1542 + 1543 + return { 1544 + unsaved: unsaved, 1545 + unsubmitted: unsubmitted, 1546 + undone: undone, 1547 + done: done, 1548 + draftDone: draft_done, 1549 + visibleDone: visible_done, 1550 + visibleGhosts: visible_ghosts, 1551 + visibleCollapsed: visible_collapsed, 1552 + visible: visible, 1553 + hidden: hidden 1554 + }; 1555 + 1556 + }, 1557 + 1473 1558 _getUnsavedButton: function() { 1474 1559 if (!this._unsavedButton) { 1475 1560 var button = new JX.PHUIXButtonView() ··· 1520 1605 1521 1606 return this._doneButton; 1522 1607 }, 1608 + 1609 + _getMenuButton: function() { 1610 + if (!this._menuButton) { 1611 + var button = new JX.PHUIXButtonView() 1612 + .setIcon('fa-gear') 1613 + .setButtonType(JX.PHUIXButtonView.BUTTONTYPE_SIMPLE); 1614 + 1615 + var dropdown = new JX.PHUIXDropdownMenu(button.getNode()); 1616 + this._menuItems = {}; 1617 + 1618 + var list = new JX.PHUIXActionListView(); 1619 + dropdown.setContent(list.getNode()); 1620 + 1621 + var map = { 1622 + hideDone: { 1623 + type: 'done' 1624 + }, 1625 + hideCollapsed: { 1626 + type: 'collapsed' 1627 + }, 1628 + hideGhosts: { 1629 + type: 'ghosts' 1630 + }, 1631 + hideAll: { 1632 + type: 'all' 1633 + }, 1634 + showAll: { 1635 + type: 'show' 1636 + } 1637 + }; 1638 + 1639 + for (var k in map) { 1640 + var spec = map[k]; 1641 + 1642 + var handler = JX.bind(this, this._onhideinlines, spec.type); 1643 + var item = new JX.PHUIXActionView() 1644 + .setHandler(handler); 1645 + 1646 + list.addItem(item); 1647 + this._menuItems[k] = item; 1648 + } 1649 + 1650 + dropdown.listen('open', JX.bind(this, this._ondropdown)); 1651 + 1652 + this._menuButton = button; 1653 + this._dropdownMenu = dropdown; 1654 + } 1655 + 1656 + return this._menuButton; 1657 + }, 1658 + 1659 + _ondropdown: function() { 1660 + var inlines = this._getInlinesByType(); 1661 + var items = this._menuItems; 1662 + var pht = this.getTranslations(); 1663 + 1664 + items.hideDone 1665 + .setName(pht('Hide "Done" Inlines')) 1666 + .setDisabled(!inlines.visibleDone.length); 1667 + 1668 + items.hideCollapsed 1669 + .setName(pht('Hide Collapsed Inlines')) 1670 + .setDisabled(!inlines.visibleCollapsed.length); 1671 + 1672 + items.hideGhosts 1673 + .setName(pht('Hide Older Inlines')) 1674 + .setDisabled(!inlines.visibleGhosts.length); 1675 + 1676 + items.hideAll 1677 + .setName(pht('Hide All Inlines')) 1678 + .setDisabled(!inlines.visible.length); 1679 + 1680 + items.showAll 1681 + .setName(pht('Show All Inlines')) 1682 + .setDisabled(!inlines.hidden.length); 1683 + }, 1684 + 1685 + _onhideinlines: function(type, e) { 1686 + this._dropdownMenu.close(); 1687 + e.prevent(); 1688 + 1689 + var inlines = this._getInlinesByType(); 1690 + 1691 + // Clear the selection state since we end up in a weird place if the 1692 + // user hides the selected inline. 1693 + this._setSelectionState(null); 1694 + 1695 + var targets; 1696 + var mode = true; 1697 + switch (type) { 1698 + case 'done': 1699 + targets = inlines.visibleDone; 1700 + break; 1701 + case 'collapsed': 1702 + targets = inlines.visibleCollapsed; 1703 + break; 1704 + case 'ghosts': 1705 + targets = inlines.visibleGhosts; 1706 + break; 1707 + case 'all': 1708 + targets = inlines.visible; 1709 + break; 1710 + case 'show': 1711 + targets = inlines.hidden; 1712 + mode = false; 1713 + break; 1714 + } 1715 + 1716 + for (var ii = 0; ii < targets.length; ii++) { 1717 + targets[ii].setHidden(mode); 1718 + } 1719 + }, 1720 + 1523 1721 _onunsavedclick: function(e) { 1524 1722 e.kill(); 1525 1723 1526 1724 var options = { 1527 1725 filter: 'comment', 1528 1726 wrap: true, 1727 + show: true, 1529 1728 attribute: 'unsaved' 1530 1729 }; 1531 1730 ··· 1538 1737 var options = { 1539 1738 filter: 'comment', 1540 1739 wrap: true, 1740 + show: true, 1541 1741 attribute: 'anyDraft' 1542 1742 }; 1543 1743 ··· 1550 1750 var options = { 1551 1751 filter: 'comment', 1552 1752 wrap: true, 1753 + show: true, 1553 1754 attribute: this._doneMode 1554 1755 }; 1555 1756
+18 -2
webroot/rsrc/js/application/diff/DiffInline.js
··· 36 36 _isEditing: false, 37 37 _isNew: false, 38 38 _isSynthetic: false, 39 + _isHidden: false, 39 40 40 41 bindToRow: function(row) { 41 42 this._row = row; ··· 107 108 108 109 isDraftDone: function() { 109 110 return this._isDraftDone; 111 + }, 112 + 113 + isHidden: function() { 114 + return this._isHidden; 115 + }, 116 + 117 + isGhost: function() { 118 + return this._isGhost; 110 119 }, 111 120 112 121 bindToRange: function(data) { ··· 204 213 205 214 setEditing: function(editing) { 206 215 this._isEditing = editing; 216 + return this; 217 + }, 218 + 219 + setHidden: function(hidden) { 220 + this._isHidden = hidden; 221 + this._redraw(); 207 222 return this; 208 223 }, 209 224 ··· 708 723 }, 709 724 710 725 _redraw: function() { 711 - var is_invisible = (this._isInvisible || this._isDeleted); 726 + var is_invisible = 727 + (this._isInvisible || this._isDeleted || this._isHidden); 712 728 var is_loading = this._isLoading; 713 - var is_collapsed = this._isCollapsed; 729 + var is_collapsed = (this._isCollapsed && !this._isHidden); 714 730 715 731 var row = this._row; 716 732 JX.DOM.alterClass(row, 'differential-inline-hidden', is_invisible);