import { useEffect, useState, useCallback } from 'react'
import { useLocation, useParams } from 'react-router-dom'
import Comment from './Comment'
import Message from './Message'
import MessageInput from './MessageInput'
import Spinner from './Spinner'
import { getMessages, comment, update, post } from '../api'
import { useVisitor } from './VisitorContext'
import { Helmet } from 'react-helmet-async'
/**
* @type { import('../api').Message }
*/
const emptyMessage = {}
/**
* Thread component
* @param {import('react').PropsWithChildren<{}>} props
*/
export default function Thread(props) {
const location = useLocation()
const params = useParams()
const [message, setMessage] = useState((location.state || {}).data || {})
const [replies, setReplies] = useState([])
const [loading, setLoading] = useState(false)
const [active, setActive] = useState(0)
const [editing, setEditing] = useState(emptyMessage)
const [visitor] = useVisitor()
const [hash] = useState(visitor.hash)
const { mid } = params
let loadReplies = useCallback(() => {
document.body.scrollTop = 0
document.documentElement.scrollTop = 0
setReplies([])
setLoading(true)
let params = {
mid: mid
}
params.hash = hash
getMessages('/api/thread', params)
.then(response => {
let updatedMessage = response.data.shift()
if (!message.mid) {
setMessage(updatedMessage)
}
setReplies(response.data)
setLoading(false)
setActive(0)
}
).catch(ex => {
console.log(ex)
})
}, [hash, message.mid, mid])
let postComment = async ({ body, attach }) => {
try {
let res = editing.rid ? await update(mid, editing.rid, body)
: await comment(mid, active, body, attach)
let result = res.status == 200
if (result) {
setEditing(emptyMessage)
}
return result
} catch (e) {
console.error(e)
}
return false
}
let startEditing = (reply) => {
setActive(reply.to.rid || 0)
setEditing(reply)
}
useEffect(() => {
setActive(0)
loadReplies()
}, [loadReplies])
useEffect(() => {
let onReply = (json) => {
const msg = JSON.parse(json.data)
if (msg.mid == message.mid) {
setReplies(oldReplies => {
return [...oldReplies, msg]
})
setActive(prev => {
return prev + 1
})
}
}
if (props.connection.addEventListener && message.mid) {
props.connection.addEventListener('msg', onReply)
}
return () => {
if (props.connection.removeEventListener && message.mid) {
props.connection.removeEventListener('msg', onReply)
}
}
}, [props.connection, message.mid])
const loaders = Math.min(message.replies || 0, 10)
const pageTitle = `${params.user} ${message && message.tags || 'thread'}`
/** @type { import('./Message').ToggleSubscriptionCallback } */
const handleSubsciptionToggle = (message) => {
if (message.subscribed) {
if (confirm('Unsubscribe?')) {
post(`U #${message.mid}`).then((response) => {
if (response.status === 200) {
setMessage({...message, subscribed: false})
}
}).catch(console.error)
}
} else {
if (confirm('Subscribe?')) {
post(`S #${message.mid}`).then((response) => {
if (response.status === 200) {
setMessage({...message, subscribed: true})
}
}).catch(console.error)
}
}
}
return (
<>