1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
import { useEffect, useRef, useState } from 'react';
import Avatar from './Avatar';
import { UserLink } from './UserInfo';
import Button from './Button';
import defaultAvatar from '../assets/av-96.png';
import MessageInput from './MessageInput';
import { fetchUserUri } from '../api';
import { chatItemStyle } from './helpers/BubbleStyle';
import { format, embedUrls } from '../utils/embed';
let isMounted;
/**
* @param {{
msg: import('../api').Message,
draft: string,
visitor: import('../api').User,
active: number,
setActive: function,
onStartEditing: function,
postComment: function
}} props
*/
export default function Comment({ msg, draft, visitor, active, setActive, onStartEditing, postComment }) {
const embedRef = useRef();
const msgRef = useRef();
const [author, setAuthor] = useState(msg.user);
useEffect(() => {
if (msgRef.current) {
embedUrls(msgRef.current.querySelectorAll('a'), embedRef.current);
if (!embedRef.current.hasChildNodes()) {
embedRef.current.style.display = 'none';
}
}
}, []);
const userRef = useRef(author);
useEffect(() => {
isMounted = true;
if (userRef.current.uri) {
fetchUserUri(userRef.current.uri).then(remote_user => {
if (isMounted) {
setAuthor({
uid: 0,
uname: remote_user.preferredUsername,
avatar: remote_user.icon && remote_user.icon.url,
uri: author.uri
});
}
}).catch(e => {
setAuthor({
uid: 0,
uname: userRef.current.uri,
uri: author.uri,
avatar: defaultAvatar
});
});
}
return () => {
isMounted = false;
};
}, [author.uri, msg.user]);
return (
<div style={chatItemStyle(visitor, msg)}>
<div className="msg-header">
<Avatar user={author} link={author.uri}>
<div className="msg-ts">
{msg.replyto > 0 &&
(
<UserLink user={msg.to} />
)}
</div>
</Avatar>
</div>
{
msg.body &&
<div className={visitor.uid === msg.user.uid ? 'msg-bubble msg-bubble-my' : 'msg-bubble'}>
<div ref={msgRef}>
<p dangerouslySetInnerHTML={{ __html: format(msg.body, msg.mid.toString(), (msg.tags || []).indexOf('code') >= 0) }} />
</div>
</div>
}
{
msg.photo &&
<div className="msg-media">
<a href={`//i.juick.com/p/${msg.mid}-${msg.rid}.${msg.attach}`} data-fname={`${msg.mid}-${msg.rid}.${msg.attach}`}>
<img src={`//i.juick.com/photos-512/${msg.mid}-${msg.rid}.${msg.attach}`} alt="" />
</a>
</div>
}
<div className="embedContainer" ref={embedRef} />
{
active === msg.rid && <MessageInput data={msg} text={draft || ''} onSend={postComment}>Write a comment...</MessageInput>
}
<div className="msg-links">
{
visitor.uid > 0 ? (
<>
{active === msg.rid || <span style={linkStyle} onClick={() => setActive(msg.rid)}>Reply</span>}
{
visitor.uid == msg.user.uid &&
<>
<span> · </span>
<span style={linkStyle} onClick={() => onStartEditing(msg)}>Edit</span>
</>
}
</>
) : (
<>
<span> · </span>{active === msg.rid || <Button>Reply</Button>}
</>
)
}
</div>
</div>
);
}
/**
* @type React.CSSProperties
*/
const linkStyle = {
cursor: 'pointer'
};
|