aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src/pages/timeline/TimelinePostView.tsx
blob: bdd2e3efc00b7d47f7c795cd81ad67cb00285af4 (plain)
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
import { useState } from "react";
import classNames from "classnames";

import { getHttpTimelineClient, HttpTimelinePostInfo } from "@/http/timeline";

import { pushAlert } from "@/services/alert";

import { useClickOutside } from "@/utilities/hooks";

import UserAvatar from "@/views/common/user/UserAvatar";
import { useDialog } from "@/views/common/dialog";
import Card from "@/views/common/Card";
import FlatButton from "@/views/common/button/FlatButton";
import ConfirmDialog from "@/views/common/dialog/ConfirmDialog";
import TimelineLine from "./TimelineLine";
import TimelinePostContentView from "./TimelinePostContentView";
import IconButton from "@/views/common/button/IconButton";

import "./TimelinePostView.css";

export interface TimelinePostViewProps {
  post: HttpTimelinePostInfo;
  className?: string;
  onChanged: (post: HttpTimelinePostInfo) => void;
  onDeleted: () => void;
}

export function TimelinePostView(props: TimelinePostViewProps) {
  const { post, className, onDeleted } = props;

  const [operationMaskVisible, setOperationMaskVisible] =
    useState<boolean>(false);

  const { switchDialog, dialogPropsMap } = useDialog(["delete"], {
    onClose: {
      delete: () => {
        setOperationMaskVisible(false);
      },
    },
  });

  const [maskElement, setMaskElement] = useState<HTMLElement | null>(null);
  useClickOutside(maskElement, () => setOperationMaskVisible(false));

  return (
    <div
      id={`timeline-post-${post.id}`}
      className={classNames("timeline-post cru-primary", className)}
    >
      <TimelineLine center="node" />
      <Card className="timeline-post-card">
        {post.editable && (
          <IconButton
            icon="chevron-down"
            className="timeline-post-edit-button"
            onClick={(e) => {
              setOperationMaskVisible(true);
              e.stopPropagation();
            }}
          />
        )}
        <div className="timeline-post-header">
          <UserAvatar
            username={post.author.username}
            className="timeline-post-author-avatar"
          />
          <small className="timeline-post-author-nickname">
            {post.author.nickname}
          </small>
          <small className="timeline-post-time">
            {new Date(post.time).toLocaleTimeString()}
          </small>
        </div>
        <div className="timeline-post-content">
          <TimelinePostContentView post={post} />
        </div>
        {operationMaskVisible ? (
          <div
            ref={setMaskElement}
            className="timeline-post-options-mask"
            onClick={() => {
              setOperationMaskVisible(false);
            }}
          >
            <FlatButton
              text="changeProperty"
              onClick={(e) => {
                e.stopPropagation();
              }}
            />
            <FlatButton
              text="delete"
              color="danger"
              onClick={(e) => {
                switchDialog("delete");
                e.stopPropagation();
              }}
            />
          </div>
        ) : null}
      </Card>
      <ConfirmDialog
        title="timeline.post.deleteDialog.title"
        body="timeline.post.deleteDialog.prompt"
        onConfirm={() => {
          void getHttpTimelineClient()
            .deletePost(post.timelineOwnerV2, post.timelineNameV2, post.id)
            .then(onDeleted, () => {
              pushAlert({
                type: "danger",
                message: "timeline.deletePostFailed",
              });
            });
        }}
        {...dialogPropsMap.delete}
      />
    </div>
  );
}

export default TimelinePostView;