aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2021-01-13 17:06:43 +0800
committercrupest <crupest@outlook.com>2021-01-13 17:06:55 +0800
commit4a633a0f83a3a7cf18feead821fcdff2453de926 (patch)
tree7cb86b62d0e36adc4ce356d7986ff695bc244417 /FrontEnd/src
parent0833654d91dca0ff36cb6352528f6d00556352c0 (diff)
downloadtimeline-4a633a0f83a3a7cf18feead821fcdff2453de926.tar.gz
timeline-4a633a0f83a3a7cf18feead821fcdff2453de926.tar.bz2
timeline-4a633a0f83a3a7cf18feead821fcdff2453de926.zip
...
Diffstat (limited to 'FrontEnd/src')
-rw-r--r--FrontEnd/src/app/views/timeline-common/Timeline.tsx84
-rw-r--r--FrontEnd/src/app/views/timeline-common/TimelineDateItem.tsx19
-rw-r--r--FrontEnd/src/app/views/timeline-common/TimelineItem.tsx23
-rw-r--r--FrontEnd/src/app/views/timeline-common/timeline-common.sass18
4 files changed, 105 insertions, 39 deletions
diff --git a/FrontEnd/src/app/views/timeline-common/Timeline.tsx b/FrontEnd/src/app/views/timeline-common/Timeline.tsx
index 5c8f9195..ab658b89 100644
--- a/FrontEnd/src/app/views/timeline-common/Timeline.tsx
+++ b/FrontEnd/src/app/views/timeline-common/Timeline.tsx
@@ -5,6 +5,15 @@ import { TimelinePostInfo } from "@/services/timeline";
import TimelineItem from "./TimelineItem";
import TimelineTop from "./TimelineTop";
+import TimelineDateItem from "./TimelineDateItem";
+
+function dateEqual(left: Date, right: Date): boolean {
+ return (
+ left.getDate() == right.getDate() &&
+ left.getMonth() == right.getMonth() &&
+ left.getFullYear() == right.getFullYear()
+ );
+}
export interface TimelinePostInfoEx extends TimelinePostInfo {
onDelete?: () => void;
@@ -24,6 +33,31 @@ const Timeline: React.FC<TimelineProps> = (props) => {
const [showMoreIndex, setShowMoreIndex] = React.useState<number>(-1);
+ const groupedPosts = React.useMemo<
+ { date: Date; posts: (TimelinePostInfoEx & { index: number })[] }[]
+ >(() => {
+ const result: {
+ date: Date;
+ posts: (TimelinePostInfoEx & { index: number })[];
+ }[] = [];
+ let index = 0;
+ for (const post of posts) {
+ const { time } = post;
+ if (result.length === 0) {
+ result.push({ date: time, posts: [{ ...post, index }] });
+ } else {
+ const lastGroup = result[result.length - 1];
+ if (dateEqual(lastGroup.date, time)) {
+ lastGroup.posts.push({ ...post, index });
+ } else {
+ result.push({ date: time, posts: [{ ...post, index }] });
+ }
+ }
+ index++;
+ }
+ return result;
+ }, [posts]);
+
return (
<div
ref={props.containerRef}
@@ -31,29 +65,33 @@ const Timeline: React.FC<TimelineProps> = (props) => {
className={clsx("timeline", props.className)}
>
<TimelineTop height="56px" />
- {(() => {
- const length = posts.length;
- return posts.map((post, index) => {
- return (
- <TimelineItem
- post={post}
- key={post.id}
- current={length - 1 === index}
- more={
- post.onDelete != null
- ? {
- isOpen: showMoreIndex === index,
- toggle: () =>
- setShowMoreIndex((old) => (old === index ? -1 : index)),
- onDelete: post.onDelete,
- }
- : undefined
- }
- onClick={() => setShowMoreIndex(-1)}
- />
- );
- });
- })()}
+ {groupedPosts.map((group) => {
+ return (
+ <>
+ <TimelineDateItem date={group.date} />
+ {group.posts.map((post) => (
+ <TimelineItem
+ post={post}
+ key={post.id}
+ current={posts.length - 1 === post.index}
+ more={
+ post.onDelete != null
+ ? {
+ isOpen: showMoreIndex === post.index,
+ toggle: () =>
+ setShowMoreIndex((old) =>
+ old === post.index ? -1 : post.index
+ ),
+ onDelete: post.onDelete,
+ }
+ : undefined
+ }
+ onClick={() => setShowMoreIndex(-1)}
+ />
+ ))}
+ </>
+ );
+ })}
</div>
);
};
diff --git a/FrontEnd/src/app/views/timeline-common/TimelineDateItem.tsx b/FrontEnd/src/app/views/timeline-common/TimelineDateItem.tsx
new file mode 100644
index 00000000..bcc1530f
--- /dev/null
+++ b/FrontEnd/src/app/views/timeline-common/TimelineDateItem.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+import TimelineLine from "./TimelineLine";
+
+export interface TimelineDateItemProps {
+ date: Date;
+}
+
+const TimelineDateItem: React.FC<TimelineDateItemProps> = ({ date }) => {
+ return (
+ <div className="timeline-date-item">
+ <TimelineLine center={null} />
+ <div className="timeline-date-item-badge">
+ {date.toLocaleDateString()}
+ </div>
+ </div>
+ );
+};
+
+export default TimelineDateItem;
diff --git a/FrontEnd/src/app/views/timeline-common/TimelineItem.tsx b/FrontEnd/src/app/views/timeline-common/TimelineItem.tsx
index 74431402..c096f890 100644
--- a/FrontEnd/src/app/views/timeline-common/TimelineItem.tsx
+++ b/FrontEnd/src/app/views/timeline-common/TimelineItem.tsx
@@ -1,7 +1,6 @@
import React from "react";
import clsx from "clsx";
import { Link } from "react-router-dom";
-import { useTranslation } from "react-i18next";
import { useAvatar } from "@/services/user";
import { TimelinePostInfo } from "@/services/timeline";
@@ -24,8 +23,6 @@ export interface TimelineItemProps {
}
const TimelineItem: React.FC<TimelineItemProps> = (props) => {
- const { i18n } = useTranslation();
-
const current = props.current === true;
const { more } = props;
@@ -42,6 +39,15 @@ const TimelineItem: React.FC<TimelineItemProps> = (props) => {
>
<TimelineLine center="node" current={current} />
<div className="timeline-item-card">
+ {more != null ? (
+ <i
+ className="bi-chevron-down text-info icon-button float-right"
+ onClick={(e) => {
+ more.toggle();
+ e.stopPropagation();
+ }}
+ />
+ ) : null}
<div className="timeline-item-header">
<span className="mr-2">
<span>
@@ -52,19 +58,10 @@ const TimelineItem: React.FC<TimelineItemProps> = (props) => {
{props.post.author.nickname}
</small>
<small className="text-secondary white-space-no-wrap">
- {props.post.time.toLocaleString(i18n.languages)}
+ {props.post.time.toLocaleTimeString()}
</small>
</span>
</span>
- {more != null ? (
- <i
- className="bi-chevron-down text-info icon-button"
- onClick={(e) => {
- more.toggle();
- e.stopPropagation();
- }}
- />
- ) : null}
</div>
<div className="timeline-content">
{(() => {
diff --git a/FrontEnd/src/app/views/timeline-common/timeline-common.sass b/FrontEnd/src/app/views/timeline-common/timeline-common.sass
index 5af3a9ef..ebaf96b5 100644
--- a/FrontEnd/src/app/views/timeline-common/timeline-common.sass
+++ b/FrontEnd/src/app/views/timeline-common/timeline-common.sass
@@ -49,7 +49,7 @@ $timeline-line-color-current: #36c2e6
background: $timeline-line-color
&.start
- height: 1.4em
+ height: 1.8em
flex: 0 0 auto
&.end
@@ -102,7 +102,7 @@ $timeline-line-color-current: #36c2e6
.timeline-item-card
@extend .cru-card
position: relative
- padding: 0.5em 2em 0.5em 4em
+ padding: 0.3em 0.5em 1em 4em
transition: background 0.5s, padding-left 0.5s
@include media-breakpoint-down(sm)
@@ -114,7 +114,7 @@ $timeline-line-color-current: #36c2e6
.timeline-item-header
display: flex
align-items: center
- @extend .mb-2
+ @extend .my-2
.timeline-avatar
border-radius: 50%
@@ -133,6 +133,18 @@ $timeline-line-color-current: #36c2e6
max-width: 60%
max-height: 200px
+.timeline-date-item
+ position: relative
+ padding: 0.3em 0 0.3em 4em
+
+.timeline-date-item-badge
+ display: inline-block
+ padding: 0.1em 0.4em
+ border-radius: 0.4em
+ background: #7c7c7c
+ color: white
+ font-size: 0.8em
+
.timeline-post-edit-image
max-width: 100px
max-height: 100px