import { useState, useEffect, ReactNode, ComponentPropsWithoutRef, } from "react"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import classNames from "classnames"; import { useC, Text } from "@/common"; import { useUser, userService } from "@/services/user"; import { getHttpUserClient } from "@/http/user"; import ConfirmDialog from "@/views/common/dialog/ConfirmDialog"; import Card from "@/views/common/Card"; import Spinner from "@/views/common/Spinner"; import Page from "@/views/common/Page"; import ChangePasswordDialog from "./ChangePasswordDialog"; import ChangeAvatarDialog from "./ChangeAvatarDialog"; import ChangeNicknameDialog from "./ChangeNicknameDialog"; import "./index.css"; import { pushAlert } from "@/services/alert"; interface SettingSectionProps extends Omit, "title"> { title: Text; children?: ReactNode; } function SettingSection({ title, className, children, ...otherProps }: SettingSectionProps) { const c = useC(); return (

{c(title)}

{children}
); } interface SettingItemContainerProps extends Omit, "title"> { title: Text; description?: Text; danger?: boolean; extraClassName?: string; } function SettingItemContainer({ title, description, danger, extraClassName, className, children, ...otherProps }: SettingItemContainerProps) { const c = useC(); return (
{c(title)}
{c(description)}
{children}
); } type ButtonSettingItemProps = Omit; function ButtonSettingItem(props: ButtonSettingItemProps) { return ( ); } interface SelectSettingItemProps extends Omit { options: { value: string; label: Text; }[]; value?: string | null; onSelect: (value: string) => void; } function SelectSettingsItem({ options, value, onSelect, ...extraProps }: SelectSettingItemProps) { const c = useC(); return ( {value == null ? ( ) : ( )} ); } function RegisterCodeSettingItem() { const user = useUser(); // undefined: loading const [registerCode, setRegisterCode] = useState(); const [dialogOpen, setDialogOpen] = useState(false); useEffect(() => { setRegisterCode(undefined); }, [user]); useEffect(() => { if (user != null && registerCode === undefined) { void getHttpUserClient() .getRegisterCode(user.username) .then((code) => { setRegisterCode(code.registerCode ?? null); }); } }, [user, registerCode]); return ( setDialogOpen(true)} > {registerCode === undefined ? ( ) : registerCode === null ? ( Noop ) : ( { void navigator.clipboard.writeText(registerCode).then(() => { pushAlert({ type: "success", message: "settings.myRegisterCodeCopied", }); }); event.stopPropagation(); }} > {registerCode} )} setDialogOpen(false)} open={dialogOpen} onConfirm={() => { if (user == null) throw new Error(); void getHttpUserClient() .renewRegisterCode(user.username) .then(() => { setRegisterCode(undefined); }); }} /> ); } function LanguageChangeSettingItem() { const { i18n } = useTranslation(); const language = i18n.language.slice(0, 2); return ( { void i18n.changeLanguage(value); }} /> ); } export default function SettingPage() { const user = useUser(); const navigate = useNavigate(); type DialogName = | "change-password" | "change-avatar" | "change-nickname" | "logout" | "renew-register-code"; const [dialog, setDialog] = useState(null); function dialogOpener(name: DialogName): () => void { return () => setDialog(name); } return ( {user ? ( ) : null} setDialog(null)} /> {user && ( <> setDialog(null)} open={dialog === "logout"} onConfirm={() => { void userService.logout().then(() => { navigate("/"); }); }} /> setDialog(null)} /> setDialog(null)} /> )} ); }