diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ea697036..d4b38381 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -161,6 +161,7 @@ importers: react-virtualized-auto-sizer: ^1.0.6 react-virtuoso: ^2.2.7 rollup-plugin-copy: ^3.4.0 + rollup-plugin-replace: ^2.2.0 socket.io-client: ^4.1.2 str2int: ^1.1.0 style-loader: ^3.0.0 @@ -250,6 +251,7 @@ importers: postcss: registry.npmmirror.com/postcss/8.4.5 postcss-loader: registry.npmmirror.com/postcss-loader/6.2.1_postcss@8.4.5+webpack@5.65.0 rollup-plugin-copy: registry.npmmirror.com/rollup-plugin-copy/3.4.0 + rollup-plugin-replace: registry.npmmirror.com/rollup-plugin-replace/2.2.0 style-loader: registry.npmmirror.com/style-loader/3.3.1_webpack@5.65.0 ts-jest: registry.npmmirror.com/ts-jest/27.1.2_bba5c8054025e571e26b132e007b3f34 ts-node: registry.npmmirror.com/ts-node/10.4.0_4533f62004d7a07c02fadff9aaedf2fa @@ -276,6 +278,15 @@ importers: devDependencies: '@types/react-highlight': registry.npmmirror.com/@types/react-highlight/0.12.5 + web/plugins/com.msgbyte.draw: + specifiers: + '@types/react-canvas-draw': ^1.1.1 + react-canvas-draw: ^1.2.1 + dependencies: + react-canvas-draw: registry.npmmirror.com/react-canvas-draw/1.2.1_react@17.0.2 + devDependencies: + '@types/react-canvas-draw': registry.npmmirror.com/@types/react-canvas-draw/1.1.1 + web/plugins/com.msgbyte.intro: specifiers: shepherd.js: ^8.3.1 @@ -8510,6 +8521,14 @@ packages: version: 1.2.4 dev: true + registry.npmmirror.com/@types/react-canvas-draw/1.1.1: + resolution: {integrity: sha1-lj1HhnxFAKVY5nQdx419wWYhmvU=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/react-canvas-draw/download/@types/react-canvas-draw-1.1.1.tgz} + name: '@types/react-canvas-draw' + version: 1.1.1 + dependencies: + '@types/react': registry.npmmirror.com/@types/react/17.0.38 + dev: true + registry.npmmirror.com/@types/react-dom/17.0.11: resolution: {integrity: sha1-4ercPF6GvbX3aE4AJ0riKOe8xGY=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/react-dom/download/@types/react-dom-17.0.11.tgz} name: '@types/react-dom' @@ -9567,6 +9586,12 @@ packages: name: caniuse-lite version: 1.0.30001292 + registry.npmmirror.com/catenary-curve/1.0.1: + resolution: {integrity: sha1-V8MGGZJzW/00snTEAaloBv4woh8=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/catenary-curve/download/catenary-curve-1.0.1.tgz} + name: catenary-curve + version: 1.0.1 + dev: false + registry.npmmirror.com/chalk/1.1.3: resolution: {integrity: sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/chalk/download/chalk-1.1.3.tgz} name: chalk @@ -10737,6 +10762,12 @@ packages: engines: {node: '>=4.0'} dev: true + registry.npmmirror.com/estree-walker/0.6.1: + resolution: {integrity: sha1-UwSRQ/QMbrkYsjZx0f4yGfOhs2I=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/estree-walker/download/estree-walker-0.6.1.tgz} + name: estree-walker + version: 0.6.1 + dev: true + registry.npmmirror.com/estree-walker/1.0.1: resolution: {integrity: sha1-MbxdYSyWtwQQa0d+bdXYqhOMtwA=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/estree-walker/download/estree-walker-1.0.1.tgz} name: estree-walker @@ -12088,6 +12119,12 @@ packages: engines: {node: '>= 8'} dev: true + registry.npmmirror.com/lazy-brush/1.0.1: + resolution: {integrity: sha1-W/CZBzI3KU0vb8nWxdHXBeiRxb8=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lazy-brush/download/lazy-brush-1.0.1.tgz} + name: lazy-brush + version: 1.0.1 + dev: false + registry.npmmirror.com/lazystream/1.0.1: resolution: {integrity: sha1-SUyDEGLx+UCCUexE2xy6KSQqJjg=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lazystream/download/lazystream-1.0.1.tgz} name: lazystream @@ -13474,6 +13511,21 @@ packages: react-dom: registry.npmmirror.com/react-dom/17.0.2_react@17.0.2 dev: false + registry.npmmirror.com/react-canvas-draw/1.2.1_react@17.0.2: + resolution: {integrity: sha512-mCHE+Q91a26gUhyraHONedmbCI7dF/4BKdOxba7s4538QNfFWv/NfzLXWZrmjAQ4tO1vTvO+axX5YGIFjGc6uw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/react-canvas-draw/download/react-canvas-draw-1.2.1.tgz} + id: registry.npmmirror.com/react-canvas-draw/1.2.1 + name: react-canvas-draw + version: 1.2.1 + peerDependencies: + react: 16.x || 17.x + dependencies: + catenary-curve: registry.npmmirror.com/catenary-curve/1.0.1 + lazy-brush: registry.npmmirror.com/lazy-brush/1.0.1 + prop-types: registry.npmmirror.com/prop-types/15.8.0 + react: registry.npmmirror.com/react/17.0.2 + resize-observer-polyfill: registry.nlark.com/resize-observer-polyfill/1.5.1 + dev: false + registry.npmmirror.com/react-dom/17.0.2_react@17.0.2: resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/react-dom/download/react-dom-17.0.2.tgz} id: registry.npmmirror.com/react-dom/17.0.2 @@ -13895,6 +13947,16 @@ packages: rollup: registry.npmmirror.com/rollup/2.62.0 dev: false + registry.npmmirror.com/rollup-plugin-replace/2.2.0: + resolution: {integrity: sha1-9BrlNy4R56IXzeNJyLXV/RFecOM=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/rollup-plugin-replace/download/rollup-plugin-replace-2.2.0.tgz} + name: rollup-plugin-replace + version: 2.2.0 + deprecated: This module has moved and is now available at @rollup/plugin-replace. Please update your dependencies. This version is no longer maintained. + dependencies: + magic-string: registry.nlark.com/magic-string/0.25.7 + rollup-pluginutils: registry.npmmirror.com/rollup-pluginutils/2.8.2 + dev: true + registry.npmmirror.com/rollup-plugin-styles/3.14.1_rollup@2.62.0: resolution: {integrity: sha1-ip0TiFrFyC9RMJn1Z7lM/5N5cow=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/rollup-plugin-styles/download/rollup-plugin-styles-3.14.1.tgz} id: registry.npmmirror.com/rollup-plugin-styles/3.14.1 @@ -13942,6 +14004,14 @@ packages: - acorn dev: true + registry.npmmirror.com/rollup-pluginutils/2.8.2: + resolution: {integrity: sha1-cvKvB0i1kjZNvTOJ5gDlqURKNR4=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/rollup-pluginutils/download/rollup-pluginutils-2.8.2.tgz} + name: rollup-pluginutils + version: 2.8.2 + dependencies: + estree-walker: registry.npmmirror.com/estree-walker/0.6.1 + dev: true + registry.npmmirror.com/rollup/2.62.0: resolution: {integrity: sha512-cJEQq2gwB0GWMD3rYImefQTSjrPYaC6s4J9pYqnstVLJ1CHa/aZNVkD4Epuvg4iLeMA4KRiq7UM7awKK6j7jcw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/rollup/download/rollup-2.62.0.tgz} name: rollup diff --git a/web/.ministarrc.js b/web/.ministarrc.js index 272d27b8..6b040f98 100644 --- a/web/.ministarrc.js +++ b/web/.ministarrc.js @@ -1,4 +1,5 @@ const copy = require('rollup-plugin-copy'); +const replace = require('rollup-plugin-replace'); const path = require('path'); module.exports = { @@ -16,5 +17,8 @@ module.exports = { }, ], }), + replace({ + 'process.env.NODE_ENV': JSON.stringify('production'), + }), ], }; diff --git a/web/package.json b/web/package.json index e922e961..c9648fdb 100644 --- a/web/package.json +++ b/web/package.json @@ -92,6 +92,7 @@ "postcss": "^8.3.5", "postcss-loader": "^6.1.0", "rollup-plugin-copy": "^3.4.0", + "rollup-plugin-replace": "^2.2.0", "style-loader": "^3.0.0", "ts-jest": "^27.1.2", "ts-node": "^10.0.0", diff --git a/web/plugins/com.msgbyte.draw/manifest.json b/web/plugins/com.msgbyte.draw/manifest.json new file mode 100644 index 00000000..b76ff482 --- /dev/null +++ b/web/plugins/com.msgbyte.draw/manifest.json @@ -0,0 +1,9 @@ +{ + "label": "绘图插件", + "name": "com.msgbyte.draw", + "url": "/plugins/com.msgbyte.draw/index.js", + "version": "0.0.0", + "author": "msgbyte", + "description": "允许发送自定义绘图", + "requireRestart": false +} diff --git a/web/plugins/com.msgbyte.draw/package.json b/web/plugins/com.msgbyte.draw/package.json new file mode 100644 index 00000000..911e4b31 --- /dev/null +++ b/web/plugins/com.msgbyte.draw/package.json @@ -0,0 +1,12 @@ +{ + "name": "@plugins/com.msgbyte.draw", + "main": "src/index.tsx", + "version": "0.0.0", + "private": true, + "dependencies": { + "react-canvas-draw": "^1.2.1" + }, + "devDependencies": { + "@types/react-canvas-draw": "^1.1.1" + } +} diff --git a/web/plugins/com.msgbyte.draw/src/DrawModal.tsx b/web/plugins/com.msgbyte.draw/src/DrawModal.tsx new file mode 100644 index 00000000..e9f6c627 --- /dev/null +++ b/web/plugins/com.msgbyte.draw/src/DrawModal.tsx @@ -0,0 +1,56 @@ +import { + ChatInputActionContextProps, + dataUrlToFile, + uploadFile, + useAsyncFn, +} from '@capital/common'; +import { Button } from '@capital/component'; +import React, { useRef } from 'react'; +import CanvasDraw from 'react-canvas-draw'; +import { Translate } from './translate'; + +declare module 'react-canvas-draw' { + export default interface CanvasDraw { + getDataURL( + fileType?: string, + useBgImage?: boolean, + backgroundColour?: string + ); + } +} + +/** + * 绘图面板 + */ +const DrawModal: React.FC<{ + actions: ChatInputActionContextProps; + onSuccess: () => void; +}> = React.memo(({ actions, onSuccess }) => { + const sendMsg = actions.sendMsg; + const drawRef = useRef(null); + const [{ loading }, handleSend] = useAsyncFn(async () => { + const dataUrl = drawRef.current.getDataURL(); + const file = dataUrlToFile(dataUrl); + const res = await uploadFile(file); + + sendMsg(`[img]${res.url}[/img]`); + onSuccess(); + }, [sendMsg, onSuccess]); + + return ( +
+ + +
+ ); +}); +DrawModal.displayName = 'DrawModal'; + +export default DrawModal; diff --git a/web/plugins/com.msgbyte.draw/src/index.tsx b/web/plugins/com.msgbyte.draw/src/index.tsx new file mode 100644 index 00000000..1ff616b4 --- /dev/null +++ b/web/plugins/com.msgbyte.draw/src/index.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { + regChatInputAction, + Loadable, + openModal, + closeModal, +} from '@capital/common'; +import { Translate } from './translate'; +const DrawModal = Loadable(() => import('./DrawModal')); + +regChatInputAction({ + label: Translate.draw, + onClick: (actions) => { + const key = openModal( + closeModal(key)} /> + ); + }, +}); diff --git a/web/plugins/com.msgbyte.draw/src/translate.ts b/web/plugins/com.msgbyte.draw/src/translate.ts new file mode 100644 index 00000000..954e24f0 --- /dev/null +++ b/web/plugins/com.msgbyte.draw/src/translate.ts @@ -0,0 +1,6 @@ +import { localTrans } from '@capital/common'; + +export const Translate = { + draw: localTrans({ 'zh-CN': '绘图', 'en-US': 'Draw' }), + send: localTrans({ 'zh-CN': '发送', 'en-US': 'Send' }), +}; diff --git a/web/plugins/com.msgbyte.draw/tsconfig.json b/web/plugins/com.msgbyte.draw/tsconfig.json new file mode 100644 index 00000000..465a28b5 --- /dev/null +++ b/web/plugins/com.msgbyte.draw/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "baseUrl": "./src", + "esModuleInterop": true, + "jsx": "react", + "paths": { + "@capital/*": ["../../../src/plugin/*"], + } + } +} diff --git a/web/src/plugin/common/index.ts b/web/src/plugin/common/index.ts index 85a05412..d3b6383b 100644 --- a/web/src/plugin/common/index.ts +++ b/web/src/plugin/common/index.ts @@ -8,9 +8,15 @@ export { useGroupPanelParams, useCurrentGroupPanelInfo, } from '@/routes/Main/Content/Group/utils'; -export { openModal, ModalWrapper, useModalContext } from '@/components/Modal'; +export { + openModal, + closeModal, + ModalWrapper, + useModalContext, +} from '@/components/Modal'; export { Loadable } from '@/components/Loadable'; export { getGlobalState } from '@/utils/global-state-helper'; +export { dataUrlToFile } from '@/utils/file-helper'; import { request, RequestConfig } from 'tailchat-shared'; export { getCachedUserInfo, @@ -19,6 +25,7 @@ export { sharedEvent, useAsync, useAsyncFn, + uploadFile, } from 'tailchat-shared'; /** diff --git a/web/src/utils/file-helper.ts b/web/src/utils/file-helper.ts index de28a022..bb7ad81e 100644 --- a/web/src/utils/file-helper.ts +++ b/web/src/utils/file-helper.ts @@ -13,6 +13,22 @@ export function fileToDataUrl(img: File): Promise { }); } +/** + * 传入一个dataUrl + * 输出对应的File结构 + */ +export function dataUrlToFile(dataUrl: string, fileName = 'file'): File { + const arr = dataUrl.split(','); + const mime = _get(arr[0].match(/:(.*?);/), [1]); + const bstr = atob(arr[1]); + let n = bstr.length; + const u8arr = new Uint8Array(n); + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + return new File([u8arr], fileName, { type: mime }); +} + /** * 传入文件并返回该文件的内容 * @param file 文件对象