Skip to content

Commit

Permalink
1. contact id
Browse files Browse the repository at this point in the history
  • Loading branch information
JingDeZhe committed Jun 7, 2024
1 parent 7ec667c commit c08cb5e
Show file tree
Hide file tree
Showing 16 changed files with 332 additions and 168 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"react-markdown": "^9.0.1",
"react-router-dom": "^6.23.1",
"react-split": "^2.0.14",
"react-toastify": "^10.0.5",
"zustand": "^4.5.2"
},
"devDependencies": {
Expand Down
21 changes: 21 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions src/main.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
import 'virtual:uno.css'
import 'overlayscrollbars/overlayscrollbars.css'
import 'react-toastify/dist/ReactToastify.css'
import './styles/main.scss'

import React from 'react'
import ReactDOM from 'react-dom/client'
import { RouterProvider } from 'react-router-dom'
import { router } from './router/main'
import { Slide, ToastContainer } from 'react-toastify'

ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<RouterProvider router={router}></RouterProvider>
<ToastContainer
position="top-center"
autoClose={500}
hideProgressBar
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable={false}
pauseOnHover={false}
theme="light"
transition={Slide}
></ToastContainer>
</React.StrictMode>
)
36 changes: 20 additions & 16 deletions src/pages/chat/AddressBook.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useLoaderData, useNavigate, useParams } from 'react-router-dom'
import { useLoaderData, useNavigate } from 'react-router-dom'
import { server } from './db/server'
import { AddressMenu } from './AddressMenu'
import { sessionDel, sessionGet, sessionSet } from '@/utils/main'
Expand All @@ -10,44 +10,48 @@ export const addressBookLoader = async ({ params }) => {
}

export const AddressBook = () => {
const { userId } = useParams()
const navigate = useNavigate()
const contacts = useLoaderData()
const LAST_TARGET_ID = 'LAST_ADDRESS_TARGET_ID'
const getLastTargetId = () => {
const id = sessionGet(LAST_TARGET_ID)

const LAST_CONTACT_ID = 'LAST_ADDRESS_CONTACT_ID'
const getLastContactId = () => {
const id = sessionGet(LAST_CONTACT_ID)
if (id) {
if (contacts.find((d) => d.id === id)) return id
sessionDel(LAST_TARGET_ID)
sessionDel(LAST_CONTACT_ID)
}
return ''
}
const [targetId, setTargetId] = useState(getLastTargetId)
const [contactId, setContactId] = useState(getLastContactId)
const handleSelectItem = (id) => {
sessionSet(LAST_TARGET_ID, id)
setTargetId(id)
sessionSet(LAST_CONTACT_ID, id)
setContactId(id)
}

const handleDeleteContact = () => {
setTargetId('')
refreshPage()
const handleDeleteContact = (id) => {
server.deleteRelation(id).then(() => {
sessionSet(LAST_CONTACT_ID, '')
setContactId('')
refreshPage()
})
}

const navigate = useNavigate()
const refreshPage = () => {
navigate('.', { replace: true })
}
return (
<MainLayout>
<AddressMenu
contacts={contacts}
targetId={targetId}
contactId={contactId}
onSelect={handleSelectItem}
onDelete={handleDeleteContact}
onRefresh={refreshPage}
></AddressMenu>
<AddressContent
fromId={userId}
targetId={targetId}
contactId={contactId}
onDelete={handleDeleteContact}
onRefresh={refreshPage}
></AddressContent>
</MainLayout>
)
Expand Down
39 changes: 26 additions & 13 deletions src/pages/chat/AddressContent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,38 @@ import { Button, Descriptions, Input, Popconfirm, Space } from 'antd'
import { EmptyInfo } from './EmptyInfo'
import { server } from './db/server'
import { useNavigate } from 'react-router-dom'
import { EditRelation } from './EditRelation'

export const AddressContent = ({ fromId, targetId, onDelete }) => {
const [contact, setContact] = useState(null)
export const AddressContent = ({ contactId, onDelete, onRefresh }) => {
const navigate = useNavigate()
const [contact, setContact] = useState()
const [editRelationVisible, setEditRelationVisible] = useState(false)

useEffect(() => {
if (!targetId) return setContact(null)
server.getContact(fromId, targetId).then(setContact)
}, [fromId, targetId])
server.getContact(contactId).then(setContact)
}, [contactId])

const handleDeleleContact = () => {
server.deleteContact(contact.id).then(() => {
onDelete(targetId)
})
onDelete(contact.id)
}
const handleEditContact = () => {
setEditRelationVisible(true)
}
const handleEditContact = () => {}
const handleChat = () => {
navigate('../talk', { state: { targetId } })
navigate('../talk', { state: { contactId: contactId } })
}
const handleEditRelationClosed = () => {
setEditRelationVisible(false)
server.getContact(contactId).then(setContact)
onRefresh()
}

return (
<div className="address-content">
{contact ? (
<>
<div className="flex gap-3">
<img src={contact.avatar} className="avatar xl" />
<img src={contact.avatar} className="chat-avatar xl" />
<Descriptions title={contact.alias} column={1}>
<Descriptions.Item label="Nickname">
{contact.nickname}
Expand All @@ -39,7 +45,7 @@ export const AddressContent = ({ fromId, targetId, onDelete }) => {
</div>
<div className="p-2">
<p className="font-bold">Character</p>
<div className="text-sm">{contact.character}</div>
<div className="text-sm">{contact.character || '无'}</div>
</div>
<Space className="justify-end mt-5">
<Popconfirm
Expand All @@ -51,9 +57,16 @@ export const AddressContent = ({ fromId, targetId, onDelete }) => {
>
<Button danger>Delete</Button>
</Popconfirm>
{/* <Button onClick={handleEditContact}>Edit</Button> */}
<Button onClick={handleEditContact}>Edit</Button>
<Button onClick={handleChat}>Chat</Button>
</Space>

{editRelationVisible && (
<EditRelation
contactId={contactId}
onClose={handleEditRelationClosed}
></EditRelation>
)}
</>
) : (
<EmptyInfo>
Expand Down
44 changes: 31 additions & 13 deletions src/pages/chat/AddressMenu.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { Button, Input } from 'antd'
import { Button, Input, Modal } from 'antd'
import PinyinEngine from 'pinyin-engine'
import { Menu, Item, useContextMenu } from 'react-contexify'
import { useNavigate } from 'react-router-dom'
import { useNavigate, useParams } from 'react-router-dom'
import { RelationManage } from './RelationManage'

export const AddressMenu = ({ contacts, targetId, onSelect, onDelete }) => {
export const AddressMenu = ({
contacts,
contactId,
onSelect,
onDelete,
onRefresh,
}) => {
const { userId } = useParams()
const [queryText, setQueryText] = useState('')
const [relationManageVisible, setRelationManageVisible] = useState(false)
const navigate = useNavigate()

const engine = useMemo(() => {
Expand All @@ -19,25 +28,24 @@ export const AddressMenu = ({ contacts, targetId, onSelect, onDelete }) => {
const { show: showContactMenu } = useContextMenu({
id: CONTACT_MENU,
})
let _menuTargetId = ''
let _menuId = ''
const handleContactMenu = (e) => {
_menuTargetId = e.currentTarget.dataset.id
_menuId = e.currentTarget.dataset.id
showContactMenu({ event: e })
}
const handleContactMenuClick = ({ id }) => {
if (id === 'chat') {
onSelect(_menuTargetId)
navigate('../talk', { state: { targetId: _menuTargetId } })
onSelect(_menuId)
navigate('../talk', { state: { contactId: _menuId } })
} else if (id === 'delete') {
onDelete(_menuTargetId)
onDelete(_menuId)
}
}

return (
<div className="address-menu col-ctn border-r">
<div className="address-menu-search v-center">
<Input value={queryText} onInput={handleQuery}></Input>
<Button>
<Button onClick={() => setRelationManageVisible(true)}>
<i className="i-tabler-user-plus"></i>
</Button>
</div>
Expand All @@ -50,15 +58,15 @@ export const AddressMenu = ({ contacts, targetId, onSelect, onDelete }) => {
return (
<div
className={cls('avatar-info', {
active: targetId === d.id,
active: contactId === d.id,
})}
key={d.id}
onClick={() => onSelect(d.id)}
onContextMenu={handleContactMenu}
data-id={d.id}
>
<img className="avatar" src={d.avatar} />
<span className="flex-1">{d.nickname}</span>
<img className="chat-avatar" src={d.avatar} />
<span className="flex-1">{d.alias}</span>
</div>
)
})}
Expand All @@ -72,6 +80,16 @@ export const AddressMenu = ({ contacts, targetId, onSelect, onDelete }) => {
Delete
</Item>
</Menu>

<Modal
title="Add contact"
open={relationManageVisible}
onCancel={() => setRelationManageVisible(false)}
onClose={onRefresh}
footer={null}
>
<RelationManage fromId={userId}></RelationManage>
</Modal>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,31 @@
import { localGet, localSet } from '@/utils/main'
import { server } from './db/server'
import { Button, Input, message } from 'antd'
import { Button, Input } from 'antd'
import { toast } from 'react-toastify'
import Draggable from 'react-draggable'

export const EditCharacter = ({ fromId, targetId, onClose }) => {
const [character, setCharacter] = useState(null)
const [desc, setDesc] = useState()
export const EditRelation = ({ contactId, onClose }) => {
const [relation, setRelation] = useState(null)
const nodeRef = useRef(null)

useEffect(() => {
server.getCharacter(fromId, targetId).then((d) => {
setCharacter(d)
setDesc(d.character || '')
})
}, [fromId, targetId])
server.getRelation(contactId).then(setRelation)
}, [contactId])

const handleConfirm = () => {
server.setCharacter(character.id, desc).then(() => {
message.success('Successful')
server.setRelation(relation.id, relation).then(() => {
onClose()
toast.success('Successful')
})
}

const EDIT_CHARACTER_POS = 'EDIT_CHARACTER_POS'
const defaultPosition = localGet(EDIT_CHARACTER_POS) || { x: 100, y: 100 }
const EDIT_RELATION_POS = 'EDIT_RELATION_POS'
const defaultPosition = localGet(EDIT_RELATION_POS) || { x: 100, y: 100 }
const handleStop = (e, data) => {
localSet(EDIT_CHARACTER_POS, { x: data.x, y: data.y })
localSet(EDIT_RELATION_POS, { x: data.x, y: data.y })
}

if (!character) return <></>
if (!relation) return <></>

return (
<Draggable
Expand All @@ -40,12 +38,14 @@ export const EditCharacter = ({ fromId, targetId, onClose }) => {
<div className="edit-character" ref={nodeRef}>
<i className="close-btn i-tabler-x" onClick={onClose}></i>
<div className="mb-3 v-center p-2 handle">
<span>{character.alias}</span>
<span>{relation.alias}</span>
</div>
<div className="p-2">
<Input.TextArea
value={desc}
onInput={(e) => setDesc(e.target.value)}
value={relation.character}
onInput={(e) =>
setRelation({ ...relation, character: e.target.value })
}
rows={6}
></Input.TextArea>
<div className="mt-2 text-right space-x-2">
Expand Down
Loading

0 comments on commit c08cb5e

Please sign in to comment.