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);
156 async componentDidMount() {
158 this.state.themeList = await fetchThemeList();
159 this.setState(this.state);
162 componentWillUnmount() {
163 this.subscription.unsubscribe();
166 get documentTitle(): string {
167 return i18n.t("settings");
172 <div class="container">
175 title={this.documentTitle}
176 path={this.context.router.route.match.url}
177 description={Some(this.documentTitle)}
178 image={this.state.saveUserSettingsForm.avatar}
180 <ul class="nav nav-tabs mb-2">
181 <li class="nav-item">
183 class={`nav-link btn ${
184 this.state.currentTab == "settings" && "active"
187 { ctx: this, tab: "settings" },
194 <li class="nav-item">
196 class={`nav-link btn ${
197 this.state.currentTab == "blocks" && "active"
200 { ctx: this, tab: "blocks" },
208 {this.state.currentTab == "settings" && this.userSettings()}
209 {this.state.currentTab == "blocks" && this.blockCards()}
218 <div class="col-12 col-md-6">
219 <div class="card border-secondary mb-3">
220 <div class="card-body">{this.saveUserSettingsHtmlForm()}</div>
223 <div class="col-12 col-md-6">
224 <div class="card border-secondary mb-3">
225 <div class="card-body">{this.changePasswordHtmlForm()}</div>
235 <div class="col-12 col-md-6">
236 <div class="card border-secondary mb-3">
237 <div class="card-body">{this.blockUserCard()}</div>
240 <div class="col-12 col-md-6">
241 <div class="card border-secondary mb-3">
242 <div class="card-body">{this.blockCommunityCard()}</div>
249 changePasswordHtmlForm() {
252 <h5>{i18n.t("change_password")}</h5>
253 <form onSubmit={linkEvent(this, this.handleChangePasswordSubmit)}>
254 <div class="form-group row">
255 <label class="col-sm-5 col-form-label" htmlFor="user-password">
256 {i18n.t("new_password")}
258 <div class="col-sm-7">
263 value={this.state.changePasswordForm.new_password}
264 autoComplete="new-password"
266 onInput={linkEvent(this, this.handleNewPasswordChange)}
270 <div class="form-group row">
272 class="col-sm-5 col-form-label"
273 htmlFor="user-verify-password"
275 {i18n.t("verify_password")}
277 <div class="col-sm-7">
280 id="user-verify-password"
282 value={this.state.changePasswordForm.new_password_verify}
283 autoComplete="new-password"
285 onInput={linkEvent(this, this.handleNewPasswordVerifyChange)}
289 <div class="form-group row">
290 <label class="col-sm-5 col-form-label" htmlFor="user-old-password">
291 {i18n.t("old_password")}
293 <div class="col-sm-7">
296 id="user-old-password"
298 value={this.state.changePasswordForm.old_password}
299 autoComplete="new-password"
301 onInput={linkEvent(this, this.handleOldPasswordChange)}
305 <div class="form-group">
306 <button type="submit" class="btn btn-block btn-secondary mr-4">
307 {this.state.changePasswordLoading ? (
310 capitalizeFirstLetter(i18n.t("save"))
322 {this.blockUserForm()}
323 {this.blockedUsersList()}
331 <h5>{i18n.t("blocked_users")}</h5>
332 <ul class="list-unstyled mb-0">
333 {this.state.personBlocks.map(pb => (
336 <PersonListing person={pb.target} />
338 className="btn btn-sm"
340 { ctx: this, recipientId: pb.target.id },
341 this.handleUnblockPerson
343 data-tippy-content={i18n.t("unblock_user")}
345 <Icon icon="x" classes="icon-inline" />
357 <div class="form-group row">
358 <label class="col-md-4 col-form-label" htmlFor="block-person-filter">
359 {i18n.t("block_user")}
361 <div class="col-md-8">
364 id="block-person-filter"
365 value={this.state.blockPerson.map(p => p.person.id).unwrapOr(0)}
367 <option value="0">—</option>
368 {this.state.blockPerson.match({
369 some: personView => (
370 <option value={personView.person.id}>
371 {personSelectName(personView)}
382 blockCommunityCard() {
385 {this.blockCommunityForm()}
386 {this.blockedCommunitiesList()}
391 blockedCommunitiesList() {
394 <h5>{i18n.t("blocked_communities")}</h5>
395 <ul class="list-unstyled mb-0">
396 {this.state.communityBlocks.map(cb => (
399 <CommunityLink community={cb.community} />
401 className="btn btn-sm"
403 { ctx: this, communityId: cb.community.id },
404 this.handleUnblockCommunity
406 data-tippy-content={i18n.t("unblock_community")}
408 <Icon icon="x" classes="icon-inline" />
418 blockCommunityForm() {
420 <div class="form-group row">
421 <label class="col-md-4 col-form-label" htmlFor="block-community-filter">
422 {i18n.t("block_community")}
424 <div class="col-md-8">
427 id="block-community-filter"
428 value={this.state.blockCommunityId}
430 <option value="0">—</option>
431 {this.state.blockCommunity && (
432 <option value={this.state.blockCommunity.community.id}>
433 {communitySelectName(this.state.blockCommunity)}
442 saveUserSettingsHtmlForm() {
445 <h5>{i18n.t("settings")}</h5>
446 <form onSubmit={linkEvent(this, this.handleSaveSettingsSubmit)}>
447 <div class="form-group row">
448 <label class="col-sm-5 col-form-label" htmlFor="display-name">
449 {i18n.t("display_name")}
451 <div class="col-sm-7">
456 placeholder={i18n.t("optional")}
458 this.state.saveUserSettingsForm.display_name
460 onInput={linkEvent(this, this.handleDisplayNameChange)}
461 pattern="^(?!@)(.+)$"
466 <div class="form-group row">
467 <label class="col-sm-3 col-form-label" htmlFor="user-bio">
470 <div class="col-sm-9">
472 initialContent={this.state.saveUserSettingsForm.bio}
473 onContentChange={this.handleBioChange}
474 maxLength={Some(300)}
477 hideNavigationWarnings
481 <div class="form-group row">
482 <label class="col-sm-3 col-form-label" htmlFor="user-email">
485 <div class="col-sm-9">
490 placeholder={i18n.t("optional")}
491 value={toUndefined(this.state.saveUserSettingsForm.email)}
492 onInput={linkEvent(this, this.handleEmailChange)}
497 <div class="form-group row">
498 <label class="col-sm-5 col-form-label" htmlFor="matrix-user-id">
499 <a href={elementUrl} rel={relTags}>
500 {i18n.t("matrix_user_id")}
503 <div class="col-sm-7">
508 placeholder="@user:example.com"
510 this.state.saveUserSettingsForm.matrix_user_id
512 onInput={linkEvent(this, this.handleMatrixUserIdChange)}
513 pattern="^@[A-Za-z0-9._=-]+:[A-Za-z0-9.-]+\.[A-Za-z]{2,}$"
517 <div class="form-group row">
518 <label class="col-sm-3">{i18n.t("avatar")}</label>
519 <div class="col-sm-9">
521 uploadTitle={i18n.t("upload_avatar")}
522 imageSrc={this.state.saveUserSettingsForm.avatar}
523 onUpload={this.handleAvatarUpload}
524 onRemove={this.handleAvatarRemove}
529 <div class="form-group row">
530 <label class="col-sm-3">{i18n.t("banner")}</label>
531 <div class="col-sm-9">
533 uploadTitle={i18n.t("upload_banner")}
534 imageSrc={this.state.saveUserSettingsForm.banner}
535 onUpload={this.handleBannerUpload}
536 onRemove={this.handleBannerRemove}
540 <div class="form-group row">
541 <label class="col-sm-3" htmlFor="user-language">
544 <div class="col-sm-9">
547 value={toUndefined(this.state.saveUserSettingsForm.lang)}
548 onChange={linkEvent(this, this.handleLangChange)}
549 class="custom-select w-auto"
551 <option disabled aria-hidden="true">
554 <option value="browser">{i18n.t("browser_default")}</option>
555 <option disabled aria-hidden="true">
559 .sort((a, b) => a.code.localeCompare(b.code))
561 <option value={lang.code}>{lang.name}</option>
566 <div class="form-group row">
567 <label class="col-sm-3" htmlFor="user-theme">
570 <div class="col-sm-9">
573 value={toUndefined(this.state.saveUserSettingsForm.theme)}
574 onChange={linkEvent(this, this.handleThemeChange)}
575 class="custom-select w-auto"
577 <option disabled aria-hidden="true">
580 <option value="browser">{i18n.t("browser_default")}</option>
581 {this.state.themeList.map(theme => (
582 <option value={theme}>{theme}</option>
587 <form className="form-group row">
588 <label class="col-sm-3">{i18n.t("type")}</label>
589 <div class="col-sm-9">
592 Object.values(ListingType)[
593 this.state.saveUserSettingsForm.default_listing_type.unwrapOr(
598 showLocal={showLocal(this.isoData)}
600 onChange={this.handleListingTypeChange}
604 <form className="form-group row">
605 <label class="col-sm-3">{i18n.t("sort_type")}</label>
606 <div class="col-sm-9">
609 Object.values(SortType)[
610 this.state.saveUserSettingsForm.default_sort_type.unwrapOr(
615 onChange={this.handleSortTypeChange}
619 {enableNsfw(this.state.siteRes) && (
620 <div class="form-group">
621 <div class="form-check">
623 class="form-check-input"
626 checked={toUndefined(
627 this.state.saveUserSettingsForm.show_nsfw
629 onChange={linkEvent(this, this.handleShowNsfwChange)}
631 <label class="form-check-label" htmlFor="user-show-nsfw">
632 {i18n.t("show_nsfw")}
637 <div class="form-group">
638 <div class="form-check">
640 class="form-check-input"
641 id="user-show-scores"
643 checked={toUndefined(
644 this.state.saveUserSettingsForm.show_scores
646 onChange={linkEvent(this, this.handleShowScoresChange)}
648 <label class="form-check-label" htmlFor="user-show-scores">
649 {i18n.t("show_scores")}
653 <div class="form-group">
654 <div class="form-check">
656 class="form-check-input"
657 id="user-show-avatars"
659 checked={toUndefined(
660 this.state.saveUserSettingsForm.show_avatars
662 onChange={linkEvent(this, this.handleShowAvatarsChange)}
664 <label class="form-check-label" htmlFor="user-show-avatars">
665 {i18n.t("show_avatars")}
669 <div class="form-group">
670 <div class="form-check">
672 class="form-check-input"
673 id="user-bot-account"
675 checked={toUndefined(
676 this.state.saveUserSettingsForm.bot_account
678 onChange={linkEvent(this, this.handleBotAccount)}
680 <label class="form-check-label" htmlFor="user-bot-account">
681 {i18n.t("bot_account")}
685 <div class="form-group">
686 <div class="form-check">
688 class="form-check-input"
689 id="user-show-bot-accounts"
691 checked={toUndefined(
692 this.state.saveUserSettingsForm.show_bot_accounts
694 onChange={linkEvent(this, this.handleShowBotAccounts)}
696 <label class="form-check-label" htmlFor="user-show-bot-accounts">
697 {i18n.t("show_bot_accounts")}
701 <div class="form-group">
702 <div class="form-check">
704 class="form-check-input"
705 id="user-show-read-posts"
707 checked={toUndefined(
708 this.state.saveUserSettingsForm.show_read_posts
710 onChange={linkEvent(this, this.handleReadPosts)}
712 <label class="form-check-label" htmlFor="user-show-read-posts">
713 {i18n.t("show_read_posts")}
717 <div class="form-group">
718 <div class="form-check">
720 class="form-check-input"
721 id="user-show-new-post-notifs"
723 checked={toUndefined(
724 this.state.saveUserSettingsForm.show_new_post_notifs
726 onChange={linkEvent(this, this.handleShowNewPostNotifs)}
729 class="form-check-label"
730 htmlFor="user-show-new-post-notifs"
732 {i18n.t("show_new_post_notifs")}
736 <div class="form-group">
737 <div class="form-check">
739 class="form-check-input"
740 id="user-send-notifications-to-email"
742 disabled={!this.state.saveUserSettingsForm.email}
743 checked={toUndefined(
744 this.state.saveUserSettingsForm.send_notifications_to_email
748 this.handleSendNotificationsToEmailChange
752 class="form-check-label"
753 htmlFor="user-send-notifications-to-email"
755 {i18n.t("send_notifications_to_email")}
759 <div class="form-group">
760 <button type="submit" class="btn btn-block btn-secondary mr-4">
761 {this.state.saveUserSettingsLoading ? (
764 capitalizeFirstLetter(i18n.t("save"))
769 <div class="form-group">
771 class="btn btn-block btn-danger"
774 this.handleDeleteAccountShowConfirmToggle
777 {i18n.t("delete_account")}
779 {this.state.deleteAccountShowConfirm && (
781 <div class="my-2 alert alert-danger" role="alert">
782 {i18n.t("delete_account_confirm")}
786 value={this.state.deleteAccountForm.password}
787 autoComplete="new-password"
791 this.handleDeleteAccountPasswordChange
793 class="form-control my-2"
796 class="btn btn-danger mr-4"
797 disabled={!this.state.deleteAccountForm.password}
798 onClick={linkEvent(this, this.handleDeleteAccount)}
800 {this.state.deleteAccountLoading ? (
803 capitalizeFirstLetter(i18n.t("delete"))
807 class="btn btn-secondary"
810 this.handleDeleteAccountShowConfirmToggle
823 setupBlockPersonChoices() {
825 let selectId: any = document.getElementById("block-person-filter");
827 this.blockPersonChoices = new Choices(selectId, choicesConfig);
828 this.blockPersonChoices.passedElement.element.addEventListener(
831 this.handleBlockPerson(Number(e.detail.choice.value));
835 this.blockPersonChoices.passedElement.element.addEventListener(
837 debounce(async (e: any) => {
839 let persons = (await fetchUsers(e.detail.value)).users;
840 let choices = persons.map(pvs => personToChoice(pvs));
841 this.blockPersonChoices.setChoices(
857 setupBlockCommunityChoices() {
859 let selectId: any = document.getElementById("block-community-filter");
861 this.blockCommunityChoices = new Choices(selectId, choicesConfig);
862 this.blockCommunityChoices.passedElement.element.addEventListener(
865 this.handleBlockCommunity(Number(e.detail.choice.value));
869 this.blockCommunityChoices.passedElement.element.addEventListener(
871 debounce(async (e: any) => {
873 let communities = (await fetchCommunities(e.detail.value))
875 let choices = communities.map(cv => communityToChoice(cv));
876 this.blockCommunityChoices.setChoices(
892 handleBlockPerson(personId: number) {
894 let blockUserForm = new BlockPerson({
897 auth: auth().unwrap(),
899 WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm));
903 handleUnblockPerson(i: { ctx: Settings; recipientId: number }) {
904 let blockUserForm = new BlockPerson({
905 person_id: i.recipientId,
907 auth: auth().unwrap(),
909 WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm));
912 handleBlockCommunity(community_id: number) {
913 if (community_id != 0) {
914 let blockCommunityForm = new BlockCommunity({
917 auth: auth().unwrap(),
919 WebSocketService.Instance.send(
920 wsClient.blockCommunity(blockCommunityForm)
925 handleUnblockCommunity(i: { ctx: Settings; communityId: number }) {
926 let blockCommunityForm = new BlockCommunity({
927 community_id: i.communityId,
929 auth: auth().unwrap(),
931 WebSocketService.Instance.send(wsClient.blockCommunity(blockCommunityForm));
934 handleShowNsfwChange(i: Settings, event: any) {
935 i.state.saveUserSettingsForm.show_nsfw = Some(event.target.checked);
939 handleShowAvatarsChange(i: Settings, event: any) {
940 i.state.saveUserSettingsForm.show_avatars = Some(event.target.checked);
941 UserService.Instance.myUserInfo.match({
943 (mui.local_user_view.local_user.show_avatars = event.target.checked),
949 handleBotAccount(i: Settings, event: any) {
950 i.state.saveUserSettingsForm.bot_account = Some(event.target.checked);
954 handleShowBotAccounts(i: Settings, event: any) {
955 i.state.saveUserSettingsForm.show_bot_accounts = Some(event.target.checked);
959 handleReadPosts(i: Settings, event: any) {
960 i.state.saveUserSettingsForm.show_read_posts = Some(event.target.checked);
964 handleShowNewPostNotifs(i: Settings, event: any) {
965 i.state.saveUserSettingsForm.show_new_post_notifs = Some(
971 handleShowScoresChange(i: Settings, event: any) {
972 i.state.saveUserSettingsForm.show_scores = Some(event.target.checked);
973 UserService.Instance.myUserInfo.match({
975 (mui.local_user_view.local_user.show_scores = event.target.checked),
981 handleSendNotificationsToEmailChange(i: Settings, event: any) {
982 i.state.saveUserSettingsForm.send_notifications_to_email = Some(
988 handleThemeChange(i: Settings, event: any) {
989 i.state.saveUserSettingsForm.theme = Some(event.target.value);
990 setTheme(event.target.value, true);
994 handleLangChange(i: Settings, event: any) {
995 i.state.saveUserSettingsForm.lang = Some(event.target.value);
997 getLanguages(i.state.saveUserSettingsForm.lang.unwrap())[0]
1002 handleSortTypeChange(val: SortType) {
1003 this.state.saveUserSettingsForm.default_sort_type = Some(
1004 Object.keys(SortType).indexOf(val)
1006 this.setState(this.state);
1009 handleListingTypeChange(val: ListingType) {
1010 this.state.saveUserSettingsForm.default_listing_type = Some(
1011 Object.keys(ListingType).indexOf(val)
1013 this.setState(this.state);
1016 handleEmailChange(i: Settings, event: any) {
1017 i.state.saveUserSettingsForm.email = Some(event.target.value);
1018 i.setState(i.state);
1021 handleBioChange(val: string) {
1022 this.state.saveUserSettingsForm.bio = Some(val);
1023 this.setState(this.state);
1026 handleAvatarUpload(url: string) {
1027 this.state.saveUserSettingsForm.avatar = Some(url);
1028 this.setState(this.state);
1031 handleAvatarRemove() {
1032 this.state.saveUserSettingsForm.avatar = Some("");
1033 this.setState(this.state);
1036 handleBannerUpload(url: string) {
1037 this.state.saveUserSettingsForm.banner = Some(url);
1038 this.setState(this.state);
1041 handleBannerRemove() {
1042 this.state.saveUserSettingsForm.banner = Some("");
1043 this.setState(this.state);
1046 handleDisplayNameChange(i: Settings, event: any) {
1047 i.state.saveUserSettingsForm.display_name = Some(event.target.value);
1048 i.setState(i.state);
1051 handleMatrixUserIdChange(i: Settings, event: any) {
1052 i.state.saveUserSettingsForm.matrix_user_id = Some(event.target.value);
1053 i.setState(i.state);
1056 handleNewPasswordChange(i: Settings, event: any) {
1057 i.state.changePasswordForm.new_password = event.target.value;
1058 if (i.state.changePasswordForm.new_password == "") {
1059 i.state.changePasswordForm.new_password = undefined;
1061 i.setState(i.state);
1064 handleNewPasswordVerifyChange(i: Settings, event: any) {
1065 i.state.changePasswordForm.new_password_verify = event.target.value;
1066 if (i.state.changePasswordForm.new_password_verify == "") {
1067 i.state.changePasswordForm.new_password_verify = undefined;
1069 i.setState(i.state);
1072 handleOldPasswordChange(i: Settings, event: any) {
1073 i.state.changePasswordForm.old_password = event.target.value;
1074 if (i.state.changePasswordForm.old_password == "") {
1075 i.state.changePasswordForm.old_password = undefined;
1077 i.setState(i.state);
1080 handleSaveSettingsSubmit(i: Settings, event: any) {
1081 event.preventDefault();
1082 i.state.saveUserSettingsLoading = true;
1083 i.state.saveUserSettingsForm.auth = auth().unwrap();
1084 i.setState(i.state);
1086 WebSocketService.Instance.send(
1087 wsClient.saveUserSettings(i.state.saveUserSettingsForm)
1091 handleChangePasswordSubmit(i: Settings, event: any) {
1092 event.preventDefault();
1093 i.state.changePasswordLoading = true;
1094 i.state.changePasswordForm.auth = auth().unwrap();
1095 i.setState(i.state);
1097 WebSocketService.Instance.send(
1098 wsClient.changePassword(i.state.changePasswordForm)
1102 handleDeleteAccountShowConfirmToggle(i: Settings, event: any) {
1103 event.preventDefault();
1104 i.state.deleteAccountShowConfirm = !i.state.deleteAccountShowConfirm;
1105 i.setState(i.state);
1108 handleDeleteAccountPasswordChange(i: Settings, event: any) {
1109 i.state.deleteAccountForm.password = event.target.value;
1110 i.setState(i.state);
1113 handleDeleteAccount(i: Settings, event: any) {
1114 event.preventDefault();
1115 i.state.deleteAccountLoading = true;
1116 i.state.deleteAccountForm.auth = auth().unwrap();
1117 i.setState(i.state);
1119 WebSocketService.Instance.send(
1120 wsClient.deleteAccount(i.state.deleteAccountForm)
1124 handleSwitchTab(i: { ctx: Settings; tab: string }) {
1125 i.ctx.setState({ currentTab: i.tab });
1127 if (i.ctx.state.currentTab == "blocks") {
1128 i.ctx.setupBlockPersonChoices();
1129 i.ctx.setupBlockCommunityChoices();
1134 UserService.Instance.myUserInfo.match({
1136 let luv = mui.local_user_view;
1137 this.state.saveUserSettingsForm.show_nsfw = Some(
1138 luv.local_user.show_nsfw
1140 this.state.saveUserSettingsForm.theme = Some(
1141 luv.local_user.theme ? luv.local_user.theme : "browser"
1143 this.state.saveUserSettingsForm.default_sort_type = Some(
1144 luv.local_user.default_sort_type
1146 this.state.saveUserSettingsForm.default_listing_type = Some(
1147 luv.local_user.default_listing_type
1149 this.state.saveUserSettingsForm.lang = Some(luv.local_user.lang);
1150 this.state.saveUserSettingsForm.avatar = luv.person.avatar;
1151 this.state.saveUserSettingsForm.banner = luv.person.banner;
1152 this.state.saveUserSettingsForm.display_name = luv.person.display_name;
1153 this.state.saveUserSettingsForm.show_avatars = Some(
1154 luv.local_user.show_avatars
1156 this.state.saveUserSettingsForm.bot_account = Some(
1157 luv.person.bot_account
1159 this.state.saveUserSettingsForm.show_bot_accounts = Some(
1160 luv.local_user.show_bot_accounts
1162 this.state.saveUserSettingsForm.show_scores = Some(
1163 luv.local_user.show_scores
1165 this.state.saveUserSettingsForm.show_read_posts = Some(
1166 luv.local_user.show_read_posts
1168 this.state.saveUserSettingsForm.show_new_post_notifs = Some(
1169 luv.local_user.show_new_post_notifs
1171 this.state.saveUserSettingsForm.email = luv.local_user.email;
1172 this.state.saveUserSettingsForm.bio = luv.person.bio;
1173 this.state.saveUserSettingsForm.send_notifications_to_email = Some(
1174 luv.local_user.send_notifications_to_email
1176 this.state.saveUserSettingsForm.matrix_user_id =
1177 luv.person.matrix_user_id;
1178 this.state.personBlocks = mui.person_blocks;
1179 this.state.communityBlocks = mui.community_blocks;
1185 parseMessage(msg: any) {
1186 let op = wsUserOp(msg);
1190 saveUserSettingsLoading: false,
1191 changePasswordLoading: false,
1192 deleteAccountLoading: false,
1194 toast(i18n.t(msg.error), "danger");
1196 } else if (op == UserOperation.SaveUserSettings) {
1197 let data = wsJsonToRes<LoginResponse>(msg, LoginResponse);
1198 UserService.Instance.login(data);
1199 this.state.saveUserSettingsLoading = false;
1200 this.setState(this.state);
1201 toast(i18n.t("saved"));
1202 window.scrollTo(0, 0);
1203 } else if (op == UserOperation.ChangePassword) {
1204 let data = wsJsonToRes<LoginResponse>(msg, LoginResponse);
1205 UserService.Instance.login(data);
1206 this.state.changePasswordLoading = false;
1207 this.setState(this.state);
1208 window.scrollTo(0, 0);
1209 toast(i18n.t("password_changed"));
1210 } else if (op == UserOperation.DeleteAccount) {
1212 deleteAccountLoading: false,
1213 deleteAccountShowConfirm: false,
1215 UserService.Instance.logout();
1216 window.location.href = "/";
1217 } else if (op == UserOperation.BlockPerson) {
1218 let data = wsJsonToRes<BlockPersonResponse>(msg, BlockPersonResponse);
1219 updatePersonBlock(data).match({
1220 some: blocks => this.setState({ personBlocks: blocks }),
1223 } else if (op == UserOperation.BlockCommunity) {
1224 let data = wsJsonToRes<BlockCommunityResponse>(
1226 BlockCommunityResponse
1228 updateCommunityBlock(data).match({
1229 some: blocks => this.setState({ communityBlocks: blocks }),