1 import { Component, linkEvent } from "inferno";
4 BlockCommunityResponse,
21 } from "lemmy-js-client";
22 import { Subscription } from "rxjs";
23 import { i18n, languages } from "../../i18next";
24 import { UserService, WebSocketService } from "../../services";
26 capitalizeFirstLetter,
52 import { HtmlTags } from "../common/html-tags";
53 import { Icon, Spinner } from "../common/icon";
54 import { ImageUploadForm } from "../common/image-upload-form";
55 import { LanguageSelect } from "../common/language-select";
56 import { ListingTypeSelect } from "../common/listing-type-select";
57 import { MarkdownTextArea } from "../common/markdown-textarea";
58 import { SortSelect } from "../common/sort-select";
59 import { CommunityLink } from "../community/community-link";
60 import { PersonListing } from "./person-listing";
64 Choices = require("choices.js");
67 interface SettingsState {
68 // TODO redo these forms
69 saveUserSettingsForm: {
72 default_sort_type?: number;
73 default_listing_type?: number;
74 interface_language?: string;
77 display_name?: string;
80 matrix_user_id?: string;
81 show_avatars?: boolean;
82 show_scores?: boolean;
83 send_notifications_to_email?: boolean;
84 bot_account?: boolean;
85 show_bot_accounts?: boolean;
86 show_read_posts?: boolean;
87 show_new_post_notifs?: boolean;
88 discussion_languages?: number[];
91 new_password?: string;
92 new_password_verify?: string;
93 old_password?: string;
98 personBlocks: PersonBlockView[];
99 blockPerson?: PersonViewSafe;
100 communityBlocks: CommunityBlockView[];
101 blockCommunityId: number;
102 blockCommunity?: CommunityView;
105 saveUserSettingsLoading: boolean;
106 changePasswordLoading: boolean;
107 deleteAccountLoading: boolean;
108 deleteAccountShowConfirm: boolean;
109 siteRes: GetSiteResponse;
112 export class Settings extends Component<any, SettingsState> {
113 private isoData = setIsoData(this.context);
114 private blockPersonChoices: any;
115 private blockCommunityChoices: any;
116 private subscription?: Subscription;
117 state: SettingsState = {
118 saveUserSettingsForm: {},
119 changePasswordForm: {},
120 saveUserSettingsLoading: false,
121 changePasswordLoading: false,
122 deleteAccountLoading: false,
123 deleteAccountShowConfirm: false,
124 deleteAccountForm: {},
128 currentTab: "settings",
129 siteRes: this.isoData.site_res,
133 constructor(props: any, context: any) {
134 super(props, context);
136 this.handleSortTypeChange = this.handleSortTypeChange.bind(this);
137 this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
138 this.handleBioChange = this.handleBioChange.bind(this);
139 this.handleDiscussionLanguageChange =
140 this.handleDiscussionLanguageChange.bind(this);
142 this.handleAvatarUpload = this.handleAvatarUpload.bind(this);
143 this.handleAvatarRemove = this.handleAvatarRemove.bind(this);
145 this.handleBannerUpload = this.handleBannerUpload.bind(this);
146 this.handleBannerRemove = this.handleBannerRemove.bind(this);
148 this.parseMessage = this.parseMessage.bind(this);
149 this.subscription = wsSubscribe(this.parseMessage);
151 let mui = UserService.Instance.myUserInfo;
153 let luv = mui.local_user_view;
156 personBlocks: mui.person_blocks,
157 communityBlocks: mui.community_blocks,
158 saveUserSettingsForm: {
159 ...this.state.saveUserSettingsForm,
160 show_nsfw: luv.local_user.show_nsfw,
161 theme: luv.local_user.theme ? luv.local_user.theme : "browser",
162 default_sort_type: luv.local_user.default_sort_type,
163 default_listing_type: luv.local_user.default_listing_type,
164 interface_language: luv.local_user.interface_language,
165 discussion_languages: mui.discussion_languages,
166 avatar: luv.person.avatar,
167 banner: luv.person.banner,
168 display_name: luv.person.display_name,
169 show_avatars: luv.local_user.show_avatars,
170 bot_account: luv.person.bot_account,
171 show_bot_accounts: luv.local_user.show_bot_accounts,
172 show_scores: luv.local_user.show_scores,
173 show_read_posts: luv.local_user.show_read_posts,
174 show_new_post_notifs: luv.local_user.show_new_post_notifs,
175 email: luv.local_user.email,
177 send_notifications_to_email:
178 luv.local_user.send_notifications_to_email,
179 matrix_user_id: luv.person.matrix_user_id,
185 async componentDidMount() {
187 this.setState({ themeList: await fetchThemeList() });
190 componentWillUnmount() {
191 this.subscription?.unsubscribe();
194 get documentTitle(): string {
195 return i18n.t("settings");
200 <div className="container-lg">
203 title={this.documentTitle}
204 path={this.context.router.route.match.url}
205 description={this.documentTitle}
206 image={this.state.saveUserSettingsForm.avatar}
208 <ul className="nav nav-tabs mb-2">
209 <li className="nav-item">
211 className={`nav-link btn ${
212 this.state.currentTab == "settings" && "active"
215 { ctx: this, tab: "settings" },
222 <li className="nav-item">
224 className={`nav-link btn ${
225 this.state.currentTab == "blocks" && "active"
228 { ctx: this, tab: "blocks" },
236 {this.state.currentTab == "settings" && this.userSettings()}
237 {this.state.currentTab == "blocks" && this.blockCards()}
245 <div className="row">
246 <div className="col-12 col-md-6">
247 <div className="card border-secondary mb-3">
248 <div className="card-body">{this.saveUserSettingsHtmlForm()}</div>
251 <div className="col-12 col-md-6">
252 <div className="card border-secondary mb-3">
253 <div className="card-body">{this.changePasswordHtmlForm()}</div>
262 <div className="row">
263 <div className="col-12 col-md-6">
264 <div className="card border-secondary mb-3">
265 <div className="card-body">{this.blockUserCard()}</div>
268 <div className="col-12 col-md-6">
269 <div className="card border-secondary mb-3">
270 <div className="card-body">{this.blockCommunityCard()}</div>
277 changePasswordHtmlForm() {
280 <h5>{i18n.t("change_password")}</h5>
281 <form onSubmit={linkEvent(this, this.handleChangePasswordSubmit)}>
282 <div className="form-group row">
283 <label className="col-sm-5 col-form-label" htmlFor="user-password">
284 {i18n.t("new_password")}
286 <div className="col-sm-7">
290 className="form-control"
291 value={this.state.changePasswordForm.new_password}
292 autoComplete="new-password"
294 onInput={linkEvent(this, this.handleNewPasswordChange)}
298 <div className="form-group row">
300 className="col-sm-5 col-form-label"
301 htmlFor="user-verify-password"
303 {i18n.t("verify_password")}
305 <div className="col-sm-7">
308 id="user-verify-password"
309 className="form-control"
310 value={this.state.changePasswordForm.new_password_verify}
311 autoComplete="new-password"
313 onInput={linkEvent(this, this.handleNewPasswordVerifyChange)}
317 <div className="form-group row">
319 className="col-sm-5 col-form-label"
320 htmlFor="user-old-password"
322 {i18n.t("old_password")}
324 <div className="col-sm-7">
327 id="user-old-password"
328 className="form-control"
329 value={this.state.changePasswordForm.old_password}
330 autoComplete="new-password"
332 onInput={linkEvent(this, this.handleOldPasswordChange)}
336 <div className="form-group">
337 <button type="submit" className="btn btn-block btn-secondary mr-4">
338 {this.state.changePasswordLoading ? (
341 capitalizeFirstLetter(i18n.t("save"))
353 {this.blockUserForm()}
354 {this.blockedUsersList()}
362 <h5>{i18n.t("blocked_users")}</h5>
363 <ul className="list-unstyled mb-0">
364 {this.state.personBlocks.map(pb => (
365 <li key={pb.target.id}>
367 <PersonListing person={pb.target} />
369 className="btn btn-sm"
371 { ctx: this, recipientId: pb.target.id },
372 this.handleUnblockPerson
374 data-tippy-content={i18n.t("unblock_user")}
376 <Icon icon="x" classes="icon-inline" />
387 let blockPerson = this.state.blockPerson;
389 <div className="form-group row">
391 className="col-md-4 col-form-label"
392 htmlFor="block-person-filter"
394 {i18n.t("block_user")}
396 <div className="col-md-8">
398 className="form-control"
399 id="block-person-filter"
400 value={blockPerson?.person.id ?? 0}
402 <option value="0">—</option>
404 <option value={blockPerson.person.id}>
405 {personSelectName(blockPerson)}
414 blockCommunityCard() {
417 {this.blockCommunityForm()}
418 {this.blockedCommunitiesList()}
423 blockedCommunitiesList() {
426 <h5>{i18n.t("blocked_communities")}</h5>
427 <ul className="list-unstyled mb-0">
428 {this.state.communityBlocks.map(cb => (
429 <li key={cb.community.id}>
431 <CommunityLink community={cb.community} />
433 className="btn btn-sm"
435 { ctx: this, communityId: cb.community.id },
436 this.handleUnblockCommunity
438 data-tippy-content={i18n.t("unblock_community")}
440 <Icon icon="x" classes="icon-inline" />
450 blockCommunityForm() {
452 <div className="form-group row">
454 className="col-md-4 col-form-label"
455 htmlFor="block-community-filter"
457 {i18n.t("block_community")}
459 <div className="col-md-8">
461 className="form-control"
462 id="block-community-filter"
463 value={this.state.blockCommunityId}
465 <option value="0">—</option>
466 {this.state.blockCommunity && (
467 <option value={this.state.blockCommunity.community.id}>
468 {communitySelectName(this.state.blockCommunity)}
477 saveUserSettingsHtmlForm() {
478 let selectedLangs = this.state.saveUserSettingsForm.discussion_languages;
482 <h5>{i18n.t("settings")}</h5>
483 <form onSubmit={linkEvent(this, this.handleSaveSettingsSubmit)}>
484 <div className="form-group row">
485 <label className="col-sm-5 col-form-label" htmlFor="display-name">
486 {i18n.t("display_name")}
488 <div className="col-sm-7">
492 className="form-control"
493 placeholder={i18n.t("optional")}
494 value={this.state.saveUserSettingsForm.display_name}
495 onInput={linkEvent(this, this.handleDisplayNameChange)}
496 pattern="^(?!@)(.+)$"
501 <div className="form-group row">
502 <label className="col-sm-3 col-form-label" htmlFor="user-bio">
505 <div className="col-sm-9">
507 initialContent={this.state.saveUserSettingsForm.bio}
508 onContentChange={this.handleBioChange}
510 hideNavigationWarnings
511 allLanguages={this.state.siteRes.all_languages}
512 siteLanguages={this.state.siteRes.discussion_languages}
516 <div className="form-group row">
517 <label className="col-sm-3 col-form-label" htmlFor="user-email">
520 <div className="col-sm-9">
524 className="form-control"
525 placeholder={i18n.t("optional")}
526 value={this.state.saveUserSettingsForm.email}
527 onInput={linkEvent(this, this.handleEmailChange)}
532 <div className="form-group row">
533 <label className="col-sm-5 col-form-label" htmlFor="matrix-user-id">
534 <a href={elementUrl} rel={relTags}>
535 {i18n.t("matrix_user_id")}
538 <div className="col-sm-7">
542 className="form-control"
543 placeholder="@user:example.com"
544 value={this.state.saveUserSettingsForm.matrix_user_id}
545 onInput={linkEvent(this, this.handleMatrixUserIdChange)}
546 pattern="^@[A-Za-z0-9._=-]+:[A-Za-z0-9.-]+\.[A-Za-z]{2,}$"
550 <div className="form-group row">
551 <label className="col-sm-3">{i18n.t("avatar")}</label>
552 <div className="col-sm-9">
554 uploadTitle={i18n.t("upload_avatar")}
555 imageSrc={this.state.saveUserSettingsForm.avatar}
556 onUpload={this.handleAvatarUpload}
557 onRemove={this.handleAvatarRemove}
562 <div className="form-group row">
563 <label className="col-sm-3">{i18n.t("banner")}</label>
564 <div className="col-sm-9">
566 uploadTitle={i18n.t("upload_banner")}
567 imageSrc={this.state.saveUserSettingsForm.banner}
568 onUpload={this.handleBannerUpload}
569 onRemove={this.handleBannerRemove}
573 <div className="form-group row">
574 <label className="col-sm-3" htmlFor="user-language">
575 {i18n.t("interface_language")}
577 <div className="col-sm-9">
580 value={this.state.saveUserSettingsForm.interface_language}
581 onChange={linkEvent(this, this.handleInterfaceLangChange)}
582 className="custom-select w-auto"
584 <option disabled aria-hidden="true">
585 {i18n.t("interface_language")}
587 <option value="browser">{i18n.t("browser_default")}</option>
588 <option disabled aria-hidden="true">
592 .sort((a, b) => a.code.localeCompare(b.code))
594 <option key={lang.code} value={lang.code}>
602 allLanguages={this.state.siteRes.all_languages}
603 siteLanguages={this.state.siteRes.discussion_languages}
604 selectedLanguageIds={selectedLangs}
607 onChange={this.handleDiscussionLanguageChange}
609 <div className="form-group row">
610 <label className="col-sm-3" htmlFor="user-theme">
613 <div className="col-sm-9">
616 value={this.state.saveUserSettingsForm.theme}
617 onChange={linkEvent(this, this.handleThemeChange)}
618 className="custom-select w-auto"
620 <option disabled aria-hidden="true">
623 <option value="browser">{i18n.t("browser_default")}</option>
624 {this.state.themeList.map(theme => (
625 <option key={theme} value={theme}>
632 <form className="form-group row">
633 <label className="col-sm-3">{i18n.t("type")}</label>
634 <div className="col-sm-9">
637 Object.values(ListingType)[
638 this.state.saveUserSettingsForm.default_listing_type ?? 1
641 showLocal={showLocal(this.isoData)}
643 onChange={this.handleListingTypeChange}
647 <form className="form-group row">
648 <label className="col-sm-3">{i18n.t("sort_type")}</label>
649 <div className="col-sm-9">
652 Object.values(SortType)[
653 this.state.saveUserSettingsForm.default_sort_type ?? 0
656 onChange={this.handleSortTypeChange}
660 {enableNsfw(this.state.siteRes) && (
661 <div className="form-group">
662 <div className="form-check">
664 className="form-check-input"
667 checked={this.state.saveUserSettingsForm.show_nsfw}
668 onChange={linkEvent(this, this.handleShowNsfwChange)}
670 <label className="form-check-label" htmlFor="user-show-nsfw">
671 {i18n.t("show_nsfw")}
676 <div className="form-group">
677 <div className="form-check">
679 className="form-check-input"
680 id="user-show-scores"
682 checked={this.state.saveUserSettingsForm.show_scores}
683 onChange={linkEvent(this, this.handleShowScoresChange)}
685 <label className="form-check-label" htmlFor="user-show-scores">
686 {i18n.t("show_scores")}
690 <div className="form-group">
691 <div className="form-check">
693 className="form-check-input"
694 id="user-show-avatars"
696 checked={this.state.saveUserSettingsForm.show_avatars}
697 onChange={linkEvent(this, this.handleShowAvatarsChange)}
699 <label className="form-check-label" htmlFor="user-show-avatars">
700 {i18n.t("show_avatars")}
704 <div className="form-group">
705 <div className="form-check">
707 className="form-check-input"
708 id="user-bot-account"
710 checked={this.state.saveUserSettingsForm.bot_account}
711 onChange={linkEvent(this, this.handleBotAccount)}
713 <label className="form-check-label" htmlFor="user-bot-account">
714 {i18n.t("bot_account")}
718 <div className="form-group">
719 <div className="form-check">
721 className="form-check-input"
722 id="user-show-bot-accounts"
724 checked={this.state.saveUserSettingsForm.show_bot_accounts}
725 onChange={linkEvent(this, this.handleShowBotAccounts)}
728 className="form-check-label"
729 htmlFor="user-show-bot-accounts"
731 {i18n.t("show_bot_accounts")}
735 <div className="form-group">
736 <div className="form-check">
738 className="form-check-input"
739 id="user-show-read-posts"
741 checked={this.state.saveUserSettingsForm.show_read_posts}
742 onChange={linkEvent(this, this.handleReadPosts)}
745 className="form-check-label"
746 htmlFor="user-show-read-posts"
748 {i18n.t("show_read_posts")}
752 <div className="form-group">
753 <div className="form-check">
755 className="form-check-input"
756 id="user-show-new-post-notifs"
758 checked={this.state.saveUserSettingsForm.show_new_post_notifs}
759 onChange={linkEvent(this, this.handleShowNewPostNotifs)}
762 className="form-check-label"
763 htmlFor="user-show-new-post-notifs"
765 {i18n.t("show_new_post_notifs")}
769 <div className="form-group">
770 <div className="form-check">
772 className="form-check-input"
773 id="user-send-notifications-to-email"
775 disabled={!this.state.saveUserSettingsForm.email}
777 this.state.saveUserSettingsForm.send_notifications_to_email
781 this.handleSendNotificationsToEmailChange
785 className="form-check-label"
786 htmlFor="user-send-notifications-to-email"
788 {i18n.t("send_notifications_to_email")}
792 <div className="form-group">
793 <button type="submit" className="btn btn-block btn-secondary mr-4">
794 {this.state.saveUserSettingsLoading ? (
797 capitalizeFirstLetter(i18n.t("save"))
802 <div className="form-group">
804 className="btn btn-block btn-danger"
807 this.handleDeleteAccountShowConfirmToggle
810 {i18n.t("delete_account")}
812 {this.state.deleteAccountShowConfirm && (
814 <div className="my-2 alert alert-danger" role="alert">
815 {i18n.t("delete_account_confirm")}
819 value={this.state.deleteAccountForm.password}
820 autoComplete="new-password"
824 this.handleDeleteAccountPasswordChange
826 className="form-control my-2"
829 className="btn btn-danger mr-4"
830 disabled={!this.state.deleteAccountForm.password}
831 onClick={linkEvent(this, this.handleDeleteAccount)}
833 {this.state.deleteAccountLoading ? (
836 capitalizeFirstLetter(i18n.t("delete"))
840 className="btn btn-secondary"
843 this.handleDeleteAccountShowConfirmToggle
856 setupBlockPersonChoices() {
858 let selectId: any = document.getElementById("block-person-filter");
860 this.blockPersonChoices = new Choices(selectId, choicesConfig);
861 this.blockPersonChoices.passedElement.element.addEventListener(
864 this.handleBlockPerson(Number(e.detail.choice.value));
868 this.blockPersonChoices.passedElement.element.addEventListener(
870 debounce(async (e: any) => {
872 let persons = (await fetchUsers(e.detail.value)).users;
873 let choices = persons.map(pvs => personToChoice(pvs));
874 this.blockPersonChoices.setChoices(
890 setupBlockCommunityChoices() {
892 let selectId: any = document.getElementById("block-community-filter");
894 this.blockCommunityChoices = new Choices(selectId, choicesConfig);
895 this.blockCommunityChoices.passedElement.element.addEventListener(
898 this.handleBlockCommunity(Number(e.detail.choice.value));
902 this.blockCommunityChoices.passedElement.element.addEventListener(
904 debounce(async (e: any) => {
906 let communities = (await fetchCommunities(e.detail.value))
908 let choices = communities.map(cv => communityToChoice(cv));
909 this.blockCommunityChoices.setChoices(
925 handleBlockPerson(personId: number) {
927 if (auth && personId != 0) {
928 let blockUserForm: BlockPerson = {
933 WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm));
937 handleUnblockPerson(i: { ctx: Settings; recipientId: number }) {
940 let blockUserForm: BlockPerson = {
941 person_id: i.recipientId,
945 WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm));
949 handleBlockCommunity(community_id: number) {
951 if (auth && community_id != 0) {
952 let blockCommunityForm: BlockCommunity = {
957 WebSocketService.Instance.send(
958 wsClient.blockCommunity(blockCommunityForm)
963 handleUnblockCommunity(i: { ctx: Settings; communityId: number }) {
966 let blockCommunityForm: BlockCommunity = {
967 community_id: i.communityId,
971 WebSocketService.Instance.send(
972 wsClient.blockCommunity(blockCommunityForm)
977 handleShowNsfwChange(i: Settings, event: any) {
978 i.state.saveUserSettingsForm.show_nsfw = event.target.checked;
982 handleShowAvatarsChange(i: Settings, event: any) {
983 i.state.saveUserSettingsForm.show_avatars = event.target.checked;
984 let mui = UserService.Instance.myUserInfo;
986 mui.local_user_view.local_user.show_avatars = event.target.checked;
991 handleBotAccount(i: Settings, event: any) {
992 i.state.saveUserSettingsForm.bot_account = event.target.checked;
996 handleShowBotAccounts(i: Settings, event: any) {
997 i.state.saveUserSettingsForm.show_bot_accounts = event.target.checked;
1001 handleReadPosts(i: Settings, event: any) {
1002 i.state.saveUserSettingsForm.show_read_posts = event.target.checked;
1003 i.setState(i.state);
1006 handleShowNewPostNotifs(i: Settings, event: any) {
1007 i.state.saveUserSettingsForm.show_new_post_notifs = event.target.checked;
1008 i.setState(i.state);
1011 handleShowScoresChange(i: Settings, event: any) {
1012 i.state.saveUserSettingsForm.show_scores = event.target.checked;
1013 let mui = UserService.Instance.myUserInfo;
1015 mui.local_user_view.local_user.show_scores = event.target.checked;
1017 i.setState(i.state);
1020 handleSendNotificationsToEmailChange(i: Settings, event: any) {
1021 i.state.saveUserSettingsForm.send_notifications_to_email =
1022 event.target.checked;
1023 i.setState(i.state);
1026 handleThemeChange(i: Settings, event: any) {
1027 i.state.saveUserSettingsForm.theme = event.target.value;
1028 setTheme(event.target.value, true);
1029 i.setState(i.state);
1032 handleInterfaceLangChange(i: Settings, event: any) {
1033 i.state.saveUserSettingsForm.interface_language = event.target.value;
1034 i18n.changeLanguage(
1035 getLanguages(i.state.saveUserSettingsForm.interface_language).at(0)
1037 i.setState(i.state);
1040 handleDiscussionLanguageChange(val: number[]) {
1042 s => ((s.saveUserSettingsForm.discussion_languages = val), s)
1046 handleSortTypeChange(val: SortType) {
1049 (s.saveUserSettingsForm.default_sort_type =
1050 Object.keys(SortType).indexOf(val)),
1056 handleListingTypeChange(val: ListingType) {
1059 (s.saveUserSettingsForm.default_listing_type =
1060 Object.keys(ListingType).indexOf(val)),
1066 handleEmailChange(i: Settings, event: any) {
1067 i.state.saveUserSettingsForm.email = event.target.value;
1068 i.setState(i.state);
1071 handleBioChange(val: string) {
1072 this.setState(s => ((s.saveUserSettingsForm.bio = val), s));
1075 handleAvatarUpload(url: string) {
1076 this.setState(s => ((s.saveUserSettingsForm.avatar = url), s));
1079 handleAvatarRemove() {
1080 this.setState(s => ((s.saveUserSettingsForm.avatar = ""), s));
1083 handleBannerUpload(url: string) {
1084 this.setState(s => ((s.saveUserSettingsForm.banner = url), s));
1087 handleBannerRemove() {
1088 this.setState(s => ((s.saveUserSettingsForm.banner = ""), s));
1091 handleDisplayNameChange(i: Settings, event: any) {
1092 i.state.saveUserSettingsForm.display_name = event.target.value;
1093 i.setState(i.state);
1096 handleMatrixUserIdChange(i: Settings, event: any) {
1097 i.state.saveUserSettingsForm.matrix_user_id = event.target.value;
1098 i.setState(i.state);
1101 handleNewPasswordChange(i: Settings, event: any) {
1102 i.state.changePasswordForm.new_password = event.target.value;
1103 if (i.state.changePasswordForm.new_password == "") {
1104 i.state.changePasswordForm.new_password = undefined;
1106 i.setState(i.state);
1109 handleNewPasswordVerifyChange(i: Settings, event: any) {
1110 i.state.changePasswordForm.new_password_verify = event.target.value;
1111 if (i.state.changePasswordForm.new_password_verify == "") {
1112 i.state.changePasswordForm.new_password_verify = undefined;
1114 i.setState(i.state);
1117 handleOldPasswordChange(i: Settings, event: any) {
1118 i.state.changePasswordForm.old_password = event.target.value;
1119 if (i.state.changePasswordForm.old_password == "") {
1120 i.state.changePasswordForm.old_password = undefined;
1122 i.setState(i.state);
1125 handleSaveSettingsSubmit(i: Settings, event: any) {
1126 event.preventDefault();
1127 i.setState({ saveUserSettingsLoading: true });
1128 let auth = myAuth();
1130 let form: SaveUserSettings = { ...i.state.saveUserSettingsForm, auth };
1131 WebSocketService.Instance.send(wsClient.saveUserSettings(form));
1135 handleChangePasswordSubmit(i: Settings, event: any) {
1136 event.preventDefault();
1137 i.setState({ changePasswordLoading: true });
1138 let auth = myAuth();
1139 let pForm = i.state.changePasswordForm;
1140 let new_password = pForm.new_password;
1141 let new_password_verify = pForm.new_password_verify;
1142 let old_password = pForm.old_password;
1143 if (auth && new_password && old_password && new_password_verify) {
1144 let form: ChangePassword = {
1146 new_password_verify,
1151 WebSocketService.Instance.send(wsClient.changePassword(form));
1155 handleDeleteAccountShowConfirmToggle(i: Settings, event: any) {
1156 event.preventDefault();
1157 i.setState({ deleteAccountShowConfirm: !i.state.deleteAccountShowConfirm });
1160 handleDeleteAccountPasswordChange(i: Settings, event: any) {
1161 i.state.deleteAccountForm.password = event.target.value;
1162 i.setState(i.state);
1165 handleDeleteAccount(i: Settings, event: any) {
1166 event.preventDefault();
1167 i.setState({ deleteAccountLoading: true });
1168 let auth = myAuth();
1169 let password = i.state.deleteAccountForm.password;
1170 if (auth && password) {
1171 let form: DeleteAccount = {
1175 WebSocketService.Instance.send(wsClient.deleteAccount(form));
1179 handleSwitchTab(i: { ctx: Settings; tab: string }) {
1180 i.ctx.setState({ currentTab: i.tab });
1182 if (i.ctx.state.currentTab == "blocks") {
1183 i.ctx.setupBlockPersonChoices();
1184 i.ctx.setupBlockCommunityChoices();
1188 parseMessage(msg: any) {
1189 let op = wsUserOp(msg);
1193 saveUserSettingsLoading: false,
1194 changePasswordLoading: false,
1195 deleteAccountLoading: false,
1197 toast(i18n.t(msg.error), "danger");
1199 } else if (op == UserOperation.SaveUserSettings) {
1200 let data = wsJsonToRes<LoginResponse>(msg);
1201 UserService.Instance.login(data);
1203 this.setState({ saveUserSettingsLoading: false });
1204 toast(i18n.t("saved"));
1205 window.scrollTo(0, 0);
1206 } else if (op == UserOperation.ChangePassword) {
1207 let data = wsJsonToRes<LoginResponse>(msg);
1208 UserService.Instance.login(data);
1209 this.setState({ changePasswordLoading: false });
1210 window.scrollTo(0, 0);
1211 toast(i18n.t("password_changed"));
1212 } else if (op == UserOperation.DeleteAccount) {
1214 deleteAccountLoading: false,
1215 deleteAccountShowConfirm: false,
1217 UserService.Instance.logout();
1218 window.location.href = "/";
1219 } else if (op == UserOperation.BlockPerson) {
1220 let data = wsJsonToRes<BlockPersonResponse>(msg);
1221 updatePersonBlock(data);
1222 let mui = UserService.Instance.myUserInfo;
1224 this.setState({ personBlocks: mui.person_blocks });
1226 } else if (op == UserOperation.BlockCommunity) {
1227 let data = wsJsonToRes<BlockCommunityResponse>(msg);
1228 updateCommunityBlock(data);
1229 let mui = UserService.Instance.myUserInfo;
1231 this.setState({ communityBlocks: mui.community_blocks });