From 4eeedd338fffa7402bbeeb426d6423841e99f940 Mon Sep 17 00:00:00 2001 From: shikelong <578622705@qq.com> Date: Thu, 4 Nov 2021 22:01:30 +0800 Subject: [PATCH 1/4] fix: fix modal invisible issue when has exist another opend modal. sample case: change avatar --- web/src/components/Modal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/components/Modal.tsx b/web/src/components/Modal.tsx index 3379a07d..ad4d7030 100644 --- a/web/src/components/Modal.tsx +++ b/web/src/components/Modal.tsx @@ -88,7 +88,7 @@ export const Modal: React.FC = React.memo((props) => { {/* Inner */}
From abb3d939e9f229239cd485c119ad2bc7eae7c055 Mon Sep 17 00:00:00 2001 From: shikelong <578622705@qq.com> Date: Thu, 4 Nov 2021 22:27:55 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat(setting):=20=E7=94=B1=E4=BA=8E=20gif?= =?UTF-8?q?=20=E4=BD=BF=E7=94=A8=20canvas=20=E8=A3=81=E5=89=AA=E5=90=8E?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E4=BF=9D=E7=95=99=E5=8A=A8=E5=9B=BE=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E5=AF=B9=20gif=20=E6=A0=BC=E5=BC=8F=E7=9A=84?= =?UTF-8?q?=E5=A4=B4=E5=83=8F=E6=96=87=E4=BB=B6=E8=B7=B3=E8=BF=87=E8=A3=81?= =?UTF-8?q?=E5=89=AA=E5=A4=84=E7=90=86=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 没有添加确认的步骤。个人感觉从用户体验上来说,直接设置成功会更好一些。 issue #7 --- web/src/components/AvatarPicker.tsx | 28 ++++++++++++++++++++-------- web/src/utils/filetype-helper.ts | 8 ++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 web/src/utils/filetype-helper.ts diff --git a/web/src/components/AvatarPicker.tsx b/web/src/components/AvatarPicker.tsx index 4f6711f6..61995439 100644 --- a/web/src/components/AvatarPicker.tsx +++ b/web/src/components/AvatarPicker.tsx @@ -4,6 +4,7 @@ import { showToasts, t } from 'tailchat-shared'; import { Avatar } from 'antd'; import { Icon } from '@iconify/react'; import { ModalAvatarCropper } from './modals/AvatarCropper'; +import { isGIF } from '@/utils/filetype-helper'; interface AvatarPickerProps { className?: string; @@ -16,10 +17,25 @@ interface AvatarPickerProps { */ export const AvatarPicker: React.FC = React.memo((props) => { const fileRef = useRef(null); - const [cropUrl, setCropUrl] = useState(props.imageUrl || ''); // 裁剪后并使用的url + const [avatarUrl, setAvatarUrl] = useState(props.imageUrl || ''); // 裁剪后并使用的url/或者未经裁剪的 gif url + + const updateAvatar = (imageBlobUrl: string) => { + setAvatarUrl(imageBlobUrl); + + if (typeof props.onChange === 'function') { + props.onChange(imageBlobUrl); + } + }; const handleSelectFile = (e: React.ChangeEvent) => { 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(); reader.addEventListener('load', () => { if (reader.result) { @@ -28,11 +44,7 @@ export const AvatarPicker: React.FC = React.memo((props) => { imageUrl={reader.result.toString()} onConfirm={(croppedImageBlobUrl) => { closeModal(key); - setCropUrl(croppedImageBlobUrl); - - if (typeof props.onChange === 'function') { - props.onChange(croppedImageBlobUrl); - } + updateAvatar(croppedImageBlobUrl); }} />, { @@ -44,7 +56,7 @@ export const AvatarPicker: React.FC = React.memo((props) => { showToasts(t('文件读取失败'), 'error'); } }); - reader.readAsDataURL(e.target.files[0]); + reader.readAsDataURL(pickedFile); // 清理选中状态 e.target.files = null; @@ -71,7 +83,7 @@ export const AvatarPicker: React.FC = React.memo((props) => { } - src={cropUrl} + src={avatarUrl} /> )}
diff --git a/web/src/utils/filetype-helper.ts b/web/src/utils/filetype-helper.ts new file mode 100644 index 00000000..b92643fe --- /dev/null +++ b/web/src/utils/filetype-helper.ts @@ -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'; +}; From 702ff7596e529ae2541620f11fb121c999e3fe0a Mon Sep 17 00:00:00 2001 From: shikelong <578622705@qq.com> Date: Thu, 4 Nov 2021 22:27:55 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat(setting):=20=E7=94=B1=E4=BA=8E=20gif?= =?UTF-8?q?=20=E4=BD=BF=E7=94=A8=20canvas=20=E8=A3=81=E5=89=AA=E5=90=8E?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E4=BF=9D=E7=95=99=E5=8A=A8=E5=9B=BE=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E5=AF=B9=20gif=20=E6=A0=BC=E5=BC=8F=E7=9A=84?= =?UTF-8?q?=E5=A4=B4=E5=83=8F=E6=96=87=E4=BB=B6=E8=B7=B3=E8=BF=87=E8=A3=81?= =?UTF-8?q?=E5=89=AA=E5=A4=84=E7=90=86=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 没有添加确认的步骤。个人感觉从用户体验上来说,直接设置成功会更好一些。 issue #7 --- web/src/components/AvatarPicker.tsx | 45 ++++++++++++++--------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/web/src/components/AvatarPicker.tsx b/web/src/components/AvatarPicker.tsx index 61995439..4efe474d 100644 --- a/web/src/components/AvatarPicker.tsx +++ b/web/src/components/AvatarPicker.tsx @@ -33,31 +33,30 @@ export const AvatarPicker: React.FC = React.memo((props) => { if (isGIF(pickedFile)) { updateAvatar(URL.createObjectURL(pickedFile)); - return; + } else { + const reader = new FileReader(); + reader.addEventListener('load', () => { + if (reader.result) { + const key = openModal( + { + closeModal(key); + updateAvatar(croppedImageBlobUrl); + }} + />, + { + maskClosable: false, + closable: true, + } + ); + } else { + showToasts(t('文件读取失败'), 'error'); + } + }); + reader.readAsDataURL(pickedFile); } - const reader = new FileReader(); - reader.addEventListener('load', () => { - if (reader.result) { - const key = openModal( - { - closeModal(key); - updateAvatar(croppedImageBlobUrl); - }} - />, - { - maskClosable: false, - closable: true, - } - ); - } else { - showToasts(t('文件读取失败'), 'error'); - } - }); - reader.readAsDataURL(pickedFile); - // 清理选中状态 e.target.files = null; e.target.value = ''; From 8a4bec8819ea570a3f43ce626619653887e93aac Mon Sep 17 00:00:00 2001 From: shikelong <578622705@qq.com> Date: Fri, 5 Nov 2021 20:02:33 +0800 Subject: [PATCH 4/4] refactor: move isGIF method's location --- web/src/components/AvatarPicker.tsx | 2 +- web/src/utils/file-helper.ts | 9 +++++++++ web/src/utils/filetype-helper.ts | 8 -------- 3 files changed, 10 insertions(+), 9 deletions(-) delete mode 100644 web/src/utils/filetype-helper.ts diff --git a/web/src/components/AvatarPicker.tsx b/web/src/components/AvatarPicker.tsx index 4efe474d..1492fa25 100644 --- a/web/src/components/AvatarPicker.tsx +++ b/web/src/components/AvatarPicker.tsx @@ -4,7 +4,7 @@ import { showToasts, t } from 'tailchat-shared'; import { Avatar } from 'antd'; import { Icon } from '@iconify/react'; import { ModalAvatarCropper } from './modals/AvatarCropper'; -import { isGIF } from '@/utils/filetype-helper'; +import { isGIF } from '@/utils/file-helper'; interface AvatarPickerProps { className?: string; diff --git a/web/src/utils/file-helper.ts b/web/src/utils/file-helper.ts index eb740deb..de28a022 100644 --- a/web/src/utils/file-helper.ts +++ b/web/src/utils/file-helper.ts @@ -114,3 +114,12 @@ export async function openFile( fileEl.click(); }); } + +/** + * 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'; +}; diff --git a/web/src/utils/filetype-helper.ts b/web/src/utils/filetype-helper.ts deleted file mode 100644 index b92643fe..00000000 --- a/web/src/utils/filetype-helper.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * 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'; -};