last min fixes

This commit is contained in:
Benjamin Jones 2021-05-23 17:21:15 +02:00
parent 9852003f55
commit 28fae929b2
13 changed files with 151 additions and 48 deletions

18
app.js
View File

@ -1,6 +1,7 @@
import { h } from 'preact'
import { useState, useEffect } from 'preact/hooks'
import { isWithinInterval, subHours } from 'date-fns'
import { zonedTimeToUtc, utcToZonedTime, format } from 'date-fns-tz'
import { addHours } from 'date-fns/esm'
import Video from './src/components/Video'
@ -23,18 +24,27 @@ export default () => {
useEffect(() => {
if (data && data.length) {
data.forEach((stream, index) => {
const utcStartDate = zonedTimeToUtc(
new Date(stream.start),
'Europe/Berlin'
)
const utcEndDate = zonedTimeToUtc(new Date(stream.end), 'Europe/Berlin')
const { timeZone } = Intl.DateTimeFormat().resolvedOptions()
const zonedStartDate = utcToZonedTime(utcStartDate, timeZone)
const zonedEndDate = utcToZonedTime(utcEndDate, timeZone)
if (
isWithinInterval(new Date(), {
start: subHours(stream.start, 1),
end: addHours(stream.end, 1),
start: subHours(zonedStartDate, 1),
end: addHours(zonedEndDate, 1),
})
) {
setCurrentVideo(stream)
}
if (
isWithinInterval(new Date(), {
start: stream.start,
end: stream.end,
start: zonedStartDate,
end: zonedEndDate,
})
) {
setStreamIsLive(true)

View File

@ -37,7 +37,7 @@
/>
<meta
name="twitter:description"
content="The Para-Real: Finding the Future in Unexpected Places - A livestream series about subcultures building livelihoods in spite of platform exploitation."
content="The NEW DESIGN CONGRESS x RECLAIMFUTURES present a livestream series about subcultures building livelihoods in spite of platform exploitation."
/>
<meta name="twitter:image" content="static/meta.png" />
@ -47,7 +47,7 @@
/>
<meta
property="og:description"
content="The Para-Real: Finding the Future in Unexpected Places - A livestream series about subcultures building livelihoods in spite of platform exploitation."
content="The NEW DESIGN CONGRESS x RECLAIMFUTURES present a livestream series about subcultures building livelihoods in spite of platform exploitation"
/>
<meta property="og:image" content="static/meta.png" />
<meta property="og:url" content="https://stream.undersco.re/" />

View File

@ -13,11 +13,11 @@ import {
} from './styles'
import { colours } from '../../assets/theme'
const Chat = ({}) => {
const Chat = ({ overlayActive }) => {
const { width, height } = useWindowDimensions()
const [chatIsOpen, toggleChatOpen] = useToggle(true)
return chatIsOpen ? (
<ChatWrapper>
<ChatWrapper chatIsOpen={chatIsOpen} overlayActive={overlayActive}>
<ChatFrame>
<ChatHeader chatIsOpen>
<Label weight="400" size={24}>
@ -26,7 +26,7 @@ const Chat = ({}) => {
<CloseBox colour={colours.white} size={18} onClick={toggleChatOpen} />
</ChatHeader>
<iframe
src="https://titanembeds.com/embed/803918964082212905?css=215&defaultchannel=817134294199566356&lang=en_EN"
src="https://titanembeds.com/embed/709318870909059082?css=215&defaultchannel=826751398757793842&lang=en_EN"
height={(height / 4) * 3}
width="350"
frameBorder="0"
@ -38,7 +38,7 @@ const Chat = ({}) => {
) : (
<ChatHeader chatIsOpen={false} onClick={toggleChatOpen}>
<Label weight="400" size={24}>
Chat
CHAT
</Label>
<OpenIcon colour={colours.white} size={16} />
</ChatHeader>

View File

@ -15,16 +15,20 @@ export const ChatWrapper = styled.div`
bottom: -5px;
right: 0;
backdrop-filter: blur(20px);
background-color: ${colours.midnight}40;
background-color: ${colours.midnight}60;
border-radius: ${ui.borderRadius}px;
opacity: ${props => (!props.chatIsOpen && !props.overlayActive ? 0 : 1)};
`
export const ChatHeader = styled.div`
position: absolute;
bottom: ${props => (props.chatIsOpen ? 'initial' : 0)};
top: ${props => (props.chatIsOpen ? '4px' : 'initial')};
border-radius: ${ui.borderRadius}px 0 0 0;
bottom: ${props => (props.chatIsOpen ? 'initial' : '0')};
top: ${props => (props.chatIsOpen ? '0px' : 'initial')};
border-radius: ${props =>
props.chatIsOpen ? `${ui.borderRadius}px 0 0 0` : '0'};
z-index: 2;
background-color: ${props => (props.chatIsOpen ? '#00000036' : '#ffffffba')};
backdrop-filter: blur(2px);
height: 32px;
box-sizing: border-box;
@ -34,17 +38,23 @@ export const ChatHeader = styled.div`
justify-content: space-between;
padding: 0px 0px 3px 0px;
right: 0;
right: ${props => (props.chatIsOpen ? '0' : '32px')};
box-sizing: content-box;
border: ${props =>
props.chatIsOpen ? 'none' : `1px solid ${colours.white}`};
props.chatIsOpen ? 'none' : `1px solid ${colours.midnightDarker}`};
border-bottom: ${props =>
props.chatIsOpen ? `1px solid ${colours.white}75` : 'none'};
border-right: none;
/* border-right: none; */
label {
margin-left: 12px;
margin-right: ${props => (props.chatIsOpen ? '0' : '12px')};
color: ${props =>
props.chatIsOpen ? colours.white : colours.midnightDarker};
}
svg path {
fill: ${props =>
props.chatIsOpen ? colours.white : colours.midnightDarker};
}
`

View File

@ -58,7 +58,9 @@ const Info = ({ data, loading, infoActive, setInfoActive, currentVideo }) => {
url={config.seriesTrailer}
/>
)}
{infoActive && <CrossSvg onClick={() => setInfoActive(false)} />}
{infoActive && (
<CrossSvg size="64" onClick={() => setInfoActive(false)} />
)}
{!loading && (
<Fragment>
<InfoContent>
@ -92,14 +94,14 @@ const Info = ({ data, loading, infoActive, setInfoActive, currentVideo }) => {
</Fragment>
)}
{futureStreams.length && (
{futureStreams.length ? (
<Fragment>
<Title>{translations.en.nextStream}:</Title>
{futureStreams.map(feeditem => (
<VideoCard key={feeditem.start} {...feeditem} />
))}
</Fragment>
)}
) : null}
{pastStreams.length ? (
<Fragment>

View File

@ -130,10 +130,11 @@ export const PositionedCross = styled(CrossSvg)`
position: fixed;
right: 2.5em;
top: 2em;
width: 24px;
height: 24px;
/* width: 32px; */
/* height: 32px; */
cursor: pointer;
stroke: ${colours.midnightDarker};
z-index: 5;
&:hover {
opacity: 0.5;

View File

@ -18,7 +18,7 @@ const Logo = ({ colour = colours.offwhite, ...rest }) => (
)
const LogoSvg = styled.svg`
height: 60px;
height: ${props => (props.$size === 'lg' ? '60px' : '32px')};
`
Logo.propTypes = {
@ -31,6 +31,7 @@ export const NdcLogo = ({ colour = colours.offwhite, ...rest }) => (
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 552 140"
$size="lg"
{...rest}
>
<path
@ -45,6 +46,7 @@ export const RFLogo = ({ colour = colours.offwhite, ...rest }) => (
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 299 140"
$size="lg"
{...rest}
>
<path

View File

@ -91,11 +91,11 @@ export const H2 = ({ children, ...rest }) => (
</Text>
)
export const P = ({ children, ...rest }) => (
export const P = ({ children, size, ...rest }) => (
<Text
tag="p"
weight="400"
$size="15"
$size={size || '15'}
lineHeight="21px"
fontFamily="Karla"
{...rest}

View File

@ -14,11 +14,13 @@ import { PeerTubePlayer } from '@peertube/embed-api'
import Chat from '../Chat'
import Overlay from '../VideoOverlay'
import { VideoWrapper, Iframe } from './styles'
import { VideoWrapper, Iframe, PlayButton } from './styles'
import config from '../../data/config'
import { useToggle } from '../../hooks/utility'
const Video = ({ video, org, setInfoActive }) => {
const [isPlaying, setPlaying] = useState(false)
const [isFullscreen, toggleIsFullscreen] = useToggle(false)
const videoiFrame = useRef(null)
const overlayTimeout = useRef(null)
const [videoReady, setVideoReady] = useState(false)
@ -73,6 +75,7 @@ const Video = ({ video, org, setInfoActive }) => {
}
const toggleFullscreen = () => {
toggleIsFullscreen()
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen()
} else if (document.exitFullscreen) {
@ -120,7 +123,10 @@ const Video = ({ video, org, setInfoActive }) => {
active={overlayActive || !isPlaying}
title={video.title}
setInfoActive={setInfoActive}
onClickFullscreen={toggleFullscreen}
isFullscreen={isFullscreen}
/>
{!isPlaying && <PlayButton />}
<Iframe
sandbox="allow-same-origin allow-scripts allow-popups"
src={`${config.peertube_root}${video.embedPath}?api=1&controls=false&vq=hd1080`}
@ -129,7 +135,7 @@ const Video = ({ video, org, setInfoActive }) => {
allow="autoplay"
ref={videoiFrame}
/>
<Chat />
<Chat overlayActive={overlayActive} />
</VideoWrapper>
)
}

View File

@ -1,4 +1,9 @@
import { h } from 'preact'
import styled from 'styled-components'
import { Label } from '../Text'
import translations from '../../data/strings'
import Button from '../Button'
import { colours } from '../../assets/theme'
export const VideoWrapper = styled.div`
width: 100vw;
@ -10,12 +15,16 @@ export const VideoWrapper = styled.div`
left: 0;
right: 0;
cursor: ${props => (props.$active ? 'pointer' : 'none')};
display: flex;
justify-content: center;
align-items: center;
`
export const Iframe = styled.iframe`
z-index: -1;
width: 100vw;
height: 100vh;
pointer-events: none;
position: absolute;
`
export const Overlay = styled.div`
z-index: 1;
@ -23,3 +32,36 @@ export const Overlay = styled.div`
height: 100vh;
width: 100vw;
`
const ButtonWrapper = styled.div`
div {
padding: 1em 2em;
background-color: #ffffffba;
display: flex;
flex-direction: row;
align-items: center;
border: 1px solid ${colours.midnight};
}
label {
color: ${colours.midnightDarker};
margin-left: 8px;
font-size: 20px;
}
:hover div {
background-color: #ffffff;
}
`
export const PlayButton = props => (
<ButtonWrapper {...props}>
<div>
<Label>{translations.en.joinStream}</Label>
</div>
</ButtonWrapper>
)
export const ActionButton = styled(Button)`
font-size: 18px;
`

View File

@ -1,28 +1,54 @@
import { Fragment, h } from 'preact'
import { bool, string } from 'prop-types'
import styled from 'styled-components'
import Logo from '../Logo'
import { H2, P } from '../Text'
import { InfoButton, OverlayWrapper, TopLeft } from './styles'
const VideoOverlay = ({ active, title, org, setInfoActive, onClick }) => (
const StyledP = styled(P)`
&:first-of-type {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
&:last-of-type {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
`
const renderTitles = titles =>
titles.split('\\n').map(title => (
<StyledP key={title} size={18}>
{title}
</StyledP>
))
const VideoOverlay = ({
active,
title,
org,
setInfoActive,
onClick,
onClickFullscreen,
isFullscreen,
}) => (
// const displayTitle = `${title}${org ? ` — ${org}` : ''}`
<Fragment>
<OverlayWrapper onClick={onClick}>
<TopLeft $active={active}>
<Logo active={active} />
<P
size={18}
css={`
margin-top: 16px;
`}
>
{title}
</P>
{/* <Logo active={active} /> */}
{title ? renderTitles(title) : null}
</TopLeft>
</OverlayWrapper>
<InfoButton $active={active} onClick={() => setInfoActive(true)} />
<InfoButton $active={active} onClick={() => setInfoActive(true)}>
INFO
</InfoButton>
<InfoButton $active={active} onClick={onClickFullscreen} postition="bl">
{isFullscreen ? 'EXIT FULLSCREEN' : 'FULLSCREEN'}
</InfoButton>
</Fragment>
)

View File

@ -1,6 +1,7 @@
import styled, { css } from 'styled-components'
import { colours } from '../../assets/theme'
import burb from '../../assets/img/IconSM.png'
import Button from '../Button'
export const OverlayWrapper = styled.div`
z-index: 2;
@ -28,23 +29,25 @@ export const TopLeft = styled.div`
padding: 4px 8px;
display: inline-block;
margin-right: 45%;
border-radius: 5px;
}
`
export const InfoButton = styled.img.attrs(() => ({
src: burb,
}))`
export const InfoButton = styled(Button)`
opacity: 0.001;
transform: translateY(-20%);
transform: translateY(
${props => (props.postition === 'bl' ? '20%' : '-20%')}
);
transition: all 0.2s ease-in-out;
transition-delay: 0.2s;
position: fixed;
right: 2em;
top: 2em;
width: 45px;
height: 45px;
right: ${props => (props.postition === 'bl' ? 'initial' : '32px')};
top: ${props => (props.postition === 'bl' ? 'initial' : '32px')};
bottom: ${props => (props.postition === 'bl' ? '0' : 'initial')};
left: ${props => (props.postition === 'bl' ? '32px' : 'initial')};
z-index: 100;
width: auto;
background-color: #ffffffba;
${props =>
props.$active &&
css`
@ -53,6 +56,6 @@ export const InfoButton = styled.img.attrs(() => ({
`};
&:hover {
filter: invert(1);
opacity: 0.7;
}
`

View File

@ -10,5 +10,6 @@ export default {
subEvent: 'Add to calendar',
watchEpisode: 'Watch Episode',
watchTrailer: 'Watch the trailer',
joinStream: 'Click to join stream',
},
}