Commit c09b5446 authored by isstuev's avatar isstuev

ssr

parent 323fbf69
import {
ChakraProvider,
cookieStorageManagerSSR,
localStorageManager,
} from '@chakra-ui/react';
import type { ChakraProviderProps } from '@chakra-ui/react';
import React from 'react';
interface Props extends ChakraProviderProps {
cookies?: string;
}
export function Chakra({ cookies, theme, children }: Props) {
const colorModeManager =
typeof cookies === 'string' ?
cookieStorageManagerSSR(cookies) :
localStorageManager;
return (
<ChakraProvider colorModeManager={ colorModeManager } theme={ theme }>
{ children }
</ChakraProvider>
);
}
...@@ -21,3 +21,7 @@ export function set(name: string, value: string, attributes: Types.CookieAttribu ...@@ -21,3 +21,7 @@ export function set(name: string, value: string, attributes: Types.CookieAttribu
return Cookies.set(name, value, attributes); return Cookies.set(name, value, attributes);
} }
export function getFromCookieString(cookieString: string, name: NAMES) {
return cookieString.split(`${ name }=`)[1]?.split(';')[0];
}
import React, { createContext, useContext } from 'react';
import type { Props as PageProps } from 'lib/next/getServerSideProps';
type Props = {
children: React.ReactNode;
pageProps: PageProps;
}
const AppContext = createContext<PageProps>({ cookies: '' });
export function AppWrapper({ children, pageProps }: Props) {
const appProps = { cookies: pageProps.cookies };
return (
<AppContext.Provider value={ appProps }>
{ children }
</AppContext.Provider>
);
}
export function useAppContext() {
return useContext(AppContext);
}
import type { GetServerSideProps } from 'next'; import type { GetServerSideProps, GetServerSidePropsResult } from 'next';
export const getServerSideProps: GetServerSideProps = async({ res }) => { export type Props = {
cookies: string;
}
export const getServerSideProps: GetServerSideProps = async({ req, res }): Promise<GetServerSidePropsResult<Props>> => {
res.setHeader( res.setHeader(
'Cache-Control', 'Cache-Control',
`public, s-maxage=${ 60 * 60 }, stale-while-revalidate=${ 2 * 60 * 60 }`, `public, s-maxage=${ 60 * 60 }, stale-while-revalidate=${ 2 * 60 * 60 }`,
); );
return { props: {} }; return {
props: {
cookies: req.headers.cookie || '',
},
};
}; };
import type { GetStaticPaths } from 'next';
export const getStaticPaths: GetStaticPaths = async() => {
return { paths: [], fallback: 'blocking' };
};
import type { GetStaticProps, GetStaticPropsResult } from 'next';
export const getStaticProps: GetStaticProps = async(): Promise<GetStaticPropsResult<{ [key: string]: unknown }>> => {
return {
props: {},
};
};
import { ChakraProvider } from '@chakra-ui/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import type { AppProps } from 'next/app'; import type { AppProps } from 'next/app';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Chakra } from 'lib/Chakra';
import useConfigSentry from 'lib/hooks/useConfigSentry'; import useConfigSentry from 'lib/hooks/useConfigSentry';
import type { ErrorType } from 'lib/hooks/useFetch'; import type { ErrorType } from 'lib/hooks/useFetch';
import { AppWrapper } from 'lib/next/AppWrapper';
import theme from 'theme'; import theme from 'theme';
function MyApp({ Component, pageProps }: AppProps) { function MyApp({ Component, pageProps }: AppProps) {
...@@ -30,12 +31,14 @@ function MyApp({ Component, pageProps }: AppProps) { ...@@ -30,12 +31,14 @@ function MyApp({ Component, pageProps }: AppProps) {
})); }));
return ( return (
<QueryClientProvider client={ queryClient }> <AppWrapper pageProps={ pageProps }>
<ChakraProvider theme={ theme }> <QueryClientProvider client={ queryClient }>
<Component { ...pageProps }/> <Chakra theme={ theme } cookies={ pageProps.cookies }>
</ChakraProvider> <Component { ...pageProps }/>
<ReactQueryDevtools/> </Chakra>
</QueryClientProvider> <ReactQueryDevtools/>
</QueryClientProvider>
</AppWrapper>
); );
} }
......
...@@ -17,4 +17,4 @@ const ApiKeysPage: NextPage = () => { ...@@ -17,4 +17,4 @@ const ApiKeysPage: NextPage = () => {
export default ApiKeysPage; export default ApiKeysPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsDummy'; export { getServerSideProps } from 'lib/next/getServerSideProps';
...@@ -17,4 +17,4 @@ const CustomAbiPage: NextPage = () => { ...@@ -17,4 +17,4 @@ const CustomAbiPage: NextPage = () => {
export default CustomAbiPage; export default CustomAbiPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsDummy'; export { getServerSideProps } from 'lib/next/getServerSideProps';
...@@ -17,4 +17,4 @@ const PublicTagsPage: NextPage = () => { ...@@ -17,4 +17,4 @@ const PublicTagsPage: NextPage = () => {
export default PublicTagsPage; export default PublicTagsPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsDummy'; export { getServerSideProps } from 'lib/next/getServerSideProps';
...@@ -17,4 +17,4 @@ const AddressTagsPage: NextPage = () => { ...@@ -17,4 +17,4 @@ const AddressTagsPage: NextPage = () => {
export default AddressTagsPage; export default AddressTagsPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsDummy'; export { getServerSideProps } from 'lib/next/getServerSideProps';
...@@ -19,4 +19,4 @@ const WatchListPage: NextPage = () => { ...@@ -19,4 +19,4 @@ const WatchListPage: NextPage = () => {
export default WatchListPage; export default WatchListPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsDummy'; export { getServerSideProps } from 'lib/next/getServerSideProps';
...@@ -19,4 +19,4 @@ const AppsPage: NextPage = () => { ...@@ -19,4 +19,4 @@ const AppsPage: NextPage = () => {
export default AppsPage; export default AppsPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsDummy'; export { getServerSideProps } from 'lib/next/getServerSideProps';
...@@ -47,5 +47,4 @@ const AppPage: NextPage = () => { ...@@ -47,5 +47,4 @@ const AppPage: NextPage = () => {
export default AppPage; export default AppPage;
export { getStaticPaths } from 'lib/next/getStaticPaths'; export { getServerSideProps } from 'lib/next/getServerSideProps';
export { getStaticProps } from 'lib/next/getStaticProps';
...@@ -15,4 +15,4 @@ const MyProfilePage: NextPage = () => { ...@@ -15,4 +15,4 @@ const MyProfilePage: NextPage = () => {
export default MyProfilePage; export default MyProfilePage;
export { getServerSideProps } from 'lib/next/getServerSidePropsDummy'; export { getServerSideProps } from 'lib/next/getServerSideProps';
...@@ -17,5 +17,4 @@ const BlockPage: NextPage<Props> = ({ pageParams }: Props) => { ...@@ -17,5 +17,4 @@ const BlockPage: NextPage<Props> = ({ pageParams }: Props) => {
export default BlockPage; export default BlockPage;
export { getStaticPaths } from 'lib/next/getStaticPaths'; export { getServerSideProps } from 'lib/next/getServerSideProps';
export { getStaticProps } from 'lib/next/getStaticProps';
...@@ -11,4 +11,4 @@ const BlockPage: NextPage = () => { ...@@ -11,4 +11,4 @@ const BlockPage: NextPage = () => {
export default BlockPage; export default BlockPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsDummy'; export { getServerSideProps } from 'lib/next/getServerSideProps';
...@@ -15,4 +15,4 @@ const HomePage: NextPage = () => { ...@@ -15,4 +15,4 @@ const HomePage: NextPage = () => {
export default HomePage; export default HomePage;
export { getServerSideProps } from 'lib/next/getServerSidePropsDummy'; export { getServerSideProps } from 'lib/next/getServerSideProps';
...@@ -17,5 +17,4 @@ const TransactionPage: NextPage<Props> = ({ pageParams }: Props) => { ...@@ -17,5 +17,4 @@ const TransactionPage: NextPage<Props> = ({ pageParams }: Props) => {
export default TransactionPage; export default TransactionPage;
export { getStaticPaths } from 'lib/next/getStaticPaths'; export { getServerSideProps } from 'lib/next/getServerSideProps';
export { getStaticProps } from 'lib/next/getStaticProps';
...@@ -17,4 +17,4 @@ const TxsPage: NextPage = () => { ...@@ -17,4 +17,4 @@ const TxsPage: NextPage = () => {
export default TxsPage; export default TxsPage;
export { getServerSideProps } from 'lib/next/getServerSidePropsDummy'; export { getServerSideProps } from 'lib/next/getServerSideProps';
...@@ -9,7 +9,7 @@ import PageTitle from 'ui/shared/Page/PageTitle'; ...@@ -9,7 +9,7 @@ import PageTitle from 'ui/shared/Page/PageTitle';
import UserAvatar from 'ui/shared/UserAvatar'; import UserAvatar from 'ui/shared/UserAvatar';
const MyProfile = () => { const MyProfile = () => {
const { data, isLoading, isError } = useFetchProfileInfo(); const { data, isLoading, isError, isFetched } = useFetchProfileInfo();
const content = (() => { const content = (() => {
if (isLoading) { if (isLoading) {
...@@ -22,7 +22,7 @@ const MyProfile = () => { ...@@ -22,7 +22,7 @@ const MyProfile = () => {
return ( return (
<VStack maxW="412px" mt={ 12 } gap={ 5 } alignItems="stretch"> <VStack maxW="412px" mt={ 12 } gap={ 5 } alignItems="stretch">
<UserAvatar size={ 64 } data={ data }/> <UserAvatar size={ 64 } data={ data } isFetched={ isFetched }/>
<FormControl variant="floating" id="name" isRequired size="lg"> <FormControl variant="floating" id="name" isRequired size="lg">
<Input <Input
required required
......
...@@ -18,7 +18,11 @@ interface Props { ...@@ -18,7 +18,11 @@ interface Props {
hideMobileHeaderOnScrollDown?: boolean; hideMobileHeaderOnScrollDown?: boolean;
} }
const Page = ({ children, wrapChildren = true, hideMobileHeaderOnScrollDown }: Props) => { const Page = ({
children,
wrapChildren = true,
hideMobileHeaderOnScrollDown,
}: Props) => {
const fetch = useFetch(); const fetch = useFetch();
useQuery<unknown, unknown, unknown>([ QueryKeys.csrf ], async() => await fetch('/node-api/account/csrf'), { useQuery<unknown, unknown, unknown>([ QueryKeys.csrf ], async() => await fetch('/node-api/account/csrf'), {
......
import { useColorModeValue, chakra, Image } from '@chakra-ui/react'; import { useColorModeValue, chakra, Box, Image } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import Identicon from 'react-identicons'; import Identicon from 'react-identicons';
import type { UserInfo } from 'types/api/account'; import type { UserInfo } from 'types/api/account';
import * as cookies from 'lib/cookies';
import { useAppContext } from 'lib/next/AppWrapper';
const ProfileIcon = chakra(Identicon); const ProfileIcon = chakra(Identicon);
interface Props { interface Props {
size: number; size: number;
data?: UserInfo; data?: UserInfo;
isFetched: boolean;
} }
const UserAvatar = ({ size, data }: Props) => { const UserAvatar = ({ size, data, isFetched }: Props) => {
const appProps = useAppContext();
const hasAuth = Boolean(cookies.getFromCookieString(appProps.cookies, cookies.NAMES.API_TOKEN));
const sizeString = `${ size }px`; const sizeString = `${ size }px`;
const bgColor = useColorModeValue('blackAlpha.100', 'white'); const bgColor = useColorModeValue('blackAlpha.100', 'white');
// if (hasAuth && !isFetched) {
// }
if (hasAuth && !isFetched) {
return <Box w={ sizeString } h={ sizeString }></Box>;
}
if (data?.avatar) { if (data?.avatar) {
return ( return (
<Image <Image
flexShrink={ 0 } flexShrink={ 0 }
src={ data.avatar } src={ data.avatar }
alt={ `Profile picture of ${ data.name || data.nickname || '' }` } alt={ `Profile picture of ${ data?.name || data?.nickname || '' }` }
w={ sizeString } w={ sizeString }
minW={ sizeString } minW={ sizeString }
h={ sizeString } h={ sizeString }
......
...@@ -5,7 +5,7 @@ import appConfig from 'configs/app/config'; ...@@ -5,7 +5,7 @@ import appConfig from 'configs/app/config';
import chevronIcon from 'icons/arrows/east-mini.svg'; import chevronIcon from 'icons/arrows/east-mini.svg';
import * as cookies from 'lib/cookies'; import * as cookies from 'lib/cookies';
import useNavItems from 'lib/hooks/useNavItems'; import useNavItems from 'lib/hooks/useNavItems';
import isBrowser from 'lib/isBrowser'; import { useAppContext } from 'lib/next/AppWrapper';
import getDefaultTransitionProps from 'theme/utils/getDefaultTransitionProps'; import getDefaultTransitionProps from 'theme/utils/getDefaultTransitionProps';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo'; import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import NetworkMenu from 'ui/snippets/networkMenu/NetworkMenu'; import NetworkMenu from 'ui/snippets/networkMenu/NetworkMenu';
...@@ -14,25 +14,16 @@ import NavFooter from './NavFooter'; ...@@ -14,25 +14,16 @@ import NavFooter from './NavFooter';
import NavLink from './NavLink'; import NavLink from './NavLink';
const NavigationDesktop = () => { const NavigationDesktop = () => {
const { mainNavItems, accountNavItems } = useNavItems(); const appProps = useAppContext();
const cookiesString = appProps.cookies;
const isNavBarCollapsed = cookies.getFromCookieString(cookiesString, cookies.NAMES.NAV_BAR_COLLAPSED) === 'true';
const hasAuth = Boolean(cookies.getFromCookieString(cookiesString, cookies.NAMES.API_TOKEN));
const isInBrowser = isBrowser(); const { mainNavItems, accountNavItems } = useNavItems();
const [ hasAccount, setHasAccount ] = React.useState(false);
const [ isCollapsed, setCollapsedState ] = React.useState<boolean | undefined>();
React.useEffect(() => { const hasAccount = hasAuth && appConfig.isAccountSupported;
const navBarCollapsedCookie = cookies.get(cookies.NAMES.NAV_BAR_COLLAPSED); const [ isCollapsed, setCollapsedState ] = React.useState<boolean | undefined>(isNavBarCollapsed);
const isAuth = Boolean(cookies.get(cookies.NAMES.API_TOKEN));
if (isInBrowser) {
if (navBarCollapsedCookie === 'true') {
setCollapsedState(true);
}
if (navBarCollapsedCookie === 'false') {
setCollapsedState(false);
}
setHasAccount(Boolean(appConfig.isAccountSupported && isAuth && isInBrowser));
}
}, [ isInBrowser ]);
const handleTogglerClick = React.useCallback(() => { const handleTogglerClick = React.useCallback(() => {
setCollapsedState((flag) => !flag); setCollapsedState((flag) => !flag);
......
...@@ -7,7 +7,7 @@ import UserAvatar from 'ui/shared/UserAvatar'; ...@@ -7,7 +7,7 @@ import UserAvatar from 'ui/shared/UserAvatar';
import ProfileMenuContent from 'ui/snippets/profileMenu/ProfileMenuContent'; import ProfileMenuContent from 'ui/snippets/profileMenu/ProfileMenuContent';
const ProfileMenuDesktop = () => { const ProfileMenuDesktop = () => {
const { data } = useFetchProfileInfo(); const { data, isFetched } = useFetchProfileInfo();
const loginUrl = link('auth'); const loginUrl = link('auth');
return ( return (
...@@ -21,7 +21,7 @@ const ProfileMenuDesktop = () => { ...@@ -21,7 +21,7 @@ const ProfileMenuDesktop = () => {
as={ data ? undefined : 'a' } as={ data ? undefined : 'a' }
href={ data ? undefined : loginUrl } href={ data ? undefined : loginUrl }
> >
<UserAvatar size={ 50 } data={ data }/> <UserAvatar size={ 50 } data={ data } isFetched={ isFetched }/>
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
{ data && ( { data && (
......
...@@ -10,13 +10,13 @@ import ProfileMenuContent from 'ui/snippets/profileMenu/ProfileMenuContent'; ...@@ -10,13 +10,13 @@ import ProfileMenuContent from 'ui/snippets/profileMenu/ProfileMenuContent';
const ProfileMenuMobile = () => { const ProfileMenuMobile = () => {
const { isOpen, onOpen, onClose } = useDisclosure(); const { isOpen, onOpen, onClose } = useDisclosure();
const { data } = useFetchProfileInfo(); const { data, isFetched } = useFetchProfileInfo();
const loginUrl = link('auth'); const loginUrl = link('auth');
return ( return (
<> <>
<Box padding={ 2 } onClick={ onOpen }> <Box padding={ 2 } onClick={ onOpen }>
<UserAvatar size={ 24 } data={ data }/> <UserAvatar size={ 24 } data={ data } isFetched={ isFetched }/>
</Box> </Box>
<Drawer <Drawer
isOpen={ isOpen } isOpen={ isOpen }
...@@ -34,7 +34,7 @@ const ProfileMenuMobile = () => { ...@@ -34,7 +34,7 @@ const ProfileMenuMobile = () => {
> >
<ColorModeToggler/> <ColorModeToggler/>
<Box onClick={ onClose }> <Box onClick={ onClose }>
<UserAvatar size={ 24 } data={ data }/> <UserAvatar size={ 24 } data={ data } isFetched={ isFetched }/>
</Box> </Box>
</Flex> </Flex>
{ data ? <ProfileMenuContent { ...data }/> : ( { data ? <ProfileMenuContent { ...data }/> : (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment