feat: 对话中打开用户的资料
This commit is contained in:
@@ -21,6 +21,8 @@ import useAsyncEffect from "./useAsyncEffect.ts"
|
|||||||
import ChatInfoDialog from "./dialog/ChatInfoDialog.tsx"
|
import ChatInfoDialog from "./dialog/ChatInfoDialog.tsx"
|
||||||
import Chat from "../api/client_data/Chat.ts"
|
import Chat from "../api/client_data/Chat.ts"
|
||||||
import AddContactDialog from './dialog/AddContactDialog.tsx'
|
import AddContactDialog from './dialog/AddContactDialog.tsx'
|
||||||
|
import UserProfileDialog from "./dialog/UserProfileDialog.tsx"
|
||||||
|
import DataCaches from "../api/DataCaches.ts"
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
namespace React {
|
namespace React {
|
||||||
@@ -56,6 +58,9 @@ export default function App() {
|
|||||||
myProfileDialogRef.current!.open = true
|
myProfileDialogRef.current!.open = true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const userProfileDialogRef = React.useRef<Dialog>(null)
|
||||||
|
const [userInfo, setUserInfo] = React.useState(null as unknown as User)
|
||||||
|
|
||||||
const addContactDialogRef = React.useRef<Dialog>(null)
|
const addContactDialogRef = React.useRef<Dialog>(null)
|
||||||
|
|
||||||
const chatInfoDialogRef = React.useRef<Dialog>(null)
|
const chatInfoDialogRef = React.useRef<Dialog>(null)
|
||||||
@@ -94,6 +99,21 @@ export default function App() {
|
|||||||
chatInfoDialogRef.current!.open = true
|
chatInfoDialogRef.current!.open = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openChatFragment(chatId: string) {
|
||||||
|
setCurrentChatId(chatId)
|
||||||
|
setIsShowChatFragment(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openUserInfoDialog(user: User | string) {
|
||||||
|
if (user instanceof User) {
|
||||||
|
setUserInfo(user)
|
||||||
|
} else {
|
||||||
|
setUserInfo(await DataCaches.getUserProfile(user))
|
||||||
|
|
||||||
|
}
|
||||||
|
userProfileDialogRef.current!.open = true
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<div style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@@ -118,13 +138,14 @@ export default function App() {
|
|||||||
<MyProfileDialog
|
<MyProfileDialog
|
||||||
myProfileDialogRef={myProfileDialogRef as any}
|
myProfileDialogRef={myProfileDialogRef as any}
|
||||||
user={myUserProfileCache} />
|
user={myUserProfileCache} />
|
||||||
|
<UserProfileDialog
|
||||||
|
userProfileDialogRef={userProfileDialogRef as any}
|
||||||
|
openChatFragment={openChatFragment}
|
||||||
|
user={userInfo} />
|
||||||
|
|
||||||
<ChatInfoDialog
|
<ChatInfoDialog
|
||||||
chatInfoDialogRef={chatInfoDialogRef as any}
|
chatInfoDialogRef={chatInfoDialogRef as any}
|
||||||
openChatFragment={(id) => {
|
openChatFragment={openChatFragment}
|
||||||
setCurrentChatId(id)
|
|
||||||
setIsShowChatFragment(true)
|
|
||||||
}}
|
|
||||||
chat={chatInfo} />
|
chat={chatInfo} />
|
||||||
|
|
||||||
<AddContactDialog
|
<AddContactDialog
|
||||||
@@ -147,10 +168,7 @@ export default function App() {
|
|||||||
{
|
{
|
||||||
// 最近聊天
|
// 最近聊天
|
||||||
<RecentsList
|
<RecentsList
|
||||||
openChatFragment={(id) => {
|
openChatFragment={openChatFragment}
|
||||||
setCurrentChatId(id)
|
|
||||||
setIsShowChatFragment(true)
|
|
||||||
}}
|
|
||||||
display={navigationItemSelected == "Recents"}
|
display={navigationItemSelected == "Recents"}
|
||||||
currentChatId={currentChatId} />
|
currentChatId={currentChatId} />
|
||||||
}
|
}
|
||||||
@@ -181,6 +199,7 @@ export default function App() {
|
|||||||
{
|
{
|
||||||
isShowChatFragment && <ChatFragment
|
isShowChatFragment && <ChatFragment
|
||||||
target={currentChatId}
|
target={currentChatId}
|
||||||
|
openUserInfoDialog={openUserInfoDialog}
|
||||||
openChatInfoDialog={openChatInfoDialog}
|
openChatInfoDialog={openChatInfoDialog}
|
||||||
key={currentChatId} />
|
key={currentChatId} />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import useAsyncEffect from "./useAsyncEffect.ts"
|
|||||||
import ChatInfoDialog from "./dialog/ChatInfoDialog.tsx"
|
import ChatInfoDialog from "./dialog/ChatInfoDialog.tsx"
|
||||||
import Chat from "../api/client_data/Chat.ts"
|
import Chat from "../api/client_data/Chat.ts"
|
||||||
import AddContactDialog from './dialog/AddContactDialog.tsx'
|
import AddContactDialog from './dialog/AddContactDialog.tsx'
|
||||||
|
import UserProfileDialog from "./dialog/UserProfileDialog.tsx"
|
||||||
|
import DataCaches from "../api/DataCaches.ts"
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
namespace React {
|
namespace React {
|
||||||
@@ -60,6 +62,9 @@ export default function AppMobile() {
|
|||||||
const chatInfoDialogRef = React.useRef<Dialog>(null)
|
const chatInfoDialogRef = React.useRef<Dialog>(null)
|
||||||
const [chatInfo, setChatInfo] = React.useState(null as unknown as Chat)
|
const [chatInfo, setChatInfo] = React.useState(null as unknown as Chat)
|
||||||
|
|
||||||
|
const userProfileDialogRef = React.useRef<Dialog>(null)
|
||||||
|
const [userInfo, setUserInfo] = React.useState(null as unknown as User)
|
||||||
|
|
||||||
const [myUserProfileCache, setMyUserProfileCache] = React.useState(null as unknown as User)
|
const [myUserProfileCache, setMyUserProfileCache] = React.useState(null as unknown as User)
|
||||||
|
|
||||||
const [isShowChatFragment, setIsShowChatFragment] = React.useState(false)
|
const [isShowChatFragment, setIsShowChatFragment] = React.useState(false)
|
||||||
@@ -96,6 +101,21 @@ export default function AppMobile() {
|
|||||||
chatInfoDialogRef.current!.open = true
|
chatInfoDialogRef.current!.open = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openChatFragment(chatId: string) {
|
||||||
|
setCurrentChatId(chatId)
|
||||||
|
setIsShowChatFragment(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openUserInfoDialog(user: User | string) {
|
||||||
|
if (user instanceof User) {
|
||||||
|
setUserInfo(user)
|
||||||
|
} else {
|
||||||
|
setUserInfo(await DataCaches.getUserProfile(user))
|
||||||
|
|
||||||
|
}
|
||||||
|
userProfileDialogRef.current!.open = true
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<div style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@@ -114,6 +134,7 @@ export default function AppMobile() {
|
|||||||
}}>
|
}}>
|
||||||
<ChatFragment
|
<ChatFragment
|
||||||
showReturnButton={true}
|
showReturnButton={true}
|
||||||
|
openUserInfoDialog={openUserInfoDialog}
|
||||||
onReturnButtonClicked={() => setIsShowChatFragment(false)}
|
onReturnButtonClicked={() => setIsShowChatFragment(false)}
|
||||||
key={currentChatId}
|
key={currentChatId}
|
||||||
openChatInfoDialog={openChatInfoDialog}
|
openChatInfoDialog={openChatInfoDialog}
|
||||||
@@ -138,6 +159,10 @@ export default function AppMobile() {
|
|||||||
<MyProfileDialog
|
<MyProfileDialog
|
||||||
myProfileDialogRef={myProfileDialogRef as any}
|
myProfileDialogRef={myProfileDialogRef as any}
|
||||||
user={myUserProfileCache} />
|
user={myUserProfileCache} />
|
||||||
|
<UserProfileDialog
|
||||||
|
userProfileDialogRef={userProfileDialogRef as any}
|
||||||
|
openChatFragment={openChatFragment}
|
||||||
|
user={userInfo} />
|
||||||
|
|
||||||
<ChatInfoDialog
|
<ChatInfoDialog
|
||||||
chatInfoDialogRef={chatInfoDialogRef as any}
|
chatInfoDialogRef={chatInfoDialogRef as any}
|
||||||
|
|||||||
@@ -14,13 +14,15 @@ import useAsyncEffect from "../useAsyncEffect.ts"
|
|||||||
import * as marked from 'marked'
|
import * as marked from 'marked'
|
||||||
import DOMPurify from 'dompurify'
|
import DOMPurify from 'dompurify'
|
||||||
import randomUUID from "../../randomUUID.ts"
|
import randomUUID from "../../randomUUID.ts"
|
||||||
import EventBus from "../../EventBus.ts";
|
import EventBus from "../../EventBus.ts"
|
||||||
|
import User from "../../api/client_data/User.ts"
|
||||||
|
|
||||||
interface Args extends React.HTMLAttributes<HTMLElement> {
|
interface Args extends React.HTMLAttributes<HTMLElement> {
|
||||||
target: string
|
target: string
|
||||||
showReturnButton?: boolean
|
showReturnButton?: boolean
|
||||||
openChatInfoDialog: (chat: Chat) => void
|
openChatInfoDialog: (chat: Chat) => void
|
||||||
onReturnButtonClicked?: () => void
|
onReturnButtonClicked?: () => void
|
||||||
|
openUserInfoDialog: (user: User | string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const markedInstance = new marked.Marked({
|
const markedInstance = new marked.Marked({
|
||||||
@@ -47,7 +49,7 @@ const markedInstance = new marked.Marked({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function ChatFragment({ target, showReturnButton, onReturnButtonClicked, openChatInfoDialog, ...props }: Args) {
|
export default function ChatFragment({ target, showReturnButton, onReturnButtonClicked, openChatInfoDialog, openUserInfoDialog, ...props }: Args) {
|
||||||
const [messagesList, setMessagesList] = React.useState([] as Message[])
|
const [messagesList, setMessagesList] = React.useState([] as Message[])
|
||||||
const [chatInfo, setChatInfo] = React.useState({
|
const [chatInfo, setChatInfo] = React.useState({
|
||||||
title: '加載中...'
|
title: '加載中...'
|
||||||
@@ -305,7 +307,8 @@ export default function ChatFragment({ target, showReturnButton, onReturnButtonC
|
|||||||
key={msg.id}
|
key={msg.id}
|
||||||
slot="trigger"
|
slot="trigger"
|
||||||
id={`chat_${target}_message_${msg.id}`}
|
id={`chat_${target}_message_${msg.id}`}
|
||||||
userId={msg.user_id} />
|
userId={msg.user_id}
|
||||||
|
openUserInfoDialog={openUserInfoDialog} />
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -8,18 +8,19 @@ import copyToClipboard from "../copyToClipboard.ts"
|
|||||||
import useAsyncEffect from "../useAsyncEffect.ts"
|
import useAsyncEffect from "../useAsyncEffect.ts"
|
||||||
import useEventListener from "../useEventListener.ts"
|
import useEventListener from "../useEventListener.ts"
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import useEventListener from "../useEventListener.ts"
|
|
||||||
import isMobileUI from "../isMobileUI.ts"
|
import isMobileUI from "../isMobileUI.ts"
|
||||||
import ReactJson from 'react-json-view'
|
import ReactJson from 'react-json-view'
|
||||||
|
import User from "../../api/client_data/User.ts"
|
||||||
|
|
||||||
interface Args extends React.HTMLAttributes<HTMLElement> {
|
interface Args extends React.HTMLAttributes<HTMLElement> {
|
||||||
userId: string
|
userId: string
|
||||||
rawData: string
|
rawData: string
|
||||||
renderHTML: string
|
renderHTML: string
|
||||||
message: Data_Message
|
message: Data_Message
|
||||||
|
openUserInfoDialog: (user: User | string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Message({ userId, rawData, renderHTML, message, ...props }: Args) {
|
export default function Message({ userId, rawData, renderHTML, message, openUserInfoDialog, ...props }: Args) {
|
||||||
const isAtRight = Client.myUserProfile?.id == userId
|
const isAtRight = Client.myUserProfile?.id == userId
|
||||||
|
|
||||||
const [nickName, setNickName] = React.useState("")
|
const [nickName, setNickName] = React.useState("")
|
||||||
@@ -87,7 +88,8 @@ export default function Message({ userId, rawData, renderHTML, message, ...props
|
|||||||
width: "43px",
|
width: "43px",
|
||||||
height: "43px",
|
height: "43px",
|
||||||
margin: "11px"
|
margin: "11px"
|
||||||
}} />
|
}}
|
||||||
|
onClick={() => openUserInfoDialog(userId)} />
|
||||||
{
|
{
|
||||||
// 发送者昵称(右)
|
// 发送者昵称(右)
|
||||||
!isAtRight && <span
|
!isAtRight && <span
|
||||||
@@ -128,7 +130,7 @@ export default function Message({ userId, rawData, renderHTML, message, ...props
|
|||||||
}}>
|
}}>
|
||||||
<mdui-menu-item icon="content_copy" onClick={() => copyToClipboard($(dropDownRef.current as HTMLElement).find('#msg').text().trim())}>複製文字</mdui-menu-item>
|
<mdui-menu-item icon="content_copy" onClick={() => copyToClipboard($(dropDownRef.current as HTMLElement).find('#msg').text().trim())}>複製文字</mdui-menu-item>
|
||||||
<mdui-menu-item icon="content_copy" onClick={() => copyToClipboard(rawData)}>複製原文</mdui-menu-item>
|
<mdui-menu-item icon="content_copy" onClick={() => copyToClipboard(rawData)}>複製原文</mdui-menu-item>
|
||||||
<mdui-menu-item icon="info" onClick={() => messageJsonDialogRef.current.open = true}>查看詳情</mdui-menu-item>
|
<mdui-menu-item icon="info" onClick={() => messageJsonDialogRef.current!.open = true}>查看詳情</mdui-menu-item>
|
||||||
</mdui-menu>
|
</mdui-menu>
|
||||||
</mdui-dropdown>
|
</mdui-dropdown>
|
||||||
</mdui-card>
|
</mdui-card>
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ export default function MyProfileDialog({
|
|||||||
myProfileDialogRef,
|
myProfileDialogRef,
|
||||||
user
|
user
|
||||||
}: Refs) {
|
}: Refs) {
|
||||||
const isMySelf = Client.myUserProfile?.id == user?.id
|
|
||||||
|
|
||||||
const editAvatarButtonRef = React.useRef<HTMLElement>(null)
|
const editAvatarButtonRef = React.useRef<HTMLElement>(null)
|
||||||
const chooseAvatarFileRef = React.useRef<HTMLInputElement>(null)
|
const chooseAvatarFileRef = React.useRef<HTMLInputElement>(null)
|
||||||
useEventListener(editAvatarButtonRef, 'click', () => chooseAvatarFileRef.current!.click())
|
useEventListener(editAvatarButtonRef, 'click', () => chooseAvatarFileRef.current!.click())
|
||||||
|
|||||||
58
client/ui/dialog/UserProfileDialog.tsx
Normal file
58
client/ui/dialog/UserProfileDialog.tsx
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import * as React from 'react'
|
||||||
|
import { Button, Dialog, TextField, dialog } from "mdui"
|
||||||
|
import useEventListener from "../useEventListener.ts"
|
||||||
|
import { checkApiSuccessOrSncakbar, snackbar } from "../snackbar.ts"
|
||||||
|
import Client from "../../api/Client.ts"
|
||||||
|
|
||||||
|
import * as CryptoJS from 'crypto-js'
|
||||||
|
import data from "../../Data.ts"
|
||||||
|
import Avatar from "../Avatar.tsx"
|
||||||
|
import User from "../../api/client_data/User.ts"
|
||||||
|
|
||||||
|
interface Refs {
|
||||||
|
userProfileDialogRef: React.MutableRefObject<Dialog>
|
||||||
|
openChatFragment: (id: string) => void
|
||||||
|
user: User
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function UserProfileDialog({
|
||||||
|
userProfileDialogRef,
|
||||||
|
openChatFragment,
|
||||||
|
user
|
||||||
|
}: Refs) {
|
||||||
|
return (
|
||||||
|
<mdui-dialog close-on-overlay-click close-on-esc ref={userProfileDialogRef}>
|
||||||
|
<div style={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}>
|
||||||
|
<Avatar src={user?.avatar} text={user?.nickname} style={{
|
||||||
|
width: '50px',
|
||||||
|
height: '50px',
|
||||||
|
}} />
|
||||||
|
<span style={{
|
||||||
|
marginLeft: "15px",
|
||||||
|
fontSize: '16.5px',
|
||||||
|
}}>{user?.nickname}</span>
|
||||||
|
</div>
|
||||||
|
<mdui-divider style={{
|
||||||
|
marginTop: "10px",
|
||||||
|
}}></mdui-divider>
|
||||||
|
|
||||||
|
<mdui-list>
|
||||||
|
{/* <mdui-list-item icon="edit" rounded>设置备注</mdui-list-item> */}
|
||||||
|
<mdui-list-item icon="chat" rounded onClick={async () => {
|
||||||
|
const re = await Client.invoke("Chat.getIdForPrivate", {
|
||||||
|
token: data.access_token,
|
||||||
|
target: user.id,
|
||||||
|
})
|
||||||
|
if (re.code != 200)
|
||||||
|
return checkApiSuccessOrSncakbar(re, '获取对话失败')
|
||||||
|
|
||||||
|
openChatFragment(re.data!.chat_id as string)
|
||||||
|
userProfileDialogRef.current!.open = false
|
||||||
|
}}>对话</mdui-list-item>
|
||||||
|
</mdui-list>
|
||||||
|
</mdui-dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user