From 5ffb5c1aeec600a224aff125ab147a44654f881c Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Tue, 14 Sep 2021 21:23:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=BE=93=E5=85=A5=E6=A1=86=E7=B2=98?= =?UTF-8?q?=E8=B4=B4=E4=B8=8A=E4=BC=A0=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/i18n/langs/en-US/translation.json | 2 + shared/i18n/langs/zh-CN/translation.json | 2 + .../ChatBox/ChatInputBox/clipboard-helper.ts | 34 +++++++++++++ .../components/ChatBox/ChatInputBox/index.tsx | 34 ++++++++++++- .../modals/ImageUploadPreviewer.tsx | 48 +++++++++++++++++++ web/tailwind.config.js | 1 + 6 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 web/src/components/ChatBox/ChatInputBox/clipboard-helper.ts create mode 100644 web/src/components/modals/ImageUploadPreviewer.tsx diff --git a/shared/i18n/langs/en-US/translation.json b/shared/i18n/langs/en-US/translation.json index 66250193..150a1aba 100644 --- a/shared/i18n/langs/en-US/translation.json +++ b/shared/i18n/langs/en-US/translation.json @@ -36,6 +36,7 @@ "k4603baea": "Create Group Panel", "k47489688": "Group Service", "k4d32a754": "Group Name", + "k50504f9e": "Upload picture to converse", "k50d471b2": "Reset", "k51243586": "Add friend", "k517db7e5": "Text Channel", @@ -110,6 +111,7 @@ "kdc4b4f92": "Public", "kdd4c838c": "Jump to Group", "kdd6c18f8": "Service exception", + "ke17b2c87": "Do not upload pictures that violate local laws and regulations", "ke187440d": "Panel type cannot be empty", "kecbd7449": "Delete", "ked2baf28": "Loading...", diff --git a/shared/i18n/langs/zh-CN/translation.json b/shared/i18n/langs/zh-CN/translation.json index c17ef15d..8032d41e 100644 --- a/shared/i18n/langs/zh-CN/translation.json +++ b/shared/i18n/langs/zh-CN/translation.json @@ -36,6 +36,7 @@ "k4603baea": "创建群组面板", "k47489688": "群组服务", "k4d32a754": "群组名称", + "k50504f9e": "上传图片到会话", "k50d471b2": "重置", "k51243586": "添加好友", "k517db7e5": "文字频道", @@ -110,6 +111,7 @@ "kdc4b4f92": "公共", "kdd4c838c": "跳转到群组", "kdd6c18f8": "服务异常", + "ke17b2c87": "请勿上传违反当地法律法规的图片", "ke187440d": "面板类型不能为空", "kecbd7449": "删除", "ked2baf28": "加载中...", diff --git a/web/src/components/ChatBox/ChatInputBox/clipboard-helper.ts b/web/src/components/ChatBox/ChatInputBox/clipboard-helper.ts new file mode 100644 index 00000000..d57e2e53 --- /dev/null +++ b/web/src/components/ChatBox/ChatInputBox/clipboard-helper.ts @@ -0,0 +1,34 @@ +export class ClipboardHelper { + data: DataTransfer; + + constructor(e: { clipboardData: DataTransfer }) { + this.data = e.clipboardData; + } + + hasImage(): File | false { + const image = this.isPasteImage(this.data.items); + if (image === false) { + return false; + } + + const file = image.getAsFile(); + if (file === null) { + return false; + } + + return file; + } + + private isPasteImage(items: DataTransferItemList): DataTransferItem | false { + let i = 0; + let item: DataTransferItem; + while (i < items.length) { + item = items[i]; + if (item.type.indexOf('image') !== -1) { + return item; + } + i++; + } + return false; + } +} diff --git a/web/src/components/ChatBox/ChatInputBox/index.tsx b/web/src/components/ChatBox/ChatInputBox/index.tsx index bf4f957c..7ed678f2 100644 --- a/web/src/components/ChatBox/ChatInputBox/index.tsx +++ b/web/src/components/ChatBox/ChatInputBox/index.tsx @@ -1,8 +1,12 @@ +import { closeModal, openModal } from '@/components/Modal'; +import { ImageUploadPreviewer } from '@/components/modals/ImageUploadPreviewer'; +import { fileToDataUrl } from '@/utils/file-helper'; import { isEnterHotkey } from '@/utils/hot-key'; import { Input } from 'antd'; import React, { useCallback, useRef, useState } from 'react'; -import { t } from 'tailchat-shared'; +import { t, uploadFile } from 'tailchat-shared'; import { ChatInputAddon } from './Addon'; +import { ClipboardHelper } from './clipboard-helper'; import { ChatInputActionContext } from './context'; interface ChatInputBoxProps { @@ -27,6 +31,33 @@ export const ChatInputBox: React.FC = React.memo((props) => { [handleSendMsg] ); + const handlePaste = useCallback( + (e: React.ClipboardEvent) => { + const helper = new ClipboardHelper(e); + const image = helper.hasImage(); + if (image) { + // 上传图片 + e.preventDefault(); + fileToDataUrl(image).then((imageLocalUrl) => { + const key = openModal( + { + const fileInfo = await uploadFile(image); + const imageRemoteUrl = fileInfo.url; + + // TODO: not good + props.onSendMsg(`[img]${imageRemoteUrl}[/img]`); + closeModal(key); + }} + /> + ); + }); + } + }, + [props.onSendMsg] + ); + return (
@@ -38,6 +69,7 @@ export const ChatInputBox: React.FC = React.memo((props) => { value={message} onChange={(e) => setMessage(e.target.value)} onKeyDown={handleKeyDown} + onPaste={handlePaste} />
diff --git a/web/src/components/modals/ImageUploadPreviewer.tsx b/web/src/components/modals/ImageUploadPreviewer.tsx new file mode 100644 index 00000000..e7a31e83 --- /dev/null +++ b/web/src/components/modals/ImageUploadPreviewer.tsx @@ -0,0 +1,48 @@ +import { ModalWrapper } from '@/plugin/common'; +import { Button } from '@/plugin/component'; +import React from 'react'; +import { t, useAsyncFn } from 'tailchat-shared'; + +interface ImageUploadPreviewerProps { + imageUrl: string; + onConfirm: () => void; +} +export const ImageUploadPreviewer: React.FC = + React.memo((props) => { + const { imageUrl } = props; + + const [{ loading }, handleConfirm] = useAsyncFn(async () => { + if (typeof props.onConfirm === 'function') { + await Promise.resolve(props.onConfirm()); + } + }, [props.onConfirm]); + + return ( + +
+
+ +
+ +
+
+
{t('上传图片到会话')}
+
+ {t('请勿上传违反当地法律法规的图片')} +
+
+ + +
+
+
+ ); + }); +ImageUploadPreviewer.displayName = 'ImageUploadPreviewer'; diff --git a/web/tailwind.config.js b/web/tailwind.config.js index 4df894c5..d8b027f7 100644 --- a/web/tailwind.config.js +++ b/web/tailwind.config.js @@ -59,6 +59,7 @@ module.exports = { spacing: { 18: '4.5rem', 142: '35.5rem', + 160: '40rem', }, lineHeight: { 13: '3.25rem',