chat-js: refactor unread message fetch

This commit is contained in:
Liam Fitzgerald 2020-04-30 12:40:26 +10:00
parent bdec28c541
commit 1167699ae6

View File

@ -23,6 +23,7 @@ function getNumPending(props) {
} }
const ACTIVITY_TIMEOUT = 60000; // a minute const ACTIVITY_TIMEOUT = 60000; // a minute
const DEFAULT_BACKLOG_SIZE = 300;
function scrollIsAtTop(container) { function scrollIsAtTop(container) {
if ((navigator.userAgent.includes("Safari") && if ((navigator.userAgent.includes("Safari") &&
@ -93,9 +94,6 @@ export class ChatScreen extends Component {
} }
componentDidMount() { componentDidMount() {
this.askForMessages();
this.scrollToBottom();
document.addEventListener("mousemove", this.handleActivity, false); document.addEventListener("mousemove", this.handleActivity, false);
document.addEventListener("mousedown", this.handleActivity, false); document.addEventListener("mousedown", this.handleActivity, false);
document.addEventListener("keypress", this.handleActivity, false); document.addEventListener("keypress", this.handleActivity, false);
@ -120,8 +118,9 @@ export class ChatScreen extends Component {
if(this.activityTimeout) { if(this.activityTimeout) {
clearTimeout(this.activityTimeout); clearTimeout(this.activityTimeout);
this.activityTimeout = setTimeout(this.setInactive, ACTIVITY_TIMEOUT);
} }
this.activityTimeout = setTimeout(this.setInactive, ACTIVITY_TIMEOUT);
} }
setInactive() { setInactive() {
@ -129,6 +128,39 @@ export class ChatScreen extends Component {
this.setState({ active: false, scrollLocked: true }); this.setState({ active: false, scrollLocked: true });
} }
receivedNewChat() {
const { props } = this;
this.hasAskedForMessages = false;
this.unreadMarker = null;
this.scrolledToMarker = false;
this.setState({ read: props.read });
const unread = props.length - props.read;
const unreadUnloaded = unread - props.envelopes.length;
if(unreadUnloaded + 20 > DEFAULT_BACKLOG_SIZE) {
this.askForMessages(unreadUnloaded + 20);
} else {
this.askForMessages(DEFAULT_BACKLOG_SIZE);
}
if(props.read === props.length){
this.scrolledToMarker = true;
this.setState(
{
scrollLocked: false,
},
() => {
this.scrollToBottom();
}
);
} else {
this.setState({ scrollLocked: true, numPages: Math.ceil(unread/100) });
}
}
componentDidUpdate(prevProps, prevState) { componentDidUpdate(prevProps, prevState) {
const { props, state } = this; const { props, state } = this;
@ -136,23 +168,7 @@ export class ChatScreen extends Component {
prevProps.match.params.station !== props.match.params.station || prevProps.match.params.station !== props.match.params.station ||
prevProps.match.params.ship !== props.match.params.ship prevProps.match.params.ship !== props.match.params.ship
) { ) {
this.hasAskedForMessages = false; this.receivedNewChat();
if (props.envelopes.length < 100) {
this.askForMessages();
}
this.unreadMarker = null;
this.scrolledToMarker = false;
this.setState(
{
scrollLocked: false,
read: props.read,
},
() => {
this.scrollToBottom();
}
);
} else if (props.chatInitialized && } else if (props.chatInitialized &&
!(props.station in props.inbox) && !(props.station in props.inbox) &&
(!!props.chatSynced && !(props.station in props.chatSynced))) { (!!props.chatSynced && !(props.station in props.chatSynced))) {
@ -163,15 +179,15 @@ export class ChatScreen extends Component {
) { ) {
this.hasAskedForMessages = false; this.hasAskedForMessages = false;
} else if(props.length !== prevProps.length && } else if(props.length !== prevProps.length &&
prevProps.length === prevProps.read && prevProps.length === prevState.read &&
state.active state.active
) { ) {
this.setState({ read: props.length }) this.setState({ read: props.length });
this.props.api.chat.read(this.props.station); this.props.api.chat.read(this.props.station);
} }
if(!prevProps.chatInitialized && props.chatInitialized) { if(!prevProps.chatInitialized && props.chatInitialized) {
this.setState({ read: props.read }) this.receivedNewChat();
} }
if ( if (
@ -189,16 +205,9 @@ export class ChatScreen extends Component {
} }
} }
askForMessages() { askForMessages(size) {
const { props, state } = this; const { props, state } = this;
if (props.envelopes.length === 0) {
setTimeout(() => {
this.askForMessages();
}, 500);
return;
}
if ( if (
props.envelopes.length >= props.length || props.envelopes.length >= props.length ||
this.hasAskedForMessages || this.hasAskedForMessages ||
@ -210,16 +219,8 @@ export class ChatScreen extends Component {
let start = let start =
props.length - props.envelopes[props.envelopes.length - 1].number; props.length - props.envelopes[props.envelopes.length - 1].number;
if (start > 0) { if (start > 0) {
const unread = props.length - props.read; const end = start + size < props.length ? start + size : props.length;
const unloadedUnread = unread - props.envelopes.length;
const willLoadUnread = unloadedUnread > 280;
const offset = willLoadUnread ? unloadedUnread + 20 : 300;
const end = start + offset < props.length ? start + offset : props.length;
this.hasAskedForMessages = true; this.hasAskedForMessages = true;
if(willLoadUnread) {
// ensure unread marker is visible
this.setState({ numPages: Math.ceil(unread / 100) });
}
props.subscription.fetchMessages(start + 1, end, props.station); props.subscription.fetchMessages(start + 1, end, props.station);
} }
} }
@ -260,7 +261,7 @@ export class ChatScreen extends Component {
scrollLocked: true scrollLocked: true
}, },
() => { () => {
this.askForMessages(); this.askForMessages(DEFAULT_BACKLOG_SIZE);
} }
); );
} else if (scrollIsAtBottom(e.target)) { } else if (scrollIsAtBottom(e.target)) {
@ -276,7 +277,8 @@ export class ChatScreen extends Component {
if(ref && !this.scrolledToMarker) { if(ref && !this.scrolledToMarker) {
this.setState({ scrollLocked: true }, () => { this.setState({ scrollLocked: true }, () => {
ref.scrollIntoView({ block: 'center' }); ref.scrollIntoView({ block: 'center' });
if(scrollIsAtBottom(ref.offsetParent)) { if(ref.offsetParent &&
scrollIsAtBottom(ref.offsetParent)) {
this.dismissUnread(); this.dismissUnread();
this.setState({ this.setState({
numPages: 1, numPages: 1,