Maintain scroll positions when switching tabs
This commit is contained in:
parent
45c61e7596
commit
52acec9d21
File diff suppressed because one or more lines are too long
@ -4,19 +4,24 @@ import { AutoSizer } from 'react-virtualized/dist/commonjs/AutoSizer';
|
|||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import Message from './Message';
|
import Message from './Message';
|
||||||
import { measureScrollBarWidth } from '../util';
|
import { measureScrollBarWidth } from '../util';
|
||||||
|
import { getScrollPos, saveScrollPos } from '../util/scrollPosition';
|
||||||
|
|
||||||
const scrollBarWidth = measureScrollBarWidth();
|
const scrollBarWidth = measureScrollBarWidth();
|
||||||
const listStyle = { padding: '7px 0', boxSizing: 'content-box' };
|
const listStyle = { padding: '7px 0', boxSizing: 'content-box' };
|
||||||
const threshold = 100;
|
const threshold = 100;
|
||||||
|
|
||||||
export default class MessageBox extends PureComponent {
|
export default class MessageBox extends PureComponent {
|
||||||
|
componentDidMount() {
|
||||||
|
this.loadScrollPos();
|
||||||
|
}
|
||||||
|
|
||||||
componentWillUpdate(nextProps) {
|
componentWillUpdate(nextProps) {
|
||||||
if (nextProps.messages !== this.props.messages) {
|
if (nextProps.messages !== this.props.messages) {
|
||||||
this.list.recomputeRowHeights();
|
this.list.recomputeRowHeights();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextProps.tab !== this.props.tab) {
|
if (nextProps.tab !== this.props.tab) {
|
||||||
this.bottom = true;
|
this.saveScrollPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextProps.messages.get(0) !== this.props.messages.get(0)) {
|
if (nextProps.messages.get(0) !== this.props.messages.get(0)) {
|
||||||
@ -34,17 +39,25 @@ export default class MessageBox extends PureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate(prevProps) {
|
||||||
|
if (prevProps.tab !== this.props.tab) {
|
||||||
|
this.loadScrollPos();
|
||||||
|
}
|
||||||
|
|
||||||
if (this.nextScrollTop > 0) {
|
if (this.nextScrollTop > 0) {
|
||||||
this.container.scrollTop = this.nextScrollTop;
|
this.container.scrollTop = this.nextScrollTop;
|
||||||
this.nextScrollTop = 0;
|
this.nextScrollTop = 0;
|
||||||
} else if (this.bottom) {
|
} else if (this.bottom) {
|
||||||
this.container.scrollTop = this.container.scrollHeight;
|
this.list.scrollToRow(this.props.messages.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateWidth();
|
this.updateWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.saveScrollPos();
|
||||||
|
}
|
||||||
|
|
||||||
getRowHeight = ({ index }) => {
|
getRowHeight = ({ index }) => {
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
if (this.props.hasMoreMessages) {
|
if (this.props.hasMoreMessages) {
|
||||||
@ -57,8 +70,38 @@ export default class MessageBox extends PureComponent {
|
|||||||
|
|
||||||
listRef = el => {
|
listRef = el => {
|
||||||
this.list = el;
|
this.list = el;
|
||||||
|
if (el) {
|
||||||
// eslint-disable-next-line no-underscore-dangle
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
this.container = el.Grid._scrollingContainer;
|
this.container = el.Grid._scrollingContainer;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
updateScrollKey = () => {
|
||||||
|
const { tab } = this.props;
|
||||||
|
this.scrollKey = `msg:${tab.server}:${tab.name}`;
|
||||||
|
return this.scrollKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadScrollPos = () => {
|
||||||
|
const pos = getScrollPos(this.updateScrollKey());
|
||||||
|
if (pos >= 0) {
|
||||||
|
this.bottom = false;
|
||||||
|
this.container.scrollTop = pos;
|
||||||
|
} else {
|
||||||
|
this.bottom = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
saveScrollPos = () => {
|
||||||
|
if (this.bottom) {
|
||||||
|
saveScrollPos(this.scrollKey, -1);
|
||||||
|
} else {
|
||||||
|
saveScrollPos(this.scrollKey, this.container.scrollTop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollDown = () => {
|
||||||
|
this.container.scrollTop = this.container.scrollHeight - this.container.clientHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
updateWidth = (width) => {
|
updateWidth = (width) => {
|
||||||
@ -105,7 +148,7 @@ export default class MessageBox extends PureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bottom = scrollTop + clientHeight >= scrollHeight;
|
this.bottom = scrollTop + clientHeight >= scrollHeight - 10;
|
||||||
this.prevScrollTop = scrollTop;
|
this.prevScrollTop = scrollTop;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ function updateSelected({ params, dispatch }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateCharWidth() {
|
function updateCharWidth() {
|
||||||
const charWidth = stringWidth(' ', '16px Roboto Mono');
|
const charWidth = stringWidth(' ', '16px Roboto Mono, monospace');
|
||||||
window.messageIndent = 6 * charWidth;
|
window.messageIndent = 6 * charWidth;
|
||||||
return setCharWidth(charWidth);
|
return setCharWidth(charWidth);
|
||||||
}
|
}
|
||||||
@ -38,9 +38,6 @@ class Chat extends PureComponent {
|
|||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
dispatch(updateCharWidth());
|
dispatch(updateCharWidth());
|
||||||
setTimeout(() => dispatch(updateCharWidth()), 1000);
|
setTimeout(() => dispatch(updateCharWidth()), 1000);
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
updateSelected(this.props);
|
updateSelected(this.props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
client/src/js/util/scrollPosition.js
Normal file
12
client/src/js/util/scrollPosition.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
const positions = {};
|
||||||
|
|
||||||
|
export function getScrollPos(key) {
|
||||||
|
if (key in positions) {
|
||||||
|
return positions[key];
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveScrollPos(key, pos) {
|
||||||
|
positions[key] = pos;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user