import DefaultAvatar from '@renderer/assets/images/avatar.png' import EmojiAvatar from '@renderer/components/Avatar/EmojiAvatar' import useAvatar from '@renderer/hooks/useAvatar' import { useSettings } from '@renderer/hooks/useSettings' import ImageStorage from '@renderer/services/ImageStorage' import { useAppDispatch } from '@renderer/store' import { setAvatar } from '@renderer/store/runtime' import { setUserName } from '@renderer/store/settings' import { compressImage, isEmoji } from '@renderer/utils' import { Avatar, Dropdown, Input, Modal, Popover, Upload } from 'antd' import React, { useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' import EmojiPicker from '../EmojiPicker' import { Center, HStack, VStack } from '../Layout' import { TopView } from '../TopView' interface Props { resolve: (data: any) => void } const PopupContainer: React.FC = ({ resolve }) => { const [open, setOpen] = useState(true) const [emojiPickerOpen, setEmojiPickerOpen] = useState(false) const [dropdownOpen, setDropdownOpen] = useState(false) const { t } = useTranslation() const { userName } = useSettings() const dispatch = useAppDispatch() const avatar = useAvatar() const onOk = () => { setOpen(false) } const onCancel = () => { setOpen(false) } const onClose = () => { resolve({}) } const handleEmojiClick = async (emoji: string) => { try { // set emoji string await ImageStorage.set('avatar', emoji) // update avatar display dispatch(setAvatar(emoji)) setEmojiPickerOpen(false) } catch (error: any) { window.toast.error(error.message) } } const handleReset = async () => { try { await ImageStorage.set('avatar', DefaultAvatar) dispatch(setAvatar(DefaultAvatar)) setDropdownOpen(false) } catch (error: any) { window.toast.error(error.message) } } const items = [ { key: 'upload', label: (
{}} accept="image/png, image/jpeg, image/gif" itemRender={() => null} maxCount={1} onChange={async ({ file }) => { try { const _file = file.originFileObj as File if (_file.type === 'image/gif') { await ImageStorage.set('avatar', _file) } else { const compressedFile = await compressImage(_file) await ImageStorage.set('avatar', compressedFile) } dispatch(setAvatar(await ImageStorage.get('avatar'))) setDropdownOpen(false) } catch (error: any) { window.toast.error(error.message) } }} > {t('settings.general.image_upload')}
) }, { key: 'emoji', label: (
{ e.stopPropagation() setEmojiPickerOpen(true) setDropdownOpen(false) }} > {t('settings.general.emoji_picker')}
) }, { key: 'reset', label: (
{ e.stopPropagation() handleReset() }} > {t('settings.general.avatar.reset')}
) } ] return (
{ setDropdownOpen(visible) if (visible) { setEmojiPickerOpen(false) } }} > } trigger="click" open={emojiPickerOpen} onOpenChange={(visible) => { setEmojiPickerOpen(visible) if (visible) { setDropdownOpen(false) } }} placement="bottom" > {isEmoji(avatar) ? ( {avatar} ) : ( )}
dispatch(setUserName(e.target.value.trim()))} style={{ flex: 1, textAlign: 'center', width: '100%' }} maxLength={30} />
) } const UserAvatar = styled(Avatar)` cursor: pointer; width: 80px; height: 80px; transition: opacity 0.3s ease; &:hover { opacity: 0.8; } ` export default class UserPopup { static topviewId = 0 static hide() { TopView.hide('UserPopup') } static show() { return new Promise((resolve) => { TopView.show( { resolve(v) this.hide() }} />, 'UserPopup' ) }) } }