Set battle settings in state on update

Also renames PartyDetails to PartyFooter and makes description reactive
This commit is contained in:
Justin Edmund 2023-06-21 02:19:50 -07:00
parent c2927166f6
commit df9aca6b67
3 changed files with 123 additions and 129 deletions

View file

@ -7,7 +7,7 @@ import clonedeep from 'lodash.clonedeep'
import Alert from '~components/common/Alert' import Alert from '~components/common/Alert'
import PartySegmentedControl from '~components/party/PartySegmentedControl' import PartySegmentedControl from '~components/party/PartySegmentedControl'
import PartyDetails from '~components/party/PartyDetails' import PartyFooter from '~components/party/PartyFooter'
import PartyHeader from '~components/party/PartyHeader' import PartyHeader from '~components/party/PartyHeader'
import WeaponGrid from '~components/weapon/WeaponGrid' import WeaponGrid from '~components/weapon/WeaponGrid'
import SummonGrid from '~components/summon/SummonGrid' import SummonGrid from '~components/summon/SummonGrid'
@ -265,6 +265,15 @@ const Party = (props: Props) => {
appState.party.jobSkills = team.job_skills appState.party.jobSkills = team.job_skills
appState.party.accessory = team.accessory appState.party.accessory = team.accessory
appState.party.chargeAttack = team.charge_attack
appState.party.fullAuto = team.full_auto
appState.party.autoGuard = team.auto_guard
appState.party.autoSummon = team.auto_summon
appState.party.clearTime = team.clear_time
appState.party.buttonCount = team.button_count
appState.party.chainCount = team.chain_count
appState.party.turnCount = team.turn_count
appState.party.id = team.id appState.party.id = team.id
appState.party.shortcode = team.shortcode appState.party.shortcode = team.shortcode
appState.party.extra = team.extra appState.party.extra = team.extra
@ -445,7 +454,7 @@ const Party = (props: Props) => {
<section id="Party">{currentGrid()}</section> <section id="Party">{currentGrid()}</section>
<PartyDetails <PartyFooter
party={props.team} party={props.team}
new={props.new || false} new={props.new || false}
editable={party.editable} editable={party.editable}

View file

@ -1,4 +1,4 @@
.DetailsWrapper { .FooterWrapper {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: $unit-2x; gap: $unit-2x;
@ -16,10 +16,13 @@
} }
} }
.PartyDetails { .PartyFooter {
box-sizing: border-box; box-sizing: border-box;
display: none; line-height: 1.4;
white-space: pre-wrap;
margin: 0 auto $unit-2x; margin: 0 auto $unit-2x;
margin-bottom: $unit-12x;
min-height: 10vh;
max-width: $unit * 94; max-width: $unit * 94;
overflow: hidden; overflow: hidden;
width: 100%; width: 100%;
@ -27,11 +30,6 @@
@include breakpoint(phone) { @include breakpoint(phone) {
padding: 0 $unit; padding: 0 $unit;
} }
&.Visible {
// margin-bottom: $unit-12x;
}
&.Editable { &.Editable {
gap: $unit; gap: $unit;
@ -174,115 +172,109 @@
} }
} }
&.ReadOnly { &.Visible {
box-sizing: border-box; display: block;
line-height: 1.4; }
white-space: pre-wrap;
&.Visible { a:hover {
text-decoration: underline;
}
p {
font-size: $font-regular;
line-height: $font-regular * 1.2;
white-space: pre-line;
}
.Details {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: $unit;
margin-bottom: $unit-2x;
}
.YoutubeWrapper {
background-color: var(--card-bg);
border-radius: $card-corner;
margin: $unit 0;
position: relative;
display: block;
contain: content;
background-position: center center;
background-size: cover;
cursor: pointer;
width: 60%;
height: 60%;
@include breakpoint(tablet) {
width: 100%;
height: 100%;
}
/* gradient */
&::before {
content: '';
display: block; display: block;
position: absolute;
top: 0;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADGCAYAAAAT+OqFAAAAdklEQVQoz42QQQ7AIAgEF/T/D+kbq/RWAlnQyyazA4aoAB4FsBSA/bFjuF1EOL7VbrIrBuusmrt4ZZORfb6ehbWdnRHEIiITaEUKa5EJqUakRSaEYBJSCY2dEstQY7AuxahwXFrvZmWl2rh4JZ07z9dLtesfNj5q0FU3A5ObbwAAAABJRU5ErkJggg==);
background-position: top;
background-repeat: repeat-x;
height: 60px;
padding-bottom: 50px;
width: 100%;
transition: all 0.2s cubic-bezier(0, 0, 0.2, 1);
} }
a:hover { /* responsive iframe with a 16:9 aspect ratio
text-decoration: underline;
}
p {
font-size: $font-regular;
line-height: $font-regular * 1.2;
white-space: pre-line;
}
.Details {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: $unit;
margin-bottom: $unit-2x;
}
.YoutubeWrapper {
background-color: var(--card-bg);
border-radius: $card-corner;
margin: $unit 0;
position: relative;
display: block;
contain: content;
background-position: center center;
background-size: cover;
cursor: pointer;
width: 60%;
height: 60%;
@include breakpoint(tablet) {
width: 100%;
height: 100%;
}
/* gradient */
&::before {
content: '';
display: block;
position: absolute;
top: 0;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADGCAYAAAAT+OqFAAAAdklEQVQoz42QQQ7AIAgEF/T/D+kbq/RWAlnQyyazA4aoAB4FsBSA/bFjuF1EOL7VbrIrBuusmrt4ZZORfb6ehbWdnRHEIiITaEUKa5EJqUakRSaEYBJSCY2dEstQY7AuxahwXFrvZmWl2rh4JZ07z9dLtesfNj5q0FU3A5ObbwAAAABJRU5ErkJggg==);
background-position: top;
background-repeat: repeat-x;
height: 60px;
padding-bottom: 50px;
width: 100%;
transition: all 0.2s cubic-bezier(0, 0, 0.2, 1);
}
/* responsive iframe with a 16:9 aspect ratio
thanks https://css-tricks.com/responsive-iframes/ thanks https://css-tricks.com/responsive-iframes/
*/ */
&::after { &::after {
content: ''; content: '';
display: block; display: block;
padding-bottom: calc(100% / (16 / 9)); padding-bottom: calc(100% / (16 / 9));
} }
&:hover > .PlayerButton { &:hover > .PlayerButton {
opacity: 1; opacity: 1;
} }
& > iframe { & > iframe {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
} }
/* Play button */ /* Play button */
& > .PlayerButton { & > .PlayerButton {
background: none; background: none;
border: none; border: none;
background-image: url('/icons/youtube.svg'); background-image: url('/icons/youtube.svg');
width: 68px; width: 68px;
height: 68px; height: 68px;
opacity: 0.8; opacity: 0.8;
transition: all 0.2s cubic-bezier(0, 0, 0.2, 1); transition: all 0.2s cubic-bezier(0, 0, 0.2, 1);
} }
& > .PlayerButton, & > .PlayerButton,
& > .PlayerButton:before { & > .PlayerButton:before {
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate3d(-50%, -50%, 0); transform: translate3d(-50%, -50%, 0);
} }
/* Post-click styles */ /* Post-click styles */
&.lyt-activated { &.lyt-activated {
cursor: unset; cursor: unset;
} }
&.lyt-activated::before, &.lyt-activated::before,
&.lyt-activated > .PlayerButton { &.lyt-activated > .PlayerButton {
opacity: 0; opacity: 0;
pointer-events: none; pointer-events: none;
}
} }
} }
} }

View file

@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useSnapshot } from 'valtio'
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
import clonedeep from 'lodash.clonedeep' import clonedeep from 'lodash.clonedeep'
@ -27,10 +28,12 @@ interface Props {
updateCallback: (details: DetailsObject) => void updateCallback: (details: DetailsObject) => void
} }
const PartyDetails = (props: Props) => { const PartyFooter = (props: Props) => {
const { t } = useTranslation('common') const { t } = useTranslation('common')
const router = useRouter() const router = useRouter()
const { party } = useSnapshot(appState)
const youtubeUrlRegex = const youtubeUrlRegex =
/(?:https:\/\/www\.youtube\.com\/watch\?v=|https:\/\/youtu\.be\/)([\w-]+)/g /(?:https:\/\/www\.youtube\.com\/watch\?v=|https:\/\/youtu\.be\/)([\w-]+)/g
@ -40,16 +43,10 @@ const PartyDetails = (props: Props) => {
const [embeddedDescription, setEmbeddedDescription] = const [embeddedDescription, setEmbeddedDescription] =
useState<React.ReactNode>() useState<React.ReactNode>()
const readOnlyClasses = classNames({
PartyDetails: true,
ReadOnly: true,
Visible: !open,
})
useEffect(() => { useEffect(() => {
// Extract the video IDs from the description // Extract the video IDs from the description
if (appState.party.description) { if (party.description) {
const videoIds = extractYoutubeVideoIds(appState.party.description) const videoIds = extractYoutubeVideoIds(party.description)
// Fetch the video titles for each ID // Fetch the video titles for each ID
const fetchPromises = videoIds.map(({ id }) => fetchYoutubeData(id)) const fetchPromises = videoIds.map(({ id }) => fetchYoutubeData(id))
@ -58,7 +55,7 @@ const PartyDetails = (props: Props) => {
Promise.all(fetchPromises).then((videoTitles) => { Promise.all(fetchPromises).then((videoTitles) => {
// Replace the video URLs in the description with LiteYoutubeEmbed elements // Replace the video URLs in the description with LiteYoutubeEmbed elements
const newDescription = reactStringReplace( const newDescription = reactStringReplace(
appState.party.description, party.description,
youtubeUrlRegex, youtubeUrlRegex,
(match, i) => ( (match, i) => (
<LiteYouTubeEmbed <LiteYouTubeEmbed
@ -77,7 +74,7 @@ const PartyDetails = (props: Props) => {
} else { } else {
setEmbeddedDescription('') setEmbeddedDescription('')
} }
}, [appState.party.description]) }, [party.description])
async function fetchYoutubeData(videoId: string) { async function fetchYoutubeData(videoId: string) {
return await youtube return await youtube
@ -173,14 +170,6 @@ const PartyDetails = (props: Props) => {
}) })
} }
const readOnly = () => {
return (
<section className={readOnlyClasses}>
<Linkify>{embeddedDescription}</Linkify>
</section>
)
}
const remixSection = () => { const remixSection = () => {
return ( return (
<section className="Remixes"> <section className="Remixes">
@ -192,10 +181,14 @@ const PartyDetails = (props: Props) => {
return ( return (
<> <>
<section className="DetailsWrapper">{readOnly()}</section> <section className="FooterWrapper">
<section className="PartyFooter">
<Linkify>{embeddedDescription}</Linkify>
</section>
</section>
{remixes && remixes.length > 0 ? remixSection() : ''} {remixes && remixes.length > 0 ? remixSection() : ''}
</> </>
) )
} }
export default PartyDetails export default PartyFooter