Maintain scroll positions when switching tabs

This commit is contained in:
Ken-Håvard Lieng 2017-05-03 22:56:06 +02:00
parent 45c61e7596
commit 52acec9d21
4 changed files with 81 additions and 29 deletions

File diff suppressed because one or more lines are too long

View File

@ -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;
}; };

View File

@ -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);
} }

View 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;
}