X-Git-Url: http://these/git/?a=blobdiff_plain;f=src%2Fshared%2Fcomponents%2Fpost%2Fpost.tsx;h=9c68532bee5122c816ae12d4a48f12375b7c265e;hb=2b1af707c3df6126b3e6890106c03c60ad49b1be;hp=e391832342b3b0b8efea1fe594affd6b72963435;hpb=f61037f5d89f12818c8100f907a98b74e980112a;p=lemmy-ui.git diff --git a/src/shared/components/post/post.tsx b/src/shared/components/post/post.tsx index e391832..9c68532 100644 --- a/src/shared/components/post/post.tsx +++ b/src/shared/components/post/post.tsx @@ -1,67 +1,88 @@ import autosize from "autosize"; import { Component, createRef, linkEvent, RefObject } from "inferno"; import { - AddAdminResponse, + AddAdmin, + AddModToCommunity, AddModToCommunityResponse, + BanFromCommunity, BanFromCommunityResponse, + BanPerson, BanPersonResponse, - BlockPersonResponse, - CommentReportResponse, + BlockCommunity, + BlockPerson, + CommentId, + CommentReplyResponse, CommentResponse, CommentSortType, CommunityResponse, + CreateComment, + CreateCommentLike, + CreateCommentReport, + CreatePostLike, + CreatePostReport, + DeleteComment, + DeleteCommunity, + DeletePost, + DistinguishComment, + EditComment, + EditCommunity, + EditPost, + FeaturePost, + FollowCommunity, GetComments, GetCommentsResponse, GetCommunityResponse, GetPost, GetPostResponse, GetSiteResponse, - PostReportResponse, + LockPost, + MarkCommentReplyAsRead, + MarkPersonMentionAsRead, PostResponse, - PostView, + PurgeComment, + PurgeCommunity, PurgeItemResponse, - Search, - SearchResponse, - UserOperation, - wsJsonToRes, - wsUserOp, + PurgePerson, + PurgePost, + RemoveComment, + RemoveCommunity, + RemovePost, + SaveComment, + SavePost, + TransferCommunity, } from "lemmy-js-client"; -import { Subscription } from "rxjs"; import { i18n } from "../../i18next"; import { CommentNodeI, CommentViewType, InitialFetchRequest, } from "../../interfaces"; -import { UserService, WebSocketService } from "../../services"; +import { UserService } from "../../services"; +import { FirstLoadService } from "../../services/FirstLoadService"; +import { HttpService, RequestState } from "../../services/HttpService"; import { buildCommentsTree, commentsToFlatNodes, commentTreeMaxDepth, - createCommentLikeRes, - createPostLikeRes, debounce, - editCommentRes, + editComment, + editWith, enableDownvotes, enableNsfw, getCommentIdFromProps, getCommentParentId, getDepthFromComment, getIdFromProps, - insertCommentIntoTree, isBrowser, isImage, myAuth, restoreScrollPosition, - saveCommentRes, saveScrollPosition, setIsoData, setupTippy, toast, - trendingFetchLimit, + updateCommunityBlock, updatePersonBlock, - wsClient, - wsSubscribe, } from "../../utils"; import { CommentForm } from "../comment/comment-form"; import { CommentNodes } from "../comment/comment-nodes"; @@ -75,135 +96,140 @@ const commentsShownInterval = 15; interface PostState { postId?: number; commentId?: number; - postRes?: GetPostResponse; - commentsRes?: GetCommentsResponse; - commentTree: CommentNodeI[]; + postRes: RequestState; + commentsRes: RequestState; commentSort: CommentSortType; commentViewType: CommentViewType; scrolled?: boolean; - loading: boolean; - crossPosts?: PostView[]; siteRes: GetSiteResponse; commentSectionRef?: RefObject; showSidebarMobile: boolean; maxCommentsShown: number; + finished: Map; + isIsomorphic: boolean; } export class Post extends Component { - private subscription?: Subscription; private isoData = setIsoData(this.context); private commentScrollDebounced: () => void; state: PostState = { + postRes: { state: "empty" }, + commentsRes: { state: "empty" }, postId: getIdFromProps(this.props), commentId: getCommentIdFromProps(this.props), - commentTree: [], commentSort: "Hot", commentViewType: CommentViewType.Tree, scrolled: false, - loading: true, siteRes: this.isoData.site_res, showSidebarMobile: false, maxCommentsShown: commentsShownInterval, + finished: new Map(), + isIsomorphic: false, }; constructor(props: any, context: any) { super(props, context); - this.parseMessage = this.parseMessage.bind(this); - this.subscription = wsSubscribe(this.parseMessage); + this.handleDeleteCommunityClick = + this.handleDeleteCommunityClick.bind(this); + this.handleEditCommunity = this.handleEditCommunity.bind(this); + this.handleFollow = this.handleFollow.bind(this); + this.handleModRemoveCommunity = this.handleModRemoveCommunity.bind(this); + this.handleCreateComment = this.handleCreateComment.bind(this); + this.handleEditComment = this.handleEditComment.bind(this); + this.handleSaveComment = this.handleSaveComment.bind(this); + this.handleBlockCommunity = this.handleBlockCommunity.bind(this); + this.handleBlockPerson = this.handleBlockPerson.bind(this); + this.handleDeleteComment = this.handleDeleteComment.bind(this); + this.handleRemoveComment = this.handleRemoveComment.bind(this); + this.handleCommentVote = this.handleCommentVote.bind(this); + this.handleAddModToCommunity = this.handleAddModToCommunity.bind(this); + this.handleAddAdmin = this.handleAddAdmin.bind(this); + this.handlePurgePerson = this.handlePurgePerson.bind(this); + this.handlePurgeComment = this.handlePurgeComment.bind(this); + this.handleCommentReport = this.handleCommentReport.bind(this); + this.handleDistinguishComment = this.handleDistinguishComment.bind(this); + this.handleTransferCommunity = this.handleTransferCommunity.bind(this); + this.handleFetchChildren = this.handleFetchChildren.bind(this); + this.handleCommentReplyRead = this.handleCommentReplyRead.bind(this); + this.handlePersonMentionRead = this.handlePersonMentionRead.bind(this); + this.handleBanFromCommunity = this.handleBanFromCommunity.bind(this); + this.handleBanPerson = this.handleBanPerson.bind(this); + this.handlePostEdit = this.handlePostEdit.bind(this); + this.handlePostVote = this.handlePostVote.bind(this); + this.handlePostReport = this.handlePostReport.bind(this); + this.handleLockPost = this.handleLockPost.bind(this); + this.handleDeletePost = this.handleDeletePost.bind(this); + this.handleRemovePost = this.handleRemovePost.bind(this); + this.handleSavePost = this.handleSavePost.bind(this); + this.handlePurgePost = this.handlePurgePost.bind(this); + this.handleFeaturePost = this.handleFeaturePost.bind(this); this.state = { ...this.state, commentSectionRef: createRef() }; // Only fetch the data if coming from another route - if (this.isoData.path == this.context.router.route.match.url) { + if (FirstLoadService.isFirstLoad) { + const [postRes, commentsRes] = this.isoData.routeData; + this.state = { ...this.state, - postRes: this.isoData.routeData[0] as GetPostResponse, - commentsRes: this.isoData.routeData[1] as GetCommentsResponse, + postRes, + commentsRes, + isIsomorphic: true, }; - if (this.state.commentsRes) { - this.state = { - ...this.state, - commentTree: buildCommentsTree( - this.state.commentsRes.comments, - !!this.state.commentId - ), - }; - } - - this.state = { ...this.state, loading: false }; - if (isBrowser()) { - if (this.state.postRes) { - WebSocketService.Instance.send( - wsClient.communityJoin({ - community_id: this.state.postRes.community_view.community.id, - }) - ); - } - - if (this.state.postId) { - WebSocketService.Instance.send( - wsClient.postJoin({ post_id: this.state.postId }) - ); - } - - this.fetchCrossPosts(); - if (this.checkScrollIntoCommentsParam) { this.scrollIntoCommentSection(); } } - } else { - this.fetchPost(); } } - fetchPost() { - const auth = myAuth(false); - const postForm: GetPost = { - id: this.state.postId, - comment_id: this.state.commentId, - auth, - }; - WebSocketService.Instance.send(wsClient.getPost(postForm)); + async fetchPost() { + this.setState({ + postRes: { state: "loading" }, + commentsRes: { state: "loading" }, + }); - const commentsForm: GetComments = { - post_id: this.state.postId, - parent_id: this.state.commentId, - max_depth: commentTreeMaxDepth, - sort: this.state.commentSort, - type_: "All", - saved_only: false, - auth, - }; - WebSocketService.Instance.send(wsClient.getComments(commentsForm)); - } - - fetchCrossPosts() { - const q = this.state.postRes?.post_view.post.url; - if (q) { - const form: Search = { - q, - type_: "Url", - sort: "TopAll", - listing_type: "All", - page: 1, - limit: trendingFetchLimit, - auth: myAuth(false), - }; - WebSocketService.Instance.send(wsClient.search(form)); + const auth = myAuth(); + + this.setState({ + postRes: await HttpService.client.getPost({ + id: this.state.postId, + comment_id: this.state.commentId, + auth, + }), + commentsRes: await HttpService.client.getComments({ + post_id: this.state.postId, + parent_id: this.state.commentId, + max_depth: commentTreeMaxDepth, + sort: this.state.commentSort, + type_: "All", + saved_only: false, + auth, + }), + }); + + setupTippy(); + + if (!this.state.commentId) restoreScrollPosition(this.context); + + if (this.checkScrollIntoCommentsParam) { + this.scrollIntoCommentSection(); } } - static fetchInitialData(req: InitialFetchRequest): Promise[] { - const pathSplit = req.path.split("/"); - const promises: Promise[] = []; + static fetchInitialData({ + auth, + client, + path, + }: InitialFetchRequest): Promise[] { + const pathSplit = path.split("/"); + const promises: Promise>[] = []; const pathType = pathSplit.at(1); const id = pathSplit.at(2) ? Number(pathSplit.at(2)) : undefined; - const auth = req.auth; const postForm: GetPost = { auth, @@ -218,7 +244,7 @@ export class Post extends Component { }; // Set the correct id based on the path type - if (pathType == "post") { + if (pathType === "post") { postForm.id = id; commentsForm.post_id = id; } else { @@ -226,36 +252,33 @@ export class Post extends Component { commentsForm.parent_id = id; } - promises.push(req.client.getPost(postForm)); - promises.push(req.client.getComments(commentsForm)); + promises.push(client.getPost(postForm)); + promises.push(client.getComments(commentsForm)); return promises; } componentWillUnmount() { - this.subscription?.unsubscribe(); document.removeEventListener("scroll", this.commentScrollDebounced); saveScrollPosition(this.context); } - componentDidMount() { + async componentDidMount() { + if (!this.state.isIsomorphic) { + await this.fetchPost(); + } + autosize(document.querySelectorAll("textarea")); this.commentScrollDebounced = debounce(this.trackCommentsBoxScrolling, 100); document.addEventListener("scroll", this.commentScrollDebounced); } - componentDidUpdate(_lastProps: any) { + async componentDidUpdate(_lastProps: any) { // Necessary if you are on a post and you click another post (same route) if (_lastProps.location.pathname !== _lastProps.history.location.pathname) { - // TODO Couldnt get a refresh working. This does for now. - location.reload(); - - // let currentId = this.props.match.params.id; - // WebSocketService.Instance.getPost(currentId); - // this.context.refresh(); - // this.context.router.history.push(_lastProps.location.pathname); + await this.fetchPost(); } } @@ -279,92 +302,123 @@ export class Post extends Component { trackCommentsBoxScrolling = () => { const wrappedElement = document.getElementsByClassName("comments")[0]; if (wrappedElement && this.isBottom(wrappedElement)) { - this.setState({ - maxCommentsShown: this.state.maxCommentsShown + commentsShownInterval, - }); + const commentCount = + this.state.commentsRes.state == "success" + ? this.state.commentsRes.data.comments.length + : 0; + + if (this.state.maxCommentsShown < commentCount) { + this.setState({ + maxCommentsShown: this.state.maxCommentsShown + commentsShownInterval, + }); + } } }; get documentTitle(): string { - const name_ = this.state.postRes?.post_view.post.name; const siteName = this.state.siteRes.site_view.site.name; - return name_ ? `${name_} - ${siteName}` : ""; + return this.state.postRes.state == "success" + ? `${this.state.postRes.data.post_view.post.name} - ${siteName}` + : siteName; } get imageTag(): string | undefined { - const post = this.state.postRes?.post_view.post; - const thumbnail = post?.thumbnail_url; - const url = post?.url; - return thumbnail || (url && isImage(url) ? url : undefined); + if (this.state.postRes.state == "success") { + const post = this.state.postRes.data.post_view.post; + const thumbnail = post.thumbnail_url; + const url = post.url; + return thumbnail || (url && isImage(url) ? url : undefined); + } else return undefined; } - render() { - const res = this.state.postRes; - const description = res?.post_view.post.body; - return ( -
- {this.state.loading ? ( + renderPostRes() { + switch (this.state.postRes.state) { + case "loading": + return (
- ) : ( - res && ( -
-
- - -
- -
- - {this.state.showSidebarMobile && this.sidebar()} -
- {this.sortRadios()} - {this.state.commentViewType == CommentViewType.Tree && - this.commentsTree()} - {this.state.commentViewType == CommentViewType.Flat && - this.commentsFlat()} + ); + case "success": { + const res = this.state.postRes.data; + return ( +
+
+ + +
+ +
+ + {this.state.showSidebarMobile && this.sidebar()}
-
{this.sidebar()}
+ {this.sortRadios()} + {this.state.commentViewType == CommentViewType.Tree && + this.commentsTree()} + {this.state.commentViewType == CommentViewType.Flat && + this.commentsFlat()}
- ) - )} -
- ); +
{this.sidebar()}
+
+ ); + } + } + } + + render() { + return
{this.renderPostRes()}
; } sortRadios() { @@ -447,97 +501,83 @@ export class Post extends Component { // These are already sorted by new const commentsRes = this.state.commentsRes; const postRes = this.state.postRes; - return ( - commentsRes && - postRes && ( + + if (commentsRes.state == "success" && postRes.state == "success") { + return (
- ) - ); + ); + } } sidebar() { const res = this.state.postRes; - return ( - res && ( + if (res.state === "success") { + return (
- ) - ); - } - - handleCommentSortChange(i: Post, event: any) { - i.setState({ - commentSort: event.target.value as CommentSortType, - commentViewType: CommentViewType.Tree, - commentsRes: undefined, - postRes: undefined, - }); - i.fetchPost(); - } - - handleCommentViewTypeChange(i: Post, event: any) { - const comments = i.state.commentsRes?.comments; - if (comments) { - i.setState({ - commentViewType: Number(event.target.value), - commentSort: "New", - commentTree: buildCommentsTree(comments, !!i.state.commentId), - }); - } - } - - handleShowSidebarMobile(i: Post) { - i.setState({ showSidebarMobile: !i.state.showSidebarMobile }); - } - - handleViewPost(i: Post) { - const id = i.state.postRes?.post_view.post.id; - if (id) { - i.context.router.history.push(`/post/${id}`); - } - } - - handleViewContext(i: Post) { - const parentId = getCommentParentId( - i.state.commentsRes?.comments?.at(0)?.comment - ); - if (parentId) { - i.context.router.history.push(`/comment/${parentId}`); + ); } } commentsTree() { const res = this.state.postRes; - const firstComment = this.state.commentTree.at(0)?.comment_view.comment; + const firstComment = this.commentTree().at(0)?.comment_view.comment; const depth = getDepthFromComment(firstComment); const showContextButton = depth ? depth > 0 : false; return ( - res && ( + res.state == "success" && (
{!!this.state.commentId && ( <> @@ -558,238 +598,437 @@ export class Post extends Component { )}
) ); } - parseMessage(msg: any) { - const op = wsUserOp(msg); - console.log(msg); - if (msg.error) { - toast(i18n.t(msg.error), "danger"); - return; - } else if (msg.reconnect) { - const post_id = this.state.postRes?.post_view.post.id; - if (post_id) { - WebSocketService.Instance.send(wsClient.postJoin({ post_id })); - WebSocketService.Instance.send( - wsClient.getPost({ - id: post_id, - auth: myAuth(false), - }) - ); - } - } else if (op == UserOperation.GetPost) { - const data = wsJsonToRes(msg); - this.setState({ postRes: data }); - - // join the rooms - WebSocketService.Instance.send( - wsClient.postJoin({ post_id: data.post_view.post.id }) - ); - WebSocketService.Instance.send( - wsClient.communityJoin({ - community_id: data.community_view.community.id, - }) + commentTree(): CommentNodeI[] { + if (this.state.commentsRes.state == "success") { + return buildCommentsTree( + this.state.commentsRes.data.comments, + !!this.state.commentId ); + } else { + return []; + } + } - // Get cross-posts - // TODO move this into initial fetch and refetch - this.fetchCrossPosts(); - setupTippy(); - if (!this.state.commentId) restoreScrollPosition(this.context); + async handleCommentSortChange(i: Post, event: any) { + i.setState({ + commentSort: event.target.value as CommentSortType, + commentViewType: CommentViewType.Tree, + commentsRes: { state: "loading" }, + postRes: { state: "loading" }, + }); + await i.fetchPost(); + } + + handleCommentViewTypeChange(i: Post, event: any) { + i.setState({ + commentViewType: Number(event.target.value), + commentSort: "New", + }); + } - if (this.checkScrollIntoCommentsParam) { - this.scrollIntoCommentSection(); + handleShowSidebarMobile(i: Post) { + i.setState({ showSidebarMobile: !i.state.showSidebarMobile }); + } + + handleViewPost(i: Post) { + if (i.state.postRes.state == "success") { + const id = i.state.postRes.data.post_view.post.id; + i.context.router.history.push(`/post/${id}`); + } + } + + handleViewContext(i: Post) { + if (i.state.commentsRes.state == "success") { + const parentId = getCommentParentId( + i.state.commentsRes.data.comments.at(0)?.comment + ); + if (parentId) { + i.context.router.history.push(`/comment/${parentId}`); } - } else if (op == UserOperation.GetComments) { - const data = wsJsonToRes(msg); - // This section sets the comments res - const comments = this.state.commentsRes?.comments; - if (comments) { - // You might need to append here, since this could be building more comments from a tree fetch - // Remove the first comment, since it is the parent - const newComments = data.comments; - newComments.shift(); - comments.push(...newComments); - } else { - this.setState({ commentsRes: data }); + } + } + + async handleDeleteCommunityClick(form: DeleteCommunity) { + const deleteCommunityRes = await HttpService.client.deleteCommunity(form); + this.updateCommunity(deleteCommunityRes); + } + + async handleAddModToCommunity(form: AddModToCommunity) { + const addModRes = await HttpService.client.addModToCommunity(form); + this.updateModerators(addModRes); + } + + async handleFollow(form: FollowCommunity) { + const followCommunityRes = await HttpService.client.followCommunity(form); + this.updateCommunity(followCommunityRes); + + // Update myUserInfo + if (followCommunityRes.state === "success") { + const communityId = followCommunityRes.data.community_view.community.id; + const mui = UserService.Instance.myUserInfo; + if (mui) { + mui.follows = mui.follows.filter(i => i.community.id != communityId); } + } + } - const cComments = this.state.commentsRes?.comments ?? []; - this.setState({ - commentTree: buildCommentsTree(cComments, !!this.state.commentId), - loading: false, - }); - } else if (op == UserOperation.CreateComment) { - const data = wsJsonToRes(msg); + async handlePurgeCommunity(form: PurgeCommunity) { + const purgeCommunityRes = await HttpService.client.purgeCommunity(form); + this.purgeItem(purgeCommunityRes); + } + + async handlePurgePerson(form: PurgePerson) { + const purgePersonRes = await HttpService.client.purgePerson(form); + this.purgeItem(purgePersonRes); + } + + async handlePurgeComment(form: PurgeComment) { + const purgeCommentRes = await HttpService.client.purgeComment(form); + this.purgeItem(purgeCommentRes); + } - // Don't get comments from the post room, if the creator is blocked - const creatorBlocked = UserService.Instance.myUserInfo?.person_blocks - .map(pb => pb.target.id) - .includes(data.comment_view.creator.id); + async handlePurgePost(form: PurgePost) { + const purgeRes = await HttpService.client.purgePost(form); + this.purgeItem(purgeRes); + } - // Necessary since it might be a user reply, which has the recipients, to avoid double - const postRes = this.state.postRes; - const commentsRes = this.state.commentsRes; + async handleBlockCommunity(form: BlockCommunity) { + const blockCommunityRes = await HttpService.client.blockCommunity(form); + // TODO Probably isn't necessary + this.setState(s => { if ( - data.recipient_ids.length == 0 && - !creatorBlocked && - postRes && - data.comment_view.post.id == postRes.post_view.post.id && - commentsRes + s.postRes.state == "success" && + blockCommunityRes.state == "success" ) { - commentsRes.comments.unshift(data.comment_view); - insertCommentIntoTree( - this.state.commentTree, - data.comment_view, - !!this.state.commentId - ); - postRes.post_view.counts.comments++; - - this.setState(this.state); - setupTippy(); + s.postRes.data.community_view = blockCommunityRes.data.community_view; } - } else if ( - op == UserOperation.EditComment || - op == UserOperation.DeleteComment || - op == UserOperation.RemoveComment - ) { - const data = wsJsonToRes(msg); - editCommentRes(data.comment_view, this.state.commentsRes?.comments); - this.setState(this.state); - setupTippy(); - } else if (op == UserOperation.SaveComment) { - const data = wsJsonToRes(msg); - saveCommentRes(data.comment_view, this.state.commentsRes?.comments); - this.setState(this.state); - setupTippy(); - } else if (op == UserOperation.CreateCommentLike) { - const data = wsJsonToRes(msg); - createCommentLikeRes(data.comment_view, this.state.commentsRes?.comments); - this.setState(this.state); - } else if (op == UserOperation.CreatePostLike) { - const data = wsJsonToRes(msg); - createPostLikeRes(data.post_view, this.state.postRes?.post_view); - this.setState(this.state); - } else if ( - op == UserOperation.EditPost || - op == UserOperation.DeletePost || - op == UserOperation.RemovePost || - op == UserOperation.LockPost || - op == UserOperation.FeaturePost || - op == UserOperation.SavePost - ) { - const data = wsJsonToRes(msg); - const res = this.state.postRes; - if (res) { - res.post_view = data.post_view; - this.setState(this.state); - setupTippy(); - } - } else if ( - op == UserOperation.EditCommunity || - op == UserOperation.DeleteCommunity || - op == UserOperation.RemoveCommunity || - op == UserOperation.FollowCommunity + return s; + }); + + if (blockCommunityRes.state == "success") { + updateCommunityBlock(blockCommunityRes.data); + } + } + + async handleBlockPerson(form: BlockPerson) { + const blockPersonRes = await HttpService.client.blockPerson(form); + if (blockPersonRes.state == "success") { + updatePersonBlock(blockPersonRes.data); + } + } + + async handleModRemoveCommunity(form: RemoveCommunity) { + const removeCommunityRes = await HttpService.client.removeCommunity(form); + this.updateCommunity(removeCommunityRes); + } + + async handleEditCommunity(form: EditCommunity) { + const res = await HttpService.client.editCommunity(form); + this.updateCommunity(res); + + return res; + } + + async handleCreateComment(form: CreateComment) { + const createCommentRes = await HttpService.client.createComment(form); + this.createAndUpdateComments(createCommentRes); + + return createCommentRes; + } + + async handleEditComment(form: EditComment) { + const editCommentRes = await HttpService.client.editComment(form); + this.findAndUpdateComment(editCommentRes); + + return editCommentRes; + } + + async handleDeleteComment(form: DeleteComment) { + const deleteCommentRes = await HttpService.client.deleteComment(form); + this.findAndUpdateComment(deleteCommentRes); + } + + async handleDeletePost(form: DeletePost) { + const deleteRes = await HttpService.client.deletePost(form); + this.updatePost(deleteRes); + } + + async handleRemovePost(form: RemovePost) { + const removeRes = await HttpService.client.removePost(form); + this.updatePost(removeRes); + } + + async handleRemoveComment(form: RemoveComment) { + const removeCommentRes = await HttpService.client.removeComment(form); + this.findAndUpdateComment(removeCommentRes); + } + + async handleSaveComment(form: SaveComment) { + const saveCommentRes = await HttpService.client.saveComment(form); + this.findAndUpdateComment(saveCommentRes); + } + + async handleSavePost(form: SavePost) { + const saveRes = await HttpService.client.savePost(form); + this.updatePost(saveRes); + } + + async handleFeaturePost(form: FeaturePost) { + const featureRes = await HttpService.client.featurePost(form); + this.updatePost(featureRes); + } + + async handleCommentVote(form: CreateCommentLike) { + const voteRes = await HttpService.client.likeComment(form); + this.findAndUpdateComment(voteRes); + } + + async handlePostVote(form: CreatePostLike) { + const voteRes = await HttpService.client.likePost(form); + this.updatePost(voteRes); + } + + async handlePostEdit(form: EditPost) { + const res = await HttpService.client.editPost(form); + this.updatePost(res); + } + + async handleCommentReport(form: CreateCommentReport) { + const reportRes = await HttpService.client.createCommentReport(form); + if (reportRes.state == "success") { + toast(i18n.t("report_created")); + } + } + + async handlePostReport(form: CreatePostReport) { + const reportRes = await HttpService.client.createPostReport(form); + if (reportRes.state == "success") { + toast(i18n.t("report_created")); + } + } + + async handleLockPost(form: LockPost) { + const lockRes = await HttpService.client.lockPost(form); + this.updatePost(lockRes); + } + + async handleDistinguishComment(form: DistinguishComment) { + const distinguishRes = await HttpService.client.distinguishComment(form); + this.findAndUpdateComment(distinguishRes); + } + + async handleAddAdmin(form: AddAdmin) { + const addAdminRes = await HttpService.client.addAdmin(form); + + if (addAdminRes.state === "success") { + this.setState(s => ((s.siteRes.admins = addAdminRes.data.admins), s)); + } + } + + async handleTransferCommunity(form: TransferCommunity) { + const transferCommunityRes = await HttpService.client.transferCommunity( + form + ); + this.updateCommunityFull(transferCommunityRes); + } + + async handleFetchChildren(form: GetComments) { + const moreCommentsRes = await HttpService.client.getComments(form); + if ( + this.state.commentsRes.state == "success" && + moreCommentsRes.state == "success" ) { - const data = wsJsonToRes(msg); - const res = this.state.postRes; - if (res) { - res.community_view = data.community_view; - res.post_view.community = data.community_view.community; - this.setState(this.state); - } - } else if (op == UserOperation.BanFromCommunity) { - const data = wsJsonToRes(msg); + const newComments = moreCommentsRes.data.comments; + // Remove the first comment, since it is the parent + newComments.shift(); + const newRes = this.state.commentsRes; + newRes.data.comments.push(...newComments); + this.setState({ commentsRes: newRes }); + } + } + + async handleCommentReplyRead(form: MarkCommentReplyAsRead) { + const readRes = await HttpService.client.markCommentReplyAsRead(form); + this.findAndUpdateCommentReply(readRes); + } + + async handlePersonMentionRead(form: MarkPersonMentionAsRead) { + // TODO not sure what to do here. Maybe it is actually optional, because post doesn't need it. + await HttpService.client.markPersonMentionAsRead(form); + } - const res = this.state.postRes; - if (res) { - if (res.post_view.creator.id == data.person_view.person.id) { - res.post_view.creator_banned_from_community = data.banned; + async handleBanFromCommunity(form: BanFromCommunity) { + const banRes = await HttpService.client.banFromCommunity(form); + this.updateBan(banRes); + } + + async handleBanPerson(form: BanPerson) { + const banRes = await HttpService.client.banPerson(form); + this.updateBan(banRes); + } + + updateBanFromCommunity(banRes: RequestState) { + // Maybe not necessary + if (banRes.state == "success") { + this.setState(s => { + if ( + s.postRes.state == "success" && + s.postRes.data.post_view.creator.id == + banRes.data.person_view.person.id + ) { + s.postRes.data.post_view.creator_banned_from_community = + banRes.data.banned; } + if (s.commentsRes.state == "success") { + s.commentsRes.data.comments + .filter(c => c.creator.id == banRes.data.person_view.person.id) + .forEach( + c => (c.creator_banned_from_community = banRes.data.banned) + ); + } + return s; + }); + } + } + + updateBan(banRes: RequestState) { + // Maybe not necessary + if (banRes.state == "success") { + this.setState(s => { + if ( + s.postRes.state == "success" && + s.postRes.data.post_view.creator.id == + banRes.data.person_view.person.id + ) { + s.postRes.data.post_view.creator.banned = banRes.data.banned; + } + if (s.commentsRes.state == "success") { + s.commentsRes.data.comments + .filter(c => c.creator.id == banRes.data.person_view.person.id) + .forEach(c => (c.creator.banned = banRes.data.banned)); + } + return s; + }); + } + } + + updateCommunity(communityRes: RequestState) { + this.setState(s => { + if (s.postRes.state == "success" && communityRes.state == "success") { + s.postRes.data.community_view = communityRes.data.community_view; } + return s; + }); + } - this.state.commentsRes?.comments - .filter(c => c.creator.id == data.person_view.person.id) - .forEach(c => (c.creator_banned_from_community = data.banned)); - this.setState(this.state); - } else if (op == UserOperation.AddModToCommunity) { - const data = wsJsonToRes(msg); - const res = this.state.postRes; - if (res) { - res.moderators = data.moderators; - this.setState(this.state); + updateCommunityFull(res: RequestState) { + this.setState(s => { + if (s.postRes.state == "success" && res.state == "success") { + s.postRes.data.community_view = res.data.community_view; + s.postRes.data.moderators = res.data.moderators; } - } else if (op == UserOperation.BanPerson) { - const data = wsJsonToRes(msg); - this.state.commentsRes?.comments - .filter(c => c.creator.id == data.person_view.person.id) - .forEach(c => (c.creator.banned = data.banned)); - - const res = this.state.postRes; - if (res) { - if (res.post_view.creator.id == data.person_view.person.id) { - res.post_view.creator.banned = data.banned; - } + return s; + }); + } + + updatePost(post: RequestState) { + this.setState(s => { + if (s.postRes.state == "success" && post.state == "success") { + s.postRes.data.post_view = post.data.post_view; } - this.setState(this.state); - } else if (op == UserOperation.AddAdmin) { - const data = wsJsonToRes(msg); - this.setState(s => ((s.siteRes.admins = data.admins), s)); - } else if (op == UserOperation.Search) { - const data = wsJsonToRes(msg); - const xPosts = data.posts.filter( - p => p.post.ap_id != this.state.postRes?.post_view.post.ap_id - ); - this.setState({ crossPosts: xPosts.length > 0 ? xPosts : undefined }); - } else if (op == UserOperation.LeaveAdmin) { - const data = wsJsonToRes(msg); - this.setState({ siteRes: data }); - } else if (op == UserOperation.TransferCommunity) { - const data = wsJsonToRes(msg); - const res = this.state.postRes; - if (res) { - res.community_view = data.community_view; - res.post_view.community = data.community_view.community; - res.moderators = data.moderators; - this.setState(this.state); + return s; + }); + } + + purgeItem(purgeRes: RequestState) { + if (purgeRes.state == "success") { + toast(i18n.t("purge_success")); + this.context.router.history.push(`/`); + } + } + + createAndUpdateComments(res: RequestState) { + this.setState(s => { + if (s.commentsRes.state === "success" && res.state === "success") { + s.commentsRes.data.comments.unshift(res.data.comment_view); + + // Set finished for the parent + s.finished.set( + getCommentParentId(res.data.comment_view.comment) ?? 0, + true + ); } - } else if (op == UserOperation.BlockPerson) { - const data = wsJsonToRes(msg); - updatePersonBlock(data); - } else if (op == UserOperation.CreatePostReport) { - const data = wsJsonToRes(msg); - if (data) { - toast(i18n.t("report_created")); + return s; + }); + } + + findAndUpdateComment(res: RequestState) { + this.setState(s => { + if (s.commentsRes.state == "success" && res.state == "success") { + s.commentsRes.data.comments = editComment( + res.data.comment_view, + s.commentsRes.data.comments + ); + s.finished.set(res.data.comment_view.comment.id, true); } - } else if (op == UserOperation.CreateCommentReport) { - const data = wsJsonToRes(msg); - if (data) { - toast(i18n.t("report_created")); + return s; + }); + } + + findAndUpdateCommentReply(res: RequestState) { + this.setState(s => { + if (s.commentsRes.state == "success" && res.state == "success") { + s.commentsRes.data.comments = editWith( + res.data.comment_reply_view, + s.commentsRes.data.comments + ); } - } else if ( - op == UserOperation.PurgePerson || - op == UserOperation.PurgePost || - op == UserOperation.PurgeComment || - op == UserOperation.PurgeCommunity - ) { - const data = wsJsonToRes(msg); - if (data.success) { - toast(i18n.t("purge_success")); - this.context.router.history.push(`/`); + return s; + }); + } + + updateModerators(res: RequestState) { + // Update the moderators + this.setState(s => { + if (s.postRes.state == "success" && res.state == "success") { + s.postRes.data.moderators = res.data.moderators; } - } + return s; + }); } }