2021-08-04 18:52:59 +09:00
|
|
|
import React, { useState, useEffect, useRef } from 'react';
|
2021-07-28 22:15:52 +09:00
|
|
|
import PropTypes from 'prop-types';
|
2021-08-31 22:13:31 +09:00
|
|
|
import './RoomView.scss';
|
2021-07-28 22:15:52 +09:00
|
|
|
|
|
|
|
import EventEmitter from 'events';
|
|
|
|
|
|
|
|
import RoomTimeline from '../../../client/state/RoomTimeline';
|
|
|
|
|
|
|
|
import ScrollView from '../../atoms/scroll/ScrollView';
|
|
|
|
|
2021-08-31 22:13:31 +09:00
|
|
|
import RoomViewHeader from './RoomViewHeader';
|
|
|
|
import RoomViewContent from './RoomViewContent';
|
|
|
|
import RoomViewFloating from './RoomViewFloating';
|
|
|
|
import RoomViewInput from './RoomViewInput';
|
|
|
|
import RoomViewCmdBar from './RoomViewCmdBar';
|
2021-07-28 22:15:52 +09:00
|
|
|
|
2021-08-04 18:52:59 +09:00
|
|
|
import { scrollToBottom, isAtBottom, autoScrollToBottom } from './common';
|
2021-07-28 22:15:52 +09:00
|
|
|
|
2021-08-04 18:52:59 +09:00
|
|
|
const viewEvent = new EventEmitter();
|
2021-07-28 22:15:52 +09:00
|
|
|
|
|
|
|
let lastScrollTop = 0;
|
|
|
|
let lastScrollHeight = 0;
|
|
|
|
let isReachedBottom = true;
|
|
|
|
let isReachedTop = false;
|
2021-08-31 22:13:31 +09:00
|
|
|
function RoomView({ roomId }) {
|
2021-07-28 22:15:52 +09:00
|
|
|
const [roomTimeline, updateRoomTimeline] = useState(null);
|
|
|
|
const timelineSVRef = useRef(null);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
roomTimeline?.removeInternalListeners();
|
|
|
|
updateRoomTimeline(new RoomTimeline(roomId));
|
|
|
|
isReachedBottom = true;
|
|
|
|
isReachedTop = false;
|
|
|
|
}, [roomId]);
|
|
|
|
|
|
|
|
const timelineScroll = {
|
|
|
|
reachBottom() {
|
|
|
|
scrollToBottom(timelineSVRef);
|
|
|
|
},
|
|
|
|
autoReachBottom() {
|
|
|
|
autoScrollToBottom(timelineSVRef);
|
|
|
|
},
|
|
|
|
tryRestoringScroll() {
|
|
|
|
const sv = timelineSVRef.current;
|
|
|
|
const { scrollHeight } = sv;
|
|
|
|
|
|
|
|
if (lastScrollHeight === scrollHeight) return;
|
|
|
|
|
|
|
|
if (lastScrollHeight < scrollHeight) {
|
|
|
|
sv.scrollTop = lastScrollTop + (scrollHeight - lastScrollHeight);
|
|
|
|
} else {
|
|
|
|
timelineScroll.reachBottom();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
enableSmoothScroll() {
|
|
|
|
timelineSVRef.current.style.scrollBehavior = 'smooth';
|
|
|
|
},
|
|
|
|
disableSmoothScroll() {
|
|
|
|
timelineSVRef.current.style.scrollBehavior = 'auto';
|
|
|
|
},
|
|
|
|
isScrollable() {
|
|
|
|
const oHeight = timelineSVRef.current.offsetHeight;
|
|
|
|
const sHeight = timelineSVRef.current.scrollHeight;
|
|
|
|
if (sHeight > oHeight) return true;
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
function onTimelineScroll(e) {
|
|
|
|
const { scrollTop, scrollHeight, offsetHeight } = e.target;
|
|
|
|
const scrollBottom = scrollTop + offsetHeight;
|
|
|
|
lastScrollTop = scrollTop;
|
|
|
|
lastScrollHeight = scrollHeight;
|
|
|
|
|
|
|
|
const PLACEHOLDER_HEIGHT = 96;
|
|
|
|
const PLACEHOLDER_COUNT = 3;
|
|
|
|
|
|
|
|
const topPagKeyPoint = PLACEHOLDER_COUNT * PLACEHOLDER_HEIGHT;
|
|
|
|
const bottomPagKeyPoint = scrollHeight - (offsetHeight / 2);
|
|
|
|
|
|
|
|
if (!isReachedBottom && isAtBottom(timelineSVRef)) {
|
|
|
|
isReachedBottom = true;
|
|
|
|
viewEvent.emit('toggle-reached-bottom', true);
|
|
|
|
}
|
|
|
|
if (isReachedBottom && !isAtBottom(timelineSVRef)) {
|
|
|
|
isReachedBottom = false;
|
|
|
|
viewEvent.emit('toggle-reached-bottom', false);
|
|
|
|
}
|
|
|
|
// TOP of timeline
|
|
|
|
if (scrollTop < topPagKeyPoint && isReachedTop === false) {
|
|
|
|
isReachedTop = true;
|
|
|
|
viewEvent.emit('reached-top');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
isReachedTop = false;
|
|
|
|
|
|
|
|
// BOTTOM of timeline
|
|
|
|
if (scrollBottom > bottomPagKeyPoint) {
|
|
|
|
// TODO:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
2021-08-31 22:13:31 +09:00
|
|
|
<div className="room-view">
|
|
|
|
<RoomViewHeader roomId={roomId} />
|
|
|
|
<div className="room-view__content-wrapper">
|
|
|
|
<div className="room-view__scrollable">
|
2021-07-28 22:15:52 +09:00
|
|
|
<ScrollView onScroll={onTimelineScroll} ref={timelineSVRef} autoHide>
|
|
|
|
{roomTimeline !== null && (
|
2021-08-31 22:13:31 +09:00
|
|
|
<RoomViewContent
|
2021-07-28 22:15:52 +09:00
|
|
|
roomId={roomId}
|
|
|
|
roomTimeline={roomTimeline}
|
|
|
|
timelineScroll={timelineScroll}
|
2021-08-04 18:52:59 +09:00
|
|
|
viewEvent={viewEvent}
|
2021-07-28 22:15:52 +09:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</ScrollView>
|
|
|
|
{roomTimeline !== null && (
|
2021-08-31 22:13:31 +09:00
|
|
|
<RoomViewFloating
|
2021-07-28 22:15:52 +09:00
|
|
|
roomId={roomId}
|
|
|
|
roomTimeline={roomTimeline}
|
|
|
|
timelineScroll={timelineScroll}
|
2021-08-04 18:52:59 +09:00
|
|
|
viewEvent={viewEvent}
|
2021-07-28 22:15:52 +09:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
{roomTimeline !== null && (
|
2021-08-31 22:13:31 +09:00
|
|
|
<div className="room-view__sticky">
|
|
|
|
<RoomViewInput
|
2021-07-28 22:15:52 +09:00
|
|
|
roomId={roomId}
|
|
|
|
roomTimeline={roomTimeline}
|
|
|
|
timelineScroll={timelineScroll}
|
2021-08-04 18:52:59 +09:00
|
|
|
viewEvent={viewEvent}
|
2021-07-28 22:15:52 +09:00
|
|
|
/>
|
2021-08-31 22:13:31 +09:00
|
|
|
<RoomViewCmdBar
|
2021-07-28 22:15:52 +09:00
|
|
|
roomId={roomId}
|
|
|
|
roomTimeline={roomTimeline}
|
2021-08-04 18:52:59 +09:00
|
|
|
viewEvent={viewEvent}
|
2021-07-28 22:15:52 +09:00
|
|
|
/>
|
2021-08-04 18:52:59 +09:00
|
|
|
</div>
|
2021-07-28 22:15:52 +09:00
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2021-08-31 22:13:31 +09:00
|
|
|
RoomView.propTypes = {
|
2021-07-28 22:15:52 +09:00
|
|
|
roomId: PropTypes.string.isRequired,
|
|
|
|
};
|
|
|
|
|
2021-08-31 22:13:31 +09:00
|
|
|
export default RoomView;
|