diff --git a/electron/electron.js b/electron/electron.js index 9a1ff8e9f..06651f934 100644 --- a/electron/electron.js +++ b/electron/electron.js @@ -413,6 +413,19 @@ ipcMain.on('setDockBadge', (event, args) => { event.returnValue = "ok" }) +/** + * 复制Base64图片 + * @param args + */ +ipcMain.on('copyBase64Image', (event, args) => { + const { base64 } = args; + if (base64) { + const img = nativeImage.createFromDataURL(base64) + clipboard.writeImage(img) + } + event.returnValue = "ok" +}) + //================================================================ // Update //================================================================ diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index 80bc9e377..767811927 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -175,9 +175,9 @@ {{ $L('编辑') }} -
  • - - {{ $L('复制') }} +
  • + + {{ $L(item.label) }}
  • @@ -472,7 +472,7 @@ export default { navStyle: {}, operateVisible: false, - operateHasText: false, + operateCopys: [], operateStyles: {}, operateItem: {}, operateEmojis: ['👌', '🤝', '🎉', '❤️', '👍', '🥰', '🥳️', '✅', '❌', '⭕️', '❓', '🚀', '👀'], @@ -1601,7 +1601,30 @@ export default { onLongpress({event, el, msgData}) { this.operateVisible = this.operateItem.id === msgData.id; this.operateItem = $A.isJson(msgData) ? msgData : {}; - this.operateHasText = msgData.type === 'text' && msgData.msg.text.replace(/<[^>]+>/g,"").length > 0 + this.operateCopys = [] + if (event.target.nodeName === 'IMG' && this.$Electron) { + this.operateCopys.push({ + type: 'image', + icon: '', + label: '复制图片', + value: $A.rightDelete(event.target.currentSrc, '_thumb.jpg'), + }) + } else if (event.target.nodeName === 'A') { + this.operateCopys.push({ + type: 'link', + icon: '', + label: '复制链接', + value: event.target.href, + }) + } + if (msgData.type === 'text' && msgData.msg.text.replace(/<[^>]+>/g,"").length > 0) { + this.operateCopys.push({ + type: 'text', + icon: '', + label: this.operateCopys.length > 0 ? '复制文本' : '复制', + value: '', + }) + } this.$nextTick(() => { const projectRect = el.getBoundingClientRect(); const wrapRect = this.$el.getBoundingClientRect(); @@ -1627,7 +1650,7 @@ export default { break; case "copy": - this.onCopy() + this.onCopy(value) break; case "forward": @@ -1693,18 +1716,34 @@ export default { } }, - onCopy() { - if (this.operateHasText) { - try { + onCopy(data) { + if (!$A.isJson(data)) { + return + } + const {type, value} = data + switch (type) { + case 'image': + if (this.$Electron) { + this.getBase64Image(value).then(base64 => { + this.$Electron.sendMessage('copyBase64Image', {base64}); + }) + } + break; + + case 'link': + this.$copyText(value).then(_ => $A.messageSuccess('复制成功')).catch(_ => $A.messageError('复制失败')) + break; + + case 'text': const copyEl = $A(this.$refs.scroller.$el).find(`[data-id="${this.operateItem.id}"]`).find('.dialog-content') if (copyEl.length > 0) { const text = copyEl[0].innerText.replace(/\n\n/g, "\n") - this.$copyText(text).then(_ => $A.messageSuccess('复制成功')).catch(_ => $A.messageError('复制失败')); - return + this.$copyText(text).then(_ => $A.messageSuccess('复制成功')).catch(_ => $A.messageError('复制失败')) + } else { + $A.messageWarning('不可复制的内容'); } - } catch (e) {} + break; } - $A.messageWarning('不可复制的内容'); }, onCancelReply() { @@ -1994,6 +2033,29 @@ export default { this.$store.dispatch("updateDialogLastMsg", data.add); } }, + + getBase64Image(url) { + return new Promise(resolve => { + let canvas = document.createElement('CANVAS'), + ctx = canvas.getContext('2d'), + img = new Image; + img.crossOrigin = 'Anonymous'; + img.onload = () => { + canvas.height = img.height; + canvas.width = img.width; + ctx.drawImage(img, 0, 0); + let format = "png"; + if ($A.rightExists(url, "jpg") || $A.rightExists(url, "jpeg")) { + format = "jpeg" + } else if ($A.rightExists(url, "git")) { + format = "git" + } + resolve(canvas.toDataURL(`image/${format}`)); + canvas = null; + }; + img.src = url; + }) + } } } diff --git a/resources/assets/sass/pages/components/dialog-group-info.scss b/resources/assets/sass/pages/components/dialog-group-info.scss index 96bb828cd..1d47c5cd8 100644 --- a/resources/assets/sass/pages/components/dialog-group-info.scss +++ b/resources/assets/sass/pages/components/dialog-group-info.scss @@ -41,6 +41,7 @@ justify-content: center; margin: 18px 24px; cursor: pointer; + > button { margin: 0 8px; } @@ -63,6 +64,7 @@ &:hover { background-color: rgba($primary-desc-color, 0.1); + .user-exit { opacity: 1; transform: translateX(0); @@ -79,8 +81,10 @@ &:hover { background-color: transparent; } + justify-content: center; color: #999; + .common-loading { width: 16px; height: 16px; @@ -90,6 +94,7 @@ .common-avatar { width: 0; flex: 1; + .avatar-name { padding-left: 8px; } @@ -117,11 +122,18 @@ opacity: 0; transform: translateX(50%); transition: all 0.2s; + + @media (max-width: 768px) { + opacity: 1; + transform: translateX(0); + } + &:hover { > i { color: $primary-text-color; } } + > i { display: flex; align-items: center; diff --git a/resources/assets/sass/pages/components/dialog-wrapper.scss b/resources/assets/sass/pages/components/dialog-wrapper.scss index 911769cf8..cff0768ae 100644 --- a/resources/assets/sass/pages/components/dialog-wrapper.scss +++ b/resources/assets/sass/pages/components/dialog-wrapper.scss @@ -1320,18 +1320,18 @@ margin-bottom: -8px; display: grid; justify-content: space-between; - grid-template-columns: repeat(auto-fill, 50px); + grid-template-columns: repeat(auto-fill, 60px); > li { list-style: none; - width: 50px; - height: 48px; - margin-bottom: 12px; + width: 60px; + height: 52px; + margin-bottom: 14px; display: flex; flex-direction: column; align-items: center; justify-content: space-between; .taskfont { - font-size: 20px; + font-size: 22px; } > span { padding: 0 1px; diff --git a/resources/assets/statics/public/css/fonts/taskfont/iconfont.ttf b/resources/assets/statics/public/css/fonts/taskfont/iconfont.ttf index 12c03b1fb..96294c664 100644 Binary files a/resources/assets/statics/public/css/fonts/taskfont/iconfont.ttf and b/resources/assets/statics/public/css/fonts/taskfont/iconfont.ttf differ diff --git a/resources/assets/statics/public/css/fonts/taskfont/iconfont.woff b/resources/assets/statics/public/css/fonts/taskfont/iconfont.woff index 289f53ae1..97dead0c8 100644 Binary files a/resources/assets/statics/public/css/fonts/taskfont/iconfont.woff and b/resources/assets/statics/public/css/fonts/taskfont/iconfont.woff differ diff --git a/resources/assets/statics/public/css/fonts/taskfont/iconfont.woff2 b/resources/assets/statics/public/css/fonts/taskfont/iconfont.woff2 index a9c7bf2a0..d74961911 100644 Binary files a/resources/assets/statics/public/css/fonts/taskfont/iconfont.woff2 and b/resources/assets/statics/public/css/fonts/taskfont/iconfont.woff2 differ