mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-11-21 22:27:11 +00:00
Add post, inbox, and user routes.
This commit is contained in:
parent
bfce461a14
commit
95b74ad74c
|
@ -202,7 +202,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<span class="mx-2">•</span>
|
<span class="mx-2">•</span>
|
||||||
<Link class="mr-2" to={`/post/${node.comment.post_id}`}>
|
<Link className="mr-2" to={`/post/${node.comment.post_id}`}>
|
||||||
{node.comment.post_name}
|
{node.comment.post_name}
|
||||||
</Link>
|
</Link>
|
||||||
</>
|
</>
|
||||||
|
@ -343,7 +343,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
{!this.myComment && (
|
{!this.myComment && (
|
||||||
<button class="btn btn-link btn-animate">
|
<button class="btn btn-link btn-animate">
|
||||||
<Link
|
<Link
|
||||||
class="text-muted"
|
className="text-muted"
|
||||||
to={`/create_private_message/recipient/${node.comment.creator_id}`}
|
to={`/create_private_message/recipient/${node.comment.creator_id}`}
|
||||||
title={i18n.t('message').toLowerCase()}
|
title={i18n.t('message').toLowerCase()}
|
||||||
>
|
>
|
||||||
|
@ -757,7 +757,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
let node = this.props.node;
|
let node = this.props.node;
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
class="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
to={`/post/${node.comment.post_id}/comment/${node.comment.id}`}
|
to={`/post/${node.comment.post_id}/comment/${node.comment.id}`}
|
||||||
title={this.props.showContext ? i18n.t('show_context') : i18n.t('link')}
|
title={this.props.showContext ? i18n.t('show_context') : i18n.t('link')}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { Component, linkEvent } from 'inferno';
|
import { Component, linkEvent } from 'inferno';
|
||||||
import { Helmet } from 'inferno-helmet';
|
import { Helmet } from 'inferno-helmet';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { retryWhen, delay, take } from 'rxjs/operators';
|
|
||||||
import {
|
import {
|
||||||
UserOperation,
|
UserOperation,
|
||||||
Comment,
|
Comment,
|
||||||
|
@ -17,7 +16,6 @@ import {
|
||||||
GetPrivateMessagesForm,
|
GetPrivateMessagesForm,
|
||||||
PrivateMessagesResponse,
|
PrivateMessagesResponse,
|
||||||
PrivateMessageResponse,
|
PrivateMessageResponse,
|
||||||
GetSiteResponse,
|
|
||||||
Site,
|
Site,
|
||||||
} from 'lemmy-js-client';
|
} from 'lemmy-js-client';
|
||||||
import { WebSocketService, UserService } from '../services';
|
import { WebSocketService, UserService } from '../services';
|
||||||
|
@ -31,6 +29,11 @@ import {
|
||||||
createCommentLikeRes,
|
createCommentLikeRes,
|
||||||
commentsToFlatNodes,
|
commentsToFlatNodes,
|
||||||
setupTippy,
|
setupTippy,
|
||||||
|
setIsoData,
|
||||||
|
wsSubscribe,
|
||||||
|
lemmyHttp,
|
||||||
|
setAuth,
|
||||||
|
isBrowser,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { CommentNodes } from './comment-nodes';
|
import { CommentNodes } from './comment-nodes';
|
||||||
import { PrivateMessage } from './private-message';
|
import { PrivateMessage } from './private-message';
|
||||||
|
@ -60,9 +63,11 @@ interface InboxState {
|
||||||
sort: SortType;
|
sort: SortType;
|
||||||
page: number;
|
page: number;
|
||||||
site: Site;
|
site: Site;
|
||||||
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Inbox extends Component<any, InboxState> {
|
export class Inbox extends Component<any, InboxState> {
|
||||||
|
private isoData = setIsoData(this.context);
|
||||||
private subscription: Subscription;
|
private subscription: Subscription;
|
||||||
private emptyState: InboxState = {
|
private emptyState: InboxState = {
|
||||||
unreadOrAll: UnreadOrAll.Unread,
|
unreadOrAll: UnreadOrAll.Unread,
|
||||||
|
@ -72,20 +77,8 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
messages: [],
|
messages: [],
|
||||||
sort: SortType.New,
|
sort: SortType.New,
|
||||||
page: 1,
|
page: 1,
|
||||||
site: {
|
site: this.isoData.site.site,
|
||||||
id: undefined,
|
loading: true,
|
||||||
name: undefined,
|
|
||||||
creator_id: undefined,
|
|
||||||
published: undefined,
|
|
||||||
creator_name: undefined,
|
|
||||||
number_of_users: undefined,
|
|
||||||
number_of_posts: undefined,
|
|
||||||
number_of_comments: undefined,
|
|
||||||
number_of_communities: undefined,
|
|
||||||
enable_downvotes: undefined,
|
|
||||||
open_registration: undefined,
|
|
||||||
enable_nsfw: undefined,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
|
@ -94,77 +87,88 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
this.state = this.emptyState;
|
this.state = this.emptyState;
|
||||||
this.handleSortChange = this.handleSortChange.bind(this);
|
this.handleSortChange = this.handleSortChange.bind(this);
|
||||||
|
|
||||||
this.subscription = WebSocketService.Instance.subject
|
this.parseMessage = this.parseMessage.bind(this);
|
||||||
.pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
|
this.subscription = wsSubscribe(this.parseMessage);
|
||||||
.subscribe(
|
|
||||||
msg => this.parseMessage(msg),
|
|
||||||
err => console.error(err),
|
|
||||||
() => console.log('complete')
|
|
||||||
);
|
|
||||||
|
|
||||||
this.refetch();
|
// Only fetch the data if coming from another route
|
||||||
WebSocketService.Instance.getSite();
|
if (this.isoData.path == this.context.router.route.match.url) {
|
||||||
|
this.state.replies = this.isoData.routeData[0].replies;
|
||||||
|
this.state.mentions = this.isoData.routeData[1].mentions;
|
||||||
|
this.state.messages = this.isoData.routeData[2].messages;
|
||||||
|
this.sendUnreadCount();
|
||||||
|
this.state.loading = false;
|
||||||
|
} else {
|
||||||
|
this.refetch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.subscription.unsubscribe();
|
if (isBrowser()) {
|
||||||
|
this.subscription.unsubscribe();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
if (this.state.site.name) {
|
return `@${UserService.Instance.user.name} ${i18n.t('inbox')} - ${
|
||||||
return `@${UserService.Instance.user.name} ${i18n.t('inbox')} - ${
|
this.state.site.name
|
||||||
this.state.site.name
|
}`;
|
||||||
}`;
|
|
||||||
} else {
|
|
||||||
return 'Lemmy';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<Helmet title={this.documentTitle} />
|
<Helmet title={this.documentTitle} />
|
||||||
<div class="row">
|
{this.state.loading ? (
|
||||||
<div class="col-12">
|
<h5>
|
||||||
<h5 class="mb-1">
|
<svg class="icon icon-spinner spin">
|
||||||
{i18n.t('inbox')}
|
<use xlinkHref="#icon-spinner"></use>
|
||||||
<small>
|
</svg>
|
||||||
<a
|
</h5>
|
||||||
href={`/feeds/inbox/${UserService.Instance.auth}.xml`}
|
) : (
|
||||||
target="_blank"
|
<div class="row">
|
||||||
title="RSS"
|
<div class="col-12">
|
||||||
rel="noopener"
|
<h5 class="mb-1">
|
||||||
>
|
{i18n.t('inbox')}
|
||||||
<svg class="icon ml-2 text-muted small">
|
<small>
|
||||||
<use xlinkHref="#icon-rss">#</use>
|
<a
|
||||||
</svg>
|
href={`/feeds/inbox/${UserService.Instance.auth}.xml`}
|
||||||
</a>
|
target="_blank"
|
||||||
</small>
|
title="RSS"
|
||||||
</h5>
|
rel="noopener"
|
||||||
{this.state.replies.length +
|
>
|
||||||
this.state.mentions.length +
|
<svg class="icon ml-2 text-muted small">
|
||||||
this.state.messages.length >
|
<use xlinkHref="#icon-rss">#</use>
|
||||||
0 &&
|
</svg>
|
||||||
this.state.unreadOrAll == UnreadOrAll.Unread && (
|
</a>
|
||||||
<ul class="list-inline mb-1 text-muted small font-weight-bold">
|
</small>
|
||||||
<li className="list-inline-item">
|
</h5>
|
||||||
<span
|
{this.state.replies.length +
|
||||||
class="pointer"
|
this.state.mentions.length +
|
||||||
onClick={linkEvent(this, this.markAllAsRead)}
|
this.state.messages.length >
|
||||||
>
|
0 &&
|
||||||
{i18n.t('mark_all_as_read')}
|
this.state.unreadOrAll == UnreadOrAll.Unread && (
|
||||||
</span>
|
<ul class="list-inline mb-1 text-muted small font-weight-bold">
|
||||||
</li>
|
<li className="list-inline-item">
|
||||||
</ul>
|
<span
|
||||||
)}
|
class="pointer"
|
||||||
{this.selects()}
|
onClick={linkEvent(this, this.markAllAsRead)}
|
||||||
{this.state.messageType == MessageType.All && this.all()}
|
>
|
||||||
{this.state.messageType == MessageType.Replies && this.replies()}
|
{i18n.t('mark_all_as_read')}
|
||||||
{this.state.messageType == MessageType.Mentions && this.mentions()}
|
</span>
|
||||||
{this.state.messageType == MessageType.Messages && this.messages()}
|
</li>
|
||||||
{this.paginator()}
|
</ul>
|
||||||
|
)}
|
||||||
|
{this.selects()}
|
||||||
|
{this.state.messageType == MessageType.All && this.all()}
|
||||||
|
{this.state.messageType == MessageType.Replies && this.replies()}
|
||||||
|
{this.state.messageType == MessageType.Mentions &&
|
||||||
|
this.mentions()}
|
||||||
|
{this.state.messageType == MessageType.Messages &&
|
||||||
|
this.messages()}
|
||||||
|
{this.paginator()}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -397,6 +401,39 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
i.refetch();
|
i.refetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fetchInitialData(auth: string, _path: string): Promise<any>[] {
|
||||||
|
let promises: Promise<any>[] = [];
|
||||||
|
|
||||||
|
// It can be /u/me, or /username/1
|
||||||
|
let repliesForm: GetRepliesForm = {
|
||||||
|
sort: SortType.New,
|
||||||
|
unread_only: true,
|
||||||
|
page: 1,
|
||||||
|
limit: fetchLimit,
|
||||||
|
};
|
||||||
|
setAuth(repliesForm, auth);
|
||||||
|
promises.push(lemmyHttp.getReplies(repliesForm));
|
||||||
|
|
||||||
|
let userMentionsForm: GetUserMentionsForm = {
|
||||||
|
sort: SortType.New,
|
||||||
|
unread_only: true,
|
||||||
|
page: 1,
|
||||||
|
limit: fetchLimit,
|
||||||
|
};
|
||||||
|
setAuth(userMentionsForm, auth);
|
||||||
|
promises.push(lemmyHttp.getUserMentions(userMentionsForm));
|
||||||
|
|
||||||
|
let privateMessagesForm: GetPrivateMessagesForm = {
|
||||||
|
unread_only: true,
|
||||||
|
page: 1,
|
||||||
|
limit: fetchLimit,
|
||||||
|
};
|
||||||
|
setAuth(privateMessagesForm, auth);
|
||||||
|
promises.push(lemmyHttp.getPrivateMessages(privateMessagesForm));
|
||||||
|
|
||||||
|
return promises;
|
||||||
|
}
|
||||||
|
|
||||||
refetch() {
|
refetch() {
|
||||||
let repliesForm: GetRepliesForm = {
|
let repliesForm: GetRepliesForm = {
|
||||||
sort: this.state.sort,
|
sort: this.state.sort,
|
||||||
|
@ -450,6 +487,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
} else if (res.op == UserOperation.GetReplies) {
|
} else if (res.op == UserOperation.GetReplies) {
|
||||||
let data = res.data as GetRepliesResponse;
|
let data = res.data as GetRepliesResponse;
|
||||||
this.state.replies = data.replies;
|
this.state.replies = data.replies;
|
||||||
|
this.state.loading = false;
|
||||||
this.sendUnreadCount();
|
this.sendUnreadCount();
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
@ -581,10 +619,6 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
let data = res.data as CommentResponse;
|
let data = res.data as CommentResponse;
|
||||||
createCommentLikeRes(data, this.state.replies);
|
createCommentLikeRes(data, this.state.replies);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (res.op == UserOperation.GetSite) {
|
|
||||||
let data = res.data as GetSiteResponse;
|
|
||||||
this.state.site = data.site;
|
|
||||||
this.setState(this.state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.parseMessage = this.parseMessage.bind(this);
|
||||||
this.subscription = wsSubscribe(this.parseMessage);
|
this.subscription = wsSubscribe(this.parseMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
AddAdminForm,
|
AddAdminForm,
|
||||||
TransferSiteForm,
|
TransferSiteForm,
|
||||||
TransferCommunityForm,
|
TransferCommunityForm,
|
||||||
|
Community,
|
||||||
} from 'lemmy-js-client';
|
} from 'lemmy-js-client';
|
||||||
import { BanType } from '../interfaces';
|
import { BanType } from '../interfaces';
|
||||||
import { MomentTime } from './moment-time';
|
import { MomentTime } from './moment-time';
|
||||||
|
@ -61,6 +62,7 @@ interface PostListingState {
|
||||||
|
|
||||||
interface PostListingProps {
|
interface PostListingProps {
|
||||||
post: Post;
|
post: Post;
|
||||||
|
communities: Community[];
|
||||||
showCommunity?: boolean;
|
showCommunity?: boolean;
|
||||||
showBody?: boolean;
|
showBody?: boolean;
|
||||||
moderators?: CommunityUser[];
|
moderators?: CommunityUser[];
|
||||||
|
@ -127,6 +129,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
onCancel={this.handleEditCancel}
|
onCancel={this.handleEditCancel}
|
||||||
enableNsfw={this.props.enableNsfw}
|
enableNsfw={this.props.enableNsfw}
|
||||||
enableDownvotes={this.props.enableDownvotes}
|
enableDownvotes={this.props.enableDownvotes}
|
||||||
|
communities={this.props.communities}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -184,6 +187,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
}
|
}
|
||||||
} else if (post.thumbnail_url) {
|
} else if (post.thumbnail_url) {
|
||||||
return pictrsImage(post.thumbnail_url, thumbnail);
|
return pictrsImage(post.thumbnail_url, thumbnail);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,7 +603,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
</li>
|
</li>
|
||||||
<li className="list-inline-item">
|
<li className="list-inline-item">
|
||||||
<Link
|
<Link
|
||||||
class="btn btn-link btn-animate text-muted"
|
className="btn btn-link btn-animate text-muted"
|
||||||
to={`/create_post${this.crossPostParams}`}
|
to={`/create_post${this.crossPostParams}`}
|
||||||
title={i18n.t('cross_post')}
|
title={i18n.t('cross_post')}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
import { Component, linkEvent } from 'inferno';
|
import { Component, linkEvent } from 'inferno';
|
||||||
import { Helmet } from 'inferno-helmet';
|
import { Helmet } from 'inferno-helmet';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { retryWhen, delay, take } from 'rxjs/operators';
|
|
||||||
import {
|
import {
|
||||||
UserOperation,
|
UserOperation,
|
||||||
Community,
|
|
||||||
Post as PostI,
|
Post as PostI,
|
||||||
GetPostResponse,
|
GetPostResponse,
|
||||||
PostResponse,
|
PostResponse,
|
||||||
Comment,
|
|
||||||
MarkCommentAsReadForm,
|
MarkCommentAsReadForm,
|
||||||
CommentResponse,
|
CommentResponse,
|
||||||
CommunityUser,
|
|
||||||
CommunityResponse,
|
CommunityResponse,
|
||||||
CommentNode as CommentNodeI,
|
CommentNode as CommentNodeI,
|
||||||
BanFromCommunityResponse,
|
BanFromCommunityResponse,
|
||||||
|
@ -26,6 +22,8 @@ import {
|
||||||
GetSiteResponse,
|
GetSiteResponse,
|
||||||
GetCommunityResponse,
|
GetCommunityResponse,
|
||||||
WebSocketJsonResponse,
|
WebSocketJsonResponse,
|
||||||
|
ListCategoriesResponse,
|
||||||
|
Category,
|
||||||
} from 'lemmy-js-client';
|
} from 'lemmy-js-client';
|
||||||
import { CommentSortType, CommentViewType } from '../interfaces';
|
import { CommentSortType, CommentViewType } from '../interfaces';
|
||||||
import { WebSocketService, UserService } from '../services';
|
import { WebSocketService, UserService } from '../services';
|
||||||
|
@ -39,6 +37,13 @@ import {
|
||||||
commentsToFlatNodes,
|
commentsToFlatNodes,
|
||||||
setupTippy,
|
setupTippy,
|
||||||
favIconUrl,
|
favIconUrl,
|
||||||
|
setIsoData,
|
||||||
|
getIdFromProps,
|
||||||
|
getCommentIdFromProps,
|
||||||
|
wsSubscribe,
|
||||||
|
setAuth,
|
||||||
|
lemmyHttp,
|
||||||
|
isBrowser,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { PostListing } from './post-listing';
|
import { PostListing } from './post-listing';
|
||||||
import { Sidebar } from './sidebar';
|
import { Sidebar } from './sidebar';
|
||||||
|
@ -48,56 +53,32 @@ import autosize from 'autosize';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
|
|
||||||
interface PostState {
|
interface PostState {
|
||||||
post: PostI;
|
postRes: GetPostResponse;
|
||||||
comments: Comment[];
|
postId: number;
|
||||||
|
commentId?: number;
|
||||||
commentSort: CommentSortType;
|
commentSort: CommentSortType;
|
||||||
commentViewType: CommentViewType;
|
commentViewType: CommentViewType;
|
||||||
community: Community;
|
|
||||||
moderators: CommunityUser[];
|
|
||||||
online: number;
|
|
||||||
scrolled?: boolean;
|
scrolled?: boolean;
|
||||||
scrolled_comment_id?: number;
|
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
crossPosts: PostI[];
|
crossPosts: PostI[];
|
||||||
siteRes: GetSiteResponse;
|
siteRes: GetSiteResponse;
|
||||||
|
categories: Category[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Post extends Component<any, PostState> {
|
export class Post extends Component<any, PostState> {
|
||||||
private subscription: Subscription;
|
private subscription: Subscription;
|
||||||
|
private isoData = setIsoData(this.context);
|
||||||
private emptyState: PostState = {
|
private emptyState: PostState = {
|
||||||
post: null,
|
postRes: null,
|
||||||
comments: [],
|
postId: getIdFromProps(this.props),
|
||||||
|
commentId: getCommentIdFromProps(this.props),
|
||||||
commentSort: CommentSortType.Hot,
|
commentSort: CommentSortType.Hot,
|
||||||
commentViewType: CommentViewType.Tree,
|
commentViewType: CommentViewType.Tree,
|
||||||
community: null,
|
|
||||||
moderators: [],
|
|
||||||
online: null,
|
|
||||||
scrolled: false,
|
scrolled: false,
|
||||||
loading: true,
|
loading: true,
|
||||||
crossPosts: [],
|
crossPosts: [],
|
||||||
siteRes: {
|
siteRes: this.isoData.site,
|
||||||
admins: [],
|
categories: [],
|
||||||
banned: [],
|
|
||||||
site: {
|
|
||||||
id: undefined,
|
|
||||||
name: undefined,
|
|
||||||
creator_id: undefined,
|
|
||||||
published: undefined,
|
|
||||||
creator_name: undefined,
|
|
||||||
number_of_users: undefined,
|
|
||||||
number_of_posts: undefined,
|
|
||||||
number_of_comments: undefined,
|
|
||||||
number_of_communities: undefined,
|
|
||||||
enable_downvotes: undefined,
|
|
||||||
open_registration: undefined,
|
|
||||||
enable_nsfw: undefined,
|
|
||||||
icon: undefined,
|
|
||||||
banner: undefined,
|
|
||||||
},
|
|
||||||
online: null,
|
|
||||||
version: null,
|
|
||||||
federated_instances: undefined,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
|
@ -105,24 +86,46 @@ export class Post extends Component<any, PostState> {
|
||||||
|
|
||||||
this.state = this.emptyState;
|
this.state = this.emptyState;
|
||||||
|
|
||||||
let postId = Number(this.props.match.params.id);
|
this.parseMessage = this.parseMessage.bind(this);
|
||||||
if (this.props.match.params.comment_id) {
|
this.subscription = wsSubscribe(this.parseMessage);
|
||||||
this.state.scrolled_comment_id = this.props.match.params.comment_id;
|
|
||||||
|
// Only fetch the data if coming from another route
|
||||||
|
if (this.isoData.path == this.context.router.route.match.url) {
|
||||||
|
this.state.postRes = this.isoData.routeData[0];
|
||||||
|
this.state.categories = this.isoData.routeData[1].categories;
|
||||||
|
this.state.loading = false;
|
||||||
|
|
||||||
|
if (isBrowser() && this.state.commentId) {
|
||||||
|
this.scrollCommentIntoView();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.fetchPost();
|
||||||
|
WebSocketService.Instance.listCategories();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.subscription = WebSocketService.Instance.subject
|
fetchPost() {
|
||||||
.pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
|
|
||||||
.subscribe(
|
|
||||||
msg => this.parseMessage(msg),
|
|
||||||
err => console.error(err),
|
|
||||||
() => console.log('complete')
|
|
||||||
);
|
|
||||||
|
|
||||||
let form: GetPostForm = {
|
let form: GetPostForm = {
|
||||||
id: postId,
|
id: this.state.postId,
|
||||||
};
|
};
|
||||||
WebSocketService.Instance.getPost(form);
|
WebSocketService.Instance.getPost(form);
|
||||||
WebSocketService.Instance.getSite();
|
}
|
||||||
|
|
||||||
|
static fetchInitialData(auth: string, path: string): Promise<any>[] {
|
||||||
|
let pathSplit = path.split('/');
|
||||||
|
let promises: Promise<any>[] = [];
|
||||||
|
|
||||||
|
let id = Number(pathSplit[2]);
|
||||||
|
|
||||||
|
let postForm: GetPostForm = {
|
||||||
|
id,
|
||||||
|
};
|
||||||
|
setAuth(postForm, auth);
|
||||||
|
|
||||||
|
promises.push(lemmyHttp.getPost(postForm));
|
||||||
|
promises.push(lemmyHttp.listCategories());
|
||||||
|
|
||||||
|
return promises;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
@ -135,17 +138,12 @@ export class Post extends Component<any, PostState> {
|
||||||
|
|
||||||
componentDidUpdate(_lastProps: any, lastState: PostState, _snapshot: any) {
|
componentDidUpdate(_lastProps: any, lastState: PostState, _snapshot: any) {
|
||||||
if (
|
if (
|
||||||
this.state.scrolled_comment_id &&
|
this.state.commentId &&
|
||||||
!this.state.scrolled &&
|
!this.state.scrolled &&
|
||||||
lastState.comments.length > 0
|
lastState.postRes &&
|
||||||
|
lastState.postRes.comments.length > 0
|
||||||
) {
|
) {
|
||||||
var elmnt = document.getElementById(
|
this.scrollCommentIntoView();
|
||||||
`comment-${this.state.scrolled_comment_id}`
|
|
||||||
);
|
|
||||||
elmnt.scrollIntoView();
|
|
||||||
elmnt.classList.add('mark');
|
|
||||||
this.state.scrolled = true;
|
|
||||||
this.markScrolledAsRead(this.state.scrolled_comment_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Necessary if you are on a post and you click another post (same route)
|
// Necessary if you are on a post and you click another post (same route)
|
||||||
|
@ -161,12 +159,20 @@ export class Post extends Component<any, PostState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scrollCommentIntoView() {
|
||||||
|
var elmnt = document.getElementById(`comment-${this.state.commentId}`);
|
||||||
|
elmnt.scrollIntoView();
|
||||||
|
elmnt.classList.add('mark');
|
||||||
|
this.state.scrolled = true;
|
||||||
|
this.markScrolledAsRead(this.state.commentId);
|
||||||
|
}
|
||||||
|
|
||||||
markScrolledAsRead(commentId: number) {
|
markScrolledAsRead(commentId: number) {
|
||||||
let found = this.state.comments.find(c => c.id == commentId);
|
let found = this.state.postRes.comments.find(c => c.id == commentId);
|
||||||
let parent = this.state.comments.find(c => found.parent_id == c.id);
|
let parent = this.state.postRes.comments.find(c => found.parent_id == c.id);
|
||||||
let parent_user_id = parent
|
let parent_user_id = parent
|
||||||
? parent.creator_id
|
? parent.creator_id
|
||||||
: this.state.post.creator_id;
|
: this.state.postRes.post.creator_id;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
UserService.Instance.user &&
|
UserService.Instance.user &&
|
||||||
|
@ -185,8 +191,8 @@ export class Post extends Component<any, PostState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
if (this.state.post) {
|
if (this.state.postRes) {
|
||||||
return `${this.state.post.name} - ${this.state.siteRes.site.name}`;
|
return `${this.state.postRes.post.name} - ${this.state.siteRes.site.name}`;
|
||||||
} else {
|
} else {
|
||||||
return 'Lemmy';
|
return 'Lemmy';
|
||||||
}
|
}
|
||||||
|
@ -219,20 +225,21 @@ export class Post extends Component<any, PostState> {
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-md-8 mb-3">
|
<div class="col-12 col-md-8 mb-3">
|
||||||
<PostListing
|
<PostListing
|
||||||
post={this.state.post}
|
communities={[this.state.postRes.community]}
|
||||||
|
post={this.state.postRes.post}
|
||||||
showBody
|
showBody
|
||||||
showCommunity
|
showCommunity
|
||||||
moderators={this.state.moderators}
|
moderators={this.state.postRes.moderators}
|
||||||
admins={this.state.siteRes.admins}
|
admins={this.state.siteRes.admins}
|
||||||
enableDownvotes={this.state.siteRes.site.enable_downvotes}
|
enableDownvotes={this.state.siteRes.site.enable_downvotes}
|
||||||
enableNsfw={this.state.siteRes.site.enable_nsfw}
|
enableNsfw={this.state.siteRes.site.enable_nsfw}
|
||||||
/>
|
/>
|
||||||
<div className="mb-2" />
|
<div className="mb-2" />
|
||||||
<CommentForm
|
<CommentForm
|
||||||
postId={this.state.post.id}
|
postId={this.state.postId}
|
||||||
disabled={this.state.post.locked}
|
disabled={this.state.postRes.post.locked}
|
||||||
/>
|
/>
|
||||||
{this.state.comments.length > 0 && this.sortRadios()}
|
{this.state.postRes.comments.length > 0 && this.sortRadios()}
|
||||||
{this.state.commentViewType == CommentViewType.Tree &&
|
{this.state.commentViewType == CommentViewType.Tree &&
|
||||||
this.commentsTree()}
|
this.commentsTree()}
|
||||||
{this.state.commentViewType == CommentViewType.Chat &&
|
{this.state.commentViewType == CommentViewType.Chat &&
|
||||||
|
@ -325,12 +332,12 @@ export class Post extends Component<any, PostState> {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<CommentNodes
|
<CommentNodes
|
||||||
nodes={commentsToFlatNodes(this.state.comments)}
|
nodes={commentsToFlatNodes(this.state.postRes.comments)}
|
||||||
noIndent
|
noIndent
|
||||||
locked={this.state.post.locked}
|
locked={this.state.postRes.post.locked}
|
||||||
moderators={this.state.moderators}
|
moderators={this.state.postRes.moderators}
|
||||||
admins={this.state.siteRes.admins}
|
admins={this.state.siteRes.admins}
|
||||||
postCreatorId={this.state.post.creator_id}
|
postCreatorId={this.state.postRes.post.creator_id}
|
||||||
showContext
|
showContext
|
||||||
enableDownvotes={this.state.siteRes.site.enable_downvotes}
|
enableDownvotes={this.state.siteRes.site.enable_downvotes}
|
||||||
sort={this.state.commentSort}
|
sort={this.state.commentSort}
|
||||||
|
@ -343,12 +350,13 @@ export class Post extends Component<any, PostState> {
|
||||||
return (
|
return (
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<Sidebar
|
<Sidebar
|
||||||
community={this.state.community}
|
community={this.state.postRes.community}
|
||||||
moderators={this.state.moderators}
|
moderators={this.state.postRes.moderators}
|
||||||
admins={this.state.siteRes.admins}
|
admins={this.state.siteRes.admins}
|
||||||
online={this.state.online}
|
online={this.state.postRes.online}
|
||||||
enableNsfw={this.state.siteRes.site.enable_nsfw}
|
enableNsfw={this.state.siteRes.site.enable_nsfw}
|
||||||
showIcon
|
showIcon
|
||||||
|
categories={this.state.categories}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -368,7 +376,7 @@ export class Post extends Component<any, PostState> {
|
||||||
|
|
||||||
buildCommentsTree(): CommentNodeI[] {
|
buildCommentsTree(): CommentNodeI[] {
|
||||||
let map = new Map<number, CommentNodeI>();
|
let map = new Map<number, CommentNodeI>();
|
||||||
for (let comment of this.state.comments) {
|
for (let comment of this.state.postRes.comments) {
|
||||||
let node: CommentNodeI = {
|
let node: CommentNodeI = {
|
||||||
comment: comment,
|
comment: comment,
|
||||||
children: [],
|
children: [],
|
||||||
|
@ -376,7 +384,7 @@ export class Post extends Component<any, PostState> {
|
||||||
map.set(comment.id, { ...node });
|
map.set(comment.id, { ...node });
|
||||||
}
|
}
|
||||||
let tree: CommentNodeI[] = [];
|
let tree: CommentNodeI[] = [];
|
||||||
for (let comment of this.state.comments) {
|
for (let comment of this.state.postRes.comments) {
|
||||||
let child = map.get(comment.id);
|
let child = map.get(comment.id);
|
||||||
if (comment.parent_id) {
|
if (comment.parent_id) {
|
||||||
let parent_ = map.get(comment.parent_id);
|
let parent_ = map.get(comment.parent_id);
|
||||||
|
@ -404,10 +412,10 @@ export class Post extends Component<any, PostState> {
|
||||||
<div>
|
<div>
|
||||||
<CommentNodes
|
<CommentNodes
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
locked={this.state.post.locked}
|
locked={this.state.postRes.post.locked}
|
||||||
moderators={this.state.moderators}
|
moderators={this.state.postRes.moderators}
|
||||||
admins={this.state.siteRes.admins}
|
admins={this.state.siteRes.admins}
|
||||||
postCreatorId={this.state.post.creator_id}
|
postCreatorId={this.state.postRes.post.creator_id}
|
||||||
sort={this.state.commentSort}
|
sort={this.state.commentSort}
|
||||||
enableDownvotes={this.state.siteRes.site.enable_downvotes}
|
enableDownvotes={this.state.siteRes.site.enable_downvotes}
|
||||||
/>
|
/>
|
||||||
|
@ -427,17 +435,13 @@ export class Post extends Component<any, PostState> {
|
||||||
});
|
});
|
||||||
} else if (res.op == UserOperation.GetPost) {
|
} else if (res.op == UserOperation.GetPost) {
|
||||||
let data = res.data as GetPostResponse;
|
let data = res.data as GetPostResponse;
|
||||||
this.state.post = data.post;
|
this.state.postRes = data;
|
||||||
this.state.comments = data.comments;
|
|
||||||
this.state.community = data.community;
|
|
||||||
this.state.moderators = data.moderators;
|
|
||||||
this.state.online = data.online;
|
|
||||||
this.state.loading = false;
|
this.state.loading = false;
|
||||||
|
|
||||||
// Get cross-posts
|
// Get cross-posts
|
||||||
if (this.state.post.url) {
|
if (this.state.postRes.post.url) {
|
||||||
let form: SearchForm = {
|
let form: SearchForm = {
|
||||||
q: this.state.post.url,
|
q: this.state.postRes.post.url,
|
||||||
type_: SearchType.Url,
|
type_: SearchType.Url,
|
||||||
sort: SortType.TopAll,
|
sort: SortType.TopAll,
|
||||||
page: 1,
|
page: 1,
|
||||||
|
@ -453,7 +457,7 @@ export class Post extends Component<any, PostState> {
|
||||||
|
|
||||||
// Necessary since it might be a user reply
|
// Necessary since it might be a user reply
|
||||||
if (data.recipient_ids.length == 0) {
|
if (data.recipient_ids.length == 0) {
|
||||||
this.state.comments.unshift(data.comment);
|
this.state.postRes.comments.unshift(data.comment);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
|
@ -462,20 +466,20 @@ export class Post extends Component<any, PostState> {
|
||||||
res.op == UserOperation.RemoveComment
|
res.op == UserOperation.RemoveComment
|
||||||
) {
|
) {
|
||||||
let data = res.data as CommentResponse;
|
let data = res.data as CommentResponse;
|
||||||
editCommentRes(data, this.state.comments);
|
editCommentRes(data, this.state.postRes.comments);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (res.op == UserOperation.SaveComment) {
|
} else if (res.op == UserOperation.SaveComment) {
|
||||||
let data = res.data as CommentResponse;
|
let data = res.data as CommentResponse;
|
||||||
saveCommentRes(data, this.state.comments);
|
saveCommentRes(data, this.state.postRes.comments);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
setupTippy();
|
setupTippy();
|
||||||
} else if (res.op == UserOperation.CreateCommentLike) {
|
} else if (res.op == UserOperation.CreateCommentLike) {
|
||||||
let data = res.data as CommentResponse;
|
let data = res.data as CommentResponse;
|
||||||
createCommentLikeRes(data, this.state.comments);
|
createCommentLikeRes(data, this.state.postRes.comments);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (res.op == UserOperation.CreatePostLike) {
|
} else if (res.op == UserOperation.CreatePostLike) {
|
||||||
let data = res.data as PostResponse;
|
let data = res.data as PostResponse;
|
||||||
createPostLikeRes(data, this.state.post);
|
createPostLikeRes(data, this.state.postRes.post);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (
|
} else if (
|
||||||
res.op == UserOperation.EditPost ||
|
res.op == UserOperation.EditPost ||
|
||||||
|
@ -485,12 +489,12 @@ export class Post extends Component<any, PostState> {
|
||||||
res.op == UserOperation.StickyPost
|
res.op == UserOperation.StickyPost
|
||||||
) {
|
) {
|
||||||
let data = res.data as PostResponse;
|
let data = res.data as PostResponse;
|
||||||
this.state.post = data.post;
|
this.state.postRes.post = data.post;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
setupTippy();
|
setupTippy();
|
||||||
} else if (res.op == UserOperation.SavePost) {
|
} else if (res.op == UserOperation.SavePost) {
|
||||||
let data = res.data as PostResponse;
|
let data = res.data as PostResponse;
|
||||||
this.state.post = data.post;
|
this.state.postRes.post = data.post;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
setupTippy();
|
setupTippy();
|
||||||
} else if (
|
} else if (
|
||||||
|
@ -499,36 +503,36 @@ export class Post extends Component<any, PostState> {
|
||||||
res.op == UserOperation.RemoveCommunity
|
res.op == UserOperation.RemoveCommunity
|
||||||
) {
|
) {
|
||||||
let data = res.data as CommunityResponse;
|
let data = res.data as CommunityResponse;
|
||||||
this.state.community = data.community;
|
this.state.postRes.community = data.community;
|
||||||
this.state.post.community_id = data.community.id;
|
this.state.postRes.post.community_id = data.community.id;
|
||||||
this.state.post.community_name = data.community.name;
|
this.state.postRes.post.community_name = data.community.name;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (res.op == UserOperation.FollowCommunity) {
|
} else if (res.op == UserOperation.FollowCommunity) {
|
||||||
let data = res.data as CommunityResponse;
|
let data = res.data as CommunityResponse;
|
||||||
this.state.community.subscribed = data.community.subscribed;
|
this.state.postRes.community.subscribed = data.community.subscribed;
|
||||||
this.state.community.number_of_subscribers =
|
this.state.postRes.community.number_of_subscribers =
|
||||||
data.community.number_of_subscribers;
|
data.community.number_of_subscribers;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (res.op == UserOperation.BanFromCommunity) {
|
} else if (res.op == UserOperation.BanFromCommunity) {
|
||||||
let data = res.data as BanFromCommunityResponse;
|
let data = res.data as BanFromCommunityResponse;
|
||||||
this.state.comments
|
this.state.postRes.comments
|
||||||
.filter(c => c.creator_id == data.user.id)
|
.filter(c => c.creator_id == data.user.id)
|
||||||
.forEach(c => (c.banned_from_community = data.banned));
|
.forEach(c => (c.banned_from_community = data.banned));
|
||||||
if (this.state.post.creator_id == data.user.id) {
|
if (this.state.postRes.post.creator_id == data.user.id) {
|
||||||
this.state.post.banned_from_community = data.banned;
|
this.state.postRes.post.banned_from_community = data.banned;
|
||||||
}
|
}
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (res.op == UserOperation.AddModToCommunity) {
|
} else if (res.op == UserOperation.AddModToCommunity) {
|
||||||
let data = res.data as AddModToCommunityResponse;
|
let data = res.data as AddModToCommunityResponse;
|
||||||
this.state.moderators = data.moderators;
|
this.state.postRes.moderators = data.moderators;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (res.op == UserOperation.BanUser) {
|
} else if (res.op == UserOperation.BanUser) {
|
||||||
let data = res.data as BanUserResponse;
|
let data = res.data as BanUserResponse;
|
||||||
this.state.comments
|
this.state.postRes.comments
|
||||||
.filter(c => c.creator_id == data.user.id)
|
.filter(c => c.creator_id == data.user.id)
|
||||||
.forEach(c => (c.banned = data.banned));
|
.forEach(c => (c.banned = data.banned));
|
||||||
if (this.state.post.creator_id == data.user.id) {
|
if (this.state.postRes.post.creator_id == data.user.id) {
|
||||||
this.state.post.banned = data.banned;
|
this.state.postRes.post.banned = data.banned;
|
||||||
}
|
}
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (res.op == UserOperation.AddAdmin) {
|
} else if (res.op == UserOperation.AddAdmin) {
|
||||||
|
@ -541,20 +545,21 @@ export class Post extends Component<any, PostState> {
|
||||||
p => p.id != Number(this.props.match.params.id)
|
p => p.id != Number(this.props.match.params.id)
|
||||||
);
|
);
|
||||||
if (this.state.crossPosts.length) {
|
if (this.state.crossPosts.length) {
|
||||||
this.state.post.duplicates = this.state.crossPosts;
|
this.state.postRes.post.duplicates = this.state.crossPosts;
|
||||||
}
|
}
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (
|
} else if (res.op == UserOperation.TransferSite) {
|
||||||
res.op == UserOperation.TransferSite ||
|
|
||||||
res.op == UserOperation.GetSite
|
|
||||||
) {
|
|
||||||
let data = res.data as GetSiteResponse;
|
let data = res.data as GetSiteResponse;
|
||||||
this.state.siteRes = data;
|
this.state.siteRes = data;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (res.op == UserOperation.TransferCommunity) {
|
} else if (res.op == UserOperation.TransferCommunity) {
|
||||||
let data = res.data as GetCommunityResponse;
|
let data = res.data as GetCommunityResponse;
|
||||||
this.state.community = data.community;
|
this.state.postRes.community = data.community;
|
||||||
this.state.moderators = data.moderators;
|
this.state.postRes.moderators = data.moderators;
|
||||||
|
this.setState(this.state);
|
||||||
|
} else if (res.op == UserOperation.ListCategories) {
|
||||||
|
let data = res.data as ListCategoriesResponse;
|
||||||
|
this.state.categories = data.categories;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +1,13 @@
|
||||||
import { Component, linkEvent } from 'inferno';
|
import { Component, linkEvent } from 'inferno';
|
||||||
import { WebSocketService, UserService } from '../services';
|
|
||||||
import { Subscription } from 'rxjs';
|
|
||||||
import { retryWhen, delay, take } from 'rxjs/operators';
|
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
import {
|
import { Post, Comment, SortType, UserDetailsResponse } from 'lemmy-js-client';
|
||||||
UserOperation,
|
|
||||||
Post,
|
|
||||||
Comment,
|
|
||||||
CommunityUser,
|
|
||||||
SortType,
|
|
||||||
UserDetailsResponse,
|
|
||||||
UserView,
|
|
||||||
WebSocketJsonResponse,
|
|
||||||
CommentResponse,
|
|
||||||
BanUserResponse,
|
|
||||||
PostResponse,
|
|
||||||
} from 'lemmy-js-client';
|
|
||||||
import { UserDetailsView } from '../interfaces';
|
import { UserDetailsView } from '../interfaces';
|
||||||
import {
|
import { commentsToFlatNodes, setupTippy } from '../utils';
|
||||||
wsJsonToRes,
|
|
||||||
toast,
|
|
||||||
commentsToFlatNodes,
|
|
||||||
setupTippy,
|
|
||||||
editCommentRes,
|
|
||||||
saveCommentRes,
|
|
||||||
createCommentLikeRes,
|
|
||||||
createPostLikeFindRes,
|
|
||||||
} from '../utils';
|
|
||||||
import { PostListing } from './post-listing';
|
import { PostListing } from './post-listing';
|
||||||
import { CommentNodes } from './comment-nodes';
|
import { CommentNodes } from './comment-nodes';
|
||||||
|
|
||||||
interface UserDetailsProps {
|
interface UserDetailsProps {
|
||||||
username?: string;
|
userRes: UserDetailsResponse;
|
||||||
user_id?: number;
|
|
||||||
page: number;
|
page: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
sort: SortType;
|
sort: SortType;
|
||||||
|
@ -40,67 +15,29 @@ interface UserDetailsProps {
|
||||||
enableNsfw: boolean;
|
enableNsfw: boolean;
|
||||||
view: UserDetailsView;
|
view: UserDetailsView;
|
||||||
onPageChange(page: number): number | any;
|
onPageChange(page: number): number | any;
|
||||||
admins: UserView[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserDetailsState {
|
interface UserDetailsState {}
|
||||||
follows: CommunityUser[];
|
|
||||||
moderates: CommunityUser[];
|
|
||||||
comments: Comment[];
|
|
||||||
posts: Post[];
|
|
||||||
saved?: Post[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
|
export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
|
||||||
private subscription: Subscription;
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
||||||
this.state = {
|
|
||||||
follows: [],
|
|
||||||
moderates: [],
|
|
||||||
comments: [],
|
|
||||||
posts: [],
|
|
||||||
saved: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO needed here?
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.fetchUserData();
|
|
||||||
setupTippy();
|
setupTippy();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(lastProps: UserDetailsProps) {
|
// TODO wut?
|
||||||
for (const key of Object.keys(lastProps)) {
|
// componentDidUpdate(lastProps: UserDetailsProps) {
|
||||||
if (lastProps[key] !== this.props[key]) {
|
// for (const key of Object.keys(lastProps)) {
|
||||||
this.fetchUserData();
|
// if (lastProps[key] !== this.props[key]) {
|
||||||
break;
|
// this.fetchUserData();
|
||||||
}
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
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() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
@ -114,20 +51,20 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
|
||||||
viewSelector(view: UserDetailsView) {
|
viewSelector(view: UserDetailsView) {
|
||||||
if (view === UserDetailsView.Overview || view === UserDetailsView.Saved) {
|
if (view === UserDetailsView.Overview || view === UserDetailsView.Saved) {
|
||||||
return this.overview();
|
return this.overview();
|
||||||
}
|
} else if (view === UserDetailsView.Comments) {
|
||||||
if (view === UserDetailsView.Comments) {
|
|
||||||
return this.comments();
|
return this.comments();
|
||||||
}
|
} else if (view === UserDetailsView.Posts) {
|
||||||
if (view === UserDetailsView.Posts) {
|
|
||||||
return this.posts();
|
return this.posts();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
overview() {
|
overview() {
|
||||||
const comments = this.state.comments.map((c: Comment) => {
|
const comments = this.props.userRes.comments.map((c: Comment) => {
|
||||||
return { type: 'comments', data: c };
|
return { type: 'comments', data: c };
|
||||||
});
|
});
|
||||||
const posts = this.state.posts.map((p: Post) => {
|
const posts = this.props.userRes.posts.map((p: Post) => {
|
||||||
return { type: 'posts', data: p };
|
return { type: 'posts', data: p };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -150,9 +87,10 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
|
||||||
<div>
|
<div>
|
||||||
{i.type === 'posts' ? (
|
{i.type === 'posts' ? (
|
||||||
<PostListing
|
<PostListing
|
||||||
|
communities={[]}
|
||||||
key={(i.data as Post).id}
|
key={(i.data as Post).id}
|
||||||
post={i.data as Post}
|
post={i.data as Post}
|
||||||
admins={this.props.admins}
|
admins={this.props.userRes.admins}
|
||||||
showCommunity
|
showCommunity
|
||||||
enableDownvotes={this.props.enableDownvotes}
|
enableDownvotes={this.props.enableDownvotes}
|
||||||
enableNsfw={this.props.enableNsfw}
|
enableNsfw={this.props.enableNsfw}
|
||||||
|
@ -161,7 +99,7 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
|
||||||
<CommentNodes
|
<CommentNodes
|
||||||
key={(i.data as Comment).id}
|
key={(i.data as Comment).id}
|
||||||
nodes={[{ comment: i.data as Comment }]}
|
nodes={[{ comment: i.data as Comment }]}
|
||||||
admins={this.props.admins}
|
admins={this.props.userRes.admins}
|
||||||
noBorder
|
noBorder
|
||||||
noIndent
|
noIndent
|
||||||
showCommunity
|
showCommunity
|
||||||
|
@ -181,8 +119,8 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<CommentNodes
|
<CommentNodes
|
||||||
nodes={commentsToFlatNodes(this.state.comments)}
|
nodes={commentsToFlatNodes(this.props.userRes.comments)}
|
||||||
admins={this.props.admins}
|
admins={this.props.userRes.admins}
|
||||||
noIndent
|
noIndent
|
||||||
showCommunity
|
showCommunity
|
||||||
showContext
|
showContext
|
||||||
|
@ -195,11 +133,12 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
|
||||||
posts() {
|
posts() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{this.state.posts.map(post => (
|
{this.props.userRes.posts.map(post => (
|
||||||
<>
|
<>
|
||||||
<PostListing
|
<PostListing
|
||||||
|
communities={[]}
|
||||||
post={post}
|
post={post}
|
||||||
admins={this.props.admins}
|
admins={this.props.userRes.admins}
|
||||||
showCommunity
|
showCommunity
|
||||||
enableDownvotes={this.props.enableDownvotes}
|
enableDownvotes={this.props.enableDownvotes}
|
||||||
enableNsfw={this.props.enableNsfw}
|
enableNsfw={this.props.enableNsfw}
|
||||||
|
@ -222,7 +161,8 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
|
||||||
{i18n.t('prev')}
|
{i18n.t('prev')}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{this.state.comments.length + this.state.posts.length > 0 && (
|
{this.props.userRes.comments.length + this.props.userRes.posts.length >
|
||||||
|
0 && (
|
||||||
<button
|
<button
|
||||||
class="btn btn-secondary"
|
class="btn btn-secondary"
|
||||||
onClick={linkEvent(this, this.nextPage)}
|
onClick={linkEvent(this, this.nextPage)}
|
||||||
|
@ -241,75 +181,4 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
|
||||||
prevPage(i: UserDetails) {
|
prevPage(i: UserDetails) {
|
||||||
i.props.onPageChange(i.props.page - 1);
|
i.props.onPageChange(i.props.page - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseMessage(msg: WebSocketJsonResponse) {
|
|
||||||
console.log(msg);
|
|
||||||
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,
|
|
||||||
});
|
|
||||||
} 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 ||
|
|
||||||
res.op == UserOperation.DeleteComment ||
|
|
||||||
res.op == UserOperation.RemoveComment
|
|
||||||
) {
|
|
||||||
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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,10 @@ import { Component, linkEvent } from 'inferno';
|
||||||
import { Helmet } from 'inferno-helmet';
|
import { Helmet } from 'inferno-helmet';
|
||||||
import { Link } from 'inferno-router';
|
import { Link } from 'inferno-router';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { retryWhen, delay, take } from 'rxjs/operators';
|
|
||||||
import {
|
import {
|
||||||
UserOperation,
|
UserOperation,
|
||||||
CommunityUser,
|
|
||||||
SortType,
|
SortType,
|
||||||
ListingType,
|
ListingType,
|
||||||
UserView,
|
|
||||||
UserSettingsForm,
|
UserSettingsForm,
|
||||||
LoginResponse,
|
LoginResponse,
|
||||||
DeleteAccountForm,
|
DeleteAccountForm,
|
||||||
|
@ -16,6 +13,10 @@ import {
|
||||||
GetSiteResponse,
|
GetSiteResponse,
|
||||||
UserDetailsResponse,
|
UserDetailsResponse,
|
||||||
AddAdminResponse,
|
AddAdminResponse,
|
||||||
|
GetUserDetailsForm,
|
||||||
|
CommentResponse,
|
||||||
|
PostResponse,
|
||||||
|
BanUserResponse,
|
||||||
} from 'lemmy-js-client';
|
} from 'lemmy-js-client';
|
||||||
import { UserDetailsView } from '../interfaces';
|
import { UserDetailsView } from '../interfaces';
|
||||||
import { WebSocketService, UserService } from '../services';
|
import { WebSocketService, UserService } from '../services';
|
||||||
|
@ -33,6 +34,16 @@ import {
|
||||||
mdToHtml,
|
mdToHtml,
|
||||||
elementUrl,
|
elementUrl,
|
||||||
favIconUrl,
|
favIconUrl,
|
||||||
|
setIsoData,
|
||||||
|
getIdFromProps,
|
||||||
|
getUsernameFromProps,
|
||||||
|
wsSubscribe,
|
||||||
|
createCommentLikeRes,
|
||||||
|
editCommentRes,
|
||||||
|
saveCommentRes,
|
||||||
|
createPostLikeFindRes,
|
||||||
|
setAuth,
|
||||||
|
lemmyHttp,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { UserListing } from './user-listing';
|
import { UserListing } from './user-listing';
|
||||||
import { SortSelect } from './sort-select';
|
import { SortSelect } from './sort-select';
|
||||||
|
@ -46,11 +57,9 @@ import { ImageUploadForm } from './image-upload-form';
|
||||||
import { BannerIconHeader } from './banner-icon-header';
|
import { BannerIconHeader } from './banner-icon-header';
|
||||||
|
|
||||||
interface UserState {
|
interface UserState {
|
||||||
user: UserView;
|
userRes: UserDetailsResponse;
|
||||||
user_id: number;
|
userId: number;
|
||||||
username: string;
|
userName: string;
|
||||||
follows: CommunityUser[];
|
|
||||||
moderates: CommunityUser[];
|
|
||||||
view: UserDetailsView;
|
view: UserDetailsView;
|
||||||
sort: SortType;
|
sort: SortType;
|
||||||
page: number;
|
page: number;
|
||||||
|
@ -78,25 +87,12 @@ interface UrlParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class User extends Component<any, UserState> {
|
export class User extends Component<any, UserState> {
|
||||||
|
private isoData = setIsoData(this.context);
|
||||||
private subscription: Subscription;
|
private subscription: Subscription;
|
||||||
private emptyState: UserState = {
|
private emptyState: UserState = {
|
||||||
user: {
|
userRes: undefined,
|
||||||
id: null,
|
userId: getIdFromProps(this.props),
|
||||||
name: null,
|
userName: getUsernameFromProps(this.props),
|
||||||
published: null,
|
|
||||||
number_of_posts: null,
|
|
||||||
post_score: null,
|
|
||||||
number_of_comments: null,
|
|
||||||
comment_score: null,
|
|
||||||
banned: null,
|
|
||||||
avatar: null,
|
|
||||||
actor_id: null,
|
|
||||||
local: null,
|
|
||||||
},
|
|
||||||
user_id: null,
|
|
||||||
username: null,
|
|
||||||
follows: [],
|
|
||||||
moderates: [],
|
|
||||||
loading: true,
|
loading: true,
|
||||||
view: User.getViewFromProps(this.props.match.view),
|
view: User.getViewFromProps(this.props.match.view),
|
||||||
sort: User.getSortTypeFromProps(this.props.match.sort),
|
sort: User.getSortTypeFromProps(this.props.match.sort),
|
||||||
|
@ -119,31 +115,7 @@ export class User extends Component<any, UserState> {
|
||||||
deleteAccountForm: {
|
deleteAccountForm: {
|
||||||
password: null,
|
password: null,
|
||||||
},
|
},
|
||||||
siteRes: {
|
siteRes: this.isoData.site,
|
||||||
admins: [],
|
|
||||||
banned: [],
|
|
||||||
online: undefined,
|
|
||||||
site: {
|
|
||||||
id: undefined,
|
|
||||||
name: undefined,
|
|
||||||
creator_id: undefined,
|
|
||||||
published: undefined,
|
|
||||||
creator_name: undefined,
|
|
||||||
number_of_users: undefined,
|
|
||||||
number_of_posts: undefined,
|
|
||||||
number_of_comments: undefined,
|
|
||||||
number_of_communities: undefined,
|
|
||||||
enable_downvotes: undefined,
|
|
||||||
open_registration: undefined,
|
|
||||||
enable_nsfw: undefined,
|
|
||||||
icon: undefined,
|
|
||||||
banner: undefined,
|
|
||||||
creator_preferred_username: undefined,
|
|
||||||
},
|
|
||||||
version: undefined,
|
|
||||||
my_user: undefined,
|
|
||||||
federated_instances: undefined,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
|
@ -168,25 +140,37 @@ export class User extends Component<any, UserState> {
|
||||||
this.handleBannerUpload = this.handleBannerUpload.bind(this);
|
this.handleBannerUpload = this.handleBannerUpload.bind(this);
|
||||||
this.handleBannerRemove = this.handleBannerRemove.bind(this);
|
this.handleBannerRemove = this.handleBannerRemove.bind(this);
|
||||||
|
|
||||||
this.state.user_id = Number(this.props.match.params.id) || null;
|
this.parseMessage = this.parseMessage.bind(this);
|
||||||
this.state.username = this.props.match.params.username;
|
this.subscription = wsSubscribe(this.parseMessage);
|
||||||
|
|
||||||
this.subscription = WebSocketService.Instance.subject
|
// Only fetch the data if coming from another route
|
||||||
.pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
|
if (this.isoData.path == this.context.router.route.match.url) {
|
||||||
.subscribe(
|
this.state.userRes = this.isoData.routeData[0];
|
||||||
msg => this.parseMessage(msg),
|
this.setUserInfo();
|
||||||
err => console.error(err),
|
this.state.loading = false;
|
||||||
() => console.log('complete')
|
} else {
|
||||||
);
|
this.fetchUserData();
|
||||||
|
}
|
||||||
|
|
||||||
WebSocketService.Instance.getSite();
|
|
||||||
setupTippy();
|
setupTippy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetchUserData() {
|
||||||
|
let form: GetUserDetailsForm = {
|
||||||
|
user_id: this.state.userId,
|
||||||
|
username: this.state.userName,
|
||||||
|
sort: this.state.sort,
|
||||||
|
saved_only: this.state.view === UserDetailsView.Saved,
|
||||||
|
page: this.state.page,
|
||||||
|
limit: fetchLimit,
|
||||||
|
};
|
||||||
|
WebSocketService.Instance.getUserDetails(form);
|
||||||
|
}
|
||||||
|
|
||||||
get isCurrentUser() {
|
get isCurrentUser() {
|
||||||
return (
|
return (
|
||||||
UserService.Instance.user &&
|
UserService.Instance.user &&
|
||||||
UserService.Instance.user.id == this.state.user.id
|
UserService.Instance.user.id == this.state.userRes.user.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +186,44 @@ export class User extends Component<any, UserState> {
|
||||||
return page ? Number(page) : 1;
|
return page ? Number(page) : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fetchInitialData(auth: string, path: string): Promise<any>[] {
|
||||||
|
let pathSplit = path.split('/');
|
||||||
|
let promises: Promise<any>[] = [];
|
||||||
|
|
||||||
|
// It can be /u/me, or /username/1
|
||||||
|
let idOrName = pathSplit[2];
|
||||||
|
let user_id: number;
|
||||||
|
let username: string;
|
||||||
|
if (isNaN(Number(idOrName))) {
|
||||||
|
username = idOrName;
|
||||||
|
} else {
|
||||||
|
user_id = Number(idOrName);
|
||||||
|
}
|
||||||
|
|
||||||
|
let view = this.getViewFromProps(pathSplit[4]);
|
||||||
|
let sort = this.getSortTypeFromProps(pathSplit[6]);
|
||||||
|
let page = this.getPageFromProps(Number(pathSplit[8]));
|
||||||
|
|
||||||
|
let form: GetUserDetailsForm = {
|
||||||
|
sort,
|
||||||
|
saved_only: view === UserDetailsView.Saved,
|
||||||
|
page,
|
||||||
|
limit: fetchLimit,
|
||||||
|
};
|
||||||
|
this.setIdOrName(form, user_id, username);
|
||||||
|
setAuth(form, auth);
|
||||||
|
promises.push(lemmyHttp.getUserDetails(form));
|
||||||
|
return promises;
|
||||||
|
}
|
||||||
|
|
||||||
|
static setIdOrName(obj: any, id: number, name_: string) {
|
||||||
|
if (id) {
|
||||||
|
obj.user_id = id;
|
||||||
|
} else {
|
||||||
|
obj.username = name_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.subscription.unsubscribe();
|
this.subscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
@ -229,7 +251,7 @@ export class User extends Component<any, UserState> {
|
||||||
|
|
||||||
get documentTitle(): string {
|
get documentTitle(): string {
|
||||||
if (this.state.siteRes.site.name) {
|
if (this.state.siteRes.site.name) {
|
||||||
return `@${this.state.username} - ${this.state.siteRes.site.name}`;
|
return `@${this.state.userName} - ${this.state.siteRes.site.name}`;
|
||||||
} else {
|
} else {
|
||||||
return 'Lemmy';
|
return 'Lemmy';
|
||||||
}
|
}
|
||||||
|
@ -252,43 +274,41 @@ export class User extends Component<any, UserState> {
|
||||||
href={this.favIcon}
|
href={this.favIcon}
|
||||||
/>
|
/>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div class="row">
|
{this.state.loading ? (
|
||||||
<div class="col-12 col-md-8">
|
<h5>
|
||||||
{this.state.loading ? (
|
<svg class="icon icon-spinner spin">
|
||||||
<h5>
|
<use xlinkHref="#icon-spinner"></use>
|
||||||
<svg class="icon icon-spinner spin">
|
</svg>
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
</h5>
|
||||||
</svg>
|
) : (
|
||||||
</h5>
|
<div class="row">
|
||||||
) : (
|
<div class="col-12 col-md-8">
|
||||||
<>
|
<>
|
||||||
{this.userInfo()}
|
{this.userInfo()}
|
||||||
<hr />
|
<hr />
|
||||||
</>
|
</>
|
||||||
)}
|
{!this.state.loading && this.selects()}
|
||||||
{!this.state.loading && this.selects()}
|
<UserDetails
|
||||||
<UserDetails
|
userRes={this.state.userRes}
|
||||||
user_id={this.state.user_id}
|
sort={this.state.sort}
|
||||||
username={this.state.username}
|
page={this.state.page}
|
||||||
sort={this.state.sort}
|
limit={fetchLimit}
|
||||||
page={this.state.page}
|
enableDownvotes={this.state.siteRes.site.enable_downvotes}
|
||||||
limit={fetchLimit}
|
enableNsfw={this.state.siteRes.site.enable_nsfw}
|
||||||
enableDownvotes={this.state.siteRes.site.enable_downvotes}
|
view={this.state.view}
|
||||||
enableNsfw={this.state.siteRes.site.enable_nsfw}
|
onPageChange={this.handlePageChange}
|
||||||
admins={this.state.siteRes.admins}
|
/>
|
||||||
view={this.state.view}
|
|
||||||
onPageChange={this.handlePageChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{!this.state.loading && (
|
|
||||||
<div class="col-12 col-md-4">
|
|
||||||
{this.isCurrentUser && this.userSettings()}
|
|
||||||
{this.moderates()}
|
|
||||||
{this.follows()}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</div>
|
{!this.state.loading && (
|
||||||
|
<div class="col-12 col-md-4">
|
||||||
|
{this.isCurrentUser && this.userSettings()}
|
||||||
|
{this.moderates()}
|
||||||
|
{this.follows()}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -362,7 +382,7 @@ export class User extends Component<any, UserState> {
|
||||||
hideHot
|
hideHot
|
||||||
/>
|
/>
|
||||||
<a
|
<a
|
||||||
href={`/feeds/u/${this.state.username}.xml?sort=${this.state.sort}`}
|
href={`/feeds/u/${this.state.userName}.xml?sort=${this.state.sort}`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
title="RSS"
|
title="RSS"
|
||||||
|
@ -376,14 +396,11 @@ export class User extends Component<any, UserState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
userInfo() {
|
userInfo() {
|
||||||
let user = this.state.user;
|
let user = this.state.userRes.user;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<BannerIconHeader
|
<BannerIconHeader banner={user.banner} icon={user.avatar} />
|
||||||
banner={this.state.user.banner}
|
|
||||||
icon={this.state.user.avatar}
|
|
||||||
/>
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<div class="">
|
<div class="">
|
||||||
<div class="mb-0 d-flex flex-wrap">
|
<div class="mb-0 d-flex flex-wrap">
|
||||||
|
@ -420,17 +437,17 @@ export class User extends Component<any, UserState> {
|
||||||
<>
|
<>
|
||||||
<a
|
<a
|
||||||
className={`d-flex align-self-start btn btn-secondary ml-2 ${
|
className={`d-flex align-self-start btn btn-secondary ml-2 ${
|
||||||
!this.state.user.matrix_user_id && 'invisible'
|
!user.matrix_user_id && 'invisible'
|
||||||
}`}
|
}`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
href={`https://matrix.to/#/${this.state.user.matrix_user_id}`}
|
href={`https://matrix.to/#/${user.matrix_user_id}`}
|
||||||
>
|
>
|
||||||
{i18n.t('send_secure_message')}
|
{i18n.t('send_secure_message')}
|
||||||
</a>
|
</a>
|
||||||
<Link
|
<Link
|
||||||
class="d-flex align-self-start btn btn-secondary ml-2"
|
class="d-flex align-self-start btn btn-secondary ml-2"
|
||||||
to={`/create_private_message/recipient/${this.state.user.id}`}
|
to={`/create_private_message/recipient/${user.id}`}
|
||||||
>
|
>
|
||||||
{i18n.t('send_message')}
|
{i18n.t('send_message')}
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -818,12 +835,12 @@ export class User extends Component<any, UserState> {
|
||||||
moderates() {
|
moderates() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{this.state.moderates.length > 0 && (
|
{this.state.userRes.moderates.length > 0 && (
|
||||||
<div class="card bg-transparent border-secondary mb-3">
|
<div class="card bg-transparent border-secondary mb-3">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5>{i18n.t('moderates')}</h5>
|
<h5>{i18n.t('moderates')}</h5>
|
||||||
<ul class="list-unstyled mb-0">
|
<ul class="list-unstyled mb-0">
|
||||||
{this.state.moderates.map(community => (
|
{this.state.userRes.moderates.map(community => (
|
||||||
<li>
|
<li>
|
||||||
<Link to={`/c/${community.community_name}`}>
|
<Link to={`/c/${community.community_name}`}>
|
||||||
{community.community_name}
|
{community.community_name}
|
||||||
|
@ -841,12 +858,12 @@ export class User extends Component<any, UserState> {
|
||||||
follows() {
|
follows() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{this.state.follows.length > 0 && (
|
{this.state.userRes.follows.length > 0 && (
|
||||||
<div class="card bg-transparent border-secondary mb-3">
|
<div class="card bg-transparent border-secondary mb-3">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5>{i18n.t('subscribed')}</h5>
|
<h5>{i18n.t('subscribed')}</h5>
|
||||||
<ul class="list-unstyled mb-0">
|
<ul class="list-unstyled mb-0">
|
||||||
{this.state.follows.map(community => (
|
{this.state.userRes.follows.map(community => (
|
||||||
<li>
|
<li>
|
||||||
<Link to={`/c/${community.community_name}`}>
|
<Link to={`/c/${community.community_name}`}>
|
||||||
{community.community_name}
|
{community.community_name}
|
||||||
|
@ -866,7 +883,7 @@ export class User extends Component<any, UserState> {
|
||||||
const viewStr = paramUpdates.view || UserDetailsView[this.state.view];
|
const viewStr = paramUpdates.view || UserDetailsView[this.state.view];
|
||||||
const sortStr = paramUpdates.sort || this.state.sort;
|
const sortStr = paramUpdates.sort || this.state.sort;
|
||||||
this.props.history.push(
|
this.props.history.push(
|
||||||
`/u/${this.state.username}/view/${viewStr}/sort/${sortStr}/page/${page}`
|
`/u/${this.state.userName}/view/${viewStr}/sort/${sortStr}/page/${page}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -966,7 +983,7 @@ export class User extends Component<any, UserState> {
|
||||||
i.state.userSettingsForm.matrix_user_id = event.target.value;
|
i.state.userSettingsForm.matrix_user_id = event.target.value;
|
||||||
if (
|
if (
|
||||||
i.state.userSettingsForm.matrix_user_id == '' &&
|
i.state.userSettingsForm.matrix_user_id == '' &&
|
||||||
!i.state.user.matrix_user_id
|
!i.state.userRes.user.matrix_user_id
|
||||||
) {
|
) {
|
||||||
i.state.userSettingsForm.matrix_user_id = undefined;
|
i.state.userSettingsForm.matrix_user_id = undefined;
|
||||||
}
|
}
|
||||||
|
@ -1029,6 +1046,33 @@ export class User extends Component<any, UserState> {
|
||||||
WebSocketService.Instance.deleteAccount(i.state.deleteAccountForm);
|
WebSocketService.Instance.deleteAccount(i.state.deleteAccountForm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setUserInfo() {
|
||||||
|
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.banner = UserService.Instance.user.banner;
|
||||||
|
this.state.userSettingsForm.preferred_username =
|
||||||
|
UserService.Instance.user.preferred_username;
|
||||||
|
this.state.userSettingsForm.show_avatars =
|
||||||
|
UserService.Instance.user.show_avatars;
|
||||||
|
this.state.userSettingsForm.email = UserService.Instance.user.email;
|
||||||
|
this.state.userSettingsForm.bio = UserService.Instance.user.bio;
|
||||||
|
this.state.userSettingsForm.send_notifications_to_email =
|
||||||
|
UserService.Instance.user.send_notifications_to_email;
|
||||||
|
this.state.userSettingsForm.matrix_user_id =
|
||||||
|
UserService.Instance.user.matrix_user_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
parseMessage(msg: WebSocketJsonResponse) {
|
parseMessage(msg: WebSocketJsonResponse) {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
const res = wsJsonToRes(msg);
|
const res = wsJsonToRes(msg);
|
||||||
|
@ -1042,50 +1086,24 @@ export class User extends Component<any, UserState> {
|
||||||
userSettingsLoading: false,
|
userSettingsLoading: false,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
} else if (msg.reconnect) {
|
||||||
|
this.fetchUserData();
|
||||||
} else if (res.op == UserOperation.GetUserDetails) {
|
} else if (res.op == UserOperation.GetUserDetails) {
|
||||||
// Since the UserDetails contains posts/comments as well as some general user info we listen here as well
|
// 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
|
// and set the parent state if it is not set or differs
|
||||||
|
// TODO this might need to get abstracted
|
||||||
const data = res.data as UserDetailsResponse;
|
const data = res.data as UserDetailsResponse;
|
||||||
|
this.state.userRes = data;
|
||||||
if (this.state.user.id !== data.user.id) {
|
this.setUserInfo();
|
||||||
this.state.user = data.user;
|
this.state.loading = false;
|
||||||
this.state.follows = data.follows;
|
this.setState(this.state);
|
||||||
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.banner = UserService.Instance.user.banner;
|
|
||||||
this.state.userSettingsForm.preferred_username =
|
|
||||||
UserService.Instance.user.preferred_username;
|
|
||||||
this.state.userSettingsForm.show_avatars =
|
|
||||||
UserService.Instance.user.show_avatars;
|
|
||||||
this.state.userSettingsForm.email = UserService.Instance.user.email;
|
|
||||||
this.state.userSettingsForm.bio = UserService.Instance.user.bio;
|
|
||||||
this.state.userSettingsForm.send_notifications_to_email =
|
|
||||||
UserService.Instance.user.send_notifications_to_email;
|
|
||||||
this.state.userSettingsForm.matrix_user_id =
|
|
||||||
UserService.Instance.user.matrix_user_id;
|
|
||||||
}
|
|
||||||
this.state.loading = false;
|
|
||||||
this.setState(this.state);
|
|
||||||
}
|
|
||||||
} else if (res.op == UserOperation.SaveUserSettings) {
|
} else if (res.op == UserOperation.SaveUserSettings) {
|
||||||
const data = res.data as LoginResponse;
|
const data = res.data as LoginResponse;
|
||||||
UserService.Instance.login(data);
|
UserService.Instance.login(data);
|
||||||
this.state.user.bio = this.state.userSettingsForm.bio;
|
this.state.userRes.user.bio = this.state.userSettingsForm.bio;
|
||||||
this.state.user.preferred_username = this.state.userSettingsForm.preferred_username;
|
this.state.userRes.user.preferred_username = this.state.userSettingsForm.preferred_username;
|
||||||
this.state.user.banner = this.state.userSettingsForm.banner;
|
this.state.userRes.user.banner = this.state.userSettingsForm.banner;
|
||||||
this.state.user.avatar = this.state.userSettingsForm.avatar;
|
this.state.userRes.user.avatar = this.state.userSettingsForm.avatar;
|
||||||
this.state.userSettingsLoading = false;
|
this.state.userSettingsLoading = false;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
|
||||||
|
@ -1096,14 +1114,47 @@ export class User extends Component<any, UserState> {
|
||||||
deleteAccountShowConfirm: false,
|
deleteAccountShowConfirm: false,
|
||||||
});
|
});
|
||||||
this.context.router.history.push('/');
|
this.context.router.history.push('/');
|
||||||
} else if (res.op == UserOperation.GetSite) {
|
|
||||||
const data = res.data as GetSiteResponse;
|
|
||||||
this.state.siteRes = data;
|
|
||||||
this.setState(this.state);
|
|
||||||
} else if (res.op == UserOperation.AddAdmin) {
|
} else if (res.op == UserOperation.AddAdmin) {
|
||||||
const data = res.data as AddAdminResponse;
|
const data = res.data as AddAdminResponse;
|
||||||
this.state.siteRes.admins = data.admins;
|
this.state.siteRes.admins = data.admins;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
} else if (res.op == UserOperation.CreateCommentLike) {
|
||||||
|
const data = res.data as CommentResponse;
|
||||||
|
createCommentLikeRes(data, this.state.userRes.comments);
|
||||||
|
this.setState(this.state);
|
||||||
|
} else if (
|
||||||
|
res.op == UserOperation.EditComment ||
|
||||||
|
res.op == UserOperation.DeleteComment ||
|
||||||
|
res.op == UserOperation.RemoveComment
|
||||||
|
) {
|
||||||
|
const data = res.data as CommentResponse;
|
||||||
|
editCommentRes(data, this.state.userRes.comments);
|
||||||
|
this.setState(this.state);
|
||||||
|
} 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.userRes.comments);
|
||||||
|
this.setState(this.state);
|
||||||
|
} else if (res.op == UserOperation.CreatePostLike) {
|
||||||
|
const data = res.data as PostResponse;
|
||||||
|
createPostLikeFindRes(data, this.state.userRes.posts);
|
||||||
|
this.setState(this.state);
|
||||||
|
} else if (res.op == UserOperation.BanUser) {
|
||||||
|
const data = res.data as BanUserResponse;
|
||||||
|
this.state.userRes.comments
|
||||||
|
.filter(c => c.creator_id == data.user.id)
|
||||||
|
.forEach(c => (c.banned = data.banned));
|
||||||
|
this.state.userRes.posts
|
||||||
|
.filter(c => c.creator_id == data.user.id)
|
||||||
|
.forEach(c => (c.banned = data.banned));
|
||||||
|
this.setState(this.state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,8 +64,13 @@ export const routes: IRoutePropsWithFetch[] = [
|
||||||
{
|
{
|
||||||
path: `/post/:id/comment/:comment_id`,
|
path: `/post/:id/comment/:comment_id`,
|
||||||
component: Post,
|
component: Post,
|
||||||
|
fetchInitialData: (auth, path) => Post.fetchInitialData(auth, path),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: `/post/:id`,
|
||||||
|
component: Post,
|
||||||
|
fetchInitialData: (auth, path) => Post.fetchInitialData(auth, path),
|
||||||
},
|
},
|
||||||
{ path: `/post/:id`, component: Post },
|
|
||||||
{
|
{
|
||||||
path: `/c/:name/data_type/:data_type/sort/:sort/page/:page`,
|
path: `/c/:name/data_type/:data_type/sort/:sort/page/:page`,
|
||||||
component: Community,
|
component: Community,
|
||||||
|
@ -84,10 +89,23 @@ export const routes: IRoutePropsWithFetch[] = [
|
||||||
{
|
{
|
||||||
path: `/u/:username/view/:view/sort/:sort/page/:page`,
|
path: `/u/:username/view/:view/sort/:sort/page/:page`,
|
||||||
component: User,
|
component: User,
|
||||||
|
fetchInitialData: (auth, path) => User.fetchInitialData(auth, path),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: `/user/:id`,
|
||||||
|
component: User,
|
||||||
|
fetchInitialData: (auth, path) => User.fetchInitialData(auth, path),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: `/u/:username`,
|
||||||
|
component: User,
|
||||||
|
fetchInitialData: (auth, path) => User.fetchInitialData(auth, path),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: `/inbox`,
|
||||||
|
component: Inbox,
|
||||||
|
fetchInitialData: (auth, path) => Inbox.fetchInitialData(auth, path),
|
||||||
},
|
},
|
||||||
{ path: `/user/:id`, component: User },
|
|
||||||
{ path: `/u/:username`, component: User },
|
|
||||||
{ path: `/inbox`, component: Inbox },
|
|
||||||
{
|
{
|
||||||
path: `/modlog/community/:community_id`,
|
path: `/modlog/community/:community_id`,
|
||||||
component: Modlog,
|
component: Modlog,
|
||||||
|
|
|
@ -31,7 +31,9 @@ export class UserService {
|
||||||
|
|
||||||
public login(res: LoginResponse) {
|
public login(res: LoginResponse) {
|
||||||
this.setClaims(res.jwt);
|
this.setClaims(res.jwt);
|
||||||
IsomorphicCookie.save('jwt', res.jwt, { expires: 365 });
|
let expires = new Date();
|
||||||
|
expires.setDate(expires.getDate() + 365);
|
||||||
|
IsomorphicCookie.save('jwt', res.jwt, { expires });
|
||||||
console.log('jwt cookie set');
|
console.log('jwt cookie set');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -845,6 +845,18 @@ export function getRecipientIdFromProps(props: any): number {
|
||||||
: 1;
|
: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getIdFromProps(props: any): number {
|
||||||
|
return Number(props.match.params.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCommentIdFromProps(props: any): number {
|
||||||
|
return Number(props.match.params.comment_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUsernameFromProps(props: any): string {
|
||||||
|
return props.match.params.username;
|
||||||
|
}
|
||||||
|
|
||||||
export function editCommentRes(data: CommentResponse, comments: Comment[]) {
|
export function editCommentRes(data: CommentResponse, comments: Comment[]) {
|
||||||
let found = comments.find(c => c.id == data.comment.id);
|
let found = comments.find(c => c.id == data.comment.id);
|
||||||
if (found) {
|
if (found) {
|
||||||
|
|
Loading…
Reference in a new issue