Bug 1534938 - Don't scroll to bottom when opening a group. r=Honza.

The heuristic to scroll the console output to the bottom was
to only look if new messages were visible. But it can happen
that such case is triggered by only opening a closed group.
This patch tweaks the heuristic a bit to exclude the case
where we open a group, while making sure that we still
scroll to bottom if there are new, opened, group messages.
A test is added to ensure this works as expected.

Differential Revision: https://phabricator.services.mozilla.com/D23996

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nicolas Chevobbe 2019-03-19 13:37:50 +00:00
parent 02fae301d6
commit 5fe7229262
4 changed files with 94 additions and 9 deletions

View File

@ -108,23 +108,31 @@ class ConsoleOutput extends Component {
return;
}
// We need to scroll to the bottom if:
// - we are reacting to "initialize" action, and we are already scrolled to the bottom
// - the number of messages displayed changed and we are already scrolled to the
// bottom, but not if we are reacting to a group opening.
// - the number of messages in the store changed and the new message is an evaluation
// result.
const lastChild = outputNode.lastChild;
const visibleMessagesDelta =
nextProps.visibleMessages.length - this.props.visibleMessages.length;
const messagesDelta =
nextProps.messages.size - this.props.messages.size;
// We need to scroll to the bottom if:
// - we are reacting to the "initialize" action,
// and we are already scrolled to the bottom
// - the number of messages displayed changed
// and we are already scrolled to the bottom
// - the number of messages in the store changed
// and the new message is an evaluation result.
const isNewMessageEvaluationResult = messagesDelta > 0 &&
[...nextProps.messages.values()][nextProps.messages.size - 1].type
=== MESSAGE_TYPE.RESULT;
const messagesUiDelta =
nextProps.messagesUi.length - this.props.messagesUi.length;
const isOpeningGroup = messagesUiDelta > 0 &&
nextProps.messagesUi.some(id =>
!this.props.messagesUi.includes(id) &&
nextProps.messagesUi.includes(id) &&
this.props.visibleMessages.includes(id) &&
nextProps.visibleMessages.includes(id));
this.shouldScrollBottom =
(
!this.props.initialized &&
@ -132,7 +140,11 @@ class ConsoleOutput extends Component {
isScrolledToBottom(lastChild, outputNode)
) ||
(isNewMessageEvaluationResult) ||
(visibleMessagesDelta > 0 && isScrolledToBottom(lastChild, outputNode));
(
isScrolledToBottom(lastChild, outputNode) &&
visibleMessagesDelta > 0 &&
!isOpeningGroup
);
}
componentDidUpdate() {

View File

@ -253,6 +253,7 @@ skip-if = true # Bug 1405250
[browser_webconsole_console_dir.js]
[browser_webconsole_console_dir_uninspectable.js]
[browser_webconsole_console_error_expand_object.js]
[browser_webconsole_console_group_open_no_scroll.js]
[browser_webconsole_console_group.js]
[browser_webconsole_console_logging_workers_api.js]
skip-if = e10s # SharedWorkers console events are not received on the current process because they could run on any process.

View File

@ -0,0 +1,49 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Check that opening a group does not scroll the console output.
const TEST_URI = `data:text/html,<meta charset=utf8><script>
Array.from({length: 100}, (_, i) => console.log("log-"+i));
console.groupCollapsed("GROUP");
console.log("in group");
</script>`;
add_task(async function() {
const hud = await openNewTabAndConsole(TEST_URI);
const outputScroller = hud.ui.outputScroller;
// Let's wait until the first message and the group are displayed.
await waitFor(() => findMessage(hud, "log-0"));
const groupMessage = await waitFor(() => findMessage(hud, "GROUP"));
is(hasVerticalOverflow(outputScroller), true, "output node overflows");
is(isScrolledToBottom(outputScroller), true, "output node is scrolled to the bottom");
info("Expand the group");
groupMessage.querySelector(".arrow").click();
await waitFor(() => findMessage(hud, "in group"));
is(hasVerticalOverflow(outputScroller), true, "output node overflows");
is(isScrolledToBottom(outputScroller), false,
"output node isn't scrolled to the bottom anymore");
info("Scroll to bottom");
outputScroller.scrollTop = outputScroller.scrollHeight;
is(isScrolledToBottom(outputScroller), true, "output node is scrolled to the bottom");
info("Check that adding a message on an open group when scrolled to bottom scrolls " +
"to bottom");
const onNewMessage = waitForMessage(hud, "new-message");
ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
content.console.group("GROUP-2");
content.console.log("new-message");
});
await onNewMessage;
is(isScrolledToBottom(outputScroller), true,
"output node is scrolled to the bottom after adding message in group");
});

View File

@ -1161,3 +1161,26 @@ async function pauseDebugger(dbg) {
});
await onPaused;
}
/**
* Check that the passed HTMLElement vertically overflows.
* @param {HTMLElement} container
* @returns {Boolean}
*/
function hasVerticalOverflow(container) {
return container.scrollHeight > container.clientHeight;
}
/**
* Check that the passed HTMLElement is scrolled to the bottom.
* @param {HTMLElement} container
* @returns {Boolean}
*/
function isScrolledToBottom(container) {
if (!container.lastChild) {
return true;
}
const lastNodeHeight = container.lastChild.clientHeight;
return container.scrollTop + container.clientHeight >=
container.scrollHeight - lastNodeHeight / 2;
}