Scrolling stuff

pull/1102/head
Vincent 5 years ago
parent 82f1f2d1b1
commit 8a609efffe

@ -73,6 +73,10 @@ window.CONSTANTS = {
DEFAULT_MEDIA_FETCH_COUNT: 50,
DEFAULT_DOCUMENTS_FETCH_COUNT: 150,
DEFAULT_MESSAGE_FETCH_COUNT: 30,
// Pixels (scroll) from the top of the top of message container
// at which more messages should be loaded
MESSAGE_CONTAINER_BUFFER_OFFSET_PX: 300,
MESSAGE_FETCH_INTERVAL: 1,
};
window.versionInfo = {

@ -24,10 +24,7 @@ interface State {
conversationKey: string;
unreadCount: number;
messages: Array<any>;
// Scroll position as percentage of message-list
scrollPositionPc: number;
// Scroll position in pixels
scrollPositionPx: number;
isScrolledToBottom: boolean;
doneInitialScroll: boolean;
messageFetchTimestamp: number;
}
@ -51,12 +48,12 @@ export class SessionConversation extends React.Component<any, State> {
conversationKey,
unreadCount,
messages: [],
isScrolledToBottom: !unreadCount,
doneInitialScroll: false,
scrollPositionPc: 0,
scrollPositionPx: 0,
messageFetchTimestamp: 0,
};
this.handleScroll = this.handleScroll.bind(this);
this.scrollToUnread = this.scrollToUnread.bind(this);
this.scrollToBottom = this.scrollToBottom.bind(this);
@ -68,50 +65,41 @@ export class SessionConversation extends React.Component<any, State> {
}
public async componentWillMount() {
const { conversationKey } = this.state;
await this.getMessages(conversationKey);
await this.getMessages();
// Inside a setTimeout to simultate onready()
setTimeout(() => {
this.scrollToBottom(true);
this.scrollToUnread();
}, 0);
setTimeout(() => {
this.setState({
doneInitialScroll: true,
});
}, 100);
}
public componentDidUpdate(){
// Keep scrolled to bottom unless user scrolls up
if (this.state.isScrolledToBottom){
this.scrollToBottom();
}
}
public async componentWillReceiveProps() {
const { conversationKey } = this.state;
const timestamp = this.getTimestamp();
// If we have pulled messages in the last second, don't bother rescanning
// This avoids getting messages on every re-render.
if (timestamp > this.state.messageFetchTimestamp) {
await this.getMessages(conversationKey);
} else{
console.log(`[vince][info] Messages recieved in last second, stream`);
await this.getMessages();
}
}
render() {
console.log('[vince] SessionConversation was just rerendered!');
console.log(`[vince] These are SessionConversation props: `, this.props);
// const headerProps = this.props.getHeaderProps;
const { messages, conversationKey, doneInitialScroll } = this.state;
const loading = !doneInitialScroll || messages.length === 0;
console.log(`[vince] Loading: `, loading);
console.log(`[vince] My conversation key is: `, conversationKey);
// TMEPORARY SOLUTION TO GETTING CONVERSATION UNTIL
// SessionConversationStack is created
// Get conversation by Key (NOT cid)
const conversation = this.props.conversations.conversationLookup[conversationKey]
return (
@ -133,13 +121,12 @@ export class SessionConversation extends React.Component<any, State> {
</div>
)}
<div className="messages-container">
<div className="messages-container" onScroll={this.handleScroll}>
{this.renderMessages()}
<div ref={this.messagesEndRef} />
</div>
<SessionScrollButton display={true} onClick={this.scrollToUnread}/>
<SessionScrollButton display={true} onClick={this.scrollToBottom}/>
</div>
@ -153,6 +140,9 @@ export class SessionConversation extends React.Component<any, State> {
public renderMessages() {
const { messages } = this.state;
// IF MESSAGE IS THE TOP OF UNREAD, THEN INSERT AN UNREAD BANNER
return (
<>{
messages.map((message: any) => {
@ -228,34 +218,7 @@ export class SessionConversation extends React.Component<any, State> {
}
public async getMessages(conversationKey: string){
const msgCount = window.CONSTANTS.DEFAULT_MESSAGE_FETCH_COUNT + this.state.unreadCount;
const messageSet = await window.Signal.Data.getMessagesByConversation(
conversationKey,
{ msgCount, MessageCollection: window.Whisper.MessageCollection },
);
// Set first member of series here.
const messageModels = messageSet.models;
let messages = [];
let previousSender;
for (let i = 0; i < messageModels.length; i++){
// Handle firstMessageOfSeries for conditional avatar rendering
let firstMessageOfSeries = true;
if (i > 0 && previousSender === messageModels[i].authorPhoneNumber){
firstMessageOfSeries = false;
}
messages.push({...messageModels[i], firstMessageOfSeries});
previousSender = messageModels[i].authorPhoneNumber;
}
const messageFetchTimestamp = this.getTimestamp();
console.log(`[vince][messages] Messages Set`, messageModels);
this.setState({ messages, messageFetchTimestamp });
}
public renderMessage(messageProps: any, firstMessageOfSeries: boolean, quoteProps?: any) {
@ -321,7 +284,7 @@ export class SessionConversation extends React.Component<any, State> {
/>
);
}
public renderFriendRequest(friendRequestProps: any){
return (
<FriendRequest
@ -342,26 +305,100 @@ export class SessionConversation extends React.Component<any, State> {
);
}
public async getMessages(numMessages?: number, fetchInterval = window.CONSTANTS.MESSAGE_FETCH_INTERVAL){
const { conversationKey, messageFetchTimestamp } = this.state;
const timestamp = this.getTimestamp();
// If we have pulled messages in the last interval, don't bother rescanning
// This avoids getting messages on every re-render.
if (timestamp >= messageFetchTimestamp + fetchInterval) {
return;
}
const msgCount = numMessages || window.CONSTANTS.DEFAULT_MESSAGE_FETCH_COUNT + this.state.unreadCount;
const messageSet = await window.Signal.Data.getMessagesByConversation(
conversationKey,
{ limit: msgCount, MessageCollection: window.Whisper.MessageCollection },
);
// Set first member of series here.
const messageModels = messageSet.models;
let messages = [];
let previousSender;
for (let i = 0; i < messageModels.length; i++){
// Handle firstMessageOfSeries for conditional avatar rendering
let firstMessageOfSeries = true;
if (i > 0 && previousSender === messageModels[i].authorPhoneNumber){
firstMessageOfSeries = false;
}
messages.push({...messageModels[i], firstMessageOfSeries});
previousSender = messageModels[i].authorPhoneNumber;
}
const previousTopMessage = this.state.messages[0]?.id;
const newTopMessage = messages[0]?.id;
this.setState({ messages, messageFetchTimestamp });
console.log(`[vince][messages] Previous Top Message: `, previousTopMessage);
console.log(`[vince][messages] New Top Message: `, newTopMessage);
return { newTopMessage, previousTopMessage };
}
public getTimestamp() {
return Math.floor(Date.now() / 1000);
}
public handleScroll() {
// Update unread count
public async handleScroll() {
const { messages } = this.state;
const messageContainer = document.getElementsByClassName('messages-container')[0];
const isScrolledToBottom = messageContainer.scrollHeight - messageContainer.clientHeight <= messageContainer.scrollTop + 1;
// FIXME VINCE: Update unread count
// In models/conversations
// Update unread count by geting all divs of .session-message-wrapper
// which are currently in view.
// Get id of message at bottom of screen in full view. This is scroll position by messageID
// Pin scroll to bottom on new message, unless user has scrolled up
if (this.state.isScrolledToBottom !== isScrolledToBottom){
this.setState({ isScrolledToBottom });
}
// Fetch more messages when nearing the top of the message list
const shouldFetchMoreMessages = messageContainer.scrollTop <= window.CONSTANTS.MESSAGE_CONTAINER_BUFFER_OFFSET_PX;
if (shouldFetchMoreMessages){
const numMessages = this.state.messages.length + window.CONSTANTS.DEFAULT_MESSAGE_FETCH_COUNT;
// Prevent grabbing messags with scroll more frequently than once per 5s.
// const messageFetchInterval = 5;
// const previousTopMessage = (await this.getMessages(numMessages, messageFetchInterval))?.previousTopMessage;
// this.scrollToMessage(previousTopMessage);
}
}
public scrollToUnread() {
const topUnreadMessage = document.getElementById('70fd6220-5292-43d8-9e0d-f98bf4792f43');
topUnreadMessage?.scrollIntoView(false);
const { messages, unreadCount } = this.state;
const message = messages[(messages.length - 1) - unreadCount];
this.scrollToMessage(message.id);
}
public scrollToMessage(messageId: string) {
const topUnreadMessage = document.getElementById(messageId);
topUnreadMessage?.scrollIntoView();
}
public scrollToBottom(firstLoad = false) {
this.messagesEndRef.current?.scrollIntoView(
{ behavior: firstLoad ? 'auto' : 'smooth' }
);
// FIXME VINCE: Smooth scrolling that isn't slow@!
// this.messagesEndRef.current?.scrollIntoView(
// { behavior: firstLoad ? 'auto' : 'smooth' }
// );
const messageContainer = document.getElementsByClassName('messages-container')[0];
messageContainer.scrollTop = messageContainer.scrollHeight - messageContainer.clientHeight;
}
}

Loading…
Cancel
Save