Reduce more code for scrolling logic

- Move from sessionStorage to in-memory for statuses cache
- Remove userInitiated, it's getting hard to differentiate between user-initiated and non-user-initiated. Probably better done from the route side instead of only stuck to this component's state
This commit is contained in:
Lim Chee Aun 2023-01-10 01:31:38 +08:00
parent 79ba6cdc29
commit 1727475336

View file

@ -14,7 +14,7 @@ import RelativeTime from '../components/relative-time';
import Status from '../components/status'; import Status from '../components/status';
import htmlContentLength from '../utils/html-content-length'; import htmlContentLength from '../utils/html-content-length';
import shortenNumber from '../utils/shorten-number'; import shortenNumber from '../utils/shorten-number';
import states from '../utils/states'; import states, { saveStatus } from '../utils/states';
import store from '../utils/store'; import store from '../utils/store';
import useDebouncedCallback from '../utils/useDebouncedCallback'; import useDebouncedCallback from '../utils/useDebouncedCallback';
import useTitle from '../utils/useTitle'; import useTitle from '../utils/useTitle';
@ -25,7 +25,6 @@ function StatusPage({ id }) {
const snapStates = useSnapshot(states); const snapStates = useSnapshot(states);
const [statuses, setStatuses] = useState([]); const [statuses, setStatuses] = useState([]);
const [uiState, setUIState] = useState('default'); const [uiState, setUIState] = useState('default');
const userInitiated = useRef(true); // Initial open is user-initiated
const heroStatusRef = useRef(); const heroStatusRef = useRef();
const scrollableRef = useRef(); const scrollableRef = useRef();
@ -49,12 +48,13 @@ function StatusPage({ id }) {
}, [id]); }, [id]);
const scrollOffsets = useRef(); const scrollOffsets = useRef();
const cachedStatusesMap = useRef({});
const initContext = () => { const initContext = () => {
console.debug('initContext', id); console.debug('initContext', id);
setUIState('loading'); setUIState('loading');
let heroTimer; let heroTimer;
const cachedStatuses = store.session.getJSON('statuses-' + id); const cachedStatuses = cachedStatusesMap.current[id];
if (cachedStatuses) { if (cachedStatuses) {
// Case 1: It's cached, let's restore them to make it snappy // Case 1: It's cached, let's restore them to make it snappy
const reallyCachedStatuses = cachedStatuses.filter( const reallyCachedStatuses = cachedStatuses.filter(
@ -85,7 +85,11 @@ function StatusPage({ id }) {
} else { } else {
try { try {
heroStatus = await heroFetch(); heroStatus = await heroFetch();
states.statuses[id] = heroStatus; saveStatus(heroStatus);
// Give time for context to appear
await new Promise((resolve) => {
setTimeout(resolve, 100);
});
} catch (e) { } catch (e) {
console.error(e); console.error(e);
setUIState('error'); setUIState('error');
@ -153,7 +157,7 @@ function StatusPage({ id }) {
}; };
console.log({ allStatuses }); console.log({ allStatuses });
setStatuses(allStatuses); setStatuses(allStatuses);
store.session.setJSON('statuses-' + id, allStatuses); cachedStatusesMap.current[id] = allStatuses;
} catch (e) { } catch (e) {
console.error(e); console.error(e);
setUIState('error'); setUIState('error');
@ -168,11 +172,11 @@ function StatusPage({ id }) {
useEffect(initContext, [id]); useEffect(initContext, [id]);
useEffect(() => { useEffect(() => {
if (!statuses.length) return; if (!statuses.length) return;
console.debug('STATUSES', statuses);
const scrollPosition = states.scrollPositions[id]; const scrollPosition = states.scrollPositions[id];
console.debug('scrollPosition', scrollPosition); console.debug('scrollPosition', scrollPosition);
if (!userInitiated.current && !!scrollPosition) { if (!!scrollPosition) {
console.debug('Case 1', { console.debug('Case 1', {
userInitiated: userInitiated.current,
scrollPosition, scrollPosition,
}); });
scrollableRef.current.scrollTop = scrollPosition; scrollableRef.current.scrollTop = scrollPosition;
@ -184,7 +188,6 @@ function StatusPage({ id }) {
const newScrollTop = const newScrollTop =
newScrollOffsets.offsetTop - scrollOffsets.current.offsetTop; newScrollOffsets.offsetTop - scrollOffsets.current.offsetTop;
console.debug('Case 2', { console.debug('Case 2', {
userInitiated: userInitiated.current,
scrollOffsets: scrollOffsets.current, scrollOffsets: scrollOffsets.current,
newScrollOffsets, newScrollOffsets,
newScrollTop, newScrollTop,
@ -193,9 +196,10 @@ function StatusPage({ id }) {
scrollableRef.current.scrollTop = newScrollTop; scrollableRef.current.scrollTop = newScrollTop;
} }
// Reset // RESET
userInitiated.current = false; // This will probably fail when user "forward" back to open the Status page again, but gosh, too many use-cases to mimic what the browser does
scrollOffsets.current = null; scrollOffsets.current = null;
cachedStatusesMap.current = {};
}, [statuses]); }, [statuses]);
useEffect(() => { useEffect(() => {
@ -384,9 +388,6 @@ function StatusPage({ id }) {
status-link status-link
" "
href={`#/s/${statusID}`} href={`#/s/${statusID}`}
onClick={() => {
userInitiated.current = true;
}}
> >
<Status <Status
statusID={statusID} statusID={statusID}
@ -409,9 +410,6 @@ function StatusPage({ id }) {
<SubComments <SubComments
hasManyStatuses={hasManyStatuses} hasManyStatuses={hasManyStatuses}
replies={replies} replies={replies}
onStatusLinkClick={() => {
userInitiated.current = true;
}}
/> />
)} )}
{uiState === 'loading' && {uiState === 'loading' &&