Fix wrong height calculation of react-list
react-list doesn't know the size of an item that just got rendered (it only later caches this size), therefore it can't correctly calculate the height of the list.
This commit is contained in:
parent
881e66ea29
commit
74d7c7cc9e
|
|
@ -0,0 +1,40 @@
|
|||
import ReactList from 'react-list';
|
||||
|
||||
// See also https://github.com/coderiety/react-list/blob/master/react-list.es6
|
||||
class FixedReactList extends ReactList {
|
||||
// deleting a messages or adding a message (per shift) requires invalidating the cache, react-list sucks as it does
|
||||
// not provide such functionality, therefore we need to hack it inside there :(
|
||||
ignoreNextCacheUpdate = false;
|
||||
|
||||
cacheSizes() {
|
||||
if (this.ignoreNextCacheUpdate) {
|
||||
this.ignoreNextCacheUpdate = false;
|
||||
return;
|
||||
}
|
||||
super.cacheSizes();
|
||||
}
|
||||
|
||||
clearCacheFromIndex(startIndex) {
|
||||
this.ignoreNextCacheUpdate = true;
|
||||
|
||||
if (startIndex === 0) {
|
||||
this.cache = {};
|
||||
} else {
|
||||
Object.keys(this.cache).filter((index) => index >= startIndex).forEach((index) => {
|
||||
delete this.cache[index];
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
componentDidUpdate() {
|
||||
const hasCacheForLastRenderedItem = Object.keys(this.cache).length && this.cache[this.getVisibleRange()[1]];
|
||||
super.componentDidUpdate();
|
||||
if (!hasCacheForLastRenderedItem) {
|
||||
// when there is no cache for the last rendered item, then its a new item, react-list doesn't know it size
|
||||
// and cant correctly calculate the height of the list, we force a rerender where react-list knows the size.
|
||||
this.forceUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default FixedReactList;
|
||||
|
|
@ -6,7 +6,7 @@ import MessageStore from '../stores/MessageStore';
|
|||
import AppStore from '../stores/AppStore';
|
||||
import * as MessageAction from '../actions/MessageAction';
|
||||
import DefaultPage from '../component/DefaultPage';
|
||||
import ReactList from 'react-list';
|
||||
import ReactList from '../component/FixedReactList';
|
||||
import {CircularProgress} from 'material-ui/Progress';
|
||||
|
||||
class Messages extends Component {
|
||||
|
|
@ -29,6 +29,12 @@ class Messages extends Component {
|
|||
|
||||
updateAllWithProps = (props) => {
|
||||
const appId = Messages.appId(props);
|
||||
|
||||
const reset = MessageStore.shouldReset(appId);
|
||||
if (reset !== false && this.list) {
|
||||
this.list.clearCacheFromIndex(reset);
|
||||
}
|
||||
|
||||
this.setState({...MessageStore.get(appId), appId, name: AppStore.getName(appId)});
|
||||
if (!MessageStore.exists(appId)) {
|
||||
MessageStore.loadNext(appId);
|
||||
|
|
|
|||
|
|
@ -7,10 +7,21 @@ class MessageStore extends EventEmitter {
|
|||
constructor() {
|
||||
super();
|
||||
this.appToMessages = {};
|
||||
this.reset = false;
|
||||
this.resetOnAll = false;
|
||||
this.loading = false;
|
||||
AppStore.on('change', this.updateApps);
|
||||
}
|
||||
|
||||
shouldReset(appId) {
|
||||
let reset = appId === -1 ? this.resetOnAll : this.reset;
|
||||
if (reset !== false) {
|
||||
this.reset = false;
|
||||
this.resetOnAll = false;
|
||||
}
|
||||
return reset;
|
||||
}
|
||||
|
||||
loadNext(id) {
|
||||
if (this.loading || !this.get(id).hasMore) {
|
||||
return;
|
||||
|
|
@ -32,8 +43,8 @@ class MessageStore extends EventEmitter {
|
|||
}
|
||||
|
||||
handle(data) {
|
||||
const {payload} = data;
|
||||
if (data.type === 'UPDATE_MESSAGES') {
|
||||
const payload = data.payload;
|
||||
if (this.exists(payload.id)) {
|
||||
payload.messages = this.get(payload.id).messages.concat(payload.messages);
|
||||
}
|
||||
|
|
@ -42,34 +53,42 @@ class MessageStore extends EventEmitter {
|
|||
this.loading = false;
|
||||
this.emit('change');
|
||||
} else if (data.type === 'ONE_MESSAGE') {
|
||||
const {payload} = data;
|
||||
this.createIfNotExist(payload.appid);
|
||||
this.createIfNotExist(-1);
|
||||
this.appToMessages[payload.appid].messages.unshift(payload);
|
||||
this.appToMessages[-1].messages.unshift(payload);
|
||||
this.reset = 0;
|
||||
this.resetOnAll = 0;
|
||||
this.updateApps();
|
||||
this.emit('change');
|
||||
} else if (data.type === 'DELETE_MESSAGE') {
|
||||
Object.keys(this.appToMessages).forEach((key) => {
|
||||
const appMessages = this.appToMessages[key];
|
||||
const index = appMessages.messages.indexOf(data.payload);
|
||||
if (index !== -1) {
|
||||
appMessages.messages.splice(index, 1);
|
||||
}
|
||||
});
|
||||
this.resetOnAll = this.removeFromList(this.appToMessages[-1], payload);
|
||||
this.reset = this.removeFromList(this.appToMessages[payload.appid], payload);
|
||||
this.emit('change');
|
||||
} else if (data.type === 'DELETE_MESSAGES') {
|
||||
const id = data.payload;
|
||||
const id = payload;
|
||||
if (id === -1) {
|
||||
this.appToMessages = {};
|
||||
} else {
|
||||
delete this.appToMessages[-1];
|
||||
delete this.appToMessages[id];
|
||||
}
|
||||
this.reset = 0;
|
||||
this.emit('change');
|
||||
}
|
||||
}
|
||||
|
||||
removeFromList(messages, messageToDelete) {
|
||||
if (messages) {
|
||||
const index = messages.messages.findIndex((message) => message.id === messageToDelete.id);
|
||||
if (index !== -1) {
|
||||
messages.messages.splice(index, 1);
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
updateApps = () => {
|
||||
const appToUrl = {};
|
||||
AppStore.get().forEach((app) => appToUrl[app.id] = app.image);
|
||||
|
|
|
|||
Loading…
Reference in New Issue