diff --git a/desktop/renderer-app/src/pages/UserSettingPage/GeneralSettingPage/UploadAvatar.tsx b/desktop/renderer-app/src/pages/UserSettingPage/GeneralSettingPage/UploadAvatar.tsx index 74ac0db1d0f..63ed91d5573 100644 --- a/desktop/renderer-app/src/pages/UserSettingPage/GeneralSettingPage/UploadAvatar.tsx +++ b/desktop/renderer-app/src/pages/UserSettingPage/GeneralSettingPage/UploadAvatar.tsx @@ -1,5 +1,5 @@ import Axios from "axios"; -import React, { ChangeEvent, useContext, useRef, useState } from "react"; +import React, { ChangeEvent, useContext, useEffect, useState } from "react"; import classNames from "classnames"; import { Region } from "flat-components"; import { observer } from "mobx-react-lite"; @@ -12,14 +12,10 @@ import { uploadAvatarFinish, uploadAvatarStart } from "../../../api-middleware/f import { globalStore } from "../../../stores/global-store"; export interface UploadAvatarProps { - fileRef?: React.MutableRefObject; + onUpload?: (file: File) => Promise; } -export function useFileRef(): React.MutableRefObject { - return useRef(); -} - -export const UploadAvatar = observer(function UploadAvatar({ fileRef }) { +export const UploadAvatar = observer(function UploadAvatar({ onUpload }) { const globalStore = useContext(GlobalStoreContext); const sp = useSafePromise(); const { t } = useTranslation(); @@ -27,17 +23,21 @@ export const UploadAvatar = observer(function UploadAvatar({ const [loading, setLoading] = useState(false); const [imageUrl, setImageUrl] = useState(globalStore.userInfo?.avatar || ""); - const updateInput = (event: ChangeEvent): void => { - const file: File | undefined = (event.target.files || [])[0]; - if (fileRef) { - fileRef.current = file; + useEffect(() => { + if (globalStore.userInfo?.avatar) { + setImageUrl(globalStore.userInfo.avatar); } + }, [globalStore.userInfo?.avatar]); + + const updateInput = async (event: ChangeEvent): Promise => { + const file: File | undefined = (event.target.files || [])[0]; if (file) { setLoading(true); - sp(fileToDataUrl(file)).then(url => { - setLoading(false); - setImageUrl(url); - }); + sp(fileToDataUrl(file)).then(setImageUrl); + if (onUpload) { + await sp(onUpload(file).catch(console.error)); + } + setLoading(false); } else { setImageUrl(globalStore.userInfo?.avatar || ""); } diff --git a/desktop/renderer-app/src/pages/UserSettingPage/GeneralSettingPage/index.tsx b/desktop/renderer-app/src/pages/UserSettingPage/GeneralSettingPage/index.tsx index ef8ac1e9352..12dc3cfb09a 100644 --- a/desktop/renderer-app/src/pages/UserSettingPage/GeneralSettingPage/index.tsx +++ b/desktop/renderer-app/src/pages/UserSettingPage/GeneralSettingPage/index.tsx @@ -10,7 +10,7 @@ import { ConfigStoreContext, GlobalStoreContext } from "../../../components/Stor import { useSafePromise } from "../../../utils/hooks/lifecycle"; import { loginCheck, rename } from "../../../api-middleware/flatServer"; import { ConfirmButtons } from "./ConfirmButtons"; -import { UploadAvatar, uploadAvatar, useFileRef } from "./UploadAvatar"; +import { UploadAvatar, uploadAvatar } from "./UploadAvatar"; enum SelectLanguage { Chinese, @@ -26,7 +26,6 @@ export const GeneralSettingPage = (): React.ReactElement => { const [name, setName] = useState(globalStore.userName || ""); const [isRenaming, setRenaming] = useState(false); - const fileRef = useFileRef(); async function changeUserName(): Promise { if (name !== globalStore.userName) { @@ -40,16 +39,12 @@ export const GeneralSettingPage = (): React.ReactElement => { } } - async function changeAvatar(): Promise { - if (fileRef.current) { - try { - await uploadAvatar(fileRef.current); - } catch (error) { - console.error(error); - message.info(t("upload-avatar-failed")); - } finally { - fileRef.current = undefined; - } + async function onUpload(file: File): Promise { + try { + await uploadAvatar(file); + } catch (error) { + message.info(t("upload-avatar-failed")); + throw error; } } @@ -93,10 +88,11 @@ export const GeneralSettingPage = (): React.ReactElement => {
{t("user-profile")}
- - + {t("avatar")} +
+ {t("username")} ; + onUpload?: (file: File) => Promise; } -export function useFileRef(): React.MutableRefObject { - return useRef(); -} - -export const UploadAvatar = observer(function UploadAvatar({ fileRef }) { +export const UploadAvatar = observer(function UploadAvatar({ onUpload }) { const globalStore = useContext(GlobalStoreContext); const sp = useSafePromise(); const { t } = useTranslation(); @@ -27,17 +23,21 @@ export const UploadAvatar = observer(function UploadAvatar({ const [loading, setLoading] = useState(false); const [imageUrl, setImageUrl] = useState(globalStore.userInfo?.avatar || ""); - const updateInput = (event: ChangeEvent): void => { - const file: File | undefined = (event.target.files || [])[0]; - if (fileRef) { - fileRef.current = file; + useEffect(() => { + if (globalStore.userInfo?.avatar) { + setImageUrl(globalStore.userInfo.avatar); } + }, [globalStore.userInfo?.avatar]); + + const updateInput = async (event: ChangeEvent): Promise => { + const file: File | undefined = (event.target.files || [])[0]; if (file) { setLoading(true); - sp(fileToDataUrl(file)).then(url => { - setLoading(false); - setImageUrl(url); - }); + sp(fileToDataUrl(file)).then(setImageUrl); + if (onUpload) { + await sp(onUpload(file).catch(console.error)); + } + setLoading(false); } else { setImageUrl(globalStore.userInfo?.avatar || ""); } diff --git a/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.less b/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.less index 41ceded6efd..9cfe3577c3a 100644 --- a/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.less +++ b/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.less @@ -24,6 +24,11 @@ } } +.general-setting-subtitle { + color: var(--text-strong); + padding-right: 16px; +} + .general-setting-user-avatar-wrapper { display: flex; align-items: center; @@ -36,7 +41,7 @@ height: 96px; margin-right: 16px; border-radius: 50%; - border: 1px solid var(--grey-6); + border: 1px solid #dbe1ea; overflow: hidden; position: relative; transition: all 0.2s ease-in-out; @@ -45,10 +50,6 @@ opacity: 0.5; } - &:hover { - border-color: var(--primary); - } - .user-avatar-input { display: block; position: absolute; @@ -74,6 +75,12 @@ justify-content: center; } } +.flat-color-scheme-dark .general-setting-user-avatar { + border-color: var(--grey-6); +} +.general-setting-user-avatar:hover { + border-color: var(--primary); +} .general-setting-select-language { > span { diff --git a/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.tsx b/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.tsx index 16a156f5109..aace2702306 100644 --- a/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.tsx +++ b/web/flat-web/src/pages/UserSettingPage/GeneralSettingPage/index.tsx @@ -11,7 +11,7 @@ import { ConfigStoreContext, GlobalStoreContext } from "../../../components/Stor import { useSafePromise } from "../../../utils/hooks/lifecycle"; import { loginCheck, rename } from "../../../api-middleware/flatServer"; import { ConfirmButtons } from "./ConfirmButtons"; -import { uploadAvatar, UploadAvatar, useFileRef } from "./UploadAvatar"; +import { uploadAvatar, UploadAvatar } from "./UploadAvatar"; enum SelectLanguage { Chinese, @@ -27,7 +27,6 @@ export const GeneralSettingPage = (): React.ReactElement => { const [name, setName] = useState(globalStore.userName || ""); const [isRenaming, setRenaming] = useState(false); - const fileRef = useFileRef(); async function changeUserName(): Promise { if (name !== globalStore.userName) { @@ -41,16 +40,12 @@ export const GeneralSettingPage = (): React.ReactElement => { } } - async function changeAvatar(): Promise { - if (fileRef.current) { - try { - await uploadAvatar(fileRef.current); - } catch (error) { - console.error(error); - message.info(t("upload-avatar-failed")); - } finally { - fileRef.current = undefined; - } + async function onUpload(file: File): Promise { + try { + await uploadAvatar(file); + } catch (error) { + message.info(t("upload-avatar-failed")); + throw error; } } @@ -70,10 +65,11 @@ export const GeneralSettingPage = (): React.ReactElement => {
{t("user-profile")}
- - + {t("avatar")} +
+ {t("username")}