From a9497d061d942b83751291aaacec9a55025ad594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Wed, 22 May 2024 14:16:46 -0500 Subject: [PATCH] feat: more code splitting --- src/app/components/Checks.tsx | 67 ++++ src/app/components/Hero.tsx | 354 ++++++++++++++++++ src/app/layout.css | 4 + src/app/layout.tsx | 50 +-- src/app/page.tsx | 352 +---------------- src/components/Footer/index.tsx | 2 + .../Navbar/components/EverythingSearch.tsx | 2 +- src/components/Navbar/index.tsx | 21 +- src/components/Party3.tsx | 2 + 9 files changed, 442 insertions(+), 412 deletions(-) create mode 100644 src/app/components/Checks.tsx create mode 100644 src/app/components/Hero.tsx create mode 100644 src/app/layout.css diff --git a/src/app/components/Checks.tsx b/src/app/components/Checks.tsx new file mode 100644 index 000000000..39cb31b3d --- /dev/null +++ b/src/app/components/Checks.tsx @@ -0,0 +1,67 @@ +'use client'; + +import { AlertDialog, Button, Flex } from '@radix-ui/themes'; +import { useEffect, useState } from 'react'; +import { extendAuth } from '../../core/blitz/extendAuth'; +import { logout } from '../../core/blitz/logout'; +import isDev from '../../core/blitzkit/isDev'; +import { isLocalhost } from '../../core/blitzkit/isLocalhost'; +import { useApp } from '../../stores/app'; + +const DEV_BUILD_AGREEMENT_COOLDOWN = 8 * 24 * 60 * 60 * 1000; + +export function Checks() { + const [showDevBuildAlert, setShowDevBuildAlert] = useState(false); + const login = useApp((state) => state.login); + + useEffect(() => { + setShowDevBuildAlert( + isDev() && + !isLocalhost() && + Date.now() - useApp.getState().devBuildAgreementTime >= + DEV_BUILD_AGREEMENT_COOLDOWN, + ); + }, []); + + useEffect(() => { + if (!login) return; + + const expiresIn = login.expiresAt - Date.now() / 1000; + const expiresInDays = expiresIn / 60 / 60 / 24; + + if (expiresInDays < 0) { + logout(); + } else if (expiresInDays < 7) { + extendAuth(); + } + }); + + return ( + + + Experimental version! + + This version may have a lot of issues. Report issues to{' '} + + the official Discord server + + . Also consider using{' '} + the more stable release version. + You will be asked again in 8 days. + + + + + + + + ); +} diff --git a/src/app/components/Hero.tsx b/src/app/components/Hero.tsx new file mode 100644 index 000000000..da1f4b375 --- /dev/null +++ b/src/app/components/Hero.tsx @@ -0,0 +1,354 @@ +'use client'; + +import { + CaretRightIcon, + Cross2Icon, + MagnifyingGlassIcon, +} from '@radix-ui/react-icons'; +import { + Button, + Card, + Flex, + Heading, + IconButton, + Link, + Spinner, + Text, + TextField, +} from '@radix-ui/themes'; +import { go } from 'fuzzysort'; +import { debounce } from 'lodash'; +import { useRef, useState } from 'react'; +import { NAVBAR_HEIGHT } from '../../components/Navbar'; +import { UNLOCALIZED_REGION_NAMES_SHORT } from '../../constants/regions'; +import searchPlayersAcrossRegions, { + AccountListWithServer, +} from '../../core/blitz/searchPlayersAcrossRegions'; +import { + TankDefinition, + tankDefinitions, + tankNames, +} from '../../core/blitzkit/tankDefinitions'; +import { TIER_ROMAN_NUMERALS } from '../../core/blitzkit/tankDefinitions/constants'; +import { useWideFormat } from '../../hooks/useWideFormat'; +import { theme } from '../../stitches.config'; + +const DISCRIMINATOR_WIDTH = 32; + +export function Hero() { + const wideFormat = useWideFormat(512); + const [showSearch, setShowSearch] = useState(false); + const [searching, setSearching] = useState(false); + const [searchResults, setSearchResults] = useState(); + const search = useRef(null); + + const performSearch = debounce(async () => { + if (!search.current) return; + + const sanitized = search.current.value.trim(); + const awaitedTankDefinitions = await tankDefinitions; + const awaitedTankNames = await tankNames; + const tanks = go(sanitized, awaitedTankNames, { + keys: ['combined'], + limit: 6, + }); + const players = await searchPlayersAcrossRegions(sanitized, 6); + + setSearchResults({ + tanks: tanks.map((tank) => awaitedTankDefinitions[tank.obj.id]), + players, + }); + setSearching(false); + }, 500); + + return ( + +
+
+ + + + + BlitzKit + + + Everything World of Tanks Blitz + + + +
+ { + if (!search.current) return; + + const sanitized = search.current.value.trim(); + + if (sanitized.length > 0) { + setShowSearch(true); + setSearching(true); + performSearch(); + } else { + setShowSearch(false); + } + }} + onFocus={() => { + if (!search.current) return; + + const sanitized = search.current.value.trim(); + setShowSearch(sanitized.length > 0); + + window.scrollTo({ + top: + search.current.getBoundingClientRect().top - + NAVBAR_HEIGHT - + 32, + behavior: 'smooth', + }); + }} + > + + + + + {showSearch && ( + + { + if (!search.current) return; + + search.current.value = ''; + setShowSearch(false); + }} + > + + + + )} + + + {showSearch && ( + + {searching && ( + + + + )} + + {!searching && searchResults && ( + <> + + + + + Tankopedia + + + + + + {searchResults.tanks.map((tank) => ( + + + + + + ))} + + {searchResults.tanks.length === 0 && ( + + No tanks found + + )} + + + + + Players + + + {searchResults.players.map((player) => ( + + + + + + ))} + + {searchResults.players.length === 0 && ( + + No players found + + )} + + + + + )} + + )} +
+
+ + ); +} diff --git a/src/app/layout.css b/src/app/layout.css new file mode 100644 index 000000000..32a08d361 --- /dev/null +++ b/src/app/layout.css @@ -0,0 +1,4 @@ +*, +html { + scroll-behavior: smooth; +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index c89bb930e..3de77ed76 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,23 +1,20 @@ 'use client'; -import { AlertDialog, Button, Flex, Theme } from '@radix-ui/themes'; +import { Flex, Theme } from '@radix-ui/themes'; import '@radix-ui/themes/styles.css'; import { config } from 'dotenv'; import { Roboto_Flex } from 'next/font/google'; import { usePathname } from 'next/navigation'; -import { ReactNode, Suspense, useEffect, useState } from 'react'; +import { ReactNode, Suspense } from 'react'; import { Footer } from '../components/Footer'; import { Loader } from '../components/Loader'; import Navbar, { NAVBAR_HEIGHT } from '../components/Navbar'; import { Party3 } from '../components/Party3'; -import isDev from '../core/blitzkit/isDev'; -import { isLocalhost } from '../core/blitzkit/isLocalhost'; -import { useApp } from '../stores/app'; +import { Checks } from './components/Checks'; +import './layout.css'; config(); -const DEV_BUILD_AGREEMENT_COOLDOWN = 8 * 24 * 60 * 60 * 1000; - interface RootLayoutProps { children: ReactNode; } @@ -31,16 +28,6 @@ export default function RootLayout({ children }: RootLayoutProps) { const pathname = usePathname(); const isEmbed = pathname.split('/')[1] === 'embeds'; const isRoot = pathname === '/'; - const [showDevBuildAlert, setShowDevBuildAlert] = useState(false); - - useEffect(() => { - setShowDevBuildAlert( - isDev() && - !isLocalhost() && - Date.now() - useApp.getState().devBuildAgreementTime >= - DEV_BUILD_AGREEMENT_COOLDOWN, - ); - }, []); return ( @@ -83,34 +70,7 @@ export default function RootLayout({ children }: RootLayoutProps) { > {!isEmbed && } - - - Experimental version! - - This version may have a lot of issues. Report issues to{' '} - - the official Discord server - - . Also consider using{' '} - - the more stable release version - - . You will be asked again in 8 days. - - - - - - - + (); - const search = useRef(null); - - const performSearch = debounce(async () => { - if (!search.current) return; - - const sanitized = search.current.value.trim(); - const awaitedTankDefinitions = await tankDefinitions; - const awaitedTankNames = await tankNames; - const tanks = go(sanitized, awaitedTankNames, { - keys: ['combined'], - limit: 6, - }); - const players = await searchPlayersAcrossRegions(sanitized, 6); - - setSearchResults({ - tanks: tanks.map((tank) => awaitedTankDefinitions[tank.obj.id]), - players, - }); - setSearching(false); - }, 500); - return ( <> - -
-
- - - - - BlitzKit - - - Everything World of Tanks Blitz - - - -
- { - if (!search.current) return; - - const sanitized = search.current.value.trim(); - - if (sanitized.length > 0) { - setShowSearch(true); - setSearching(true); - performSearch(); - } else { - setShowSearch(false); - } - }} - onFocus={() => { - if (!search.current) return; - - const sanitized = search.current.value.trim(); - setShowSearch(sanitized.length > 0); - - window.scrollTo({ - top: - search.current.getBoundingClientRect().top - - NAVBAR_HEIGHT - - 32, - behavior: 'smooth', - }); - }} - > - - - - - {showSearch && ( - - { - if (!search.current) return; - - search.current.value = ''; - setShowSearch(false); - }} - > - - - - )} - - - {showSearch && ( - - {searching && ( - - - - )} - - {!searching && searchResults && ( - <> - - - - - Tankopedia - - - - - - {searchResults.tanks.map((tank) => ( - - - - - - ))} - - {searchResults.tanks.length === 0 && ( - - No tanks found - - )} - - - - - Players - - - {searchResults.players.map((player) => ( - - - - - - ))} - - {searchResults.players.length === 0 && ( - - No players found - - )} - - - - - )} - - )} -
-
- + {times(64, () => (
diff --git a/src/components/Footer/index.tsx b/src/components/Footer/index.tsx index 0851aa1ec..99da41984 100644 --- a/src/components/Footer/index.tsx +++ b/src/components/Footer/index.tsx @@ -1,3 +1,5 @@ +'use client'; + import { Code, Flex, Link, Spinner, Text, Theme } from '@radix-ui/themes'; import { Suspense } from 'react'; import packageJSON from '../../../package.json'; diff --git a/src/components/Navbar/components/EverythingSearch.tsx b/src/components/Navbar/components/EverythingSearch.tsx index 9d8f605f8..8640bc2df 100644 --- a/src/components/Navbar/components/EverythingSearch.tsx +++ b/src/components/Navbar/components/EverythingSearch.tsx @@ -33,7 +33,7 @@ export function EverythingSearch({ width: '100%', zIndex: 1, }} - > + /> )} diff --git a/src/components/Navbar/index.tsx b/src/components/Navbar/index.tsx index 8b013afdd..85fef0b0a 100644 --- a/src/components/Navbar/index.tsx +++ b/src/components/Navbar/index.tsx @@ -1,3 +1,5 @@ +'use client'; + import { Cross1Icon, DiscordLogoIcon, @@ -19,13 +21,11 @@ import { } from '@radix-ui/themes'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; -import { Suspense, useEffect, useState } from 'react'; +import { Suspense, useState } from 'react'; import * as styles from '../../app/page.css'; import { REGIONS, UNLOCALIZED_REGION_NAMES } from '../../constants/regions'; import { TOOLS } from '../../constants/tools'; import { authURL } from '../../core/blitz/authURL'; -import { extendAuth } from '../../core/blitz/extendAuth'; -import { logout } from '../../core/blitz/logout'; import { useWideFormat } from '../../hooks/useWideFormat'; import { BlitzkitWide } from '../../icons/BlitzkitWide'; import { PatreonIcon } from '../../icons/Patreon'; @@ -37,22 +37,9 @@ export const NAVBAR_HEIGHT = 64; export default function Navbar() { const wideFormat = useWideFormat(688 - 32 - 64); - const login = useApp((state) => state.login); const [showHamburgerMenu, setShowHamburgerMenu] = useState(false); const pathname = usePathname(); - - useEffect(() => { - if (!login) return; - - const expiresIn = login.expiresAt - Date.now() / 1000; - const expiresInDays = expiresIn / 60 / 60 / 24; - - if (expiresInDays < 0) { - logout(); - } else if (expiresInDays < 7) { - extendAuth(); - } - }); + const login = useApp((state) => state.login!); return (