Skip to content

Commit

Permalink
Fixed not scrolling properly on chapter change and adjusted for ux fe…
Browse files Browse the repository at this point in the history
…edback
  • Loading branch information
tjcouch-sil committed Apr 19, 2024
1 parent 67541c2 commit 717c77d
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 18 deletions.
4 changes: 3 additions & 1 deletion extensions/src/platform-scripture/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ const booksPresentValidator: ProjectSettingValidator<'platformScripture.booksPre
const versificationValidator: ProjectSettingValidator<'platformScripture.versification'> = async (
newValue: number,
): Promise<boolean> => {
return typeof newValue === 'number' && newValue >= 0 && newValue <= 6;
return (
typeof newValue === 'number' && newValue >= 0 && newValue <= 6 && Number.isInteger(newValue)
);
};

// #endregion
Expand Down
4 changes: 1 addition & 3 deletions extensions/src/resource-viewer/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ const resourceWebViewProvider: IWebViewProvider = {
undefined;
return {
title: projectId
? `Resource Viewer : ${
(await papi.projectLookup.getMetadataForProject(projectId)).name ?? projectId
}`
? (await papi.projectLookup.getMetadataForProject(projectId)).name ?? projectId
: 'Resource Viewer',
...savedWebView,
content: resourceViewerWebView,
Expand Down
52 changes: 39 additions & 13 deletions extensions/src/resource-viewer/src/resource-viewer.web-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,36 @@ import {
usxStringToUsj,
} from '@biblionexus-foundation/platform-editor';

/** The offset in pixels from the top of the window to scroll to show the verse number */
const VERSE_NUMBER_SCROLL_OFFSET = 80;

/**
* Time in ms to delay taking action to wait for the editor to load. Hope to be obsoleted by a way
* to listen for the editor to finish loading
*/
const EDITOR_LOAD_DELAY_TIME = 100;

const defaultScrRef: ScriptureReference = {
bookNum: 1,
chapterNum: 1,
verseNum: 1,
};

function scrollToScrRef(scrRef: ScriptureReference) {
// We are querying for a span, so this Element will be an HTMLElement
// eslint-disable-next-line no-type-assertion/no-type-assertion
const verseElement = document.querySelector(
const verseElement = document.querySelector<HTMLElement>(
`.editor-container span[data-marker="v"][data-number="${scrRef.verseNum}"]`,
) as HTMLElement | undefined;
if (verseElement) {
);

// Scroll if we find the verse or we're at the start of the chapter
if (verseElement || scrRef.verseNum === 1) {
// If we're at the first verse, scroll to the top so we can see intro material
let scrollTop = 0;
if (verseElement && scrRef.verseNum > 1)
scrollTop =
verseElement.getBoundingClientRect().top + window.scrollY - VERSE_NUMBER_SCROLL_OFFSET;

window.scrollTo({
top: verseElement.getBoundingClientRect().top + window.scrollY - 55,
top: scrollTop,
behavior: 'smooth',
});
}
Expand All @@ -38,7 +53,6 @@ globalThis.webViewComponent = function ResourceViewer({
useWebViewState,
}: WebViewProps): JSX.Element {
const [projectId] = useWebViewState<string>('projectId', '');
logger.debug(`Resource Viewer project ID: ${projectId}`);

// Using react's ref api which uses null, so we must use null
// eslint-disable-next-line no-null/no-null
Expand Down Expand Up @@ -85,9 +99,9 @@ globalThis.webViewComponent = function ResourceViewer({
useEffect(() => {
if (usx && !hasFirstRetrievedScripture.current) {
hasFirstRetrievedScripture.current = true;
// Wait 100 ms before scrolling to make sure there is plenty of time for the editor to load
// Wait before scrolling to make sure there is time for the editor to load
// TODO: hook into the editor and detect when it has loaded somehow
setTimeout(() => scrollToScrRef(scrRef), 100);
setTimeout(() => scrollToScrRef(scrRef), EDITOR_LOAD_DELAY_TIME);
}
}, [usx, scrRef]);

Expand All @@ -106,13 +120,25 @@ globalThis.webViewComponent = function ResourceViewer({
return () => {};
}

// Add a highlight to the current verse element
const highlightedVerseElement = scrollToScrRef(scrRef);
if (highlightedVerseElement) highlightedVerseElement.classList.add('highlighted');
// Using react's ref api which uses null, so we must use null
// eslint-disable-next-line no-null/no-null
let highlightedVerseElement: HTMLElement | null;

// Wait before scrolling to make sure there is time for the editor to load
// TODO: hook into the editor and detect when it has loaded somehow
const scrollTimeout = setTimeout(() => {
// Scroll to and add a highlight to the current verse element
highlightedVerseElement = scrollToScrRef(scrRef);
if (highlightedVerseElement) highlightedVerseElement.classList.add('highlighted');

internallySetScrRefRef.current = undefined;
internallySetScrRefRef.current = undefined;
}, EDITOR_LOAD_DELAY_TIME);

return () => {
// Cancel this timeout to scroll if it is running because the scrRef changed and we need to
// scroll somewhere else
clearTimeout(scrollTimeout);

// Remove highlight from the current verse element
if (highlightedVerseElement) highlightedVerseElement.classList.remove('highlighted');
};
Expand Down
1 change: 1 addition & 0 deletions src/renderer/app.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,5 @@ a:hover {

.test-panel {
margin: 0.5em;
overflow-y: auto;
}
21 changes: 21 additions & 0 deletions src/renderer/testing/lorem-ipsum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const LOREM_IPSUM = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam convallis aliquet justo vitae vehicula. Vestibulum tincidunt porttitor urna, non scelerisque nibh commodo quis. Nunc vel porta nisl, in maximus massa. Donec convallis sem in magna iaculis, ut sagittis lectus semper. Aliquam pellentesque orci et scelerisque egestas. Sed ac vehicula arcu. Etiam rutrum sapien risus, a venenatis urna accumsan sit amet. In vel turpis vitae risus tristique tincidunt. Aenean et leo vel lacus venenatis bibendum. Donec semper libero sed purus efficitur, condimentum lacinia odio rhoncus. Proin et quam magna. Cras risus arcu, dictum vel sapien a, accumsan lacinia est. Pellentesque sit amet dolor nec ex pellentesque aliquam. Mauris eget libero gravida, egestas orci sed, feugiat erat.
Fusce eget mattis eros. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean consectetur turpis urna, ut ullamcorper tortor ultricies non. Phasellus nec bibendum quam, eget rutrum dolor. Integer vel tempor neque. Suspendisse id mollis nisl. Nunc finibus ac enim sed congue. Vivamus ac accumsan turpis.
Aliquam eu tempor nibh. Curabitur scelerisque tortor purus, volutpat efficitur magna pellentesque sit amet. Curabitur id pulvinar sem, vel porta eros. Maecenas nunc urna, imperdiet nec lobortis eget, rutrum a neque. Suspendisse eu vulputate lorem. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nam dictum at ante ut dignissim. Sed tempor tempus odio id varius. Praesent eu neque leo. Mauris bibendum dui sollicitudin, imperdiet justo ut, porttitor justo. Nulla feugiat mi id dictum feugiat. Duis feugiat arcu risus, a tincidunt ex faucibus sed. Donec egestas lectus sit amet tincidunt maximus. Mauris scelerisque, mauris suscipit dapibus pretium, nisi nulla dignissim metus, elementum tincidunt massa ipsum vel velit.
Donec sit amet felis leo. Duis vitae sem id libero sodales iaculis. Interdum et malesuada fames ac ante ipsum primis in faucibus. Duis eu dolor condimentum, pretium libero quis, ornare sapien. Nullam efficitur ornare ipsum nec tincidunt. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nulla iaculis ultrices lacus in sagittis. Maecenas facilisis fringilla turpis ac cursus. Duis commodo fringilla dui.
Fusce convallis massa nec lectus venenatis vulputate vel id justo. Donec vel mauris orci. Suspendisse finibus accumsan lacus a feugiat. Pellentesque interdum pellentesque orci, at ultrices ipsum aliquam a. Curabitur scelerisque, diam nec commodo vestibulum, neque nisl feugiat lorem, et iaculis nisl mi sit amet dui. Mauris ut nisl viverra, mollis felis id, aliquet tellus. Praesent ullamcorper faucibus lectus, maximus pellentesque mi vehicula et. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Maecenas metus felis, interdum nec urna sed, sodales ornare eros. Quisque volutpat justo sed sem aliquet, in fermentum lectus feugiat. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer quis ultricies lacus, euismod placerat dolor. Donec tempor ullamcorper ex, sit amet euismod ligula pharetra sed. Fusce sagittis molestie odio et iaculis. Nullam id dolor aliquet risus venenatis congue eget id erat. Ut eget vulputate est, nec luctus quam.
Mauris nec condimentum nulla, eu malesuada lectus. Integer blandit tellus eu sem gravida aliquam. Donec convallis lacinia ante in porta. Aliquam nec felis suscipit, efficitur mi non, convallis diam. Etiam in mollis nisi. Cras pellentesque luctus justo, vel convallis elit eleifend ut. Ut pulvinar nisl urna, in volutpat dui facilisis a. Sed in imperdiet ligula. Praesent feugiat neque nibh, non eleifend ex vestibulum in.
Mauris auctor nibh at magna posuere commodo. Maecenas sit amet fermentum lorem, eu rhoncus augue. Aenean eu urna ultricies, consequat augue nec, eleifend libero. Nunc eu diam sagittis, condimentum quam quis, vestibulum leo. Pellentesque nec ante in purus lacinia luctus. In non gravida tellus. Duis quam erat, faucibus at pharetra eu, blandit a nunc. Sed felis quam, bibendum a orci id, sodales facilisis mauris. Fusce feugiat nisi nulla, ut vehicula mauris pulvinar in. Aliquam scelerisque faucibus risus et dignissim. Suspendisse ut finibus mi. Proin finibus aliquet feugiat. Sed et tortor vestibulum, pharetra libero in, facilisis quam. Etiam bibendum efficitur ligula id congue. Suspendisse sit amet sapien ac nisl maximus ullamcorper id eget ante.
Aliquam consequat elit et rhoncus porttitor. Sed condimentum pulvinar lorem, at varius ante laoreet ut. Suspendisse egestas euismod lorem, quis pretium odio iaculis eu. Aliquam erat volutpat. Cras faucibus, elit quis scelerisque vestibulum, est justo pharetra urna, et sodales augue magna a leo. Fusce eu massa convallis, commodo sapien quis, sagittis ex. Ut quis mattis erat. Ut purus massa, varius sit amet tempus efficitur, cursus eleifend velit. Aliquam a ipsum eu velit dictum semper. Nulla dignissim at tellus nec interdum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Suspendisse sed ultrices dui. Sed rhoncus turpis elit, eget pharetra ligula pharetra ut.
Quisque quis est nec orci aliquet dictum id vulputate turpis. Ut nisl sapien, aliquam sed pulvinar sed, dignissim ac ipsum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Fusce auctor odio facilisis purus porta ullamcorper. Morbi tincidunt lorem ac orci hendrerit, eget sollicitudin metus sagittis. Nunc pellentesque justo quis massa interdum congue. Praesent a ultrices justo.
Suspendisse laoreet metus a malesuada laoreet. Aliquam erat volutpat. Nam sagittis mattis rutrum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nunc eget tempor felis. Sed ultricies justo vitae lorem elementum, sit amet tincidunt lorem imperdiet. Maecenas id porta mauris, eu auctor augue. Vestibulum ultrices erat at augue tempus malesuada. Aliquam facilisis urna at lectus feugiat, sit amet porta erat sagittis. Nulla interdum condimentum leo vitae dictum. Donec semper suscipit auctor. Nunc a nibh arcu. Integer vehicula magna vel augue scelerisque tempus. Aenean hendrerit sem et mi sollicitudin, vel dignissim libero fringilla. Nam at interdum elit.`;

export default LOREM_IPSUM;
6 changes: 6 additions & 0 deletions src/renderer/testing/test-layout.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { TAB_TYPE_TEST } from '@renderer/testing/test-panel.component';
import { TAB_TYPE_SETTINGS_DIALOG } from '@renderer/components/settings-dialog/settings-tab.component';
import { TAB_TYPE_RUN_BASIC_CHECKS } from '@renderer/components/run-basic-checks-dialog/run-basic-checks-tab.component';
import { TAB_TYPE_BASIC_LIST } from '@renderer/components/basic-list/basic-list.component';
import LOREM_IPSUM from './lorem-ipsum';

export const FIRST_TAB_ID = 'About';

Expand All @@ -28,6 +29,11 @@ const testLayout: LayoutBase = {
{ id: 'About', tabType: TAB_TYPE_ABOUT },
{ id: 'Test Tab Two', tabType: TAB_TYPE_TEST },
{ id: 'Test Tab One', tabType: TAB_TYPE_TEST },
{
id: 'Lorem Ipsum',
tabType: TAB_TYPE_TEST,
data: { content: LOREM_IPSUM },
},
] as SavedTabInfo[],
},
],
Expand Down
8 changes: 7 additions & 1 deletion src/renderer/testing/test-panel.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@ import { SavedTabInfo, TabInfo } from '@shared/models/docking-framework.model';

export const TAB_TYPE_TEST = 'tab';

type TestTabData = { content?: string } | undefined;

export default function TestPanel({ content }: { content: string }) {
return <div className="test-panel">{content}</div>;
}

export function loadTestTab(savedTabInfo: SavedTabInfo): TabInfo {
if (!savedTabInfo.id) throw new Error('Tab creation "id" is missing');

// We set this in `test-layout.data.ts`
// eslint-disable-next-line no-type-assertion/no-type-assertion
const data = savedTabInfo.data as TestTabData;

const tabTitle = savedTabInfo.id || 'Unknown';
const content = savedTabInfo.id ? `Content for ${tabTitle}` : 'Unknown';
const content = data?.content ?? (savedTabInfo.id ? `Content for ${tabTitle}` : 'Unknown');
return {
...savedTabInfo,
tabTitle,
Expand Down

0 comments on commit 717c77d

Please sign in to comment.