diff --git a/server/src/websocket/server.rs b/server/src/websocket/server.rs index 9b53f21..1fbe443 100644 --- a/server/src/websocket/server.rs +++ b/server/src/websocket/server.rs @@ -94,12 +94,6 @@ pub struct ChatServer { db: Pool>, } -// TODO show online users for communities too -// TODO GetPosts is the community / front page join. -// What is sent: New posts, post edits, post removes, post likes, community edits, community mod adds. Notifs for new posts? -// GetPost is the PostJoin, LeavePost is the leave -// What is sent: New comments, comment edits, comment likes -// UserJoin is the user join, a disconnect should remove you from all the scopes impl ChatServer { pub fn startup(db: Pool>) -> ChatServer { ChatServer { @@ -501,7 +495,7 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result Result { private subscription: Subscription; - private postFetcher: any; private emptyState: State = { community: { id: null, @@ -107,7 +106,6 @@ export class Community extends Component { componentWillUnmount() { this.subscription.unsubscribe(); - clearInterval(this.postFetcher); } // Necessary for back button for some reason diff --git a/ui/src/components/inbox.tsx b/ui/src/components/inbox.tsx index 5585d84..5fd9dbd 100644 --- a/ui/src/components/inbox.tsx +++ b/ui/src/components/inbox.tsx @@ -421,11 +421,25 @@ export class Inbox extends Component { this.sendUnreadCount(); this.setState(this.state); } else if (res.op == UserOperation.CreateComment) { - // let res: CommentResponse = msg; - // TODO gotta remove this - toast(i18n.t('reply_sent')); - // this.state.replies.unshift(res.comment); // TODO do this right - // this.setState(this.state); + let data = res.data as CommentResponse; + + if (data.recipient_ids.includes(UserService.Instance.user.id)) { + this.state.replies.unshift(data.comment); + this.setState(this.state); + } else if (data.comment.creator_id == UserService.Instance.user.id) { + toast(i18n.t('reply_sent')); + } + this.setState(this.state); + } else if (res.op == UserOperation.CreatePrivateMessage) { + let data = res.data as PrivateMessageResponse; + + if (data.message.recipient_id == UserService.Instance.user.id) { + this.state.messages.unshift(data.message); + this.setState(this.state); + } else if (data.message.creator_id == UserService.Instance.user.id) { + toast(i18n.t('message_sent')); + } + this.setState(this.state); } else if (res.op == UserOperation.SaveComment) { let data = res.data as CommentResponse; let found = this.state.replies.find(c => c.id == data.comment.id); diff --git a/ui/src/components/login.tsx b/ui/src/components/login.tsx index 64687a3..b65b7a8 100644 --- a/ui/src/components/login.tsx +++ b/ui/src/components/login.tsx @@ -306,6 +306,7 @@ export class Login extends Component { this.state = this.emptyState; this.setState(this.state); UserService.Instance.login(data); + WebSocketService.Instance.userJoin(); toast(i18n.t('logged_in')); this.props.history.push('/'); } else if (res.op == UserOperation.Register) { @@ -313,6 +314,7 @@ export class Login extends Component { this.state = this.emptyState; this.setState(this.state); UserService.Instance.login(data); + WebSocketService.Instance.userJoin(); this.props.history.push('/communities'); } else if (res.op == UserOperation.PasswordReset) { toast(i18n.t('reset_password_mail_sent')); diff --git a/ui/src/components/navbar.tsx b/ui/src/components/navbar.tsx index d433ad1..d679583 100644 --- a/ui/src/components/navbar.tsx +++ b/ui/src/components/navbar.tsx @@ -16,6 +16,7 @@ import { Comment, CommentResponse, PrivateMessage, + PrivateMessageResponse, WebSocketJsonResponse, } from '../interfaces'; import { @@ -36,7 +37,6 @@ interface NavbarState { replies: Array; mentions: Array; messages: Array; - fetchCount: number; unreadCount: number; siteName: string; } @@ -47,7 +47,6 @@ export class Navbar extends Component { emptyState: NavbarState = { isLoggedIn: UserService.Instance.user !== undefined, unreadCount: 0, - fetchCount: 0, replies: [], mentions: [], messages: [], @@ -59,8 +58,6 @@ export class Navbar extends Component { super(props, context); this.state = this.emptyState; - this.fetchUnreads(); - // Subscribe to user changes this.userSub = UserService.Instance.sub.subscribe(user => { this.state.isLoggedIn = user.user !== undefined; @@ -79,6 +76,8 @@ export class Navbar extends Component { if (this.state.isLoggedIn) { this.requestNotificationPermission(); + // TODO couldn't get re-logging in to re-fetch unreads + this.fetchUnreads(); } WebSocketService.Instance.getSite(); @@ -214,6 +213,7 @@ export class Navbar extends Component { let unreadReplies = data.replies.filter(r => !r.read); this.state.replies = unreadReplies; + this.state.unreadCount = this.calculateUnreadCount(); this.setState(this.state); this.sendUnreadCount(); } else if (res.op == UserOperation.GetUserMentions) { @@ -221,6 +221,7 @@ export class Navbar extends Component { let unreadMentions = data.mentions.filter(r => !r.read); this.state.mentions = unreadMentions; + this.state.unreadCount = this.calculateUnreadCount(); this.setState(this.state); this.sendUnreadCount(); } else if (res.op == UserOperation.GetPrivateMessages) { @@ -228,17 +229,33 @@ export class Navbar extends Component { let unreadMessages = data.messages.filter(r => !r.read); this.state.messages = unreadMessages; + this.state.unreadCount = this.calculateUnreadCount(); this.setState(this.state); this.sendUnreadCount(); } else if (res.op == UserOperation.CreateComment) { - // TODO do private messages too let data = res.data as CommentResponse; - if (UserService.Instance.user) { + if (this.state.isLoggedIn) { if (data.recipient_ids.includes(UserService.Instance.user.id)) { + this.state.replies.push(data.comment); + this.state.unreadCount++; + this.setState(this.state); + this.sendUnreadCount(); this.notify(data.comment); } } + } else if (res.op == UserOperation.CreatePrivateMessage) { + let data = res.data as PrivateMessageResponse; + + if (this.state.isLoggedIn) { + if (data.message.recipient_id == UserService.Instance.user.id) { + this.state.messages.push(data.message); + this.state.unreadCount++; + this.setState(this.state); + this.sendUnreadCount(); + this.notify(data.message); + } + } } else if (res.op == UserOperation.GetSite) { let data = res.data as GetSiteResponse; @@ -276,7 +293,6 @@ export class Navbar extends Component { WebSocketService.Instance.getReplies(repliesForm); WebSocketService.Instance.getUserMentions(userMentionsForm); WebSocketService.Instance.getPrivateMessages(privateMessagesForm); - this.state.fetchCount++; } } } @@ -288,11 +304,11 @@ export class Navbar extends Component { sendUnreadCount() { UserService.Instance.sub.next({ user: UserService.Instance.user, - unreadCount: this.unreadCount, + unreadCount: this.state.unreadCount, }); } - get unreadCount() { + calculateUnreadCount(): number { return ( this.state.replies.filter(r => !r.read).length + this.state.mentions.filter(r => !r.read).length + @@ -317,15 +333,12 @@ export class Navbar extends Component { notify(reply: Comment | PrivateMessage) { if (Notification.permission !== 'granted') Notification.requestPermission(); else { - var notification = new Notification( - `${this.state.unreadCount} ${i18n.t('unread_messages')}`, - { - icon: reply.creator_avatar - ? reply.creator_avatar - : `${window.location.protocol}//${window.location.host}/static/assets/apple-touch-icon.png`, - body: `${reply.creator_name}: ${reply.content}`, - } - ); + var notification = new Notification(reply.creator_name, { + icon: reply.creator_avatar + ? reply.creator_avatar + : `${window.location.protocol}//${window.location.host}/static/assets/apple-touch-icon.png`, + body: `${reply.content}`, + }); notification.onclick = () => { this.context.router.history.push(