chat: fixed indentation

logging for scrollback
This commit is contained in:
Logan Allen 2020-03-24 18:49:04 -04:00
parent 16b4e2e8e4
commit 8d64d9d253
5 changed files with 299 additions and 287 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -14,288 +14,297 @@ import { deSig } from '/lib/util';
export class ChatScreen extends Component { export class ChatScreen extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
numPages: 1, numPages: 1,
scrollLocked: false scrollLocked: false
}; };
this.hasAskedForMessages = false; this.hasAskedForMessages = false;
this.onScroll = this.onScroll.bind(this); this.onScroll = this.onScroll.bind(this);
this.updateReadInterval = setInterval( this.updateReadInterval = setInterval(
this.updateReadNumber.bind(this), this.updateReadNumber.bind(this),
1000 1000
); );
} }
componentDidMount() { componentDidMount() {
this.updateReadNumber(); this.updateReadNumber();
} }
componentWillUnmount() { componentWillUnmount() {
if (this.updateReadInterval) { if (this.updateReadInterval) {
clearInterval(this.updateReadInterval); clearInterval(this.updateReadInterval);
this.updateReadInterval = null; this.updateReadInterval = null;
} }
} }
componentDidUpdate(prevProps, prevState) { componentDidUpdate(prevProps, prevState) {
const { props, state } = this; const { props, state } = this;
if ( if (
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.hasAskedForMessages = false;
clearInterval(this.updateReadInterval); clearInterval(this.updateReadInterval);
this.setState( this.setState(
{ scrollLocked: false }, { scrollLocked: false },
() => { () => {
this.scrollToBottom(); this.scrollToBottom();
this.updateReadInterval = setInterval( this.updateReadInterval = setInterval(
this.updateReadNumber.bind(this), this.updateReadNumber.bind(this),
1000 1000
); );
this.updateReadNumber(); this.updateReadNumber();
} }
); );
} else if (props.chatInitialized && !(props.station in props.inbox)) { } else if (props.chatInitialized && !(props.station in props.inbox)) {
props.history.push("/~chat"); props.history.push("/~chat");
} else if ( } else if (
props.envelopes.length - prevProps.envelopes.length >= props.envelopes.length - prevProps.envelopes.length >=
200 200
) { ) {
this.hasAskedForMessages = false; this.hasAskedForMessages = false;
} }
} }
updateReadNumber() { updateReadNumber() {
const { props, state } = this; const { props, state } = this;
if (props.read < props.length) { if (props.read < props.length) {
props.api.chat.read(props.station); props.api.chat.read(props.station);
} }
} }
askForMessages() { askForMessages() {
const { props, state } = this; const { props, state } = this;
if ( console.log('askForMessages');
state.numPages * 100 < props.length - 400 || if (
this.hasAskedForMessages state.numPages * 100 < props.length - 400 ||
) { this.hasAskedForMessages
return; ) {
} console.log('condition 1: ', state.numPages * 100 < props.length - 400);
console.log('condition 2: ', this.hasAskedForMessages);
return;
}
if (props.length > 0) { console.log('length: ', props.length);
let end = props.envelopes[0].number; if (props.length > 0) {
if (end > 0) { let end = props.envelopes[0].number;
let start = end - 400 > 0 ? end - 400 : 0; console.log('end: ', end);
if (end > 0) {
let start = end - 400 > 0 ? end - 400 : 0;
if (start === 0 && end === 1) { console.log('start: ', start);
return; if (start === 0 && end === 1) {
} return;
}
this.hasAskedForMessages = true; this.hasAskedForMessages = true;
props.subscription.fetchMessages(start, end - 1, props.station); props.subscription.fetchMessages(start, end - 1, props.station);
} }
} }
} }
scrollToBottom() { scrollToBottom() {
if (!this.state.scrollLocked && this.scrollElement) { if (!this.state.scrollLocked && this.scrollElement) {
this.scrollElement.scrollIntoView({ behavior: "smooth" }); this.scrollElement.scrollIntoView({ behavior: "smooth" });
} }
} }
onScroll(e) { onScroll(e) {
if ( if (
navigator.userAgent.includes("Safari") && navigator.userAgent.includes("Safari") &&
navigator.userAgent.includes("Chrome") navigator.userAgent.includes("Chrome")
) { ) {
// Google Chrome // Google Chrome
if (e.target.scrollTop === 0) { console.log('scrollTop: ', e.target.scrollTop);
this.setState( if (e.target.scrollTop === 0) {
{ console.log('google chrome');
numPages: this.state.numPages + 1, this.setState(
scrollLocked: true {
}, numPages: this.state.numPages + 1,
() => { scrollLocked: true
this.askForMessages(); },
} () => {
); this.askForMessages();
} else if ( }
e.target.scrollHeight - Math.round(e.target.scrollTop) === );
e.target.clientHeight } else if (
) { e.target.scrollHeight - Math.round(e.target.scrollTop) ===
this.setState({ e.target.clientHeight
numPages: 1, ) {
scrollLocked: false this.setState({
}); numPages: 1,
} scrollLocked: false
} else if (navigator.userAgent.includes("Safari")) { });
// Safari }
if (e.target.scrollTop === 0) { } else if (navigator.userAgent.includes("Safari")) {
this.setState({ // Safari
numPages: 1, console.log('safari');
scrollLocked: false if (e.target.scrollTop === 0) {
}); this.setState({
} else if ( numPages: 1,
e.target.scrollHeight + Math.round(e.target.scrollTop) <= scrollLocked: false
e.target.clientHeight + 10 });
) { } else if (
this.setState( e.target.scrollHeight + Math.round(e.target.scrollTop) <=
{ e.target.clientHeight + 10
numPages: this.state.numPages + 1, ) {
scrollLocked: true this.setState(
}, {
() => { numPages: this.state.numPages + 1,
this.askForMessages(); scrollLocked: true
} },
); () => {
} this.askForMessages();
} else { }
console.log("Your browser is not supported."); );
} }
} } else {
console.log("Your browser is not supported.");
}
}
render() { render() {
const { props, state } = this; const { props, state } = this;
let messages = props.envelopes.slice(0); let messages = props.envelopes.slice(0);
let lastMsgNum = messages.length > 0 ? messages.length : 0; let lastMsgNum = messages.length > 0 ? messages.length : 0;
if (messages.length > 100 * state.numPages) { if (messages.length > 100 * state.numPages) {
messages = messages.slice( messages = messages.slice(
messages.length - 100 * state.numPages, messages.length - 100 * state.numPages,
messages.length messages.length
); );
} }
let pendingMessages = props.pendingMessages.has(props.station) let pendingMessages = props.pendingMessages.has(props.station)
? props.pendingMessages.get(props.station) ? props.pendingMessages.get(props.station)
: []; : [];
pendingMessages.map(function(value) { pendingMessages.map(function(value) {
return (value.pending = true); return (value.pending = true);
}); });
let reversedMessages = messages.concat(pendingMessages); let reversedMessages = messages.concat(pendingMessages);
reversedMessages = reversedMessages.reverse(); reversedMessages = reversedMessages.reverse();
reversedMessages = reversedMessages.map((msg, i) => { reversedMessages = reversedMessages.map((msg, i) => {
// Render sigil if previous message is not by the same sender // Render sigil if previous message is not by the same sender
let aut = ["author"]; let aut = ["author"];
let renderSigil = let renderSigil =
_.get(reversedMessages[i + 1], aut) !== _.get(reversedMessages[i + 1], aut) !==
_.get(msg, aut, msg.author); _.get(msg, aut, msg.author);
let paddingTop = renderSigil; let paddingTop = renderSigil;
let paddingBot = let paddingBot =
_.get(reversedMessages[i - 1], aut) !== _.get(reversedMessages[i - 1], aut) !==
_.get(msg, aut, msg.author); _.get(msg, aut, msg.author);
return ( return (
<Message <Message
key={msg.uid} key={msg.uid}
msg={msg} msg={msg}
contacts={props.contacts} contacts={props.contacts}
renderSigil={renderSigil} renderSigil={renderSigil}
paddingTop={paddingTop} paddingTop={paddingTop}
paddingBot={paddingBot} paddingBot={paddingBot}
pending={!!msg.pending} pending={!!msg.pending}
/> />
); );
}); });
let group = Array.from(props.group.values()); let group = Array.from(props.group.values());
const isinPopout = props.popout ? "popout/" : ""; const isinPopout = props.popout ? "popout/" : "";
let ownerContact = (window.ship in props.contacts) let ownerContact = (window.ship in props.contacts)
? props.contacts[window.ship] : false; ? props.contacts[window.ship] : false;
let title = props.station.substr(1); let title = props.station.substr(1);
if (props.association && "metadata" in props.association) { if (props.association && "metadata" in props.association) {
title = title =
props.association.metadata.title !== "" props.association.metadata.title !== ""
? props.association.metadata.title ? props.association.metadata.title
: props.station.substr(1); : props.station.substr(1);
} }
return ( return (
<div <div
key={props.station} key={props.station}
className="h-100 w-100 overflow-hidden flex flex-column"> className="h-100 w-100 overflow-hidden flex flex-column">
<div <div
className="w-100 dn-m dn-l dn-xl inter pt4 pb6 pl3 f8" className="w-100 dn-m dn-l dn-xl inter pt4 pb6 pl3 f8"
style={{ height: "1rem" }}> style={{ height: "1rem" }}>
<Link to="/~chat/">{"⟵ All Chats"}</Link> <Link to="/~chat/">{"⟵ All Chats"}</Link>
</div> </div>
<div <div
className={"pl4 pt2 bb b--gray4 b--gray1-d bg-gray0-d flex relative" + className={"pl4 pt2 bb b--gray4 b--gray1-d bg-gray0-d flex relative" +
"overflow-x-scroll overflow-x-auto-l overflow-x-auto-xl flex-shrink-0"} "overflow-x-scroll overflow-x-auto-l overflow-x-auto-xl flex-shrink-0"}
style={{ height: 48 }}> style={{ height: 48 }}>
<SidebarSwitcher <SidebarSwitcher
sidebarShown={this.props.sidebarShown} sidebarShown={this.props.sidebarShown}
popout={this.props.popout} popout={this.props.popout}
/> />
<Link to={`/~chat/` + isinPopout + `room` + props.station} <Link to={`/~chat/` + isinPopout + `room` + props.station}
className="pt2 white-d"> className="pt2 white-d">
<h2 <h2
className={"dib f9 fw4 lh-solid v-top " + className={"dib f9 fw4 lh-solid v-top " +
((title === props.station.substr(1)) ? "mono" : "")} ((title === props.station.substr(1)) ? "mono" : "")}
style={{ width: "max-content" }}> style={{ width: "max-content" }}>
{title} {title}
</h2> </h2>
</Link> </Link>
<ChatTabBar <ChatTabBar
{...props} {...props}
station={props.station} station={props.station}
numPeers={group.length} numPeers={group.length}
isOwner={deSig(props.match.params.ship) === window.ship} isOwner={deSig(props.match.params.ship) === window.ship}
popout={this.props.popout} popout={this.props.popout}
api={props.api} api={props.api}
/> />
</div> </div>
<div <div
className="overflow-y-scroll bg-white bg-gray0-d pt3 pb2 flex flex-column-reverse" className="overflow-y-scroll bg-white bg-gray0-d pt3 pb2 flex flex-column-reverse"
style={{ height: "100%", resize: "vertical" }} style={{ height: "100%", resize: "vertical" }}
onScroll={this.onScroll}> onScroll={this.onScroll}>
<div <div
ref={el => { ref={el => {
this.scrollElement = el; this.scrollElement = el;
}}></div> }}></div>
{ ( { (
!(props.station in props.chatSynced) && !(props.station in props.chatSynced) &&
(reversedMessages.length > 0) (reversedMessages.length > 0)
) ? ( ) ? (
<ResubscribeElement <ResubscribeElement
api={props.api} api={props.api}
host={props.match.params.ship} host={props.match.params.ship}
station={props.station} /> station={props.station} />
) : (<div/>) ) : (<div/>)
} }
{reversedMessages} {reversedMessages}
</div> </div>
<ChatInput <ChatInput
api={props.api} api={props.api}
numMsgs={lastMsgNum} numMsgs={lastMsgNum}
station={props.station} station={props.station}
owner={deSig(props.match.params.ship)} owner={deSig(props.match.params.ship)}
ownerContact={ownerContact} ownerContact={ownerContact}
permissions={props.permissions} permissions={props.permissions}
envelopes={props.envelopes} envelopes={props.envelopes}
contacts={props.contacts} contacts={props.contacts}
placeholder="Message..." placeholder="Message..."
/> />
</div> </div>
); );
} }
} }

View File

@ -125,7 +125,7 @@ export class ChatInput extends Component {
this.textareaInput = _.debounce(this.textareaInput.bind(this), 16); this.textareaInput = _.debounce(this.textareaInput.bind(this), 16);
// perf testing: // perf testing:
/*let closure = () => { let closure = () => {
let x = 0; let x = 0;
for (var i = 0; i < 30; i++) { for (var i = 0; i < 30; i++) {
x++; x++;
@ -140,7 +140,7 @@ export class ChatInput extends Component {
} }
setTimeout(closure, 1000); setTimeout(closure, 1000);
}; };
this.closure = closure.bind(this);*/ this.closure = closure.bind(this);
moment.updateLocale('en', { moment.updateLocale('en', {
relativeTime : { relativeTime : {
@ -400,6 +400,7 @@ export class ChatInput extends Component {
} }
}) })
if (message.length > 0) { if (message.length > 0) {
message = message.join(" "); message = message.join(" ");
message = this.getLetterType(message); message = this.getLetterType(message);
@ -412,7 +413,8 @@ export class ChatInput extends Component {
message = []; message = [];
} }
// perf: setTimeout(this.closure, 2000); // perf:
setTimeout(this.closure, 2000);
this.setState({ this.setState({
message: '', message: '',

View File

@ -69,6 +69,7 @@ export class Subscription {
fetch(`/~chat/paginate/${start}/${end}${path}`) fetch(`/~chat/paginate/${start}/${end}${path}`)
.then((response) => response.json()) .then((response) => response.json())
.then((json) => { .then((json) => {
console.log(json);
store.handleEvent({ store.handleEvent({
data: json data: json
}); });