From e598adae85c60a9231feb9be0d55f0d845c80ccd Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sat, 28 Jan 2023 22:11:23 -0800 Subject: [PATCH 1/9] Fix party details grid CSS Somehow, an extra grid-template-columns got in there. I'm sure this will haunt me in the future. --- components/PartyDetails/index.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/components/PartyDetails/index.scss b/components/PartyDetails/index.scss index 0b0fb4c3..354367c9 100644 --- a/components/PartyDetails/index.scss +++ b/components/PartyDetails/index.scss @@ -37,7 +37,6 @@ &.Visible { display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); } fieldset { From 3f545a681e8bc5085719c945513b0c87438054df Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sat, 28 Jan 2023 22:20:55 -0800 Subject: [PATCH 2/9] Header title will update on save --- components/Header/index.tsx | 39 ++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/components/Header/index.tsx b/components/Header/index.tsx index d17defde..c66da26b 100644 --- a/components/Header/index.tsx +++ b/components/Header/index.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react' -import { useSnapshot } from 'valtio' +import { subscribe, useSnapshot } from 'valtio' +import { subscribeKey } from 'valtio/utils' import { deleteCookie } from 'cookies-next' import { useRouter } from 'next/router' import { Trans, useTranslation } from 'next-i18next' @@ -49,11 +50,21 @@ const Header = () => { const [settingsModalOpen, setSettingsModalOpen] = useState(false) const [leftMenuOpen, setLeftMenuOpen] = useState(false) const [rightMenuOpen, setRightMenuOpen] = useState(false) + + const [name, setName] = useState('') const [originalName, setOriginalName] = useState('') // Snapshots const { account } = useSnapshot(accountState) - const { party } = useSnapshot(appState) + const { party: partySnapshot } = useSnapshot(appState) + + const unsubscribe = subscribe(appState, () => { + const newName = + appState.party && appState.party.name ? appState.party.name : '' + setName(newName) + }) + + useEffect(() => () => unsubscribe(), []) function handleCopyToastOpenChanged(open: boolean) { setCopyToastOpen(open) @@ -140,31 +151,31 @@ const Header = () => { } function toggleFavorite() { - if (party.favorited) unsaveFavorite() + if (partySnapshot.favorited) unsaveFavorite() else saveFavorite() } function saveFavorite() { - if (party.id) - api.saveTeam({ id: party.id }).then((response) => { + if (partySnapshot.id) + api.saveTeam({ id: partySnapshot.id }).then((response) => { if (response.status == 201) appState.party.favorited = true }) else console.error('Failed to save team: No party ID') } function unsaveFavorite() { - if (party.id) - api.unsaveTeam({ id: party.id }).then((response) => { + if (partySnapshot.id) + api.unsaveTeam({ id: partySnapshot.id }).then((response) => { if (response.status == 200) appState.party.favorited = false }) else console.error('Failed to unsave team: No party ID') } function remixTeam() { - setOriginalName(party.name ? party.name : t('no_title')) + setOriginalName(partySnapshot.name ? partySnapshot.name : t('no_title')) - if (party.shortcode) - api.remix(party.shortcode).then((response) => { + if (partySnapshot.shortcode) + api.remix(partySnapshot.shortcode).then((response) => { const remix = response.data.party router.push(`/p/${remix.shortcode}`) setRemixToastOpen(true) @@ -265,10 +276,12 @@ const Header = () => { leftAccessoryIcon={} className={classNames({ Save: true, - Saved: party.favorited, + Saved: partySnapshot.favorited, })} blended={true} - text={party.favorited ? t('buttons.saved') : t('buttons.save')} + text={ + partySnapshot.favorited ? t('buttons.saved') : t('buttons.save') + } onClick={toggleFavorite} /> @@ -348,7 +361,7 @@ const Header = () => {
{router.route === '/p/[party]' && account.user && - (!party.user || party.user.id !== account.user.id) && + (!partySnapshot.user || partySnapshot.user.id !== account.user.id) && !appState.errorCode ? saveButton() : ''} From 1bc8aafac0c1a10deeeb71825429c1ae740c382c Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sat, 28 Jan 2023 22:23:10 -0800 Subject: [PATCH 3/9] Fix dropdown menu width again --- components/DropdownMenuContent/index.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/DropdownMenuContent/index.scss b/components/DropdownMenuContent/index.scss index 96fa2040..4d5d867c 100644 --- a/components/DropdownMenuContent/index.scss +++ b/components/DropdownMenuContent/index.scss @@ -4,7 +4,8 @@ border-radius: 6px; box-shadow: 0 1px 4px rgb(0 0 0 / 8%); box-sizing: border-box; - min-width: 30vw; + width: 30vw; + max-width: 180px; margin: 0 $unit-2x; // top: $unit-8x; // This shouldn't be hardcoded. How to calculate it? // Also, add space that doesn't make the menu disappear if you move your mouse slowly From 820f8739167972da64e67191df2ed8079571d1cc Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sat, 28 Jan 2023 22:23:23 -0800 Subject: [PATCH 4/9] Remove commented lines --- components/DropdownMenuContent/index.scss | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/DropdownMenuContent/index.scss b/components/DropdownMenuContent/index.scss index 4d5d867c..e1536c42 100644 --- a/components/DropdownMenuContent/index.scss +++ b/components/DropdownMenuContent/index.scss @@ -7,8 +7,6 @@ width: 30vw; max-width: 180px; margin: 0 $unit-2x; - // top: $unit-8x; // This shouldn't be hardcoded. How to calculate it? - // Also, add space that doesn't make the menu disappear if you move your mouse slowly z-index: 15; @include breakpoint(phone) { From 7d4fc7b6ac9bfbbd3aa5fdb427c79aac0b937dc3 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sat, 28 Jan 2023 22:55:26 -0800 Subject: [PATCH 5/9] Fix blue links --- components/PartyDetails/index.scss | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/components/PartyDetails/index.scss b/components/PartyDetails/index.scss index 354367c9..a6306701 100644 --- a/components/PartyDetails/index.scss +++ b/components/PartyDetails/index.scss @@ -339,6 +339,18 @@ font-size: $font-small; } + a:visited:not(.fire):not(.water):not(.wind):not(.earth):not(.dark):not( + .light + ) { + color: var(--text-primary); + } + + a:hover:not(.fire):not(.water):not(.wind):not(.earth):not(.dark):not( + .light + ) { + color: $blue; + } + & > *:not(:last-child):after { content: ' · '; margin: 0 calc($unit / 2); From 4e6fb19fb0ebb92fb64cbe69b8788543a3d6942e Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sat, 28 Jan 2023 23:12:06 -0800 Subject: [PATCH 6/9] Subscribe to router and reset state on change --- components/PartyDetails/index.tsx | 390 ++++++++++++++++-------------- 1 file changed, 210 insertions(+), 180 deletions(-) diff --git a/components/PartyDetails/index.tsx b/components/PartyDetails/index.tsx index 369016be..646da2c3 100644 --- a/components/PartyDetails/index.tsx +++ b/components/PartyDetails/index.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState, ChangeEvent, KeyboardEvent } from 'react' import Link from 'next/link' import { useRouter } from 'next/router' -import { useSnapshot } from 'valtio' +import { subscribe, useSnapshot } from 'valtio' import { useTranslation } from 'next-i18next' import clonedeep from 'lodash.clonedeep' @@ -25,7 +25,7 @@ import Token from '~components/Token' import api from '~utils/api' import { accountState } from '~utils/accountState' -import { appState } from '~utils/appState' +import { appState, initialAppState } from '~utils/appState' import { formatTimeAgo } from '~utils/timeAgo' import { youtube } from '~utils/youtube' @@ -124,6 +124,26 @@ const PartyDetails = (props: Props) => { } }, [props.party]) + // Subscribe to router changes and reset state + // if the new route is a new team + useEffect(() => { + router.events.on('routeChangeStart', (url, { shallow }) => { + if (url === '/new' || url === '/') { + const party = initialAppState.party + + setName(party.name ? party.name : '') + setAutoGuard(party.autoGuard) + setFullAuto(party.fullAuto) + setChargeAttack(party.chargeAttack) + setClearTime(party.clearTime) + setRemixes(party.remixes) + setTurnCount(party.turnCount) + setButtonCount(party.buttonCount) + setChainCount(party.chainCount) + } + }) + }, []) + useEffect(() => { // Extract the video IDs from the description if (appState.party.description) { @@ -475,161 +495,163 @@ const PartyDetails = (props: Props) => { } } - const editable = ( -
- - -
    -
  • - -
  • -
  • - -
  • -
  • - -
  • -
-
    -
  • - -
  • -
  • - -
  • -
  • - -
  • -
- + + +
  • + +
  • + + -
    -
    - {router.pathname !== '/new' ? ( +
    +
    + {router.pathname !== '/new' ? ( +
    +
    +
    -
    -
    -
    -
    - ) +
    + ) + } const clearTimeString = () => { const minutes = Math.floor(clearTime / 60) @@ -664,38 +686,46 @@ const PartyDetails = (props: Props) => { } } - const readOnly = ( -
    -
    - - {`${t('party.details.labels.charge_attack')} ${ - chargeAttack ? 'On' : 'Off' - }`} - - - - {`${t('party.details.labels.full_auto')} ${fullAuto ? 'On' : 'Off'}`} - - - - {`${t('party.details.labels.auto_guard')} ${fullAuto ? 'On' : 'Off'}`} - - - {turnCount ? ( - - {t('party.details.turns.with_count', { - count: turnCount, - })} + const readOnly = () => { + return ( +
    +
    + + {`${t('party.details.labels.charge_attack')} ${ + chargeAttack ? 'On' : 'Off' + }`} - ) : ( - '' - )} - {clearTime > 0 ? {clearTimeString()} : ''} - {buttonChainToken()} + + + {`${t('party.details.labels.full_auto')} ${ + fullAuto ? 'On' : 'Off' + }`} + + + + {`${t('party.details.labels.auto_guard')} ${ + fullAuto ? 'On' : 'Off' + }`} + + + {turnCount ? ( + + {t('party.details.turns.with_count', { + count: turnCount, + })} + + ) : ( + '' + )} + {clearTime > 0 ? {clearTimeString()} : ''} + {buttonChainToken()} +
    + {embeddedDescription}
    - {embeddedDescription} -
    - ) + ) + } const remixSection = () => { return ( @@ -755,8 +785,8 @@ const PartyDetails = (props: Props) => { '' )} - {readOnly} - {editable} + {readOnly()} + {editable()} {deleteAlert()}
    From 71c9d5a7445c1b7d0c845b4bf730db05f9165ad0 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sat, 28 Jan 2023 23:15:44 -0800 Subject: [PATCH 7/9] Replace native JS redirect with useRouter --- pages/new/index.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pages/new/index.tsx b/pages/new/index.tsx index 86907577..dc4fe4c9 100644 --- a/pages/new/index.tsx +++ b/pages/new/index.tsx @@ -35,8 +35,7 @@ const NewRoute: React.FC = ({ const router = useRouter() function callback(path: string) { - // This is scuffed, how do we do this natively? - window.history.replaceState(null, `Grid Tool`, `${path}`) + router.push(path, undefined, { shallow: true }) } useEffect(() => { From 69a1b461f79558027020e27eff97307680906fb6 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sat, 28 Jan 2023 23:15:48 -0800 Subject: [PATCH 8/9] Cleanup --- components/Header/index.tsx | 164 +++++++++++++++++++++--------------- 1 file changed, 95 insertions(+), 69 deletions(-) diff --git a/components/Header/index.tsx b/components/Header/index.tsx index c66da26b..ea329543 100644 --- a/components/Header/index.tsx +++ b/components/Header/index.tsx @@ -10,7 +10,7 @@ import Link from 'next/link' import api from '~utils/api' import { accountState, initialAccountState } from '~utils/accountState' -import { appState } from '~utils/appState' +import { appState, initialAppState } from '~utils/appState' import { DropdownMenu, @@ -58,6 +58,8 @@ const Header = () => { const { account } = useSnapshot(accountState) const { party: partySnapshot } = useSnapshot(appState) + // Subscribe to app state to listen for party name and + // unsubscribe when component is unmounted const unsubscribe = subscribe(appState, () => { const newName = appState.party && appState.party.name ? appState.party.name : '' @@ -66,22 +68,14 @@ const Header = () => { useEffect(() => () => unsubscribe(), []) - function handleCopyToastOpenChanged(open: boolean) { - setCopyToastOpen(open) - } - - function handleCopyToastCloseClicked() { - setCopyToastOpen(false) - } - - function handleRemixToastOpenChanged(open: boolean) { - setRemixToastOpen(open) - } - - function handleRemixToastCloseClicked() { - setRemixToastOpen(false) - } + // Subscribe to router changes + useEffect(() => { + router.events.on('routeChangeStart', (url, { shallow }) => { + console.log(`routing to ${url}`, `is shallow routing: ${shallow}`) + }) + }, []) + // Methods: Event handlers (Buttons) function handleLeftMenuButtonClicked() { setLeftMenuOpen(!leftMenuOpen) } @@ -90,9 +84,11 @@ const Header = () => { setRightMenuOpen(!rightMenuOpen) } + // Methods: Event handlers (Menus) function handleLeftMenuOpenChange(open: boolean) { setLeftMenuOpen(open) } + function handleRightMenuOpenChange(open: boolean) { setRightMenuOpen(open) } @@ -105,6 +101,41 @@ const Header = () => { setRightMenuOpen(false) } + // Methods: Event handlers (Copy toast) + function handleCopyToastOpenChanged(open: boolean) { + setCopyToastOpen(open) + } + + function handleCopyToastCloseClicked() { + setCopyToastOpen(false) + } + + // Methods: Event handlers (Remix toasts) + function handleRemixToastOpenChanged(open: boolean) { + setRemixToastOpen(open) + } + + function handleRemixToastCloseClicked() { + setRemixToastOpen(false) + } + + // Methods: Actions + function handleNewParty(event: React.MouseEvent, path: string) { + event.preventDefault() + + // Clean state + const resetState = clonedeep(initialAppState) + Object.keys(resetState).forEach((key) => { + appState[key] = resetState[key] + }) + + // Push the root URL + router.push(path) + + // Close right menu + closeRightMenu() + } + function copyToClipboard() { const path = router.asPath.split('/')[1] @@ -122,16 +153,6 @@ const Header = () => { } } - function handleNewParty(event: React.MouseEvent, path: string) { - event.preventDefault() - - // Push the root URL - router.push(path) - - // Close right menu - closeRightMenu() - } - function logout() { // Close menu closeRightMenu() @@ -150,6 +171,17 @@ const Header = () => { return false } + function remixTeam() { + setOriginalName(partySnapshot.name ? partySnapshot.name : t('no_title')) + + if (partySnapshot.shortcode) + api.remix(partySnapshot.shortcode).then((response) => { + const remix = response.data.party + router.push(`/p/${remix.shortcode}`) + setRemixToastOpen(true) + }) + } + function toggleFavorite() { if (partySnapshot.favorited) unsaveFavorite() else saveFavorite() @@ -171,17 +203,7 @@ const Header = () => { else console.error('Failed to unsave team: No party ID') } - function remixTeam() { - setOriginalName(partySnapshot.name ? partySnapshot.name : t('no_title')) - - if (partySnapshot.shortcode) - api.remix(partySnapshot.shortcode).then((response) => { - const remix = response.data.party - router.push(`/p/${remix.shortcode}`) - setRemixToastOpen(true) - }) - } - + // Rendering: Elements const pageTitle = () => { let title = '' let hasAccessory = false @@ -237,38 +259,7 @@ const Header = () => { return image } - const urlCopyToast = () => { - return ( - - ) - } - - const remixToast = () => { - return ( - - You remixed {{ title: originalName }} - - } - onOpenChange={handleRemixToastOpenChanged} - onCloseClick={handleRemixToastCloseClicked} - /> - ) - } - + // Rendering: Buttons const saveButton = () => { return ( @@ -302,6 +293,40 @@ const Header = () => { ) } + // Rendering: Toasts + const urlCopyToast = () => { + return ( + + ) + } + + const remixToast = () => { + return ( + + You remixed {{ title: originalName }} + + } + onOpenChange={handleRemixToastOpenChanged} + onCloseClick={handleRemixToastCloseClicked} + /> + ) + } + + // Rendering: Modals const settingsModal = () => { const user = accountState.account.user @@ -330,6 +355,7 @@ const Header = () => { ) } + // Rendering: Compositing const left = () => { return (
    From e603ee1bdba8b5cdd2bf860a80644f7149aa8b08 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Sat, 28 Jan 2023 23:16:30 -0800 Subject: [PATCH 9/9] Remove unnecessary router updates --- components/Header/index.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/components/Header/index.tsx b/components/Header/index.tsx index ea329543..bae9e7be 100644 --- a/components/Header/index.tsx +++ b/components/Header/index.tsx @@ -68,13 +68,6 @@ const Header = () => { useEffect(() => () => unsubscribe(), []) - // Subscribe to router changes - useEffect(() => { - router.events.on('routeChangeStart', (url, { shallow }) => { - console.log(`routing to ${url}`, `is shallow routing: ${shallow}`) - }) - }, []) - // Methods: Event handlers (Buttons) function handleLeftMenuButtonClicked() { setLeftMenuOpen(!leftMenuOpen)