import { Component, linkEvent } from 'inferno'; import { Link } from 'inferno-router'; import { Subscription } from "rxjs"; import { retryWhen, delay, take } from 'rxjs/operators'; import { UserOperation, Post, Comment, CommunityUser, GetUserDetailsForm, SortType, UserDetailsResponse, UserView, CommentResponse, UserSettingsForm, LoginResponse, BanUserResponse, AddAdminResponse } from '../interfaces'; import { WebSocketService, UserService } from '../services'; import { msgOp, fetchLimit, routeSortTypeToEnum, capitalizeFirstLetter, themes, setTheme } from '../utils'; import { PostListing } from './post-listing'; import { CommentNodes } from './comment-nodes'; import { MomentTime } from './moment-time'; import { i18n } from '../i18next'; import { T } from 'inferno-i18next'; enum View { Overview, Comments, Posts, Saved } interface UserState { user: UserView; user_id: number; username: string; follows: Array; moderates: Array; comments: Array; posts: Array; saved?: Array; admins: Array; view: View; sort: SortType; page: number; loading: boolean; userSettingsForm: UserSettingsForm; userSettingsLoading: boolean; } export class User extends Component { private subscription: Subscription; private emptyState: UserState = { user: { id: null, name: null, fedi_name: null, published: null, number_of_posts: null, post_score: null, number_of_comments: null, comment_score: null, banned: null, }, user_id: null, username: null, follows: [], moderates: [], comments: [], posts: [], admins: [], loading: true, view: this.getViewFromProps(this.props), sort: this.getSortTypeFromProps(this.props), page: this.getPageFromProps(this.props), userSettingsForm: { show_nsfw: null, theme: null, auth: null, }, userSettingsLoading: null, } constructor(props: any, context: any) { super(props, context); this.state = this.emptyState; this.state.user_id = Number(this.props.match.params.id); this.state.username = this.props.match.params.username; 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') ); this.refetch(); } get isCurrentUser() { return UserService.Instance.user && UserService.Instance.user.id == this.state.user.id; } getViewFromProps(props: any): View { return (props.match.params.view) ? View[capitalizeFirstLetter(props.match.params.view)] : View.Overview; } getSortTypeFromProps(props: any): SortType { return (props.match.params.sort) ? routeSortTypeToEnum(props.match.params.sort) : SortType.New; } getPageFromProps(props: any): number { return (props.match.params.page) ? Number(props.match.params.page) : 1; } componentWillUnmount() { this.subscription.unsubscribe(); } // Necessary for back button for some reason componentWillReceiveProps(nextProps: any) { if (nextProps.history.action == 'POP') { this.state = this.emptyState; this.state.view = this.getViewFromProps(nextProps); this.state.sort = this.getSortTypeFromProps(nextProps); this.state.page = this.getPageFromProps(nextProps); this.refetch(); } } render() { return (
{this.state.loading ?
:
/u/{this.state.user.name}
{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() } {this.paginator()}
{this.userInfo()} {this.isCurrentUser && this.userSettings() } {this.moderates()} {this.follows()}
}
) } selects() { return (
) } 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 (
{combined.map(i =>
{i.type_ == "posts" ? : }
) }
) } comments() { return (
{this.state.comments.map(comment => )}
); } posts() { return (
{this.state.posts.map(post => )}
); } userInfo() { let user = this.state.user; return (
  • {user.name}
  • {user.banned &&
  • #
  • }
{i18n.t('joined')}
# #
# #
) } userSettings() { return (
#
) } moderates() { return (
{this.state.moderates.length > 0 &&
#
    {this.state.moderates.map(community =>
  • {community.community_name}
  • )}
}
) } follows() { return (
{this.state.follows.length > 0 &&
#
    {this.state.follows.map(community =>
  • {community.community_name}
  • )}
}
) } paginator() { return (
{this.state.page > 1 && }
); } updateUrl() { let viewStr = View[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}`); } 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(i: User, event: any) { i.state.sort = Number(event.target.value); i.state.page = 1; i.setState(i.state); i.updateUrl(); i.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); } handleUserSettingsThemeChange(i: User, event: any) { i.state.userSettingsForm.theme = event.target.value; setTheme(event.target.value); i.setState(i.state); } handleUserSettingsSubmit(i: User, event: any) { event.preventDefault(); i.state.userSettingsLoading = true; i.setState(i.state); WebSocketService.Instance.saveUserSettings(i.state.userSettingsForm); } parseMessage(msg: any) { console.log(msg); let op: UserOperation = msgOp(msg); if (msg.error) { alert(i18n.t(msg.error)); return; } else if (op == UserOperation.GetUserDetails) { let res: UserDetailsResponse = msg; this.state.user = res.user; this.state.comments = res.comments; this.state.follows = res.follows; this.state.moderates = res.moderates; this.state.posts = res.posts; this.state.admins = res.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'; } document.title = `/u/${this.state.user.name} - ${WebSocketService.Instance.site.name}`; window.scrollTo(0,0); this.setState(this.state); } else if (op == UserOperation.EditComment) { let res: CommentResponse = msg; let found = this.state.comments.find(c => c.id == res.comment.id); found.content = res.comment.content; found.updated = res.comment.updated; found.removed = res.comment.removed; found.deleted = res.comment.deleted; found.upvotes = res.comment.upvotes; found.downvotes = res.comment.downvotes; found.score = res.comment.score; this.setState(this.state); } else if (op == UserOperation.CreateComment) { // let res: CommentResponse = msg; alert(i18n.t('reply_sent')); // this.state.comments.unshift(res.comment); // TODO do this right // this.setState(this.state); } else if (op == UserOperation.SaveComment) { let res: CommentResponse = msg; let found = this.state.comments.find(c => c.id == res.comment.id); found.saved = res.comment.saved; this.setState(this.state); } else if (op == UserOperation.CreateCommentLike) { let res: CommentResponse = msg; let found: Comment = this.state.comments.find(c => c.id === res.comment.id); found.score = res.comment.score; found.upvotes = res.comment.upvotes; found.downvotes = res.comment.downvotes; if (res.comment.my_vote !== null) found.my_vote = res.comment.my_vote; this.setState(this.state); } else if (op == UserOperation.BanUser) { let res: BanUserResponse = msg; this.state.comments.filter(c => c.creator_id == res.user.id) .forEach(c => c.banned = res.banned); this.state.posts.filter(c => c.creator_id == res.user.id) .forEach(c => c.banned = res.banned); this.setState(this.state); } else if (op == UserOperation.AddAdmin) { let res: AddAdminResponse = msg; this.state.admins = res.admins; this.setState(this.state); } else if (op == UserOperation.SaveUserSettings) { this.state = this.emptyState; this.state.userSettingsLoading = false; this.setState(this.state); let res: LoginResponse = msg; UserService.Instance.login(res); } } }