feat(setting): 由于 gif 使用 canvas 裁剪后无法保留动图格式,对 gif 格式的头像文件跳过裁剪处理。

没有添加确认的步骤。个人感觉从用户体验上来说,直接设置成功会更好一些。

issue #7
pull/13/head
shikelong 4 years ago
parent 4eeedd338f
commit abb3d939e9

@ -4,6 +4,7 @@ import { showToasts, t } from 'tailchat-shared';
import { Avatar } from 'antd'; import { Avatar } from 'antd';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { ModalAvatarCropper } from './modals/AvatarCropper'; import { ModalAvatarCropper } from './modals/AvatarCropper';
import { isGIF } from '@/utils/filetype-helper';
interface AvatarPickerProps { interface AvatarPickerProps {
className?: string; className?: string;
@ -16,10 +17,25 @@ interface AvatarPickerProps {
*/ */
export const AvatarPicker: React.FC<AvatarPickerProps> = React.memo((props) => { export const AvatarPicker: React.FC<AvatarPickerProps> = React.memo((props) => {
const fileRef = useRef<HTMLInputElement>(null); const fileRef = useRef<HTMLInputElement>(null);
const [cropUrl, setCropUrl] = useState<string>(props.imageUrl || ''); // 裁剪后并使用的url const [avatarUrl, setAvatarUrl] = useState<string>(props.imageUrl || ''); // 裁剪后并使用的url/或者未经裁剪的 gif url
const updateAvatar = (imageBlobUrl: string) => {
setAvatarUrl(imageBlobUrl);
if (typeof props.onChange === 'function') {
props.onChange(imageBlobUrl);
}
};
const handleSelectFile = (e: React.ChangeEvent<HTMLInputElement>) => { const handleSelectFile = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files && e.target.files.length > 0) { if (e.target.files && e.target.files.length > 0) {
const pickedFile = e.target.files[0];
if (isGIF(pickedFile)) {
updateAvatar(URL.createObjectURL(pickedFile));
return;
}
const reader = new FileReader(); const reader = new FileReader();
reader.addEventListener('load', () => { reader.addEventListener('load', () => {
if (reader.result) { if (reader.result) {
@ -28,11 +44,7 @@ export const AvatarPicker: React.FC<AvatarPickerProps> = React.memo((props) => {
imageUrl={reader.result.toString()} imageUrl={reader.result.toString()}
onConfirm={(croppedImageBlobUrl) => { onConfirm={(croppedImageBlobUrl) => {
closeModal(key); closeModal(key);
setCropUrl(croppedImageBlobUrl); updateAvatar(croppedImageBlobUrl);
if (typeof props.onChange === 'function') {
props.onChange(croppedImageBlobUrl);
}
}} }}
/>, />,
{ {
@ -44,7 +56,7 @@ export const AvatarPicker: React.FC<AvatarPickerProps> = React.memo((props) => {
showToasts(t('文件读取失败'), 'error'); showToasts(t('文件读取失败'), 'error');
} }
}); });
reader.readAsDataURL(e.target.files[0]); reader.readAsDataURL(pickedFile);
// 清理选中状态 // 清理选中状态
e.target.files = null; e.target.files = null;
@ -71,7 +83,7 @@ export const AvatarPicker: React.FC<AvatarPickerProps> = React.memo((props) => {
<Avatar <Avatar
size={64} size={64}
icon={<Icon className="anticon" icon="mdi:account" />} icon={<Icon className="anticon" icon="mdi:account" />}
src={cropUrl} src={avatarUrl}
/> />
)} )}
</div> </div>

@ -0,0 +1,8 @@
/**
* Judge GIF File type by mime type
* @param file File object
* @returns if passed file object is a gif image.
*/
export const isGIF = (file: File): boolean => {
return file.type === 'image/gif';
};
Loading…
Cancel
Save