-Subproject commit 7ac48ae98271b3b573e28c90b87f9704492e0b62
+Subproject commit 05fb028e8b85de9e7e9d516abb1ebb8a01aad060
"eslint-plugin-prettier": "^4.2.1",
"husky": "^8.0.1",
"import-sort-style-module": "^6.0.0",
- "lemmy-js-client": "0.17.0-rc.43",
+ "lemmy-js-client": "0.17.0-rc.44",
"lint-staged": "^13.0.3",
"mini-css-extract-plugin": "^2.6.1",
"node-fetch": "^2.6.1",
import {
amAdmin,
auth,
+ canCreateCommunity,
donateLemmyUrl,
isBrowser,
notifyComment,
{i18n.t("create_post")}
</NavLink>
</li>
- {this.canCreateCommunity && (
+ {canCreateCommunity(this.props.siteRes) && (
<li className="nav-item">
<NavLink
to="/create_community"
return amAdmin(Some(this.props.siteRes.admins));
}
- get canCreateCommunity(): boolean {
- let adminOnly = this.props.siteRes.site_view
- .map(s => s.site.community_creation_admin_only)
- .unwrapOr(false);
- return !adminOnly || this.amAdmin;
- }
-
handleToggleExpandNavbar(i: Navbar) {
i.setState({ expanded: !i.state.expanded });
}
CommentResponse,
CreateComment,
EditComment,
+ Language,
UserOperation,
wsJsonToRes,
wsUserOp,
import {
auth,
capitalizeFirstLetter,
+ myFirstDiscussionLanguageId,
wsClient,
wsSubscribe,
} from "../../utils";
disabled?: boolean;
focus?: boolean;
onReplyCancel?(): any;
+ allLanguages: Language[];
}
interface CommentFormState {
this.props.edit ? Some(node.comment_view.comment.content) : None,
right: () => None,
});
+
+ let selectedLang = this.props.node
+ .left()
+ .map(n => n.comment_view.comment.language_id)
+ .or(myFirstDiscussionLanguageId(UserService.Instance.myUserInfo));
+
return (
<div className="mb-3">
{UserService.Instance.myUserInfo.isSome() ? (
<MarkdownTextArea
initialContent={initialContent}
+ initialLanguageId={selectedLang}
+ showLanguage
buttonTitle={Some(this.state.buttonTitle)}
maxLength={None}
finished={this.state.finished}
onSubmit={this.handleCommentSubmit}
onReplyCancel={this.handleReplyCancel}
placeholder={Some(i18n.t("comment_here"))}
+ allLanguages={this.props.allLanguages}
/>
) : (
<div className="alert alert-warning" role="alert">
);
}
- handleCommentSubmit(msg: { val: string; formId: string }) {
+ handleCommentSubmit(msg: {
+ val: Option<string>;
+ formId: string;
+ languageId: Option<number>;
+ }) {
let content = msg.val;
+ let language_id = msg.languageId;
this.setState({ formId: Some(msg.formId) });
this.props.node.match({
left: node => {
if (this.props.edit) {
let form = new EditComment({
- content: Some(content),
+ content,
distinguished: None,
form_id: this.state.formId,
comment_id: node.comment_view.comment.id,
+ language_id,
auth: auth().unwrap(),
});
WebSocketService.Instance.send(wsClient.editComment(form));
} else {
let form = new CreateComment({
- content,
+ content: content.unwrap(),
form_id: this.state.formId,
post_id: node.comment_view.post.id,
parent_id: Some(node.comment_view.comment.id),
+ language_id,
auth: auth().unwrap(),
});
WebSocketService.Instance.send(wsClient.createComment(form));
},
right: postId => {
let form = new CreateComment({
- content,
+ content: content.unwrap(),
form_id: this.state.formId,
post_id: postId,
parent_id: None,
+ language_id,
auth: auth().unwrap(),
});
WebSocketService.Instance.send(wsClient.createComment(form));
DeleteComment,
EditComment,
GetComments,
+ Language,
ListingType,
MarkCommentReplyAsRead,
MarkPersonMentionAsRead,
showCommunity?: boolean;
enableDownvotes: boolean;
viewType: CommentViewType;
+ allLanguages: Language[];
}
export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
onReplyCancel={this.handleReplyCancel}
disabled={this.props.locked}
focus
+ allLanguages={this.props.allLanguages}
/>
)}
{!this.state.showEdit && !this.state.collapsed && (
onReplyCancel={this.handleReplyCancel}
disabled={this.props.locked}
focus
+ allLanguages={this.props.allLanguages}
/>
)}
{!this.state.collapsed && node.children.length > 0 && (
maxCommentsShown={None}
enableDownvotes={this.props.enableDownvotes}
viewType={this.props.viewType}
+ allLanguages={this.props.allLanguages}
/>
)}
{/* A collapsed clearfix */}
form_id: None, // TODO not sure about this
content: None,
distinguished: Some(!comment.distinguished),
+ language_id: Some(comment.language_id),
auth: auth().unwrap(),
});
WebSocketService.Instance.send(wsClient.editComment(form));
import {
CommentNode as CommentNodeI,
CommunityModeratorView,
+ Language,
PersonViewSafe,
} from "lemmy-js-client";
import { CommentViewType } from "../../interfaces";
showCommunity?: boolean;
enableDownvotes?: boolean;
viewType: CommentViewType;
+ allLanguages: Language[];
}
export class CommentNodes extends Component<CommentNodesProps, any> {
showCommunity={this.props.showCommunity}
enableDownvotes={this.props.enableDownvotes}
viewType={this.props.viewType}
+ allLanguages={this.props.allLanguages}
/>
))}
</div>
enableDownvotes={true}
viewOnly={true}
showCommunity={true}
+ allLanguages={[]}
/>
<div>
{i18n.t("reporter")}: <PersonListing person={r.creator} />
--- /dev/null
+import { Option } from "@sniptt/monads";
+import classNames from "classnames";
+import { Component, linkEvent } from "inferno";
+import { Language } from "lemmy-js-client";
+import { i18n } from "../../i18next";
+import { randomStr } from "../../utils";
+import { Icon } from "./icon";
+
+interface LanguageSelectProps {
+ allLanguages: Language[];
+ selectedLanguageIds: Option<number[]>;
+ multiple: boolean;
+ onChange(val: number[]): any;
+}
+
+export class LanguageSelect extends Component<LanguageSelectProps, any> {
+ private id = `language-select-${randomStr()}`;
+
+ constructor(props: any, context: any) {
+ super(props, context);
+ }
+
+ componentDidMount() {
+ this.setSelectedValues();
+ }
+
+ // Necessary because there is no HTML way to set selected for multiple in value=
+ setSelectedValues() {
+ this.props.selectedLanguageIds.map(toString).match({
+ some: ids => {
+ var select = (document.getElementById(this.id) as HTMLSelectElement)
+ .options;
+ for (let i = 0; i < select.length; i++) {
+ let o = select[i];
+ if (ids.includes(o.value)) {
+ o.selected = true;
+ }
+ }
+ },
+ none: void 0,
+ });
+ }
+
+ render() {
+ let selectedLangs = this.props.selectedLanguageIds;
+
+ return (
+ <div className="form-group row">
+ <label
+ className={classNames("col-form-label", {
+ "col-sm-3": this.props.multiple,
+ "col-sm-2": !this.props.multiple,
+ })}
+ htmlFor={this.id}
+ >
+ {i18n.t(this.props.multiple ? "language_plural" : "language")}
+ </label>
+ <div
+ className={classNames("input-group", {
+ "col-sm-9": this.props.multiple,
+ "col-sm-10": !this.props.multiple,
+ })}
+ >
+ <select
+ className="form-control custom-select"
+ id={this.id}
+ onChange={linkEvent(this, this.handleLanguageChange)}
+ aria-label="action"
+ multiple={this.props.multiple}
+ >
+ {this.props.allLanguages.map(l => (
+ <option
+ key={l.id}
+ value={l.id}
+ selected={selectedLangs.unwrapOr([]).includes(l.id)}
+ >
+ {l.name}
+ </option>
+ ))}
+ </select>
+ {this.props.multiple && (
+ <div className="input-group-append">
+ <button
+ className="input-group-text"
+ onClick={linkEvent(this, this.handleDeselectAll)}
+ >
+ <Icon icon="x" />
+ </button>
+ </div>
+ )}
+ </div>
+ </div>
+ );
+ }
+
+ handleLanguageChange(i: LanguageSelect, event: any) {
+ let options: HTMLOptionElement[] = Array.from(event.target.options);
+ let selected: number[] = options
+ .filter(o => o.selected)
+ .map(o => Number(o.value));
+
+ i.props.onChange(selected);
+ }
+
+ handleDeselectAll(i: LanguageSelect, event: any) {
+ event.preventDefault();
+ i.props.onChange([]);
+ }
+}
import autosize from "autosize";
import { Component, linkEvent } from "inferno";
import { Prompt } from "inferno-router";
-import { toUndefined } from "lemmy-js-client";
+import { Language, toUndefined } from "lemmy-js-client";
import { pictrsUri } from "../../env";
import { i18n } from "../../i18next";
import { UserService } from "../../services";
toast,
} from "../../utils";
import { Icon, Spinner } from "./icon";
+import { LanguageSelect } from "./language-select";
interface MarkdownTextAreaProps {
initialContent: Option<string>;
+ initialLanguageId: Option<number>;
placeholder: Option<string>;
buttonTitle: Option<string>;
maxLength: Option<number>;
focus?: boolean;
disabled?: boolean;
finished?: boolean;
+ showLanguage?: boolean;
hideNavigationWarnings?: boolean;
onContentChange?(val: string): any;
onReplyCancel?(): any;
- onSubmit?(msg: { val: string; formId: string }): any;
+ onSubmit?(msg: {
+ val: Option<string>;
+ formId: string;
+ languageId: Option<number>;
+ }): any;
+ allLanguages: Language[];
}
interface MarkdownTextAreaState {
content: Option<string>;
+ languageId: Option<number>;
previewMode: boolean;
loading: boolean;
imageLoading: boolean;
private tribute: any;
private emptyState: MarkdownTextAreaState = {
content: this.props.initialContent,
+ languageId: this.props.initialLanguageId,
previewMode: false,
loading: false,
imageLoading: false,
constructor(props: any, context: any) {
super(props, context);
+ this.handleLanguageChange = this.handleLanguageChange.bind(this);
+
if (isBrowser()) {
this.tribute = setupTribute();
}
{i18n.t("body")}
</label>
</div>
+ {this.props.showLanguage && (
+ <div className="row justify-content-end">
+ <div className="col-sm-8">
+ <LanguageSelect
+ allLanguages={this.props.allLanguages}
+ selectedLanguageIds={this.state.languageId.map(Array.of)}
+ multiple={false}
+ onChange={this.handleLanguageChange}
+ />
+ </div>
+ </div>
+ )}
<div className="row">
<div className="col-sm-12 d-flex flex-wrap">
{this.props.buttonTitle.match({
i.setState({ previewMode: !i.state.previewMode });
}
+ handleLanguageChange(val: number[]) {
+ this.setState({ languageId: Some(val[0]) });
+ }
+
handleSubmit(i: MarkdownTextArea, event: any) {
event.preventDefault();
i.setState({ loading: true });
- let msg = { val: toUndefined(i.state.content), formId: i.formId };
+ let msg = {
+ val: i.state.content,
+ formId: i.formId,
+ languageId: i.state.languageId,
+ };
i.props.onSubmit(msg);
}
<div className="col-sm-10">
<MarkdownTextArea
initialContent={this.state.denyReason}
+ initialLanguageId={None}
onContentChange={this.handleDenyReasonChange}
placeholder={None}
buttonTitle={None}
maxLength={None}
hideNavigationWarnings
+ allLanguages={[]}
/>
</div>
</div>
<div className="col-12 col-sm-10">
<MarkdownTextArea
initialContent={this.state.communityForm.description}
+ initialLanguageId={None}
placeholder={Some("description")}
buttonTitle={None}
maxLength={None}
onContentChange={this.handleCommunityDescriptionChange}
+ allLanguages={[]}
/>
</div>
</div>
removeDuplicates
enableDownvotes={enableDownvotes(this.state.siteRes)}
enableNsfw={enableNsfw(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
/>
)
) : this.state.commentsLoading ? (
moderators={this.state.communityRes.map(r => r.moderators)}
admins={Some(this.state.siteRes.admins)}
maxCommentsShown={None}
+ allLanguages={this.state.siteRes.all_languages}
/>
);
}
import { UserService, WebSocketService } from "../../services";
import {
auth,
+ canCreateCommunity,
commentsToFlatNodes,
createCommentLikeRes,
createPostLikeFindRes,
<div className="card border-secondary mb-3">
<div className="card-body">
{this.trendingCommunities()}
- {this.createCommunityButton()}
+ {canCreateCommunity(this.state.siteRes) &&
+ this.createCommunityButton()}
{this.exploreCommunitiesButton()}
</div>
</div>
removeDuplicates
enableDownvotes={enableDownvotes(this.state.siteRes)}
enableNsfw={enableNsfw(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
/>
) : (
<CommentNodes
showCommunity
showContext
enableDownvotes={enableDownvotes(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
/>
);
}
<div className="col-sm-10">
<MarkdownTextArea
initialContent={None}
+ initialLanguageId={None}
placeholder={None}
buttonTitle={None}
maxLength={None}
onContentChange={this.handleAnswerChange}
hideNavigationWarnings
+ allLanguages={[]}
/>
</div>
</div>
<div className="col-12">
<MarkdownTextArea
initialContent={this.state.siteForm.sidebar}
+ initialLanguageId={None}
placeholder={None}
buttonTitle={None}
maxLength={None}
onContentChange={this.handleSiteSidebarChange}
hideNavigationWarnings
+ allLanguages={[]}
/>
</div>
</div>
<div className="col-12">
<MarkdownTextArea
initialContent={this.state.siteForm.legal_information}
+ initialLanguageId={None}
placeholder={None}
buttonTitle={None}
maxLength={None}
onContentChange={this.handleSiteLegalInfoChange}
hideNavigationWarnings
+ allLanguages={[]}
/>
</div>
</div>
<div className="col-12">
<MarkdownTextArea
initialContent={this.state.siteForm.application_question}
+ initialLanguageId={None}
placeholder={None}
buttonTitle={None}
maxLength={None}
onContentChange={this.handleSiteApplicationQuestionChange}
hideNavigationWarnings
+ allLanguages={[]}
/>
</div>
</div>
showCommunity
showContext
enableDownvotes={enableDownvotes(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
/>
);
case ReplyEnum.Mention:
showCommunity
showContext
enableDownvotes={enableDownvotes(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
/>
);
case ReplyEnum.Message:
showCommunity
showContext
enableDownvotes={enableDownvotes(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
/>
</div>
);
showCommunity
showContext
enableDownvotes={enableDownvotes(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
/>
))}
</div>
import {
CommentView,
GetPersonDetailsResponse,
+ Language,
PersonViewSafe,
PostView,
SortType,
interface PersonDetailsProps {
personRes: GetPersonDetailsResponse;
admins: PersonViewSafe[];
+ allLanguages: Language[];
page: number;
limit: number;
sort: SortType;
showCommunity
showContext
enableDownvotes={this.props.enableDownvotes}
+ allLanguages={this.props.allLanguages}
/>
);
}
showCommunity
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
+ allLanguages={this.props.allLanguages}
/>
);
}
showCommunity
showContext
enableDownvotes={this.props.enableDownvotes}
+ allLanguages={this.props.allLanguages}
/>
</div>
);
moderators={None}
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
+ allLanguages={this.props.allLanguages}
/>
<hr className="my-3" />
</>
enableNsfw={enableNsfw(this.state.siteRes)}
view={this.state.view}
onPageChange={this.handlePageChange}
+ allLanguages={this.state.siteRes.all_languages}
/>
</div>
import { HtmlTags } from "../common/html-tags";
import { Icon, Spinner } from "../common/icon";
import { ImageUploadForm } from "../common/image-upload-form";
+import { LanguageSelect } from "../common/language-select";
import { ListingTypeSelect } from "../common/listing-type-select";
import { MarkdownTextArea } from "../common/markdown-textarea";
import { SortSelect } from "../common/sort-select";
default_sort_type: None,
default_listing_type: None,
theme: None,
- lang: None,
+ interface_language: None,
+ discussion_languages: None,
avatar: None,
banner: None,
display_name: None,
this.handleSortTypeChange = this.handleSortTypeChange.bind(this);
this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
this.handleBioChange = this.handleBioChange.bind(this);
+ this.handleDiscussionLanguageChange =
+ this.handleDiscussionLanguageChange.bind(this);
this.handleAvatarUpload = this.handleAvatarUpload.bind(this);
this.handleAvatarRemove = this.handleAvatarRemove.bind(this);
theme: Some(luv.local_user.theme ? luv.local_user.theme : "browser"),
default_sort_type: Some(luv.local_user.default_sort_type),
default_listing_type: Some(luv.local_user.default_listing_type),
- lang: Some(luv.local_user.lang),
+ interface_language: Some(luv.local_user.interface_language),
avatar: luv.person.avatar,
banner: luv.person.banner,
display_name: luv.person.display_name,
}
saveUserSettingsHtmlForm() {
+ let selectedLangs = this.state.saveUserSettingsForm.discussion_languages;
+
return (
<>
<h5>{i18n.t("settings")}</h5>
<div className="col-sm-9">
<MarkdownTextArea
initialContent={this.state.saveUserSettingsForm.bio}
+ initialLanguageId={None}
onContentChange={this.handleBioChange}
maxLength={Some(300)}
placeholder={None}
buttonTitle={None}
hideNavigationWarnings
+ allLanguages={this.state.siteRes.all_languages}
/>
</div>
</div>
</div>
<div className="form-group row">
<label className="col-sm-3" htmlFor="user-language">
- {i18n.t("language")}
+ {i18n.t("interface_language")}
</label>
<div className="col-sm-9">
<select
id="user-language"
- value={toUndefined(this.state.saveUserSettingsForm.lang)}
- onChange={linkEvent(this, this.handleLangChange)}
+ value={toUndefined(
+ this.state.saveUserSettingsForm.interface_language
+ )}
+ onChange={linkEvent(this, this.handleInterfaceLangChange)}
className="custom-select w-auto"
>
<option disabled aria-hidden="true">
- {i18n.t("language")}
+ {i18n.t("interface_language")}
</option>
<option value="browser">{i18n.t("browser_default")}</option>
<option disabled aria-hidden="true">
</select>
</div>
</div>
+ <LanguageSelect
+ allLanguages={this.state.siteRes.all_languages}
+ selectedLanguageIds={selectedLangs}
+ multiple={true}
+ onChange={this.handleDiscussionLanguageChange}
+ />
<div className="form-group row">
<label className="col-sm-3" htmlFor="user-theme">
{i18n.t("theme")}
i.setState(i.state);
}
- handleLangChange(i: Settings, event: any) {
- i.state.saveUserSettingsForm.lang = Some(event.target.value);
+ handleInterfaceLangChange(i: Settings, event: any) {
+ i.state.saveUserSettingsForm.interface_language = Some(event.target.value);
i18n.changeLanguage(
- getLanguages(i.state.saveUserSettingsForm.lang.unwrap())[0]
+ getLanguages(i.state.saveUserSettingsForm.interface_language.unwrap())[0]
);
i.setState(i.state);
}
+ handleDiscussionLanguageChange(val: number[]) {
+ this.setState(
+ s => ((s.saveUserSettingsForm.discussion_languages = Some(val)), s)
+ );
+ }
+
handleSortTypeChange(val: SortType) {
this.setState(
s => (
params={Some(this.params)}
enableDownvotes={enableDownvotes(this.state.siteRes)}
enableNsfw={enableNsfw(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
/>
</div>
</div>
),
none: <></>,
})}
- {post.embed_html.isSome() && (
+ {post.embed_video_url.isSome() && (
<button
className="mt-2 btn btn-secondary text-monospace"
onClick={linkEvent(this, this.handleIframeExpand)}
none: <></>,
})}
{this.state.expanded &&
- post.embed_html.match({
+ post.embed_video_url.match({
some: html => (
<div
className="mt-3 mb-2"
CommunityView,
CreatePost,
EditPost,
+ Language,
ListingType,
PostResponse,
PostView,
ghostArchiveUrl,
isBrowser,
isImage,
+ myFirstDiscussionLanguageId,
pictrsDeleteToast,
relTags,
setupTippy,
wsSubscribe,
} from "../../utils";
import { Icon, Spinner } from "../common/icon";
+import { LanguageSelect } from "../common/language-select";
import { MarkdownTextArea } from "../common/markdown-textarea";
import { PostListings } from "./post-listings";
interface PostFormProps {
post_view: Option<PostView>; // If a post is given, that means this is an edit
+ allLanguages: Language[];
communities: Option<CommunityView[]>;
params: Option<PostFormParams>;
onCancel?(): any;
url: None,
body: None,
honeypot: None,
+ language_id: None,
auth: undefined,
}),
loading: false,
this.fetchSimilarPosts = debounce(this.fetchSimilarPosts.bind(this));
this.fetchPageTitle = debounce(this.fetchPageTitle.bind(this));
this.handlePostBodyChange = this.handlePostBodyChange.bind(this);
+ this.handleLanguageChange = this.handleLanguageChange.bind(this);
this.state = this.emptyState;
url: pv.post.url,
nsfw: Some(pv.post.nsfw),
honeypot: None,
+ language_id: Some(pv.post.language_id),
auth: auth().unwrap(),
}),
};
}
render() {
+ let selectedLangs = this.state.postForm.language_id
+ .or(myFirstDiscussionLanguageId(UserService.Instance.myUserInfo))
+ .map(Array.of);
+
return (
<div>
<Prompt
posts={xPosts}
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
+ allLanguages={this.props.allLanguages}
/>
</>
),
posts={sPosts}
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
+ allLanguages={this.props.allLanguages}
/>
</>
),
<div className="col-sm-10">
<MarkdownTextArea
initialContent={this.state.postForm.body}
+ initialLanguageId={None}
onContentChange={this.handlePostBodyChange}
placeholder={None}
buttonTitle={None}
maxLength={None}
+ allLanguages={this.props.allLanguages}
/>
</div>
</div>
</div>
</div>
)}
+ <LanguageSelect
+ allLanguages={this.props.allLanguages}
+ selectedLanguageIds={selectedLangs}
+ multiple={false}
+ onChange={this.handleLanguageChange}
+ />
<input
tabIndex={-1}
autoComplete="false"
body: pForm.body,
nsfw: pForm.nsfw,
post_id: pv.post.id,
+ language_id: Some(pv.post.language_id),
auth: auth().unwrap(),
});
WebSocketService.Instance.send(wsClient.editPost(form));
i.setState(s => ((s.postForm.nsfw = Some(event.target.checked)), s));
}
+ handleLanguageChange(val: number[]) {
+ this.setState(s => ((s.postForm.language_id = Some(val[0])), s));
+ }
+
handleHoneyPotChange(i: PostForm, event: any) {
i.setState(s => ((s.postForm.honeypot = Some(event.target.value)), s));
}
CreatePostLike,
CreatePostReport,
DeletePost,
+ Language,
LockPost,
PersonViewSafe,
PostView,
duplicates: Option<PostView[]>;
moderators: Option<CommunityModeratorView[]>;
admins: Option<PersonViewSafe[]>;
+ allLanguages: Language[];
showCommunity?: boolean;
showBody?: boolean;
enableDownvotes?: boolean;
onCancel={this.handleEditCancel}
enableNsfw={this.props.enableNsfw}
enableDownvotes={this.props.enableDownvotes}
+ allLanguages={this.props.allLanguages}
/>
</div>
)}
import { Component } from "inferno";
import { T } from "inferno-i18next-dess";
import { Link } from "inferno-router";
-import { PostView } from "lemmy-js-client";
+import { Language, PostView } from "lemmy-js-client";
import { i18n } from "../../i18next";
import { PostListing } from "./post-listing";
interface PostListingsProps {
posts: PostView[];
+ allLanguages: Language[];
showCommunity?: boolean;
removeDuplicates?: boolean;
enableDownvotes: boolean;
showCommunity={this.props.showCommunity}
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
+ allLanguages={this.props.allLanguages}
/>
<hr className="my-3" />
</>
enableDownvotes={true}
enableNsfw={true}
viewOnly={true}
+ allLanguages={[]}
/>
<div>
{i18n.t("reporter")}: <PersonListing person={r.creator} />
admins={Some(this.state.siteRes.admins)}
enableDownvotes={enableDownvotes(this.state.siteRes)}
enableNsfw={enableNsfw(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
/>
<div ref={this.state.commentSectionRef} className="mb-2" />
<CommentForm
node={Right(res.post_view.post.id)}
disabled={res.post_view.post.locked}
+ allLanguages={this.state.siteRes.all_languages}
/>
<div className="d-block d-md-none">
<button
admins={Some(this.state.siteRes.admins)}
enableDownvotes={enableDownvotes(this.state.siteRes)}
showContext
+ allLanguages={this.state.siteRes.all_languages}
/>
</div>
),
moderators={Some(res.moderators)}
admins={Some(this.state.siteRes.admins)}
enableDownvotes={enableDownvotes(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
/>
</div>
),
<div className="col-sm-10">
<MarkdownTextArea
initialContent={Some(this.state.privateMessageForm.content)}
+ initialLanguageId={None}
placeholder={None}
buttonTitle={None}
maxLength={None}
onContentChange={this.handleContentChange}
+ allLanguages={[]}
/>
</div>
</div>
showCommunity
enableDownvotes={enableDownvotes(this.state.siteRes)}
enableNsfw={enableNsfw(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
viewOnly
/>
)}
locked
noIndent
enableDownvotes={enableDownvotes(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
/>
)}
{i.type_ == "communities" && (
admins={None}
maxCommentsShown={None}
enableDownvotes={enableDownvotes(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
/>
);
}
admins={None}
enableDownvotes={enableDownvotes(this.state.siteRes)}
enableNsfw={enableNsfw(this.state.siteRes)}
+ allLanguages={this.state.siteRes.all_languages}
viewOnly
/>
</div>
-import { None, Option, Result, Some } from "@sniptt/monads";
+import { Err, None, Ok, Option, Result, Some } from "@sniptt/monads";
import { ClassConstructor, deserialize, serialize } from "class-transformer";
import emojiShortName from "emoji-short-name";
import {
myUserInfo = UserService.Instance.myUserInfo
): string[] {
let myLang = myUserInfo
- .map(m => m.local_user_view.local_user.lang)
+ .map(m => m.local_user_view.local_user.interface_language)
.unwrapOr("browser");
let lang = override || myLang;
return CommentSortType.Top;
}
}
+
+export function arrayGet<T>(arr: Array<T>, index: number): Result<T, string> {
+ let out = arr.at(index);
+ if (out == undefined) {
+ return Err("Index undefined");
+ } else {
+ return Ok(out);
+ }
+}
+
+export function myFirstDiscussionLanguageId(
+ myUserInfo = UserService.Instance.myUserInfo
+): Option<number> {
+ return myUserInfo.andThen(mui =>
+ arrayGet(mui.discussion_languages, 0)
+ .ok()
+ .map(i => i.id)
+ );
+}
+
+export function canCreateCommunity(siteRes: GetSiteResponse): boolean {
+ let adminOnly = siteRes.site_view
+ .map(s => s.site.community_creation_admin_only)
+ .unwrapOr(false);
+ return !adminOnly || amAdmin(Some(siteRes.admins));
+}
dependencies:
invert-kv "^1.0.0"
-lemmy-js-client@0.17.0-rc.43:
- version "0.17.0-rc.43"
- resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.17.0-rc.43.tgz#30e985365a93d72184646fdfe359f39ccc2e2091"
- integrity sha512-/+TOTZazoi74zwc8H2AJMd/Znrdnqfi0+TrfnmqvQ3fzrOl741ojEURxAHw3NsgW9b8HkubXZFLsi1RVR99UqA==
+lemmy-js-client@0.17.0-rc.44:
+ version "0.17.0-rc.44"
+ resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.17.0-rc.44.tgz#a5bd870b73bc25c3d8b47569ddcd66ef506b73ee"
+ integrity sha512-xXxjmDhRWCjRtfAIy8LwHDheR+VzQ4Co5xJyop1mXHtxrlUJx0mrcvXu84LnJ00zrqGa8lpE5R2IpbsRg9DsZA==
levn@^0.4.1:
version "0.4.1"