mirror of https://github.com/LemmyNet/lemmy
ui.components: split user component up to fix duplicate requests
Replace componentWillReceiveProps with getDerivedState and pass state as props to new componentpull/959/head
parent
d71897620c
commit
f1d01f4fa0
@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue