aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-06-12 00:51:39 +0800
committercrupest <crupest@outlook.com>2020-06-12 00:51:39 +0800
commit1f6c3002791a0d4399171e87f3eeb9df0cce930a (patch)
tree21b5dddecc0283375ae7f2109b7f3553ccea5129
parent97fd549d3fbc9206219da83972b37a1c3bb36756 (diff)
downloadtimeline-1f6c3002791a0d4399171e87f3eeb9df0cce930a.tar.gz
timeline-1f6c3002791a0d4399171e87f3eeb9df0cce930a.tar.bz2
timeline-1f6c3002791a0d4399171e87f3eeb9df0cce930a.zip
feat(front): Fix #98 . Fix #99 .
-rw-r--r--Timeline/ClientApp/src/app/timeline/Timeline.tsx13
-rw-r--r--Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx66
2 files changed, 56 insertions, 23 deletions
diff --git a/Timeline/ClientApp/src/app/timeline/Timeline.tsx b/Timeline/ClientApp/src/app/timeline/Timeline.tsx
index 35d6490b..0a68c5db 100644
--- a/Timeline/ClientApp/src/app/timeline/Timeline.tsx
+++ b/Timeline/ClientApp/src/app/timeline/Timeline.tsx
@@ -1,6 +1,5 @@
import React from 'react';
import clsx from 'clsx';
-import { Container } from 'reactstrap';
import { TimelinePostInfo } from '../data/timeline';
import { useUser } from '../data/user';
@@ -19,6 +18,7 @@ export interface TimelineProps {
posts: TimelinePostInfoEx[];
onDelete: TimelineDeleteCallback;
onResize?: () => void;
+ containerRef?: React.Ref<HTMLDivElement>;
}
const Timeline: React.FC<TimelineProps> = (props) => {
@@ -56,9 +56,12 @@ const Timeline: React.FC<TimelineProps> = (props) => {
}, [posts, onDelete]);
return (
- <Container
- fluid
- className={clsx('d-flex flex-column position-relative', props.className)}
+ <div
+ ref={props.containerRef}
+ className={clsx(
+ 'container-fluid d-flex flex-column position-relative',
+ props.className
+ )}
>
<div className="timeline-enter-animation-mask" />
{(() => {
@@ -92,7 +95,7 @@ const Timeline: React.FC<TimelineProps> = (props) => {
);
});
})()}
- </Container>
+ </div>
);
};
diff --git a/Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx b/Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx
index 275e9ae0..5eb6a310 100644
--- a/Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx
+++ b/Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx
@@ -69,29 +69,58 @@ export default function TimelinePageTemplateUI<
}
}, []);
+ const timelineRef = React.useRef<HTMLDivElement | null>(null);
+
const [getResizeEvent, triggerResizeEvent] = useEventEmiiter();
React.useEffect(() => {
- let scrollToBottom = true;
- const disableScrollToBottom = (): void => {
- scrollToBottom = false;
- };
-
- const subscriptions = [
- fromEvent(window, 'wheel').subscribe(disableScrollToBottom),
- fromEvent(window, 'pointerdown').subscribe(disableScrollToBottom),
- fromEvent(window, 'keydown').subscribe(disableScrollToBottom),
- getResizeEvent().subscribe(() => {
- if (scrollToBottom) {
+ const { current: timelineElement } = timelineRef;
+ if (timelineElement != null) {
+ let loadingScrollToBottom = true;
+ let pinBottom = false;
+
+ const isAtBottom = (): boolean =>
+ window.innerHeight + window.scrollY + 10 >= document.body.scrollHeight;
+
+ const disableLoadingScrollToBottom = (): void => {
+ loadingScrollToBottom = false;
+ if (isAtBottom()) pinBottom = true;
+ };
+
+ const checkAndScrollToBottom = (): void => {
+ if (loadingScrollToBottom || pinBottom) {
window.scrollTo(0, document.body.scrollHeight);
}
- }),
- ];
-
- return () => {
- subscriptions.forEach((s) => s.unsubscribe());
- };
- }, [getResizeEvent, timeline, props.posts]);
+ };
+
+ const subscriptions = [
+ fromEvent(timelineElement, 'wheel').subscribe(
+ disableLoadingScrollToBottom
+ ),
+ fromEvent(timelineElement, 'pointerdown').subscribe(
+ disableLoadingScrollToBottom
+ ),
+ fromEvent(timelineElement, 'keydown').subscribe(
+ disableLoadingScrollToBottom
+ ),
+ fromEvent(window, 'scroll').subscribe(() => {
+ if (loadingScrollToBottom) return;
+
+ if (isAtBottom()) {
+ pinBottom = true;
+ } else {
+ pinBottom = false;
+ }
+ }),
+ fromEvent(window, 'resize').subscribe(checkAndScrollToBottom),
+ getResizeEvent().subscribe(checkAndScrollToBottom),
+ ];
+
+ return () => {
+ subscriptions.forEach((s) => s.unsubscribe());
+ };
+ }
+ }, [getResizeEvent, triggerResizeEvent, timeline, props.posts]);
const [cardHeight, setCardHeight] = React.useState<number>(0);
@@ -125,6 +154,7 @@ export default function TimelinePageTemplateUI<
} else {
timelineBody = (
<Timeline
+ containerRef={timelineRef}
posts={props.posts}
onDelete={props.onDelete}
onResize={triggerResizeEvent}