Some fixes for windowed render

This commit is contained in:
Scott Nonnenberg 2019-08-15 07:59:56 -07:00
parent e4d2e28ec4
commit 0b0214cbf9
4 changed files with 84 additions and 49 deletions

View file

@ -2252,12 +2252,18 @@
const existing = this.model.get('quotedMessageId'); const existing = this.model.get('quotedMessageId');
if (existing !== messageId) { if (existing !== messageId) {
const timestamp = messageId ? Date.now() : null;
this.model.set({ this.model.set({
quotedMessageId: messageId, quotedMessageId: messageId,
draftTimestamp: timestamp,
timestamp,
}); });
if (messageId) {
const timestamp = Date.now();
this.model.set({
draftTimestamp: timestamp,
timestamp,
});
}
await this.saveModel(); await this.saveModel();
} }

View file

@ -494,6 +494,10 @@ export class Timeline extends React.PureComponent<Props, State> {
renderTypingBubble, renderTypingBubble,
} = this.props; } = this.props;
const styleWithWidth = {
...style,
width: `${this.mostRecentWidth}px`,
};
const row = index; const row = index;
const oldestUnreadRow = this.getLastSeenIndicatorRow(); const oldestUnreadRow = this.getLastSeenIndicatorRow();
const typingBubbleRow = this.getTypingBubbleRow(); const typingBubbleRow = this.getTypingBubbleRow();
@ -501,13 +505,13 @@ export class Timeline extends React.PureComponent<Props, State> {
if (!haveOldest && row === 0) { if (!haveOldest && row === 0) {
rowContents = ( rowContents = (
<div data-row={row} style={style}> <div data-row={row} style={styleWithWidth}>
{renderLoadingRow(id)} {renderLoadingRow(id)}
</div> </div>
); );
} else if (oldestUnreadRow === row) { } else if (oldestUnreadRow === row) {
rowContents = ( rowContents = (
<div data-row={row} style={style}> <div data-row={row} style={styleWithWidth}>
{renderLastSeenIndicator(id)} {renderLastSeenIndicator(id)}
</div> </div>
); );
@ -516,7 +520,7 @@ export class Timeline extends React.PureComponent<Props, State> {
<div <div
data-row={row} data-row={row}
className="module-timeline__message-container" className="module-timeline__message-container"
style={style} style={styleWithWidth}
> >
{renderTypingBubble(id)} {renderTypingBubble(id)}
</div> </div>
@ -534,7 +538,7 @@ export class Timeline extends React.PureComponent<Props, State> {
id={messageId} id={messageId}
data-row={row} data-row={row}
className="module-timeline__message-container" className="module-timeline__message-container"
style={style} style={styleWithWidth}
> >
{renderItem(messageId, this.props)} {renderItem(messageId, this.props)}
</div> </div>
@ -715,6 +719,7 @@ export class Timeline extends React.PureComponent<Props, State> {
this.updateWithVisibleRows(forceFocus); this.updateWithVisibleRows(forceFocus);
}; };
// tslint:disable-next-line cyclomatic-complexity
public componentDidUpdate(prevProps: Props) { public componentDidUpdate(prevProps: Props) {
const { const {
id, id,
@ -763,35 +768,48 @@ export class Timeline extends React.PureComponent<Props, State> {
const oldFirstIndex = 0; const oldFirstIndex = 0;
const oldFirstId = prevProps.items[oldFirstIndex]; const oldFirstId = prevProps.items[oldFirstIndex];
const newIndex = items.findIndex(item => item === oldFirstId); const newFirstIndex = items.findIndex(item => item === oldFirstId);
if (newIndex < 0) { if (newFirstIndex < 0) {
this.resizeAll(); this.resizeAll();
return; return;
} }
const newRow = this.fromItemIndexToRow(newIndex); const newRow = this.fromItemIndexToRow(newFirstIndex);
const delta = newFirstIndex - oldFirstIndex;
if (delta > 0) {
// We're loading more new messages at the top; we want to stay at the top
this.resizeAll();
this.setState({ oneTimeScrollRow: newRow });
return;
}
}
// We continue on after our atTop check; because if we're not loading new messages
// we still have to check for all the other situations which might require a
// resize.
const oldLastIndex = prevProps.items.length - 1;
const oldLastId = prevProps.items[oldLastIndex];
const newLastIndex = items.findIndex(item => item === oldLastId);
if (newLastIndex < 0) {
this.resizeAll(); this.resizeAll();
this.setState({ oneTimeScrollRow: newRow });
} else {
const oldLastIndex = prevProps.items.length - 1;
const oldLastId = prevProps.items[oldLastIndex];
const newIndex = items.findIndex(item => item === oldLastId); return;
if (newIndex < 0) { }
this.resizeAll();
return; const indexDelta = newLastIndex - oldLastIndex;
}
const indexDelta = newIndex - oldLastIndex; // If we've just added to the end of the list, then the index of the last id's
// index won't have changed, and we can rely on List's detection that items is
// If we've just added to the end of the list, then the index of the last id's // different for the necessary re-render.
// index won't have changed, and we can rely on List's detection that items is if (indexDelta !== 0) {
// different for the necessary re-render. this.resizeAll();
if (indexDelta !== 0) { } else if (typingContact && prevProps.typingContact) {
this.resizeAll(); // The last row will be off, because it was previously the typing indicator
} this.resizeAll();
} }
} else if (messageHeightChanges) { } else if (messageHeightChanges) {
this.resizeAll(); this.resizeAll();

View file

@ -857,6 +857,30 @@ export function reducer(
totalUnread, totalUnread,
} = existingConversation.metrics; } = existingConversation.metrics;
if (messages.length < 1) {
return state;
}
const lookup = fromPairs(
existingConversation.messageIds.map(id => [id, messagesLookup[id]])
);
messages.forEach(message => {
lookup[message.id] = message;
});
const sorted = orderBy(values(lookup), ['received_at'], ['ASC']);
const messageIds = sorted.map(message => message.id);
const first = sorted[0];
const last = sorted[sorted.length - 1];
if (!newest) {
newest = pick(first, ['id', 'received_at']);
}
if (!oldest) {
oldest = pick(last, ['id', 'received_at']);
}
const existingTotal = existingConversation.messageIds.length; const existingTotal = existingConversation.messageIds.length;
if (isNewMessage && existingTotal > 0) { if (isNewMessage && existingTotal > 0) {
const lastMessageId = existingConversation.messageIds[existingTotal - 1]; const lastMessageId = existingConversation.messageIds[existingTotal - 1];
@ -869,27 +893,6 @@ export function reducer(
} }
} }
const newIds = messages.map(message => message.id);
const newChanges = intersection(newIds, existingConversation.messageIds);
const heightChangeMessageIds = uniq([
...newChanges,
...existingConversation.heightChangeMessageIds,
]);
const lookup = fromPairs(
existingConversation.messageIds.map(id => [id, messagesLookup[id]])
);
messages.forEach(message => {
lookup[message.id] = message;
});
const sorted = orderBy(values(lookup), ['received_at'], ['ASC']);
const messageIds = sorted.map(message => message.id);
const first = sorted[0];
const last = sorted.length > 0 ? sorted[sorted.length - 1] : null;
if (first && oldest && first.received_at < oldest.received_at) { if (first && oldest && first.received_at < oldest.received_at) {
oldest = pick(first, ['id', 'received_at']); oldest = pick(first, ['id', 'received_at']);
} }
@ -897,6 +900,7 @@ export function reducer(
newest = pick(last, ['id', 'received_at']); newest = pick(last, ['id', 'received_at']);
} }
const newIds = messages.map(message => message.id);
const newMessageIds = difference(newIds, existingConversation.messageIds); const newMessageIds = difference(newIds, existingConversation.messageIds);
const { isNearBottom } = existingConversation; const { isNearBottom } = existingConversation;
@ -924,6 +928,12 @@ export function reducer(
totalUnread = (totalUnread || 0) + newUnread; totalUnread = (totalUnread || 0) + newUnread;
} }
const changedIds = intersection(newIds, existingConversation.messageIds);
const heightChangeMessageIds = uniq([
...changedIds,
...existingConversation.heightChangeMessageIds,
]);
return { return {
...state, ...state,
messagesLookup: { messagesLookup: {

View file

@ -1,4 +1,5 @@
import memoizee from 'memoizee'; import memoizee from 'memoizee';
import { isNumber } from 'lodash';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { format } from '../../types/PhoneNumber'; import { format } from '../../types/PhoneNumber';
@ -388,7 +389,7 @@ export function _conversationMessagesSelector(
items, items,
messageHeightChanges, messageHeightChanges,
oldestUnreadIndex: oldestUnreadIndex:
oldestUnreadIndex && oldestUnreadIndex >= 0 isNumber(oldestUnreadIndex) && oldestUnreadIndex >= 0
? oldestUnreadIndex ? oldestUnreadIndex
: undefined, : undefined,
resetCounter, resetCounter,