ch ch changes

This commit is contained in:
sunda 2022-09-07 14:37:49 +02:00
parent fdc031c64b
commit c24124c970
8 changed files with 190 additions and 117 deletions

31
index.js Normal file → Executable file
View File

@ -16,13 +16,16 @@ import Series from './src/pages/Series'
import Program from './src/pages/Program' import Program from './src/pages/Program'
import StreamPreview from './src/components/StreamPreview' import StreamPreview from './src/components/StreamPreview'
import Video from './src/components/Video' import Video from './src/components/Video'
import Chat from './src/components/Chat'
// import { useWindowSize } from './src/hooks/dom' // import { useWindowSize } from './src/hooks/dom'
const App = () => { const App = () => {
const { theme } = useTheme((store) => store) const { theme } = useTheme(store => store)
const { data, loading: eventsLoading, error } = useEventApi() const { data, loading: eventsLoading, error } = useEventApi()
const [minLoadTimePassed, setMinTimeUp] = useState(false) const [minLoadTimePassed, setMinTimeUp] = useState(false)
const { setCurrentStream, currentStream, streamIsLive } = useStreamStore(store => store) const { setCurrentStream, currentStream, streamIsLive } = useStreamStore(
store => store
)
const streamActive = useUiStore(store => store.streamActive) const streamActive = useUiStore(store => store.streamActive)
usePeertubeApi(data.episodes) usePeertubeApi(data.episodes)
@ -37,7 +40,10 @@ const App = () => {
new Date(stream.beginsOn), new Date(stream.beginsOn),
'Europe/Berlin' 'Europe/Berlin'
) )
const utcEndDate = zonedTimeToUtc(new Date(stream.endsOn), 'Europe/Berlin') const utcEndDate = zonedTimeToUtc(
new Date(stream.endsOn),
'Europe/Berlin'
)
const { timeZone } = Intl.DateTimeFormat().resolvedOptions() const { timeZone } = Intl.DateTimeFormat().resolvedOptions()
const zonedStartDate = utcToZonedTime(utcStartDate, 'Europe/Berlin') const zonedStartDate = utcToZonedTime(utcStartDate, 'Europe/Berlin')
@ -69,23 +75,30 @@ const App = () => {
<Route exact path="/" component={Program} /> <Route exact path="/" component={Program} />
<Route exact path="/series" component={Series} /> <Route exact path="/series" component={Series} />
<Route exact path="/program" component={Program} /> <Route exact path="/program" component={Program} />
{seriesData.length ? seriesData.map(series => ( {seriesData.length
? seriesData.map(series => (
<Route exact path={`/series/${series.slug}`}> <Route exact path={`/series/${series.slug}`}>
<SeriesPage data={series} /> <SeriesPage data={series} />
</Route>)) : null} </Route>
))
: null}
<Route path="*"> <Route path="*">
<FourOhFour /> <FourOhFour />
</Route> </Route>
</Switch> </Switch>
</BrowserRouter> </BrowserRouter>
{streamActive ? <Video stream={currentStream} /> :
<StreamPreview stream={currentStream} isLive={streamIsLive} />} {streamActive ? (
<Video stream={currentStream} />
) : (
<StreamPreview stream={currentStream} isLive={streamIsLive} />
)}
</Fragment> </Fragment>
)} )}
</ThemeProvider>) </ThemeProvider>
)
} }
const appEl = document.getElementById('app') const appEl = document.getElementById('app')
render(<App />, appEl) render(<App />, appEl)

19
src/components/Chat/index.js Normal file → Executable file
View File

@ -26,18 +26,23 @@ const Chat = ({ overlayActive }) => {
</Label> </Label>
<CloseBox colour={colours.white} size={18} onClick={toggleChatOpen} /> <CloseBox colour={colours.white} size={18} onClick={toggleChatOpen} />
</ChatHeader> </ChatHeader>
<iframe {/* <iframe
src={`https://titanembeds.com/embed/${config.chat.guildId}?css=${config.chat.css}&defaultchannel=${config.chat.channelId}&lang=en_EN`} src="https://discord.com/widget?id=854082188785221662&theme=dark"
height={(height / 4) * 3}
width="350" width="350"
height="500"
allowTransparency="true"
frameBorder="0" frameBorder="0"
title="discord-chat" sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"
className="titanembed" title="chat"
/> /> */}
</ChatFrame> </ChatFrame>
</ChatWrapper> </ChatWrapper>
) : ( ) : (
<ChatHeader chatIsOpen={false} onClick={toggleChatOpen} $active={overlayActive}> <ChatHeader
chatIsOpen={false}
onClick={toggleChatOpen}
$active={overlayActive}
>
<Label weight="400" size={16} colour={colours.midnightDarker}> <Label weight="400" size={16} colour={colours.midnightDarker}>
CHAT CHAT
</Label> </Label>

18
src/components/EpisodeCard/styles.js Normal file → Executable file
View File

@ -16,7 +16,8 @@ export const ButtonRow = styled(Flexbox)`
width: 100%; width: 100%;
align-items: stretch; align-items: stretch;
button, a{ button,
a {
font-size: 16px; font-size: 16px;
width: 49%; width: 49%;
height: 100%; height: 100%;
@ -29,11 +30,12 @@ export const ButtonRow = styled(Flexbox)`
@media screen and (min-width: ${screenSizes.md}px) and (max-width: ${screenSizes.lg}px) { @media screen and (min-width: ${screenSizes.md}px) and (max-width: ${screenSizes.lg}px) {
flex-direction: column; flex-direction: column;
button, a { button,
a {
width: 100%; width: 100%;
height: auto;
} }
} }
` `
export const Left = styled(FlexColumn)` export const Left = styled(FlexColumn)`
@ -43,20 +45,20 @@ export const Left = styled(FlexColumn)`
@media screen and (max-width: ${screenSizes.md}px) { @media screen and (max-width: ${screenSizes.md}px) {
margin-right: 0em; margin-right: 0em;
} }
` `
export const Center = styled(FlexColumn)` export const Center = styled(FlexColumn)`
@media screen and (max-width: ${screenSizes.md}px) { @media screen and (max-width: ${screenSizes.md}px) {
order: 2; order: 2;
position: relative; position: relative;
top: -1em; top: -1em;
} }
` `
export const Title = styled(H2)` export const Title = styled(H2)`
max-width: 80%; max-width: 80%;
margin-bottom: 1em; margin-bottom: 1em;
` `
export const Right = styled.div` export const Right = styled.div`
flex: 1; flex: 1;

49
src/components/StreamPreview/index.js Normal file → Executable file
View File

@ -1,10 +1,7 @@
import { Fragment, h } from 'preact' import { h } from 'preact'
import { useEffect, useRef } from 'preact/hooks' import { useEffect, useRef } from 'preact/hooks'
import { PeerTubePlayer } from '@peertube/embed-api' import { PeerTubePlayer } from '@peertube/embed-api'
import { string } from 'prop-types'
import Link from '../Link'
import { Label } from '../Text' import { Label } from '../Text'
import strings from '../../data/strings'
import { colours, textSizes } from '../../assets/theme' import { colours, textSizes } from '../../assets/theme'
import { Row } from '../Flex' import { Row } from '../Flex'
import CrossSvg from '../Svg/Cross' import CrossSvg from '../Svg/Cross'
@ -13,18 +10,18 @@ import { getLabel } from './helpers'
import Chevron from '../Svg/Chevron' import Chevron from '../Svg/Chevron'
import { Frame, Img, Iframe, InnerWrapper } from './styles' import { Frame, Img, Iframe, InnerWrapper } from './styles'
// import { useEventApi } from '../../hooks/data'
const StreamPreview = ({ stream, isLive, ...rest }) => { const StreamPreview = ({ stream, isLive, ...rest }) => {
const currentLanguage = 'en' const currentLanguage = 'en'
const videoiFrame = useRef(null) const videoiFrame = useRef(null)
const ptVideo = useRef(null) const ptVideo = useRef(null)
const { isMinimized, toggleMinimized, setStreamActive } = useUiStore(store => ({ const { isMinimized, toggleMinimized, setStreamActive } = useUiStore(
store => ({
isMinimized: store.streamPreviewMinimized, isMinimized: store.streamPreviewMinimized,
toggleMinimized: store.toggleStreamPreviewMinimized, toggleMinimized: store.toggleStreamPreviewMinimized,
setStreamActive: store.setStreamActive setStreamActive: store.setStreamActive,
})) })
)
useEffect(() => { useEffect(() => {
const setupAndPlayVideo = async () => { const setupAndPlayVideo = async () => {
@ -47,12 +44,30 @@ const StreamPreview = ({ stream, isLive, ...rest }) => {
return stream ? ( return stream ? (
<Frame isMinimized={isMinimized}> <Frame isMinimized={isMinimized}>
<Row justify="space-between"> <Row justify="space-between">
<Label colour={colours.midnightDarker} size={textSizes.lg} onClick={activateStream}>{getLabel(stream, isLive, isMinimized)}</Label> <Label
{isMinimized ? <Chevron colour={colours.midnightDarker} size={14} onClick={toggleMinimized} /> : <CrossSvg colour={colours.midnightDarker} size={16} onClick={toggleMinimized} />} colour={colours.midnightDarker}
size={textSizes.lg}
onClick={activateStream}
>
{getLabel(stream, isLive, isMinimized)}
</Label>
{isMinimized ? (
<Chevron
colour={colours.midnightDarker}
size={14}
onClick={toggleMinimized}
/>
) : (
<CrossSvg
colour={colours.midnightDarker}
size={16}
onClick={toggleMinimized}
/>
)}
</Row> </Row>
{!isMinimized ? {!isMinimized ? (
<InnerWrapper onClick={activateStream}> <InnerWrapper onClick={activateStream}>
{isLive ? {isLive ? (
<Iframe <Iframe
width="560" width="560"
height="315" height="315"
@ -64,11 +79,13 @@ const StreamPreview = ({ stream, isLive, ...rest }) => {
allowFullScreen allowFullScreen
ref={videoiFrame} ref={videoiFrame}
/> />
: <Img src={stream.image} onClick={activateStream} />} ) : (
</InnerWrapper> : null} <Img src={stream.image} onClick={activateStream} />
)}
</InnerWrapper>
) : null}
</Frame> </Frame>
) : null ) : null
} }
export default StreamPreview export default StreamPreview

18
src/pages/Series/index.js Normal file → Executable file
View File

@ -14,20 +14,23 @@ const Series = () => {
const { data } = useEventApi() const { data } = useEventApi()
const pastSeries = [] const pastSeries = []
const currentSeries = data.series ? data.series.filter(series => { const currentSeries = data.series
? data.series.filter(series => {
if (series.episodes.future.length) { if (series.episodes.future.length) {
return true return true
} }
if (series.episodes.past.every(({ beginsOn }) => isFuture(addYears(new Date(beginsOn), 1)))) { if (
series.episodes.past.every(({ beginsOn }) =>
isFuture(addYears(new Date(beginsOn), 1))
)
) {
return true return true
} }
pastSeries.push(series) pastSeries.push(series)
return false return false
}) : [] })
: []
console.log({ currentSeries })
return ( return (
<Page title={strings.en.series}> <Page title={strings.en.series}>
@ -48,7 +51,8 @@ const Series = () => {
<SeriesCard series={series} isPast /> <SeriesCard series={series} isPast />
))} ))}
</SeriesGrid> </SeriesGrid>
</Fragment>) : null} </Fragment>
) : null}
</Content> </Content>
</Page> </Page>
) )

51
src/pages/SeriesPage/index.js Normal file → Executable file
View File

@ -26,24 +26,37 @@ const SeriesPage = ({ data }) => {
const theme = data.theme || defaultTheme const theme = data.theme || defaultTheme
const { orgs } = data const { orgs } = data
const credits = data.credits ? ` const credits = data.credits
? `
## Credits ## Credits
${data.credits} ${data.credits}
` : null `
: null
const orgsList = Object.values(orgs || {}) const orgsList = Object.values(orgs || {})
console.log({ orgsList })
const links = data.links.length ? splitArray(data.links, 2) : null const links = data.links.length ? splitArray(data.links, 2) : null
console.log({ description: data.description })
return ( return (
<Page title={data.title} theme={data.theme} withHeader={false}> <Page title={data.title} theme={data.theme} withHeader={false}>
<InfoLayout title={data.title} subtitle={data.subtitle} image={data.image} theme={theme}> <InfoLayout
title={data.title}
subtitle={data.subtitle}
image={data.image}
theme={theme}
>
<Fragment> <Fragment>
<InfoContent> <InfoContent>
<H1>{data.title}:</H1> <H1>{data.title}:</H1>
<H1>{data.subtitle}</H1> <H1>{data.subtitle}</H1>
{data.description ? <Markdown withLinebreaks theme={theme}>{data.description}</Markdown> : null} {data.description ? (
<Markdown withLinebreaks theme={theme}>
{data.description}
</Markdown>
) : null}
{data.trailer ? ( {data.trailer ? (
<TrailerContainer> <TrailerContainer>
@ -51,8 +64,9 @@ const SeriesPage = ({ data }) => {
</TrailerContainer> </TrailerContainer>
) : null} ) : null}
{links ? {links
links.map(linkRow => <Row> ? links.map(linkRow => (
<Row>
{linkRow.map(link => ( {linkRow.map(link => (
<a <a
href={link.resourceUrl} href={link.resourceUrl}
@ -62,18 +76,15 @@ const SeriesPage = ({ data }) => {
<Button>{link.summary}</Button> <Button>{link.summary}</Button>
</a> </a>
))} ))}
</Row>) : null </Row>
} ))
: null}
</InfoContent> </InfoContent>
{data.episodes.future.length ? ( {data.episodes.future.length ? (
<Fragment> <Fragment>
<Title>{translations.en.program}:</Title> <Title>{translations.en.program}:</Title>
{data.episodes.future.map(feeditem => ( {data.episodes.future.map(feeditem => (
<EpisodeCard <EpisodeCard theme={theme} key={feeditem.start} {...feeditem} />
theme={theme}
key={feeditem.start}
{...feeditem}
/>
))} ))}
</Fragment> </Fragment>
) : null} ) : null}
@ -91,18 +102,22 @@ const SeriesPage = ({ data }) => {
))} ))}
</Fragment> </Fragment>
) : null} ) : null}
{credits ? <InfoContent> {credits ? (
<InfoContent>
<Markdown theme={theme}>{credits}</Markdown> <Markdown theme={theme}>{credits}</Markdown>
</InfoContent> : null} </InfoContent>
) : null}
</Fragment> </Fragment>
{orgsList.length ? ( {orgsList.length ? (
<LogosRow $wrap> <LogosRow $wrap>
{orgsList.map((org, index) => ( {orgsList.map((org, index) => (
<Fragment> <Fragment>
<a href={org.orgUrl}>
<img src={org.logoUrl} alt={`${org.orgName} logo`} /> <img src={org.logoUrl} alt={`${org.orgName} logo`} />
</a> {orgsList.length < 4 !== 1 &&
{orgsList.length === 2 && index + 1 !== orgsList.length ? <Label colour={theme.foreground}>{'//'}</Label> : null} orgsList.length < 4 &&
index + 1 !== orgsList.length ? (
<Label colour={theme.foreground}>{'//'}</Label>
) : null}
</Fragment> </Fragment>
))} ))}
</LogosRow> </LogosRow>

41
src/pages/SeriesPage/styles.js Normal file → Executable file
View File

@ -40,7 +40,6 @@ export const TrailerContainer = styled.div`
} }
` `
export const ActionButton = styled(Button)` export const ActionButton = styled(Button)`
font-size: 18px; font-size: 18px;
` `
@ -49,7 +48,7 @@ export const Row = styled.div`
display: flex; display: flex;
flex-direction: row; flex-direction: row;
margin-bottom: 32px; margin-bottom: 32px;
flex-wrap: ${props => props.$wrap ? 'wrap' : 'nowrap'}; flex-wrap: ${props => (props.$wrap ? 'wrap' : 'nowrap')};
a { a {
display: block; display: block;
@ -64,19 +63,20 @@ export const LogosRow = styled(Row)`
align-items: center; align-items: center;
max-width: 600px; max-width: 600px;
justify-content: space-between; justify-content: space-between;
padding: 32px 0 ; padding: 32px 0;
a { a {
width: auto; width: auto;
margin-right: 0; margin-right: 0;
&[href]:hover { &[href]:hover {
opacity: 0.7 opacity: 0.7;
} }
} }
img { img {
height: 64px; max-height: 42px;
width: 25%;
} }
` `
@ -170,7 +170,7 @@ export const EpisodeCard = ({
videoUrl, videoUrl,
theme, theme,
peertubeReplay, peertubeReplay,
id id,
}) => { }) => {
const startDate = new Date(beginsOn) const startDate = new Date(beginsOn)
@ -179,11 +179,14 @@ export const EpisodeCard = ({
const zonedDate = utcToZonedTime(utcDate, timeZone) const zonedDate = utcToZonedTime(utcDate, timeZone)
const timezoneLabel = format(zonedDate, hasPassed ? 'dd/MM/yy' : 'do LLLL y // HH:mm zzz', { const timezoneLabel = format(
zonedDate,
hasPassed ? 'dd/MM/yy' : 'do LLLL y // HH:mm zzz',
{
timeZone, timeZone,
locale: enGB, locale: enGB,
}) }
)
return ( return (
<VCWrapper id={id}> <VCWrapper id={id}>
@ -204,11 +207,25 @@ export const EpisodeCard = ({
<VCImg src={image} alt="" /> <VCImg src={image} alt="" />
</Fragment> </Fragment>
)} )}
<Markdown withLinebreaks theme={theme}>{description}</Markdown> <Markdown withLinebreaks theme={theme}>
{description}
</Markdown>
{hasPassed ? ( {hasPassed ? (
<a href={peertubeReplay.url || url}><Button>{peertubeReplay.url ? translations.en.watchEpisode : translations.en.eventDetails}</Button></a> <a href={peertubeReplay.url || url}>
<Button>
{peertubeReplay.url
? translations.en.watchEpisode
: translations.en.eventDetails}
</Button>
</a>
) : ( ) : (
<ButtonsRows title={title} description={description} beginsOn={beginsOn} endsOn={endsOn} url={url} /> <ButtonsRows
title={title}
description={description}
beginsOn={beginsOn}
endsOn={endsOn}
url={url}
/>
)} )}
</VCWrapper> </VCWrapper>
) )