-import { None, Option, Some } from "@sniptt/monads";
+import { NoOptionI18nKeys } from "i18next";
import { Component, linkEvent } from "inferno";
import {
- BlockCommunity,
BlockCommunityResponse,
- BlockPerson,
BlockPersonResponse,
- ChangePassword,
CommunityBlockView,
- CommunityView,
- DeleteAccount,
+ DeleteAccountResponse,
GetSiteResponse,
ListingType,
LoginResponse,
PersonBlockView,
- PersonViewSafe,
- SaveUserSettings,
SortType,
- toUndefined,
- UserOperation,
- wsJsonToRes,
- wsUserOp,
} from "lemmy-js-client";
-import { Subscription } from "rxjs";
import { i18n, languages } from "../../i18next";
-import { UserService, WebSocketService } from "../../services";
+import { UserService } from "../../services";
+import { HttpService, RequestState } from "../../services/HttpService";
import {
- auth,
+ Choice,
capitalizeFirstLetter,
- choicesConfig,
- communitySelectName,
communityToChoice,
- debounce,
elementUrl,
+ emDash,
enableNsfw,
fetchCommunities,
fetchThemeList,
fetchUsers,
- getLanguages,
- isBrowser,
- personSelectName,
+ myAuth,
+ myAuthRequired,
personToChoice,
relTags,
setIsoData,
toast,
updateCommunityBlock,
updatePersonBlock,
- wsClient,
- wsSubscribe,
} from "../../utils";
+import { debounce } from "../../utils/helpers/debounce";
import { HtmlTags } from "../common/html-tags";
import { Icon, Spinner } from "../common/icon";
import { ImageUploadForm } from "../common/image-upload-form";
+import { LanguageSelect } from "../common/language-select";
import { ListingTypeSelect } from "../common/listing-type-select";
import { MarkdownTextArea } from "../common/markdown-textarea";
+import { SearchableSelect } from "../common/searchable-select";
import { SortSelect } from "../common/sort-select";
+import Tabs from "../common/tabs";
import { CommunityLink } from "../community/community-link";
import { PersonListing } from "./person-listing";
-var Choices: any;
-if (isBrowser()) {
- Choices = require("choices.js");
-}
-
interface SettingsState {
- saveUserSettingsForm: SaveUserSettings;
- changePasswordForm: ChangePassword;
- deleteAccountForm: DeleteAccount;
+ saveRes: RequestState<LoginResponse>;
+ changePasswordRes: RequestState<LoginResponse>;
+ deleteAccountRes: RequestState<DeleteAccountResponse>;
+ // TODO redo these forms
+ saveUserSettingsForm: {
+ show_nsfw?: boolean;
+ theme?: string;
+ default_sort_type?: SortType;
+ default_listing_type?: ListingType;
+ interface_language?: string;
+ avatar?: string;
+ banner?: string;
+ display_name?: string;
+ email?: string;
+ bio?: string;
+ matrix_user_id?: string;
+ show_avatars?: boolean;
+ show_scores?: boolean;
+ send_notifications_to_email?: boolean;
+ bot_account?: boolean;
+ show_bot_accounts?: boolean;
+ show_read_posts?: boolean;
+ show_new_post_notifs?: boolean;
+ discussion_languages?: number[];
+ generate_totp_2fa?: boolean;
+ };
+ changePasswordForm: {
+ new_password?: string;
+ new_password_verify?: string;
+ old_password?: string;
+ };
+ deleteAccountForm: {
+ password?: string;
+ };
personBlocks: PersonBlockView[];
- blockPerson: Option<PersonViewSafe>;
communityBlocks: CommunityBlockView[];
- blockCommunityId: number;
- blockCommunity?: CommunityView;
currentTab: string;
themeList: string[];
- saveUserSettingsLoading: boolean;
- changePasswordLoading: boolean;
- deleteAccountLoading: boolean;
deleteAccountShowConfirm: boolean;
siteRes: GetSiteResponse;
+ searchCommunityLoading: boolean;
+ searchCommunityOptions: Choice[];
+ searchPersonLoading: boolean;
+ searchPersonOptions: Choice[];
}
+type FilterType = "user" | "community";
+
+const Filter = ({
+ filterType,
+ options,
+ onChange,
+ onSearch,
+ loading,
+}: {
+ filterType: FilterType;
+ options: Choice[];
+ onSearch: (text: string) => void;
+ onChange: (choice: Choice) => void;
+ loading: boolean;
+}) => (
+ <div className="form-group row">
+ <label
+ className="col-md-4 col-form-label"
+ htmlFor={`block-${filterType}-filter`}
+ >
+ {i18n.t(`block_${filterType}` as NoOptionI18nKeys)}
+ </label>
+ <div className="col-md-8">
+ <SearchableSelect
+ id={`block-${filterType}-filter`}
+ options={[
+ { label: emDash, value: "0", disabled: true } as Choice,
+ ].concat(options)}
+ loading={loading}
+ onChange={onChange}
+ onSearch={onSearch}
+ />
+ </div>
+ </div>
+);
+
export class Settings extends Component<any, SettingsState> {
private isoData = setIsoData(this.context);
- private blockPersonChoices: any;
- private blockCommunityChoices: any;
- private subscription: Subscription;
- private emptyState: SettingsState = {
- saveUserSettingsForm: new SaveUserSettings({
- show_nsfw: None,
- show_scores: None,
- show_avatars: None,
- show_read_posts: None,
- show_bot_accounts: None,
- show_new_post_notifs: None,
- default_sort_type: None,
- default_listing_type: None,
- theme: None,
- lang: None,
- avatar: None,
- banner: None,
- display_name: None,
- email: None,
- bio: None,
- matrix_user_id: None,
- send_notifications_to_email: None,
- bot_account: None,
- auth: undefined,
- }),
- changePasswordForm: new ChangePassword({
- new_password: undefined,
- new_password_verify: undefined,
- old_password: undefined,
- auth: undefined,
- }),
- saveUserSettingsLoading: false,
- changePasswordLoading: false,
- deleteAccountLoading: false,
+ state: SettingsState = {
+ saveRes: { state: "empty" },
+ deleteAccountRes: { state: "empty" },
+ changePasswordRes: { state: "empty" },
+ saveUserSettingsForm: {},
+ changePasswordForm: {},
deleteAccountShowConfirm: false,
- deleteAccountForm: new DeleteAccount({
- password: undefined,
- auth: undefined,
- }),
+ deleteAccountForm: {},
personBlocks: [],
- blockPerson: None,
communityBlocks: [],
- blockCommunityId: 0,
currentTab: "settings",
siteRes: this.isoData.site_res,
themeList: [],
+ searchCommunityLoading: false,
+ searchCommunityOptions: [],
+ searchPersonLoading: false,
+ searchPersonOptions: [],
};
constructor(props: any, context: any) {
super(props, context);
- this.state = this.emptyState;
this.handleSortTypeChange = this.handleSortTypeChange.bind(this);
this.handleListingTypeChange = this.handleListingTypeChange.bind(this);
this.handleBioChange = this.handleBioChange.bind(this);
+ this.handleDiscussionLanguageChange =
+ this.handleDiscussionLanguageChange.bind(this);
this.handleAvatarUpload = this.handleAvatarUpload.bind(this);
this.handleAvatarRemove = this.handleAvatarRemove.bind(this);
this.handleBannerUpload = this.handleBannerUpload.bind(this);
this.handleBannerRemove = this.handleBannerRemove.bind(this);
-
- this.parseMessage = this.parseMessage.bind(this);
- this.subscription = wsSubscribe(this.parseMessage);
-
- this.setUserInfo();
+ this.userSettings = this.userSettings.bind(this);
+ this.blockCards = this.blockCards.bind(this);
+
+ this.handleBlockPerson = this.handleBlockPerson.bind(this);
+ this.handleBlockCommunity = this.handleBlockCommunity.bind(this);
+
+ const mui = UserService.Instance.myUserInfo;
+ if (mui) {
+ const {
+ local_user: {
+ show_nsfw,
+ theme,
+ default_sort_type,
+ default_listing_type,
+ interface_language,
+ show_avatars,
+ show_bot_accounts,
+ show_scores,
+ show_read_posts,
+ show_new_post_notifs,
+ send_notifications_to_email,
+ email,
+ },
+ person: {
+ avatar,
+ banner,
+ display_name,
+ bot_account,
+ bio,
+ matrix_user_id,
+ },
+ } = mui.local_user_view;
+
+ this.state = {
+ ...this.state,
+ personBlocks: mui.person_blocks,
+ communityBlocks: mui.community_blocks,
+ saveUserSettingsForm: {
+ ...this.state.saveUserSettingsForm,
+ show_nsfw,
+ theme: theme ?? "browser",
+ default_sort_type,
+ default_listing_type,
+ interface_language,
+ discussion_languages: mui.discussion_languages,
+ avatar,
+ banner,
+ display_name,
+ show_avatars,
+ bot_account,
+ show_bot_accounts,
+ show_scores,
+ show_read_posts,
+ show_new_post_notifs,
+ email,
+ bio,
+ send_notifications_to_email,
+ matrix_user_id,
+ },
+ };
+ }
}
async componentDidMount() {
setupTippy();
- this.state.themeList = await fetchThemeList();
- this.setState(this.state);
- }
-
- componentWillUnmount() {
- this.subscription.unsubscribe();
+ this.setState({ themeList: await fetchThemeList() });
}
get documentTitle(): string {
render() {
return (
- <div class="container">
- <>
- <HtmlTags
- title={this.documentTitle}
- path={this.context.router.route.match.url}
- description={Some(this.documentTitle)}
- image={this.state.saveUserSettingsForm.avatar}
- />
- <ul class="nav nav-tabs mb-2">
- <li class="nav-item">
- <button
- class={`nav-link btn ${
- this.state.currentTab == "settings" && "active"
- }`}
- onClick={linkEvent(
- { ctx: this, tab: "settings" },
- this.handleSwitchTab
- )}
- >
- {i18n.t("settings")}
- </button>
- </li>
- <li class="nav-item">
- <button
- class={`nav-link btn ${
- this.state.currentTab == "blocks" && "active"
- }`}
- onClick={linkEvent(
- { ctx: this, tab: "blocks" },
- this.handleSwitchTab
- )}
- >
- {i18n.t("blocks")}
- </button>
- </li>
- </ul>
- {this.state.currentTab == "settings" && this.userSettings()}
- {this.state.currentTab == "blocks" && this.blockCards()}
- </>
+ <div className="container-lg">
+ <HtmlTags
+ title={this.documentTitle}
+ path={this.context.router.route.match.url}
+ description={this.documentTitle}
+ image={this.state.saveUserSettingsForm.avatar}
+ />
+ <Tabs
+ tabs={[
+ {
+ key: "settings",
+ label: i18n.t("settings"),
+ getNode: this.userSettings,
+ },
+ {
+ key: "blocks",
+ label: i18n.t("blocks"),
+ getNode: this.blockCards,
+ },
+ ]}
+ />
</div>
);
}
userSettings() {
return (
- <div class="row">
- <div class="col-12 col-md-6">
- <div class="card border-secondary mb-3">
- <div class="card-body">{this.saveUserSettingsHtmlForm()}</div>
+ <div className="row">
+ <div className="col-12 col-md-6">
+ <div className="card border-secondary mb-3">
+ <div className="card-body">{this.saveUserSettingsHtmlForm()}</div>
</div>
</div>
- <div class="col-12 col-md-6">
- <div class="card border-secondary mb-3">
- <div class="card-body">{this.changePasswordHtmlForm()}</div>
+ <div className="col-12 col-md-6">
+ <div className="card border-secondary mb-3">
+ <div className="card-body">{this.changePasswordHtmlForm()}</div>
</div>
</div>
</div>
blockCards() {
return (
- <div class="row">
- <div class="col-12 col-md-6">
- <div class="card border-secondary mb-3">
- <div class="card-body">{this.blockUserCard()}</div>
+ <div className="row">
+ <div className="col-12 col-md-6">
+ <div className="card border-secondary mb-3">
+ <div className="card-body">{this.blockUserCard()}</div>
</div>
</div>
- <div class="col-12 col-md-6">
- <div class="card border-secondary mb-3">
- <div class="card-body">{this.blockCommunityCard()}</div>
+ <div className="col-12 col-md-6">
+ <div className="card border-secondary mb-3">
+ <div className="card-body">{this.blockCommunityCard()}</div>
</div>
</div>
</div>
<>
<h5>{i18n.t("change_password")}</h5>
<form onSubmit={linkEvent(this, this.handleChangePasswordSubmit)}>
- <div class="form-group row">
- <label class="col-sm-5 col-form-label" htmlFor="user-password">
+ <div className="form-group row">
+ <label className="col-sm-5 col-form-label" htmlFor="user-password">
{i18n.t("new_password")}
</label>
- <div class="col-sm-7">
+ <div className="col-sm-7">
<input
type="password"
id="user-password"
- class="form-control"
+ className="form-control"
value={this.state.changePasswordForm.new_password}
autoComplete="new-password"
maxLength={60}
/>
</div>
</div>
- <div class="form-group row">
+ <div className="form-group row">
<label
- class="col-sm-5 col-form-label"
+ className="col-sm-5 col-form-label"
htmlFor="user-verify-password"
>
{i18n.t("verify_password")}
</label>
- <div class="col-sm-7">
+ <div className="col-sm-7">
<input
type="password"
id="user-verify-password"
- class="form-control"
+ className="form-control"
value={this.state.changePasswordForm.new_password_verify}
autoComplete="new-password"
maxLength={60}
/>
</div>
</div>
- <div class="form-group row">
- <label class="col-sm-5 col-form-label" htmlFor="user-old-password">
+ <div className="form-group row">
+ <label
+ className="col-sm-5 col-form-label"
+ htmlFor="user-old-password"
+ >
{i18n.t("old_password")}
</label>
- <div class="col-sm-7">
+ <div className="col-sm-7">
<input
type="password"
id="user-old-password"
- class="form-control"
+ className="form-control"
value={this.state.changePasswordForm.old_password}
autoComplete="new-password"
maxLength={60}
/>
</div>
</div>
- <div class="form-group">
- <button type="submit" class="btn btn-block btn-secondary mr-4">
- {this.state.changePasswordLoading ? (
+ <div className="form-group">
+ <button type="submit" className="btn btn-block btn-secondary mr-4">
+ {this.state.changePasswordRes.state === "loading" ? (
<Spinner />
) : (
capitalizeFirstLetter(i18n.t("save"))
}
blockUserCard() {
+ const { searchPersonLoading, searchPersonOptions } = this.state;
+
return (
<div>
- {this.blockUserForm()}
+ <Filter
+ filterType="user"
+ loading={searchPersonLoading}
+ onChange={this.handleBlockPerson}
+ onSearch={this.handlePersonSearch}
+ options={searchPersonOptions}
+ />
{this.blockedUsersList()}
</div>
);
return (
<>
<h5>{i18n.t("blocked_users")}</h5>
- <ul class="list-unstyled mb-0">
+ <ul className="list-unstyled mb-0">
{this.state.personBlocks.map(pb => (
- <li>
+ <li key={pb.target.id}>
<span>
<PersonListing person={pb.target} />
<button
);
}
- blockUserForm() {
- return (
- <div class="form-group row">
- <label class="col-md-4 col-form-label" htmlFor="block-person-filter">
- {i18n.t("block_user")}
- </label>
- <div class="col-md-8">
- <select
- class="form-control"
- id="block-person-filter"
- value={this.state.blockPerson.map(p => p.person.id).unwrapOr(0)}
- >
- <option value="0">—</option>
- {this.state.blockPerson.match({
- some: personView => (
- <option value={personView.person.id}>
- {personSelectName(personView)}
- </option>
- ),
- none: <></>,
- })}
- </select>
- </div>
- </div>
- );
- }
-
blockCommunityCard() {
+ const { searchCommunityLoading, searchCommunityOptions } = this.state;
+
return (
<div>
- {this.blockCommunityForm()}
+ <Filter
+ filterType="community"
+ loading={searchCommunityLoading}
+ onChange={this.handleBlockCommunity}
+ onSearch={this.handleCommunitySearch}
+ options={searchCommunityOptions}
+ />
{this.blockedCommunitiesList()}
</div>
);
return (
<>
<h5>{i18n.t("blocked_communities")}</h5>
- <ul class="list-unstyled mb-0">
+ <ul className="list-unstyled mb-0">
{this.state.communityBlocks.map(cb => (
- <li>
+ <li key={cb.community.id}>
<span>
<CommunityLink community={cb.community} />
<button
);
}
- blockCommunityForm() {
- return (
- <div class="form-group row">
- <label class="col-md-4 col-form-label" htmlFor="block-community-filter">
- {i18n.t("block_community")}
- </label>
- <div class="col-md-8">
- <select
- class="form-control"
- id="block-community-filter"
- value={this.state.blockCommunityId}
- >
- <option value="0">—</option>
- {this.state.blockCommunity && (
- <option value={this.state.blockCommunity.community.id}>
- {communitySelectName(this.state.blockCommunity)}
- </option>
- )}
- </select>
- </div>
- </div>
- );
- }
-
saveUserSettingsHtmlForm() {
+ const selectedLangs = this.state.saveUserSettingsForm.discussion_languages;
+
return (
<>
<h5>{i18n.t("settings")}</h5>
<form onSubmit={linkEvent(this, this.handleSaveSettingsSubmit)}>
- <div class="form-group row">
- <label class="col-sm-5 col-form-label" htmlFor="display-name">
+ <div className="form-group row">
+ <label className="col-sm-5 col-form-label" htmlFor="display-name">
{i18n.t("display_name")}
</label>
- <div class="col-sm-7">
+ <div className="col-sm-7">
<input
id="display-name"
type="text"
- class="form-control"
+ className="form-control"
placeholder={i18n.t("optional")}
- value={toUndefined(
- this.state.saveUserSettingsForm.display_name
- )}
+ value={this.state.saveUserSettingsForm.display_name}
onInput={linkEvent(this, this.handleDisplayNameChange)}
pattern="^(?!@)(.+)$"
minLength={3}
/>
</div>
</div>
- <div class="form-group row">
- <label class="col-sm-3 col-form-label" htmlFor="user-bio">
+ <div className="form-group row">
+ <label className="col-sm-3 col-form-label" htmlFor="user-bio">
{i18n.t("bio")}
</label>
- <div class="col-sm-9">
+ <div className="col-sm-9">
<MarkdownTextArea
initialContent={this.state.saveUserSettingsForm.bio}
onContentChange={this.handleBioChange}
- maxLength={Some(300)}
- placeholder={None}
- buttonTitle={None}
+ maxLength={300}
hideNavigationWarnings
+ allLanguages={this.state.siteRes.all_languages}
+ siteLanguages={this.state.siteRes.discussion_languages}
/>
</div>
</div>
- <div class="form-group row">
- <label class="col-sm-3 col-form-label" htmlFor="user-email">
+ <div className="form-group row">
+ <label className="col-sm-3 col-form-label" htmlFor="user-email">
{i18n.t("email")}
</label>
- <div class="col-sm-9">
+ <div className="col-sm-9">
<input
type="email"
id="user-email"
- class="form-control"
+ className="form-control"
placeholder={i18n.t("optional")}
- value={toUndefined(this.state.saveUserSettingsForm.email)}
+ value={this.state.saveUserSettingsForm.email}
onInput={linkEvent(this, this.handleEmailChange)}
minLength={3}
/>
</div>
</div>
- <div class="form-group row">
- <label class="col-sm-5 col-form-label" htmlFor="matrix-user-id">
+ <div className="form-group row">
+ <label className="col-sm-5 col-form-label" htmlFor="matrix-user-id">
<a href={elementUrl} rel={relTags}>
{i18n.t("matrix_user_id")}
</a>
</label>
- <div class="col-sm-7">
+ <div className="col-sm-7">
<input
id="matrix-user-id"
type="text"
- class="form-control"
+ className="form-control"
placeholder="@user:example.com"
- value={toUndefined(
- this.state.saveUserSettingsForm.matrix_user_id
- )}
+ value={this.state.saveUserSettingsForm.matrix_user_id}
onInput={linkEvent(this, this.handleMatrixUserIdChange)}
pattern="^@[A-Za-z0-9._=-]+:[A-Za-z0-9.-]+\.[A-Za-z]{2,}$"
/>
</div>
</div>
- <div class="form-group row">
- <label class="col-sm-3">{i18n.t("avatar")}</label>
- <div class="col-sm-9">
+ <div className="form-group row">
+ <label className="col-sm-3">{i18n.t("avatar")}</label>
+ <div className="col-sm-9">
<ImageUploadForm
uploadTitle={i18n.t("upload_avatar")}
imageSrc={this.state.saveUserSettingsForm.avatar}
/>
</div>
</div>
- <div class="form-group row">
- <label class="col-sm-3">{i18n.t("banner")}</label>
- <div class="col-sm-9">
+ <div className="form-group row">
+ <label className="col-sm-3">{i18n.t("banner")}</label>
+ <div className="col-sm-9">
<ImageUploadForm
uploadTitle={i18n.t("upload_banner")}
imageSrc={this.state.saveUserSettingsForm.banner}
/>
</div>
</div>
- <div class="form-group row">
- <label class="col-sm-3" htmlFor="user-language">
- {i18n.t("language")}
+ <div className="form-group row">
+ <label className="col-sm-3" htmlFor="user-language">
+ {i18n.t("interface_language")}
</label>
- <div class="col-sm-9">
+ <div className="col-sm-9">
<select
id="user-language"
- value={toUndefined(this.state.saveUserSettingsForm.lang)}
- onChange={linkEvent(this, this.handleLangChange)}
- class="custom-select w-auto"
+ value={this.state.saveUserSettingsForm.interface_language}
+ onChange={linkEvent(this, this.handleInterfaceLangChange)}
+ className="custom-select w-auto"
>
<option disabled aria-hidden="true">
- {i18n.t("language")}
+ {i18n.t("interface_language")}
</option>
<option value="browser">{i18n.t("browser_default")}</option>
<option disabled aria-hidden="true">
{languages
.sort((a, b) => a.code.localeCompare(b.code))
.map(lang => (
- <option value={lang.code}>{lang.name}</option>
+ <option key={lang.code} value={lang.code}>
+ {lang.name}
+ </option>
))}
</select>
</div>
</div>
- <div class="form-group row">
- <label class="col-sm-3" htmlFor="user-theme">
+ <LanguageSelect
+ allLanguages={this.state.siteRes.all_languages}
+ siteLanguages={this.state.siteRes.discussion_languages}
+ selectedLanguageIds={selectedLangs}
+ multiple={true}
+ showLanguageWarning={true}
+ showSite
+ onChange={this.handleDiscussionLanguageChange}
+ />
+ <div className="form-group row">
+ <label className="col-sm-3" htmlFor="user-theme">
{i18n.t("theme")}
</label>
- <div class="col-sm-9">
+ <div className="col-sm-9">
<select
id="user-theme"
- value={toUndefined(this.state.saveUserSettingsForm.theme)}
+ value={this.state.saveUserSettingsForm.theme}
onChange={linkEvent(this, this.handleThemeChange)}
- class="custom-select w-auto"
+ className="custom-select w-auto"
>
<option disabled aria-hidden="true">
{i18n.t("theme")}
</option>
<option value="browser">{i18n.t("browser_default")}</option>
{this.state.themeList.map(theme => (
- <option value={theme}>{theme}</option>
+ <option key={theme} value={theme}>
+ {theme}
+ </option>
))}
</select>
</div>
</div>
<form className="form-group row">
- <label class="col-sm-3">{i18n.t("type")}</label>
- <div class="col-sm-9">
+ <label className="col-sm-3">{i18n.t("type")}</label>
+ <div className="col-sm-9">
<ListingTypeSelect
type_={
- Object.values(ListingType)[
- this.state.saveUserSettingsForm.default_listing_type.unwrapOr(
- 1
- )
- ]
+ this.state.saveUserSettingsForm.default_listing_type ??
+ "Local"
}
showLocal={showLocal(this.isoData)}
showSubscribed
</div>
</form>
<form className="form-group row">
- <label class="col-sm-3">{i18n.t("sort_type")}</label>
- <div class="col-sm-9">
+ <label className="col-sm-3">{i18n.t("sort_type")}</label>
+ <div className="col-sm-9">
<SortSelect
sort={
- Object.values(SortType)[
- this.state.saveUserSettingsForm.default_sort_type.unwrapOr(
- 0
- )
- ]
+ this.state.saveUserSettingsForm.default_sort_type ?? "Active"
}
onChange={this.handleSortTypeChange}
/>
</div>
</form>
{enableNsfw(this.state.siteRes) && (
- <div class="form-group">
- <div class="form-check">
+ <div className="form-group">
+ <div className="form-check">
<input
- class="form-check-input"
+ className="form-check-input"
id="user-show-nsfw"
type="checkbox"
- checked={toUndefined(
- this.state.saveUserSettingsForm.show_nsfw
- )}
+ checked={this.state.saveUserSettingsForm.show_nsfw}
onChange={linkEvent(this, this.handleShowNsfwChange)}
/>
- <label class="form-check-label" htmlFor="user-show-nsfw">
+ <label className="form-check-label" htmlFor="user-show-nsfw">
{i18n.t("show_nsfw")}
</label>
</div>
</div>
)}
- <div class="form-group">
- <div class="form-check">
+ <div className="form-group">
+ <div className="form-check">
<input
- class="form-check-input"
+ className="form-check-input"
id="user-show-scores"
type="checkbox"
- checked={toUndefined(
- this.state.saveUserSettingsForm.show_scores
- )}
+ checked={this.state.saveUserSettingsForm.show_scores}
onChange={linkEvent(this, this.handleShowScoresChange)}
/>
- <label class="form-check-label" htmlFor="user-show-scores">
+ <label className="form-check-label" htmlFor="user-show-scores">
{i18n.t("show_scores")}
</label>
</div>
</div>
- <div class="form-group">
- <div class="form-check">
+ <div className="form-group">
+ <div className="form-check">
<input
- class="form-check-input"
+ className="form-check-input"
id="user-show-avatars"
type="checkbox"
- checked={toUndefined(
- this.state.saveUserSettingsForm.show_avatars
- )}
+ checked={this.state.saveUserSettingsForm.show_avatars}
onChange={linkEvent(this, this.handleShowAvatarsChange)}
/>
- <label class="form-check-label" htmlFor="user-show-avatars">
+ <label className="form-check-label" htmlFor="user-show-avatars">
{i18n.t("show_avatars")}
</label>
</div>
</div>
- <div class="form-group">
- <div class="form-check">
+ <div className="form-group">
+ <div className="form-check">
<input
- class="form-check-input"
+ className="form-check-input"
id="user-bot-account"
type="checkbox"
- checked={toUndefined(
- this.state.saveUserSettingsForm.bot_account
- )}
+ checked={this.state.saveUserSettingsForm.bot_account}
onChange={linkEvent(this, this.handleBotAccount)}
/>
- <label class="form-check-label" htmlFor="user-bot-account">
+ <label className="form-check-label" htmlFor="user-bot-account">
{i18n.t("bot_account")}
</label>
</div>
</div>
- <div class="form-group">
- <div class="form-check">
+ <div className="form-group">
+ <div className="form-check">
<input
- class="form-check-input"
+ className="form-check-input"
id="user-show-bot-accounts"
type="checkbox"
- checked={toUndefined(
- this.state.saveUserSettingsForm.show_bot_accounts
- )}
+ checked={this.state.saveUserSettingsForm.show_bot_accounts}
onChange={linkEvent(this, this.handleShowBotAccounts)}
/>
- <label class="form-check-label" htmlFor="user-show-bot-accounts">
+ <label
+ className="form-check-label"
+ htmlFor="user-show-bot-accounts"
+ >
{i18n.t("show_bot_accounts")}
</label>
</div>
</div>
- <div class="form-group">
- <div class="form-check">
+ <div className="form-group">
+ <div className="form-check">
<input
- class="form-check-input"
+ className="form-check-input"
id="user-show-read-posts"
type="checkbox"
- checked={toUndefined(
- this.state.saveUserSettingsForm.show_read_posts
- )}
+ checked={this.state.saveUserSettingsForm.show_read_posts}
onChange={linkEvent(this, this.handleReadPosts)}
/>
- <label class="form-check-label" htmlFor="user-show-read-posts">
+ <label
+ className="form-check-label"
+ htmlFor="user-show-read-posts"
+ >
{i18n.t("show_read_posts")}
</label>
</div>
</div>
- <div class="form-group">
- <div class="form-check">
+ <div className="form-group">
+ <div className="form-check">
<input
- class="form-check-input"
+ className="form-check-input"
id="user-show-new-post-notifs"
type="checkbox"
- checked={toUndefined(
- this.state.saveUserSettingsForm.show_new_post_notifs
- )}
+ checked={this.state.saveUserSettingsForm.show_new_post_notifs}
onChange={linkEvent(this, this.handleShowNewPostNotifs)}
/>
<label
- class="form-check-label"
+ className="form-check-label"
htmlFor="user-show-new-post-notifs"
>
{i18n.t("show_new_post_notifs")}
</label>
</div>
</div>
- <div class="form-group">
- <div class="form-check">
+ <div className="form-group">
+ <div className="form-check">
<input
- class="form-check-input"
+ className="form-check-input"
id="user-send-notifications-to-email"
type="checkbox"
disabled={!this.state.saveUserSettingsForm.email}
- checked={toUndefined(
+ checked={
this.state.saveUserSettingsForm.send_notifications_to_email
- )}
+ }
onChange={linkEvent(
this,
this.handleSendNotificationsToEmailChange
)}
/>
<label
- class="form-check-label"
+ className="form-check-label"
htmlFor="user-send-notifications-to-email"
>
{i18n.t("send_notifications_to_email")}
</label>
</div>
</div>
- <div class="form-group">
- <button type="submit" class="btn btn-block btn-secondary mr-4">
- {this.state.saveUserSettingsLoading ? (
+ {this.totpSection()}
+ <div className="form-group">
+ <button type="submit" className="btn btn-block btn-secondary mr-4">
+ {this.state.saveRes.state === "loading" ? (
<Spinner />
) : (
capitalizeFirstLetter(i18n.t("save"))
</button>
</div>
<hr />
- <div class="form-group">
+ <div className="form-group">
<button
- class="btn btn-block btn-danger"
+ className="btn btn-block btn-danger"
onClick={linkEvent(
this,
this.handleDeleteAccountShowConfirmToggle
</button>
{this.state.deleteAccountShowConfirm && (
<>
- <div class="my-2 alert alert-danger" role="alert">
+ <div className="my-2 alert alert-danger" role="alert">
{i18n.t("delete_account_confirm")}
</div>
<input
this,
this.handleDeleteAccountPasswordChange
)}
- class="form-control my-2"
+ className="form-control my-2"
/>
<button
- class="btn btn-danger mr-4"
+ className="btn btn-danger mr-4"
disabled={!this.state.deleteAccountForm.password}
onClick={linkEvent(this, this.handleDeleteAccount)}
>
- {this.state.deleteAccountLoading ? (
+ {this.state.deleteAccountRes.state === "loading" ? (
<Spinner />
) : (
capitalizeFirstLetter(i18n.t("delete"))
)}
</button>
<button
- class="btn btn-secondary"
+ className="btn btn-secondary"
onClick={linkEvent(
this,
this.handleDeleteAccountShowConfirmToggle
);
}
- setupBlockPersonChoices() {
- if (isBrowser()) {
- let selectId: any = document.getElementById("block-person-filter");
- if (selectId) {
- this.blockPersonChoices = new Choices(selectId, choicesConfig);
- this.blockPersonChoices.passedElement.element.addEventListener(
- "choice",
- (e: any) => {
- this.handleBlockPerson(Number(e.detail.choice.value));
- },
- false
- );
- this.blockPersonChoices.passedElement.element.addEventListener(
- "search",
- debounce(async (e: any) => {
- try {
- let persons = (await fetchUsers(e.detail.value)).users;
- let choices = persons.map(pvs => personToChoice(pvs));
- this.blockPersonChoices.setChoices(
- choices,
- "value",
- "label",
- true
- );
- } catch (err) {
- console.error(err);
- }
- }),
- false
- );
- }
- }
+ totpSection() {
+ const totpUrl =
+ UserService.Instance.myUserInfo?.local_user_view.local_user.totp_2fa_url;
+
+ return (
+ <>
+ {!totpUrl && (
+ <div className="form-group">
+ <div className="form-check">
+ <input
+ className="form-check-input"
+ id="user-generate-totp"
+ type="checkbox"
+ checked={this.state.saveUserSettingsForm.generate_totp_2fa}
+ onChange={linkEvent(this, this.handleGenerateTotp)}
+ />
+ <label className="form-check-label" htmlFor="user-generate-totp">
+ {i18n.t("set_up_two_factor")}
+ </label>
+ </div>
+ </div>
+ )}
+
+ {totpUrl && (
+ <>
+ <div>
+ <a className="btn btn-secondary mb-2" href={totpUrl}>
+ {i18n.t("two_factor_link")}
+ </a>
+ </div>
+ <div className="form-group">
+ <div className="form-check">
+ <input
+ className="form-check-input"
+ id="user-remove-totp"
+ type="checkbox"
+ checked={
+ this.state.saveUserSettingsForm.generate_totp_2fa == false
+ }
+ onChange={linkEvent(this, this.handleRemoveTotp)}
+ />
+ <label className="form-check-label" htmlFor="user-remove-totp">
+ {i18n.t("remove_two_factor")}
+ </label>
+ </div>
+ </div>
+ </>
+ )}
+ </>
+ );
}
- setupBlockCommunityChoices() {
- if (isBrowser()) {
- let selectId: any = document.getElementById("block-community-filter");
- if (selectId) {
- this.blockCommunityChoices = new Choices(selectId, choicesConfig);
- this.blockCommunityChoices.passedElement.element.addEventListener(
- "choice",
- (e: any) => {
- this.handleBlockCommunity(Number(e.detail.choice.value));
- },
- false
- );
- this.blockCommunityChoices.passedElement.element.addEventListener(
- "search",
- debounce(async (e: any) => {
- try {
- let communities = (await fetchCommunities(e.detail.value))
- .communities;
- let choices = communities.map(cv => communityToChoice(cv));
- this.blockCommunityChoices.setChoices(
- choices,
- "value",
- "label",
- true
- );
- } catch (err) {
- console.log(err);
- }
- }),
- false
- );
- }
+ handlePersonSearch = debounce(async (text: string) => {
+ this.setState({ searchPersonLoading: true });
+
+ const searchPersonOptions: Choice[] = [];
+
+ if (text.length > 0) {
+ searchPersonOptions.push(...(await fetchUsers(text)).map(personToChoice));
}
- }
- handleBlockPerson(personId: number) {
- if (personId != 0) {
- let blockUserForm = new BlockPerson({
- person_id: personId,
+ this.setState({
+ searchPersonLoading: false,
+ searchPersonOptions,
+ });
+ });
+
+ handleCommunitySearch = debounce(async (text: string) => {
+ this.setState({ searchCommunityLoading: true });
+
+ const searchCommunityOptions: Choice[] = [];
+
+ if (text.length > 0) {
+ searchCommunityOptions.push(
+ ...(await fetchCommunities(text)).map(communityToChoice)
+ );
+ }
+
+ this.setState({
+ searchCommunityLoading: false,
+ searchCommunityOptions,
+ });
+ });
+
+ async handleBlockPerson({ value }: Choice) {
+ if (value !== "0") {
+ const res = await HttpService.client.blockPerson({
+ person_id: Number(value),
block: true,
- auth: auth().unwrap(),
+ auth: myAuthRequired(),
});
- WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm));
+ this.personBlock(res);
}
}
- handleUnblockPerson(i: { ctx: Settings; recipientId: number }) {
- let blockUserForm = new BlockPerson({
- person_id: i.recipientId,
+ async handleUnblockPerson({
+ ctx,
+ recipientId,
+ }: {
+ ctx: Settings;
+ recipientId: number;
+ }) {
+ const res = await HttpService.client.blockPerson({
+ person_id: recipientId,
block: false,
- auth: auth().unwrap(),
+ auth: myAuthRequired(),
});
- WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm));
+ ctx.personBlock(res);
}
- handleBlockCommunity(community_id: number) {
- if (community_id != 0) {
- let blockCommunityForm = new BlockCommunity({
- community_id,
+ async handleBlockCommunity({ value }: Choice) {
+ if (value !== "0") {
+ const res = await HttpService.client.blockCommunity({
+ community_id: Number(value),
block: true,
- auth: auth().unwrap(),
+ auth: myAuthRequired(),
});
- WebSocketService.Instance.send(
- wsClient.blockCommunity(blockCommunityForm)
- );
+ this.communityBlock(res);
}
}
- handleUnblockCommunity(i: { ctx: Settings; communityId: number }) {
- let blockCommunityForm = new BlockCommunity({
- community_id: i.communityId,
- block: false,
- auth: auth().unwrap(),
- });
- WebSocketService.Instance.send(wsClient.blockCommunity(blockCommunityForm));
+ async handleUnblockCommunity(i: { ctx: Settings; communityId: number }) {
+ const auth = myAuth();
+ if (auth) {
+ const res = await HttpService.client.blockCommunity({
+ community_id: i.communityId,
+ block: false,
+ auth: myAuthRequired(),
+ });
+ i.ctx.communityBlock(res);
+ }
}
handleShowNsfwChange(i: Settings, event: any) {
- i.state.saveUserSettingsForm.show_nsfw = Some(event.target.checked);
- i.setState(i.state);
+ i.setState(
+ s => ((s.saveUserSettingsForm.show_nsfw = event.target.checked), s)
+ );
}
handleShowAvatarsChange(i: Settings, event: any) {
- i.state.saveUserSettingsForm.show_avatars = Some(event.target.checked);
- UserService.Instance.myUserInfo.match({
- some: mui =>
- (mui.local_user_view.local_user.show_avatars = event.target.checked),
- none: void 0,
- });
- i.setState(i.state);
+ const mui = UserService.Instance.myUserInfo;
+ if (mui) {
+ mui.local_user_view.local_user.show_avatars = event.target.checked;
+ }
+ i.setState(
+ s => ((s.saveUserSettingsForm.show_avatars = event.target.checked), s)
+ );
}
handleBotAccount(i: Settings, event: any) {
- i.state.saveUserSettingsForm.bot_account = Some(event.target.checked);
- i.setState(i.state);
+ i.setState(
+ s => ((s.saveUserSettingsForm.bot_account = event.target.checked), s)
+ );
}
handleShowBotAccounts(i: Settings, event: any) {
- i.state.saveUserSettingsForm.show_bot_accounts = Some(event.target.checked);
- i.setState(i.state);
+ i.setState(
+ s => (
+ (s.saveUserSettingsForm.show_bot_accounts = event.target.checked), s
+ )
+ );
}
handleReadPosts(i: Settings, event: any) {
- i.state.saveUserSettingsForm.show_read_posts = Some(event.target.checked);
- i.setState(i.state);
+ i.setState(
+ s => ((s.saveUserSettingsForm.show_read_posts = event.target.checked), s)
+ );
}
handleShowNewPostNotifs(i: Settings, event: any) {
- i.state.saveUserSettingsForm.show_new_post_notifs = Some(
- event.target.checked
+ i.setState(
+ s => (
+ (s.saveUserSettingsForm.show_new_post_notifs = event.target.checked), s
+ )
);
- i.setState(i.state);
}
handleShowScoresChange(i: Settings, event: any) {
- i.state.saveUserSettingsForm.show_scores = Some(event.target.checked);
- UserService.Instance.myUserInfo.match({
- some: mui =>
- (mui.local_user_view.local_user.show_scores = event.target.checked),
- none: void 0,
- });
- i.setState(i.state);
+ const mui = UserService.Instance.myUserInfo;
+ if (mui) {
+ mui.local_user_view.local_user.show_scores = event.target.checked;
+ }
+ i.setState(
+ s => ((s.saveUserSettingsForm.show_scores = event.target.checked), s)
+ );
+ }
+
+ handleGenerateTotp(i: Settings, event: any) {
+ // Coerce false to undefined here, so it won't generate it.
+ const checked: boolean | undefined = event.target.checked || undefined;
+ if (checked) {
+ toast(i18n.t("two_factor_setup_instructions"));
+ }
+ i.setState(s => ((s.saveUserSettingsForm.generate_totp_2fa = checked), s));
+ }
+
+ handleRemoveTotp(i: Settings, event: any) {
+ // Coerce true to undefined here, so it won't generate it.
+ const checked: boolean | undefined = !event.target.checked && undefined;
+ i.setState(s => ((s.saveUserSettingsForm.generate_totp_2fa = checked), s));
}
handleSendNotificationsToEmailChange(i: Settings, event: any) {
- i.state.saveUserSettingsForm.send_notifications_to_email = Some(
- event.target.checked
+ i.setState(
+ s => (
+ (s.saveUserSettingsForm.send_notifications_to_email =
+ event.target.checked),
+ s
+ )
);
- i.setState(i.state);
}
handleThemeChange(i: Settings, event: any) {
- i.state.saveUserSettingsForm.theme = Some(event.target.value);
+ i.setState(s => ((s.saveUserSettingsForm.theme = event.target.value), s));
setTheme(event.target.value, true);
- i.setState(i.state);
}
- handleLangChange(i: Settings, event: any) {
- i.state.saveUserSettingsForm.lang = Some(event.target.value);
- i18n.changeLanguage(
- getLanguages(i.state.saveUserSettingsForm.lang.unwrap())[0]
+ handleInterfaceLangChange(i: Settings, event: any) {
+ const newLang = event.target.value ?? "browser";
+ i18n.changeLanguage(newLang === "browser" ? navigator.languages : newLang);
+
+ i.setState(
+ s => ((s.saveUserSettingsForm.interface_language = event.target.value), s)
);
- i.setState(i.state);
}
- handleSortTypeChange(val: SortType) {
- this.state.saveUserSettingsForm.default_sort_type = Some(
- Object.keys(SortType).indexOf(val)
+ handleDiscussionLanguageChange(val: number[]) {
+ this.setState(
+ s => ((s.saveUserSettingsForm.discussion_languages = val), s)
);
- this.setState(this.state);
+ }
+
+ handleSortTypeChange(val: SortType) {
+ this.setState(s => ((s.saveUserSettingsForm.default_sort_type = val), s));
}
handleListingTypeChange(val: ListingType) {
- this.state.saveUserSettingsForm.default_listing_type = Some(
- Object.keys(ListingType).indexOf(val)
+ this.setState(
+ s => ((s.saveUserSettingsForm.default_listing_type = val), s)
);
- this.setState(this.state);
}
handleEmailChange(i: Settings, event: any) {
- i.state.saveUserSettingsForm.email = Some(event.target.value);
- i.setState(i.state);
+ i.setState(s => ((s.saveUserSettingsForm.email = event.target.value), s));
}
handleBioChange(val: string) {
- this.state.saveUserSettingsForm.bio = Some(val);
- this.setState(this.state);
+ this.setState(s => ((s.saveUserSettingsForm.bio = val), s));
}
handleAvatarUpload(url: string) {
- this.state.saveUserSettingsForm.avatar = Some(url);
- this.setState(this.state);
+ this.setState(s => ((s.saveUserSettingsForm.avatar = url), s));
}
handleAvatarRemove() {
- this.state.saveUserSettingsForm.avatar = Some("");
- this.setState(this.state);
+ this.setState(s => ((s.saveUserSettingsForm.avatar = ""), s));
}
handleBannerUpload(url: string) {
- this.state.saveUserSettingsForm.banner = Some(url);
- this.setState(this.state);
+ this.setState(s => ((s.saveUserSettingsForm.banner = url), s));
}
handleBannerRemove() {
- this.state.saveUserSettingsForm.banner = Some("");
- this.setState(this.state);
+ this.setState(s => ((s.saveUserSettingsForm.banner = ""), s));
}
handleDisplayNameChange(i: Settings, event: any) {
- i.state.saveUserSettingsForm.display_name = Some(event.target.value);
- i.setState(i.state);
+ i.setState(
+ s => ((s.saveUserSettingsForm.display_name = event.target.value), s)
+ );
}
handleMatrixUserIdChange(i: Settings, event: any) {
- i.state.saveUserSettingsForm.matrix_user_id = Some(event.target.value);
- i.setState(i.state);
+ i.setState(
+ s => ((s.saveUserSettingsForm.matrix_user_id = event.target.value), s)
+ );
}
handleNewPasswordChange(i: Settings, event: any) {
- i.state.changePasswordForm.new_password = event.target.value;
- if (i.state.changePasswordForm.new_password == "") {
- i.state.changePasswordForm.new_password = undefined;
- }
- i.setState(i.state);
+ const newPass: string | undefined =
+ event.target.value == "" ? undefined : event.target.value;
+ i.setState(s => ((s.changePasswordForm.new_password = newPass), s));
}
handleNewPasswordVerifyChange(i: Settings, event: any) {
- i.state.changePasswordForm.new_password_verify = event.target.value;
- if (i.state.changePasswordForm.new_password_verify == "") {
- i.state.changePasswordForm.new_password_verify = undefined;
- }
- i.setState(i.state);
+ const newPassVerify: string | undefined =
+ event.target.value == "" ? undefined : event.target.value;
+ i.setState(
+ s => ((s.changePasswordForm.new_password_verify = newPassVerify), s)
+ );
}
handleOldPasswordChange(i: Settings, event: any) {
- i.state.changePasswordForm.old_password = event.target.value;
- if (i.state.changePasswordForm.old_password == "") {
- i.state.changePasswordForm.old_password = undefined;
- }
- i.setState(i.state);
+ const oldPass: string | undefined =
+ event.target.value == "" ? undefined : event.target.value;
+ i.setState(s => ((s.changePasswordForm.old_password = oldPass), s));
}
- handleSaveSettingsSubmit(i: Settings, event: any) {
+ async handleSaveSettingsSubmit(i: Settings, event: any) {
event.preventDefault();
- i.state.saveUserSettingsLoading = true;
- i.state.saveUserSettingsForm.auth = auth().unwrap();
- i.setState(i.state);
+ i.setState({ saveRes: { state: "loading" } });
- WebSocketService.Instance.send(
- wsClient.saveUserSettings(i.state.saveUserSettingsForm)
- );
+ const saveRes = await HttpService.client.saveUserSettings({
+ ...i.state.saveUserSettingsForm,
+ auth: myAuthRequired(),
+ });
+ if (saveRes.state === "success") {
+ UserService.Instance.login(saveRes.data);
+ location.reload();
+ toast(i18n.t("saved"));
+ window.scrollTo(0, 0);
+ }
+
+ i.setState({ saveRes });
}
- handleChangePasswordSubmit(i: Settings, event: any) {
+ async handleChangePasswordSubmit(i: Settings, event: any) {
event.preventDefault();
- i.state.changePasswordLoading = true;
- i.state.changePasswordForm.auth = auth().unwrap();
- i.setState(i.state);
+ const { new_password, new_password_verify, old_password } =
+ i.state.changePasswordForm;
+
+ if (new_password && old_password && new_password_verify) {
+ i.setState({ changePasswordRes: { state: "loading" } });
+ const changePasswordRes = await HttpService.client.changePassword({
+ new_password,
+ new_password_verify,
+ old_password,
+ auth: myAuthRequired(),
+ });
+ if (changePasswordRes.state === "success") {
+ UserService.Instance.login(changePasswordRes.data);
+ window.scrollTo(0, 0);
+ toast(i18n.t("password_changed"));
+ }
- WebSocketService.Instance.send(
- wsClient.changePassword(i.state.changePasswordForm)
- );
+ i.setState({ changePasswordRes });
+ }
}
- handleDeleteAccountShowConfirmToggle(i: Settings, event: any) {
- event.preventDefault();
- i.state.deleteAccountShowConfirm = !i.state.deleteAccountShowConfirm;
- i.setState(i.state);
+ handleDeleteAccountShowConfirmToggle(i: Settings) {
+ i.setState({ deleteAccountShowConfirm: !i.state.deleteAccountShowConfirm });
}
handleDeleteAccountPasswordChange(i: Settings, event: any) {
- i.state.deleteAccountForm.password = event.target.value;
- i.setState(i.state);
+ i.setState(s => ((s.deleteAccountForm.password = event.target.value), s));
}
- handleDeleteAccount(i: Settings, event: any) {
- event.preventDefault();
- i.state.deleteAccountLoading = true;
- i.state.deleteAccountForm.auth = auth().unwrap();
- i.setState(i.state);
+ async handleDeleteAccount(i: Settings) {
+ const password = i.state.deleteAccountForm.password;
+ if (password) {
+ i.setState({ deleteAccountRes: { state: "loading" } });
+ const deleteAccountRes = await HttpService.client.deleteAccount({
+ password,
+ auth: myAuthRequired(),
+ });
+ if (deleteAccountRes.state === "success") {
+ UserService.Instance.logout();
+ this.context.router.history.replace("/");
+ }
- WebSocketService.Instance.send(
- wsClient.deleteAccount(i.state.deleteAccountForm)
- );
+ i.setState({ deleteAccountRes });
+ }
}
handleSwitchTab(i: { ctx: Settings; tab: string }) {
i.ctx.setState({ currentTab: i.tab });
-
- if (i.ctx.state.currentTab == "blocks") {
- i.ctx.setupBlockPersonChoices();
- i.ctx.setupBlockCommunityChoices();
- }
}
- setUserInfo() {
- UserService.Instance.myUserInfo.match({
- some: mui => {
- let luv = mui.local_user_view;
- this.state.saveUserSettingsForm.show_nsfw = Some(
- luv.local_user.show_nsfw
- );
- this.state.saveUserSettingsForm.theme = Some(
- luv.local_user.theme ? luv.local_user.theme : "browser"
- );
- this.state.saveUserSettingsForm.default_sort_type = Some(
- luv.local_user.default_sort_type
- );
- this.state.saveUserSettingsForm.default_listing_type = Some(
- luv.local_user.default_listing_type
- );
- this.state.saveUserSettingsForm.lang = Some(luv.local_user.lang);
- this.state.saveUserSettingsForm.avatar = luv.person.avatar;
- this.state.saveUserSettingsForm.banner = luv.person.banner;
- this.state.saveUserSettingsForm.display_name = luv.person.display_name;
- this.state.saveUserSettingsForm.show_avatars = Some(
- luv.local_user.show_avatars
- );
- this.state.saveUserSettingsForm.bot_account = Some(
- luv.person.bot_account
- );
- this.state.saveUserSettingsForm.show_bot_accounts = Some(
- luv.local_user.show_bot_accounts
- );
- this.state.saveUserSettingsForm.show_scores = Some(
- luv.local_user.show_scores
- );
- this.state.saveUserSettingsForm.show_read_posts = Some(
- luv.local_user.show_read_posts
- );
- this.state.saveUserSettingsForm.show_new_post_notifs = Some(
- luv.local_user.show_new_post_notifs
- );
- this.state.saveUserSettingsForm.email = luv.local_user.email;
- this.state.saveUserSettingsForm.bio = luv.person.bio;
- this.state.saveUserSettingsForm.send_notifications_to_email = Some(
- luv.local_user.send_notifications_to_email
- );
- this.state.saveUserSettingsForm.matrix_user_id =
- luv.person.matrix_user_id;
- this.state.personBlocks = mui.person_blocks;
- this.state.communityBlocks = mui.community_blocks;
- },
- none: void 0,
- });
+ personBlock(res: RequestState<BlockPersonResponse>) {
+ if (res.state === "success") {
+ updatePersonBlock(res.data);
+ const mui = UserService.Instance.myUserInfo;
+ if (mui) {
+ this.setState({ personBlocks: mui.person_blocks });
+ }
+ }
}
- parseMessage(msg: any) {
- let op = wsUserOp(msg);
- console.log(msg);
- if (msg.error) {
- this.setState({
- saveUserSettingsLoading: false,
- changePasswordLoading: false,
- deleteAccountLoading: false,
- });
- toast(i18n.t(msg.error), "danger");
- return;
- } else if (op == UserOperation.SaveUserSettings) {
- let data = wsJsonToRes<LoginResponse>(msg, LoginResponse);
- UserService.Instance.login(data);
- this.state.saveUserSettingsLoading = false;
- this.setState(this.state);
- toast(i18n.t("saved"));
- window.scrollTo(0, 0);
- } else if (op == UserOperation.ChangePassword) {
- let data = wsJsonToRes<LoginResponse>(msg, LoginResponse);
- UserService.Instance.login(data);
- this.state.changePasswordLoading = false;
- this.setState(this.state);
- window.scrollTo(0, 0);
- toast(i18n.t("password_changed"));
- } else if (op == UserOperation.DeleteAccount) {
- this.setState({
- deleteAccountLoading: false,
- deleteAccountShowConfirm: false,
- });
- UserService.Instance.logout();
- window.location.href = "/";
- } else if (op == UserOperation.BlockPerson) {
- let data = wsJsonToRes<BlockPersonResponse>(msg, BlockPersonResponse);
- updatePersonBlock(data).match({
- some: blocks => this.setState({ personBlocks: blocks }),
- none: void 0,
- });
- } else if (op == UserOperation.BlockCommunity) {
- let data = wsJsonToRes<BlockCommunityResponse>(
- msg,
- BlockCommunityResponse
- );
- updateCommunityBlock(data).match({
- some: blocks => this.setState({ communityBlocks: blocks }),
- none: void 0,
- });
+ communityBlock(res: RequestState<BlockCommunityResponse>) {
+ if (res.state === "success") {
+ updateCommunityBlock(res.data);
+ const mui = UserService.Instance.myUserInfo;
+ if (mui) {
+ this.setState({ communityBlocks: mui.community_blocks });
+ }
}
}
}