Skip to content

Commit

Permalink
fix: save scroll position on exit from video xblock fullscreen mode
Browse files Browse the repository at this point in the history
  • Loading branch information
ihor-romaniuk committed Jul 6, 2023
1 parent eac884b commit 8018989
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 1 deletion.
14 changes: 13 additions & 1 deletion src/courseware/course/sequence/Unit.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ function Unit({
const [hasLoaded, setHasLoaded] = useState(false);
const [modalOptions, setModalOptions] = useState({ open: false });
const [shouldDisplayHonorCode, setShouldDisplayHonorCode] = useState(false);
const [windowTopOffset, setWindowTopOffset] = useState(null);

const unit = useModel('units', id);
const course = useModel('coursewareMeta', courseId);
Expand Down Expand Up @@ -128,6 +129,13 @@ function Unit({
const { type, payload } = event.data;
if (type === 'plugin.resize') {
setIframeHeight(payload.height);

// We observe exit from the video xblock full screen mode
// and do page scroll to the previously saved scroll position
if (windowTopOffset !== null) {
window.scrollTo(0, Number(windowTopOffset));
}

if (!hasLoaded && iframeHeight === 0 && payload.height > 0) {
setHasLoaded(true);
if (onLoaded) {
Expand All @@ -137,6 +145,10 @@ function Unit({
} else if (type === 'plugin.modal') {
payload.open = true;
setModalOptions(payload);
} else if (type === 'plugin.videoFullScreen') {
// We listen for this message from LMS to know when we need to
// save or reset scroll position on toggle video xblock full screen mode.
setWindowTopOffset(payload.open ? window.scrollY : null);
} else if (event.data.offset) {
// We listen for this message from LMS to know when the page needs to
// be scrolled to another location on the page.
Expand All @@ -154,7 +166,7 @@ function Unit({
messageEventListenerRef.current = receiveMessage;
// When the component finally unmounts, use the ref to remove the correct handler.
return () => global.removeEventListener('message', messageEventListenerRef.current);
}, [id, setIframeHeight, hasLoaded, iframeHeight, setHasLoaded, onLoaded]);
}, [id, setIframeHeight, hasLoaded, iframeHeight, setHasLoaded, onLoaded, setWindowTopOffset, windowTopOffset]);

return (
<div className="unit">
Expand Down
15 changes: 15 additions & 0 deletions src/courseware/course/sequence/Unit.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,21 @@ describe('Unit', () => {
expect(window.scrollY === testMessageWithOffset.offset);
});

it('scrolls page on MessagaeEvent when receiving videoFullScreen state', async () => {
// Set message to constain video full screen data.
const defaultTopOffset = 800;
const testMessageWithOtherHeight = { ...messageEvent, payload: { height: 500 } };
const testMessageWithFullscreenState = (isOpen) => ({ type: 'plugin.videoFullScreen', payload: { open: isOpen } });
render(<Unit {...mockData} />);
Object.defineProperty(window, 'scrollY', { value: defaultTopOffset, writable: true });
window.postMessage(testMessageWithFullscreenState(true), '*');
window.postMessage(testMessageWithFullscreenState(false), '*');
window.postMessage(testMessageWithOtherHeight, '*');

await expect(waitFor(() => expect(window.scrollTo()).toHaveBeenCalledTimes(1)));
expect(window.scrollY === defaultTopOffset);
});

it('ignores MessageEvent with unhandled type', async () => {
// Clone message and set different type.
const testMessageWithUnhandledType = { ...messageEvent, type: 'wrong type' };
Expand Down

0 comments on commit 8018989

Please sign in to comment.