Hide create community (#787)

* Adding post and comment language tagging. Fixes #771

* Hiding create community button. Fixes #754
This commit is contained in:
Dessalines 2022-09-22 11:14:58 -04:00 committed by GitHub
parent 6320357d21
commit c6e3a4213a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 321 additions and 36 deletions

@ -1 +1 @@
Subproject commit 7ac48ae98271b3b573e28c90b87f9704492e0b62
Subproject commit 05fb028e8b85de9e7e9d516abb1ebb8a01aad060

View file

@ -78,7 +78,7 @@
"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",

View file

@ -21,6 +21,7 @@ import { UserService, WebSocketService } from "../../services";
import {
amAdmin,
auth,
canCreateCommunity,
donateLemmyUrl,
isBrowser,
notifyComment,
@ -274,7 +275,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
{i18n.t("create_post")}
</NavLink>
</li>
{this.canCreateCommunity && (
{canCreateCommunity(this.props.siteRes) && (
<li className="nav-item">
<NavLink
to="/create_community"
@ -528,13 +529,6 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
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 });
}

View file

@ -7,6 +7,7 @@ import {
CommentResponse,
CreateComment,
EditComment,
Language,
UserOperation,
wsJsonToRes,
wsUserOp,
@ -17,6 +18,7 @@ import { UserService, WebSocketService } from "../../services";
import {
auth,
capitalizeFirstLetter,
myFirstDiscussionLanguageId,
wsClient,
wsSubscribe,
} from "../../utils";
@ -32,6 +34,7 @@ interface CommentFormProps {
disabled?: boolean;
focus?: boolean;
onReplyCancel?(): any;
allLanguages: Language[];
}
interface CommentFormState {
@ -74,11 +77,19 @@ export class CommentForm extends Component<CommentFormProps, 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}
@ -88,6 +99,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
onSubmit={this.handleCommentSubmit}
onReplyCancel={this.handleReplyCancel}
placeholder={Some(i18n.t("comment_here"))}
allLanguages={this.props.allLanguages}
/>
) : (
<div className="alert alert-warning" role="alert">
@ -104,27 +116,34 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
);
}
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));
@ -132,10 +151,11 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
},
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));

View file

@ -17,6 +17,7 @@ import {
DeleteComment,
EditComment,
GetComments,
Language,
ListingType,
MarkCommentReplyAsRead,
MarkPersonMentionAsRead,
@ -101,6 +102,7 @@ interface CommentNodeProps {
showCommunity?: boolean;
enableDownvotes: boolean;
viewType: CommentViewType;
allLanguages: Language[];
}
export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
@ -324,6 +326,7 @@ 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 && (
@ -1007,6 +1010,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
onReplyCancel={this.handleReplyCancel}
disabled={this.props.locked}
focus
allLanguages={this.props.allLanguages}
/>
)}
{!this.state.collapsed && node.children.length > 0 && (
@ -1018,6 +1022,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
maxCommentsShown={None}
enableDownvotes={this.props.enableDownvotes}
viewType={this.props.viewType}
allLanguages={this.props.allLanguages}
/>
)}
{/* A collapsed clearfix */}
@ -1264,6 +1269,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
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));

View file

@ -3,6 +3,7 @@ import { Component } from "inferno";
import {
CommentNode as CommentNodeI,
CommunityModeratorView,
Language,
PersonViewSafe,
} from "lemmy-js-client";
import { CommentViewType } from "../../interfaces";
@ -22,6 +23,7 @@ interface CommentNodesProps {
showCommunity?: boolean;
enableDownvotes?: boolean;
viewType: CommentViewType;
allLanguages: Language[];
}
export class CommentNodes extends Component<CommentNodesProps, any> {
@ -51,6 +53,7 @@ export class CommentNodes extends Component<CommentNodesProps, any> {
showCommunity={this.props.showCommunity}
enableDownvotes={this.props.enableDownvotes}
viewType={this.props.viewType}
allLanguages={this.props.allLanguages}
/>
))}
</div>

View file

@ -64,6 +64,7 @@ export class CommentReport extends Component<CommentReportProps, any> {
enableDownvotes={true}
viewOnly={true}
showCommunity={true}
allLanguages={[]}
/>
<div>
{i18n.t("reporter")}: <PersonListing person={r.creator} />

View file

@ -0,0 +1,109 @@
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([]);
}
}

View file

@ -2,7 +2,7 @@ import { None, Option, Some } from "@sniptt/monads";
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";
@ -18,9 +18,11 @@ import {
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>;
@ -28,14 +30,21 @@ interface MarkdownTextAreaProps {
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;
@ -50,6 +59,7 @@ export class MarkdownTextArea extends Component<
private tribute: any;
private emptyState: MarkdownTextAreaState = {
content: this.props.initialContent,
languageId: this.props.initialLanguageId,
previewMode: false,
loading: false,
imageLoading: false,
@ -58,6 +68,8 @@ export class MarkdownTextArea extends Component<
constructor(props: any, context: any) {
super(props, context);
this.handleLanguageChange = this.handleLanguageChange.bind(this);
if (isBrowser()) {
this.tribute = setupTribute();
}
@ -149,6 +161,18 @@ export class MarkdownTextArea extends Component<
{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({
@ -394,10 +418,18 @@ export class MarkdownTextArea extends Component<
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);
}

View file

@ -95,11 +95,13 @@ export class RegistrationApplication extends Component<
<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>

View file

@ -212,10 +212,12 @@ export class CommunityForm extends Component<
<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>

View file

@ -391,6 +391,7 @@ export class Community extends Component<any, State> {
removeDuplicates
enableDownvotes={enableDownvotes(this.state.siteRes)}
enableNsfw={enableNsfw(this.state.siteRes)}
allLanguages={this.state.siteRes.all_languages}
/>
)
) : this.state.commentsLoading ? (
@ -407,6 +408,7 @@ export class Community extends Component<any, State> {
moderators={this.state.communityRes.map(r => r.moderators)}
admins={Some(this.state.siteRes.admins)}
maxCommentsShown={None}
allLanguages={this.state.siteRes.all_languages}
/>
);
}

View file

@ -38,6 +38,7 @@ import {
import { UserService, WebSocketService } from "../../services";
import {
auth,
canCreateCommunity,
commentsToFlatNodes,
createCommentLikeRes,
createPostLikeFindRes,
@ -430,7 +431,8 @@ export class Home extends Component<any, HomeState> {
<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>
@ -579,6 +581,7 @@ export class Home extends Component<any, HomeState> {
removeDuplicates
enableDownvotes={enableDownvotes(this.state.siteRes)}
enableNsfw={enableNsfw(this.state.siteRes)}
allLanguages={this.state.siteRes.all_languages}
/>
) : (
<CommentNodes
@ -591,6 +594,7 @@ export class Home extends Component<any, HomeState> {
showCommunity
showContext
enableDownvotes={enableDownvotes(this.state.siteRes)}
allLanguages={this.state.siteRes.all_languages}
/>
);
}

View file

@ -295,11 +295,13 @@ export class Signup extends Component<any, State> {
<div className="col-sm-10">
<MarkdownTextArea
initialContent={None}
initialLanguageId={None}
placeholder={None}
buttonTitle={None}
maxLength={None}
onContentChange={this.handleAnswerChange}
hideNavigationWarnings
allLanguages={[]}
/>
</div>
</div>

View file

@ -212,11 +212,13 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
<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>
@ -227,11 +229,13 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
<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>
@ -243,11 +247,13 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
<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>

View file

@ -398,6 +398,7 @@ export class Inbox extends Component<any, InboxState> {
showCommunity
showContext
enableDownvotes={enableDownvotes(this.state.siteRes)}
allLanguages={this.state.siteRes.all_languages}
/>
);
case ReplyEnum.Mention:
@ -420,6 +421,7 @@ export class Inbox extends Component<any, InboxState> {
showCommunity
showContext
enableDownvotes={enableDownvotes(this.state.siteRes)}
allLanguages={this.state.siteRes.all_languages}
/>
);
case ReplyEnum.Message:
@ -452,6 +454,7 @@ export class Inbox extends Component<any, InboxState> {
showCommunity
showContext
enableDownvotes={enableDownvotes(this.state.siteRes)}
allLanguages={this.state.siteRes.all_languages}
/>
</div>
);
@ -473,6 +476,7 @@ export class Inbox extends Component<any, InboxState> {
showCommunity
showContext
enableDownvotes={enableDownvotes(this.state.siteRes)}
allLanguages={this.state.siteRes.all_languages}
/>
))}
</div>

View file

@ -3,6 +3,7 @@ import { Component } from "inferno";
import {
CommentView,
GetPersonDetailsResponse,
Language,
PersonViewSafe,
PostView,
SortType,
@ -16,6 +17,7 @@ import { PostListing } from "../post/post-listing";
interface PersonDetailsProps {
personRes: GetPersonDetailsResponse;
admins: PersonViewSafe[];
allLanguages: Language[];
page: number;
limit: number;
sort: SortType;
@ -99,6 +101,7 @@ export class PersonDetails extends Component<PersonDetailsProps, any> {
showCommunity
showContext
enableDownvotes={this.props.enableDownvotes}
allLanguages={this.props.allLanguages}
/>
);
}
@ -114,6 +117,7 @@ export class PersonDetails extends Component<PersonDetailsProps, any> {
showCommunity
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
allLanguages={this.props.allLanguages}
/>
);
}
@ -171,6 +175,7 @@ export class PersonDetails extends Component<PersonDetailsProps, any> {
showCommunity
showContext
enableDownvotes={this.props.enableDownvotes}
allLanguages={this.props.allLanguages}
/>
</div>
);
@ -189,6 +194,7 @@ export class PersonDetails extends Component<PersonDetailsProps, any> {
moderators={None}
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
allLanguages={this.props.allLanguages}
/>
<hr className="my-3" />
</>

View file

@ -283,6 +283,7 @@ export class Profile extends Component<any, ProfileState> {
enableNsfw={enableNsfw(this.state.siteRes)}
view={this.state.view}
onPageChange={this.handlePageChange}
allLanguages={this.state.siteRes.all_languages}
/>
</div>

View file

@ -54,6 +54,7 @@ import {
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";
@ -99,7 +100,8 @@ export class Settings extends Component<any, SettingsState> {
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,
@ -140,6 +142,8 @@ export class Settings extends Component<any, SettingsState> {
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);
@ -163,7 +167,7 @@ export class Settings extends Component<any, SettingsState> {
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,
@ -479,6 +483,8 @@ export class Settings extends Component<any, SettingsState> {
}
saveUserSettingsHtmlForm() {
let selectedLangs = this.state.saveUserSettingsForm.discussion_languages;
return (
<>
<h5>{i18n.t("settings")}</h5>
@ -509,11 +515,13 @@ export class Settings extends Component<any, SettingsState> {
<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>
@ -578,17 +586,19 @@ export class Settings extends Component<any, SettingsState> {
</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">
@ -604,6 +614,12 @@ export class Settings extends Component<any, SettingsState> {
</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")}
@ -1040,14 +1056,20 @@ export class Settings extends Component<any, SettingsState> {
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 => (

View file

@ -151,6 +151,7 @@ export class CreatePost extends Component<any, CreatePostState> {
params={Some(this.params)}
enableDownvotes={enableDownvotes(this.state.siteRes)}
enableNsfw={enableNsfw(this.state.siteRes)}
allLanguages={this.state.siteRes.all_languages}
/>
</div>
</div>

View file

@ -72,7 +72,7 @@ export class MetadataCard extends Component<
),
none: <></>,
})}
{post.embed_html.isSome() && (
{post.embed_video_url.isSome() && (
<button
className="mt-2 btn btn-secondary text-monospace"
onClick={linkEvent(this, this.handleIframeExpand)}
@ -91,7 +91,7 @@ export class MetadataCard extends Component<
none: <></>,
})}
{this.state.expanded &&
post.embed_html.match({
post.embed_video_url.match({
some: html => (
<div
className="mt-3 mb-2"

View file

@ -6,6 +6,7 @@ import {
CommunityView,
CreatePost,
EditPost,
Language,
ListingType,
PostResponse,
PostView,
@ -36,6 +37,7 @@ import {
ghostArchiveUrl,
isBrowser,
isImage,
myFirstDiscussionLanguageId,
pictrsDeleteToast,
relTags,
setupTippy,
@ -48,6 +50,7 @@ import {
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";
@ -60,6 +63,7 @@ const MAX_POST_TITLE_LENGTH = 200;
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;
@ -90,6 +94,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
url: None,
body: None,
honeypot: None,
language_id: None,
auth: undefined,
}),
loading: false,
@ -105,6 +110,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
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;
@ -124,6 +130,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
url: pv.post.url,
nsfw: Some(pv.post.nsfw),
honeypot: None,
language_id: Some(pv.post.language_id),
auth: auth().unwrap(),
}),
};
@ -172,6 +179,10 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
}
render() {
let selectedLangs = this.state.postForm.language_id
.or(myFirstDiscussionLanguageId(UserService.Instance.myUserInfo))
.map(Array.of);
return (
<div>
<Prompt
@ -284,6 +295,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
posts={xPosts}
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
allLanguages={this.props.allLanguages}
/>
</>
),
@ -325,6 +337,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
posts={sPosts}
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
allLanguages={this.props.allLanguages}
/>
</>
),
@ -338,10 +351,12 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
<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>
@ -388,6 +403,12 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
</div>
</div>
)}
<LanguageSelect
allLanguages={this.props.allLanguages}
selectedLanguageIds={selectedLangs}
multiple={false}
onChange={this.handleLanguageChange}
/>
<input
tabIndex={-1}
autoComplete="false"
@ -453,6 +474,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
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));
@ -559,6 +581,10 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
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));
}

View file

@ -12,6 +12,7 @@ import {
CreatePostLike,
CreatePostReport,
DeletePost,
Language,
LockPost,
PersonViewSafe,
PostView,
@ -88,6 +89,7 @@ interface PostListingProps {
duplicates: Option<PostView[]>;
moderators: Option<CommunityModeratorView[]>;
admins: Option<PersonViewSafe[]>;
allLanguages: Language[];
showCommunity?: boolean;
showBody?: boolean;
enableDownvotes?: boolean;
@ -169,6 +171,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
onCancel={this.handleEditCancel}
enableNsfw={this.props.enableNsfw}
enableDownvotes={this.props.enableDownvotes}
allLanguages={this.props.allLanguages}
/>
</div>
)}

View file

@ -2,12 +2,13 @@ import { None, Some } from "@sniptt/monads";
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;
@ -41,6 +42,7 @@ export class PostListings extends Component<PostListingsProps, any> {
showCommunity={this.props.showCommunity}
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
allLanguages={this.props.allLanguages}
/>
<hr className="my-3" />
</>

View file

@ -58,6 +58,7 @@ export class PostReport extends Component<PostReportProps, any> {
enableDownvotes={true}
enableNsfw={true}
viewOnly={true}
allLanguages={[]}
/>
<div>
{i18n.t("reporter")}: <PersonListing person={r.creator} />

View file

@ -370,11 +370,13 @@ export class Post extends Component<any, PostState> {
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
@ -508,6 +510,7 @@ export class Post extends Component<any, PostState> {
admins={Some(this.state.siteRes.admins)}
enableDownvotes={enableDownvotes(this.state.siteRes)}
showContext
allLanguages={this.state.siteRes.all_languages}
/>
</div>
),
@ -611,6 +614,7 @@ export class Post extends Component<any, PostState> {
moderators={Some(res.moderators)}
admins={Some(this.state.siteRes.admins)}
enableDownvotes={enableDownvotes(this.state.siteRes)}
allLanguages={this.state.siteRes.all_languages}
/>
</div>
),

View file

@ -130,10 +130,12 @@ export class PrivateMessageForm extends Component<
<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>

View file

@ -597,6 +597,7 @@ export class Search extends Component<any, SearchState> {
showCommunity
enableDownvotes={enableDownvotes(this.state.siteRes)}
enableNsfw={enableNsfw(this.state.siteRes)}
allLanguages={this.state.siteRes.all_languages}
viewOnly
/>
)}
@ -618,6 +619,7 @@ export class Search extends Component<any, SearchState> {
locked
noIndent
enableDownvotes={enableDownvotes(this.state.siteRes)}
allLanguages={this.state.siteRes.all_languages}
/>
)}
{i.type_ == "communities" && (
@ -656,6 +658,7 @@ export class Search extends Component<any, SearchState> {
admins={None}
maxCommentsShown={None}
enableDownvotes={enableDownvotes(this.state.siteRes)}
allLanguages={this.state.siteRes.all_languages}
/>
);
}
@ -685,6 +688,7 @@ export class Search extends Component<any, SearchState> {
admins={None}
enableDownvotes={enableDownvotes(this.state.siteRes)}
enableNsfw={enableNsfw(this.state.siteRes)}
allLanguages={this.state.siteRes.all_languages}
viewOnly
/>
</div>

View file

@ -1,4 +1,4 @@
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 {
@ -418,7 +418,7 @@ export function getLanguages(
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;
@ -1461,3 +1461,29 @@ export function postToCommentSortType(sort: SortType): CommentSortType {
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));
}

View file

@ -5224,10 +5224,10 @@ lcid@^1.0.0:
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"