import { None, Option, Some } from "@sniptt/monads"; import { Component, linkEvent } from "inferno"; import { BlockCommunity, BlockCommunityResponse, BlockPerson, BlockPersonResponse, ChangePassword, CommunityBlockView, CommunityView, DeleteAccount, 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 { auth, capitalizeFirstLetter, choicesConfig, communitySelectName, communityToChoice, debounce, elementUrl, enableNsfw, fetchCommunities, fetchThemeList, fetchUsers, getLanguages, isBrowser, personSelectName, personToChoice, relTags, setIsoData, setTheme, setupTippy, showLocal, toast, updateCommunityBlock, updatePersonBlock, wsClient, wsSubscribe, } from "../../utils"; import { HtmlTags } from "../common/html-tags"; import { Icon, Spinner } from "../common/icon"; import { ImageUploadForm } from "../common/image-upload-form"; import { ListingTypeSelect } from "../common/listing-type-select"; import { MarkdownTextArea } from "../common/markdown-textarea"; import { SortSelect } from "../common/sort-select"; 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; personBlocks: PersonBlockView[]; blockPerson: Option; communityBlocks: CommunityBlockView[]; blockCommunityId: number; blockCommunity?: CommunityView; currentTab: string; themeList: string[]; saveUserSettingsLoading: boolean; changePasswordLoading: boolean; deleteAccountLoading: boolean; deleteAccountShowConfirm: boolean; siteRes: GetSiteResponse; } export class Settings extends Component { 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, deleteAccountShowConfirm: false, deleteAccountForm: new DeleteAccount({ password: undefined, auth: undefined, }), personBlocks: [], blockPerson: None, communityBlocks: [], blockCommunityId: 0, currentTab: "settings", siteRes: this.isoData.site_res, themeList: [], }; 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.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(); } async componentDidMount() { setupTippy(); this.state.themeList = await fetchThemeList(); this.setState(this.state); } componentWillUnmount() { this.subscription.unsubscribe(); } get documentTitle(): string { return i18n.t("settings"); } render() { return (
<> {this.state.currentTab == "settings" && this.userSettings()} {this.state.currentTab == "blocks" && this.blockCards()}
); } userSettings() { return (
{this.saveUserSettingsHtmlForm()}
{this.changePasswordHtmlForm()}
); } blockCards() { return (
{this.blockUserCard()}
{this.blockCommunityCard()}
); } changePasswordHtmlForm() { return ( <>
{i18n.t("change_password")}
); } blockUserCard() { return (
{this.blockUserForm()} {this.blockedUsersList()}
); } blockedUsersList() { return ( <>
{i18n.t("blocked_users")}
); } blockUserForm() { return (
); } blockCommunityCard() { return (
{this.blockCommunityForm()} {this.blockedCommunitiesList()}
); } blockedCommunitiesList() { return ( <>
{i18n.t("blocked_communities")}
); } blockCommunityForm() { return (
); } saveUserSettingsHtmlForm() { return ( <>
{i18n.t("settings")}
{enableNsfw(this.state.siteRes) && (
)}

{this.state.deleteAccountShowConfirm && ( <> )}
); } 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 ); } } } 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 ); } } } handleBlockPerson(personId: number) { if (personId != 0) { let blockUserForm = new BlockPerson({ person_id: personId, block: true, auth: auth().unwrap(), }); WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm)); } } handleUnblockPerson(i: { ctx: Settings; recipientId: number }) { let blockUserForm = new BlockPerson({ person_id: i.recipientId, block: false, auth: auth().unwrap(), }); WebSocketService.Instance.send(wsClient.blockPerson(blockUserForm)); } handleBlockCommunity(community_id: number) { if (community_id != 0) { let blockCommunityForm = new BlockCommunity({ community_id, block: true, auth: auth().unwrap(), }); WebSocketService.Instance.send( wsClient.blockCommunity(blockCommunityForm) ); } } 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)); } handleShowNsfwChange(i: Settings, event: any) { i.state.saveUserSettingsForm.show_nsfw = Some(event.target.checked); i.setState(i.state); } 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); } handleBotAccount(i: Settings, event: any) { i.state.saveUserSettingsForm.bot_account = Some(event.target.checked); i.setState(i.state); } handleShowBotAccounts(i: Settings, event: any) { i.state.saveUserSettingsForm.show_bot_accounts = Some(event.target.checked); i.setState(i.state); } handleReadPosts(i: Settings, event: any) { i.state.saveUserSettingsForm.show_read_posts = Some(event.target.checked); i.setState(i.state); } handleShowNewPostNotifs(i: Settings, event: any) { i.state.saveUserSettingsForm.show_new_post_notifs = Some( event.target.checked ); 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); } handleSendNotificationsToEmailChange(i: Settings, event: any) { i.state.saveUserSettingsForm.send_notifications_to_email = Some( event.target.checked ); i.setState(i.state); } handleThemeChange(i: Settings, event: any) { i.state.saveUserSettingsForm.theme = Some(event.target.value); 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] ); i.setState(i.state); } handleSortTypeChange(val: SortType) { this.state.saveUserSettingsForm.default_sort_type = Some( Object.keys(SortType).indexOf(val) ); this.setState(this.state); } handleListingTypeChange(val: ListingType) { this.state.saveUserSettingsForm.default_listing_type = Some( Object.keys(ListingType).indexOf(val) ); this.setState(this.state); } handleEmailChange(i: Settings, event: any) { i.state.saveUserSettingsForm.email = Some(event.target.value); i.setState(i.state); } handleBioChange(val: string) { this.state.saveUserSettingsForm.bio = Some(val); this.setState(this.state); } handleAvatarUpload(url: string) { this.state.saveUserSettingsForm.avatar = Some(url); this.setState(this.state); } handleAvatarRemove() { this.state.saveUserSettingsForm.avatar = Some(""); this.setState(this.state); } handleBannerUpload(url: string) { this.state.saveUserSettingsForm.banner = Some(url); this.setState(this.state); } handleBannerRemove() { this.state.saveUserSettingsForm.banner = Some(""); this.setState(this.state); } handleDisplayNameChange(i: Settings, event: any) { i.state.saveUserSettingsForm.display_name = Some(event.target.value); i.setState(i.state); } handleMatrixUserIdChange(i: Settings, event: any) { i.state.saveUserSettingsForm.matrix_user_id = Some(event.target.value); i.setState(i.state); } 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); } 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); } 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); } handleSaveSettingsSubmit(i: Settings, event: any) { event.preventDefault(); i.state.saveUserSettingsLoading = true; i.state.saveUserSettingsForm.auth = auth().unwrap(); i.setState(i.state); WebSocketService.Instance.send( wsClient.saveUserSettings(i.state.saveUserSettingsForm) ); } handleChangePasswordSubmit(i: Settings, event: any) { event.preventDefault(); i.state.changePasswordLoading = true; i.state.changePasswordForm.auth = auth().unwrap(); i.setState(i.state); WebSocketService.Instance.send( wsClient.changePassword(i.state.changePasswordForm) ); } handleDeleteAccountShowConfirmToggle(i: Settings, event: any) { event.preventDefault(); i.state.deleteAccountShowConfirm = !i.state.deleteAccountShowConfirm; i.setState(i.state); } handleDeleteAccountPasswordChange(i: Settings, event: any) { i.state.deleteAccountForm.password = event.target.value; i.setState(i.state); } handleDeleteAccount(i: Settings, event: any) { event.preventDefault(); i.state.deleteAccountLoading = true; i.state.deleteAccountForm.auth = auth().unwrap(); i.setState(i.state); WebSocketService.Instance.send( wsClient.deleteAccount(i.state.deleteAccountForm) ); } 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, }); } 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(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(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(msg, BlockPersonResponse); updatePersonBlock(data).match({ some: blocks => this.setState({ personBlocks: blocks }), none: void 0, }); } else if (op == UserOperation.BlockCommunity) { let data = wsJsonToRes( msg, BlockCommunityResponse ); updateCommunityBlock(data).match({ some: blocks => this.setState({ communityBlocks: blocks }), none: void 0, }); } } }