From 036d6260bb7da3952c6862617e5438d105483645 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Sun, 9 Feb 2020 15:04:41 -0500 Subject: [PATCH] Adding instant voting / vote animations. Fixes #526 --- server/src/websocket/server.rs | 3 + ui/assets/css/main.css | 6 ++ ui/src/components/comment-node.tsx | 112 ++++++++++++++++------------- ui/src/components/post-listing.tsx | 103 ++++++++++++++------------ ui/src/interfaces.ts | 4 -- ui/src/utils.ts | 4 -- 6 files changed, 130 insertions(+), 102 deletions(-) diff --git a/server/src/websocket/server.rs b/server/src/websocket/server.rs index 003b886..1cbcb34 100644 --- a/server/src/websocket/server.rs +++ b/server/src/websocket/server.rs @@ -280,6 +280,9 @@ impl ChatServer { self.send_community_room_message(0, &post_sent_str, id); self.send_community_room_message(community_id, &post_sent_str, id); + // Send it to the post room + self.send_post_room_message(post_sent.post.id, &post_sent_str, id); + to_json_string(&user_operation, post) } diff --git a/ui/assets/css/main.css b/ui/assets/css/main.css index b1ad884..df75ec3 100644 --- a/ui/assets/css/main.css +++ b/ui/assets/css/main.css @@ -175,3 +175,9 @@ hr { .img-expanded { max-height: 90vh; } + +.vote-animate:active { + transform: scale(1.2); + -webkit-transform: scale(1.2); + -ms-transform: scale(1.2); +} diff --git a/ui/src/components/comment-node.tsx b/ui/src/components/comment-node.tsx index 0e51106..1d0b12c 100644 --- a/ui/src/components/comment-node.tsx +++ b/ui/src/components/comment-node.tsx @@ -48,8 +48,10 @@ interface CommentNodeState { showConfirmAppointAsAdmin: boolean; collapsed: boolean; viewSource: boolean; - upvoteLoading: boolean; - downvoteLoading: boolean; + my_vote: number; + score: number; + upvotes: number; + downvotes: number; } interface CommentNodeProps { @@ -83,8 +85,10 @@ export class CommentNode extends Component { showConfirmTransferCommunity: false, showConfirmAppointAsMod: false, showConfirmAppointAsAdmin: false, - upvoteLoading: this.props.node.comment.upvoteLoading, - downvoteLoading: this.props.node.comment.downvoteLoading, + my_vote: this.props.node.comment.my_vote, + score: this.props.node.comment.score, + upvotes: this.props.node.comment.upvotes, + downvotes: this.props.node.comment.downvotes, }; constructor(props: any, context: any) { @@ -97,15 +101,11 @@ export class CommentNode extends Component { } componentWillReceiveProps(nextProps: CommentNodeProps) { - if ( - nextProps.node.comment.upvoteLoading !== this.state.upvoteLoading || - nextProps.node.comment.downvoteLoading !== this.state.downvoteLoading - ) { - this.setState({ - upvoteLoading: false, - downvoteLoading: false, - }); - } + this.state.my_vote = nextProps.node.comment.my_vote; + this.state.upvotes = nextProps.node.comment.upvotes; + this.state.downvotes = nextProps.node.comment.downvotes; + this.state.score = nextProps.node.comment.score; + this.setState(this.state); } render() { @@ -122,40 +122,26 @@ export class CommentNode extends Component { .viewOnly && 'no-click'}`} > -
- {node.comment.score} -
+
{this.state.score}
{WebSocketService.Instance.site.enable_downvotes && ( )} @@ -205,9 +191,9 @@ export class CommentNode extends Component { )}
  • - (+{node.comment.upvotes} + (+{this.state.upvotes} | - -{node.comment.downvotes} + -{this.state.downvotes} )
  • @@ -772,31 +758,57 @@ export class CommentNode extends Component { } handleCommentUpvote(i: CommentNodeI) { - if (UserService.Instance.user) { - this.setState({ - upvoteLoading: true, - }); + let new_vote = this.state.my_vote == 1 ? 0 : 1; + + if (this.state.my_vote == 1) { + this.state.score--; + this.state.upvotes--; + } else if (this.state.my_vote == -1) { + this.state.downvotes--; + this.state.upvotes++; + this.state.score += 2; + } else { + this.state.upvotes++; + this.state.score++; } + + this.state.my_vote = new_vote; + let form: CommentLikeForm = { comment_id: i.comment.id, post_id: i.comment.post_id, - score: i.comment.my_vote == 1 ? 0 : 1, + score: this.state.my_vote, }; + WebSocketService.Instance.likeComment(form); + this.setState(this.state); } handleCommentDownvote(i: CommentNodeI) { - if (UserService.Instance.user) { - this.setState({ - downvoteLoading: true, - }); + let new_vote = this.state.my_vote == -1 ? 0 : -1; + + if (this.state.my_vote == 1) { + this.state.score -= 2; + this.state.upvotes--; + this.state.downvotes++; + } else if (this.state.my_vote == -1) { + this.state.downvotes--; + this.state.score++; + } else { + this.state.downvotes++; + this.state.score--; } + + this.state.my_vote = new_vote; + let form: CommentLikeForm = { comment_id: i.comment.id, post_id: i.comment.post_id, - score: i.comment.my_vote == -1 ? 0 : -1, + score: this.state.my_vote, }; + WebSocketService.Instance.likeComment(form); + this.setState(this.state); } handleModRemoveShow(i: CommentNode) { diff --git a/ui/src/components/post-listing.tsx b/ui/src/components/post-listing.tsx index f11d9e1..1e72890 100644 --- a/ui/src/components/post-listing.tsx +++ b/ui/src/components/post-listing.tsx @@ -43,8 +43,10 @@ interface PostListingState { showConfirmTransferCommunity: boolean; imageExpanded: boolean; viewSource: boolean; - upvoteLoading: boolean; - downvoteLoading: boolean; + my_vote: number; + score: number; + upvotes: number; + downvotes: number; } interface PostListingProps { @@ -68,8 +70,10 @@ export class PostListing extends Component { showConfirmTransferCommunity: false, imageExpanded: false, viewSource: false, - upvoteLoading: this.props.post.upvoteLoading, - downvoteLoading: this.props.post.downvoteLoading, + my_vote: this.props.post.my_vote, + score: this.props.post.score, + upvotes: this.props.post.upvotes, + downvotes: this.props.post.downvotes, }; constructor(props: any, context: any) { @@ -83,15 +87,11 @@ export class PostListing extends Component { } componentWillReceiveProps(nextProps: PostListingProps) { - if ( - nextProps.post.upvoteLoading !== this.state.upvoteLoading || - nextProps.post.downvoteLoading !== this.state.downvoteLoading - ) { - this.setState({ - upvoteLoading: false, - downvoteLoading: false, - }); - } + this.state.my_vote = nextProps.post.my_vote; + this.state.upvotes = nextProps.post.upvotes; + this.state.downvotes = nextProps.post.downvotes; + this.state.score = nextProps.post.score; + this.setState(this.state); } render() { @@ -118,38 +118,26 @@ export class PostListing extends Component {
    -
    {post.score}
    +
    {this.state.score}
    {WebSocketService.Instance.site.enable_downvotes && ( )}
    @@ -315,9 +303,9 @@ export class PostListing extends Component {
  • - (+{post.upvotes} + (+{this.state.upvotes} | - -{post.downvotes} + -{this.state.downvotes} )
  • @@ -747,28 +735,55 @@ export class PostListing extends Component { } handlePostLike(i: PostListing) { - if (UserService.Instance.user) { - i.setState({ upvoteLoading: true }); + let new_vote = i.state.my_vote == 1 ? 0 : 1; + + if (i.state.my_vote == 1) { + i.state.score--; + i.state.upvotes--; + } else if (i.state.my_vote == -1) { + i.state.downvotes--; + i.state.upvotes++; + i.state.score += 2; + } else { + i.state.upvotes++; + i.state.score++; } + i.state.my_vote = new_vote; + let form: CreatePostLikeForm = { post_id: i.props.post.id, - score: i.props.post.my_vote == 1 ? 0 : 1, + score: i.state.my_vote, }; WebSocketService.Instance.likePost(form); + i.setState(i.state); } handlePostDisLike(i: PostListing) { - if (UserService.Instance.user) { - i.setState({ downvoteLoading: true }); + let new_vote = i.state.my_vote == -1 ? 0 : -1; + + if (i.state.my_vote == 1) { + i.state.score -= 2; + i.state.upvotes--; + i.state.downvotes++; + } else if (i.state.my_vote == -1) { + i.state.downvotes--; + i.state.score++; + } else { + i.state.downvotes++; + i.state.score--; } + i.state.my_vote = new_vote; + let form: CreatePostLikeForm = { post_id: i.props.post.id, - score: i.props.post.my_vote == -1 ? 0 : -1, + score: i.state.my_vote, }; + WebSocketService.Instance.likePost(form); + i.setState(i.state); } handleEditClick(i: PostListing) { diff --git a/ui/src/interfaces.ts b/ui/src/interfaces.ts index 185056f..23551b5 100644 --- a/ui/src/interfaces.ts +++ b/ui/src/interfaces.ts @@ -177,8 +177,6 @@ export interface Post { subscribed?: boolean; read?: boolean; saved?: boolean; - upvoteLoading?: boolean; - downvoteLoading?: boolean; duplicates?: Array; } @@ -209,8 +207,6 @@ export interface Comment { saved?: boolean; user_mention_id?: number; // For mention type recipient_id?: number; - upvoteLoading?: boolean; - downvoteLoading?: boolean; } export interface Category { diff --git a/ui/src/utils.ts b/ui/src/utils.ts index 929877f..384d5c1 100644 --- a/ui/src/utils.ts +++ b/ui/src/utils.ts @@ -601,8 +601,6 @@ export function createCommentLikeRes( found.downvotes = data.comment.downvotes; if (data.comment.my_vote !== null) { found.my_vote = data.comment.my_vote; - found.upvoteLoading = false; - found.downvoteLoading = false; } } } @@ -620,8 +618,6 @@ export function createPostLikeRes(data: PostResponse, post: Post) { post.downvotes = data.post.downvotes; if (data.post.my_vote !== null) { post.my_vote = data.post.my_vote; - post.upvoteLoading = false; - post.downvoteLoading = false; } }