A few more fixes.
This commit is contained in:
parent
e64b71339d
commit
f981f103ef
19 changed files with 249 additions and 116 deletions
41
README.md
41
README.md
|
@ -1,21 +1,20 @@
|
|||
# lemmy-ui
|
||||
|
||||
The official web app for [Lemmy](https://github.com/LemmyNet/lemmy), written in inferno.
|
||||
|
||||
Based off of MrFoxPro's [inferno-isomorphic-template](https://github.com/MrFoxPro/inferno-isomorphic-template).
|
||||
|
||||
## Configuration
|
||||
|
||||
The following environment variables can be used to configure lemmy-ui:
|
||||
|
||||
`ENV_VAR` | type | default | description
|
||||
--- | --- | --- | ---
|
||||
`LEMMY_UI_HOST` | `string` | `0.0.0.0:1234` | The IP / port that the lemmy-ui isomorphic node server is hosted at.
|
||||
`LEMMY_UI_LEMMY_INTERNAL_HOST` | `string` | `0.0.0.0:8536` | The internal IP / port that lemmy is hosted at. Often `lemmy:8536` if using docker.
|
||||
`LEMMY_UI_LEMMY_EXTERNAL_HOST` | `string` | `0.0.0.0:8536` | The external IP / port that lemmy is hosted at. Often `DOMAIN.TLD`.
|
||||
`LEMMY_UI_LEMMY_WS_HOST` | `string` | `0.0.0.0:8536` | An alternate location for lemmy's websocket address. Not usually necessary.
|
||||
`LEMMY_UI_HTTPS` | `bool` | `false` | Whether to use https.
|
||||
`LEMMY_UI_EXTRA_THEMES_FOLDER` | `string` | `./extra_themes` | A location for additional lemmy css themes.
|
||||
`LEMMY_UI_DEBUG` | `bool` | `false` | Loads the [Eruda](https://github.com/liriliri/eruda) debugging utility.
|
||||
`LEMMY_UI_DISABLE_CSP` | `bool` | `false` | Disables CSP security headers
|
||||
`LEMMY_UI_CUSTOM_HTML_HEADER` | `string` | | Injects a custom script into `<head>`.
|
||||
# Lemmy-UI
|
||||
|
||||
The official web app for [Lemmy](https://github.com/LemmyNet/lemmy), written in inferno.
|
||||
|
||||
Based off of MrFoxPro's [inferno-isomorphic-template](https://github.com/MrFoxPro/inferno-isomorphic-template).
|
||||
|
||||
## Configuration
|
||||
|
||||
The following environment variables can be used to configure lemmy-ui:
|
||||
|
||||
| `ENV_VAR` | type | default | description |
|
||||
| ------------------------------ | -------- | ---------------- | ----------------------------------------------------------------------------------- |
|
||||
| `LEMMY_UI_HOST` | `string` | `0.0.0.0:1234` | The IP / port that the lemmy-ui isomorphic node server is hosted at. |
|
||||
| `LEMMY_UI_LEMMY_INTERNAL_HOST` | `string` | `0.0.0.0:8536` | The internal IP / port that lemmy is hosted at. Often `lemmy:8536` if using docker. |
|
||||
| `LEMMY_UI_LEMMY_EXTERNAL_HOST` | `string` | `0.0.0.0:8536` | The external IP / port that lemmy is hosted at. Often `DOMAIN.TLD`. |
|
||||
| `LEMMY_UI_HTTPS` | `bool` | `false` | Whether to use https. |
|
||||
| `LEMMY_UI_EXTRA_THEMES_FOLDER` | `string` | `./extra_themes` | A location for additional lemmy css themes. |
|
||||
| `LEMMY_UI_DEBUG` | `bool` | `false` | Loads the [Eruda](https://github.com/liriliri/eruda) debugging utility. |
|
||||
| `LEMMY_UI_DISABLE_CSP` | `bool` | `false` | Disables CSP security headers |
|
||||
| `LEMMY_UI_CUSTOM_HTML_HEADER` | `string` | | Injects a custom script into `<head>`. |
|
||||
|
|
|
@ -14,6 +14,7 @@ interface CommentFormProps {
|
|||
* Can either be the parent, or the editable comment. The right side is a postId.
|
||||
*/
|
||||
node: CommentNodeI | number;
|
||||
finished?: boolean;
|
||||
edit?: boolean;
|
||||
disabled?: boolean;
|
||||
focus?: boolean;
|
||||
|
@ -24,25 +25,11 @@ interface CommentFormProps {
|
|||
onEditComment(form: EditComment): void;
|
||||
}
|
||||
|
||||
interface CommentFormState {
|
||||
buttonTitle: string;
|
||||
}
|
||||
|
||||
export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
||||
state: CommentFormState = {
|
||||
buttonTitle:
|
||||
typeof this.props.node === "number"
|
||||
? capitalizeFirstLetter(i18n.t("post"))
|
||||
: this.props.edit
|
||||
? capitalizeFirstLetter(i18n.t("save"))
|
||||
: capitalizeFirstLetter(i18n.t("reply")),
|
||||
};
|
||||
|
||||
export class CommentForm extends Component<CommentFormProps, any> {
|
||||
constructor(props: any, context: any) {
|
||||
super(props, context);
|
||||
|
||||
this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
|
||||
this.handleReplyCancel = this.handleReplyCancel.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -59,12 +46,13 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
|||
<MarkdownTextArea
|
||||
initialContent={initialContent}
|
||||
showLanguage
|
||||
buttonTitle={this.state.buttonTitle}
|
||||
buttonTitle={this.buttonTitle}
|
||||
finished={this.props.finished}
|
||||
replyType={typeof this.props.node !== "number"}
|
||||
focus={this.props.focus}
|
||||
disabled={this.props.disabled}
|
||||
onSubmit={this.handleCommentSubmit}
|
||||
onReplyCancel={this.handleReplyCancel}
|
||||
onReplyCancel={this.props.onReplyCancel}
|
||||
placeholder={i18n.t("comment_here")}
|
||||
allLanguages={this.props.allLanguages}
|
||||
siteLanguages={this.props.siteLanguages}
|
||||
|
@ -84,6 +72,14 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
|||
);
|
||||
}
|
||||
|
||||
get buttonTitle(): string {
|
||||
return typeof this.props.node === "number"
|
||||
? capitalizeFirstLetter(i18n.t("post"))
|
||||
: this.props.edit
|
||||
? capitalizeFirstLetter(i18n.t("save"))
|
||||
: capitalizeFirstLetter(i18n.t("reply"));
|
||||
}
|
||||
|
||||
handleCommentSubmit(content: string, form_id: string, language_id?: number) {
|
||||
let node = this.props.node;
|
||||
|
||||
|
@ -100,6 +96,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
|||
if (this.props.edit) {
|
||||
let comment_id = node.comment_view.comment.id;
|
||||
this.props.onEditComment({
|
||||
content,
|
||||
comment_id,
|
||||
form_id,
|
||||
language_id,
|
||||
|
@ -119,8 +116,4 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleReplyCancel() {
|
||||
this.props.onReplyCancel?.();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@ interface CommentNodeProps {
|
|||
allLanguages: Language[];
|
||||
siteLanguages: number[];
|
||||
hideImages?: boolean;
|
||||
finished: Map<CommentId, boolean | undefined>;
|
||||
onSaveComment(form: SaveComment): void;
|
||||
onCommentReplyRead(form: MarkCommentReplyAsRead): void;
|
||||
onPersonMentionRead(form: MarkPersonMentionAsRead): void;
|
||||
|
@ -197,6 +198,22 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
): void {
|
||||
if (this.props != nextProps) {
|
||||
this.setState({
|
||||
showReply: false,
|
||||
showEdit: false,
|
||||
showRemoveDialog: false,
|
||||
showBanDialog: false,
|
||||
removeData: false,
|
||||
banType: BanType.Community,
|
||||
showPurgeDialog: false,
|
||||
purgeType: PurgeType.Person,
|
||||
collapsed: false,
|
||||
viewSource: false,
|
||||
showAdvanced: false,
|
||||
showConfirmTransferSite: false,
|
||||
showConfirmTransferCommunity: false,
|
||||
showConfirmAppointAsMod: false,
|
||||
showConfirmAppointAsAdmin: false,
|
||||
showReportDialog: false,
|
||||
createOrEditCommentLoading: false,
|
||||
upvoteLoading: false,
|
||||
downvoteLoading: false,
|
||||
|
@ -389,6 +406,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
edit
|
||||
onReplyCancel={this.handleReplyCancel}
|
||||
disabled={this.props.locked}
|
||||
finished={this.props.finished.get(
|
||||
this.props.node.comment_view.comment.id
|
||||
)}
|
||||
focus
|
||||
allLanguages={this.props.allLanguages}
|
||||
siteLanguages={this.props.siteLanguages}
|
||||
|
@ -1130,6 +1150,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
node={node}
|
||||
onReplyCancel={this.handleReplyCancel}
|
||||
disabled={this.props.locked}
|
||||
finished={this.props.finished.get(
|
||||
this.props.node.comment_view.comment.id
|
||||
)}
|
||||
focus
|
||||
allLanguages={this.props.allLanguages}
|
||||
siteLanguages={this.props.siteLanguages}
|
||||
|
@ -1148,6 +1171,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
allLanguages={this.props.allLanguages}
|
||||
siteLanguages={this.props.siteLanguages}
|
||||
hideImages={this.props.hideImages}
|
||||
finished={this.props.finished}
|
||||
onCommentReplyRead={this.props.onCommentReplyRead}
|
||||
onPersonMentionRead={this.props.onPersonMentionRead}
|
||||
onCreateComment={this.props.onCreateComment}
|
||||
|
@ -1457,7 +1481,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
|||
read: !cv.person_mention.read,
|
||||
auth: myAuthRequired(),
|
||||
});
|
||||
} else if (this.isCommentReplyType(cv)) {
|
||||
} else if (i.isCommentReplyType(cv)) {
|
||||
i.props.onCommentReplyRead({
|
||||
comment_reply_id: cv.comment_reply.id,
|
||||
read: !cv.comment_reply.read,
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
BanFromCommunity,
|
||||
BanPerson,
|
||||
BlockPerson,
|
||||
CommentId,
|
||||
CommunityModeratorView,
|
||||
CreateComment,
|
||||
CreateCommentLike,
|
||||
|
@ -43,6 +44,7 @@ interface CommentNodesProps {
|
|||
allLanguages: Language[];
|
||||
siteLanguages: number[];
|
||||
hideImages?: boolean;
|
||||
finished: Map<CommentId, boolean | undefined>;
|
||||
onSaveComment(form: SaveComment): void;
|
||||
onCommentReplyRead(form: MarkCommentReplyAsRead): void;
|
||||
onPersonMentionRead(form: MarkPersonMentionAsRead): void;
|
||||
|
@ -94,6 +96,7 @@ export class CommentNodes extends Component<CommentNodesProps, any> {
|
|||
hideImages={this.props.hideImages}
|
||||
onCommentReplyRead={this.props.onCommentReplyRead}
|
||||
onPersonMentionRead={this.props.onPersonMentionRead}
|
||||
finished={this.props.finished}
|
||||
onCreateComment={this.props.onCreateComment}
|
||||
onEditComment={this.props.onEditComment}
|
||||
onCommentVote={this.props.onCommentVote}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, linkEvent } from "inferno";
|
||||
import { Component, InfernoNode, linkEvent } from "inferno";
|
||||
import { T } from "inferno-i18next-dess";
|
||||
import {
|
||||
CommentReportView,
|
||||
|
@ -32,6 +32,14 @@ export class CommentReport extends Component<
|
|||
super(props, context);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(
|
||||
nextProps: Readonly<{ children?: InfernoNode } & CommentReportProps>
|
||||
): void {
|
||||
if (this.props != nextProps) {
|
||||
this.setState({ loading: false });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let r = this.props.report;
|
||||
let comment = r.comment;
|
||||
|
@ -73,6 +81,7 @@ export class CommentReport extends Component<
|
|||
siteLanguages={[]}
|
||||
hideImages
|
||||
// All of these are unused, since its viewonly
|
||||
finished={new Map()}
|
||||
onSaveComment={() => {}}
|
||||
onBlockPerson={() => {}}
|
||||
onDeleteComment={() => {}}
|
||||
|
|
|
@ -36,6 +36,7 @@ interface MarkdownTextAreaProps {
|
|||
replyType?: boolean;
|
||||
focus?: boolean;
|
||||
disabled?: boolean;
|
||||
finished?: boolean;
|
||||
showLanguage?: boolean;
|
||||
hideNavigationWarnings?: boolean;
|
||||
onContentChange?(val: string): void;
|
||||
|
@ -113,12 +114,7 @@ export class MarkdownTextArea extends Component<
|
|||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: MarkdownTextAreaProps) {
|
||||
if (
|
||||
nextProps != this.props &&
|
||||
// Don't trigger this on an initial content change (IE the form field version)
|
||||
// This should only trigger in an
|
||||
this.props.initialContent == nextProps.initialContent
|
||||
) {
|
||||
if (nextProps.finished) {
|
||||
this.setState({
|
||||
previewMode: false,
|
||||
imageUploadStatus: undefined,
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
BanPersonResponse,
|
||||
BlockCommunity,
|
||||
BlockPerson,
|
||||
CommentId,
|
||||
CommentReplyResponse,
|
||||
CommentResponse,
|
||||
CommunityResponse,
|
||||
|
@ -73,6 +74,7 @@ import {
|
|||
enableDownvotes,
|
||||
enableNsfw,
|
||||
fetchLimit,
|
||||
getCommentParentId,
|
||||
getDataTypeString,
|
||||
getPageFromString,
|
||||
getQueryParams,
|
||||
|
@ -108,6 +110,7 @@ interface State {
|
|||
commentsRes: RequestState<GetCommentsResponse>;
|
||||
siteRes: GetSiteResponse;
|
||||
showSidebarMobile: boolean;
|
||||
finished: Map<CommentId, boolean | undefined>;
|
||||
}
|
||||
|
||||
interface CommunityProps {
|
||||
|
@ -147,6 +150,7 @@ export class Community extends Component<
|
|||
commentsRes: { state: "empty" },
|
||||
siteRes: this.isoData.site_res,
|
||||
showSidebarMobile: false,
|
||||
finished: new Map(),
|
||||
};
|
||||
|
||||
constructor(props: RouteComponentProps<{ name: string }>, context: any) {
|
||||
|
@ -445,6 +449,7 @@ export class Community extends Component<
|
|||
<CommentNodes
|
||||
nodes={commentsToFlatNodes(this.state.commentsRes.data.comments)}
|
||||
viewType={CommentViewType.Flat}
|
||||
finished={this.state.finished}
|
||||
noIndent
|
||||
showContext
|
||||
enableDownvotes={enableDownvotes(site_res)}
|
||||
|
@ -706,16 +711,7 @@ export class Community extends Component<
|
|||
const createCommentRes = await apiWrapper(
|
||||
HttpService.client.createComment(form)
|
||||
);
|
||||
|
||||
this.setState(s => {
|
||||
if (
|
||||
s.commentsRes.state == "success" &&
|
||||
createCommentRes.state == "success"
|
||||
) {
|
||||
s.commentsRes.data.comments.unshift(createCommentRes.data.comment_view);
|
||||
}
|
||||
return s;
|
||||
});
|
||||
this.createAndUpdateComments(createCommentRes);
|
||||
}
|
||||
|
||||
async handleEditComment(form: EditComment) {
|
||||
|
@ -924,6 +920,22 @@ export class Community extends Component<
|
|||
res.data.comment_view,
|
||||
s.commentsRes.data.comments
|
||||
);
|
||||
s.finished.set(res.data.comment_view.comment.id, true);
|
||||
}
|
||||
return s;
|
||||
});
|
||||
}
|
||||
|
||||
createAndUpdateComments(res: RequestState<CommentResponse>) {
|
||||
this.setState(s => {
|
||||
if (s.commentsRes.state == "success" && res.state == "success") {
|
||||
s.commentsRes.data.comments.unshift(res.data.comment_view);
|
||||
|
||||
// Set finished for the parent
|
||||
s.finished.set(
|
||||
getCommentParentId(res.data.comment_view.comment) ?? 0,
|
||||
true
|
||||
);
|
||||
}
|
||||
return s;
|
||||
});
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
BanPerson,
|
||||
BanPersonResponse,
|
||||
BlockPerson,
|
||||
CommentId,
|
||||
CommentReplyResponse,
|
||||
CommentResponse,
|
||||
CreateComment,
|
||||
|
@ -67,6 +68,7 @@ import {
|
|||
enableDownvotes,
|
||||
enableNsfw,
|
||||
fetchLimit,
|
||||
getCommentParentId,
|
||||
getDataTypeString,
|
||||
getPageFromString,
|
||||
getQueryParams,
|
||||
|
@ -108,6 +110,7 @@ interface HomeState {
|
|||
subscribedCollapsed: boolean;
|
||||
tagline?: string;
|
||||
siteRes: GetSiteResponse;
|
||||
finished: Map<CommentId, boolean | undefined>;
|
||||
}
|
||||
|
||||
interface HomeProps {
|
||||
|
@ -186,6 +189,7 @@ export class Home extends Component<any, HomeState> {
|
|||
showTrendingMobile: false,
|
||||
showSidebarMobile: false,
|
||||
subscribedCollapsed: false,
|
||||
finished: new Map(),
|
||||
};
|
||||
|
||||
constructor(props: any, context: any) {
|
||||
|
@ -646,6 +650,7 @@ export class Home extends Component<any, HomeState> {
|
|||
<CommentNodes
|
||||
nodes={commentsToFlatNodes(comments)}
|
||||
viewType={CommentViewType.Flat}
|
||||
finished={this.state.finished}
|
||||
noIndent
|
||||
showCommunity
|
||||
showContext
|
||||
|
@ -864,15 +869,7 @@ export class Home extends Component<any, HomeState> {
|
|||
HttpService.client.createComment(form)
|
||||
);
|
||||
|
||||
this.setState(s => {
|
||||
if (
|
||||
s.commentsRes.state == "success" &&
|
||||
createCommentRes.state == "success"
|
||||
) {
|
||||
s.commentsRes.data.comments.unshift(createCommentRes.data.comment_view);
|
||||
}
|
||||
return s;
|
||||
});
|
||||
this.createAndUpdateComments(createCommentRes);
|
||||
}
|
||||
|
||||
async handleEditComment(form: EditComment) {
|
||||
|
@ -1057,6 +1054,22 @@ export class Home extends Component<any, HomeState> {
|
|||
res.data.comment_view,
|
||||
s.commentsRes.data.comments
|
||||
);
|
||||
s.finished.set(res.data.comment_view.comment.id, true);
|
||||
}
|
||||
return s;
|
||||
});
|
||||
}
|
||||
|
||||
createAndUpdateComments(res: RequestState<CommentResponse>) {
|
||||
this.setState(s => {
|
||||
if (s.commentsRes.state == "success" && res.state == "success") {
|
||||
s.commentsRes.data.comments.unshift(res.data.comment_view);
|
||||
|
||||
// Set finished for the parent
|
||||
s.finished.set(
|
||||
getCommentParentId(res.data.comment_view.comment) ?? 0,
|
||||
true
|
||||
);
|
||||
}
|
||||
return s;
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
BanPerson,
|
||||
BanPersonResponse,
|
||||
BlockPerson,
|
||||
CommentId,
|
||||
CommentReplyResponse,
|
||||
CommentReplyView,
|
||||
CommentReportResponse,
|
||||
|
@ -64,6 +65,7 @@ import {
|
|||
editPrivateMessages,
|
||||
enableDownvotes,
|
||||
fetchLimit,
|
||||
getCommentParentId,
|
||||
isBrowser,
|
||||
isInitialRoute,
|
||||
myAuth,
|
||||
|
@ -114,6 +116,7 @@ interface InboxState {
|
|||
sort: CommentSortType;
|
||||
page: number;
|
||||
siteRes: GetSiteResponse;
|
||||
finished: Map<CommentId, boolean | undefined>;
|
||||
}
|
||||
|
||||
export class Inbox extends Component<any, InboxState> {
|
||||
|
@ -128,6 +131,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
mentionsRes: { state: "empty" },
|
||||
messagesRes: { state: "empty" },
|
||||
markAllAsReadRes: { state: "empty" },
|
||||
finished: new Map(),
|
||||
};
|
||||
|
||||
constructor(props: any, context: any) {
|
||||
|
@ -434,6 +438,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
{ comment_view: i.view as CommentView, children: [], depth: 0 },
|
||||
]}
|
||||
viewType={CommentViewType.Flat}
|
||||
finished={this.state.finished}
|
||||
noIndent
|
||||
markable
|
||||
showCommunity
|
||||
|
@ -472,6 +477,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
depth: 0,
|
||||
},
|
||||
]}
|
||||
finished={this.state.finished}
|
||||
viewType={CommentViewType.Flat}
|
||||
noIndent
|
||||
markable
|
||||
|
@ -529,7 +535,9 @@ export class Inbox extends Component<any, InboxState> {
|
|||
</h5>
|
||||
);
|
||||
} else {
|
||||
return <div>{this.buildCombined().map(this.renderReplyType)}</div>;
|
||||
return (
|
||||
<div>{this.buildCombined().map(r => this.renderReplyType(r))}</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -548,6 +556,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
<CommentNodes
|
||||
nodes={commentsToFlatNodes(replies)}
|
||||
viewType={CommentViewType.Flat}
|
||||
finished={this.state.finished}
|
||||
noIndent
|
||||
markable
|
||||
showCommunity
|
||||
|
@ -597,6 +606,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
key={umv.person_mention.id}
|
||||
nodes={[{ comment_view: umv, children: [], depth: 0 }]}
|
||||
viewType={CommentViewType.Flat}
|
||||
finished={this.state.finished}
|
||||
noIndent
|
||||
markable
|
||||
showCommunity
|
||||
|
@ -683,7 +693,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
if (auth) {
|
||||
// It can be /u/me, or /username/1
|
||||
let repliesForm: GetReplies = {
|
||||
sort: "New",
|
||||
sort,
|
||||
unread_only: true,
|
||||
page: 1,
|
||||
limit: fetchLimit,
|
||||
|
@ -772,7 +782,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
),
|
||||
});
|
||||
|
||||
if (this.state.markAllAsReadRes.state == "success") {
|
||||
if (i.state.markAllAsReadRes.state == "success") {
|
||||
i.setState({
|
||||
repliesRes: { state: "empty" },
|
||||
mentionsRes: { state: "empty" },
|
||||
|
@ -819,7 +829,8 @@ export class Inbox extends Component<any, InboxState> {
|
|||
const res = await apiWrapper(HttpService.client.createComment(form));
|
||||
|
||||
if (res.state == "success") {
|
||||
toast(i18n.t("created"));
|
||||
toast(i18n.t("reply_sent"));
|
||||
this.findAndUpdateComment(res);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -828,6 +839,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
|
||||
if (res.state == "success") {
|
||||
toast(i18n.t("edit"));
|
||||
this.findAndUpdateComment(res);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -835,6 +847,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
const res = await apiWrapper(HttpService.client.deleteComment(form));
|
||||
if (res.state == "success") {
|
||||
toast(i18n.t("deleted"));
|
||||
this.findAndUpdateComment(res);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -842,6 +855,7 @@ export class Inbox extends Component<any, InboxState> {
|
|||
const res = await apiWrapper(HttpService.client.removeComment(form));
|
||||
if (res.state == "success") {
|
||||
toast(i18n.t("remove_comment"));
|
||||
this.findAndUpdateComment(res);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1026,6 +1040,11 @@ export class Inbox extends Component<any, InboxState> {
|
|||
s.mentionsRes.data.mentions
|
||||
);
|
||||
}
|
||||
// Set finished for the parent
|
||||
s.finished.set(
|
||||
getCommentParentId(res.data.comment_view.comment) ?? 0,
|
||||
true
|
||||
);
|
||||
return s;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
BanFromCommunity,
|
||||
BanPerson,
|
||||
BlockPerson,
|
||||
CommentId,
|
||||
CommentView,
|
||||
CreateComment,
|
||||
CreateCommentLike,
|
||||
|
@ -42,6 +43,7 @@ import { PostListing } from "../post/post-listing";
|
|||
|
||||
interface PersonDetailsProps {
|
||||
personRes: GetPersonDetailsResponse;
|
||||
finished: Map<CommentId, boolean | undefined>;
|
||||
admins: PersonView[];
|
||||
allLanguages: Language[];
|
||||
siteLanguages: number[];
|
||||
|
@ -147,6 +149,7 @@ export class PersonDetails extends Component<PersonDetailsProps, any> {
|
|||
key={i.id}
|
||||
nodes={[{ comment_view: c, children: [], depth: 0 }]}
|
||||
viewType={CommentViewType.Flat}
|
||||
finished={this.props.finished}
|
||||
admins={this.props.admins}
|
||||
noBorder
|
||||
noIndent
|
||||
|
@ -255,6 +258,7 @@ export class PersonDetails extends Component<PersonDetailsProps, any> {
|
|||
nodes={commentsToFlatNodes(this.props.personRes.comments)}
|
||||
viewType={CommentViewType.Flat}
|
||||
admins={this.props.admins}
|
||||
finished={this.props.finished}
|
||||
noIndent
|
||||
showCommunity
|
||||
showContext
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
BanPerson,
|
||||
BanPersonResponse,
|
||||
BlockPerson,
|
||||
CommentId,
|
||||
CommentReplyResponse,
|
||||
CommentResponse,
|
||||
Community,
|
||||
|
@ -65,6 +66,7 @@ import {
|
|||
enableNsfw,
|
||||
fetchLimit,
|
||||
futureDaysToUnixTime,
|
||||
getCommentParentId,
|
||||
getPageFromString,
|
||||
getQueryParams,
|
||||
getQueryString,
|
||||
|
@ -100,6 +102,7 @@ interface ProfileState {
|
|||
showBanDialog: boolean;
|
||||
removeData: boolean;
|
||||
siteRes: GetSiteResponse;
|
||||
finished: Map<CommentId, boolean | undefined>;
|
||||
}
|
||||
|
||||
interface ProfileProps {
|
||||
|
@ -163,6 +166,7 @@ export class Profile extends Component<
|
|||
siteRes: this.isoData.site_res,
|
||||
showBanDialog: false,
|
||||
removeData: false,
|
||||
finished: new Map(),
|
||||
};
|
||||
|
||||
constructor(props: RouteComponentProps<{ username: string }>, context: any) {
|
||||
|
@ -333,6 +337,7 @@ export class Profile extends Component<
|
|||
sort={sort}
|
||||
page={page}
|
||||
limit={fetchLimit}
|
||||
finished={this.state.finished}
|
||||
enableDownvotes={enableDownvotes(siteRes)}
|
||||
enableNsfw={enableNsfw(siteRes)}
|
||||
view={view}
|
||||
|
@ -842,16 +847,7 @@ export class Profile extends Component<
|
|||
const createCommentRes = await apiWrapper(
|
||||
HttpService.client.createComment(form)
|
||||
);
|
||||
|
||||
this.setState(s => {
|
||||
if (
|
||||
s.personRes.state == "success" &&
|
||||
createCommentRes.state == "success"
|
||||
) {
|
||||
s.personRes.data.comments.unshift(createCommentRes.data.comment_view);
|
||||
}
|
||||
return s;
|
||||
});
|
||||
this.createAndUpdateComments(createCommentRes);
|
||||
}
|
||||
|
||||
async handleEditComment(form: EditComment) {
|
||||
|
@ -1033,6 +1029,21 @@ export class Profile extends Component<
|
|||
res.data.comment_view,
|
||||
s.personRes.data.comments
|
||||
);
|
||||
s.finished.set(res.data.comment_view.comment.id, true);
|
||||
}
|
||||
return s;
|
||||
});
|
||||
}
|
||||
|
||||
createAndUpdateComments(res: RequestState<CommentResponse>) {
|
||||
this.setState(s => {
|
||||
if (s.personRes.state == "success" && res.state == "success") {
|
||||
s.personRes.data.comments.unshift(res.data.comment_view);
|
||||
// Set finished for the parent
|
||||
s.finished.set(
|
||||
getCommentParentId(res.data.comment_view.comment) ?? 0,
|
||||
true
|
||||
);
|
||||
}
|
||||
return s;
|
||||
});
|
||||
|
|
|
@ -17,7 +17,6 @@ import {
|
|||
ResolvePostReport,
|
||||
ResolvePrivateMessageReport,
|
||||
} from "lemmy-js-client";
|
||||
import { Subscription } from "rxjs";
|
||||
import { i18n } from "../../i18next";
|
||||
import { InitialFetchRequest } from "../../interfaces";
|
||||
import { HttpService, UserService } from "../../services";
|
||||
|
@ -82,7 +81,6 @@ interface ReportsState {
|
|||
|
||||
export class Reports extends Component<any, ReportsState> {
|
||||
private isoData = setIsoData(this.context);
|
||||
private subscription?: Subscription;
|
||||
state: ReportsState = {
|
||||
commentReportsRes: { state: "empty" },
|
||||
postReportsRes: { state: "empty" },
|
||||
|
@ -130,9 +128,9 @@ export class Reports extends Component<any, ReportsState> {
|
|||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (isBrowser()) {
|
||||
this.subscription?.unsubscribe();
|
||||
async componentDidMount() {
|
||||
if (!isInitialRoute(this.isoData, this.context)) {
|
||||
await this.refetch();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,14 +467,14 @@ export class Reports extends Component<any, ReportsState> {
|
|||
await this.refetch();
|
||||
}
|
||||
|
||||
handleUnreadOrAllChange(i: Reports, event: any) {
|
||||
async handleUnreadOrAllChange(i: Reports, event: any) {
|
||||
i.setState({ unreadOrAll: Number(event.target.value), page: 1 });
|
||||
i.refetch();
|
||||
await i.refetch();
|
||||
}
|
||||
|
||||
handleMessageTypeChange(i: Reports, event: any) {
|
||||
async handleMessageTypeChange(i: Reports, event: any) {
|
||||
i.setState({ messageType: Number(event.target.value), page: 1 });
|
||||
i.refetch();
|
||||
await i.refetch();
|
||||
}
|
||||
|
||||
static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, linkEvent } from "inferno";
|
||||
import { Component, InfernoNode, linkEvent } from "inferno";
|
||||
import { T } from "inferno-i18next-dess";
|
||||
import { PostReportView, PostView, ResolvePostReport } from "lemmy-js-client";
|
||||
import { i18n } from "../../i18next";
|
||||
|
@ -25,6 +25,14 @@ export class PostReport extends Component<PostReportProps, PostReportState> {
|
|||
super(props, context);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(
|
||||
nextProps: Readonly<{ children?: InfernoNode } & PostReportProps>
|
||||
): void {
|
||||
if (this.props != nextProps) {
|
||||
this.setState({ loading: false });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let r = this.props.report;
|
||||
let resolver = r.resolver;
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
BanPersonResponse,
|
||||
BlockCommunity,
|
||||
BlockPerson,
|
||||
CommentId,
|
||||
CommentReplyResponse,
|
||||
CommentResponse,
|
||||
CommentSortType,
|
||||
|
@ -108,6 +109,7 @@ interface PostState {
|
|||
commentSectionRef?: RefObject<HTMLDivElement>;
|
||||
showSidebarMobile: boolean;
|
||||
maxCommentsShown: number;
|
||||
finished: Map<CommentId, boolean | undefined>;
|
||||
}
|
||||
|
||||
export class Post extends Component<any, PostState> {
|
||||
|
@ -124,6 +126,7 @@ export class Post extends Component<any, PostState> {
|
|||
siteRes: this.isoData.site_res,
|
||||
showSidebarMobile: false,
|
||||
maxCommentsShown: commentsShownInterval,
|
||||
finished: new Map(),
|
||||
};
|
||||
|
||||
constructor(props: any, context: any) {
|
||||
|
@ -382,6 +385,7 @@ export class Post extends Component<any, PostState> {
|
|||
siteLanguages={this.state.siteRes.discussion_languages}
|
||||
onCreateComment={this.handleCreateComment}
|
||||
onEditComment={this.handleEditComment}
|
||||
finished={this.state.finished.get(0)}
|
||||
/>
|
||||
<div className="d-block d-md-none">
|
||||
<button
|
||||
|
@ -511,6 +515,7 @@ export class Post extends Component<any, PostState> {
|
|||
admins={this.state.siteRes.admins}
|
||||
enableDownvotes={enableDownvotes(this.state.siteRes)}
|
||||
showContext
|
||||
finished={this.state.finished}
|
||||
allLanguages={this.state.siteRes.all_languages}
|
||||
siteLanguages={this.state.siteRes.discussion_languages}
|
||||
onSaveComment={this.handleSaveComment}
|
||||
|
@ -600,6 +605,7 @@ export class Post extends Component<any, PostState> {
|
|||
moderators={res.data.moderators}
|
||||
admins={this.state.siteRes.admins}
|
||||
enableDownvotes={enableDownvotes(this.state.siteRes)}
|
||||
finished={this.state.finished}
|
||||
allLanguages={this.state.siteRes.all_languages}
|
||||
siteLanguages={this.state.siteRes.discussion_languages}
|
||||
onSaveComment={this.handleSaveComment}
|
||||
|
@ -782,16 +788,7 @@ export class Post extends Component<any, PostState> {
|
|||
const createCommentRes = await apiWrapper(
|
||||
HttpService.client.createComment(form)
|
||||
);
|
||||
|
||||
this.setState(s => {
|
||||
if (
|
||||
s.commentsRes.state == "success" &&
|
||||
createCommentRes.state == "success"
|
||||
) {
|
||||
s.commentsRes.data.comments.unshift(createCommentRes.data.comment_view);
|
||||
}
|
||||
return s;
|
||||
});
|
||||
this.createAndUpdateComments(createCommentRes);
|
||||
}
|
||||
|
||||
async handleEditComment(form: EditComment) {
|
||||
|
@ -1021,6 +1018,21 @@ export class Post extends Component<any, PostState> {
|
|||
}
|
||||
}
|
||||
|
||||
createAndUpdateComments(res: RequestState<CommentResponse>) {
|
||||
this.setState(s => {
|
||||
if (s.commentsRes.state == "success" && res.state == "success") {
|
||||
s.commentsRes.data.comments.unshift(res.data.comment_view);
|
||||
|
||||
// Set finished for the parent
|
||||
s.finished.set(
|
||||
getCommentParentId(res.data.comment_view.comment) ?? 0,
|
||||
true
|
||||
);
|
||||
}
|
||||
return s;
|
||||
});
|
||||
}
|
||||
|
||||
findAndUpdateComment(res: RequestState<CommentResponse>) {
|
||||
this.setState(s => {
|
||||
if (s.commentsRes.state == "success" && res.state == "success") {
|
||||
|
@ -1028,6 +1040,7 @@ export class Post extends Component<any, PostState> {
|
|||
res.data.comment_view,
|
||||
s.commentsRes.data.comments
|
||||
);
|
||||
s.finished.set(res.data.comment_view.comment.id, true);
|
||||
}
|
||||
return s;
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Component } from "inferno";
|
||||
import {
|
||||
CreatePrivateMessage as CreatePrivateMessageI,
|
||||
GetPersonDetails,
|
||||
GetPersonDetailsResponse,
|
||||
GetSiteResponse,
|
||||
|
@ -151,10 +152,14 @@ export class CreatePrivateMessage extends Component<
|
|||
);
|
||||
}
|
||||
|
||||
handlePrivateMessageCreate() {
|
||||
toast(i18n.t("message_sent"));
|
||||
async handlePrivateMessageCreate(form: CreatePrivateMessageI) {
|
||||
const res = await apiWrapper(HttpService.client.createPrivateMessage(form));
|
||||
|
||||
// Navigate to the front
|
||||
this.context.router.history.push("/");
|
||||
if (res.state == "success") {
|
||||
toast(i18n.t("message_sent"));
|
||||
|
||||
// Navigate to the front
|
||||
this.context.router.history.push("/");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, linkEvent } from "inferno";
|
||||
import { Component, InfernoNode, linkEvent } from "inferno";
|
||||
import { T } from "inferno-i18next-dess";
|
||||
import { Prompt } from "inferno-router";
|
||||
import {
|
||||
|
@ -56,12 +56,11 @@ export class PrivateMessageForm extends Component<
|
|||
setupTippy();
|
||||
}
|
||||
|
||||
// TODO what is this
|
||||
componentDidUpdate() {
|
||||
if (!this.state.loading && this.state.content) {
|
||||
window.onbeforeunload = () => true;
|
||||
} else {
|
||||
window.onbeforeunload = null;
|
||||
componentWillReceiveProps(
|
||||
nextProps: Readonly<{ children?: InfernoNode } & PrivateMessageFormProps>
|
||||
): void {
|
||||
if (this.props != nextProps) {
|
||||
this.setState({ loading: false, content: undefined, previewMode: false });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, linkEvent } from "inferno";
|
||||
import { Component, InfernoNode, linkEvent } from "inferno";
|
||||
import { T } from "inferno-i18next-dess";
|
||||
import {
|
||||
PrivateMessageReportView,
|
||||
|
@ -27,6 +27,14 @@ export class PrivateMessageReport extends Component<Props, State> {
|
|||
super(props, context);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(
|
||||
nextProps: Readonly<{ children?: InfernoNode } & Props>
|
||||
): void {
|
||||
if (this.props != nextProps) {
|
||||
this.setState({ loading: false });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let r = this.props.report;
|
||||
let pmr = r.private_message_report;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, linkEvent } from "inferno";
|
||||
import { Component, InfernoNode, linkEvent } from "inferno";
|
||||
import {
|
||||
CreatePrivateMessage,
|
||||
CreatePrivateMessageReport,
|
||||
|
@ -64,6 +64,23 @@ export class PrivateMessage extends Component<
|
|||
);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(
|
||||
nextProps: Readonly<{ children?: InfernoNode } & PrivateMessageProps>
|
||||
): void {
|
||||
if (this.props != nextProps) {
|
||||
this.setState({
|
||||
showReply: false,
|
||||
showEdit: false,
|
||||
collapsed: false,
|
||||
viewSource: false,
|
||||
showReportDialog: false,
|
||||
deleteLoading: false,
|
||||
readLoading: false,
|
||||
reportLoading: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let message_view = this.props.private_message_view;
|
||||
let otherPerson: Person = this.mine
|
||||
|
|
|
@ -657,6 +657,7 @@ export class Search extends Component<any, SearchState> {
|
|||
allLanguages={this.state.siteRes.all_languages}
|
||||
siteLanguages={this.state.siteRes.discussion_languages}
|
||||
// All of these are unused, since its viewonly
|
||||
finished={new Map()}
|
||||
onSaveComment={() => {}}
|
||||
onBlockPerson={() => {}}
|
||||
onDeleteComment={() => {}}
|
||||
|
@ -717,6 +718,7 @@ export class Search extends Component<any, SearchState> {
|
|||
allLanguages={siteRes.all_languages}
|
||||
siteLanguages={siteRes.discussion_languages}
|
||||
// All of these are unused, since its viewonly
|
||||
finished={new Map()}
|
||||
onSaveComment={() => {}}
|
||||
onBlockPerson={() => {}}
|
||||
onDeleteComment={() => {}}
|
||||
|
|
Loading…
Reference in a new issue