added timezone adaptation, trailer etc

This commit is contained in:
Benjamin Jones 2021-05-17 01:08:25 +02:00
parent 90b3a71b2f
commit e07fc8c510
10 changed files with 131 additions and 17 deletions

View File

@ -18,6 +18,7 @@
"@peertube/embed-api": "^0.0.4", "@peertube/embed-api": "^0.0.4",
"axios": "^0.21.1", "axios": "^0.21.1",
"date-fns": "^2.19.0", "date-fns": "^2.19.0",
"date-fns-tz": "^1.1.4",
"ical": "^0.8.0", "ical": "^0.8.0",
"ical.js": "^1.4.0", "ical.js": "^1.4.0",
"markdown-to-jsx": "^7.1.2", "markdown-to-jsx": "^7.1.2",

View File

@ -1,11 +1,13 @@
/* eslint-disable react/prop-types */ /* eslint-disable react/prop-types */
import { h, Fragment } from 'preact' import { h, Fragment } from 'preact'
import { useState, useEffect } from 'preact/hooks'
import { isFuture, isPast } from 'date-fns' import { isFuture, isPast } from 'date-fns'
import { H1 } from '../Text' import { H1 } from '../Text'
import Markdown from '../Markdown' import Markdown from '../Markdown'
import translations from '../../data/strings' import translations from '../../data/strings'
import InfoLayout from '../InfoLayout' import InfoLayout from '../InfoLayout'
import TrailerEmbed from '../VideoEmbed'
import { import {
VideoCard, VideoCard,
Title, Title,
@ -19,8 +21,12 @@ import credits from '../../data/credits.md'
import Button from '../Button' import Button from '../Button'
import PlaySvg from '../Svg/Play' import PlaySvg from '../Svg/Play'
import { colours } from '../../assets/theme' import { colours } from '../../assets/theme'
import config from '../../data/config'
const Info = ({ data, loading, infoActive, setInfoActive, currentVideo }) => { const Info = ({ data, loading, infoActive, setInfoActive, currentVideo }) => {
const [trailerActive, setTrailerActive] = useState(false)
const toggleTrailerActive = () =>
setTrailerActive(trailerState => !trailerState)
const pastStreams = const pastStreams =
data && data.length data && data.length
? data.filter(feeditem => isPast(new Date(feeditem.end))) ? data.filter(feeditem => isPast(new Date(feeditem.end)))
@ -44,6 +50,12 @@ const Info = ({ data, loading, infoActive, setInfoActive, currentVideo }) => {
return ( return (
<InfoLayout loading={loading}> <InfoLayout loading={loading}>
{trailerActive && (
<TrailerEmbed
onClose={toggleTrailerActive}
url={config.seriesTrailer}
/>
)}
{infoActive && <CrossSvg onClick={() => setInfoActive(false)} />} {infoActive && <CrossSvg onClick={() => setInfoActive(false)} />}
{!loading && ( {!loading && (
<Fragment> <Fragment>
@ -51,7 +63,7 @@ const Info = ({ data, loading, infoActive, setInfoActive, currentVideo }) => {
<H1>The Para-Real:</H1> <H1>The Para-Real:</H1>
<H1>Finding the Future in Unexpected Places</H1> <H1>Finding the Future in Unexpected Places</H1>
<Markdown withLinebreaks>{intro}</Markdown> <Markdown withLinebreaks>{intro}</Markdown>
<Button> <Button onClick={toggleTrailerActive}>
<PlaySvg colour={colours.midnightDarker} size="20" /> <PlaySvg colour={colours.midnightDarker} size="20" />
Watch the trailer Watch the trailer
</Button> </Button>

View File

@ -1,5 +1,5 @@
import { format } from 'date-fns'
import { h, Fragment } from 'preact' import { h, Fragment } from 'preact'
import { zonedTimeToUtc, utcToZonedTime, format } from 'date-fns-tz'
import styled from 'styled-components' import styled from 'styled-components'
import { colours, textSizes } from '../../assets/theme' import { colours, textSizes } from '../../assets/theme'
import config from '../../data/config' import config from '../../data/config'
@ -121,15 +121,19 @@ export const VideoCard = ({
hasPassed, hasPassed,
videoUrl, videoUrl,
}) => { }) => {
console.log('start', start) const startDate = new Date(start)
const utcDate = zonedTimeToUtc(startDate, 'Europe/Berlin')
const { timeZone } = Intl.DateTimeFormat().resolvedOptions()
const zonedDate = utcToZonedTime(utcDate, timeZone)
return ( return (
<VCWrapper> <VCWrapper>
<DateLabel colour={colours.midnight} size={textSizes.lg}> <DateLabel colour={colours.midnight} size={textSizes.lg}>
{`${hasPassed ? translations.en.streamDatePast : ''}`} {`${hasPassed ? translations.en.streamDatePast : ''}`}
<Span bold colour={colours.midnight}> <Span bold colour={colours.midnight}>
{hasPassed {hasPassed
? format(new Date(start), 'dd/MM/yy') ? format(zonedDate, 'dd/MM/yy')
: format(new Date(start), 'do LLLL y // HH:mm')} : format(zonedDate, 'do LLLL y // HH:mm')}
</Span> </Span>
</DateLabel> </DateLabel>
{videoUrl && hasPassed ? ( {videoUrl && hasPassed ? (
@ -144,7 +148,11 @@ export const VideoCard = ({
</Fragment> </Fragment>
)} )}
<P>{description}</P> <P>{description}</P>
<Button>Subscribe to this event</Button> <a href="webcal://cloud.undersco.re/remote.php/dav/public-calendars/9FzomgAfidHWCQcx/?export">
<Button>
{hasPassed ? translations.en.watchEpisode : translations.en.subEvent}
</Button>
</a>
</VCWrapper> </VCWrapper>
) )
} }

View File

@ -4,6 +4,7 @@ import { number, string } from 'prop-types'
const Play = ({ size = '24', colour = 'inherit', ...rest }) => ( const Play = ({ size = '24', colour = 'inherit', ...rest }) => (
<svg viewBox="0 0 24 24" height={size} width={size} {...rest}> <svg viewBox="0 0 24 24" height={size} width={size} {...rest}>
<path <path
strokeWidth="1.5"
stroke={colour} stroke={colour}
fill="transparent" fill="transparent"
d="M2.12436,1.73205 C2.12436,0.96225 2.95769,0.481125 3.62436,0.866025 L21.6244,11.2583 C22.291,11.6432 22.291,12.6055 21.6244,12.9904 L3.62436,23.3827 C2.95769,23.7676 2.12436,23.2865 2.12436,22.5167 L2.12436,1.73205 Z" d="M2.12436,1.73205 C2.12436,0.96225 2.95769,0.481125 3.62436,0.866025 L21.6244,11.2583 C22.291,11.6432 22.291,12.6055 21.6244,12.9904 L3.62436,23.3827 C2.95769,23.7676 2.12436,23.2865 2.12436,22.5167 L2.12436,1.73205 Z"

View File

@ -123,7 +123,7 @@ const Video = ({ video, org, setInfoActive }) => {
/> />
<Iframe <Iframe
sandbox="allow-same-origin allow-scripts allow-popups" sandbox="allow-same-origin allow-scripts allow-popups"
src={`${config.peertube_root}${video.embedPath}?api=1&controls=false`} src={`${config.peertube_root}${video.embedPath}?api=1&controls=false&vq=hd1080`}
frameborder="0" frameborder="0"
allowfullscreen allowfullscreen
allow="autoplay" allow="autoplay"

View File

@ -0,0 +1,44 @@
import { Fragment, h } from 'preact'
import { useEffect, useRef, useState } from 'preact/hooks'
import { string } from 'prop-types'
import { VideoWrapper, Iframe, StyledCrossSvg as CrossSvg } from './styles'
const Video = ({ url, onClose }) => {
const overlayTimeout = useRef(null)
const [overlayActive, setOverlayActiveState] = useState(false)
const activateOverlay = () => {
clearTimeout(overlayTimeout.current)
overlayTimeout.current = null
setOverlayActiveState(true)
console.log('overlayTimeout.current', overlayTimeout.current)
overlayTimeout.current = setTimeout(
() => setOverlayActiveState(false),
1500
)
}
return (
<Fragment>
<VideoWrapper onMouseMove={activateOverlay} $active={overlayActive}>
<CrossSvg $active={overlayActive} onClick={onClose} size="64" />
</VideoWrapper>
<Iframe
width="560"
height="315"
src="https://www.youtube-nocookie.com/embed/Ye5qTm9vqcE?controls=0&autoplay=1"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
/>
</Fragment>
)
}
Video.propTypes = {
url: string,
}
export default Video

View File

@ -0,0 +1,41 @@
import styled from 'styled-components'
import { colours } from '../../assets/theme'
import CrossSvg from '../Svg/Cross'
export const VideoWrapper = styled.div`
width: 100vw;
height: 100vh;
z-index: 12;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
/* background-color: ${props => (props.$active ? 'red' : 'green')}; */
`
export const Iframe = styled.iframe`
z-index: 1;
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
`
export const StyledCrossSvg = styled(CrossSvg)`
position: fixed;
right: 2.5em;
top: 2em;
width: 64px;
height: 64px;
cursor: pointer;
stroke: ${colours.midnightDarker};
z-index: 12;
opacity: ${props => (props.$active ? '1' : '0.2')};
&:hover {
opacity: 1;
}
`

View File

@ -1,14 +1,8 @@
export default { export default {
peertube_root: 'https://tv.undersco.re', peertube_root: 'https://tv.undersco.re',
seriesTrailer:
'https://tv.undersco.re/videos/embed/5e29327c-41de-4b48-b567-ee28b181336f',
calendar: calendar:
'https://cloud.undersco.re/remote.php/dav/public-calendars/9FzomgAfidHWCQcx?export', 'https://cloud.undersco.re/remote.php/dav/public-calendars/9FzomgAfidHWCQcx?export',
next_stream: {
title: 'Femboy Photoshoot',
peertube_id: 'cafce2b3-550b-4656-bae0-c167d3994a0d',
org: 'New Design Congress',
startDate:
'Fri Mar 05 2021 21:00:00 GMT+0100 (Central European Standard Time',
endDate:
'Fri Mar 05 2021 21:00:00 GMT+0100 (Central European Standard Time',
},
} }

View File

@ -7,6 +7,8 @@ export default {
underscoreTagline: ['LEAVE THE', 'SURVEILLANCE ECONOMY', '— TOGETHER.'], underscoreTagline: ['LEAVE THE', 'SURVEILLANCE ECONOMY', '— TOGETHER.'],
streamDateFuture: 'Going live at: ', streamDateFuture: 'Going live at: ',
streamDatePast: 'First broadcast: ', streamDatePast: 'First broadcast: ',
subEvent: 'Subscribe to this event',
watchEpisode: 'Watch Episode',
main_text: main_text:
"[NEW DESIGN CONGRESS](https://newdesigncongress.org) x [RECLAIMFUTURES](https://reclaimfutures.org) present *The Para-Real: Finding the Future in Unexpected Places,* a Spring/Summer livestream series about economic subcultures and emergent technology use. Over 12 episodes streamed weekly, we meet filmmakers who have never met their actors, artists building their own networks of value, documentarians exploring digital identity, and members of resilient subcultures. All of these people share a commonality: they have an innate understanding of the *Para-Real,* and have seized upon it to better their surroundings. \nBetween the digital realm and our physical world is a third space, equally material but poorly understood. The *Para-Real* is a tangible place where class structures, economics and the outcomes of hardware and infrastructure design collide. The Para-Real manifests in many ways — It can be the desire for play that turns young Minecraft players into network administrators, the drive that fosters the resilience of subculture-driven mutually-supportive marketplaces, or the tension of class structures inherent in Virtual Reality's encroachment on living room space.\n\nWe shape our tools, and thereafter our tools shape us.* The Para-Real is everywhere. Whether attending a Furcon at the height of pandemic, organising community for resilience, or navigating a commissioned open world, we must consider ourselves as inhabiting not a real or online world, but a bridge between the two, one whose rules are not yet settled. *The future is not a Zoom call*. The digital systems we are confined to today merge protocol with platform to prey on isolation and extract value from labour. That we grapple with this incarnation of the digital realm indicates a dominant cartel in decline. In its place is a vacuum. We must resist the immature groupthink of the 90s vision of what the Internet can be — the Para-Real is a contested space*. Never trust someone who says the Internet is boring.* Thanks to the Para-Real, the Internet has never been weirder.", "[NEW DESIGN CONGRESS](https://newdesigncongress.org) x [RECLAIMFUTURES](https://reclaimfutures.org) present *The Para-Real: Finding the Future in Unexpected Places,* a Spring/Summer livestream series about economic subcultures and emergent technology use. Over 12 episodes streamed weekly, we meet filmmakers who have never met their actors, artists building their own networks of value, documentarians exploring digital identity, and members of resilient subcultures. All of these people share a commonality: they have an innate understanding of the *Para-Real,* and have seized upon it to better their surroundings. \nBetween the digital realm and our physical world is a third space, equally material but poorly understood. The *Para-Real* is a tangible place where class structures, economics and the outcomes of hardware and infrastructure design collide. The Para-Real manifests in many ways — It can be the desire for play that turns young Minecraft players into network administrators, the drive that fosters the resilience of subculture-driven mutually-supportive marketplaces, or the tension of class structures inherent in Virtual Reality's encroachment on living room space.\n\nWe shape our tools, and thereafter our tools shape us.* The Para-Real is everywhere. Whether attending a Furcon at the height of pandemic, organising community for resilience, or navigating a commissioned open world, we must consider ourselves as inhabiting not a real or online world, but a bridge between the two, one whose rules are not yet settled. *The future is not a Zoom call*. The digital systems we are confined to today merge protocol with platform to prey on isolation and extract value from labour. That we grapple with this incarnation of the digital realm indicates a dominant cartel in decline. In its place is a vacuum. We must resist the immature groupthink of the 90s vision of what the Internet can be — the Para-Real is a contested space*. Never trust someone who says the Internet is boring.* Thanks to the Para-Real, the Internet has never been weirder.",
}, },

View File

@ -17,7 +17,18 @@ export const useEventStream = () => {
const vevents = comp.getAllSubcomponents('vevent') const vevents = comp.getAllSubcomponents('vevent')
const calEvents = vevents const calEvents = vevents
.map(vevent => new ICAL.Event(vevent)) .filter(
vevent =>
vevent.getFirstPropertyValue('status') === null ||
(vevent.getFirstPropertyValue('status') &&
vevent.getFirstPropertyValue('status').toUpperCase() ===
'CONFIRMED')
)
.map(vevent => {
const event = new ICAL.Event(vevent)
console.log('eventstat', vevent.getFirstPropertyValue('status'))
return event
})
.sort((a, b) => a.startDate.toJSDate() - b.startDate.toJSDate()) .sort((a, b) => a.startDate.toJSDate() - b.startDate.toJSDate())
await Promise.all( await Promise.all(