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 { LanguageSelect } from "../common/language-select";
58 import { ListingTypeSelect } from "../common/listing-type-select";
59 import { MarkdownTextArea } from "../common/markdown-textarea";
60 import { SortSelect } from "../common/sort-select";
61 import { CommunityLink } from "../community/community-link";
62 import { PersonListing } from "./person-listing";
66 Choices = require("choices.js");
69 interface SettingsState {
70 saveUserSettingsForm: SaveUserSettings;
71 changePasswordForm: ChangePassword;
72 deleteAccountForm: DeleteAccount;
73 personBlocks: PersonBlockView[];
74 blockPerson: Option<PersonViewSafe>;
75 communityBlocks: CommunityBlockView[];
76 blockCommunityId: number;
77 blockCommunity?: CommunityView;
80 saveUserSettingsLoading: boolean;
81 changePasswordLoading: boolean;
82 deleteAccountLoading: boolean;
83 deleteAccountShowConfirm: boolean;
84 siteRes: GetSiteResponse;
87 export class Settings extends Component<any, SettingsState> {
88 private isoData = setIsoData(this.context);
89 private blockPersonChoices: any;
90 private blockCommunityChoices: any;
91 private subscription: Subscription;
92 private emptyState: SettingsState = {
93 saveUserSettingsForm: new SaveUserSettings({
97 show_read_posts: None,
98 show_bot_accounts: None,
99 show_new_post_notifs: None,
100 default_sort_type: None,
101 default_listing_type: None,
103 interface_language: None,
104 discussion_languages: None,
110 matrix_user_id: None,
111 send_notifications_to_email: None,
115 changePasswordForm: new ChangePassword({
116 new_password: undefined,
117 new_password_verify: undefined,
118 old_password: undefined,
121 saveUserSettingsLoading: false,
122 changePasswordLoading: false,
123 deleteAccountLoading: false,
124 deleteAccountShowConfirm: false,
125 deleteAccountForm: new DeleteAccount({
133 currentTab: "settings",
134 siteRes: this.isoData.site_res,
138 constructor(props: any, context: any) {
139 super(props, context);
141 this.state = this.emptyState;
142 this.handleSortTypeChange = this.handleSortTypeChange.bind(this);
143 this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
144 this.handleBioChange = this.handleBioChange.bind(this);
145 this.handleDiscussionLanguageChange =
146 this.handleDiscussionLanguageChange.bind(this);
148 this.handleAvatarUpload = this.handleAvatarUpload.bind(this);
149 this.handleAvatarRemove = this.handleAvatarRemove.bind(this);
151 this.handleBannerUpload = this.handleBannerUpload.bind(this);
152 this.handleBannerRemove = this.handleBannerRemove.bind(this);
154 this.parseMessage = this.parseMessage.bind(this);
155 this.subscription = wsSubscribe(this.parseMessage);
157 if (UserService.Instance.myUserInfo.isSome()) {
158 let mui = UserService.Instance.myUserInfo.unwrap();
159 let luv = mui.local_user_view;
162 personBlocks: mui.person_blocks,
163 communityBlocks: mui.community_blocks,
164 saveUserSettingsForm: {
165 ...this.state.saveUserSettingsForm,
166 show_nsfw: Some(luv.local_user.show_nsfw),
167 theme: Some(luv.local_user.theme ? luv.local_user.theme : "browser"),
168 default_sort_type: Some(luv.local_user.default_sort_type),
169 default_listing_type: Some(luv.local_user.default_listing_type),
170 interface_language: Some(luv.local_user.interface_language),
171 discussion_languages: Some(mui.discussion_languages.map(l => l.id)),
172 avatar: luv.person.avatar,
173 banner: luv.person.banner,
174 display_name: luv.person.display_name,
175 show_avatars: Some(luv.local_user.show_avatars),
176 bot_account: Some(luv.person.bot_account),
177 show_bot_accounts: Some(luv.local_user.show_bot_accounts),
178 show_scores: Some(luv.local_user.show_scores),
179 show_read_posts: Some(luv.local_user.show_read_posts),
180 show_new_post_notifs: Some(luv.local_user.show_new_post_notifs),
181 email: luv.local_user.email,
183 send_notifications_to_email: Some(
184 luv.local_user.send_notifications_to_email
186 matrix_user_id: luv.person.matrix_user_id,
192 async componentDidMount() {
194 this.setState({ themeList: await fetchThemeList() });
197 componentWillUnmount() {
198 this.subscription.unsubscribe();
201 get documentTitle(): string {
202 return i18n.t("settings");
207 <div className="container">
210 title={this.documentTitle}
211 path={this.context.router.route.match.url}
212 description={Some(this.documentTitle)}
213 image={this.state.saveUserSettingsForm.avatar}
215 <ul className="nav nav-tabs mb-2">
216 <li className="nav-item">
218 className={`nav-link btn ${
219 this.state.currentTab == "settings" && "active"
222 { ctx: this, tab: "settings" },
229 <li className="nav-item">
231 className={`nav-link btn ${
232 this.state.currentTab == "blocks" && "active"
235 { ctx: this, tab: "blocks" },
243 {this.state.currentTab == "settings" && this.userSettings()}
244 {this.state.currentTab == "blocks" && this.blockCards()}
252 <div className="row">
253 <div className="col-12 col-md-6">
254 <div className="card border-secondary mb-3">
255 <div className="card-body">{this.saveUserSettingsHtmlForm()}</div>
258 <div className="col-12 col-md-6">
259 <div className="card border-secondary mb-3">
260 <div className="card-body">{this.changePasswordHtmlForm()}</div>
269 <div className="row">
270 <div className="col-12 col-md-6">
271 <div className="card border-secondary mb-3">
272 <div className="card-body">{this.blockUserCard()}</div>
275 <div className="col-12 col-md-6">
276 <div className="card border-secondary mb-3">
277 <div className="card-body">{this.blockCommunityCard()}</div>
284 changePasswordHtmlForm() {
287 <h5>{i18n.t("change_password")}</h5>
288 <form onSubmit={linkEvent(this, this.handleChangePasswordSubmit)}>
289 <div className="form-group row">
290 <label className="col-sm-5 col-form-label" htmlFor="user-password">
291 {i18n.t("new_password")}
293 <div className="col-sm-7">
297 className="form-control"
298 value={this.state.changePasswordForm.new_password}
299 autoComplete="new-password"
301 onInput={linkEvent(this, this.handleNewPasswordChange)}
305 <div className="form-group row">
307 className="col-sm-5 col-form-label"
308 htmlFor="user-verify-password"
310 {i18n.t("verify_password")}
312 <div className="col-sm-7">
315 id="user-verify-password"
316 className="form-control"
317 value={this.state.changePasswordForm.new_password_verify}
318 autoComplete="new-password"
320 onInput={linkEvent(this, this.handleNewPasswordVerifyChange)}
324 <div className="form-group row">
326 className="col-sm-5 col-form-label"
327 htmlFor="user-old-password"
329 {i18n.t("old_password")}
331 <div className="col-sm-7">
334 id="user-old-password"
335 className="form-control"
336 value={this.state.changePasswordForm.old_password}
337 autoComplete="new-password"
339 onInput={linkEvent(this, this.handleOldPasswordChange)}
343 <div className="form-group">
344 <button type="submit" className="btn btn-block btn-secondary mr-4">
345 {this.state.changePasswordLoading ? (
348 capitalizeFirstLetter(i18n.t("save"))
360 {this.blockUserForm()}
361 {this.blockedUsersList()}
369 <h5>{i18n.t("blocked_users")}</h5>
370 <ul className="list-unstyled mb-0">
371 {this.state.personBlocks.map(pb => (
372 <li key={pb.target.id}>
374 <PersonListing person={pb.target} />
376 className="btn btn-sm"
378 { ctx: this, recipientId: pb.target.id },
379 this.handleUnblockPerson
381 data-tippy-content={i18n.t("unblock_user")}
383 <Icon icon="x" classes="icon-inline" />
395 <div className="form-group row">
397 className="col-md-4 col-form-label"
398 htmlFor="block-person-filter"
400 {i18n.t("block_user")}
402 <div className="col-md-8">
404 className="form-control"
405 id="block-person-filter"
406 value={this.state.blockPerson.map(p => p.person.id).unwrapOr(0)}
408 <option value="0">—</option>
409 {this.state.blockPerson.match({
410 some: personView => (
411 <option value={personView.person.id}>
412 {personSelectName(personView)}
423 blockCommunityCard() {
426 {this.blockCommunityForm()}
427 {this.blockedCommunitiesList()}
432 blockedCommunitiesList() {
435 <h5>{i18n.t("blocked_communities")}</h5>
436 <ul className="list-unstyled mb-0">
437 {this.state.communityBlocks.map(cb => (
438 <li key={cb.community.id}>
440 <CommunityLink community={cb.community} />
442 className="btn btn-sm"
444 { ctx: this, communityId: cb.community.id },
445 this.handleUnblockCommunity
447 data-tippy-content={i18n.t("unblock_community")}
449 <Icon icon="x" classes="icon-inline" />
459 blockCommunityForm() {
461 <div className="form-group row">
463 className="col-md-4 col-form-label"
464 htmlFor="block-community-filter"
466 {i18n.t("block_community")}
468 <div className="col-md-8">
470 className="form-control"
471 id="block-community-filter"
472 value={this.state.blockCommunityId}
474 <option value="0">—</option>
475 {this.state.blockCommunity && (
476 <option value={this.state.blockCommunity.community.id}>
477 {communitySelectName(this.state.blockCommunity)}
486 saveUserSettingsHtmlForm() {
487 let selectedLangs = this.state.saveUserSettingsForm.discussion_languages;
491 <h5>{i18n.t("settings")}</h5>
492 <form onSubmit={linkEvent(this, this.handleSaveSettingsSubmit)}>
493 <div className="form-group row">
494 <label className="col-sm-5 col-form-label" htmlFor="display-name">
495 {i18n.t("display_name")}
497 <div className="col-sm-7">
501 className="form-control"
502 placeholder={i18n.t("optional")}
504 this.state.saveUserSettingsForm.display_name
506 onInput={linkEvent(this, this.handleDisplayNameChange)}
507 pattern="^(?!@)(.+)$"
512 <div className="form-group row">
513 <label className="col-sm-3 col-form-label" htmlFor="user-bio">
516 <div className="col-sm-9">
518 initialContent={this.state.saveUserSettingsForm.bio}
519 initialLanguageId={None}
520 onContentChange={this.handleBioChange}
521 maxLength={Some(300)}
524 hideNavigationWarnings
525 allLanguages={this.state.siteRes.all_languages}
529 <div className="form-group row">
530 <label className="col-sm-3 col-form-label" htmlFor="user-email">
533 <div className="col-sm-9">
537 className="form-control"
538 placeholder={i18n.t("optional")}
539 value={toUndefined(this.state.saveUserSettingsForm.email)}
540 onInput={linkEvent(this, this.handleEmailChange)}
545 <div className="form-group row">
546 <label className="col-sm-5 col-form-label" htmlFor="matrix-user-id">
547 <a href={elementUrl} rel={relTags}>
548 {i18n.t("matrix_user_id")}
551 <div className="col-sm-7">
555 className="form-control"
556 placeholder="@user:example.com"
558 this.state.saveUserSettingsForm.matrix_user_id
560 onInput={linkEvent(this, this.handleMatrixUserIdChange)}
561 pattern="^@[A-Za-z0-9._=-]+:[A-Za-z0-9.-]+\.[A-Za-z]{2,}$"
565 <div className="form-group row">
566 <label className="col-sm-3">{i18n.t("avatar")}</label>
567 <div className="col-sm-9">
569 uploadTitle={i18n.t("upload_avatar")}
570 imageSrc={this.state.saveUserSettingsForm.avatar}
571 onUpload={this.handleAvatarUpload}
572 onRemove={this.handleAvatarRemove}
577 <div className="form-group row">
578 <label className="col-sm-3">{i18n.t("banner")}</label>
579 <div className="col-sm-9">
581 uploadTitle={i18n.t("upload_banner")}
582 imageSrc={this.state.saveUserSettingsForm.banner}
583 onUpload={this.handleBannerUpload}
584 onRemove={this.handleBannerRemove}
588 <div className="form-group row">
589 <label className="col-sm-3" htmlFor="user-language">
590 {i18n.t("interface_language")}
592 <div className="col-sm-9">
596 this.state.saveUserSettingsForm.interface_language
598 onChange={linkEvent(this, this.handleInterfaceLangChange)}
599 className="custom-select w-auto"
601 <option disabled aria-hidden="true">
602 {i18n.t("interface_language")}
604 <option value="browser">{i18n.t("browser_default")}</option>
605 <option disabled aria-hidden="true">
609 .sort((a, b) => a.code.localeCompare(b.code))
611 <option key={lang.code} value={lang.code}>
619 allLanguages={this.state.siteRes.all_languages}
620 selectedLanguageIds={selectedLangs}
622 onChange={this.handleDiscussionLanguageChange}
624 <div className="form-group row">
625 <label className="col-sm-3" htmlFor="user-theme">
628 <div className="col-sm-9">
631 value={toUndefined(this.state.saveUserSettingsForm.theme)}
632 onChange={linkEvent(this, this.handleThemeChange)}
633 className="custom-select w-auto"
635 <option disabled aria-hidden="true">
638 <option value="browser">{i18n.t("browser_default")}</option>
639 {this.state.themeList.map(theme => (
640 <option key={theme} value={theme}>
647 <form className="form-group row">
648 <label className="col-sm-3">{i18n.t("type")}</label>
649 <div className="col-sm-9">
652 Object.values(ListingType)[
653 this.state.saveUserSettingsForm.default_listing_type.unwrapOr(
658 showLocal={showLocal(this.isoData)}
660 onChange={this.handleListingTypeChange}
664 <form className="form-group row">
665 <label className="col-sm-3">{i18n.t("sort_type")}</label>
666 <div className="col-sm-9">
669 Object.values(SortType)[
670 this.state.saveUserSettingsForm.default_sort_type.unwrapOr(
675 onChange={this.handleSortTypeChange}
679 {enableNsfw(this.state.siteRes) && (
680 <div className="form-group">
681 <div className="form-check">
683 className="form-check-input"
686 checked={toUndefined(
687 this.state.saveUserSettingsForm.show_nsfw
689 onChange={linkEvent(this, this.handleShowNsfwChange)}
691 <label className="form-check-label" htmlFor="user-show-nsfw">
692 {i18n.t("show_nsfw")}
697 <div className="form-group">
698 <div className="form-check">
700 className="form-check-input"
701 id="user-show-scores"
703 checked={toUndefined(
704 this.state.saveUserSettingsForm.show_scores
706 onChange={linkEvent(this, this.handleShowScoresChange)}
708 <label className="form-check-label" htmlFor="user-show-scores">
709 {i18n.t("show_scores")}
713 <div className="form-group">
714 <div className="form-check">
716 className="form-check-input"
717 id="user-show-avatars"
719 checked={toUndefined(
720 this.state.saveUserSettingsForm.show_avatars
722 onChange={linkEvent(this, this.handleShowAvatarsChange)}
724 <label className="form-check-label" htmlFor="user-show-avatars">
725 {i18n.t("show_avatars")}
729 <div className="form-group">
730 <div className="form-check">
732 className="form-check-input"
733 id="user-bot-account"
735 checked={toUndefined(
736 this.state.saveUserSettingsForm.bot_account
738 onChange={linkEvent(this, this.handleBotAccount)}
740 <label className="form-check-label" htmlFor="user-bot-account">
741 {i18n.t("bot_account")}
745 <div className="form-group">
746 <div className="form-check">
748 className="form-check-input"
749 id="user-show-bot-accounts"
751 checked={toUndefined(
752 this.state.saveUserSettingsForm.show_bot_accounts
754 onChange={linkEvent(this, this.handleShowBotAccounts)}
757 className="form-check-label"
758 htmlFor="user-show-bot-accounts"
760 {i18n.t("show_bot_accounts")}
764 <div className="form-group">
765 <div className="form-check">
767 className="form-check-input"
768 id="user-show-read-posts"
770 checked={toUndefined(
771 this.state.saveUserSettingsForm.show_read_posts
773 onChange={linkEvent(this, this.handleReadPosts)}
776 className="form-check-label"
777 htmlFor="user-show-read-posts"
779 {i18n.t("show_read_posts")}
783 <div className="form-group">
784 <div className="form-check">
786 className="form-check-input"
787 id="user-show-new-post-notifs"
789 checked={toUndefined(
790 this.state.saveUserSettingsForm.show_new_post_notifs
792 onChange={linkEvent(this, this.handleShowNewPostNotifs)}
795 className="form-check-label"
796 htmlFor="user-show-new-post-notifs"
798 {i18n.t("show_new_post_notifs")}
802 <div className="form-group">
803 <div className="form-check">
805 className="form-check-input"
806 id="user-send-notifications-to-email"
808 disabled={!this.state.saveUserSettingsForm.email}
809 checked={toUndefined(
810 this.state.saveUserSettingsForm.send_notifications_to_email
814 this.handleSendNotificationsToEmailChange
818 className="form-check-label"
819 htmlFor="user-send-notifications-to-email"
821 {i18n.t("send_notifications_to_email")}
825 <div className="form-group">
826 <button type="submit" className="btn btn-block btn-secondary mr-4">
827 {this.state.saveUserSettingsLoading ? (
830 capitalizeFirstLetter(i18n.t("save"))
835 <div className="form-group">
837 className="btn btn-block btn-danger"
840 this.handleDeleteAccountShowConfirmToggle
843 {i18n.t("delete_account")}
845 {this.state.deleteAccountShowConfirm && (
847 <div className="my-2 alert alert-danger" role="alert">
848 {i18n.t("delete_account_confirm")}
852 value={this.state.deleteAccountForm.password}
853 autoComplete="new-password"
857 this.handleDeleteAccountPasswordChange
859 className="form-control my-2"
862 className="btn btn-danger mr-4"
863 disabled={!this.state.deleteAccountForm.password}
864 onClick={linkEvent(this, this.handleDeleteAccount)}
866 {this.state.deleteAccountLoading ? (
869 capitalizeFirstLetter(i18n.t("delete"))
873 className="btn btn-secondary"
876 this.handleDeleteAccountShowConfirmToggle
889 setupBlockPersonChoices() {
891 let selectId: any = document.getElementById("block-person-filter");
893 this.blockPersonChoices = new Choices(selectId, choicesConfig);
894 this.blockPersonChoices.passedElement.element.addEventListener(
897 this.handleBlockPerson(Number(e.detail.choice.value));
901 this.blockPersonChoices.passedElement.element.addEventListener(
903 debounce(async (e: any) => {
905 let persons = (await fetchUsers(e.detail.value)).users;
906 let choices = persons.map(pvs => personToChoice(pvs));
907 this.blockPersonChoices.setChoices(
923 setupBlockCommunityChoices() {
925 let selectId: any = document.getElementById("block-community-filter");
927 this.blockCommunityChoices = new Choices(selectId, choicesConfig);
928 this.blockCommunityChoices.passedElement.element.addEventListener(
931 this.handleBlockCommunity(Number(e.detail.choice.value));
935 this.blockCommunityChoices.passedElement.element.addEventListener(
937 debounce(async (e: any) => {
939 let communities = (await fetchCommunities(e.detail.value))
941 let choices = communities.map(cv => communityToChoice(cv));
942 this.blockCommunityChoices.setChoices(
958 handleBlockPerson(personId: number) {
960 let blockUserForm = new BlockPerson({
963 auth: auth().unwrap(),
965 WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm));
969 handleUnblockPerson(i: { ctx: Settings; recipientId: number }) {
970 let blockUserForm = new BlockPerson({
971 person_id: i.recipientId,
973 auth: auth().unwrap(),
975 WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm));
978 handleBlockCommunity(community_id: number) {
979 if (community_id != 0) {
980 let blockCommunityForm = new BlockCommunity({
983 auth: auth().unwrap(),
985 WebSocketService.Instance.send(
986 wsClient.blockCommunity(blockCommunityForm)
991 handleUnblockCommunity(i: { ctx: Settings; communityId: number }) {
992 let blockCommunityForm = new BlockCommunity({
993 community_id: i.communityId,
995 auth: auth().unwrap(),
997 WebSocketService.Instance.send(wsClient.blockCommunity(blockCommunityForm));
1000 handleShowNsfwChange(i: Settings, event: any) {
1001 i.state.saveUserSettingsForm.show_nsfw = Some(event.target.checked);
1002 i.setState(i.state);
1005 handleShowAvatarsChange(i: Settings, event: any) {
1006 i.state.saveUserSettingsForm.show_avatars = Some(event.target.checked);
1007 UserService.Instance.myUserInfo.match({
1009 (mui.local_user_view.local_user.show_avatars = event.target.checked),
1012 i.setState(i.state);
1015 handleBotAccount(i: Settings, event: any) {
1016 i.state.saveUserSettingsForm.bot_account = Some(event.target.checked);
1017 i.setState(i.state);
1020 handleShowBotAccounts(i: Settings, event: any) {
1021 i.state.saveUserSettingsForm.show_bot_accounts = Some(event.target.checked);
1022 i.setState(i.state);
1025 handleReadPosts(i: Settings, event: any) {
1026 i.state.saveUserSettingsForm.show_read_posts = Some(event.target.checked);
1027 i.setState(i.state);
1030 handleShowNewPostNotifs(i: Settings, event: any) {
1031 i.state.saveUserSettingsForm.show_new_post_notifs = Some(
1032 event.target.checked
1034 i.setState(i.state);
1037 handleShowScoresChange(i: Settings, event: any) {
1038 i.state.saveUserSettingsForm.show_scores = Some(event.target.checked);
1039 UserService.Instance.myUserInfo.match({
1041 (mui.local_user_view.local_user.show_scores = event.target.checked),
1044 i.setState(i.state);
1047 handleSendNotificationsToEmailChange(i: Settings, event: any) {
1048 i.state.saveUserSettingsForm.send_notifications_to_email = Some(
1049 event.target.checked
1051 i.setState(i.state);
1054 handleThemeChange(i: Settings, event: any) {
1055 i.state.saveUserSettingsForm.theme = Some(event.target.value);
1056 setTheme(event.target.value, true);
1057 i.setState(i.state);
1060 handleInterfaceLangChange(i: Settings, event: any) {
1061 i.state.saveUserSettingsForm.interface_language = Some(event.target.value);
1062 i18n.changeLanguage(
1063 getLanguages(i.state.saveUserSettingsForm.interface_language.unwrap())[0]
1065 i.setState(i.state);
1068 handleDiscussionLanguageChange(val: number[]) {
1070 s => ((s.saveUserSettingsForm.discussion_languages = Some(val)), s)
1074 handleSortTypeChange(val: SortType) {
1077 (s.saveUserSettingsForm.default_sort_type = Some(
1078 Object.keys(SortType).indexOf(val)
1085 handleListingTypeChange(val: ListingType) {
1088 (s.saveUserSettingsForm.default_listing_type = Some(
1089 Object.keys(ListingType).indexOf(val)
1096 handleEmailChange(i: Settings, event: any) {
1097 i.state.saveUserSettingsForm.email = Some(event.target.value);
1098 i.setState(i.state);
1101 handleBioChange(val: string) {
1102 this.setState(s => ((s.saveUserSettingsForm.bio = Some(val)), s));
1105 handleAvatarUpload(url: string) {
1106 this.setState(s => ((s.saveUserSettingsForm.avatar = Some(url)), s));
1109 handleAvatarRemove() {
1110 this.setState(s => ((s.saveUserSettingsForm.avatar = Some("")), s));
1113 handleBannerUpload(url: string) {
1114 this.setState(s => ((s.saveUserSettingsForm.banner = Some(url)), s));
1117 handleBannerRemove() {
1118 this.setState(s => ((s.saveUserSettingsForm.banner = Some("")), s));
1121 handleDisplayNameChange(i: Settings, event: any) {
1122 i.state.saveUserSettingsForm.display_name = Some(event.target.value);
1123 i.setState(i.state);
1126 handleMatrixUserIdChange(i: Settings, event: any) {
1127 i.state.saveUserSettingsForm.matrix_user_id = Some(event.target.value);
1128 i.setState(i.state);
1131 handleNewPasswordChange(i: Settings, event: any) {
1132 i.state.changePasswordForm.new_password = event.target.value;
1133 if (i.state.changePasswordForm.new_password == "") {
1134 i.state.changePasswordForm.new_password = undefined;
1136 i.setState(i.state);
1139 handleNewPasswordVerifyChange(i: Settings, event: any) {
1140 i.state.changePasswordForm.new_password_verify = event.target.value;
1141 if (i.state.changePasswordForm.new_password_verify == "") {
1142 i.state.changePasswordForm.new_password_verify = undefined;
1144 i.setState(i.state);
1147 handleOldPasswordChange(i: Settings, event: any) {
1148 i.state.changePasswordForm.old_password = event.target.value;
1149 if (i.state.changePasswordForm.old_password == "") {
1150 i.state.changePasswordForm.old_password = undefined;
1152 i.setState(i.state);
1155 handleSaveSettingsSubmit(i: Settings, event: any) {
1156 event.preventDefault();
1157 i.setState({ saveUserSettingsLoading: true });
1158 i.setState(s => ((s.saveUserSettingsForm.auth = auth().unwrap()), s));
1160 let form = new SaveUserSettings({ ...i.state.saveUserSettingsForm });
1161 WebSocketService.Instance.send(wsClient.saveUserSettings(form));
1164 handleChangePasswordSubmit(i: Settings, event: any) {
1165 event.preventDefault();
1166 i.setState({ changePasswordLoading: true });
1167 i.setState(s => ((s.changePasswordForm.auth = auth().unwrap()), s));
1169 let form = new ChangePassword({ ...i.state.changePasswordForm });
1171 WebSocketService.Instance.send(wsClient.changePassword(form));
1174 handleDeleteAccountShowConfirmToggle(i: Settings, event: any) {
1175 event.preventDefault();
1176 i.setState({ deleteAccountShowConfirm: !i.state.deleteAccountShowConfirm });
1179 handleDeleteAccountPasswordChange(i: Settings, event: any) {
1180 i.state.deleteAccountForm.password = event.target.value;
1181 i.setState(i.state);
1184 handleDeleteAccount(i: Settings, event: any) {
1185 event.preventDefault();
1186 i.setState({ deleteAccountLoading: true });
1187 i.setState(s => ((s.deleteAccountForm.auth = auth().unwrap()), s));
1189 let form = new DeleteAccount({ ...i.state.deleteAccountForm });
1191 WebSocketService.Instance.send(wsClient.deleteAccount(form));
1194 handleSwitchTab(i: { ctx: Settings; tab: string }) {
1195 i.ctx.setState({ currentTab: i.tab });
1197 if (i.ctx.state.currentTab == "blocks") {
1198 i.ctx.setupBlockPersonChoices();
1199 i.ctx.setupBlockCommunityChoices();
1203 parseMessage(msg: any) {
1204 let op = wsUserOp(msg);
1208 saveUserSettingsLoading: false,
1209 changePasswordLoading: false,
1210 deleteAccountLoading: false,
1212 toast(i18n.t(msg.error), "danger");
1214 } else if (op == UserOperation.SaveUserSettings) {
1215 let data = wsJsonToRes<LoginResponse>(msg, LoginResponse);
1216 UserService.Instance.login(data);
1217 this.setState({ saveUserSettingsLoading: false });
1218 toast(i18n.t("saved"));
1219 window.scrollTo(0, 0);
1220 } else if (op == UserOperation.ChangePassword) {
1221 let data = wsJsonToRes<LoginResponse>(msg, LoginResponse);
1222 UserService.Instance.login(data);
1223 this.setState({ changePasswordLoading: false });
1224 window.scrollTo(0, 0);
1225 toast(i18n.t("password_changed"));
1226 } else if (op == UserOperation.DeleteAccount) {
1228 deleteAccountLoading: false,
1229 deleteAccountShowConfirm: false,
1231 UserService.Instance.logout();
1232 window.location.href = "/";
1233 } else if (op == UserOperation.BlockPerson) {
1234 let data = wsJsonToRes<BlockPersonResponse>(msg, BlockPersonResponse);
1235 updatePersonBlock(data).match({
1236 some: blocks => this.setState({ personBlocks: blocks }),
1239 } else if (op == UserOperation.BlockCommunity) {
1240 let data = wsJsonToRes<BlockCommunityResponse>(
1242 BlockCommunityResponse
1244 updateCommunityBlock(data).match({
1245 some: blocks => this.setState({ communityBlocks: blocks }),