From 61484c61ba379e4a7d347ef21b5af6823ef0d829 Mon Sep 17 00:00:00 2001 From: hyrious Date: Tue, 31 May 2022 15:28:46 +0800 Subject: [PATCH] feat(project): add rename settings --- .../api-middleware/flatServer/constants.ts | 5 - .../src/api-middleware/flatServer/index.ts | 25 ++- .../GeneralSettingPage/index.tsx | 41 +++- .../GeneralSettingPage/style.less | 15 ++ packages/flat-i18n/locales/en.json | 4 +- packages/flat-i18n/locales/zh-CN.json | 4 +- .../src/api-middleware/flatServer/index.ts | 12 ++ .../index.tsx | 184 +++++++++--------- .../GeneralSettingPage/index.less | 15 ++ .../GeneralSettingPage/index.tsx | 40 +++- web/flat-web/src/stores/GlobalStore.ts | 2 + 11 files changed, 239 insertions(+), 108 deletions(-) diff --git a/desktop/renderer-app/src/api-middleware/flatServer/constants.ts b/desktop/renderer-app/src/api-middleware/flatServer/constants.ts index 95158219157..cf91771d492 100644 --- a/desktop/renderer-app/src/api-middleware/flatServer/constants.ts +++ b/desktop/renderer-app/src/api-middleware/flatServer/constants.ts @@ -43,11 +43,6 @@ export enum Status { AuthFailed, } -export enum Sex { - Man = "Man", - Woman = "Woman", -} - export enum FileConvertStep { None = "None", Converting = "Converting", diff --git a/desktop/renderer-app/src/api-middleware/flatServer/index.ts b/desktop/renderer-app/src/api-middleware/flatServer/index.ts index 5fbc7d9b801..4dcb05feb7a 100644 --- a/desktop/renderer-app/src/api-middleware/flatServer/index.ts +++ b/desktop/renderer-app/src/api-middleware/flatServer/index.ts @@ -1,5 +1,5 @@ import { Region } from "flat-components"; -import { RoomStatus, RoomType, Sex, Week } from "./constants"; +import { RoomStatus, RoomType, Week } from "./constants"; import { post, postNotAuth } from "./utils"; export interface CreateOrdinaryRoomPayload { @@ -451,22 +451,18 @@ export async function updatePeriodicSubRoom(payload: UpdatePeriodicSubRoomPayloa ); } -export interface LoginCheckPayload { - type: "web" | "mobile"; -} +export interface LoginCheckPayload {} export interface LoginCheckResult { name: string; - sex: Sex; avatar: string; + token: string; userUUID: string; hasPhone: boolean; } export async function loginCheck(): Promise { - return await post("login", { - type: "web", - }); + return await post("login", {}); } export interface setAuthUUIDPayload { @@ -489,7 +485,6 @@ export interface LoginProcessPayload { export interface LoginProcessResult { name: string; - sex: Sex; avatar: string; userUUID: string; token: string; @@ -557,3 +552,15 @@ export async function bindingPhone(phone: string, code: number): Promise { + return await post("user/rename", { + name, + }); +} diff --git a/desktop/renderer-app/src/pages/UserSettingPage/GeneralSettingPage/index.tsx b/desktop/renderer-app/src/pages/UserSettingPage/GeneralSettingPage/index.tsx index a6cce4b4edb..71b26d89df5 100644 --- a/desktop/renderer-app/src/pages/UserSettingPage/GeneralSettingPage/index.tsx +++ b/desktop/renderer-app/src/pages/UserSettingPage/GeneralSettingPage/index.tsx @@ -1,12 +1,14 @@ import "./style.less"; -import { Checkbox, Radio, RadioChangeEvent } from "antd"; +import { Button, Checkbox, Input, Radio, RadioChangeEvent } from "antd"; import React, { useContext, useEffect, useState } from "react"; import { UserSettingLayoutContainer } from "../UserSettingLayoutContainer"; import { ipcSyncByApp, ipcAsyncByApp } from "../../../utils/ipc"; import { useTranslation } from "react-i18next"; import { AppearancePicker, FlatPrefersColorScheme } from "flat-components"; -import { ConfigStoreContext } from "../../../components/StoreProvider"; +import { ConfigStoreContext, GlobalStoreContext } from "../../../components/StoreProvider"; +import { useSafePromise } from "../../../utils/hooks/lifecycle"; +import { loginCheck, rename } from "../../../api-middleware/flatServer"; enum SelectLanguage { Chinese, @@ -14,9 +16,26 @@ enum SelectLanguage { } export const GeneralSettingPage = (): React.ReactElement => { + const sp = useSafePromise(); const { t, i18n } = useTranslation(); const [openAtLogin, setOpenAtLogin] = useState(false); const configStore = useContext(ConfigStoreContext); + const globalStore = useContext(GlobalStoreContext); + + const [name, setName] = useState(globalStore.userName || ""); + const [isRenaming, setRenaming] = useState(false); + + async function changeUserName(): Promise { + if (name !== globalStore.userName) { + setRenaming(true); + await sp(rename(name)); + setRenaming(false); + // Refresh user info in global store. + const result = await sp(loginCheck()); + globalStore.updateUserInfo(result); + globalStore.updateLastLoginCheck(Date.now()); + } + } useEffect(() => { ipcSyncByApp("get-open-at-login") @@ -55,6 +74,24 @@ export const GeneralSettingPage = (): React.ReactElement => { +
+ {t("user-profile")} + + setName(ev.currentTarget.value)} + /> + +
{t("language-settings")} span { + display: block; + padding-bottom: 4px; + } + > label { + padding-right: 16px; + color: var(--text); + } + .ant-input { + width: 320px; + margin-bottom: 12px; + } +} + .general-setting-checkbox { margin-bottom: 32px; } diff --git a/packages/flat-i18n/locales/en.json b/packages/flat-i18n/locales/en.json index f22f6509b5b..380c3d5e545 100644 --- a/packages/flat-i18n/locales/en.json +++ b/packages/flat-i18n/locales/en.json @@ -453,5 +453,7 @@ "math_1": "Coordinate Axis", "english_1": "Four Lines and Three Grids", "chinese_1": "Tin Word Format" - } + }, + "user-profile": "User Profile", + "username": "Name" } diff --git a/packages/flat-i18n/locales/zh-CN.json b/packages/flat-i18n/locales/zh-CN.json index 70ca14f3c98..75b1589c14f 100644 --- a/packages/flat-i18n/locales/zh-CN.json +++ b/packages/flat-i18n/locales/zh-CN.json @@ -453,5 +453,7 @@ "math_1": "坐标系", "english_1": "四线三格", "chinese_1": "田字格" - } + }, + "user-profile": "我的资料", + "username": "昵称" } diff --git a/web/flat-web/src/api-middleware/flatServer/index.ts b/web/flat-web/src/api-middleware/flatServer/index.ts index 3aad93af130..ff9792ade3d 100644 --- a/web/flat-web/src/api-middleware/flatServer/index.ts +++ b/web/flat-web/src/api-middleware/flatServer/index.ts @@ -571,3 +571,15 @@ export async function bindingPhone(phone: string, code: number): Promise { + return await post("user/rename", { + name, + }); +} diff --git a/web/flat-web/src/components/MainPageLayoutHorizontalContainer/index.tsx b/web/flat-web/src/components/MainPageLayoutHorizontalContainer/index.tsx index 4965f286224..dd30539c5db 100644 --- a/web/flat-web/src/components/MainPageLayoutHorizontalContainer/index.tsx +++ b/web/flat-web/src/components/MainPageLayoutHorizontalContainer/index.tsx @@ -1,5 +1,6 @@ /* eslint react/display-name: off */ import React, { useContext } from "react"; +import { observer } from "mobx-react-lite"; import { useHistory, useLocation } from "react-router-dom"; import { MainPageLayoutHorizontal, @@ -29,102 +30,109 @@ export interface MainPageLayoutHorizontalContainerProps { onBackPreviousPage?: () => void; } -export const MainPageLayoutHorizontalContainer: React.FC< - MainPageLayoutHorizontalContainerProps -> = ({ subMenu, children, activeKeys, onRouteChange, title, onBackPreviousPage }) => { - const { t } = useTranslation(); - const leftMenu = [ - { - key: routeConfig[RouteNameType.HomePage].path, - icon: (active: boolean): React.ReactNode => { - return active ? : ; +export const MainPageLayoutHorizontalContainer = observer( + function MainPageLayoutHorizontalContainer({ + subMenu, + children, + activeKeys, + onRouteChange, + title, + onBackPreviousPage, + }) { + const { t } = useTranslation(); + const leftMenu = [ + { + key: routeConfig[RouteNameType.HomePage].path, + icon: (active: boolean): React.ReactNode => { + return active ? : ; + }, + title: t("home"), + route: routeConfig[RouteNameType.HomePage].path, }, - title: t("home"), - route: routeConfig[RouteNameType.HomePage].path, - }, - { - key: routeConfig[RouteNameType.CloudStoragePage].path, - icon: (active: boolean): React.ReactNode => { - return active ? : ; + { + key: routeConfig[RouteNameType.CloudStoragePage].path, + icon: (active: boolean): React.ReactNode => { + return active ? : ; + }, + title: t("cloud-storage"), + route: routeConfig[RouteNameType.CloudStoragePage].path, }, - title: t("cloud-storage"), - route: routeConfig[RouteNameType.CloudStoragePage].path, - }, - ]; + ]; - const rightMenu: MainPageLayoutItem[] = [ - { - key: "download", - icon: (): React.ReactNode => , - title: <>, - route: FLAT_DOWNLOAD_URL, - }, - { - key: "getGitHubCode", - icon: (): React.ReactNode => , - title: <>, - route: "https://github.com/netless-io/flat/", - }, - { - key: routeConfig[RouteNameType.GeneralSettingPage].path, - icon: (): React.ReactNode => , - title: <>, - route: routeConfig[RouteNameType.GeneralSettingPage].path, - }, - ]; + const rightMenu: MainPageLayoutItem[] = [ + { + key: "download", + icon: (): React.ReactNode => , + title: <>, + route: FLAT_DOWNLOAD_URL, + }, + { + key: "getGitHubCode", + icon: (): React.ReactNode => , + title: <>, + route: "https://github.com/netless-io/flat/", + }, + { + key: routeConfig[RouteNameType.GeneralSettingPage].path, + icon: (): React.ReactNode => , + title: <>, + route: routeConfig[RouteNameType.GeneralSettingPage].path, + }, + ]; - const popMenu = [ - { - key: "feedback", - icon: (): React.ReactNode => , - title: t("feedback"), - route: "https://github.com/netless-io/flat/issues", - }, - { - key: "logout", - icon: (): React.ReactNode => , - title: {t("logout")}, - route: routeConfig[RouteNameType.LoginPage].path, - }, - ]; + const popMenu = [ + { + key: "feedback", + icon: (): React.ReactNode => , + title: t("feedback"), + route: "https://github.com/netless-io/flat/issues", + }, + { + key: "logout", + icon: (): React.ReactNode => , + title: {t("logout")}, + route: routeConfig[RouteNameType.LoginPage].path, + }, + ]; - const location = useLocation(); + const location = useLocation(); - activeKeys ??= [location.pathname]; + activeKeys ??= [location.pathname]; - const history = useHistory(); + const history = useHistory(); - const globalStore = useContext(GlobalStoreContext); + const globalStore = useContext(GlobalStoreContext); - const onMenuItemClick = (mainPageLayoutItem: MainPageLayoutItem): void => { - if (mainPageLayoutItem.key === "logout") { - globalStore.logout(); - } + const onMenuItemClick = (mainPageLayoutItem: MainPageLayoutItem): void => { + if (mainPageLayoutItem.key === "logout") { + globalStore.logout(); + } - if (mainPageLayoutItem.route.startsWith("/")) { - onRouteChange - ? onRouteChange(mainPageLayoutItem) - : history.push(mainPageLayoutItem.route); - } else { - void window.open(mainPageLayoutItem.route); - } - }; + if (mainPageLayoutItem.route.startsWith("/")) { + onRouteChange + ? onRouteChange(mainPageLayoutItem) + : history.push(mainPageLayoutItem.route); + } else { + void window.open(mainPageLayoutItem.route); + } + }; - return ( - - {children} - - ); -}; + return ( + + {children} + + ); + }, +); diff --git a/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.less b/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.less index 0d486b67605..cbd6239f244 100644 --- a/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.less +++ b/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.less @@ -5,6 +5,21 @@ } } +.general-setting-user-profile { + > span { + display: block; + padding-bottom: 4px; + } + > label { + padding-right: 16px; + color: var(--text); + } + .ant-input { + width: 320px; + margin-bottom: 12px; + } +} + .general-setting-select-language { > span { display: block; diff --git a/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.tsx b/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.tsx index a22c888c2b5..7f059170442 100644 --- a/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.tsx +++ b/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.tsx @@ -1,12 +1,14 @@ import "./index.less"; import { FlatPrefersColorScheme, AppearancePicker } from "flat-components"; -import { Checkbox, Radio } from "antd"; -import React, { useContext } from "react"; +import { Button, Checkbox, Input, Radio } from "antd"; +import React, { useContext, useState } from "react"; import { UserSettingLayoutContainer } from "../UserSettingLayoutContainer"; import { useTranslation } from "react-i18next"; import type { CheckboxChangeEvent } from "antd/lib/checkbox"; import { ConfigStoreContext, GlobalStoreContext } from "../../../components/StoreProvider"; +import { useSafePromise } from "../../../utils/hooks/lifecycle"; +import { loginCheck, rename } from "../../../api-middleware/flatServer"; enum SelectLanguage { Chinese, @@ -17,8 +19,24 @@ export const GeneralSettingPage = (): React.ReactElement => { const globalStore = useContext(GlobalStoreContext); const configStore = useContext(ConfigStoreContext); + const sp = useSafePromise(); const { t, i18n } = useTranslation(); + const [name, setName] = useState(globalStore.userName || ""); + const [isRenaming, setRenaming] = useState(false); + + async function changeUserName(): Promise { + if (name !== globalStore.userName) { + setRenaming(true); + await sp(rename(name)); + setRenaming(false); + // Refresh user info in global store. + const result = await sp(loginCheck()); + globalStore.updateUserInfo(result); + globalStore.updateLastLoginCheck(Date.now()); + } + } + function changeLanguage(event: CheckboxChangeEvent): void { const language: SelectLanguage = event.target.value; void i18n.changeLanguage(language === SelectLanguage.Chinese ? "zh-CN" : "en"); @@ -32,6 +50,24 @@ export const GeneralSettingPage = (): React.ReactElement => { return (
+
+ {t("user-profile")} + + setName(ev.currentTarget.value)} + /> + +
{t("language-settings")}