use new PostCard component & use new listing method

This commit is contained in:
srgooglo 2022-06-03 06:25:40 +02:00
parent 85a0d206bb
commit b4b2094253

View File

@ -3,40 +3,53 @@ import * as antd from "antd"
import { User } from "models" import { User } from "models"
import { PostCard } from "components" import { PostCard } from "components"
import List from "rc-virtual-list"
import "./index.less" import "./index.less"
export default class PostsFeed extends React.Component { export default class PostsFeed extends React.Component {
state = { state = {
selfId: null, selfId: null,
initialLoading: true, initialLoading: true,
list: [], renderList: [],
animating: false,
} }
api = window.app.request api = window.app.request
listRef = React.createRef() listRef = React.createRef()
componentDidMount = async () => { wsEvents = {
const selfId = await User.selfUserId() "post.new": async (data) => {
this.insert(data)
},
"post.delete": async (data) => {
this.remove(data)
}
}
componentDidMount = async () => {
await this.loadSelfId()
// load ws events
Object.keys(this.wsEvents).forEach((event) => {
window.app.ws.listen(event, this.wsEvents[event])
})
await this.registerWSEvents()
await this.loadPosts() await this.loadPosts()
await this.setState({ await this.setState({ initialLoading: false })
selfId: selfId, }
initialLoading: false,
componentWillUnmount = async () => {
// unload ws events
Object.keys(this.wsEvents).forEach((event) => {
window.app.ws.unlisten(event, this.wsEvents[event])
}) })
} }
registerWSEvents = async () => { loadSelfId = async () => {
window.app.ws.listen(`post.new`, async (data) => { const selfId = await User.selfUserId()
this.insert(data)
}) this.setState({
window.app.ws.listen(`post.delete`, async (post_id) => { selfId: selfId,
this.remove(post_id)
}) })
} }
@ -54,45 +67,60 @@ export default class PostsFeed extends React.Component {
console.log(result) console.log(result)
if (result) { if (result) {
this.setState({ list: result }) this.setState({
renderList: result.map((item, index) => this.getPostRender(item, index))
})
} }
} }
onAppear = (...args) => { onLikePost = async (data) => {
console.log("Appear:", args) let result = await this.api.put.toogleLike({ post_id: data._id }).catch(() => {
this.setState({ animating: false }) antd.message.error("Failed to like post")
return false
})
return result
} }
lockForAnimation = () => { onDeletePost = async (data) => {
this.setState({ animating: true }) let result = await this.api.delete.post({ post_id: data._id }).catch(() => {
antd.message.error("Failed to delete post")
return false
})
return result
} }
insert = async (data) => { insert = async (data) => {
const updatedList = this.state.list // insert at the top, but without firing react lifecycle
updatedList.unshift(data)
await this.setState({ await this.setState({
list: updatedList, renderList: [this.getPostRender(data), ...this.state.renderList],
}) })
this.lockForAnimation()
} }
remove = async (post_id) => { remove = async (post_id) => {
const updatedList = this.state.list const updatedList = this.state.renderList
updatedList.splice(updatedList.findIndex((item) => item._id === post_id), 1) const postIndex = updatedList.findIndex((item) => item.props.data._id === post_id)
updatedList.splice(postIndex, 1)
await this.setState({ await this.setState({
list: updatedList, renderList: updatedList,
}) })
this.lockForAnimation()
} }
isSelf = (id) => { getPostRender = (item, index) => {
return this.state.selfId === id return <PostCard
key={index ?? this.state.renderList.findIndex((i) => i._id === item._id)}
data={item}
selfId={this.state.selfId}
events={{
onClickLike: this.onLikePost,
onClickDelete: this.onDeletePost,
}}
/>
} }
render() { render() {
@ -100,33 +128,15 @@ export default class PostsFeed extends React.Component {
return <antd.Skeleton active /> return <antd.Skeleton active />
} }
if (this.state.list.length === 0) { if (this.state.renderList.length === 0) {
return <div> return <div>
<antd.Empty /> <antd.Empty />
<h1>Whoa, nothing on here...</h1> <h1>Whoa, nothing on here...</h1>
</div> </div>
} }
return <div return <div className="postsFeed" ref={this.listRef}>
className="postsFeed" {this.state.renderList}
>
<List
ref={this.listRef}
data={this.state.list}
height="80vh"
itemHeight="100%"
className="content"
>
{(item, index) => {
return <PostCard
data={item}
motionAppear={this.state.animating && index === 0}
onAppear={this.onAppear}
self={this.isSelf(item.user_id)}
selfId={this.state.selfId}
/>
}}
</List>
</div> </div>
} }
} }