Compare commits

...

2 Commits

Author SHA1 Message Date
CrescentLeaf
f376de2b48 ui: 微調消息菜單
* 仿照電報邏輯
* 添加 JsonView
2025-10-01 11:51:28 +08:00
CrescentLeaf
459fca064c depend: add react-json-view@1.21.3 2025-10-01 11:23:09 +08:00
4 changed files with 26 additions and 12 deletions

View File

@@ -28,6 +28,7 @@
"socket.io-client": "npm:socket.io-client@4.8.1",
"marked": "npm:marked@16.3.0",
"dompurify": "npm:dompurify@3.2.7",
"pinch-zoom-element": "npm:pinch-zoom-element@1.1.1"
"pinch-zoom-element": "npm:pinch-zoom-element@1.1.1",
"react-json-view": "npm:react-json-view@1.21.3"
}
}

View File

@@ -14,7 +14,6 @@ import useAsyncEffect from "../useAsyncEffect.ts"
import * as marked from 'marked'
import DOMPurify from 'dompurify'
import randomUUID from "../../randomUUID.ts"
import { time } from "node:console";
interface Args extends React.HTMLAttributes<HTMLElement> {
target: string

View File

@@ -1,4 +1,4 @@
import { alert, Dropdown } from "mdui"
import { Dropdown, Dialog } from "mdui"
import { $ } from "mdui/jq"
import Client from "../../api/Client.ts"
import Data_Message from "../../api/client_data/Message.ts"
@@ -6,9 +6,11 @@ import DataCaches from "../../api/DataCaches.ts"
import Avatar from "../Avatar.tsx"
import copyToClipboard from "../copyToClipboard.ts"
import useAsyncEffect from "../useAsyncEffect.ts"
import useEventListener from "../useEventListener.ts"
import React from "react"
import useEventListener from "../useEventListener.ts"
import isMobileUI from "../isMobileUI.ts"
import ReactJson from 'react-json-view'
interface Args extends React.HTMLAttributes<HTMLElement> {
userId: string
@@ -30,10 +32,23 @@ export default function Message({ userId, rawData, renderHTML, message, ...props
}, [userId])
const dropDownRef = React.useRef<Dropdown>(null)
const messageJsonDialogRef = React.useRef<Dialog>(null)
const [isDropDownOpen, setDropDownOpen] = React.useState(false)
return (
<div
slot="trigger"
onContextMenu={(e) => {
if (isMobileUI()) return
e.preventDefault()
setDropDownOpen(!isDropDownOpen)
}}
onClick={(e) => {
if (!isMobileUI()) return
e.preventDefault()
setDropDownOpen(!isDropDownOpen)
}}
style={{
width: "100%",
display: "flex",
@@ -88,7 +103,10 @@ export default function Message({ userId, rawData, renderHTML, message, ...props
padding: "15px",
alignSelf: isAtRight ? "flex-end" : "flex-start",
}}>
<mdui-dropdown trigger={isMobileUI() ? 'click' : 'contextmenu'} ref={dropDownRef}>
<mdui-dialog close-on-overlay-click close-on-esc ref={messageJsonDialogRef}>
<ReactJson src={message} />
</mdui-dialog>
<mdui-dropdown trigger="manual" ref={dropDownRef} open={isDropDownOpen}>
<span
slot="trigger"
id="msg"
@@ -98,15 +116,10 @@ export default function Message({ userId, rawData, renderHTML, message, ...props
dangerouslySetInnerHTML={{
__html: renderHTML
}} />
<mdui-menu>
<mdui-menu onClick={(e) => e.stopPropagation()}>
<mdui-menu-item icon="content_copy" onClick={() => copyToClipboard($(dropDownRef.current as HTMLElement).find('#msg').text())}></mdui-menu-item>
<mdui-menu-item icon="content_copy" onClick={() => copyToClipboard(rawData)}></mdui-menu-item>
<mdui-menu-item icon="info" onClick={() => alert({
headline: "消息详情",
description: JSON.stringify(message),
confirmText: "关闭",
onConfirm: () => { },
})}></mdui-menu-item>
<mdui-menu-item icon="info" onClick={() => messageJsonDialogRef.current.open = true}></mdui-menu-item>
</mdui-menu>
</mdui-dropdown>
</mdui-card>

View File

@@ -29,7 +29,8 @@ customElements.define('chat-image', class extends HTMLElement {
})
}
e.src = $(this).attr('src') as string
e.onclick = () => {
e.onclick = (event) => {
event.stopPropagation()
openImageViewer($(this).attr('src') as string)
}
this.appendChild(e)