Optimize Buffer

Convert to classes and implement shouldComponentUpdate to avoid
re-rendering elements unnecessarily.
This commit is contained in:
Simon Ser 2020-07-09 23:33:34 +02:00
parent 0a825547a7
commit 8809fdcd6a
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48

View File

@ -25,79 +25,94 @@ function Nick(props) {
`; `;
} }
function LogLine(props) { function Timestamp({ date }) {
var msg = props.message; if (!date) {
return html`<spam class="timestamp">--:--:--</span>`;
function createNick(nick) {
return html`
<${Nick} nick=${nick} onClick=${() => props.onNickClick(nick)}/>
`;
} }
var date = new Date(msg.tags["time"]); var hh = date.getHours().toString().padStart(2, "0");
var timestamp = date.toLocaleTimeString(undefined, { var mm = date.getMinutes().toString().padStart(2, "0");
timeStyle: "short", var ss = date.getSeconds().toString().padStart(2, "0");
hour12: false, var timestamp = `${hh}:${mm}:${ss}`;
}); return html`
var timestampLink = html`
<a href="#" class="timestamp" onClick=${(event) => event.preventDefault()}>${timestamp}</a> <a href="#" class="timestamp" onClick=${(event) => event.preventDefault()}>${timestamp}</a>
`; `;
}
var lineClass = ""; class LogLine extends Component {
var content; shouldComponentUpdate(nextProps) {
switch (msg.command) { return this.props.message != nextProps.message;
case "NOTICE":
case "PRIVMSG":
var text = msg.params[1];
var actionPrefix = "\x01ACTION ";
if (text.startsWith(actionPrefix) && text.endsWith("\x01")) {
var action = text.slice(actionPrefix.length, -1);
lineClass = "me-tell";
content = html`* ${createNick(msg.prefix.name)} ${linkify(action)}`;
} else {
lineClass = "talk";
content = html`${"<"}${createNick(msg.prefix.name)}${">"} ${linkify(text)}`;
}
break;
case "JOIN":
content = html`
${createNick(msg.prefix.name)} has joined
`;
break;
case "PART":
content = html`
${createNick(msg.prefix.name)} has left
`;
break;
case "QUIT":
content = html`
${createNick(msg.prefix.name)} has quit
`;
break;
case "NICK":
var newNick = msg.params[0];
content = html`
${createNick(msg.prefix.name)} is now known as ${createNick(newNick)}
`;
break;
case "TOPIC":
var topic = msg.params[1];
content = html`
${createNick(msg.prefix.name)} changed the topic to: ${linkify(topic)}
`;
break;
default:
if (irc.isError(msg.command) && msg.command != irc.ERR_NOMOTD) {
lineClass = "error";
}
content = html`${msg.command} ${msg.params.join(" ")}`;
} }
return html` render() {
<div class="logline ${lineClass}">${timestampLink} ${content}</div> var msg = this.props.message;
`;
function createNick(nick) {
return html`
<${Nick} nick=${nick} onClick=${() => props.onNickClick(nick)}/>
`;
}
var lineClass = "";
var content;
switch (msg.command) {
case "NOTICE":
case "PRIVMSG":
var text = msg.params[1];
var actionPrefix = "\x01ACTION ";
if (text.startsWith(actionPrefix) && text.endsWith("\x01")) {
var action = text.slice(actionPrefix.length, -1);
lineClass = "me-tell";
content = html`* ${createNick(msg.prefix.name)} ${linkify(action)}`;
} else {
lineClass = "talk";
content = html`${"<"}${createNick(msg.prefix.name)}${">"} ${linkify(text)}`;
}
break;
case "JOIN":
content = html`
${createNick(msg.prefix.name)} has joined
`;
break;
case "PART":
content = html`
${createNick(msg.prefix.name)} has left
`;
break;
case "QUIT":
content = html`
${createNick(msg.prefix.name)} has quit
`;
break;
case "NICK":
var newNick = msg.params[0];
content = html`
${createNick(msg.prefix.name)} is now known as ${createNick(newNick)}
`;
break;
case "TOPIC":
var topic = msg.params[1];
content = html`
${createNick(msg.prefix.name)} changed the topic to: ${linkify(topic)}
`;
break;
default:
if (irc.isError(msg.command) && msg.command != irc.ERR_NOMOTD) {
lineClass = "error";
}
content = html`${msg.command} ${msg.params.join(" ")}`;
}
return html`
<div class="logline ${lineClass}">
<${Timestamp} date=${new Date(msg.tags.time)}/>
${" "}
${content}
</div>
`;
}
} }
class NotificationNagger extends Component { class NotificationNagger extends Component {
@ -130,7 +145,7 @@ class NotificationNagger extends Component {
return html` return html`
<div class="logline"> <div class="logline">
<span class="timestamp">--:--:--</span> <${Timestamp}/>
${" "} ${" "}
<a href="#" onClick=${this.handleClick}>Turn on desktop notifications</a> to get notified about new messages <a href="#" onClick=${this.handleClick}>Turn on desktop notifications</a> to get notified about new messages
</div> </div>
@ -138,22 +153,28 @@ class NotificationNagger extends Component {
} }
} }
export default function Buffer(props) { export default class Buffer extends Component {
if (!props.buffer) { shouldComponentUpdate(nextProps) {
return null; return this.props.buffer != nextProps.buffer;
} }
var notifNagger = null; render() {
if (props.buffer.type == BufferType.SERVER) { if (!this.props.buffer) {
notifNagger = html`<${NotificationNagger}/>`; return null;
} }
return html` var notifNagger = null;
<div class="logline-list"> if (this.props.buffer.type == BufferType.SERVER) {
${notifNagger} notifNagger = html`<${NotificationNagger}/>`;
${props.buffer.messages.map((msg) => html` }
<${LogLine} key=${msg.key} message=${msg} onNickClick=${props.onNickClick}/>
`)} return html`
</div> <div class="logline-list">
`; ${notifNagger}
${this.props.buffer.messages.map((msg) => html`
<${LogLine} key=${msg.key} message=${msg} onNickClick=${this.props.onNickClick}/>
`)}
</div>
`;
}
} }