@@ -139,6 +139,7 @@ function MessageList({
139139 room : string ;
140140} ) {
141141 const [ messages , setMessages ] = useState ( data ) ;
142+ const { idToken : Authorization } = useAuthContext ( ) ;
142143
143144 useEffect ( ( ) => {
144145 handlers . onCreate = ( message ) => {
@@ -188,12 +189,62 @@ function MessageList({
188189 bottomRef . current ?. scrollIntoView ( { behavior : "auto" } ) ;
189190 } , [ messages ] ) ;
190191
192+ const [ selectedMessageId , setSelectedMessageId ] = useState < string | null > ( null ) ;
193+ const [ showConfirmModal , setShowConfirmModal ] = useState ( false ) ;
194+ const [ deletingMessageId , setDeletingMessageId ] = useState < string | null > ( null ) ;
195+ const longPressTimer = useRef < NodeJS . Timer | null > ( null ) ;
196+
197+ const handleRequestDelete = ( id : string ) => {
198+ setDeletingMessageId ( id ) ;
199+ setShowConfirmModal ( true ) ;
200+ } ;
201+
202+ const handleDelete = async ( ) => {
203+ if ( ! deletingMessageId ) return ;
204+
205+ try {
206+ await client . chat . messages [ ":message" ] [ ":room" ] . $delete ( {
207+ header : { Authorization } ,
208+ param : { message : deletingMessageId , room : room } ,
209+ } ) ;
210+
211+ setMessages ( ( prev ) => prev . filter ( ( m ) => m . id !== deletingMessageId ) ) ;
212+
213+ setDeletingMessageId ( null ) ;
214+ setShowConfirmModal ( false ) ;
215+ } catch ( error ) {
216+ alert ( "削除に失敗しました" ) ;
217+ }
218+ } ;
219+
220+ const handleEdit = ( id : string ) => {
221+ console . log ( "編集" , id ) ;
222+ setSelectedMessageId ( null ) ;
223+ } ;
224+
225+ const handleLongPressStart = ( id : string ) => {
226+ longPressTimer . current = setTimeout ( ( ) => {
227+ setSelectedMessageId ( id ) ;
228+ } , 600 ) ; // 600ms 長押しで発動
229+ } ;
230+
231+ const handleLongPressEnd = ( ) => {
232+ if ( longPressTimer . current ) clearTimeout ( longPressTimer . current ) ;
233+ } ;
234+
191235 return (
192236 < ul className = "mx-3 mt-[56px] mb-[76px] grow overflow-y-scroll sm:pb-0" id = "scroll-bottom" >
193237 { messages . map ( ( m ) => (
194238 // TODO: handle pictures
195239 < li key = { m . id } >
196- < div className = { `chat ${ m . senderId === me . id ? "chat-end" : "chat-start" } ` } >
240+ < div
241+ className = { `chat ${ m . senderId === me . id ? "chat-end" : "chat-start" } ` }
242+ onTouchStart = { ( ) => handleLongPressStart ( m . id ) }
243+ onTouchEnd = { handleLongPressEnd }
244+ onMouseDown = { ( ) => handleLongPressStart ( m . id ) }
245+ onMouseUp = { handleLongPressEnd }
246+ onMouseLeave = { handleLongPressEnd }
247+ >
197248 < div className = "chat-header" >
198249 < time className = "text-xs opacity-50" > { m . createdAt . toLocaleString ( ) } </ time >
199250 </ div >
@@ -204,8 +255,42 @@ function MessageList({
204255 < br />
205256 </ div >
206257 ) ) }
258+
259+ { selectedMessageId === m . id && (
260+ < div className = "absolute top-0 right-0 z-10 flex gap-1 rounded border bg-white p-1 shadow" >
261+ < button
262+ type = "button"
263+ className = "text-blue-600 text-sm hover:underline"
264+ onClick = { ( ) => handleEdit ( m . id ) }
265+ >
266+ 編集
267+ </ button >
268+ < button type = "button" onClick = { ( ) => handleRequestDelete ( m . id ) } className = "text-red-600" >
269+ 削除
270+ </ button >
271+ </ div >
272+ ) }
207273 </ div >
208274 { /* <div className="chat-footer opacity-50">Seen</div> */ }
275+ { showConfirmModal && (
276+ < div className = "fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-40" >
277+ < div className = "rounded-lg bg-white p-4 shadow-lg" >
278+ < p className = "mb-4" > このメッセージを削除しますか?</ p >
279+ < div className = "flex justify-end gap-3" >
280+ < button
281+ type = "button"
282+ className = "rounded bg-gray-300 px-4 py-2"
283+ onClick = { ( ) => setShowConfirmModal ( false ) }
284+ >
285+ キャンセル
286+ </ button >
287+ < button type = "button" className = "rounded bg-red-500 px-4 py-2 text-white" onClick = { handleDelete } >
288+ 削除
289+ </ button >
290+ </ div >
291+ </ div >
292+ </ div >
293+ ) }
209294 </ div >
210295 </ li >
211296 ) ) }
0 commit comments