diff --git a/src/pages/article.page.tsx b/src/pages/article.page.tsx index 8378bf37..bece4351 100644 --- a/src/pages/article.page.tsx +++ b/src/pages/article.page.tsx @@ -7,6 +7,7 @@ import { useRouter } from '../stores/router' import { Loading } from '../components/_shared/Loading' import { ReactionsProvider } from '../context/reactions' import { FullArticle } from '../components/Article/FullArticle' +import { setPageLoadManagerPromise } from '../utils/pageLoadManager' export const ArticlePage = (props: PageProps) => { const shouts = props.article ? [props.article] : [] @@ -33,7 +34,9 @@ export const ArticlePage = (props: PageProps) => { const articleValue = articleEntities()[slug()] if (!articleValue || !articleValue.body) { - await loadShout(slug()) + const loadShoutPromise = loadShout(slug()) + setPageLoadManagerPromise(loadShoutPromise) + await loadShoutPromise } }) diff --git a/src/stores/router.ts b/src/stores/router.ts index c21d25b8..a2d7c3c5 100644 --- a/src/stores/router.ts +++ b/src/stores/router.ts @@ -2,6 +2,8 @@ import type { Accessor } from 'solid-js' import { createRouter, createSearchParams } from '@nanostores/router' import { isServer } from 'solid-js/web' import { useStore } from '@nanostores/solid' +import { loadShoutPromise } from './zine/articles' +import { getPageLoadManagerPromise } from '../utils/pageLoadManager' export const ROUTES = { home: '/', @@ -54,7 +56,27 @@ const checkOpenOnClient = (link: HTMLAnchorElement, event) => { ) } -const handleClientRouteLinkClick = (event) => { +const scrollToHash = (hash: string) => { + let selector = hash + + if (/^#\d+/.test(selector)) { + // id="1" fix + // https://stackoverflow.com/questions/20306204/using-queryselector-with-ids-that-are-numbers + selector = `[id="${selector.replace('#', '')}"]` + } + + const anchor = document.querySelector(selector) + const headerOffset = 80 // 100px for header + const elementPosition = anchor ? anchor.getBoundingClientRect().top : 0 + const newScrollTop = elementPosition + window.scrollY - headerOffset + + window.scrollTo({ + top: newScrollTop, + behavior: 'smooth' + }) +} + +const handleClientRouteLinkClick = async (event) => { const link = event.target.closest('a') if (!checkOpenOnClient(link, event)) { @@ -77,31 +99,37 @@ const handleClientRouteLinkClick = (event) => { searchParamsStore.open(params) } - if (url.hash) { - let selector = url.hash - - if (/^#\d+/.test(selector)) { - // id="1" fix - // https://stackoverflow.com/questions/20306204/using-queryselector-with-ids-that-are-numbers - selector = `[id="${selector.replace('#', '')}"]` - } - - const anchor = document.querySelector(selector) - const headerOffset = 80 // 100px for header - const elementPosition = anchor ? anchor.getBoundingClientRect().top : 0 - const newScrollTop = elementPosition + window.scrollY - headerOffset - + if (!url.hash) { window.scrollTo({ - top: newScrollTop, - behavior: 'smooth' + top: 0, + left: 0 }) return } - window.scrollTo({ - top: 0, - left: 0 + await getPageLoadManagerPromise() + + const images = document.querySelectorAll('img') + + let imagesLoaded = 0 + + const imageLoadEventHandler = () => { + imagesLoaded++ + if (imagesLoaded === images.length) { + scrollToHash(url.hash) + images.forEach((image) => image.removeEventListener('load', imageLoadEventHandler)) + images.forEach((image) => image.removeEventListener('error', imageLoadEventHandler)) + } + } + + images.forEach((image) => { + if (image.complete) { + imagesLoaded++ + } + + image.addEventListener('load', imageLoadEventHandler) + image.addEventListener('error', imageLoadEventHandler) }) } diff --git a/src/utils/pageLoadManager.ts b/src/utils/pageLoadManager.ts new file mode 100644 index 00000000..d04a3d3d --- /dev/null +++ b/src/utils/pageLoadManager.ts @@ -0,0 +1,11 @@ +const pageLoadManager: { + promise: Promise +} = { promise: Promise.resolve() } + +export const getPageLoadManagerPromise = () => { + return pageLoadManager.promise +} + +export const setPageLoadManagerPromise = (promise: Promise) => { + pageLoadManager.promise = promise +}