diff options
author | crupest <crupest@outlook.com> | 2020-06-11 17:27:15 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-06-11 17:27:15 +0800 |
commit | cf6cfe87b46a2a3eb2913209092ab4c5639e75c3 (patch) | |
tree | eba7504d04dad89f67524b48d88a3b5eb27de6de /Timeline/ClientApp/src/app/timeline/Timeline.tsx | |
parent | 4b8abdd1921935ebb29d18961534db04a2e58fbb (diff) | |
download | timeline-cf6cfe87b46a2a3eb2913209092ab4c5639e75c3.tar.gz timeline-cf6cfe87b46a2a3eb2913209092ab4c5639e75c3.tar.bz2 timeline-cf6cfe87b46a2a3eb2913209092ab4c5639e75c3.zip |
feat(front): Service worker is coming!
Diffstat (limited to 'Timeline/ClientApp/src/app/timeline/Timeline.tsx')
-rw-r--r-- | Timeline/ClientApp/src/app/timeline/Timeline.tsx | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/Timeline/ClientApp/src/app/timeline/Timeline.tsx b/Timeline/ClientApp/src/app/timeline/Timeline.tsx new file mode 100644 index 00000000..35d6490b --- /dev/null +++ b/Timeline/ClientApp/src/app/timeline/Timeline.tsx @@ -0,0 +1,99 @@ +import React from 'react'; +import clsx from 'clsx'; +import { Container } from 'reactstrap'; + +import { TimelinePostInfo } from '../data/timeline'; +import { useUser } from '../data/user'; +import { useAvatarVersion } from '../user/api'; + +import TimelineItem from './TimelineItem'; + +export interface TimelinePostInfoEx extends TimelinePostInfo { + deletable: boolean; +} + +export type TimelineDeleteCallback = (index: number, id: number) => void; + +export interface TimelineProps { + className?: string; + posts: TimelinePostInfoEx[]; + onDelete: TimelineDeleteCallback; + onResize?: () => void; +} + +const Timeline: React.FC<TimelineProps> = (props) => { + const user = useUser(); + const avatarVersion = useAvatarVersion(); + + const { posts, onDelete, onResize } = props; + + const [indexShowDeleteButton, setIndexShowDeleteButton] = React.useState< + number + >(-1); + + const onItemClick = React.useCallback(() => { + setIndexShowDeleteButton(-1); + }, []); + + const onToggleDelete = React.useMemo(() => { + return posts.map((post, i) => { + return post.deletable + ? () => { + setIndexShowDeleteButton((oldIndexShowDeleteButton) => { + return oldIndexShowDeleteButton !== i ? i : -1; + }); + } + : undefined; + }); + }, [posts]); + + const onItemDelete = React.useMemo(() => { + return posts.map((post, i) => { + return () => { + onDelete(i, post.id); + }; + }); + }, [posts, onDelete]); + + return ( + <Container + fluid + className={clsx('d-flex flex-column position-relative', props.className)} + > + <div className="timeline-enter-animation-mask" /> + {(() => { + const length = posts.length; + return posts.map((post, i) => { + const av: number | undefined = + user != null && user.username === post.author.username + ? avatarVersion + : undefined; + + const toggleMore = onToggleDelete[i]; + + return ( + <TimelineItem + post={post} + key={post.id} + current={length - 1 === i} + more={ + toggleMore + ? { + isOpen: indexShowDeleteButton === i, + toggle: toggleMore, + onDelete: onItemDelete[i], + } + : undefined + } + onClick={onItemClick} + avatarVersion={av} + onResize={onResize} + /> + ); + }); + })()} + </Container> + ); +}; + +export default Timeline; |