added more detailed info page + styles. Commit rest before refactor

This commit is contained in:
Benjamin Jones 2021-03-10 14:51:24 +01:00
parent 8f68c37588
commit 4973f351aa
20 changed files with 337 additions and 66 deletions

40
app.js
View File

@ -5,34 +5,36 @@ import 'regenerator-runtime/runtime'
import { useEffect, useState } from 'preact/hooks' import { useEffect, useState } from 'preact/hooks'
import Video from './src/components/Video' import Video from './src/components/Video'
import config from './src/data/conf.json' import config from './src/data/config'
import Info from './src/components/Info' import Info from './src/components/Info'
import { useFetch } from './src/assets/hooks/calendar'
import { P } from './src/components/Text'
// const appStates = [
// 'noStream',
// 'streamLive',
// 'streamFinished'
// ]
export default () => { export default () => {
const [isPlaying, setIsPlaying] = useState(false) const [isPlaying, setIsPlaying] = useState(false)
const [videoUrl, setVideoUrl] = useState(null) const [videoUrl, setVideoUrl] = useState(null)
// const [feedData, setFeedData] = useState([])
useEffect(() => { const { data: feedData, loading } = useFetch(`${config.calendar}`)
const getData = async () => {
const { data } = await axios.get(
`${config.peertube_root}/api/v1/videos/${config.next_stream.peertube_id}`
)
console.log(data)
const src = `${config.peertube_root}${data.embedPath}`
console.log('src', src)
setVideoUrl(src)
}
getData()
}, [])
return ( return (
<div> <div>
{videoUrl ? ( {/* {false ? (
<Video playing={isPlaying} setPlaying={setIsPlaying} src={videoUrl} /> <Video
) : ( playing={isPlaying}
<Info /> setPlaying={setIsPlaying}
)} src={videoUrl}
title={config.next_stream.title}
org={config.next_stream.org}
/>
) : ( */}
{loading ? <P>LOADING :)</P> : <Info data={feedData} />}
</div> </div>
) )
} }

View File

@ -1,6 +1,6 @@
import { h, render } from 'preact' import { h, render } from 'preact'
import App from './app' import App from './app'
const AppEl = document.getElementById('app') const appEl = document.getElementById('app')
render(<App />, AppEl) render(<App />, appEl)

View File

@ -21,6 +21,7 @@
"styled-components": "^5.2.1" "styled-components": "^5.2.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/eslint-parser": "^7.13.10",
"babel": "^6.23.0", "babel": "^6.23.0",
"babel-plugin-transform-react-jsx": "^6.24.1", "babel-plugin-transform-react-jsx": "^6.24.1",
"babel-preset-env": "^1.6.1", "babel-preset-env": "^1.6.1",

View File

@ -0,0 +1,23 @@
import { useEffect, useState } from 'preact/hooks'
import axios from 'axios'
export const useFetch = url => {
const [data, setData] = useState(null)
const [loading, setLoading] = useState(true)
async function fetchData() {
setLoading(true)
const { data: responseData } = await axios.get(url)
console.log('url', url)
console.log('responseData', responseData)
setData(responseData)
setLoading(false)
}
useEffect(() => {
fetchData()
}, [])
return { loading, data }
}

View File

@ -1,14 +1,20 @@
export const colours = { export const colours = {
midnight: '#233b4a', midnight: '#233b4a',
midnightDarker: '#112B39',
offwhite: '#f6f4f5', offwhite: '#f6f4f5',
white: '#fff', white: '#fff',
highlight: '#03a59e', highlight: '#03a59e',
rose: '#FEB9B3', roseDarker: '#FEB9B3',
rose: '#F1CFCD',
} }
colours.text = colours.offwhite colours.text = colours.offwhite
export const ui = {
borderRadius: 4,
}
export const textSizes = { export const textSizes = {
xs: 11, xs: 11,
sm: 14, sm: 14,
@ -22,4 +28,5 @@ export const textSizes = {
export default { export default {
colours, colours,
textSizes, textSizes,
ui,
} }

View File

@ -1,9 +1,10 @@
import styled from 'styled-components' import styled from 'styled-components'
import { colours } from '../../assets/theme' import { colours, ui } from '../../assets/theme'
export const ChatWrapper = styled.div` export const ChatWrapper = styled.div`
position: fixed; position: fixed;
z-index: 10; z-index: 10;
bottom: 0; bottom: 0;
right: 32px; right: 32px;
border-radius: ${ui.borderRadius}px;
` `

View File

@ -1,18 +1,42 @@
import { h } from 'preact' import { h } from 'preact'
import { useEffect, useRef, useState } from 'preact/hooks' import { useEffect, useRef, useState } from 'preact/hooks'
import Logo from '../Logo' import { H1, H2, P } from '../Text'
import { H1, P } from '../Text' import {
import { Wrapper } from './styles' Wrapper,
PositionedLogo as Logo,
TaglineContainer,
Top,
} from './styles'
import translations from '../../data/strings'
import InfoLayout from '../InfoLayout'
const allowedChannels = [7, 4] // ReclaimFutures, NDC
const Info = ({ data }) => { const Info = ({ data }) => {
// const [feed, setFeed] = useState([])
// useEffect(() => {
// setFeed(sortData(data))
// }, [data])
useEffect(() => {
console.log({ data })
}, [data])
return ( return (
<Wrapper> <InfoLayout title={translations.en.noStreams}>
<Logo active /> <P>ding dong</P>
<H1>Next Stream</H1> </InfoLayout>
<P>dsdas</P>
</Wrapper>
) )
} }
const sortData = data => {
// if (!data || data?.length === 0) return
// console.log('data', data)
// return data.filter(feedItem => {
// return allowedChannels.includes(feedItem.channel.id) && feedItem.isLive
// })
}
export default Info export default Info

View File

@ -1,9 +1,38 @@
import styled from 'styled-components' import styled from 'styled-components'
import { colours } from '../../assets/theme' import { colours } from '../../assets/theme'
import Logo from '../Logo'
export const Wrapper = styled.div` export const Wrapper = styled.div`
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
padding: 2em;
display: flex;
justify-content: space-between;
flex-direction: column;
background-color: ${colours.rose}; background: url(https://images.unsplash.com/photo-1579762715118-a6f1d4b934f1?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=3031&q=80)
${colours.rose};
box-sizing: border-box;
background-size: cover;
background-position-y: 50%;
background-position-x: 20vw;
background-blend-mode: soft-light;
p,
h1,
h2 {
color: ${colours.midnightDarker};
}
`
export const Top = styled.div``
export const PositionedLogo = styled(Logo)`
margin-bottom: 64px;
`
export const TaglineContainer = styled.div`
h1 {
margin-top: 32px;
}
` `

View File

@ -0,0 +1,34 @@
import { h } from 'preact'
import { useEffect, useRef, useState } from 'preact/hooks'
import { H1, H2, P } from '../Text'
import {
Wrapper,
PositionedLogo as Logo,
TaglineContainer,
Top,
Content,
} from './styles'
import translations from '../../data/strings'
import { colours } from '../../assets/theme'
const InfoLayout = ({ title, children }) => {
return (
<Wrapper>
<Logo active colour={colours.midnightDarker} />
<Content>
<H2>{title}</H2>
{children}
</Content>
<TaglineContainer>
{translations &&
translations.en.underscoreTagline.map(line => (
<H1 key={line}>{line}</H1>
))}
</TaglineContainer>
</Wrapper>
)
}
export default InfoLayout

View File

@ -0,0 +1,54 @@
import styled from 'styled-components'
import { colours } from '../../assets/theme'
import Logo from '../Logo'
export const Wrapper = styled.div`
height: 100vh;
width: 100vw;
padding: 6em 2em 2em 2em;
display: flex;
/* justify-content: space-between; */
/* flex-direction: column; */
background: url(https://images.unsplash.com/photo-1579762715118-a6f1d4b934f1?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=3031&q=80)
${colours.rose};
box-sizing: border-box;
background-size: cover;
background-position-y: 50%;
background-position-x: 23vw;
background-blend-mode: soft-light;
position: fixed;
overflow-y: scroll;
p,
h1,
h2 {
color: ${colours.midnightDarker};
}
@media screen and (max-width: 1200px) {
padding: 6em 1.5em 1.5em 1.5em;
background-size: 150%;
background-position-x: 0vw;
}
@media screen and (max-width: 800px) {
padding: 6em 1em 1em 1em;
background-size: 250%;
background-position-x: -50vw;
}
`
export const Top = styled.div`
width: 50%;
`
export const Content = styled.div``
export const PositionedLogo = styled(Logo)`
position: fixed;
top: 2em;
`
export const TaglineContainer = styled.div`
position: fixed;
bottom: 2em;
`

View File

@ -1,14 +1,15 @@
import { h } from 'preact' import { h } from 'preact'
import { bool, string } from 'prop-types' import { bool, string } from 'prop-types'
import styled, { css } from 'styled-components' import styled from 'styled-components'
import { colours } from '../../assets/theme' import { colours } from '../../assets/theme'
const Logo = ({ colour = colours.offwhite, active }) => ( const Logo = ({ colour = colours.offwhite, active, ...rest }) => (
<LogoSvg <LogoSvg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
fill="none" fill="none"
viewBox="0 0 865 140" viewBox="0 0 865 140"
$active={active} $active={active}
{...rest}
> >
<path <path
fill={colour} fill={colour}
@ -19,18 +20,6 @@ const Logo = ({ colour = colours.offwhite, active }) => (
const LogoSvg = styled.svg` const LogoSvg = styled.svg`
width: 200px; width: 200px;
padding: 1em;
transform: translateY(-20%);
transition: all 0.2s ease-in-out;
opacity: 0;
pointer-events: none;
${props =>
props.$active &&
css`
transform: translateY(0%);
opacity: 1;
`}
` `
Logo.propTypes = { Logo.propTypes = {

View File

@ -62,16 +62,29 @@ Text.propTypes = {
} }
export const H1 = ({ children, ...rest }) => { export const H1 = ({ children, ...rest }) => {
console.log({ children })
return ( return (
<Text tag="h1" weight="700" size="48" fontFamily="Lunchtype24" {...rest}> <Text
tag="h1"
weight="700"
size="48"
lineHeight="0.8"
fontFamily="Lunchtype24"
{...rest}
>
{children} {children}
</Text> </Text>
) )
} }
export const H2 = ({ children, ...rest }) => ( export const H2 = ({ children, ...rest }) => (
<Text tag="h2" weight="700" size="25" fontFamily="Lunchtype24" {...rest}> <Text
tag="h2"
weight="700"
size="25"
lineHeight="1"
fontFamily="Lunchtype24"
{...rest}
>
{children} {children}
</Text> </Text>
) )

View File

@ -1,4 +1,5 @@
import styled, { css } from 'styled-components' import styled, { css } from 'styled-components'
import { colours } from '../../assets/theme'
export const TextBase = styled.span` export const TextBase = styled.span`
${({ ${({
@ -21,5 +22,10 @@ export const TextBase = styled.span`
user-select: ${selectable ? 'inherit' : 'none'}; user-select: ${selectable ? 'inherit' : 'none'};
text-decoration: ${underline ? 'underline' : 'none'}; text-decoration: ${underline ? 'underline' : 'none'};
font-size: ${size}px; font-size: ${size}px;
::selection {
background-color: ${colours.midnightDarker};
color: ${colours.offwhite};
}
`} `}
` `

View File

@ -1,13 +1,16 @@
import { h } from 'preact' import { h } from 'preact'
import { useEffect, useRef, useState } from 'preact/hooks' import { useEffect, useRef, useState } from 'preact/hooks'
import { bool, func, string } from 'prop-types'
import 'regenerator-runtime/runtime' import 'regenerator-runtime/runtime'
import { PeerTubePlayer } from '@peertube/embed-api' import { PeerTubePlayer } from '@peertube/embed-api'
import Logo from '../Logo' import Logo from '../Logo'
import Chat from '../Chat' import Chat from '../Chat'
import { VideoWrapper, Iframe, Overlay } from './styles' import { H2 } from '../Text'
import Overlay from '../VideoOverlay'
import { VideoWrapper, Iframe } from './styles'
const Video = ({ playing, setPlaying, src }) => { const Video = ({ playing, setPlaying, src, title, org }) => {
const videoiFrame = useRef(null) const videoiFrame = useRef(null)
const overlayTimeout = useRef(null) const overlayTimeout = useRef(null)
const [videoReady, setVideoReady] = useState(false) const [videoReady, setVideoReady] = useState(false)
@ -56,9 +59,7 @@ const Video = ({ playing, setPlaying, src }) => {
onClick={() => setPlaying(!playing)} onClick={() => setPlaying(!playing)}
onMouseMove={activateOverlay} onMouseMove={activateOverlay}
> >
<Overlay> <Overlay active={overlayActive || !playing} title={title} org={org} />
<Logo active={overlayActive || !playing}></Logo>
</Overlay>
<Iframe <Iframe
sandbox="allow-same-origin allow-scripts allow-popups" sandbox="allow-same-origin allow-scripts allow-popups"
src={`${src}?api=1&controls=false`} src={`${src}?api=1&controls=false`}
@ -66,9 +67,17 @@ const Video = ({ playing, setPlaying, src }) => {
allowfullscreen allowfullscreen
ref={videoiFrame} ref={videoiFrame}
/> />
<Chat></Chat> <Chat />
</VideoWrapper> </VideoWrapper>
) )
} }
Video.propTypes = {
playing: bool,
setPlaying: func.isRequired,
src: string.isRequired,
title: string.isRequired,
org: string,
}
export default Video export default Video

View File

@ -0,0 +1,34 @@
import { h } from 'preact'
import { bool, string } from 'prop-types'
import Logo from '../Logo'
import { P } from '../Text'
import { OverlayWrapper, TopLeft } from './styles'
const VideoOverlay = ({ active, title, org }) => {
const displayTitle = `${title}${org ? `${org}` : ''}`
return (
<OverlayWrapper>
<TopLeft $active={active}>
<Logo active={active} />
<P
size={18}
css={`
margin-top: 16px;
`}
>
{displayTitle}
</P>
</TopLeft>
</OverlayWrapper>
)
}
VideoOverlay.propTypes = {
active: bool,
title: string.isRequired,
org: string,
}
export default VideoOverlay

View File

@ -0,0 +1,21 @@
import styled, { css } from 'styled-components'
export const OverlayWrapper = styled.div`
z-index: 2;
position: fixed;
height: 100vh;
width: 100vw;
pointer-events: none;
`
export const TopLeft = styled.div`
opacity: 0;
transform: translateY(-20%);
transition: all 0.2s ease-in-out;
padding: 2em;
${props =>
props.$active &&
css`
transform: translateY(0%);
opacity: 1;
`};
`

View File

@ -1,9 +0,0 @@
{
"peertube_root": "https://tv.undersco.re",
"next_stream": {
"title": "Femboy Photoshoot",
"peertube_id": "5c457282-e8d0-4464-9c07-cb6bb71d7153",
"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"
}
}

14
src/data/config.js Normal file
View File

@ -0,0 +1,14 @@
export default {
peertube_root: 'https://tv.undersco.re',
calendar:
'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

@ -1,5 +1,7 @@
export default { export default {
en: { en: {
nextStream: 'Next stream:', nextStream: 'Next stream',
noStreams: 'No upcoming streams, check back soon.',
underscoreTagline: ['LEAVE THE', 'SURVEILLANCE ECONOMY', '— TOGETHER.'],
}, },
} }

View File

@ -41,6 +41,15 @@
semver "^5.4.1" semver "^5.4.1"
source-map "^0.5.0" source-map "^0.5.0"
"@babel/eslint-parser@^7.13.10":
version "7.13.10"
resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.13.10.tgz#e272979914f36bb6cea144c14c32bb51632696dd"
integrity sha512-/I1HQ3jGPhIpeBFeI3wO9WwWOnBYpuR0pX0KlkdGcRQAVX9prB/FCS2HBpL7BiFbzhny1YCiBH8MTZD2jJa7Hg==
dependencies:
eslint-scope "5.1.0"
eslint-visitor-keys "^1.3.0"
semver "^6.3.0"
"@babel/generator@^7.0.0 <7.4.0": "@babel/generator@^7.0.0 <7.4.0":
version "7.3.4" version "7.3.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e"
@ -2940,6 +2949,14 @@ eslint-restricted-globals@^0.1.1:
resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7" resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7"
integrity sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc= integrity sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=
eslint-scope@5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5"
integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==
dependencies:
esrecurse "^4.1.0"
estraverse "^4.1.1"
eslint-scope@^3.7.1: eslint-scope@^3.7.1:
version "3.7.3" version "3.7.3"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535"
@ -2948,7 +2965,7 @@ eslint-scope@^3.7.1:
esrecurse "^4.1.0" esrecurse "^4.1.0"
estraverse "^4.1.1" estraverse "^4.1.1"
eslint-visitor-keys@^1.0.0: eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.3.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==