2023-09-29 16:01:27 +02:00
|
|
|
// __SDEFILE__ - This file is a dependency for the stand-alone environment
|
2023-03-26 06:50:59 +02:00
|
|
|
// Dependencies
|
2023-04-28 21:23:06 +02:00
|
|
|
import React, { useState, useEffect, useContext } from 'react'
|
2023-11-03 15:36:09 +01:00
|
|
|
import { ogUrl, nsMerge } from 'shared/utils.mjs'
|
|
|
|
import { siteConfig } from 'site/site.config.mjs'
|
2023-09-04 08:40:05 +02:00
|
|
|
// Context
|
|
|
|
import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs'
|
2023-03-26 06:50:59 +02:00
|
|
|
// Hooks
|
|
|
|
import { useTheme } from 'shared/hooks/use-theme.mjs'
|
|
|
|
// Components
|
2023-06-17 16:57:17 -05:00
|
|
|
import Head from 'next/head'
|
2023-04-25 17:33:34 +02:00
|
|
|
import { SwipeWrapper } from 'shared/components/wrappers/swipes.mjs'
|
2023-06-20 16:52:00 -05:00
|
|
|
import { LayoutWrapper, ns as layoutNs } from 'shared/components/wrappers/layout.mjs'
|
2023-07-15 10:45:44 +02:00
|
|
|
import { DefaultLayout, ns as defaultLayoutNs } from 'site/components/layouts/default.mjs'
|
2023-03-26 06:50:59 +02:00
|
|
|
import { Feeds } from 'site/components/feeds.mjs'
|
2023-04-28 21:23:06 +02:00
|
|
|
import { ModalContext } from 'shared/context/modal-context.mjs'
|
2023-03-26 06:50:59 +02:00
|
|
|
|
2023-10-22 18:43:17 +02:00
|
|
|
export const ns = nsMerge(layoutNs, defaultLayoutNs, 'status', 'hodl')
|
2023-03-26 06:50:59 +02:00
|
|
|
|
|
|
|
/* This component should wrap all page content */
|
2023-04-28 21:23:06 +02:00
|
|
|
export const PageWrapper = (props) => {
|
|
|
|
/*
|
|
|
|
* Deconstruct props
|
|
|
|
*/
|
2023-11-03 15:36:09 +01:00
|
|
|
const {
|
|
|
|
layout = DefaultLayout,
|
|
|
|
footer = true,
|
|
|
|
header = true,
|
|
|
|
locale = 'en',
|
|
|
|
children = [],
|
|
|
|
path = [],
|
|
|
|
} = props
|
2023-04-28 21:23:06 +02:00
|
|
|
// Title is typically set in props.t but check props.title too
|
|
|
|
const pageTitle = props.t ? props.t : props.title ? props.title : null
|
|
|
|
|
2023-07-15 16:55:22 +02:00
|
|
|
/*
|
|
|
|
* Slug should come from page props.path not from context
|
|
|
|
* which won't be available in SSR
|
|
|
|
*/
|
|
|
|
const slug = path.join('/')
|
|
|
|
|
2023-05-20 13:22:36 +02:00
|
|
|
/*
|
|
|
|
* Contexts
|
|
|
|
*/
|
2023-06-23 17:45:50 -05:00
|
|
|
const { modalContent } = useContext(ModalContext)
|
2023-09-04 08:40:05 +02:00
|
|
|
const { LoadingStatus } = useContext(LoadingStatusContext)
|
2023-05-20 13:22:36 +02:00
|
|
|
|
2023-03-26 06:50:59 +02:00
|
|
|
/*
|
|
|
|
* This forces a re-render upon initial bootstrap of the app
|
|
|
|
* This is needed to avoid hydration errors because theme can't be set reliably in SSR
|
|
|
|
*/
|
2023-07-29 14:21:59 +02:00
|
|
|
const { theme } = useTheme()
|
2023-03-26 06:50:59 +02:00
|
|
|
const [currentTheme, setCurrentTheme] = useState()
|
2023-05-20 14:47:29 +02:00
|
|
|
useEffect(() => setCurrentTheme(theme), [currentTheme, theme])
|
2023-03-26 06:50:59 +02:00
|
|
|
|
|
|
|
// Helper object to pass props down (keeps things DRY)
|
2023-07-15 16:55:22 +02:00
|
|
|
const childProps = { footer, header, pageTitle, slug }
|
2023-03-26 06:50:59 +02:00
|
|
|
|
|
|
|
// Make layout prop into a (uppercase) component
|
|
|
|
const Layout = layout
|
|
|
|
|
|
|
|
// Return wrapper
|
|
|
|
return (
|
2023-04-28 21:23:06 +02:00
|
|
|
<SwipeWrapper>
|
2023-06-17 16:57:17 -05:00
|
|
|
{pageTitle && (
|
|
|
|
<Head>
|
|
|
|
<meta property="og:title" content={pageTitle} key="title" />
|
2023-10-06 09:15:07 +02:00
|
|
|
{props.intro && (
|
|
|
|
<meta property="og:description" content={props.intro} key="description" />
|
|
|
|
)}
|
2023-11-03 15:36:09 +01:00
|
|
|
<meta property="og:title" content={pageTitle} key="title" />
|
|
|
|
<meta property="og:type" content="article" key="type" />
|
|
|
|
<meta property="og:article:author" content="Joost De Cock" key="author" />
|
|
|
|
<meta
|
|
|
|
property="og:image"
|
|
|
|
content={`${ogUrl({ site: siteConfig.tld, title: pageTitle, intro: props.intro })}`}
|
|
|
|
key="image"
|
|
|
|
/>
|
|
|
|
<meta property="og:image:type" content="image/png" />
|
|
|
|
<meta property="og:image:width" content="2400" />
|
|
|
|
<meta property="og:image:height" content="1260" />
|
|
|
|
<meta
|
|
|
|
property="og:url"
|
|
|
|
content={`https://FreeSewing.${siteConfig.tld}/${path.join('/')}`}
|
|
|
|
key="url"
|
|
|
|
/>
|
|
|
|
<meta property="og:locale" content={locale} key="locale" />
|
|
|
|
<meta property="og:site_name" content={`FreeSewing.${siteConfig.tld}`} key="site" />
|
|
|
|
<title>{pageTitle}</title>
|
2023-06-17 16:57:17 -05:00
|
|
|
</Head>
|
|
|
|
)}
|
2023-04-28 21:23:06 +02:00
|
|
|
<div
|
|
|
|
data-theme={currentTheme} // This facilitates CSS selectors
|
|
|
|
key={currentTheme} // This forces the data-theme update
|
|
|
|
>
|
2023-09-04 08:40:05 +02:00
|
|
|
<LoadingStatus />
|
2023-04-28 21:23:06 +02:00
|
|
|
<Feeds />
|
|
|
|
<LayoutWrapper {...childProps}>
|
|
|
|
{Layout ? <Layout {...childProps}>{children}</Layout> : children}
|
|
|
|
</LayoutWrapper>
|
2023-06-23 17:45:50 -05:00
|
|
|
{typeof modalContent === 'function' ? modalContent() : modalContent}
|
2023-04-28 21:23:06 +02:00
|
|
|
</div>
|
|
|
|
</SwipeWrapper>
|
2023-03-26 06:50:59 +02:00
|
|
|
)
|
|
|
|
}
|