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

Stabilize scroll position as diffs load

Summary:
Try to lock the screen to whatever the user is looking at as we load changesets.

Notably, this improves the use case of taking a known action on a diff. Currently, you have to wait for everything to load or the comments keep getting scrolled down. After this change, the comments stay in the same place on screen.

Test Plan:
Raised the autoload changeset limit from 100 to 1000, looked at a 220 changeset diff.

- Reloaded it while scrolled at the top; normal behavior (no scrolling).
- Reloaded it, scrolled to the bottom. Comment area now stable.
- Reloaded it, kind of scrolled around the middle? Behavior seemed stable/reasonable. This one is kind of heursitic so it's hard to say I'm getting it totally right or not, but it's less important than the "bottom" case.

Reviewers: vrana, btrahan, chad, dctrwatson

Reviewed By: btrahan

CC: aran

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

+91 -48
+47 -46
src/__celerity_resource_map__.php
··· 1305 1305 ), 1306 1306 'javelin-behavior-differential-populate' => 1307 1307 array( 1308 - 'uri' => '/res/71effec4/rsrc/js/application/differential/behavior-populate.js', 1308 + 'uri' => '/res/526c2615/rsrc/js/application/differential/behavior-populate.js', 1309 1309 'type' => 'js', 1310 1310 'requires' => 1311 1311 array( ··· 1315 1315 3 => 'javelin-dom', 1316 1316 4 => 'javelin-stratcom', 1317 1317 5 => 'javelin-behavior-device', 1318 - 6 => 'phabricator-tooltip', 1318 + 6 => 'javelin-vector', 1319 + 7 => 'phabricator-tooltip', 1319 1320 ), 1320 1321 'disk' => '/rsrc/js/application/differential/behavior-populate.js', 1321 1322 ), ··· 1850 1851 ), 1851 1852 'javelin-behavior-pholio-mock-view' => 1852 1853 array( 1853 - 'uri' => '/res/e7946465/rsrc/js/application/pholio/behavior-pholio-mock-view.js', 1854 + 'uri' => '/res/10fbdca1/rsrc/js/application/pholio/behavior-pholio-mock-view.js', 1854 1855 'type' => 'js', 1855 1856 'requires' => 1856 1857 array( ··· 2038 2039 ), 2039 2040 'javelin-event' => 2040 2041 array( 2041 - 'uri' => '/res/fdb41aa9/rsrc/js/javelin/core/Event.js', 2042 + 'uri' => '/res/3815b473/rsrc/js/javelin/core/Event.js', 2042 2043 'type' => 'js', 2043 2044 'requires' => 2044 2045 array( ··· 3504 3505 'uri' => '/res/pkg/ec01d039/differential.pkg.css', 3505 3506 'type' => 'css', 3506 3507 ), 3507 - '9dae5f20' => 3508 + '1b2c991b' => 3508 3509 array( 3509 3510 'name' => 'differential.pkg.js', 3510 3511 'symbols' => ··· 3529 3530 17 => 'javelin-behavior-differential-toggle-files', 3530 3531 18 => 'javelin-behavior-differential-user-select', 3531 3532 ), 3532 - 'uri' => '/res/pkg/9dae5f20/differential.pkg.js', 3533 + 'uri' => '/res/pkg/1b2c991b/differential.pkg.js', 3533 3534 'type' => 'js', 3534 3535 ), 3535 3536 'c8ce2d88' => ··· 3555 3556 'uri' => '/res/pkg/f96657b8/diffusion.pkg.js', 3556 3557 'type' => 'js', 3557 3558 ), 3558 - '5f5e63ce' => 3559 + 'fbeded59' => 3559 3560 array( 3560 3561 'name' => 'javelin.pkg.js', 3561 3562 'symbols' => ··· 3580 3581 17 => 'javelin-typeahead-ondemand-source', 3581 3582 18 => 'javelin-tokenizer', 3582 3583 ), 3583 - 'uri' => '/res/pkg/5f5e63ce/javelin.pkg.js', 3584 + 'uri' => '/res/pkg/fbeded59/javelin.pkg.js', 3584 3585 'type' => 'js', 3585 3586 ), 3586 3587 'e30a3fa8' => ··· 3629 3630 'aphront-typeahead-control-css' => '6ea96b26', 3630 3631 'differential-changeset-view-css' => 'ec01d039', 3631 3632 'differential-core-view-css' => 'ec01d039', 3632 - 'differential-inline-comment-editor' => '9dae5f20', 3633 + 'differential-inline-comment-editor' => '1b2c991b', 3633 3634 'differential-local-commits-view-css' => 'ec01d039', 3634 3635 'differential-results-table-css' => 'ec01d039', 3635 3636 'differential-revision-add-comment-css' => 'ec01d039', ··· 3643 3644 'global-drag-and-drop-css' => '6ea96b26', 3644 3645 'inline-comment-summary-css' => 'ec01d039', 3645 3646 'javelin-aphlict' => '8a3f0fbd', 3646 - 'javelin-behavior' => '5f5e63ce', 3647 + 'javelin-behavior' => 'fbeded59', 3647 3648 'javelin-behavior-aphlict-dropdown' => '8a3f0fbd', 3648 3649 'javelin-behavior-aphlict-listen' => '8a3f0fbd', 3649 3650 'javelin-behavior-aphront-basic-tokenizer' => '8a3f0fbd', 3650 - 'javelin-behavior-aphront-drag-and-drop' => '9dae5f20', 3651 - 'javelin-behavior-aphront-drag-and-drop-textarea' => '9dae5f20', 3651 + 'javelin-behavior-aphront-drag-and-drop' => '1b2c991b', 3652 + 'javelin-behavior-aphront-drag-and-drop-textarea' => '1b2c991b', 3652 3653 'javelin-behavior-aphront-form-disable-on-submit' => '8a3f0fbd', 3653 3654 'javelin-behavior-audit-preview' => 'f96657b8', 3654 3655 'javelin-behavior-dark-console' => '8edbada5', 3655 3656 'javelin-behavior-dark-console-ajax' => '8edbada5', 3656 3657 'javelin-behavior-device' => '8a3f0fbd', 3657 - 'javelin-behavior-differential-accept-with-errors' => '9dae5f20', 3658 - 'javelin-behavior-differential-add-reviewers-and-ccs' => '9dae5f20', 3659 - 'javelin-behavior-differential-comment-jump' => '9dae5f20', 3660 - 'javelin-behavior-differential-diff-radios' => '9dae5f20', 3661 - 'javelin-behavior-differential-dropdown-menus' => '9dae5f20', 3662 - 'javelin-behavior-differential-edit-inline-comments' => '9dae5f20', 3663 - 'javelin-behavior-differential-feedback-preview' => '9dae5f20', 3664 - 'javelin-behavior-differential-keyboard-navigation' => '9dae5f20', 3665 - 'javelin-behavior-differential-populate' => '9dae5f20', 3666 - 'javelin-behavior-differential-show-more' => '9dae5f20', 3667 - 'javelin-behavior-differential-toggle-files' => '9dae5f20', 3668 - 'javelin-behavior-differential-user-select' => '9dae5f20', 3658 + 'javelin-behavior-differential-accept-with-errors' => '1b2c991b', 3659 + 'javelin-behavior-differential-add-reviewers-and-ccs' => '1b2c991b', 3660 + 'javelin-behavior-differential-comment-jump' => '1b2c991b', 3661 + 'javelin-behavior-differential-diff-radios' => '1b2c991b', 3662 + 'javelin-behavior-differential-dropdown-menus' => '1b2c991b', 3663 + 'javelin-behavior-differential-edit-inline-comments' => '1b2c991b', 3664 + 'javelin-behavior-differential-feedback-preview' => '1b2c991b', 3665 + 'javelin-behavior-differential-keyboard-navigation' => '1b2c991b', 3666 + 'javelin-behavior-differential-populate' => '1b2c991b', 3667 + 'javelin-behavior-differential-show-more' => '1b2c991b', 3668 + 'javelin-behavior-differential-toggle-files' => '1b2c991b', 3669 + 'javelin-behavior-differential-user-select' => '1b2c991b', 3669 3670 'javelin-behavior-diffusion-commit-graph' => 'f96657b8', 3670 3671 'javelin-behavior-diffusion-pull-lastmodified' => 'f96657b8', 3671 3672 'javelin-behavior-error-log' => '8edbada5', ··· 3682 3683 'javelin-behavior-phabricator-home-reveal-tiles' => '8a3f0fbd', 3683 3684 'javelin-behavior-phabricator-keyboard-shortcuts' => '8a3f0fbd', 3684 3685 'javelin-behavior-phabricator-nav' => '8a3f0fbd', 3685 - 'javelin-behavior-phabricator-object-selector' => '9dae5f20', 3686 + 'javelin-behavior-phabricator-object-selector' => '1b2c991b', 3686 3687 'javelin-behavior-phabricator-oncopy' => '8a3f0fbd', 3687 3688 'javelin-behavior-phabricator-remarkup-assist' => '8a3f0fbd', 3688 3689 'javelin-behavior-phabricator-search-typeahead' => '8a3f0fbd', 3689 3690 'javelin-behavior-phabricator-tooltips' => '8a3f0fbd', 3690 3691 'javelin-behavior-phabricator-watch-anchor' => '8a3f0fbd', 3691 3692 'javelin-behavior-refresh-csrf' => '8a3f0fbd', 3692 - 'javelin-behavior-repository-crossreference' => '9dae5f20', 3693 + 'javelin-behavior-repository-crossreference' => '1b2c991b', 3693 3694 'javelin-behavior-toggle-class' => '8a3f0fbd', 3694 3695 'javelin-behavior-workflow' => '8a3f0fbd', 3695 - 'javelin-dom' => '5f5e63ce', 3696 - 'javelin-event' => '5f5e63ce', 3697 - 'javelin-install' => '5f5e63ce', 3698 - 'javelin-json' => '5f5e63ce', 3699 - 'javelin-mask' => '5f5e63ce', 3700 - 'javelin-request' => '5f5e63ce', 3701 - 'javelin-resource' => '5f5e63ce', 3702 - 'javelin-stratcom' => '5f5e63ce', 3703 - 'javelin-tokenizer' => '5f5e63ce', 3704 - 'javelin-typeahead' => '5f5e63ce', 3705 - 'javelin-typeahead-normalizer' => '5f5e63ce', 3706 - 'javelin-typeahead-ondemand-source' => '5f5e63ce', 3707 - 'javelin-typeahead-preloaded-source' => '5f5e63ce', 3708 - 'javelin-typeahead-source' => '5f5e63ce', 3709 - 'javelin-uri' => '5f5e63ce', 3710 - 'javelin-util' => '5f5e63ce', 3711 - 'javelin-vector' => '5f5e63ce', 3712 - 'javelin-workflow' => '5f5e63ce', 3696 + 'javelin-dom' => 'fbeded59', 3697 + 'javelin-event' => 'fbeded59', 3698 + 'javelin-install' => 'fbeded59', 3699 + 'javelin-json' => 'fbeded59', 3700 + 'javelin-mask' => 'fbeded59', 3701 + 'javelin-request' => 'fbeded59', 3702 + 'javelin-resource' => 'fbeded59', 3703 + 'javelin-stratcom' => 'fbeded59', 3704 + 'javelin-tokenizer' => 'fbeded59', 3705 + 'javelin-typeahead' => 'fbeded59', 3706 + 'javelin-typeahead-normalizer' => 'fbeded59', 3707 + 'javelin-typeahead-ondemand-source' => 'fbeded59', 3708 + 'javelin-typeahead-preloaded-source' => 'fbeded59', 3709 + 'javelin-typeahead-source' => 'fbeded59', 3710 + 'javelin-uri' => 'fbeded59', 3711 + 'javelin-util' => 'fbeded59', 3712 + 'javelin-vector' => 'fbeded59', 3713 + 'javelin-workflow' => 'fbeded59', 3713 3714 'lightbox-attachment-css' => '6ea96b26', 3714 3715 'maniphest-task-summary-css' => 'e30a3fa8', 3715 3716 'maniphest-transaction-detail-css' => 'e30a3fa8', ··· 3719 3720 'phabricator-core-css' => '6ea96b26', 3720 3721 'phabricator-crumbs-view-css' => '6ea96b26', 3721 3722 'phabricator-directory-css' => '6ea96b26', 3722 - 'phabricator-drag-and-drop-file-upload' => '9dae5f20', 3723 + 'phabricator-drag-and-drop-file-upload' => '1b2c991b', 3723 3724 'phabricator-dropdown-menu' => '8a3f0fbd', 3724 3725 'phabricator-file-upload' => '8a3f0fbd', 3725 3726 'phabricator-filetree-view-css' => '6ea96b26', ··· 3741 3742 'phabricator-prefab' => '8a3f0fbd', 3742 3743 'phabricator-project-tag-css' => 'e30a3fa8', 3743 3744 'phabricator-remarkup-css' => '6ea96b26', 3744 - 'phabricator-shaped-request' => '9dae5f20', 3745 + 'phabricator-shaped-request' => '1b2c991b', 3745 3746 'phabricator-side-menu-view-css' => '6ea96b26', 3746 3747 'phabricator-standard-page-view' => '6ea96b26', 3747 3748 'phabricator-textareautils' => '8a3f0fbd',
+44 -2
webroot/rsrc/js/application/differential/behavior-populate.js
··· 6 6 * javelin-dom 7 7 * javelin-stratcom 8 8 * javelin-behavior-device 9 + * javelin-vector 9 10 * phabricator-tooltip 10 11 */ 11 12 12 13 JX.behavior('differential-populate', function(config) { 13 14 14 - function onresponse(target, response) { 15 - JX.DOM.replace(JX.$(target), JX.$H(response.changeset)); 15 + function onresponse(target_id, response) { 16 + // As we populate the diff, we try to hold the document scroll position 17 + // steady, so that, e.g., users who want to leave a comment on a diff with a 18 + // large number of changes don't constantly have the text area scrolled off 19 + // the bottom of the screen until the entire diff loads. 20 + // 21 + // There are two three major cases here: 22 + // 23 + // - If we're near the top of the document, never scroll. 24 + // - If we're near the bottom of the document, always scroll. 25 + // - Otherwise, scroll if the changes were above the midline of the 26 + // viewport. 27 + var target = JX.$(target_id); 28 + 29 + var old_pos = JX.Vector.getScroll(); 30 + var old_view = JX.Vector.getViewport(); 31 + var old_dim = JX.Vector.getDocument(); 32 + 33 + // Number of pixels away from the top or bottom of the document which 34 + // count as "nearby". 35 + var sticky = 480; 36 + 37 + var near_top = (old_pos.y <= sticky); 38 + var near_bot = ((old_pos.y + old_view.y) >= (old_dim.y - sticky)); 39 + 40 + var target_pos = JX.Vector.getPos(target); 41 + var target_dim = JX.Vector.getDim(target); 42 + var target_mid = (target_pos.y + (target_dim.y / 2)); 43 + 44 + var view_mid = (old_pos.y + (old_view.y / 2)); 45 + var above_mid = (target_mid < view_mid); 46 + 47 + JX.DOM.replace(target, JX.$H(response.changeset)); 48 + 49 + if (!near_top) { 50 + if (near_bot || above_mid) { 51 + // Figure out how much taller the document got. 52 + var delta = (JX.Vector.getDocument().y - old_dim.y); 53 + 54 + window.scrollTo(old_pos.x, old_pos.y + delta); 55 + } 56 + } 57 + 16 58 if (response.coverage) { 17 59 for (var k in response.coverage) { 18 60 try {