aboutsummaryrefslogtreecommitdiff
path: root/vnext/src/components/Message.js
blob: 6b0854a47a1f79a069c662e44e1c4f03afb6c51b (plain) (blame)
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
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import moment from 'moment';

import { UserType, MessageType } from './Types';
import Icon from './Icon';
import Avatar from './Avatar';

import { format } from '../utils/embed';

import './Message.css';

function Message({ data, visitor, children, ...rest }) {
    const isCode = (data.tags || []).indexOf('code') >= 0;
    return (
        <div className="msg-cont">
            <header className="h">
                <Avatar user={data.user}>
                    <div className="msg-ts">
                        <Link to={{ pathname: `/${data.user.uname}/${data.mid}`, state: { msg: data } }}>
                            <time dateTime={data.timestamp}
                                title={moment.utc(data.timestamp).local().format('lll')}>
                                {moment.utc(data.timestamp).fromNow()}
                            </time>
                        </Link>
                    </div>
                </Avatar>
                <TagsList user={data.user} data={data.tags || []} />
            </header>
            <div className="msg-txt">
                <MessageContainer isCode={isCode} data={{ __html: format(data.body, data.mid, isCode) }} />
            </div>
            {data.photo &&
                <p className="ir"><a href={`//i.juick.com/p/${data.mid}.${data.attach}`} data-fname={`${data.mid}.${data.attach}`}>
                    <img src={`//i.juick.com/photos-512/${data.mid}.${data.attach}`} alt="" /></a>
                </p>
            }
            <nav className="l">
                {visitor.uid === data.user.uid ? (
                    <a href={`/${data.user.uname}/${data.mid}`} className="a-like msg-button">
                        <span className="msg-button-icon">
                            <Icon name="ei-heart" size="s" />
                            {data.likes > 0 && (` ${data.likes}`)}
                        </span>
                        <span>&nbsp;Recommend</span>
                    </a>
                ) : visitor.uid > 0 ? (
                    <Link to={{ pathname: '/post', search: `?body=!+%23${data.mid}` }} className="a-like msg-button">
                        <span className="msg-button-icon">
                            <Icon name="ei-heart" size="s" />
                            {data.likes > 0 && (` ${data.likes}`)}
                        </span>
                        <span>&nbsp;Recommend</span>
                    </Link>
                ) : (
                            <a href="/login" className="a-login msg-button">
                                <span className="msg-button-icon">
                                    <Icon name="ei-heart" size="s" />
                                    {data.likes > 0 && (` ${data.likes}`)}
                                </span>
                                <span>&nbsp;Recommend</span>
                            </a>
                        )}
                {!data.ReadOnly | (visitor.uid === data.user.uid) && (
                    <>
                        <Link to={{ pathname: `/${data.user.uname}/${data.mid}`, state: { msg: data } }} className="a-comment msg-button">
                            <span className="msg-button-icon">
                                <Icon name="ei-comment" size="s" />
                                {data.replies > 0 &&
                                    (visitor.unread && visitor.unread.includes(data.mid) ? (
                                        <span className="badge">{data.replies}</span>
                                    ) : (
                                            `${data.replies}`
                                        ))
                                }
                            </span>
                            <span>&nbsp;Comment</span>
                        </Link>
                    </>
                )}
            </nav>
            {children}
        </div>
    );
}

export default React.memo(Message);

function MessageContainer({isCode, data}) {
    return isCode ? (<pre dangerouslySetInnerHTML={data} />) : (<p dangerouslySetInnerHTML={data} />);
}

function Tags({ data, user, ...rest }) {
    return data.length > 0 && (
        <div className="msg-tags">
            {
                data.map(tag => {
                    return (<Link key={tag} to={{ pathname: `/${user.uname}`, search: `?tag=${tag}` }} title={tag}>{tag}</Link>);
                }).reduce((prev, curr) => [prev, ', ', curr])
            }
        </div>
    );
}

const TagsList = React.memo(Tags);

Message.propTypes = {
    data: MessageType,
    visitor: UserType.isRequired,
    children: PropTypes.node
};

Tags.propTypes = {
    user: UserType.isRequired,
    data: PropTypes.array
};