1 import { None, Option, Some } from "@sniptt/monads";
2 import { Component, linkEvent } from "inferno";
5 BlockCommunityResponse,
23 } from "lemmy-js-client";
24 import { Subscription } from "rxjs";
25 import { i18n, languages } from "../../i18next";
26 import { UserService, WebSocketService } from "../../services";
29 capitalizeFirstLetter,
54 import { HtmlTags } from "../common/html-tags";
55 import { Icon, Spinner } from "../common/icon";
56 import { ImageUploadForm } from "../common/image-upload-form";
57 import { ListingTypeSelect } from "../common/listing-type-select";
58 import { MarkdownTextArea } from "../common/markdown-textarea";
59 import { SortSelect } from "../common/sort-select";
60 import { CommunityLink } from "../community/community-link";
61 import { PersonListing } from "./person-listing";
65 Choices = require("choices.js");
68 interface SettingsState {
69 saveUserSettingsForm: SaveUserSettings;
70 changePasswordForm: ChangePassword;
71 deleteAccountForm: DeleteAccount;
72 personBlocks: PersonBlockView[];
73 blockPerson: Option<PersonViewSafe>;
74 communityBlocks: CommunityBlockView[];
75 blockCommunityId: number;
76 blockCommunity?: CommunityView;
79 saveUserSettingsLoading: boolean;
80 changePasswordLoading: boolean;
81 deleteAccountLoading: boolean;
82 deleteAccountShowConfirm: boolean;
83 siteRes: GetSiteResponse;
86 export class Settings extends Component<any, SettingsState> {
87 private isoData = setIsoData(this.context);
88 private blockPersonChoices: any;
89 private blockCommunityChoices: any;
90 private subscription: Subscription;
91 private emptyState: SettingsState = {
92 saveUserSettingsForm: new SaveUserSettings({
96 show_read_posts: None,
97 show_bot_accounts: None,
98 show_new_post_notifs: None,
99 default_sort_type: None,
100 default_listing_type: None,
108 matrix_user_id: None,
109 send_notifications_to_email: None,
113 changePasswordForm: new ChangePassword({
114 new_password: undefined,
115 new_password_verify: undefined,
116 old_password: undefined,
119 saveUserSettingsLoading: false,
120 changePasswordLoading: false,
121 deleteAccountLoading: false,
122 deleteAccountShowConfirm: false,
123 deleteAccountForm: new DeleteAccount({
131 currentTab: "settings",
132 siteRes: this.isoData.site_res,
136 constructor(props: any, context: any) {
137 super(props, context);
139 this.state = this.emptyState;
140 this.handleSortTypeChange = this.handleSortTypeChange.bind(this);
141 this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
142 this.handleBioChange = this.handleBioChange.bind(this);
144 this.handleAvatarUpload = this.handleAvatarUpload.bind(this);
145 this.handleAvatarRemove = this.handleAvatarRemove.bind(this);
147 this.handleBannerUpload = this.handleBannerUpload.bind(this);
148 this.handleBannerRemove = this.handleBannerRemove.bind(this);
150 this.parseMessage = this.parseMessage.bind(this);
151 this.subscription = wsSubscribe(this.parseMessage);
153 if (UserService.Instance.myUserInfo.isSome()) {
154 let mui = UserService.Instance.myUserInfo.unwrap();
155 let luv = mui.local_user_view;
158 personBlocks: mui.person_blocks,
159 communityBlocks: mui.community_blocks,
160 saveUserSettingsForm: {
161 ...this.state.saveUserSettingsForm,
162 show_nsfw: Some(luv.local_user.show_nsfw),
163 theme: Some(luv.local_user.theme ? luv.local_user.theme : "browser"),
164 default_sort_type: Some(luv.local_user.default_sort_type),
165 default_listing_type: Some(luv.local_user.default_listing_type),
166 lang: Some(luv.local_user.lang),
167 avatar: luv.person.avatar,
168 banner: luv.person.banner,
169 display_name: luv.person.display_name,
170 show_avatars: Some(luv.local_user.show_avatars),
171 bot_account: Some(luv.person.bot_account),
172 show_bot_accounts: Some(luv.local_user.show_bot_accounts),
173 show_scores: Some(luv.local_user.show_scores),
174 show_read_posts: Some(luv.local_user.show_read_posts),
175 show_new_post_notifs: Some(luv.local_user.show_new_post_notifs),
176 email: luv.local_user.email,
178 send_notifications_to_email: Some(
179 luv.local_user.send_notifications_to_email
181 matrix_user_id: luv.person.matrix_user_id,
187 async componentDidMount() {
189 this.setState({ themeList: await fetchThemeList() });
192 componentWillUnmount() {
193 this.subscription.unsubscribe();
196 get documentTitle(): string {
197 return i18n.t("settings");
202 <div className="container">
205 title={this.documentTitle}
206 path={this.context.router.route.match.url}
207 description={Some(this.documentTitle)}
208 image={this.state.saveUserSettingsForm.avatar}
210 <ul className="nav nav-tabs mb-2">
211 <li className="nav-item">
213 className={`nav-link btn ${
214 this.state.currentTab == "settings" && "active"
217 { ctx: this, tab: "settings" },
224 <li className="nav-item">
226 className={`nav-link btn ${
227 this.state.currentTab == "blocks" && "active"
230 { ctx: this, tab: "blocks" },
238 {this.state.currentTab == "settings" && this.userSettings()}
239 {this.state.currentTab == "blocks" && this.blockCards()}
247 <div className="row">
248 <div className="col-12 col-md-6">
249 <div className="card border-secondary mb-3">
250 <div className="card-body">{this.saveUserSettingsHtmlForm()}</div>
253 <div className="col-12 col-md-6">
254 <div className="card border-secondary mb-3">
255 <div className="card-body">{this.changePasswordHtmlForm()}</div>
264 <div className="row">
265 <div className="col-12 col-md-6">
266 <div className="card border-secondary mb-3">
267 <div className="card-body">{this.blockUserCard()}</div>
270 <div className="col-12 col-md-6">
271 <div className="card border-secondary mb-3">
272 <div className="card-body">{this.blockCommunityCard()}</div>
279 changePasswordHtmlForm() {
282 <h5>{i18n.t("change_password")}</h5>
283 <form onSubmit={linkEvent(this, this.handleChangePasswordSubmit)}>
284 <div className="form-group row">
285 <label className="col-sm-5 col-form-label" htmlFor="user-password">
286 {i18n.t("new_password")}
288 <div className="col-sm-7">
292 className="form-control"
293 value={this.state.changePasswordForm.new_password}
294 autoComplete="new-password"
296 onInput={linkEvent(this, this.handleNewPasswordChange)}
300 <div className="form-group row">
302 className="col-sm-5 col-form-label"
303 htmlFor="user-verify-password"
305 {i18n.t("verify_password")}
307 <div className="col-sm-7">
310 id="user-verify-password"
311 className="form-control"
312 value={this.state.changePasswordForm.new_password_verify}
313 autoComplete="new-password"
315 onInput={linkEvent(this, this.handleNewPasswordVerifyChange)}
319 <div className="form-group row">
321 className="col-sm-5 col-form-label"
322 htmlFor="user-old-password"
324 {i18n.t("old_password")}
326 <div className="col-sm-7">
329 id="user-old-password"
330 className="form-control"
331 value={this.state.changePasswordForm.old_password}
332 autoComplete="new-password"
334 onInput={linkEvent(this, this.handleOldPasswordChange)}
338 <div className="form-group">
339 <button type="submit" className="btn btn-block btn-secondary mr-4">
340 {this.state.changePasswordLoading ? (
343 capitalizeFirstLetter(i18n.t("save"))
355 {this.blockUserForm()}
356 {this.blockedUsersList()}
364 <h5>{i18n.t("blocked_users")}</h5>
365 <ul className="list-unstyled mb-0">
366 {this.state.personBlocks.map(pb => (
367 <li key={pb.target.id}>
369 <PersonListing person={pb.target} />
371 className="btn btn-sm"
373 { ctx: this, recipientId: pb.target.id },
374 this.handleUnblockPerson
376 data-tippy-content={i18n.t("unblock_user")}
378 <Icon icon="x" classes="icon-inline" />
390 <div className="form-group row">
392 className="col-md-4 col-form-label"
393 htmlFor="block-person-filter"
395 {i18n.t("block_user")}
397 <div className="col-md-8">
399 className="form-control"
400 id="block-person-filter"
401 value={this.state.blockPerson.map(p => p.person.id).unwrapOr(0)}
403 <option value="0">—</option>
404 {this.state.blockPerson.match({
405 some: personView => (
406 <option value={personView.person.id}>
407 {personSelectName(personView)}
418 blockCommunityCard() {
421 {this.blockCommunityForm()}
422 {this.blockedCommunitiesList()}
427 blockedCommunitiesList() {
430 <h5>{i18n.t("blocked_communities")}</h5>
431 <ul className="list-unstyled mb-0">
432 {this.state.communityBlocks.map(cb => (
433 <li key={cb.community.id}>
435 <CommunityLink community={cb.community} />
437 className="btn btn-sm"
439 { ctx: this, communityId: cb.community.id },
440 this.handleUnblockCommunity
442 data-tippy-content={i18n.t("unblock_community")}
444 <Icon icon="x" classes="icon-inline" />
454 blockCommunityForm() {
456 <div className="form-group row">
458 className="col-md-4 col-form-label"
459 htmlFor="block-community-filter"
461 {i18n.t("block_community")}
463 <div className="col-md-8">
465 className="form-control"
466 id="block-community-filter"
467 value={this.state.blockCommunityId}
469 <option value="0">—</option>
470 {this.state.blockCommunity && (
471 <option value={this.state.blockCommunity.community.id}>
472 {communitySelectName(this.state.blockCommunity)}
481 saveUserSettingsHtmlForm() {
484 <h5>{i18n.t("settings")}</h5>
485 <form onSubmit={linkEvent(this, this.handleSaveSettingsSubmit)}>
486 <div className="form-group row">
487 <label className="col-sm-5 col-form-label" htmlFor="display-name">
488 {i18n.t("display_name")}
490 <div className="col-sm-7">
494 className="form-control"
495 placeholder={i18n.t("optional")}
497 this.state.saveUserSettingsForm.display_name
499 onInput={linkEvent(this, this.handleDisplayNameChange)}
500 pattern="^(?!@)(.+)$"
505 <div className="form-group row">
506 <label className="col-sm-3 col-form-label" htmlFor="user-bio">
509 <div className="col-sm-9">
511 initialContent={this.state.saveUserSettingsForm.bio}
512 onContentChange={this.handleBioChange}
513 maxLength={Some(300)}
516 hideNavigationWarnings
520 <div className="form-group row">
521 <label className="col-sm-3 col-form-label" htmlFor="user-email">
524 <div className="col-sm-9">
528 className="form-control"
529 placeholder={i18n.t("optional")}
530 value={toUndefined(this.state.saveUserSettingsForm.email)}
531 onInput={linkEvent(this, this.handleEmailChange)}
536 <div className="form-group row">
537 <label className="col-sm-5 col-form-label" htmlFor="matrix-user-id">
538 <a href={elementUrl} rel={relTags}>
539 {i18n.t("matrix_user_id")}
542 <div className="col-sm-7">
546 className="form-control"
547 placeholder="@user:example.com"
549 this.state.saveUserSettingsForm.matrix_user_id
551 onInput={linkEvent(this, this.handleMatrixUserIdChange)}
552 pattern="^@[A-Za-z0-9._=-]+:[A-Za-z0-9.-]+\.[A-Za-z]{2,}$"
556 <div className="form-group row">
557 <label className="col-sm-3">{i18n.t("avatar")}</label>
558 <div className="col-sm-9">
560 uploadTitle={i18n.t("upload_avatar")}
561 imageSrc={this.state.saveUserSettingsForm.avatar}
562 onUpload={this.handleAvatarUpload}
563 onRemove={this.handleAvatarRemove}
568 <div className="form-group row">
569 <label className="col-sm-3">{i18n.t("banner")}</label>
570 <div className="col-sm-9">
572 uploadTitle={i18n.t("upload_banner")}
573 imageSrc={this.state.saveUserSettingsForm.banner}
574 onUpload={this.handleBannerUpload}
575 onRemove={this.handleBannerRemove}
579 <div className="form-group row">
580 <label className="col-sm-3" htmlFor="user-language">
583 <div className="col-sm-9">
586 value={toUndefined(this.state.saveUserSettingsForm.lang)}
587 onChange={linkEvent(this, this.handleLangChange)}
588 className="custom-select w-auto"
590 <option disabled aria-hidden="true">
593 <option value="browser">{i18n.t("browser_default")}</option>
594 <option disabled aria-hidden="true">
598 .sort((a, b) => a.code.localeCompare(b.code))
600 <option key={lang.code} value={lang.code}>
607 <div className="form-group row">
608 <label className="col-sm-3" htmlFor="user-theme">
611 <div className="col-sm-9">
614 value={toUndefined(this.state.saveUserSettingsForm.theme)}
615 onChange={linkEvent(this, this.handleThemeChange)}
616 className="custom-select w-auto"
618 <option disabled aria-hidden="true">
621 <option value="browser">{i18n.t("browser_default")}</option>
622 {this.state.themeList.map(theme => (
623 <option key={theme} value={theme}>
630 <form className="form-group row">
631 <label className="col-sm-3">{i18n.t("type")}</label>
632 <div className="col-sm-9">
635 Object.values(ListingType)[
636 this.state.saveUserSettingsForm.default_listing_type.unwrapOr(
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.unwrapOr(
658 onChange={this.handleSortTypeChange}
662 {enableNsfw(this.state.siteRes) && (
663 <div className="form-group">
664 <div className="form-check">
666 className="form-check-input"
669 checked={toUndefined(
670 this.state.saveUserSettingsForm.show_nsfw
672 onChange={linkEvent(this, this.handleShowNsfwChange)}
674 <label className="form-check-label" htmlFor="user-show-nsfw">
675 {i18n.t("show_nsfw")}
680 <div className="form-group">
681 <div className="form-check">
683 className="form-check-input"
684 id="user-show-scores"
686 checked={toUndefined(
687 this.state.saveUserSettingsForm.show_scores
689 onChange={linkEvent(this, this.handleShowScoresChange)}
691 <label className="form-check-label" htmlFor="user-show-scores">
692 {i18n.t("show_scores")}
696 <div className="form-group">
697 <div className="form-check">
699 className="form-check-input"
700 id="user-show-avatars"
702 checked={toUndefined(
703 this.state.saveUserSettingsForm.show_avatars
705 onChange={linkEvent(this, this.handleShowAvatarsChange)}
707 <label className="form-check-label" htmlFor="user-show-avatars">
708 {i18n.t("show_avatars")}
712 <div className="form-group">
713 <div className="form-check">
715 className="form-check-input"
716 id="user-bot-account"
718 checked={toUndefined(
719 this.state.saveUserSettingsForm.bot_account
721 onChange={linkEvent(this, this.handleBotAccount)}
723 <label className="form-check-label" htmlFor="user-bot-account">
724 {i18n.t("bot_account")}
728 <div className="form-group">
729 <div className="form-check">
731 className="form-check-input"
732 id="user-show-bot-accounts"
734 checked={toUndefined(
735 this.state.saveUserSettingsForm.show_bot_accounts
737 onChange={linkEvent(this, this.handleShowBotAccounts)}
740 className="form-check-label"
741 htmlFor="user-show-bot-accounts"
743 {i18n.t("show_bot_accounts")}
747 <div className="form-group">
748 <div className="form-check">
750 className="form-check-input"
751 id="user-show-read-posts"
753 checked={toUndefined(
754 this.state.saveUserSettingsForm.show_read_posts
756 onChange={linkEvent(this, this.handleReadPosts)}
759 className="form-check-label"
760 htmlFor="user-show-read-posts"
762 {i18n.t("show_read_posts")}
766 <div className="form-group">
767 <div className="form-check">
769 className="form-check-input"
770 id="user-show-new-post-notifs"
772 checked={toUndefined(
773 this.state.saveUserSettingsForm.show_new_post_notifs
775 onChange={linkEvent(this, this.handleShowNewPostNotifs)}
778 className="form-check-label"
779 htmlFor="user-show-new-post-notifs"
781 {i18n.t("show_new_post_notifs")}
785 <div className="form-group">
786 <div className="form-check">
788 className="form-check-input"
789 id="user-send-notifications-to-email"
791 disabled={!this.state.saveUserSettingsForm.email}
792 checked={toUndefined(
793 this.state.saveUserSettingsForm.send_notifications_to_email
797 this.handleSendNotificationsToEmailChange
801 className="form-check-label"
802 htmlFor="user-send-notifications-to-email"
804 {i18n.t("send_notifications_to_email")}
808 <div className="form-group">
809 <button type="submit" className="btn btn-block btn-secondary mr-4">
810 {this.state.saveUserSettingsLoading ? (
813 capitalizeFirstLetter(i18n.t("save"))
818 <div className="form-group">
820 className="btn btn-block btn-danger"
823 this.handleDeleteAccountShowConfirmToggle
826 {i18n.t("delete_account")}
828 {this.state.deleteAccountShowConfirm && (
830 <div className="my-2 alert alert-danger" role="alert">
831 {i18n.t("delete_account_confirm")}
835 value={this.state.deleteAccountForm.password}
836 autoComplete="new-password"
840 this.handleDeleteAccountPasswordChange
842 className="form-control my-2"
845 className="btn btn-danger mr-4"
846 disabled={!this.state.deleteAccountForm.password}
847 onClick={linkEvent(this, this.handleDeleteAccount)}
849 {this.state.deleteAccountLoading ? (
852 capitalizeFirstLetter(i18n.t("delete"))
856 className="btn btn-secondary"
859 this.handleDeleteAccountShowConfirmToggle
872 setupBlockPersonChoices() {
874 let selectId: any = document.getElementById("block-person-filter");
876 this.blockPersonChoices = new Choices(selectId, choicesConfig);
877 this.blockPersonChoices.passedElement.element.addEventListener(
880 this.handleBlockPerson(Number(e.detail.choice.value));
884 this.blockPersonChoices.passedElement.element.addEventListener(
886 debounce(async (e: any) => {
888 let persons = (await fetchUsers(e.detail.value)).users;
889 let choices = persons.map(pvs => personToChoice(pvs));
890 this.blockPersonChoices.setChoices(
906 setupBlockCommunityChoices() {
908 let selectId: any = document.getElementById("block-community-filter");
910 this.blockCommunityChoices = new Choices(selectId, choicesConfig);
911 this.blockCommunityChoices.passedElement.element.addEventListener(
914 this.handleBlockCommunity(Number(e.detail.choice.value));
918 this.blockCommunityChoices.passedElement.element.addEventListener(
920 debounce(async (e: any) => {
922 let communities = (await fetchCommunities(e.detail.value))
924 let choices = communities.map(cv => communityToChoice(cv));
925 this.blockCommunityChoices.setChoices(
941 handleBlockPerson(personId: number) {
943 let blockUserForm = new BlockPerson({
946 auth: auth().unwrap(),
948 WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm));
952 handleUnblockPerson(i: { ctx: Settings; recipientId: number }) {
953 let blockUserForm = new BlockPerson({
954 person_id: i.recipientId,
956 auth: auth().unwrap(),
958 WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm));
961 handleBlockCommunity(community_id: number) {
962 if (community_id != 0) {
963 let blockCommunityForm = new BlockCommunity({
966 auth: auth().unwrap(),
968 WebSocketService.Instance.send(
969 wsClient.blockCommunity(blockCommunityForm)
974 handleUnblockCommunity(i: { ctx: Settings; communityId: number }) {
975 let blockCommunityForm = new BlockCommunity({
976 community_id: i.communityId,
978 auth: auth().unwrap(),
980 WebSocketService.Instance.send(wsClient.blockCommunity(blockCommunityForm));
983 handleShowNsfwChange(i: Settings, event: any) {
984 i.state.saveUserSettingsForm.show_nsfw = Some(event.target.checked);
988 handleShowAvatarsChange(i: Settings, event: any) {
989 i.state.saveUserSettingsForm.show_avatars = Some(event.target.checked);
990 UserService.Instance.myUserInfo.match({
992 (mui.local_user_view.local_user.show_avatars = event.target.checked),
998 handleBotAccount(i: Settings, event: any) {
999 i.state.saveUserSettingsForm.bot_account = Some(event.target.checked);
1000 i.setState(i.state);
1003 handleShowBotAccounts(i: Settings, event: any) {
1004 i.state.saveUserSettingsForm.show_bot_accounts = Some(event.target.checked);
1005 i.setState(i.state);
1008 handleReadPosts(i: Settings, event: any) {
1009 i.state.saveUserSettingsForm.show_read_posts = Some(event.target.checked);
1010 i.setState(i.state);
1013 handleShowNewPostNotifs(i: Settings, event: any) {
1014 i.state.saveUserSettingsForm.show_new_post_notifs = Some(
1015 event.target.checked
1017 i.setState(i.state);
1020 handleShowScoresChange(i: Settings, event: any) {
1021 i.state.saveUserSettingsForm.show_scores = Some(event.target.checked);
1022 UserService.Instance.myUserInfo.match({
1024 (mui.local_user_view.local_user.show_scores = event.target.checked),
1027 i.setState(i.state);
1030 handleSendNotificationsToEmailChange(i: Settings, event: any) {
1031 i.state.saveUserSettingsForm.send_notifications_to_email = Some(
1032 event.target.checked
1034 i.setState(i.state);
1037 handleThemeChange(i: Settings, event: any) {
1038 i.state.saveUserSettingsForm.theme = Some(event.target.value);
1039 setTheme(event.target.value, true);
1040 i.setState(i.state);
1043 handleLangChange(i: Settings, event: any) {
1044 i.state.saveUserSettingsForm.lang = Some(event.target.value);
1045 i18n.changeLanguage(
1046 getLanguages(i.state.saveUserSettingsForm.lang.unwrap())[0]
1048 i.setState(i.state);
1051 handleSortTypeChange(val: SortType) {
1054 (s.saveUserSettingsForm.default_sort_type = Some(
1055 Object.keys(SortType).indexOf(val)
1062 handleListingTypeChange(val: ListingType) {
1065 (s.saveUserSettingsForm.default_listing_type = Some(
1066 Object.keys(ListingType).indexOf(val)
1073 handleEmailChange(i: Settings, event: any) {
1074 i.state.saveUserSettingsForm.email = Some(event.target.value);
1075 i.setState(i.state);
1078 handleBioChange(val: string) {
1079 this.setState(s => ((s.saveUserSettingsForm.bio = Some(val)), s));
1082 handleAvatarUpload(url: string) {
1083 this.setState(s => ((s.saveUserSettingsForm.avatar = Some(url)), s));
1086 handleAvatarRemove() {
1087 this.setState(s => ((s.saveUserSettingsForm.avatar = Some("")), s));
1090 handleBannerUpload(url: string) {
1091 this.setState(s => ((s.saveUserSettingsForm.banner = Some(url)), s));
1094 handleBannerRemove() {
1095 this.setState(s => ((s.saveUserSettingsForm.banner = Some("")), s));
1098 handleDisplayNameChange(i: Settings, event: any) {
1099 i.state.saveUserSettingsForm.display_name = Some(event.target.value);
1100 i.setState(i.state);
1103 handleMatrixUserIdChange(i: Settings, event: any) {
1104 i.state.saveUserSettingsForm.matrix_user_id = Some(event.target.value);
1105 i.setState(i.state);
1108 handleNewPasswordChange(i: Settings, event: any) {
1109 i.state.changePasswordForm.new_password = event.target.value;
1110 if (i.state.changePasswordForm.new_password == "") {
1111 i.state.changePasswordForm.new_password = undefined;
1113 i.setState(i.state);
1116 handleNewPasswordVerifyChange(i: Settings, event: any) {
1117 i.state.changePasswordForm.new_password_verify = event.target.value;
1118 if (i.state.changePasswordForm.new_password_verify == "") {
1119 i.state.changePasswordForm.new_password_verify = undefined;
1121 i.setState(i.state);
1124 handleOldPasswordChange(i: Settings, event: any) {
1125 i.state.changePasswordForm.old_password = event.target.value;
1126 if (i.state.changePasswordForm.old_password == "") {
1127 i.state.changePasswordForm.old_password = undefined;
1129 i.setState(i.state);
1132 handleSaveSettingsSubmit(i: Settings, event: any) {
1133 event.preventDefault();
1134 i.setState({ saveUserSettingsLoading: true });
1135 i.setState(s => ((s.saveUserSettingsForm.auth = auth().unwrap()), s));
1137 let form = new SaveUserSettings({ ...i.state.saveUserSettingsForm });
1138 WebSocketService.Instance.send(wsClient.saveUserSettings(form));
1141 handleChangePasswordSubmit(i: Settings, event: any) {
1142 event.preventDefault();
1143 i.setState({ changePasswordLoading: true });
1144 i.setState(s => ((s.changePasswordForm.auth = auth().unwrap()), s));
1146 let form = new ChangePassword({ ...i.state.changePasswordForm });
1148 WebSocketService.Instance.send(wsClient.changePassword(form));
1151 handleDeleteAccountShowConfirmToggle(i: Settings, event: any) {
1152 event.preventDefault();
1153 i.setState({ deleteAccountShowConfirm: !i.state.deleteAccountShowConfirm });
1156 handleDeleteAccountPasswordChange(i: Settings, event: any) {
1157 i.state.deleteAccountForm.password = event.target.value;
1158 i.setState(i.state);
1161 handleDeleteAccount(i: Settings, event: any) {
1162 event.preventDefault();
1163 i.setState({ deleteAccountLoading: true });
1164 i.setState(s => ((s.deleteAccountForm.auth = auth().unwrap()), s));
1166 let form = new DeleteAccount({ ...i.state.deleteAccountForm });
1168 WebSocketService.Instance.send(wsClient.deleteAccount(form));
1171 handleSwitchTab(i: { ctx: Settings; tab: string }) {
1172 i.ctx.setState({ currentTab: i.tab });
1174 if (i.ctx.state.currentTab == "blocks") {
1175 i.ctx.setupBlockPersonChoices();
1176 i.ctx.setupBlockCommunityChoices();
1180 parseMessage(msg: any) {
1181 let op = wsUserOp(msg);
1185 saveUserSettingsLoading: false,
1186 changePasswordLoading: false,
1187 deleteAccountLoading: false,
1189 toast(i18n.t(msg.error), "danger");
1191 } else if (op == UserOperation.SaveUserSettings) {
1192 let data = wsJsonToRes<LoginResponse>(msg, LoginResponse);
1193 UserService.Instance.login(data);
1194 this.setState({ saveUserSettingsLoading: false });
1195 toast(i18n.t("saved"));
1196 window.scrollTo(0, 0);
1197 } else if (op == UserOperation.ChangePassword) {
1198 let data = wsJsonToRes<LoginResponse>(msg, LoginResponse);
1199 UserService.Instance.login(data);
1200 this.setState({ changePasswordLoading: false });
1201 window.scrollTo(0, 0);
1202 toast(i18n.t("password_changed"));
1203 } else if (op == UserOperation.DeleteAccount) {
1205 deleteAccountLoading: false,
1206 deleteAccountShowConfirm: false,
1208 UserService.Instance.logout();
1209 window.location.href = "/";
1210 } else if (op == UserOperation.BlockPerson) {
1211 let data = wsJsonToRes<BlockPersonResponse>(msg, BlockPersonResponse);
1212 updatePersonBlock(data).match({
1213 some: blocks => this.setState({ personBlocks: blocks }),
1216 } else if (op == UserOperation.BlockCommunity) {
1217 let data = wsJsonToRes<BlockCommunityResponse>(
1219 BlockCommunityResponse
1221 updateCommunityBlock(data).match({
1222 some: blocks => this.setState({ communityBlocks: blocks }),