]> Untitled Git - lemmy.git/commitdiff
ui.components: split user component up to fix duplicate requests
authorderek <wwsage@gmail.com>
Sun, 12 Jul 2020 08:00:10 +0000 (04:00 -0400)
committerderek <wwsage@gmail.com>
Tue, 14 Jul 2020 00:14:01 +0000 (20:14 -0400)
Replace componentWillReceiveProps with getDerivedState and pass state as props to new component

ui/src/components/user-details.tsx [new file with mode: 0644]
ui/src/components/user.tsx
ui/src/interfaces.ts

diff --git a/ui/src/components/user-details.tsx b/ui/src/components/user-details.tsx
new file mode 100644 (file)
index 0000000..a622985
--- /dev/null
@@ -0,0 +1,270 @@
+import { Component } from 'inferno';
+import { WebSocketService, UserService } from '../services';
+import { Subscription } from 'rxjs';
+import { retryWhen, delay, take, last } from 'rxjs/operators';
+import { i18n } from '../i18next';
+import {
+  UserOperation,
+  Post,
+  Comment,
+  CommunityUser,
+  SortType,
+  UserDetailsResponse,
+  UserView,
+  WebSocketJsonResponse,
+  UserDetailsView,
+  CommentResponse,
+  BanUserResponse,
+  PostResponse,
+  AddAdminResponse,
+} from '../interfaces';
+import {
+  wsJsonToRes,
+  toast,
+  commentsToFlatNodes,
+  setupTippy,
+  editCommentRes,
+  saveCommentRes,
+  createCommentLikeRes,
+  createPostLikeFindRes,
+} from '../utils';
+import { PostListing } from './post-listing';
+import { CommentNodes } from './comment-nodes';
+
+interface UserDetailsProps {
+  username?: string;
+  user_id?: number;
+  page: number;
+  limit: number;
+  sort: string;
+  enableDownvotes: boolean;
+  enableNsfw: boolean;
+  view: UserDetailsView;
+}
+
+interface UserDetailsState {
+  follows: Array<CommunityUser>;
+  moderates: Array<CommunityUser>;
+  comments: Array<Comment>;
+  posts: Array<Post>;
+  saved?: Array<Post>;
+  admins: Array<UserView>;
+}
+
+export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
+  private subscription: Subscription;
+  constructor(props: any, context: any) {
+    super(props, context);
+
+    this.state = {
+      follows: [],
+      moderates: [],
+      comments: [],
+      posts: [],
+      saved: [],
+      admins: [],
+    };
+
+    this.subscription = WebSocketService.Instance.subject
+      .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
+      .subscribe(
+        msg => this.parseMessage(msg),
+        err => console.error(err),
+        () => console.log('complete')
+      );
+  }
+
+  componentWillUnmount() {
+    this.subscription.unsubscribe();
+  }
+
+  componentDidMount() {
+    this.fetchUserData();
+  }
+
+  componentDidUpdate(lastProps: UserDetailsProps) {
+    for (const key of Object.keys(lastProps)) {
+      if (lastProps[key] !== this.props[key]) {
+        this.fetchUserData();
+        break;
+      }
+    }
+    setupTippy();
+  }
+
+  fetchUserData() {
+    WebSocketService.Instance.getUserDetails({
+      user_id: this.props.user_id,
+      username: this.props.username,
+      sort: this.props.sort,
+      saved_only: this.props.view === UserDetailsView.Saved,
+      page: this.props.page,
+      limit: this.props.limit,
+    });
+  }
+
+  render() {
+    return this.viewSelector(this.props.view);
+  }
+
+  viewSelector(view: UserDetailsView) {
+    if (view === UserDetailsView.Overview || view === UserDetailsView.Saved) {
+      return this.overview();
+    }
+    if (view === UserDetailsView.Comments) {
+      return this.comments();
+    }
+    if (view === UserDetailsView.Posts) {
+      return this.posts();
+    }
+  }
+
+  overview() {
+    const comments = this.state.comments.map((c: Comment) => {
+      return { type: 'comments', data: c };
+    });
+    const posts = this.state.posts.map((p: Post) => {
+      return { type: 'posts', data: p };
+    });
+
+    const combined: Array<{ type: string; data: Comment | Post }> = [
+      ...comments,
+      ...posts,
+    ];
+
+    // Sort it
+    if (SortType[this.props.sort] === SortType.New) {
+      combined.sort((a, b) => b.data.published.localeCompare(a.data.published));
+    } else {
+      combined.sort((a, b) => b.data.score - a.data.score);
+    }
+
+    return (
+      <div>
+        {combined.map(i => (
+          <div>
+            {i.type === 'posts' ? (
+              <PostListing
+                post={i.data as Post}
+                admins={this.state.admins}
+                showCommunity
+                enableDownvotes={this.props.enableDownvotes}
+                enableNsfw={this.props.enableNsfw}
+              />
+            ) : (
+              <CommentNodes
+                nodes={[{ comment: i.data as Comment }]}
+                admins={this.state.admins}
+                noIndent
+                showContext
+                enableDownvotes={this.props.enableDownvotes}
+              />
+            )}
+          </div>
+        ))}
+      </div>
+    );
+  }
+
+  comments() {
+    return (
+      <div>
+        <CommentNodes
+          nodes={commentsToFlatNodes(this.state.comments)}
+          admins={this.state.admins}
+          noIndent
+          showContext
+          enableDownvotes={this.props.enableDownvotes}
+        />
+      </div>
+    );
+  }
+
+  posts() {
+    return (
+      <div>
+        {this.state.posts.map(post => (
+          <PostListing
+            post={post}
+            admins={this.state.admins}
+            showCommunity
+            enableDownvotes={this.props.enableDownvotes}
+            enableNsfw={this.props.enableNsfw}
+          />
+        ))}
+      </div>
+    );
+  }
+
+  parseMessage(msg: WebSocketJsonResponse) {
+    const res = wsJsonToRes(msg);
+
+    if (msg.error) {
+      toast(i18n.t(msg.error), 'danger');
+      if (msg.error == 'couldnt_find_that_username_or_email') {
+        this.context.router.history.push('/');
+      }
+      return;
+    } else if (msg.reconnect) {
+      this.fetchUserData();
+    } else if (res.op == UserOperation.GetUserDetails) {
+      const data = res.data as UserDetailsResponse;
+      this.setState({
+        comments: data.comments,
+        follows: data.follows,
+        moderates: data.moderates,
+        posts: data.posts,
+        admins: data.admins,
+      });
+    } else if (res.op == UserOperation.CreateCommentLike) {
+      const data = res.data as CommentResponse;
+      createCommentLikeRes(data, this.state.comments);
+      this.setState({
+        comments: this.state.comments,
+      });
+    } else if (res.op == UserOperation.EditComment) {
+      const data = res.data as CommentResponse;
+      editCommentRes(data, this.state.comments);
+      this.setState({
+        comments: this.state.comments,
+      });
+    } else if (res.op == UserOperation.CreateComment) {
+      const data = res.data as CommentResponse;
+      if (
+        UserService.Instance.user &&
+        data.comment.creator_id == UserService.Instance.user.id
+      ) {
+        toast(i18n.t('reply_sent'));
+      }
+    } else if (res.op == UserOperation.SaveComment) {
+      const data = res.data as CommentResponse;
+      saveCommentRes(data, this.state.comments);
+      this.setState({
+        comments: this.state.comments,
+      });
+    } else if (res.op == UserOperation.CreatePostLike) {
+      const data = res.data as PostResponse;
+      createPostLikeFindRes(data, this.state.posts);
+      this.setState({
+        posts: this.state.posts,
+      });
+    } else if (res.op == UserOperation.BanUser) {
+      const data = res.data as BanUserResponse;
+      this.state.comments
+        .filter(c => c.creator_id == data.user.id)
+        .forEach(c => (c.banned = data.banned));
+      this.state.posts
+        .filter(c => c.creator_id == data.user.id)
+        .forEach(c => (c.banned = data.banned));
+      this.setState({
+        posts: this.state.posts,
+        comments: this.state.comments,
+      });
+    } else if (res.op == UserOperation.AddAdmin) {
+      const data = res.data as AddAdminResponse;
+      this.setState({
+        admins: data.admins,
+      });
+    }
+  }
+}
index 854dd6efdbefbe63984db88ba4883dc735f81422..25aaf22086c527a84dc7f7fa6a5091e43b391a67 100644 (file)
@@ -4,24 +4,18 @@ import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
 import {
   UserOperation,
-  Post,
-  Comment,
   CommunityUser,
-  GetUserDetailsForm,
   SortType,
   ListingType,
-  UserDetailsResponse,
   UserView,
-  CommentResponse,
   UserSettingsForm,
   LoginResponse,
-  BanUserResponse,
-  AddAdminResponse,
   DeleteAccountForm,
-  PostResponse,
   WebSocketJsonResponse,
   GetSiteResponse,
   Site,
+  UserDetailsView,
+  UserDetailsResponse,
 } from '../interfaces';
 import { WebSocketService, UserService } from '../services';
 import {
@@ -34,28 +28,15 @@ import {
   languages,
   showAvatars,
   toast,
-  editCommentRes,
-  saveCommentRes,
-  createCommentLikeRes,
-  createPostLikeFindRes,
-  commentsToFlatNodes,
   setupTippy,
 } from '../utils';
-import { PostListing } from './post-listing';
 import { UserListing } from './user-listing';
 import { SortSelect } from './sort-select';
 import { ListingTypeSelect } from './listing-type-select';
-import { CommentNodes } from './comment-nodes';
 import { MomentTime } from './moment-time';
 import { i18n } from '../i18next';
 import moment from 'moment';
-
-enum View {
-  Overview,
-  Comments,
-  Posts,
-  Saved,
-}
+import { UserDetails } from './user-details';
 
 interface UserState {
   user: UserView;
@@ -63,11 +44,7 @@ interface UserState {
   username: string;
   follows: Array<CommunityUser>;
   moderates: Array<CommunityUser>;
-  comments: Array<Comment>;
-  posts: Array<Post>;
-  saved?: Array<Post>;
-  admins: Array<UserView>;
-  view: View;
+  view: UserDetailsView;
   sort: SortType;
   page: number;
   loading: boolean;
@@ -102,14 +79,11 @@ export class User extends Component<any, UserState> {
     username: null,
     follows: [],
     moderates: [],
-    comments: [],
-    posts: [],
-    admins: [],
-    loading: true,
+    loading: false,
     avatarLoading: false,
-    view: this.getViewFromProps(this.props),
-    sort: this.getSortTypeFromProps(this.props),
-    page: this.getPageFromProps(this.props),
+    view: User.getViewFromProps(this.props.match.view),
+    sort: User.getSortTypeFromProps(this.props.match.sort),
+    page: User.getPageFromProps(this.props.match.page),
     userSettingsForm: {
       show_nsfw: null,
       theme: null,
@@ -145,7 +119,7 @@ export class User extends Component<any, UserState> {
   constructor(props: any, context: any) {
     super(props, context);
 
-    this.state = this.emptyState;
+    this.state = Object.assign({}, this.emptyState);
     this.handleSortChange = this.handleSortChange.bind(this);
     this.handleUserSettingsSortTypeChange = this.handleUserSettingsSortTypeChange.bind(
       this
@@ -154,7 +128,7 @@ export class User extends Component<any, UserState> {
       this
     );
 
-    this.state.user_id = Number(this.props.match.params.id);
+    this.state.user_id = Number(this.props.match.params.id) || null;
     this.state.username = this.props.match.params.username;
 
     this.subscription = WebSocketService.Instance.subject
@@ -165,7 +139,6 @@ export class User extends Component<any, UserState> {
         () => console.log('complete')
       );
 
-    this.refetch();
     WebSocketService.Instance.getSite();
   }
 
@@ -176,38 +149,32 @@ export class User extends Component<any, UserState> {
     );
   }
 
-  getViewFromProps(props: any): View {
-    return props.match.params.view
-      ? View[capitalizeFirstLetter(props.match.params.view)]
-      : View.Overview;
+  static getViewFromProps(view: any): UserDetailsView {
+    return view
+      ? UserDetailsView[capitalizeFirstLetter(view)]
+      : UserDetailsView.Overview;
   }
 
-  getSortTypeFromProps(props: any): SortType {
-    return props.match.params.sort
-      ? routeSortTypeToEnum(props.match.params.sort)
-      : SortType.New;
+  static getSortTypeFromProps(sort: any): SortType {
+    return sort ? routeSortTypeToEnum(sort) : SortType.New;
   }
 
-  getPageFromProps(props: any): number {
-    return props.match.params.page ? Number(props.match.params.page) : 1;
+  static getPageFromProps(page: any): number {
+    return page ? Number(page) : 1;
   }
 
   componentWillUnmount() {
     this.subscription.unsubscribe();
   }
 
-  // Necessary for back button for some reason
-  componentWillReceiveProps(nextProps: any) {
-    if (
-      nextProps.history.action == 'POP' ||
-      nextProps.history.action == 'PUSH'
-    ) {
-      this.state.view = this.getViewFromProps(nextProps);
-      this.state.sort = this.getSortTypeFromProps(nextProps);
-      this.state.page = this.getPageFromProps(nextProps);
-      this.setState(this.state);
-      this.refetch();
-    }
+  static getDerivedStateFromProps(props) {
+    return {
+      view: this.getViewFromProps(props.match.params.view),
+      sort: this.getSortTypeFromProps(props.match.params.sort),
+      page: this.getPageFromProps(props.match.params.page),
+      user_id: Number(props.match.params.id) || null,
+      username: props.match.params.username,
+    };
   }
 
   componentDidUpdate(lastProps: any, _lastState: UserState, _snapshot: any) {
@@ -219,6 +186,8 @@ export class User extends Component<any, UserState> {
       // Couldnt get a refresh working. This does for now.
       location.reload();
     }
+    document.title = `/u/${this.state.username} - ${this.state.site.name}`;
+    setupTippy();
   }
 
   render() {
@@ -242,13 +211,20 @@ export class User extends Component<any, UserState> {
                     class="rounded-circle mr-2"
                   />
                 )}
-                <span>/u/{this.state.user.name}</span>
+                <span>/u/{this.state.username}</span>
               </h5>
               {this.selects()}
-              {this.state.view == View.Overview && this.overview()}
-              {this.state.view == View.Comments && this.comments()}
-              {this.state.view == View.Posts && this.posts()}
-              {this.state.view == View.Saved && this.overview()}
+              <UserDetails
+                user_id={this.state.user_id}
+                username={this.state.username}
+                sort={SortType[this.state.sort]}
+                page={this.state.page}
+                limit={fetchLimit}
+                enableDownvotes={this.state.site.enable_downvotes}
+                enableNsfw={this.state.site.enable_nsfw}
+                view={this.state.view}
+                key={this.state.user_id || this.state.username}
+              />
               {this.paginator()}
             </div>
             <div class="col-12 col-md-4">
@@ -268,52 +244,52 @@ export class User extends Component<any, UserState> {
       <div class="btn-group btn-group-toggle">
         <label
           className={`btn btn-sm btn-secondary pointer btn-outline-light
-            ${this.state.view == View.Overview && 'active'}
+            ${this.state.view == UserDetailsView.Overview && 'active'}
           `}
         >
           <input
             type="radio"
-            value={View.Overview}
-            checked={this.state.view == View.Overview}
+            value={UserDetailsView.Overview}
+            checked={this.state.view === UserDetailsView.Overview}
             onChange={linkEvent(this, this.handleViewChange)}
           />
           {i18n.t('overview')}
         </label>
         <label
           className={`btn btn-sm btn-secondary pointer btn-outline-light
-            ${this.state.view == View.Comments && 'active'}
+            ${this.state.view == UserDetailsView.Comments && 'active'}
           `}
         >
           <input
             type="radio"
-            value={View.Comments}
-            checked={this.state.view == View.Comments}
+            value={UserDetailsView.Comments}
+            checked={this.state.view == UserDetailsView.Comments}
             onChange={linkEvent(this, this.handleViewChange)}
           />
           {i18n.t('comments')}
         </label>
         <label
           className={`btn btn-sm btn-secondary pointer btn-outline-light
-            ${this.state.view == View.Posts && 'active'}
+            ${this.state.view == UserDetailsView.Posts && 'active'}
           `}
         >
           <input
             type="radio"
-            value={View.Posts}
-            checked={this.state.view == View.Posts}
+            value={UserDetailsView.Posts}
+            checked={this.state.view == UserDetailsView.Posts}
             onChange={linkEvent(this, this.handleViewChange)}
           />
           {i18n.t('posts')}
         </label>
         <label
           className={`btn btn-sm btn-secondary pointer btn-outline-light
-            ${this.state.view == View.Saved && 'active'}
+            ${this.state.view == UserDetailsView.Saved && 'active'}
           `}
         >
           <input
             type="radio"
-            value={View.Saved}
-            checked={this.state.view == View.Saved}
+            value={UserDetailsView.Saved}
+            checked={this.state.view == UserDetailsView.Saved}
             onChange={linkEvent(this, this.handleViewChange)}
           />
           {i18n.t('saved')}
@@ -347,84 +323,6 @@ export class User extends Component<any, UserState> {
     );
   }
 
-  overview() {
-    let combined: Array<{ type_: string; data: Comment | Post }> = [];
-    let comments = this.state.comments.map(e => {
-      return { type_: 'comments', data: e };
-    });
-    let posts = this.state.posts.map(e => {
-      return { type_: 'posts', data: e };
-    });
-
-    combined.push(...comments);
-    combined.push(...posts);
-
-    // Sort it
-    if (this.state.sort == SortType.New) {
-      combined.sort((a, b) => b.data.published.localeCompare(a.data.published));
-    } else {
-      combined.sort((a, b) => b.data.score - a.data.score);
-    }
-
-    return (
-      <div>
-        {combined.map(i => (
-          <div>
-            {i.type_ == 'posts' ? (
-              <PostListing
-                post={i.data as Post}
-                admins={this.state.admins}
-                showCommunity
-                enableDownvotes={this.state.site.enable_downvotes}
-                enableNsfw={this.state.site.enable_nsfw}
-              />
-            ) : (
-              <CommentNodes
-                nodes={[{ comment: i.data as Comment }]}
-                admins={this.state.admins}
-                noIndent
-                showCommunity
-                showContext
-                enableDownvotes={this.state.site.enable_downvotes}
-              />
-            )}
-          </div>
-        ))}
-      </div>
-    );
-  }
-
-  comments() {
-    return (
-      <div>
-        <CommentNodes
-          nodes={commentsToFlatNodes(this.state.comments)}
-          admins={this.state.admins}
-          noIndent
-          showCommunity
-          showContext
-          enableDownvotes={this.state.site.enable_downvotes}
-        />
-      </div>
-    );
-  }
-
-  posts() {
-    return (
-      <div>
-        {this.state.posts.map(post => (
-          <PostListing
-            post={post}
-            admins={this.state.admins}
-            showCommunity
-            enableDownvotes={this.state.site.enable_downvotes}
-            enableNsfw={this.state.site.enable_nsfw}
-          />
-        ))}
-      </div>
-    );
-  }
-
   userInfo() {
     let user = this.state.user;
     return (
@@ -920,58 +818,43 @@ export class User extends Component<any, UserState> {
   }
 
   updateUrl() {
-    let viewStr = View[this.state.view].toLowerCase();
+    let viewStr = UserDetailsView[this.state.view].toLowerCase();
     let sortStr = SortType[this.state.sort].toLowerCase();
     this.props.history.push(
-      `/u/${this.state.user.name}/view/${viewStr}/sort/${sortStr}/page/${this.state.page}`
+      `/u/${this.state.username}/view/${viewStr}/sort/${sortStr}/page/${this.state.page}`
     );
+    this.setState(this.state);
   }
 
   nextPage(i: User) {
     i.state.page++;
-    i.setState(i.state);
     i.updateUrl();
-    i.refetch();
   }
 
   prevPage(i: User) {
     i.state.page--;
-    i.setState(i.state);
     i.updateUrl();
-    i.refetch();
-  }
-
-  refetch() {
-    let form: GetUserDetailsForm = {
-      user_id: this.state.user_id,
-      username: this.state.username,
-      sort: SortType[this.state.sort],
-      saved_only: this.state.view == View.Saved,
-      page: this.state.page,
-      limit: fetchLimit,
-    };
-    WebSocketService.Instance.getUserDetails(form);
   }
 
   handleSortChange(val: SortType) {
     this.state.sort = val;
     this.state.page = 1;
-    this.setState(this.state);
     this.updateUrl();
-    this.refetch();
   }
 
   handleViewChange(i: User, event: any) {
     i.state.view = Number(event.target.value);
     i.state.page = 1;
-    i.setState(i.state);
     i.updateUrl();
-    i.refetch();
   }
 
   handleUserSettingsShowNsfwChange(i: User, event: any) {
-    i.state.userSettingsForm.show_nsfw = event.target.checked;
-    i.setState(i.state);
+    i.setState({
+      userSettingsForm: {
+        ...i.state.userSettingsForm,
+        show_nsfw: event.target.checked,
+      },
+    });
   }
 
   handleUserSettingsShowAvatarsChange(i: User, event: any) {
@@ -1136,102 +1019,66 @@ export class User extends Component<any, UserState> {
   }
 
   parseMessage(msg: WebSocketJsonResponse) {
-    console.log(msg);
-    let res = wsJsonToRes(msg);
+    const res = wsJsonToRes(msg);
     if (msg.error) {
       toast(i18n.t(msg.error), 'danger');
-      this.state.deleteAccountLoading = false;
-      this.state.avatarLoading = false;
-      this.state.userSettingsLoading = false;
       if (msg.error == 'couldnt_find_that_username_or_email') {
         this.context.router.history.push('/');
       }
-      this.setState(this.state);
+      this.setState({
+        deleteAccountLoading: false,
+        avatarLoading: false,
+        userSettingsLoading: false,
+      });
       return;
-    } else if (msg.reconnect) {
-      this.refetch();
     } else if (res.op == UserOperation.GetUserDetails) {
-      let data = res.data as UserDetailsResponse;
-      this.state.user = data.user;
-      this.state.comments = data.comments;
-      this.state.follows = data.follows;
-      this.state.moderates = data.moderates;
-      this.state.posts = data.posts;
-      this.state.admins = data.admins;
-      this.state.loading = false;
-      if (this.isCurrentUser) {
-        this.state.userSettingsForm.show_nsfw =
-          UserService.Instance.user.show_nsfw;
-        this.state.userSettingsForm.theme = UserService.Instance.user.theme
-          ? UserService.Instance.user.theme
-          : 'darkly';
-        this.state.userSettingsForm.default_sort_type =
-          UserService.Instance.user.default_sort_type;
-        this.state.userSettingsForm.default_listing_type =
-          UserService.Instance.user.default_listing_type;
-        this.state.userSettingsForm.lang = UserService.Instance.user.lang;
-        this.state.userSettingsForm.avatar = UserService.Instance.user.avatar;
-        this.state.userSettingsForm.email = this.state.user.email;
-        this.state.userSettingsForm.send_notifications_to_email = this.state.user.send_notifications_to_email;
-        this.state.userSettingsForm.show_avatars =
-          UserService.Instance.user.show_avatars;
-        this.state.userSettingsForm.matrix_user_id = this.state.user.matrix_user_id;
-      }
-      document.title = `/u/${this.state.user.name} - ${this.state.site.name}`;
-      window.scrollTo(0, 0);
-      this.setState(this.state);
-      setupTippy();
-    } else if (res.op == UserOperation.EditComment) {
-      let data = res.data as CommentResponse;
-      editCommentRes(data, this.state.comments);
-      this.setState(this.state);
-    } else if (res.op == UserOperation.CreateComment) {
-      let data = res.data as CommentResponse;
-      if (
-        UserService.Instance.user &&
-        data.comment.creator_id == UserService.Instance.user.id
-      ) {
-        toast(i18n.t('reply_sent'));
+      // Since the UserDetails contains posts/comments as well as some general user info we listen here as well
+      // and set the parent state if it is not set or differs
+      const data = res.data as UserDetailsResponse;
+
+      if (this.state.user.id !== data.user.id) {
+        this.state.user = data.user;
+        this.state.follows = data.follows;
+        this.state.moderates = data.moderates;
+
+        if (this.isCurrentUser) {
+          this.state.userSettingsForm.show_nsfw =
+            UserService.Instance.user.show_nsfw;
+          this.state.userSettingsForm.theme = UserService.Instance.user.theme
+            ? UserService.Instance.user.theme
+            : 'darkly';
+          this.state.userSettingsForm.default_sort_type =
+            UserService.Instance.user.default_sort_type;
+          this.state.userSettingsForm.default_listing_type =
+            UserService.Instance.user.default_listing_type;
+          this.state.userSettingsForm.lang = UserService.Instance.user.lang;
+          this.state.userSettingsForm.avatar = UserService.Instance.user.avatar;
+          this.state.userSettingsForm.email = this.state.user.email;
+          this.state.userSettingsForm.send_notifications_to_email = this.state.user.send_notifications_to_email;
+          this.state.userSettingsForm.show_avatars =
+            UserService.Instance.user.show_avatars;
+          this.state.userSettingsForm.matrix_user_id = this.state.user.matrix_user_id;
+        }
+        this.setState(this.state);
       }
-    } else if (res.op == UserOperation.SaveComment) {
-      let data = res.data as CommentResponse;
-      saveCommentRes(data, this.state.comments);
-      this.setState(this.state);
-    } else if (res.op == UserOperation.CreateCommentLike) {
-      let data = res.data as CommentResponse;
-      createCommentLikeRes(data, this.state.comments);
-      this.setState(this.state);
-    } else if (res.op == UserOperation.CreatePostLike) {
-      let data = res.data as PostResponse;
-      createPostLikeFindRes(data, this.state.posts);
-      this.setState(this.state);
-    } else if (res.op == UserOperation.BanUser) {
-      let data = res.data as BanUserResponse;
-      this.state.comments
-        .filter(c => c.creator_id == data.user.id)
-        .forEach(c => (c.banned = data.banned));
-      this.state.posts
-        .filter(c => c.creator_id == data.user.id)
-        .forEach(c => (c.banned = data.banned));
-      this.setState(this.state);
-    } else if (res.op == UserOperation.AddAdmin) {
-      let data = res.data as AddAdminResponse;
-      this.state.admins = data.admins;
-      this.setState(this.state);
     } else if (res.op == UserOperation.SaveUserSettings) {
-      let data = res.data as LoginResponse;
-      this.state.userSettingsLoading = false;
-      this.setState(this.state);
+      const data = res.data as LoginResponse;
       UserService.Instance.login(data);
+      this.setState({
+        userSettingsLoading: false,
+      });
+      window.scrollTo(0, 0);
     } else if (res.op == UserOperation.DeleteAccount) {
-      this.state.deleteAccountLoading = false;
-      this.state.deleteAccountShowConfirm = false;
-      this.setState(this.state);
+      this.setState({
+        deleteAccountLoading: false,
+        deleteAccountShowConfirm: false,
+      });
       this.context.router.history.push('/');
     } else if (res.op == UserOperation.GetSite) {
-      let data = res.data as GetSiteResponse;
-      this.state.site = data.site;
-      this.setState(this.state);
+      const data = res.data as GetSiteResponse;
+      this.setState({
+        site: data.site,
+      });
     }
   }
 }
index 1f2813021b9cdf47db9eda6365736c30188b8e78..dc860e0684acb03b3a2b9635a272772ee6eb83ab 100644 (file)
@@ -937,3 +937,10 @@ export interface WebSocketJsonResponse {
   error?: string;
   reconnect?: boolean;
 }
+
+export enum UserDetailsView {
+  Overview,
+  Comments,
+  Posts,
+  Saved,
+}