last min fixes
This commit is contained in:
parent
9852003f55
commit
28fae929b2
18
app.js
18
app.js
@ -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)
|
||||
|
@ -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/" />
|
||||
|
@ -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>
|
||||
|
@ -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};
|
||||
}
|
||||
`
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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}
|
||||
|
@ -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>
|
||||
)
|
||||
}
|
||||
|
@ -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;
|
||||
`
|
||||
|
@ -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>
|
||||
)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
`
|
||||
|
@ -10,5 +10,6 @@ export default {
|
||||
subEvent: 'Add to calendar',
|
||||
watchEpisode: 'Watch Episode',
|
||||
watchTrailer: 'Watch the trailer',
|
||||
joinStream: 'Click to join stream',
|
||||
},
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user