mirror of
https://github.com/koodiklinikka/koodiklinikka.fi.git
synced 2026-02-11 04:51:26 +00:00
* Remove render blocking stripe JS that seems unnecessary * Use native lazy loading of images - Truly a progressive enhancement, only affects browsers that support it - Causes a warning: [Intervention] An <img> element was lazyloaded with loading=lazy, but had no dimensions specified. Specifying dimensions improves performance. See https://crbug.com/954323, which can not be easily fixed * Render content first, hydrate after that
82 lines
2.2 KiB
TypeScript
82 lines
2.2 KiB
TypeScript
import flatMap from "lodash/flatMap";
|
|
import sortBy from "lodash/sortBy";
|
|
import React from "react";
|
|
import request from "axios";
|
|
import api from "./api";
|
|
import transformers from "./feed-transformers";
|
|
import ReactTimeAgo from "react-time-ago";
|
|
import JavascriptTimeAgo from "javascript-time-ago";
|
|
import timeagoFi from "javascript-time-ago/locale/fi";
|
|
|
|
// TODO: Add type definitions for javascript-time-ago
|
|
(JavascriptTimeAgo as any).locale(timeagoFi);
|
|
|
|
export default class Feed extends React.Component {
|
|
state = {
|
|
messages: [],
|
|
};
|
|
|
|
componentDidMount() {
|
|
this.updateFeed();
|
|
}
|
|
|
|
async updateFeed() {
|
|
const res = await request.get(api("feeds"));
|
|
const messages = sortBy(
|
|
flatMap(res.data, (messages, type) => transformers[type](messages)),
|
|
"timestamp"
|
|
);
|
|
messages.reverse(); // In-place
|
|
this.setState({
|
|
messages: messages.slice(0, 40),
|
|
});
|
|
}
|
|
|
|
render() {
|
|
const messages = this.state.messages.map((message, i) => {
|
|
let image = <img src={message.image} alt="" loading="lazy" />;
|
|
|
|
if (message.imageLink) {
|
|
image = (
|
|
<a
|
|
target="_blank"
|
|
href={message.imageLink}
|
|
rel="noopener noreferrer"
|
|
tabIndex={-1}
|
|
>
|
|
{image}
|
|
</a>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="message" key={i}>
|
|
<div className="message__image" aria-hidden="true">
|
|
{image}
|
|
</div>
|
|
<div className="message__content">
|
|
<div className="message__user">
|
|
<a href={message.userLink}>{message.user}</a>
|
|
</div>
|
|
<div
|
|
className="message__body"
|
|
dangerouslySetInnerHTML={{ __html: message.body }}
|
|
/>
|
|
<div className="message__icon">
|
|
<i className={`fa fa-${message.type}`} aria-hidden="true" />
|
|
</div>
|
|
<div className="message__details">
|
|
<span className="message__timestamp">
|
|
<ReactTimeAgo date={message.timestamp} locale="fi" />
|
|
</span>
|
|
<span className="message__meta">{message.meta}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
});
|
|
|
|
return <div className="feed">{messages}</div>;
|
|
}
|
|
}
|