import React from "react" import * as antd from "antd" import { Icons } from "components/Icons" import { PostCard, LoadMore } from "components" import { ViewportList } from "react-viewport-list" import PostModel from "models/post" import "./index.less" const LoadingComponent = () => { // FIXME: Im not sure why but, using will cause a memory leak of DOM Nodes when using IntersectionObserver //return return

Loading more ...

} const NoResultComponent = () => { return } export class PostsListsComponent extends React.Component { state = { openPost: null, loading: false, initialLoading: true, realtimeUpdates: true, hasMore: true, list: this.props.list ?? [], } viewRef = this.props.innerRef timelineWsEvents = { "post.new": (data) => { console.log("New post => ", data) if (!this.state.realtimeUpdates) { return } this.setState({ list: [data, ...this.state.list], }) }, "post.delete": (id) => { console.log("Deleted post => ", id) this.setState({ list: this.state.list.filter((post) => { return post._id !== id }), }) } } handleLoad = async (fn) => { this.setState({ loading: true, }) let payload = { trim: this.state.list.length, } if (this.props.loadFromModelProps) { payload = { ...payload, ...this.props.loadFromModelProps, } } const result = await fn(payload).catch((err) => { console.error(err) app.message.error("Failed to load more posts") return null }) if (result) { if (result.length === 0) { return this.setState({ hasMore: false, }) } this.setState({ list: [...this.state.list, ...result], }) } this.setState({ loading: false, }) } addPost = (post) => { this.setState({ list: [post, ...this.state.list], }) } removePost = (id) => { this.setState({ list: this.state.list.filter((post) => { return post._id !== id }), }) } _hacks = { addPost: this.addPost, removePost: this.removePost, addRandomPost: () => { this.addPost({ _id: Math.random().toString(36).substring(7), message: `Random post ${Math.random().toString(36).substring(7)}`, user: { _id: Math.random().toString(36).substring(7), username: "random user", } }) } } onResumeRealtimeUpdates = async () => { // fetch new posts await this.handleLoad(this.props.loadFromModel) this.setState({ realtimeUpdates: true, }) } onScrollList = (e) => { const { scrollTop, scrollHeight, clientHeight } = e.target if (scrollTop + clientHeight >= scrollHeight - 100) { this.setState({ realtimeUpdates: false, }) } } componentDidMount = async () => { if (typeof this.props.loadFromModel === "function") { await this.handleLoad(this.props.loadFromModel) } this.setState({ initialLoading: false, }) if (this.props.watchTimeline) { Object.entries(this.timelineWsEvents).forEach(([event, callback]) => { app.cores.api.listenEvent(event, callback) }) } //console.log("PostsList mounted", this.viewRef) if (this.viewRef) { // handle when the user is scrolling a bit down, disable ws events this.viewRef.current.addEventListener("scroll", this.onScrollList) } window._hacks = this._hacks } componentWillUnmount = async () => { if (this.props.watchTimeline) { Object.entries(this.timelineWsEvents).forEach(([event, callback]) => { app.cores.api.unlistenEvent(event, callback) }) } if (this.viewRef) { this.viewRef.current.removeEventListener("scroll", this.onScrollList) } window._hacks = null } componentDidUpdate = async (prevProps) => { if (prevProps.list !== this.props.list) { this.setState({ list: this.props.list, }) } } onLikePost = async (data) => { let result = await PostModel.toogleLike({ post_id: data._id }).catch(() => { antd.message.error("Failed to like post") return false }) return result } onSavePost = async (data) => { let result = await PostModel.toogleSave({ post_id: data._id }).catch(() => { antd.message.error("Failed to save post") return false }) return result } onDeletePost = async (data) => { antd.Modal.confirm({ title: "Are you sure you want to delete this post?", content: "This action is irreversible", okText: "Yes", okType: "danger", cancelText: "No", onOk: async () => { await PostModel.deletePost({ post_id: data._id }).catch(() => { antd.message.error("Failed to delete post") }) }, }) } onToogleOpen = (to, data) => { if (typeof this.props.onOpenPost === "function") { this.props.onOpenPost(to, data) } } onLoadMore = async () => { if (typeof this.props.onLoadMore === "function") { return this.handleLoad(this.props.onLoadMore) } } render() { if (this.state.initialLoading) { return } if (this.state.list.length === 0) { if (typeof this.props.emptyListRender === "function") { return React.createElement(this.props.emptyListRender) } return

Whoa, nothing on here...

} return { !this.state.realtimeUpdates &&
} { (item) => }
} } export default React.forwardRef((props, ref) => )