mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 04:45:45 +00:00
Bug 1511710 - The timeline should let you zoom. r=bhackett
Tags: Bug #: 1511710 Differential Revision: https://phabricator.services.mozilla.com/D13643
This commit is contained in:
parent
966d77bf1d
commit
ae132b3430
@ -483,6 +483,7 @@
|
||||
background: #fff;
|
||||
margin: 4px 10px 4px 0;
|
||||
border: 1px solid #bfc9d2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.webreplay-player .progress {
|
||||
@ -497,7 +498,7 @@
|
||||
background: var(--purple-50);
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
right: 0;
|
||||
right: -0.5px;
|
||||
opacity: 0.4;
|
||||
display: block;
|
||||
content: "";
|
||||
@ -629,3 +630,55 @@
|
||||
background: #d0021b;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.webreplay-player .tick {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
transition-duration: var(--progress-bar-transition);
|
||||
}
|
||||
|
||||
.webreplay-player .tick::before,
|
||||
.webreplay-player .tick::after {
|
||||
height: 1.5px;
|
||||
width: 1px;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
content: "";
|
||||
display: block;
|
||||
}
|
||||
|
||||
.webreplay-player .recording .tick::before,
|
||||
.webreplay-player .recording .tick::after {
|
||||
background: #d0021b;
|
||||
}
|
||||
|
||||
.webreplay-player .tick.future::before,
|
||||
.webreplay-player .tick.future::after {
|
||||
background: #bfc9d2;
|
||||
}
|
||||
|
||||
.webreplay-player .tick::before,
|
||||
.webreplay-player .tick::after {
|
||||
background: var(--blue-50);
|
||||
}
|
||||
|
||||
.webreplay-player .tick::after {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.webreplay-player .tick::before {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
|
||||
.webreplay-player #overlay:hover .tick {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.webreplay-player #overlay .tick {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.webreplay-player #overlay .tick:hover ~ .tick {
|
||||
opacity: 0.5;
|
||||
}
|
@ -7,7 +7,7 @@ const { Component } = require("devtools/client/shared/vendor/react");
|
||||
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const {sortBy} = require("devtools/client/shared/vendor/lodash");
|
||||
const { sortBy, range } = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
const { LocalizationHelper } = require("devtools/shared/l10n");
|
||||
const L10N = new LocalizationHelper(
|
||||
@ -104,8 +104,11 @@ class WebReplayPlayer extends Component {
|
||||
paused: false,
|
||||
messages: [],
|
||||
highlightedMessage: null,
|
||||
start: 0,
|
||||
end: 1,
|
||||
};
|
||||
this.overlayWidth = 0;
|
||||
this.overlayWidth = 1;
|
||||
this.onClickProgressBar = this.onClickProgressBar.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@ -159,6 +162,19 @@ class WebReplayPlayer extends Component {
|
||||
return this.state.seeking;
|
||||
}
|
||||
|
||||
getTickSize() {
|
||||
const {start, end} = this.state;
|
||||
const minSize = 10;
|
||||
|
||||
if (!start && !end) {
|
||||
return minSize;
|
||||
}
|
||||
|
||||
const maxSize = this.overlayWidth / 10;
|
||||
const ratio = end - start;
|
||||
return ((1 - ratio) * maxSize) + minSize;
|
||||
}
|
||||
|
||||
onPaused(_, packet) {
|
||||
if (packet && packet.recordingEndpoint) {
|
||||
const { executionPoint, recordingEndpoint } = packet;
|
||||
@ -204,9 +220,13 @@ class WebReplayPlayer extends Component {
|
||||
const {
|
||||
messages: { visibleMessages, messagesById },
|
||||
} = consoleState;
|
||||
const messages = visibleMessages.map(id => messagesById.get(id));
|
||||
|
||||
if (visibleMessages != this.state.visibleMessages) {
|
||||
const messages = sortBy(
|
||||
visibleMessages.map(id => messagesById.get(id)),
|
||||
message => getMessageProgress(message)
|
||||
);
|
||||
|
||||
this.setState({ messages, visibleMessages });
|
||||
}
|
||||
}
|
||||
@ -223,6 +243,27 @@ class WebReplayPlayer extends Component {
|
||||
return null;
|
||||
}
|
||||
|
||||
onClickProgressBar(e) {
|
||||
if (!e.altKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {start, end} = this.state;
|
||||
|
||||
const direction = e.shiftKey ? "end" : "start";
|
||||
const { left, width } = e.currentTarget.getBoundingClientRect();
|
||||
const clickLeft = e.clientX;
|
||||
|
||||
const clickPosition = (clickLeft - left) / width;
|
||||
const position = ((end - start) * clickPosition) + start;
|
||||
|
||||
this.setTimelinePosition({ position, direction });
|
||||
}
|
||||
|
||||
setTimelinePosition({ position, direction }) {
|
||||
this.setState({[direction]: position});
|
||||
}
|
||||
|
||||
scrollToMessage() {
|
||||
const {closestMessage} = this.state;
|
||||
|
||||
@ -358,7 +399,7 @@ class WebReplayPlayer extends Component {
|
||||
|
||||
updateOverlayWidth() {
|
||||
const el = ReactDOM.findDOMNode(this).querySelector(".progressBar");
|
||||
return el.clientWidth;
|
||||
return el ? el.clientWidth : 1;
|
||||
}
|
||||
|
||||
// calculate pixel distance from two points
|
||||
@ -374,12 +415,48 @@ class WebReplayPlayer extends Component {
|
||||
return (percent * this.overlayWidth) / 100;
|
||||
}
|
||||
|
||||
getPercent(executionPoint) {
|
||||
const {recordingEndpoint} = this.state;
|
||||
|
||||
if (!recordingEndpoint) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
if (!executionPoint) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const ratio = executionPoint.progress / recordingEndpoint.progress;
|
||||
return ratio * 100;
|
||||
}
|
||||
|
||||
getVisiblePercent(executionPoint) {
|
||||
const {start, end} = this.state;
|
||||
|
||||
const position = this.getPercent(executionPoint) / 100;
|
||||
|
||||
if (position < start || position > end) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ((position - start) / (end - start)) * 100;
|
||||
}
|
||||
|
||||
getVisibleOffset(point) {
|
||||
const percent = this.getVisiblePercent(point);
|
||||
return (percent * this.overlayWidth) / 100;
|
||||
}
|
||||
|
||||
renderMessage(message, index) {
|
||||
const { messages, executionPoint, highlightedMessage } = this.state;
|
||||
|
||||
const offset = this.getOffset(message.executionPoint);
|
||||
const offset = this.getVisibleOffset(message.executionPoint);
|
||||
const previousMessage = messages[index - 1];
|
||||
|
||||
if (offset < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check to see if two messages overlay each other on the timeline
|
||||
const isOverlayed =
|
||||
previousMessage &&
|
||||
@ -402,35 +479,50 @@ class WebReplayPlayer extends Component {
|
||||
highlighted: isHighlighted,
|
||||
}),
|
||||
style: {
|
||||
left: `${offset - markerWidth / 2}px`,
|
||||
left: `${Math.max(offset - markerWidth/2, 0)}px`,
|
||||
zIndex: `${index + 100}`,
|
||||
},
|
||||
title: getFormatStr("jumpMessage", index + 1),
|
||||
onClick: () => this.seek(message.executionPoint),
|
||||
onClick: (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.seek(message.executionPoint);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
renderMessages() {
|
||||
const messages = this.state.messages;
|
||||
return messages.map((message, index) => this.renderMessage(message, index));
|
||||
return messages
|
||||
.map((message, index) => this.renderMessage(message, index));
|
||||
}
|
||||
|
||||
getPercent(executionPoint) {
|
||||
if (!this.state.recordingEndpoint) {
|
||||
return 100;
|
||||
}
|
||||
renderTicks() {
|
||||
const tickSize = this.getTickSize();
|
||||
const ticks = Math.round((this.overlayWidth) / tickSize);
|
||||
return range(ticks).map((value, index) => this.renderTick(index));
|
||||
}
|
||||
|
||||
if (!executionPoint) {
|
||||
return 0;
|
||||
}
|
||||
renderTick(index) {
|
||||
const { executionPoint } = this.state;
|
||||
const tickSize = this.getTickSize();
|
||||
const offset = Math.round(this.getOffset(executionPoint));
|
||||
const position = index * tickSize;
|
||||
const isFuture = position > offset;
|
||||
|
||||
const ratio =
|
||||
executionPoint.progress / this.state.recordingEndpoint.progress;
|
||||
return ratio * 100;
|
||||
return dom.span({
|
||||
className: classname("tick", {
|
||||
future: isFuture,
|
||||
}),
|
||||
style: {
|
||||
left: `${position}px`,
|
||||
width: `${tickSize}px`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const percent = this.getPercent(this.state.executionPoint);
|
||||
const percent = this.getVisiblePercent(this.state.executionPoint);
|
||||
const recording = this.isRecording();
|
||||
return div(
|
||||
{ className: "webreplay-player" },
|
||||
@ -443,7 +535,11 @@ class WebReplayPlayer extends Component {
|
||||
{ className: "overlay-container " },
|
||||
div({ className: "commands" }, ...this.renderCommands()),
|
||||
div(
|
||||
{ className: "progressBar" },
|
||||
{
|
||||
className: "progressBar",
|
||||
onClick: this.onClickProgressBar,
|
||||
onDoubleClick: () => this.setState({ start: 0, end: 1 }),
|
||||
},
|
||||
div({
|
||||
className: "progress",
|
||||
style: { width: `${percent}%` },
|
||||
@ -456,7 +552,8 @@ class WebReplayPlayer extends Component {
|
||||
className: "progress-line end",
|
||||
style: { left: `${percent}%`, width: `${100 - percent}%` },
|
||||
}),
|
||||
...this.renderMessages()
|
||||
...this.renderMessages(),
|
||||
...this.renderTicks()
|
||||
)
|
||||
)
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user