Commit 06e046ba authored by Erik Luo's avatar Erik Luo Committed by Commit Bot

DevTools: add space-below-prompt experiment

- Adds an empty 15px space directly below the Console
  prompt's editor.
- Updates "isScrolledToBottom" logic in Console to account
  for the new space. Without this update, typing on the
  prompt's last line will not "jump + stick to bottom"
  as expected.

With this CL, overlay scrollbars (e.g. on Mac), should
never cover the prompt's editor.

Bug: 725249
Change-Id: Ib0167f6919d5b9942e7f2dc4d8cf0c15fc9368df
Reviewed-on: https://chromium-review.googlesource.com/965020
Commit-Queue: Erik Luo <luoe@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarJoel Einbinder <einbinder@chromium.org>
Cr-Commit-Position: refs/heads/master@{#551222}
parent 1aef3d91
Verifies viewport stick-to-bottom behavior when prompt has space below editable area.
Running: testStickToBottomWhenAddingMessages
Is at bottom: true, should stick: true
Running: testScrollViewportToBottom
Is at bottom: true, should stick: true
Running: testJumpToBottomWhenTypingOnLastPromptLine
Is at bottom: true, should stick: true
Running: testDoNotJumpToBottomWhenTypingAboveLastPromptLine
Is at bottom: false, should stick: false
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(async function() {
TestRunner.addResult(`Verifies viewport stick-to-bottom behavior when prompt has space below editable area.\n`);
await TestRunner.loadModule('console_test_runner');
await TestRunner.showPanel('console');
await TestRunner.evaluateInPagePromise(`
function populateConsoleWithMessages(count)
{
for (var i = 0; i < count; ++i)
console.log("Multiline\\nMessage #" + i);
}
//# sourceURL=console-viewport-stick-to-bottom-with-large-prompt.js
`);
await ConsoleTestRunner.waitUntilConsoleEditorLoaded();
ConsoleTestRunner.fixConsoleViewportDimensions(600, 200);
await ConsoleTestRunner.waitForPendingViewportUpdates();
const consoleView = Console.ConsoleView.instance();
const viewport = consoleView._viewport;
const heightBelowPromptEditor = consoleView._prompt.heightBelowEditor();
const messagesCount = 150;
TestRunner.runTestSuite([
async function testStickToBottomWhenAddingMessages(next) {
await logMessagesToConsole(messagesCount);
await ConsoleTestRunner.waitForPendingViewportUpdates();
dumpAndContinue(next);
},
async function testScrollViewportToBottom(next) {
viewport.element.scrollTop = 0;
consoleView._immediatelyScrollToBottom();
await ConsoleTestRunner.waitForPendingViewportUpdates();
dumpAndContinue(next);
},
async function testJumpToBottomWhenTypingOnLastPromptLine(next) {
viewport.element.scrollTop = 0;
await ConsoleTestRunner.waitForPendingViewportUpdates();
// Simulate scroll on type.
viewport.element.scrollTop = viewport.element.scrollHeight - viewport.element.clientHeight - heightBelowPromptEditor;
consoleView._prompt.setText('a');
await ConsoleTestRunner.waitForPendingViewportUpdates();
dumpAndContinue(next);
},
async function testDoNotJumpToBottomWhenTypingAboveLastPromptLine(next) {
const multilineText = `Multiline text\n\n\nfoo`;
consoleView._prompt.setText(multilineText);
viewport.element.scrollTop = 0;
await ConsoleTestRunner.waitForPendingViewportUpdates();
// Simulate scroll on type.
viewport.element.scrollTop = viewport.element.scrollHeight - viewport.element.clientHeight - heightBelowPromptEditor - 3;
consoleView._prompt.setText(multilineText + 'a');
await ConsoleTestRunner.waitForPendingViewportUpdates();
dumpAndContinue(next);
}
]);
function dumpAndContinue(callback) {
viewport.refresh();
TestRunner.addResult(
'Is at bottom: ' + viewport.element.isScrolledToBottom() + ', should stick: ' + viewport.stickToBottom());
callback();
}
function logMessagesToConsole(count) {
return new Promise(resolve => {
var awaitingMessagesCount = count;
function messageAdded() {
if (!--awaitingMessagesCount)
resolve();
else
ConsoleTestRunner.addConsoleSniffer(messageAdded, false);
}
ConsoleTestRunner.addConsoleSniffer(messageAdded, false);
TestRunner.evaluateInPage(String.sprintf('populateConsoleWithMessages(%d)', count));
})
}
})();
...@@ -12,6 +12,8 @@ Console.ConsolePrompt = class extends UI.Widget { ...@@ -12,6 +12,8 @@ Console.ConsolePrompt = class extends UI.Widget {
this._initialText = ''; this._initialText = '';
this._editor = null; this._editor = null;
this._isBelowPromptEnabled = Runtime.experiments.isEnabled('consoleBelowPrompt');
this._eagerPreviewElement = createElementWithClass('div', 'console-eager-preview');
this.element.tabIndex = 0; this.element.tabIndex = 0;
...@@ -33,6 +35,8 @@ Console.ConsolePrompt = class extends UI.Widget { ...@@ -33,6 +35,8 @@ Console.ConsolePrompt = class extends UI.Widget {
this._editor.widget().element.addEventListener('keydown', this._editorKeyDown.bind(this), true); this._editor.widget().element.addEventListener('keydown', this._editorKeyDown.bind(this), true);
this._editor.widget().show(this.element); this._editor.widget().show(this.element);
this._editor.addEventListener(UI.TextEditor.Events.TextChanged, this._onTextChanged, this); this._editor.addEventListener(UI.TextEditor.Events.TextChanged, this._onTextChanged, this);
if (this._isBelowPromptEnabled)
this.element.appendChild(this._eagerPreviewElement);
this.setText(this._initialText); this.setText(this._initialText);
delete this._initialText; delete this._initialText;
...@@ -44,6 +48,13 @@ Console.ConsolePrompt = class extends UI.Widget { ...@@ -44,6 +48,13 @@ Console.ConsolePrompt = class extends UI.Widget {
} }
} }
/**
* @return {number}
*/
heightBelowEditor() {
return this._eagerPreviewElement.offsetHeight;
}
_onTextChanged() { _onTextChanged() {
this.dispatchEventToListeners(Console.ConsolePrompt.Events.TextChanged); this.dispatchEventToListeners(Console.ConsolePrompt.Events.TextChanged);
} }
......
...@@ -47,6 +47,7 @@ Console.ConsoleView = class extends UI.VBox { ...@@ -47,6 +47,7 @@ Console.ConsoleView = class extends UI.VBox {
this._sidebar.addEventListener(Console.ConsoleSidebar.Events.FilterSelected, this._onFilterChanged.bind(this)); this._sidebar.addEventListener(Console.ConsoleSidebar.Events.FilterSelected, this._onFilterChanged.bind(this));
this._isSidebarOpen = false; this._isSidebarOpen = false;
this._filter = new Console.ConsoleViewFilter(this._onFilterChanged.bind(this)); this._filter = new Console.ConsoleViewFilter(this._onFilterChanged.bind(this));
this._isBelowPromptEnabled = Runtime.experiments.isEnabled('consoleBelowPrompt');
const toolbar = new UI.Toolbar('', this.element); const toolbar = new UI.Toolbar('', this.element);
this._splitWidget = this._splitWidget =
...@@ -1132,7 +1133,7 @@ Console.ConsoleView = class extends UI.VBox { ...@@ -1132,7 +1133,7 @@ Console.ConsoleView = class extends UI.VBox {
function updateViewportState() { function updateViewportState() {
this._muteViewportUpdates = false; this._muteViewportUpdates = false;
if (this.isShowing()) if (this.isShowing())
this._viewport.setStickToBottom(this._messagesElement.isScrolledToBottom()); this._viewport.setStickToBottom(this._isScrolledToBottom());
if (this._maybeDirtyWhileMuted) { if (this._maybeDirtyWhileMuted) {
this._scheduleViewportRefresh(); this._scheduleViewportRefresh();
delete this._maybeDirtyWhileMuted; delete this._maybeDirtyWhileMuted;
...@@ -1152,13 +1153,24 @@ Console.ConsoleView = class extends UI.VBox { ...@@ -1152,13 +1153,24 @@ Console.ConsoleView = class extends UI.VBox {
} }
_promptTextChanged() { _promptTextChanged() {
this._viewport.setStickToBottom(this._messagesElement.isScrolledToBottom()); this._viewport.setStickToBottom(this._isScrolledToBottom());
this._promptTextChangedForTest(); this._promptTextChangedForTest();
} }
_promptTextChangedForTest() { _promptTextChangedForTest() {
// This method is sniffed in tests. // This method is sniffed in tests.
} }
/**
* @return {boolean}
*/
_isScrolledToBottom() {
if (!this._isBelowPromptEnabled)
return this._messagesElement.isScrolledToBottom();
const distanceToPromptEditorBottom = this._messagesElement.scrollHeight - this._messagesElement.scrollTop -
this._messagesElement.clientHeight - this._prompt.heightBelowEditor();
return distanceToPromptEditorBottom <= 2;
}
}; };
Console.ConsoleView.persistedHistorySize = 300; Console.ConsoleView.persistedHistorySize = 300;
......
...@@ -448,3 +448,7 @@ ...@@ -448,3 +448,7 @@
.console-searchable-view { .console-searchable-view {
max-height: 100%; max-height: 100%;
} }
.console-eager-preview {
height: 15px;
}
...@@ -108,6 +108,7 @@ Main.Main = class { ...@@ -108,6 +108,7 @@ Main.Main = class {
Runtime.experiments.register('applyCustomStylesheet', 'Allow custom UI themes'); Runtime.experiments.register('applyCustomStylesheet', 'Allow custom UI themes');
Runtime.experiments.register('blackboxJSFramesOnTimeline', 'Blackbox JavaScript frames on Timeline', true); Runtime.experiments.register('blackboxJSFramesOnTimeline', 'Blackbox JavaScript frames on Timeline', true);
Runtime.experiments.register('colorContrastRatio', 'Color contrast ratio line in color picker', true); Runtime.experiments.register('colorContrastRatio', 'Color contrast ratio line in color picker', true);
Runtime.experiments.register('consoleBelowPrompt', 'Console below-prompt UI', true);
Runtime.experiments.register('emptySourceMapAutoStepping', 'Empty sourcemap auto-stepping'); Runtime.experiments.register('emptySourceMapAutoStepping', 'Empty sourcemap auto-stepping');
Runtime.experiments.register('inputEventsOnTimelineOverview', 'Input events on Timeline overview', true); Runtime.experiments.register('inputEventsOnTimelineOverview', 'Input events on Timeline overview', true);
Runtime.experiments.register('nativeHeapProfiler', 'Native memory sampling heap profiler', true); Runtime.experiments.register('nativeHeapProfiler', 'Native memory sampling heap profiler', true);
...@@ -138,6 +139,8 @@ Main.Main = class { ...@@ -138,6 +139,8 @@ Main.Main = class {
Runtime.experiments.enableForTest('oopifInlineDOM'); Runtime.experiments.enableForTest('oopifInlineDOM');
if (testPath.indexOf('network/') !== -1) if (testPath.indexOf('network/') !== -1)
Runtime.experiments.enableForTest('networkSearch'); Runtime.experiments.enableForTest('networkSearch');
if (testPath.indexOf('console/viewport-testing/') !== -1)
Runtime.experiments.enableForTest('consoleBelowPrompt');
} }
Runtime.experiments.setDefaultExperiments(['colorContrastRatio', 'stepIntoAsync', 'oopifInlineDOM']); Runtime.experiments.setDefaultExperiments(['colorContrastRatio', 'stepIntoAsync', 'oopifInlineDOM']);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment