Set battle settings in state on update
Also renames PartyDetails to PartyFooter and makes description reactive
This commit is contained in:
parent
c2927166f6
commit
df9aca6b67
3 changed files with 123 additions and 129 deletions
|
|
@ -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}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in a new issue