diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index c93507b7..fea0d97f 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -23,6 +23,7 @@ "react-aria-components": "1.2.1", "react-dom": "18.2.0", "react-i18next": "14.1.3", + "valtio": "1.13.2", "wouter": "3.3.0" }, "devDependencies": { @@ -3643,13 +3644,13 @@ "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true + "devOptional": true }, "node_modules/@types/react": { "version": "18.3.3", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", - "dev": true, + "devOptional": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -5134,7 +5135,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "devOptional": true }, "node_modules/damerau-levenshtein": { "version": "1.0.8", @@ -5282,6 +5283,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/derive-valtio": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/derive-valtio/-/derive-valtio-0.1.0.tgz", + "integrity": "sha512-OCg2UsLbXK7GmmpzMXhYkdO64vhJ1ROUUGaTFyHjVwEdMEcTTRj7W1TxLbSBxdY8QLBPCcp66MTyaSy0RpO17A==", + "peerDependencies": { + "valtio": "*" + } + }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -8937,6 +8946,11 @@ "node": "10.* || >= 12.*" } }, + "node_modules/proxy-compare": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.6.0.tgz", + "integrity": "sha512-8xuCeM3l8yqdmbPoYeLbrAXCBWu19XEYc5/F28f5qOaoAIMyfmBUkl5axiK+x9olUvRlcekvnm98AP9RDngOIw==" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -10101,6 +10115,39 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/valtio": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/valtio/-/valtio-1.13.2.tgz", + "integrity": "sha512-Qik0o+DSy741TmkqmRfjq+0xpZBXi/Y6+fXZLn0xNF1z/waFMbE3rkivv5Zcf9RrMUp6zswf2J7sbh2KBlba5A==", + "dependencies": { + "derive-valtio": "0.1.0", + "proxy-compare": "2.6.0", + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/valtio/node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/value-or-function": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-4.0.0.tgz", diff --git a/src/frontend/package.json b/src/frontend/package.json index 7e068a7f..8495a491 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -26,6 +26,7 @@ "react-aria-components": "1.2.1", "react-dom": "18.2.0", "react-i18next": "14.1.3", + "valtio": "1.13.2", "wouter": "3.3.0" }, "devDependencies": { diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 9a055d34..4c61e898 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -6,8 +6,8 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { useTranslation } from 'react-i18next' import { useLang } from 'hoofd' import { Switch, Route } from 'wouter' -import { NotFoundScreen } from './layout/NotFoundScreen' -import { RenderIfUserFetched } from './features/auth' +import { Layout } from './layout/Layout' +import { NotFoundScreen } from './components/NotFoundScreen' import { routes } from './routes' import './i18n/init' @@ -19,14 +19,14 @@ function App() { return ( - + {Object.entries(routes).map(([, route], i) => ( ))} - + diff --git a/src/frontend/src/components/BackToHome.tsx b/src/frontend/src/components/BackToHome.tsx new file mode 100644 index 00000000..4c6fc287 --- /dev/null +++ b/src/frontend/src/components/BackToHome.tsx @@ -0,0 +1,14 @@ +import { Link } from '@/primitives' +import { AProps } from '@/primitives/A' +import { useTranslation } from 'react-i18next' + +export const BackToHome = ({ size }: { size?: AProps['size'] }) => { + const { t } = useTranslation() + return ( +

+ + {t('backToHome')} + +

+ ) +} diff --git a/src/frontend/src/components/DelayedRender.ts b/src/frontend/src/components/DelayedRender.ts new file mode 100644 index 00000000..e16f3bbe --- /dev/null +++ b/src/frontend/src/components/DelayedRender.ts @@ -0,0 +1,24 @@ +import { useState, useEffect, type ReactNode } from 'react' + +export const DelayedRender = ({ + children, + delay = 500, +}: { + delay?: number + children: ReactNode +}) => { + const [show, setShow] = useState(false) + useEffect(() => { + if (delay === 0) { + setShow(true) + return + } + const timeout = setTimeout(() => setShow(true), delay) + return () => clearTimeout(timeout) + }, [delay]) + if (delay !== 0 && !show) { + return null + } + + return children +} diff --git a/src/frontend/src/components/ErrorScreen.tsx b/src/frontend/src/components/ErrorScreen.tsx new file mode 100644 index 00000000..e33d89f9 --- /dev/null +++ b/src/frontend/src/components/ErrorScreen.tsx @@ -0,0 +1,12 @@ +import { CenteredContent } from '@/layout/CenteredContent' +import { Screen } from '@/layout/Screen' +import { useTranslation } from 'react-i18next' + +export const ErrorScreen = () => { + const { t } = useTranslation() + return ( + + + + ) +} diff --git a/src/frontend/src/components/LoadingScreen.tsx b/src/frontend/src/components/LoadingScreen.tsx new file mode 100644 index 00000000..ded2c21b --- /dev/null +++ b/src/frontend/src/components/LoadingScreen.tsx @@ -0,0 +1,27 @@ +import { Screen, type ScreenProps } from '@/layout/Screen' +import { DelayedRender } from './DelayedRender' +import { CenteredContent } from '@/layout/CenteredContent' +import { useTranslation } from 'react-i18next' +import { Center } from '@/styled-system/jsx' + +export const LoadingScreen = ({ + delay = 500, + header = undefined, + layout = 'centered', +}: { + delay?: number +} & Omit) => { + const { t } = useTranslation() + + return ( + + + +
+

{t('loading')}

+
+
+
+
+ ) +} diff --git a/src/frontend/src/components/NotFoundScreen.tsx b/src/frontend/src/components/NotFoundScreen.tsx new file mode 100644 index 00000000..56caf247 --- /dev/null +++ b/src/frontend/src/components/NotFoundScreen.tsx @@ -0,0 +1,12 @@ +import { CenteredContent } from '@/layout/CenteredContent' +import { Screen } from '@/layout/Screen' +import { useTranslation } from 'react-i18next' + +export const NotFoundScreen = () => { + const { t } = useTranslation() + return ( + + + + ) +} diff --git a/src/frontend/src/components/QueryAware.tsx b/src/frontend/src/components/QueryAware.tsx new file mode 100644 index 00000000..54946b56 --- /dev/null +++ b/src/frontend/src/components/QueryAware.tsx @@ -0,0 +1,28 @@ +import { ErrorScreen } from '@/components/ErrorScreen' +import { LoadingScreen } from '@/components/LoadingScreen' + +/** + * Render an error or loading Screen while a given `status` is not a success, + * otherwise directly render children. + * + * `status` matches react query statuses. + * + * Children usually contain a Screen at some point in the render tree. + */ +export const QueryAware = ({ + status, + children, +}: { + status: 'error' | 'pending' | 'success' + children: React.ReactNode +}) => { + if (status === 'error') { + return + } + + if (status === 'pending') { + return + } + + return children +} diff --git a/src/frontend/src/features/auth/components/RenderIfUserFetched.tsx b/src/frontend/src/features/auth/components/RenderIfUserFetched.tsx deleted file mode 100644 index 276a0133..00000000 --- a/src/frontend/src/features/auth/components/RenderIfUserFetched.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { type ReactNode } from 'react' -import { useUser } from '@/features/auth' -import { LoadingScreen } from '@/layout/LoadingScreen' - -/** - * wrapper that renders children only when user info has been actually fetched - * - * this is helpful to prevent flash of logged-out content for a few milliseconds when user is actually logged in - */ -export const RenderIfUserFetched = ({ children }: { children: ReactNode }) => { - const { isLoggedIn } = useUser() - return isLoggedIn !== undefined ? ( - children - ) : ( - - ) -} diff --git a/src/frontend/src/features/auth/components/UserAware.tsx b/src/frontend/src/features/auth/components/UserAware.tsx new file mode 100644 index 00000000..3a4b84cb --- /dev/null +++ b/src/frontend/src/features/auth/components/UserAware.tsx @@ -0,0 +1,20 @@ +import { useUser } from '@/features/auth' +import { LoadingScreen } from '@/components/LoadingScreen' + +/** + * Renders a loading Screen while user info has not been fetched yet, + * otherwise directly render children. + * + * Children usually contain a Screen at some point in the render tree. + * + * This is helpful to prevent flash of logged-out content for a few milliseconds when user is actually logged in + */ +export const UserAware = ({ children }: { children: React.ReactNode }) => { + const { isLoggedIn } = useUser() + + return isLoggedIn !== undefined ? ( + children + ) : ( + + ) +} diff --git a/src/frontend/src/features/auth/index.ts b/src/frontend/src/features/auth/index.ts index 0b533fea..c08b819e 100644 --- a/src/frontend/src/features/auth/index.ts +++ b/src/frontend/src/features/auth/index.ts @@ -1,4 +1,4 @@ export { useUser } from './api/useUser' export { authUrl } from './utils/authUrl' export { logoutUrl } from './utils/logoutUrl' -export { RenderIfUserFetched } from './components/RenderIfUserFetched' +export { UserAware } from './components/UserAware' diff --git a/src/frontend/src/features/home/routes/Home.tsx b/src/frontend/src/features/home/routes/Home.tsx index 32130928..69b5e234 100644 --- a/src/frontend/src/features/home/routes/Home.tsx +++ b/src/frontend/src/features/home/routes/Home.tsx @@ -1,20 +1,21 @@ import { useTranslation } from 'react-i18next' import { DialogTrigger } from 'react-aria-components' -import { Button, Div, Text, VerticallyOffCenter } from '@/primitives' +import { Button, Text } from '@/primitives' import { HStack } from '@/styled-system/jsx' import { navigateTo } from '@/navigation/navigateTo' -import { generateRoomId } from '@/features/rooms' -import { authUrl, useUser } from '@/features/auth' import { Screen } from '@/layout/Screen' +import { Centered } from '@/layout/Centered' +import { generateRoomId } from '@/features/rooms' +import { authUrl, useUser, UserAware } from '@/features/auth' import { JoinMeetingDialog } from '../components/JoinMeetingDialog' export const Home = () => { const { t } = useTranslation('home') const { isLoggedIn } = useUser() return ( - - -
+ + + {t('heading')} @@ -49,8 +50,8 @@ export const Home = () => { -
-
-
+ + + ) } diff --git a/src/frontend/src/features/rooms/components/Conference.tsx b/src/frontend/src/features/rooms/components/Conference.tsx index 0e820338..5f0dd4ae 100644 --- a/src/frontend/src/features/rooms/components/Conference.tsx +++ b/src/frontend/src/features/rooms/components/Conference.tsx @@ -8,7 +8,8 @@ import { import { Room, RoomOptions } from 'livekit-client' import { keys } from '@/api/queryKeys' import { navigateTo } from '@/navigation/navigateTo' -import { QueryAware } from '@/layout/QueryAware' +import { Screen } from '@/layout/Screen' +import { QueryAware } from '@/components/QueryAware' import { fetchRoom } from '../api/fetchRoom' import { InviteDialog } from './InviteDialog' @@ -67,24 +68,26 @@ export const Conference = ({ return ( - - - {showInviteDialog && ( - setShowInviteDialog(false)} - /> - )} - + + + + {showInviteDialog && ( + setShowInviteDialog(false)} + /> + )} + + ) } diff --git a/src/frontend/src/features/rooms/components/Join.tsx b/src/frontend/src/features/rooms/components/Join.tsx index 03da5a4e..0657ec97 100644 --- a/src/frontend/src/features/rooms/components/Join.tsx +++ b/src/frontend/src/features/rooms/components/Join.tsx @@ -1,6 +1,7 @@ import { useTranslation } from 'react-i18next' -import { Box } from '@/layout/Box' import { PreJoin, type LocalUserChoices } from '@livekit/components-react' +import { Screen } from '@/layout/Screen' +import { CenteredContent } from '@/layout/CenteredContent' export const Join = ({ onSubmit, @@ -10,15 +11,17 @@ export const Join = ({ const { t } = useTranslation('rooms') return ( - - - + + + + + ) } diff --git a/src/frontend/src/features/rooms/routes/Feedback.tsx b/src/frontend/src/features/rooms/routes/Feedback.tsx index 468c73fb..bb4fa34a 100644 --- a/src/frontend/src/features/rooms/routes/Feedback.tsx +++ b/src/frontend/src/features/rooms/routes/Feedback.tsx @@ -1,19 +1,15 @@ import { useTranslation } from 'react-i18next' -import { BoxScreen } from '@/layout/BoxScreen' -import { Div, Link, P } from '@/primitives' +import { P } from '@/primitives' +import { Screen } from '@/layout/Screen' +import { CenteredContent } from '@/layout/CenteredContent' export const FeedbackRoute = () => { const { t } = useTranslation('rooms') return ( - -
+ +

{t('feedback.body')}

-
-
-

- {t('backToHome', { ns: 'global' })} -

-
-
+ + ) } diff --git a/src/frontend/src/features/rooms/routes/Room.tsx b/src/frontend/src/features/rooms/routes/Room.tsx index 83de6cbf..a0e5e6f8 100644 --- a/src/frontend/src/features/rooms/routes/Room.tsx +++ b/src/frontend/src/features/rooms/routes/Room.tsx @@ -4,9 +4,8 @@ import { type LocalUserChoices, } from '@livekit/components-react' import { useParams } from 'wouter' -import { Screen } from '@/layout/Screen' -import { ErrorScreen } from '@/layout/ErrorScreen' -import { useUser } from '@/features/auth' +import { ErrorScreen } from '@/components/ErrorScreen' +import { useUser, UserAware } from '@/features/auth' import { Conference } from '../components/Conference' import { Join } from '../components/Join' @@ -25,21 +24,23 @@ export const Room = () => { if (!userConfig && !skipJoinScreen) { return ( - + - + ) } return ( - + + + ) } diff --git a/src/frontend/src/layout/Box.tsx b/src/frontend/src/layout/Box.tsx deleted file mode 100644 index 90fc2b44..00000000 --- a/src/frontend/src/layout/Box.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import type { ReactNode } from 'react' -import { useTranslation } from 'react-i18next' -import { Box as BoxDiv, H, Link, VerticallyOffCenter } from '@/primitives' - -export type BoxProps = { - children?: ReactNode - title?: ReactNode - withBackButton?: boolean -} - -export const Box = ({ - children, - title = '', - withBackButton = false, -}: BoxProps) => { - const { t } = useTranslation() - return ( - - - {!!title && {title}} - {children} - {!!withBackButton && ( -

- - {t('backToHome')} - -

- )} -
-
- ) -} diff --git a/src/frontend/src/layout/BoxScreen.tsx b/src/frontend/src/layout/BoxScreen.tsx deleted file mode 100644 index 147639b2..00000000 --- a/src/frontend/src/layout/BoxScreen.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { Screen } from './Screen' -import { Box, type BoxProps } from './Box' - -export const BoxScreen = (props: BoxProps) => { - return ( - - - - ) -} diff --git a/src/frontend/src/layout/Centered.tsx b/src/frontend/src/layout/Centered.tsx new file mode 100644 index 00000000..5a403152 --- /dev/null +++ b/src/frontend/src/layout/Centered.tsx @@ -0,0 +1,19 @@ +import type { ReactNode } from 'react' +import { Div, VerticallyOffCenter } from '@/primitives' +import type { SystemStyleObject } from '../styled-system/types' + +export const Centered = ({ + width = '38rem', + children, +}: { + width?: SystemStyleObject['width'] + children?: ReactNode +}) => { + return ( + +
+ {children} +
+
+ ) +} diff --git a/src/frontend/src/layout/CenteredContent.tsx b/src/frontend/src/layout/CenteredContent.tsx new file mode 100644 index 00000000..c4a3fbf8 --- /dev/null +++ b/src/frontend/src/layout/CenteredContent.tsx @@ -0,0 +1,29 @@ +import { BackToHome } from '@/components/BackToHome' +import { H } from '@/primitives' +import { Center } from '@/styled-system/jsx' + +export const CenteredContent = ({ + title, + children, + withBackButton, +}: { + title?: string + children?: React.ReactNode + withBackButton?: boolean +}) => { + return ( + <> + {!!title && ( +
+ {title} +
+ )} + {children} + {!!withBackButton && ( +
+ +
+ )} + + ) +} diff --git a/src/frontend/src/layout/ErrorScreen.tsx b/src/frontend/src/layout/ErrorScreen.tsx deleted file mode 100644 index 6f820ad0..00000000 --- a/src/frontend/src/layout/ErrorScreen.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { BoxScreen } from './BoxScreen' -import { useTranslation } from 'react-i18next' - -export const ErrorScreen = () => { - const { t } = useTranslation() - return -} diff --git a/src/frontend/src/layout/ForbiddenScreen.tsx b/src/frontend/src/layout/ForbiddenScreen.tsx deleted file mode 100644 index fefd0555..00000000 --- a/src/frontend/src/layout/ForbiddenScreen.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { BoxScreen } from './BoxScreen' -import { useTranslation } from 'react-i18next' - -export const ForbiddenScreen = () => { - const { t } = useTranslation() - return -} diff --git a/src/frontend/src/layout/Layout.tsx b/src/frontend/src/layout/Layout.tsx new file mode 100644 index 00000000..9159a0c7 --- /dev/null +++ b/src/frontend/src/layout/Layout.tsx @@ -0,0 +1,42 @@ +import { type ReactNode } from 'react' +import { css } from '@/styled-system/css' +import { Header } from './Header' +import { layoutStore } from '@/stores/layout' +import { useSnapshot } from 'valtio' + +export type Layout = 'fullpage' | 'centered' + +/** + * Layout component for the app. + * + * This component is meant to be used as a wrapper around the whole app. + * In a specific page, use the `Screen` component and change its props to change global page layout. + */ +export const Layout = ({ children }: { children: ReactNode }) => { + const layoutSnap = useSnapshot(layoutStore) + const showHeader = layoutSnap.showHeader + + return ( +
+ {showHeader &&
} +
+ {children} +
+
+ ) +} diff --git a/src/frontend/src/layout/LoadingScreen.tsx b/src/frontend/src/layout/LoadingScreen.tsx deleted file mode 100644 index 167c6205..00000000 --- a/src/frontend/src/layout/LoadingScreen.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { useState, useEffect } from 'react' -import { useTranslation } from 'react-i18next' -import { BoxScreen } from './BoxScreen' -import { Screen } from './Screen' -import { VerticallyOffCenter } from '@/primitives' -import { Center } from '@/styled-system/jsx' - -export const LoadingScreen = ({ - asBox = false, - renderTimeout = 500, -}: { - asBox?: boolean - renderTimeout?: number -}) => { - const { t } = useTranslation() - // show the loading screen only after a little while to prevent flash of texts - const [show, setShow] = useState(false) - useEffect(() => { - const timeout = setTimeout(() => setShow(true), renderTimeout) - return () => clearTimeout(timeout) - }, [renderTimeout]) - if (!show) { - return null - } - const Container = asBox ? BoxScreen : Screen - return ( - - -
-

{t('loading')}

-
-
-
- ) -} diff --git a/src/frontend/src/layout/NotFoundScreen.tsx b/src/frontend/src/layout/NotFoundScreen.tsx deleted file mode 100644 index 7d4283a0..00000000 --- a/src/frontend/src/layout/NotFoundScreen.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { useTranslation } from 'react-i18next' -import { BoxScreen } from './BoxScreen' - -export const NotFoundScreen = () => { - const { t } = useTranslation() - return -} diff --git a/src/frontend/src/layout/QueryAware.tsx b/src/frontend/src/layout/QueryAware.tsx deleted file mode 100644 index b396d697..00000000 --- a/src/frontend/src/layout/QueryAware.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { ErrorScreen } from './ErrorScreen' -import { LoadingScreen } from './LoadingScreen' -import { Screen } from './Screen' - -export const QueryAware = ({ - status, - children, -}: { - status: 'error' | 'pending' | 'success' - children: React.ReactNode -}) => { - if (status === 'error') { - return - } - - if (status === 'pending') { - return - } - - return {children} -} diff --git a/src/frontend/src/layout/Screen.tsx b/src/frontend/src/layout/Screen.tsx index d5c144dc..189dca38 100644 --- a/src/frontend/src/layout/Screen.tsx +++ b/src/frontend/src/layout/Screen.tsx @@ -1,35 +1,30 @@ -import type { ReactNode } from 'react' -import { css } from '@/styled-system/css' -import { Header } from './Header' +import { layoutStore } from '@/stores/layout' +import { Layout } from './Layout' +import { useEffect } from 'react' +import { Centered } from './Centered' + +export type ScreenProps = { + /** + * 'fullpage' by default. + */ + layout?: Layout + /** + * Show header or not. + * True by default. Pass undefined to render the screen without modifying current header visibility + */ + header?: boolean + children: React.ReactNode +} export const Screen = ({ - type, + layout = 'fullpage', + header = true, children, -}: { - type?: 'splash' - children?: ReactNode -}) => { - return ( -
- {type !== 'splash' &&
} -
- {children} -
-
- ) +}: ScreenProps) => { + useEffect(() => { + if (header !== undefined) { + layoutStore.showHeader = header + } + }, [header]) + return layout === 'centered' ? {children} : children } diff --git a/src/frontend/src/stores/layout.ts b/src/frontend/src/stores/layout.ts new file mode 100644 index 00000000..bee6baed --- /dev/null +++ b/src/frontend/src/stores/layout.ts @@ -0,0 +1,9 @@ +import { proxy } from 'valtio' + +type State = { + showHeader: boolean +} + +export const layoutStore = proxy({ + showHeader: false, +}) diff --git a/src/frontend/src/styles/livekit.css b/src/frontend/src/styles/livekit.css index 11b940b0..07164ac0 100644 --- a/src/frontend/src/styles/livekit.css +++ b/src/frontend/src/styles/livekit.css @@ -145,6 +145,7 @@ [data-lk-theme] .lk-prejoin { padding-top: 0; + width: 100%; } [data-lk-theme] .lk-participant-tile {