]> Untitled Git - lemmy-ui.git/blobdiff - src/shared/components/person/inbox.tsx
Changing all bigints to numbers
[lemmy-ui.git] / src / shared / components / person / inbox.tsx
index 2a8a7b2984640cade3ebe22dc365fface8dc794f..a39977917480aa13c8713abc0ff2fa8e12d65338 100644 (file)
@@ -1,4 +1,3 @@
-import { None, Some } from "@sniptt/monads";
 import { Component, linkEvent } from "inferno";
 import {
   BlockPersonResponse,
@@ -17,9 +16,10 @@ import {
   PersonMentionResponse,
   PersonMentionView,
   PostReportResponse,
+  PrivateMessageReportResponse,
   PrivateMessageResponse,
-  PrivateMessagesResponse,
   PrivateMessageView,
+  PrivateMessagesResponse,
   UserOperation,
   wsJsonToRes,
   wsUserOp,
@@ -29,13 +29,13 @@ import { i18n } from "../../i18next";
 import { CommentViewType, InitialFetchRequest } from "../../interfaces";
 import { UserService, WebSocketService } from "../../services";
 import {
-  auth,
   commentsToFlatNodes,
   createCommentLikeRes,
   editCommentRes,
   enableDownvotes,
   fetchLimit,
   isBrowser,
+  myAuth,
   relTags,
   saveCommentRes,
   setIsoData,
@@ -90,21 +90,16 @@ interface InboxState {
 }
 
 export class Inbox extends Component<any, InboxState> {
-  private isoData = setIsoData(
-    this.context,
-    GetRepliesResponse,
-    GetPersonMentionsResponse,
-    PrivateMessagesResponse
-  );
-  private subscription: Subscription;
-  private emptyState: InboxState = {
+  private isoData = setIsoData(this.context);
+  private subscription?: Subscription;
+  state: InboxState = {
     unreadOrAll: UnreadOrAll.Unread,
     messageType: MessageType.All,
     replies: [],
     mentions: [],
     messages: [],
     combined: [],
-    sort: CommentSortType.New,
+    sort: "New",
     page: 1,
     siteRes: this.isoData.site_res,
     loading: true,
@@ -113,11 +108,10 @@ export class Inbox extends Component<any, InboxState> {
   constructor(props: any, context: any) {
     super(props, context);
 
-    this.state = this.emptyState;
     this.handleSortChange = this.handleSortChange.bind(this);
     this.handlePageChange = this.handlePageChange.bind(this);
 
-    if (UserService.Instance.myUserInfo.isNone() && isBrowser()) {
+    if (!UserService.Instance.myUserInfo && isBrowser()) {
       toast(i18n.t("not_logged_in"), "danger");
       this.context.router.history.push(`/login`);
     }
@@ -127,15 +121,19 @@ export class Inbox extends Component<any, InboxState> {
 
     // Only fetch the data if coming from another route
     if (this.isoData.path == this.context.router.route.match.url) {
-      this.state.replies =
-        (this.isoData.routeData[0] as GetRepliesResponse).replies || [];
-      this.state.mentions =
-        (this.isoData.routeData[1] as GetPersonMentionsResponse).mentions || [];
-      this.state.messages =
-        (this.isoData.routeData[2] as PrivateMessagesResponse)
-          .private_messages || [];
-      this.state.combined = this.buildCombined();
-      this.state.loading = false;
+      this.state = {
+        ...this.state,
+        replies:
+          (this.isoData.routeData[0] as GetRepliesResponse).replies || [],
+        mentions:
+          (this.isoData.routeData[1] as GetPersonMentionsResponse).mentions ||
+          [],
+        messages:
+          (this.isoData.routeData[2] as PrivateMessagesResponse)
+            .private_messages || [],
+        loading: false,
+      };
+      this.state = { ...this.state, combined: this.buildCombined() };
     } else {
       this.refetch();
     }
@@ -143,60 +141,49 @@ export class Inbox extends Component<any, InboxState> {
 
   componentWillUnmount() {
     if (isBrowser()) {
-      this.subscription.unsubscribe();
+      this.subscription?.unsubscribe();
     }
   }
 
   get documentTitle(): string {
-    return this.state.siteRes.site_view.match({
-      some: siteView =>
-        UserService.Instance.myUserInfo.match({
-          some: mui =>
-            `@${mui.local_user_view.person.name} ${i18n.t("inbox")} - ${
-              siteView.site.name
-            }`,
-          none: "",
-        }),
-      none: "",
-    });
+    let mui = UserService.Instance.myUserInfo;
+    return mui
+      ? `@${mui.local_user_view.person.name} ${i18n.t("inbox")} - ${
+          this.state.siteRes.site_view.site.name
+        }`
+      : "";
   }
 
   render() {
-    let inboxRss = auth()
-      .ok()
-      .map(a => `/feeds/inbox/${a}.xml`);
+    let auth = myAuth();
+    let inboxRss = auth ? `/feeds/inbox/${auth}.xml` : undefined;
     return (
-      <div class="container">
+      <div className="container-lg">
         {this.state.loading ? (
           <h5>
             <Spinner large />
           </h5>
         ) : (
-          <div class="row">
-            <div class="col-12">
+          <div className="row">
+            <div className="col-12">
               <HtmlTags
                 title={this.documentTitle}
                 path={this.context.router.route.match.url}
-                description={None}
-                image={None}
               />
-              <h5 class="mb-2">
+              <h5 className="mb-2">
                 {i18n.t("inbox")}
-                {inboxRss.match({
-                  some: rss => (
-                    <small>
-                      <a href={rss} title="RSS" rel={relTags}>
-                        <Icon icon="rss" classes="ml-2 text-muted small" />
-                      </a>
-                      <link
-                        rel="alternate"
-                        type="application/atom+xml"
-                        href={rss}
-                      />
-                    </small>
-                  ),
-                  none: <></>,
-                })}
+                {inboxRss && (
+                  <small>
+                    <a href={inboxRss} title="RSS" rel={relTags}>
+                      <Icon icon="rss" classes="ml-2 text-muted small" />
+                    </a>
+                    <link
+                      rel="alternate"
+                      type="application/atom+xml"
+                      href={inboxRss}
+                    />
+                  </small>
+                )}
               </h5>
               {this.state.replies.length +
                 this.state.mentions.length +
@@ -204,7 +191,7 @@ export class Inbox extends Component<any, InboxState> {
                 0 &&
                 this.state.unreadOrAll == UnreadOrAll.Unread && (
                   <button
-                    class="btn btn-secondary mb-2"
+                    className="btn btn-secondary mb-2"
                     onClick={linkEvent(this, this.markAllAsRead)}
                   >
                     {i18n.t("mark_all_as_read")}
@@ -230,7 +217,7 @@ export class Inbox extends Component<any, InboxState> {
 
   unreadOrAllRadios() {
     return (
-      <div class="btn-group btn-group-toggle flex-wrap mb-2">
+      <div className="btn-group btn-group-toggle flex-wrap mb-2">
         <label
           className={`btn btn-outline-secondary pointer
             ${this.state.unreadOrAll == UnreadOrAll.Unread && "active"}
@@ -263,7 +250,7 @@ export class Inbox extends Component<any, InboxState> {
 
   messageTypeRadios() {
     return (
-      <div class="btn-group btn-group-toggle flex-wrap mb-2">
+      <div className="btn-group btn-group-toggle flex-wrap mb-2">
         <label
           className={`btn btn-outline-secondary pointer
             ${this.state.messageType == MessageType.All && "active"}
@@ -323,8 +310,8 @@ export class Inbox extends Component<any, InboxState> {
   selects() {
     return (
       <div className="mb-2">
-        <span class="mr-3">{this.unreadOrAllRadios()}</span>
-        <span class="mr-3">{this.messageTypeRadios()}</span>
+        <span className="mr-3">{this.unreadOrAllRadios()}</span>
+        <span className="mr-3">{this.messageTypeRadios()}</span>
         <CommentSortSelect
           sort={this.state.sort}
           onChange={this.handleSortChange}
@@ -386,14 +373,13 @@ export class Inbox extends Component<any, InboxState> {
               { comment_view: i.view as CommentView, children: [], depth: 0 },
             ]}
             viewType={CommentViewType.Flat}
-            moderators={None}
-            admins={None}
-            maxCommentsShown={None}
             noIndent
             markable
             showCommunity
             showContext
             enableDownvotes={enableDownvotes(this.state.siteRes)}
+            allLanguages={this.state.siteRes.all_languages}
+            siteLanguages={this.state.siteRes.discussion_languages}
           />
         );
       case ReplyEnum.Mention:
@@ -408,14 +394,13 @@ export class Inbox extends Component<any, InboxState> {
               },
             ]}
             viewType={CommentViewType.Flat}
-            moderators={None}
-            admins={None}
-            maxCommentsShown={None}
             noIndent
             markable
             showCommunity
             showContext
             enableDownvotes={enableDownvotes(this.state.siteRes)}
+            allLanguages={this.state.siteRes.all_languages}
+            siteLanguages={this.state.siteRes.discussion_languages}
           />
         );
       case ReplyEnum.Message:
@@ -440,14 +425,13 @@ export class Inbox extends Component<any, InboxState> {
         <CommentNodes
           nodes={commentsToFlatNodes(this.state.replies)}
           viewType={CommentViewType.Flat}
-          moderators={None}
-          admins={None}
-          maxCommentsShown={None}
           noIndent
           markable
           showCommunity
           showContext
           enableDownvotes={enableDownvotes(this.state.siteRes)}
+          allLanguages={this.state.siteRes.all_languages}
+          siteLanguages={this.state.siteRes.discussion_languages}
         />
       </div>
     );
@@ -461,14 +445,13 @@ export class Inbox extends Component<any, InboxState> {
             key={umv.person_mention.id}
             nodes={[{ comment_view: umv, children: [], depth: 0 }]}
             viewType={CommentViewType.Flat}
-            moderators={None}
-            admins={None}
-            maxCommentsShown={None}
             noIndent
             markable
             showCommunity
             showContext
             enableDownvotes={enableDownvotes(this.state.siteRes)}
+            allLanguages={this.state.siteRes.all_languages}
+            siteLanguages={this.state.siteRes.discussion_languages}
           />
         ))}
       </div>
@@ -494,111 +477,112 @@ export class Inbox extends Component<any, InboxState> {
   }
 
   handleUnreadOrAllChange(i: Inbox, event: any) {
-    i.state.unreadOrAll = Number(event.target.value);
-    i.state.page = 1;
-    i.setState(i.state);
+    i.setState({ unreadOrAll: Number(event.target.value), page: 1 });
     i.refetch();
   }
 
   handleMessageTypeChange(i: Inbox, event: any) {
-    i.state.messageType = Number(event.target.value);
-    i.state.page = 1;
-    i.setState(i.state);
+    i.setState({ messageType: Number(event.target.value), page: 1 });
     i.refetch();
   }
 
   static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
     let promises: Promise<any>[] = [];
 
-    let sort = Some(CommentSortType.New);
-
-    // It can be /u/me, or /username/1
-    let repliesForm = new GetReplies({
-      sort,
-      unread_only: Some(true),
-      page: Some(1),
-      limit: Some(fetchLimit),
-      auth: req.auth.unwrap(),
-    });
-    promises.push(req.client.getReplies(repliesForm));
-
-    let personMentionsForm = new GetPersonMentions({
-      sort,
-      unread_only: Some(true),
-      page: Some(1),
-      limit: Some(fetchLimit),
-      auth: req.auth.unwrap(),
-    });
-    promises.push(req.client.getPersonMentions(personMentionsForm));
-
-    let privateMessagesForm = new GetPrivateMessages({
-      unread_only: Some(true),
-      page: Some(1),
-      limit: Some(fetchLimit),
-      auth: req.auth.unwrap(),
-    });
-    promises.push(req.client.getPrivateMessages(privateMessagesForm));
+    let sort: CommentSortType = "New";
+    let auth = req.auth;
+
+    if (auth) {
+      // It can be /u/me, or /username/1
+      let repliesForm: GetReplies = {
+        sort: "New",
+        unread_only: true,
+        page: 1,
+        limit: fetchLimit,
+        auth,
+      };
+      promises.push(req.client.getReplies(repliesForm));
+
+      let personMentionsForm: GetPersonMentions = {
+        sort,
+        unread_only: true,
+        page: 1,
+        limit: fetchLimit,
+        auth,
+      };
+      promises.push(req.client.getPersonMentions(personMentionsForm));
+
+      let privateMessagesForm: GetPrivateMessages = {
+        unread_only: true,
+        page: 1,
+        limit: fetchLimit,
+        auth,
+      };
+      promises.push(req.client.getPrivateMessages(privateMessagesForm));
+    }
 
     return promises;
   }
 
   refetch() {
-    let sort = Some(this.state.sort);
-    let unread_only = Some(this.state.unreadOrAll == UnreadOrAll.Unread);
-    let page = Some(this.state.page);
-    let limit = Some(fetchLimit);
-
-    let repliesForm = new GetReplies({
-      sort,
-      unread_only,
-      page,
-      limit,
-      auth: auth().unwrap(),
-    });
-    WebSocketService.Instance.send(wsClient.getReplies(repliesForm));
-
-    let personMentionsForm = new GetPersonMentions({
-      sort,
-      unread_only,
-      page,
-      limit,
-      auth: auth().unwrap(),
-    });
-    WebSocketService.Instance.send(
-      wsClient.getPersonMentions(personMentionsForm)
-    );
+    let sort = this.state.sort;
+    let unread_only = this.state.unreadOrAll == UnreadOrAll.Unread;
+    let page = this.state.page;
+    let limit = fetchLimit;
+    let auth = myAuth();
+
+    if (auth) {
+      let repliesForm: GetReplies = {
+        sort,
+        unread_only,
+        page,
+        limit,
+        auth,
+      };
+      WebSocketService.Instance.send(wsClient.getReplies(repliesForm));
+
+      let personMentionsForm: GetPersonMentions = {
+        sort,
+        unread_only,
+        page,
+        limit,
+        auth,
+      };
+      WebSocketService.Instance.send(
+        wsClient.getPersonMentions(personMentionsForm)
+      );
 
-    let privateMessagesForm = new GetPrivateMessages({
-      unread_only,
-      page,
-      limit,
-      auth: auth().unwrap(),
-    });
-    WebSocketService.Instance.send(
-      wsClient.getPrivateMessages(privateMessagesForm)
-    );
+      let privateMessagesForm: GetPrivateMessages = {
+        unread_only,
+        page,
+        limit,
+        auth,
+      };
+      WebSocketService.Instance.send(
+        wsClient.getPrivateMessages(privateMessagesForm)
+      );
+    }
   }
 
   handleSortChange(val: CommentSortType) {
-    this.state.sort = val;
-    this.state.page = 1;
-    this.setState(this.state);
+    this.setState({ sort: val, page: 1 });
     this.refetch();
   }
 
   markAllAsRead(i: Inbox) {
-    WebSocketService.Instance.send(
-      wsClient.markAllAsRead({
-        auth: auth().unwrap(),
-      })
-    );
-    i.state.replies = [];
-    i.state.mentions = [];
-    i.state.messages = [];
-    i.state.combined = i.buildCombined();
-    UserService.Instance.unreadInboxCountSub.next(0);
-    window.scrollTo(0, 0);
-    i.setState(i.state);
+    let auth = myAuth();
+    if (auth) {
+      WebSocketService.Instance.send(
+        wsClient.markAllAsRead({
+          auth,
+        })
+      );
+      i.setState({ replies: [], mentions: [], messages: [] });
+      i.setState({ combined: i.buildCombined() });
+      UserService.Instance.unreadInboxCountSub.next(0);
+      window.scrollTo(0, 0);
+      i.setState(i.state);
+    }
   }
 
   sendUnreadCount(read: boolean) {
@@ -619,104 +603,97 @@ export class Inbox extends Component<any, InboxState> {
     } else if (msg.reconnect) {
       this.refetch();
     } else if (op == UserOperation.GetReplies) {
-      let data = wsJsonToRes<GetRepliesResponse>(msg, GetRepliesResponse);
-      this.state.replies = data.replies;
-      this.state.combined = this.buildCombined();
-      this.state.loading = false;
+      let data = wsJsonToRes<GetRepliesResponse>(msg);
+      this.setState({ replies: data.replies });
+      this.setState({ combined: this.buildCombined(), loading: false });
       window.scrollTo(0, 0);
-      this.setState(this.state);
       setupTippy();
     } else if (op == UserOperation.GetPersonMentions) {
-      let data = wsJsonToRes<GetPersonMentionsResponse>(
-        msg,
-        GetPersonMentionsResponse
-      );
-      this.state.mentions = data.mentions;
-      this.state.combined = this.buildCombined();
+      let data = wsJsonToRes<GetPersonMentionsResponse>(msg);
+      this.setState({ mentions: data.mentions });
+      this.setState({ combined: this.buildCombined() });
       window.scrollTo(0, 0);
-      this.setState(this.state);
       setupTippy();
     } else if (op == UserOperation.GetPrivateMessages) {
-      let data = wsJsonToRes<PrivateMessagesResponse>(
-        msg,
-        PrivateMessagesResponse
-      );
-      this.state.messages = data.private_messages;
-      this.state.combined = this.buildCombined();
+      let data = wsJsonToRes<PrivateMessagesResponse>(msg);
+      this.setState({ messages: data.private_messages });
+      this.setState({ combined: this.buildCombined() });
       window.scrollTo(0, 0);
-      this.setState(this.state);
       setupTippy();
     } else if (op == UserOperation.EditPrivateMessage) {
-      let data = wsJsonToRes<PrivateMessageResponse>(
-        msg,
-        PrivateMessageResponse
-      );
-      let found: PrivateMessageView = this.state.messages.find(
+      let data = wsJsonToRes<PrivateMessageResponse>(msg);
+      let found = this.state.messages.find(
         m =>
           m.private_message.id === data.private_message_view.private_message.id
       );
       if (found) {
         let combinedView = this.state.combined.find(
           i => i.id == data.private_message_view.private_message.id
-        ).view as PrivateMessageView;
-        found.private_message.content = combinedView.private_message.content =
-          data.private_message_view.private_message.content;
-        found.private_message.updated = combinedView.private_message.updated =
-          data.private_message_view.private_message.updated;
+        )?.view as PrivateMessageView | undefined;
+        if (combinedView) {
+          found.private_message.content = combinedView.private_message.content =
+            data.private_message_view.private_message.content;
+          found.private_message.updated = combinedView.private_message.updated =
+            data.private_message_view.private_message.updated;
+        }
       }
       this.setState(this.state);
     } else if (op == UserOperation.DeletePrivateMessage) {
-      let data = wsJsonToRes<PrivateMessageResponse>(
-        msg,
-        PrivateMessageResponse
-      );
-      let found: PrivateMessageView = this.state.messages.find(
+      let data = wsJsonToRes<PrivateMessageResponse>(msg);
+      let found = this.state.messages.find(
         m =>
           m.private_message.id === data.private_message_view.private_message.id
       );
       if (found) {
         let combinedView = this.state.combined.find(
           i => i.id == data.private_message_view.private_message.id
-        ).view as PrivateMessageView;
-        found.private_message.deleted = combinedView.private_message.deleted =
-          data.private_message_view.private_message.deleted;
-        found.private_message.updated = combinedView.private_message.updated =
-          data.private_message_view.private_message.updated;
+        )?.view as PrivateMessageView | undefined;
+        if (combinedView) {
+          found.private_message.deleted = combinedView.private_message.deleted =
+            data.private_message_view.private_message.deleted;
+          found.private_message.updated = combinedView.private_message.updated =
+            data.private_message_view.private_message.updated;
+        }
       }
       this.setState(this.state);
     } else if (op == UserOperation.MarkPrivateMessageAsRead) {
-      let data = wsJsonToRes<PrivateMessageResponse>(
-        msg,
-        PrivateMessageResponse
-      );
-      let found: PrivateMessageView = this.state.messages.find(
+      let data = wsJsonToRes<PrivateMessageResponse>(msg);
+      let found = this.state.messages.find(
         m =>
           m.private_message.id === data.private_message_view.private_message.id
       );
 
       if (found) {
         let combinedView = this.state.combined.find(
-          i => i.id == data.private_message_view.private_message.id
-        ).view as PrivateMessageView;
-        found.private_message.updated = combinedView.private_message.updated =
-          data.private_message_view.private_message.updated;
-
-        // If youre in the unread view, just remove it from the list
-        if (
-          this.state.unreadOrAll == UnreadOrAll.Unread &&
-          data.private_message_view.private_message.read
-        ) {
-          this.state.messages = this.state.messages.filter(
-            r =>
-              r.private_message.id !==
-              data.private_message_view.private_message.id
-          );
-          this.state.combined = this.state.combined.filter(
-            r => r.id !== data.private_message_view.private_message.id
-          );
-        } else {
-          found.private_message.read = combinedView.private_message.read =
-            data.private_message_view.private_message.read;
+          i =>
+            i.id == data.private_message_view.private_message.id &&
+            i.type_ == ReplyEnum.Message
+        )?.view as PrivateMessageView | undefined;
+        if (combinedView) {
+          found.private_message.updated = combinedView.private_message.updated =
+            data.private_message_view.private_message.updated;
+
+          // If youre in the unread view, just remove it from the list
+          if (
+            this.state.unreadOrAll == UnreadOrAll.Unread &&
+            data.private_message_view.private_message.read
+          ) {
+            this.setState({
+              messages: this.state.messages.filter(
+                r =>
+                  r.private_message.id !==
+                  data.private_message_view.private_message.id
+              ),
+            });
+            this.setState({
+              combined: this.state.combined.filter(
+                r => r.id !== data.private_message_view.private_message.id
+              ),
+            });
+          } else {
+            found.private_message.read = combinedView.private_message.read =
+              data.private_message_view.private_message.read;
+          }
         }
       }
       this.sendUnreadCount(data.private_message_view.private_message.read);
@@ -728,12 +705,11 @@ export class Inbox extends Component<any, InboxState> {
       op == UserOperation.DeleteComment ||
       op == UserOperation.RemoveComment
     ) {
-      let data = wsJsonToRes<CommentResponse>(msg, CommentResponse);
+      let data = wsJsonToRes<CommentResponse>(msg);
       editCommentRes(data.comment_view, this.state.replies);
       this.setState(this.state);
     } else if (op == UserOperation.MarkCommentReplyAsRead) {
-      let data = wsJsonToRes<CommentReplyResponse>(msg, CommentReplyResponse);
-      console.log(data);
+      let data = wsJsonToRes<CommentReplyResponse>(msg);
 
       let found = this.state.replies.find(
         c => c.comment_reply.id == data.comment_reply_view.comment_reply.id
@@ -741,43 +717,53 @@ export class Inbox extends Component<any, InboxState> {
 
       if (found) {
         let combinedView = this.state.combined.find(
-          i => i.id == data.comment_reply_view.comment_reply.id
-        ).view as CommentReplyView;
-        found.comment.content = combinedView.comment.content =
-          data.comment_reply_view.comment.content;
-        found.comment.updated = combinedView.comment.updated =
-          data.comment_reply_view.comment.updated;
-        found.comment.removed = combinedView.comment.removed =
-          data.comment_reply_view.comment.removed;
-        found.comment.deleted = combinedView.comment.deleted =
-          data.comment_reply_view.comment.deleted;
-        found.counts.upvotes = combinedView.counts.upvotes =
-          data.comment_reply_view.counts.upvotes;
-        found.counts.downvotes = combinedView.counts.downvotes =
-          data.comment_reply_view.counts.downvotes;
-        found.counts.score = combinedView.counts.score =
-          data.comment_reply_view.counts.score;
-
-        // If youre in the unread view, just remove it from the list
-        if (
-          this.state.unreadOrAll == UnreadOrAll.Unread &&
-          data.comment_reply_view.comment_reply.read
-        ) {
-          this.state.replies = this.state.replies.filter(
-            r => r.comment_reply.id !== data.comment_reply_view.comment_reply.id
-          );
-          this.state.combined = this.state.combined.filter(
-            r => r.id !== data.comment_reply_view.comment_reply.id
-          );
-        } else {
-          found.comment_reply.read = combinedView.comment_reply.read =
-            data.comment_reply_view.comment_reply.read;
+          i =>
+            i.id == data.comment_reply_view.comment_reply.id &&
+            i.type_ == ReplyEnum.Reply
+        )?.view as CommentReplyView | undefined;
+        if (combinedView) {
+          found.comment.content = combinedView.comment.content =
+            data.comment_reply_view.comment.content;
+          found.comment.updated = combinedView.comment.updated =
+            data.comment_reply_view.comment.updated;
+          found.comment.removed = combinedView.comment.removed =
+            data.comment_reply_view.comment.removed;
+          found.comment.deleted = combinedView.comment.deleted =
+            data.comment_reply_view.comment.deleted;
+          found.counts.upvotes = combinedView.counts.upvotes =
+            data.comment_reply_view.counts.upvotes;
+          found.counts.downvotes = combinedView.counts.downvotes =
+            data.comment_reply_view.counts.downvotes;
+          found.counts.score = combinedView.counts.score =
+            data.comment_reply_view.counts.score;
+
+          // If youre in the unread view, just remove it from the list
+          if (
+            this.state.unreadOrAll == UnreadOrAll.Unread &&
+            data.comment_reply_view.comment_reply.read
+          ) {
+            this.setState({
+              replies: this.state.replies.filter(
+                r =>
+                  r.comment_reply.id !==
+                  data.comment_reply_view.comment_reply.id
+              ),
+            });
+            this.setState({
+              combined: this.state.combined.filter(
+                r => r.id !== data.comment_reply_view.comment_reply.id
+              ),
+            });
+          } else {
+            found.comment_reply.read = combinedView.comment_reply.read =
+              data.comment_reply_view.comment_reply.read;
+          }
         }
       }
       this.sendUnreadCount(data.comment_reply_view.comment_reply.read);
       this.setState(this.state);
     } else if (op == UserOperation.MarkPersonMentionAsRead) {
-      let data = wsJsonToRes<PersonMentionResponse>(msg, PersonMentionResponse);
+      let data = wsJsonToRes<PersonMentionResponse>(msg);
 
       // TODO this might not be correct, it might need to use the comment id
       let found = this.state.mentions.find(
@@ -786,82 +772,88 @@ export class Inbox extends Component<any, InboxState> {
 
       if (found) {
         let combinedView = this.state.combined.find(
-          i => i.id == data.person_mention_view.person_mention.id
-        ).view as PersonMentionView;
-        found.comment.content = combinedView.comment.content =
-          data.person_mention_view.comment.content;
-        found.comment.updated = combinedView.comment.updated =
-          data.person_mention_view.comment.updated;
-        found.comment.removed = combinedView.comment.removed =
-          data.person_mention_view.comment.removed;
-        found.comment.deleted = combinedView.comment.deleted =
-          data.person_mention_view.comment.deleted;
-        found.counts.upvotes = combinedView.counts.upvotes =
-          data.person_mention_view.counts.upvotes;
-        found.counts.downvotes = combinedView.counts.downvotes =
-          data.person_mention_view.counts.downvotes;
-        found.counts.score = combinedView.counts.score =
-          data.person_mention_view.counts.score;
-
-        // If youre in the unread view, just remove it from the list
-        if (
-          this.state.unreadOrAll == UnreadOrAll.Unread &&
-          data.person_mention_view.person_mention.read
-        ) {
-          this.state.mentions = this.state.mentions.filter(
-            r =>
-              r.person_mention.id !== data.person_mention_view.person_mention.id
-          );
-          this.state.combined = this.state.combined.filter(
-            r => r.id !== data.person_mention_view.person_mention.id
-          );
-        } else {
-          // TODO test to make sure these mentions are getting marked as read
-          found.person_mention.read = combinedView.person_mention.read =
-            data.person_mention_view.person_mention.read;
+          i =>
+            i.id == data.person_mention_view.person_mention.id &&
+            i.type_ == ReplyEnum.Mention
+        )?.view as PersonMentionView | undefined;
+        if (combinedView) {
+          found.comment.content = combinedView.comment.content =
+            data.person_mention_view.comment.content;
+          found.comment.updated = combinedView.comment.updated =
+            data.person_mention_view.comment.updated;
+          found.comment.removed = combinedView.comment.removed =
+            data.person_mention_view.comment.removed;
+          found.comment.deleted = combinedView.comment.deleted =
+            data.person_mention_view.comment.deleted;
+          found.counts.upvotes = combinedView.counts.upvotes =
+            data.person_mention_view.counts.upvotes;
+          found.counts.downvotes = combinedView.counts.downvotes =
+            data.person_mention_view.counts.downvotes;
+          found.counts.score = combinedView.counts.score =
+            data.person_mention_view.counts.score;
+
+          // If youre in the unread view, just remove it from the list
+          if (
+            this.state.unreadOrAll == UnreadOrAll.Unread &&
+            data.person_mention_view.person_mention.read
+          ) {
+            this.setState({
+              mentions: this.state.mentions.filter(
+                r =>
+                  r.person_mention.id !==
+                  data.person_mention_view.person_mention.id
+              ),
+            });
+            this.setState({
+              combined: this.state.combined.filter(
+                r => r.id !== data.person_mention_view.person_mention.id
+              ),
+            });
+          } else {
+            // TODO test to make sure these mentions are getting marked as read
+            found.person_mention.read = combinedView.person_mention.read =
+              data.person_mention_view.person_mention.read;
+          }
         }
       }
       this.sendUnreadCount(data.person_mention_view.person_mention.read);
       this.setState(this.state);
     } else if (op == UserOperation.CreatePrivateMessage) {
-      let data = wsJsonToRes<PrivateMessageResponse>(
-        msg,
-        PrivateMessageResponse
-      );
-      UserService.Instance.myUserInfo.match({
-        some: mui => {
-          if (
-            data.private_message_view.recipient.id ==
-            mui.local_user_view.person.id
-          ) {
-            this.state.messages.unshift(data.private_message_view);
-            this.state.combined.unshift(
-              this.messageToReplyType(data.private_message_view)
-            );
-            this.setState(this.state);
-          }
-        },
-        none: void 0,
-      });
+      let data = wsJsonToRes<PrivateMessageResponse>(msg);
+      let mui = UserService.Instance.myUserInfo;
+      if (
+        data.private_message_view.recipient.id == mui?.local_user_view.person.id
+      ) {
+        this.state.messages.unshift(data.private_message_view);
+        this.state.combined.unshift(
+          this.messageToReplyType(data.private_message_view)
+        );
+        this.setState(this.state);
+      }
     } else if (op == UserOperation.SaveComment) {
-      let data = wsJsonToRes<CommentResponse>(msg, CommentResponse);
+      let data = wsJsonToRes<CommentResponse>(msg);
       saveCommentRes(data.comment_view, this.state.replies);
       this.setState(this.state);
       setupTippy();
     } else if (op == UserOperation.CreateCommentLike) {
-      let data = wsJsonToRes<CommentResponse>(msg, CommentResponse);
+      let data = wsJsonToRes<CommentResponse>(msg);
       createCommentLikeRes(data.comment_view, this.state.replies);
       this.setState(this.state);
     } else if (op == UserOperation.BlockPerson) {
-      let data = wsJsonToRes<BlockPersonResponse>(msg, BlockPersonResponse);
+      let data = wsJsonToRes<BlockPersonResponse>(msg);
       updatePersonBlock(data);
     } else if (op == UserOperation.CreatePostReport) {
-      let data = wsJsonToRes<PostReportResponse>(msg, PostReportResponse);
+      let data = wsJsonToRes<PostReportResponse>(msg);
       if (data) {
         toast(i18n.t("report_created"));
       }
     } else if (op == UserOperation.CreateCommentReport) {
-      let data = wsJsonToRes<CommentReportResponse>(msg, CommentReportResponse);
+      let data = wsJsonToRes<CommentReportResponse>(msg);
+      if (data) {
+        toast(i18n.t("report_created"));
+      }
+    } else if (op == UserOperation.CreatePrivateMessageReport) {
+      let data = wsJsonToRes<PrivateMessageReportResponse>(msg);
       if (data) {
         toast(i18n.t("report_created"));
       }