diff options
Diffstat (limited to 'Timeline/ClientApp/src')
-rw-r--r-- | Timeline/ClientApp/src/app/common.ts | 42 | ||||
-rw-r--r-- | Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx | 18 |
2 files changed, 47 insertions, 13 deletions
diff --git a/Timeline/ClientApp/src/app/common.ts b/Timeline/ClientApp/src/app/common.ts index 0b11791a..56fdbc0e 100644 --- a/Timeline/ClientApp/src/app/common.ts +++ b/Timeline/ClientApp/src/app/common.ts @@ -1,4 +1,44 @@ +import React from 'react'; +import { Observable, Subject } from 'rxjs'; + // This error is thrown when ui goes wrong with bad logic. -// Such as am variable should not be null, but it does. +// Such as a variable should not be null, but it does. // This error should never occur. If it does, it indicates there is some logic bug in codes. export class UiLogicError extends Error {} + +export function useEventEmiiter(): [() => Observable<null>, () => void] { + const ref = React.useRef<Subject<null> | null>(null); + + return React.useMemo(() => { + const getter = (): Subject<null> => { + if (ref.current == null) { + ref.current = new Subject<null>(); + } + return ref.current; + }; + const trigger = (): void => { + getter().next(null); + }; + return [getter, trigger]; + }, []); +} + +export function useValueEventEmiiter<T>(): [ + () => Observable<T>, + (value: T) => void +] { + const ref = React.useRef<Subject<T> | null>(null); + + return React.useMemo(() => { + const getter = (): Subject<T> => { + if (ref.current == null) { + ref.current = new Subject<T>(); + } + return ref.current; + }; + const trigger = (value: T): void => { + getter().next(value); + }; + return [getter, trigger]; + }, []); +} diff --git a/Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx b/Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx index d74fffc4..275e9ae0 100644 --- a/Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx +++ b/Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Spinner } from 'reactstrap'; import { useTranslation } from 'react-i18next'; -import { Subject, fromEvent } from 'rxjs'; +import { fromEvent } from 'rxjs'; import { getAlertHost } from '../common/alert-service'; @@ -12,6 +12,7 @@ import Timeline, { import AppBar from '../common/AppBar'; import TimelinePostEdit, { TimelinePostSendCallback } from './TimelinePostEdit'; import CollapseButton from '../common/CollapseButton'; +import { useEventEmiiter } from '../common'; export interface TimelineCardComponentProps<TTimeline, TManageItems> { timeline: TTimeline; @@ -68,10 +69,7 @@ export default function TimelinePageTemplateUI< } }, []); - const resizeSubject = React.useMemo(() => new Subject(), []); - const triggerResizeEvent = React.useCallback(() => { - resizeSubject.next(null); - }, [resizeSubject]); + const [getResizeEvent, triggerResizeEvent] = useEventEmiiter(); React.useEffect(() => { let scrollToBottom = true; @@ -83,7 +81,7 @@ export default function TimelinePageTemplateUI< fromEvent(window, 'wheel').subscribe(disableScrollToBottom), fromEvent(window, 'pointerdown').subscribe(disableScrollToBottom), fromEvent(window, 'keydown').subscribe(disableScrollToBottom), - resizeSubject.subscribe(() => { + getResizeEvent().subscribe(() => { if (scrollToBottom) { window.scrollTo(0, document.body.scrollHeight); } @@ -93,14 +91,10 @@ export default function TimelinePageTemplateUI< return () => { subscriptions.forEach((s) => s.unsubscribe()); }; - }, [resizeSubject, timeline, props.posts]); + }, [getResizeEvent, timeline, props.posts]); const [cardHeight, setCardHeight] = React.useState<number>(0); - const onCardHeightChange = React.useCallback((height: number) => { - setCardHeight(height); - }, []); - const genCardCollapseLocalStorageKey = (timelineName: string): string => `timeline.${timelineName}.cardCollapse`; @@ -181,7 +175,7 @@ export default function TimelinePageTemplateUI< timeline={timeline} onManage={props.onManage} onMember={props.onMember} - onHeight={onCardHeightChange} + onHeight={setCardHeight} className="info-card-content" /> </div> |