1- import React , { useContext , useMemo } from "react" ;
1+ import React , { useContext , useEffect , useMemo , useState } from "react" ;
22import UserAvatar from "../../../../components/user-avatar" ;
33import { classNameObject } from "../../../../helper/class-name-object" ;
44import {
@@ -8,15 +8,19 @@ import {
88 useGetPublicKeysQuery ,
99 useKeysQuery ,
1010 useLastMessageQuery ,
11+ usePinContact ,
1112 useUnreadCountQuery
1213} from "@ecency/ns-query" ;
1314import { _t } from "../../../../i18n" ;
1415import Tooltip from "../../../../components/tooltip" ;
15- import { informationOutlineSvg } from "../../../../img/svg" ;
16+ import { informationOutlineSvg , pinSvg } from "../../../../img/svg" ;
1617import { Button } from "@ui/button" ;
17- import { Link } from "react-router-dom" ;
1818import { Badge } from "@ui/badge" ;
1919import { ChatSidebarSavedMessagesAvatar } from "./chat-sidebar-saved-messages-avatar" ;
20+ import { Dropdown , DropdownItemWithIcon , DropdownMenu } from "@ui/dropdown" ;
21+ import { error , success } from "../../../../components/feedback" ;
22+ import { history } from "../../../../store" ;
23+ import useDebounce from "react-use/lib/useDebounce" ;
2024
2125interface Props {
2226 contact : DirectContact ;
@@ -28,6 +32,9 @@ export function ChatSidebarDirectContact({ contact, onClick, isLink = true }: Pr
2832 const { receiverPubKey, setReceiverPubKey, revealPrivateKey, setRevealPrivateKey } =
2933 useContext ( ChatContext ) ;
3034
35+ const [ holdStarted , setHoldStarted ] = useState ( false ) ;
36+ const [ showContextMenu , setShowContextMenu ] = useState ( false ) ;
37+
3138 const { publicKey } = useKeysQuery ( ) ;
3239 const { data : contactKeys , isLoading : isContactKeysLoading } = useGetPublicKeysQuery (
3340 contact . name
@@ -43,6 +50,36 @@ export function ChatSidebarDirectContact({ contact, onClick, isLink = true }: Pr
4350 ) ;
4451 const isActiveUser = useMemo ( ( ) => contact . pubkey === publicKey , [ publicKey , contact ] ) ;
4552
53+ const {
54+ mutateAsync : pinContact ,
55+ isLoading : isContactPinning ,
56+ isSuccess : isPinned ,
57+ isError : isPinFailed
58+ } = usePinContact ( ) ;
59+
60+ useEffect ( ( ) => {
61+ if ( isPinned ) {
62+ success ( _t ( "g.success" ) ) ;
63+ }
64+ } , [ isPinned ] ) ;
65+
66+ useEffect ( ( ) => {
67+ if ( isPinFailed ) {
68+ error ( _t ( "g.error" ) ) ;
69+ }
70+ } , [ isPinFailed ] ) ;
71+
72+ useDebounce (
73+ ( ) => {
74+ if ( holdStarted ) {
75+ setHoldStarted ( false ) ;
76+ setShowContextMenu ( true ) ;
77+ }
78+ } ,
79+ 500 ,
80+ [ holdStarted ]
81+ ) ;
82+
4683 const content = (
4784 < >
4885 < div
@@ -75,8 +112,9 @@ export function ChatSidebarDirectContact({ contact, onClick, isLink = true }: Pr
75112 </ Tooltip >
76113 </ div >
77114 ) }
78- < div className = "font-semibold truncate dark:text-white" >
115+ < div className = "font-semibold truncate dark:text-white flex items-center gap-2 " >
79116 { isActiveUser ? _t ( "chat.saved-messages" ) : contact . name }
117+ { contact . pinned && < span className = "rotate-45 opacity-25 w-3.5" > { pinSvg } </ span > }
80118 </ div >
81119 </ div >
82120 < div className = "text-xs text-gray-500" > { lastMessageDate } </ div >
@@ -94,40 +132,74 @@ export function ChatSidebarDirectContact({ contact, onClick, isLink = true }: Pr
94132 </ >
95133 ) ;
96134
97- return isLink ? (
98- < Link
99- to = "/chats"
100- className = { classNameObject ( {
101- "flex items-center text-dark-200 gap-3 p-3 border-b border-[--border-color] last:border-0 hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer" :
102- true ,
103- "bg-gray-100 dark:bg-gray-800" : receiverPubKey === contact . pubkey
104- } ) }
105- onClick = { ( ) => {
106- setReceiverPubKey ( contact . pubkey ) ;
107- if ( revealPrivateKey ) {
108- setRevealPrivateKey ( false ) ;
109- }
110- onClick ?.( ) ;
111- } }
112- >
113- { content }
114- </ Link >
115- ) : (
116- < div
117- className = { classNameObject ( {
118- "flex items-center text-dark-200 gap-3 p-3 border-b border-[--border-color] last:border-0 hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer" :
119- true ,
120- "bg-gray-100 dark:bg-gray-800" : receiverPubKey === contact . pubkey
121- } ) }
122- onClick = { ( ) => {
123- setReceiverPubKey ( contact . pubkey ) ;
124- if ( revealPrivateKey ) {
125- setRevealPrivateKey ( false ) ;
126- }
127- onClick ?.( ) ;
128- } }
135+ return (
136+ < Dropdown
137+ closeOnClickOutside = { true }
138+ show = { showContextMenu }
139+ setShow = { ( v ) => setShowContextMenu ( v ) }
129140 >
130- { content }
131- </ div >
141+ < div
142+ onMouseDown = { ( ) => setHoldStarted ( true ) }
143+ onMouseUp = { ( ) => {
144+ setHoldStarted ( false ) ;
145+
146+ setTimeout ( ( ) => {
147+ if ( ! holdStarted ) {
148+ return ;
149+ }
150+
151+ if ( isLink ) {
152+ history ?. push ( "/chats" ) ;
153+ }
154+
155+ setReceiverPubKey ( contact . pubkey ) ;
156+ if ( revealPrivateKey ) {
157+ setRevealPrivateKey ( false ) ;
158+ }
159+ onClick ?.( ) ;
160+ } , 500 ) ;
161+ } }
162+ onTouchStart = { ( ) => setHoldStarted ( true ) }
163+ onTouchEnd = { ( ) => {
164+ setHoldStarted ( false ) ;
165+ console . log ( "touch ended" ) ;
166+
167+ setTimeout ( ( ) => {
168+ if ( ! holdStarted ) {
169+ return ;
170+ }
171+
172+ if ( isLink ) {
173+ history ?. push ( "/chats" ) ;
174+ }
175+
176+ setReceiverPubKey ( contact . pubkey ) ;
177+ if ( revealPrivateKey ) {
178+ setRevealPrivateKey ( false ) ;
179+ }
180+ onClick ?.( ) ;
181+ } , 500 ) ;
182+ } }
183+ onContextMenu = { ( e ) => {
184+ e . stopPropagation ( ) ;
185+ e . preventDefault ( ) ;
186+ setShowContextMenu ( true ) ;
187+ } }
188+ className = { classNameObject ( {
189+ "flex items-center text-dark-200 gap-3 p-3 border-b border-[--border-color] last:border-0 hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer" :
190+ true ,
191+ "bg-gray-100 dark:bg-gray-800" : receiverPubKey === contact . pubkey
192+ } ) }
193+ >
194+ { content }
195+ </ div >
196+ < DropdownMenu className = "top-[70%]" >
197+ < DropdownItemWithIcon
198+ icon = { pinSvg }
199+ label = { contact . pinned ? _t ( "chat.unpin" ) : _t ( "chat.pin" ) }
200+ onClick = { ( ) => pinContact ( { contact, pinned : ! contact . pinned } ) }
201+ />
202+ </ DropdownMenu >
203+ </ Dropdown >
132204 ) ;
133205}
0 commit comments