bunch of styling
This commit is contained in:
parent
d4a07710ba
commit
aa7ffc900b
88
app.js
88
app.js
@ -1,26 +1,21 @@
|
||||
import { h } from 'preact'
|
||||
import { useState, useEffect } from 'preact/hooks'
|
||||
import 'regenerator-runtime/runtime'
|
||||
import axios from 'axios'
|
||||
import { isWithinInterval, subHours } from 'date-fns'
|
||||
import { addHours } from 'date-fns/esm'
|
||||
|
||||
import Video from './src/components/Video'
|
||||
import config from './src/data/config'
|
||||
import Info from './src/components/Info'
|
||||
import { useCalendar } from './src/hooks/data'
|
||||
import { useEventStream } from './src/hooks/data'
|
||||
import { useTimeout } from './src/hooks/timerHooks'
|
||||
|
||||
// const appStates = [
|
||||
// 'noStream',
|
||||
// 'streamLive',
|
||||
// 'streamFinished'
|
||||
// ]
|
||||
|
||||
export default () => {
|
||||
const [isPlaying, setIsPlaying] = useState(false)
|
||||
const [videoUrl, setVideoUrl] = useState(null)
|
||||
const [feedData, setFeedData] = useState([])
|
||||
const [currentVideo, setCurrentVideo] = useState(null)
|
||||
const [streamIsLive, setStreamLive] = useState(false)
|
||||
const [infoActive, setInfoActive] = useState(false)
|
||||
const [minLoadTimePassed, setMinTimeUp] = useState(false)
|
||||
const { data, loading } = useCalendar()
|
||||
const { data, loading } = useEventStream()
|
||||
|
||||
useTimeout(() => {
|
||||
setMinTimeUp(true)
|
||||
@ -28,40 +23,26 @@ export default () => {
|
||||
|
||||
useEffect(() => {
|
||||
if (data && data.length) {
|
||||
data.forEach(async (calItem, index) => {
|
||||
if (calItem.url) {
|
||||
const id = calItem.url.val.split('/').pop()
|
||||
|
||||
const {
|
||||
data: {
|
||||
account,
|
||||
category,
|
||||
channel,
|
||||
embedPath,
|
||||
language,
|
||||
name,
|
||||
state,
|
||||
previewPath,
|
||||
views,
|
||||
},
|
||||
} = await axios.get(`https://tv.undersco.re/api/v1/videos/${id}`)
|
||||
|
||||
const item = {
|
||||
name,
|
||||
account,
|
||||
category,
|
||||
channel,
|
||||
description: calItem.description,
|
||||
embedPath,
|
||||
language,
|
||||
state,
|
||||
previewPath,
|
||||
views,
|
||||
start: calItem.start,
|
||||
end: calItem.end,
|
||||
id,
|
||||
data.forEach((stream, index) => {
|
||||
// if (stream.title === 'A Wider Screen') {
|
||||
if (index === 0) {
|
||||
setCurrentVideo(stream)
|
||||
}
|
||||
setFeedData(arr => [...arr, item])
|
||||
if (
|
||||
isWithinInterval(new Date(), {
|
||||
start: subHours(stream.start, 1),
|
||||
end: addHours(stream.end, 1),
|
||||
})
|
||||
) {
|
||||
setCurrentVideo(stream)
|
||||
}
|
||||
if (
|
||||
isWithinInterval(new Date(), {
|
||||
start: stream.start,
|
||||
end: stream.end,
|
||||
})
|
||||
) {
|
||||
setStreamLive(`${config.peertube_root}${stream.embedPath}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -69,16 +50,23 @@ export default () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
{false ? (
|
||||
{currentVideo && !infoActive && minLoadTimePassed ? (
|
||||
<Video
|
||||
playing={isPlaying}
|
||||
setPlaying={setIsPlaying}
|
||||
src={videoUrl}
|
||||
title={config.next_stream.title}
|
||||
org={config.next_stream.org}
|
||||
src={`${config.peertube_root}${currentVideo.embedPath}`}
|
||||
title={currentVideo.title}
|
||||
org={currentVideo.channel.displayName}
|
||||
setInfoActive={setInfoActive}
|
||||
/>
|
||||
) : (
|
||||
<Info data={feedData} loading={loading || !minLoadTimePassed} />
|
||||
<Info
|
||||
data={data}
|
||||
loading={loading || !minLoadTimePassed}
|
||||
infoActive={infoActive}
|
||||
currentVideo={currentVideo}
|
||||
setInfoActive={setInfoActive}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
BIN
src/assets/img/IconSM.png
Normal file
BIN
src/assets/img/IconSM.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
@ -3,7 +3,7 @@ export const colours = {
|
||||
midnightDarker: '#112B39',
|
||||
offwhite: '#f6f4f5',
|
||||
|
||||
white: '#fff',
|
||||
white: '#ffffff',
|
||||
highlight: '#03a59e',
|
||||
roseDarker: '#FEB9B3',
|
||||
rose: '#F1CFCD',
|
||||
|
@ -1,19 +1,40 @@
|
||||
import { h } from 'preact'
|
||||
import { useEffect, useRef, useState } from 'preact/hooks'
|
||||
import { useWindowDimensions } from '../../hooks/dom'
|
||||
import { useToggle } from '../../hooks/utility'
|
||||
|
||||
import { ChatWrapper } from './styles'
|
||||
import { Label } from '../Text'
|
||||
import { ChatFrame, ChatWrapper, ChatHeader, CloseBox } from './styles'
|
||||
import { colours } from '../../assets/theme'
|
||||
|
||||
const Chat = ({}) => {
|
||||
return (
|
||||
const { width, height } = useWindowDimensions()
|
||||
const [chatIsOpen, toggleChatOpen] = useToggle(true)
|
||||
return chatIsOpen ? (
|
||||
<ChatWrapper>
|
||||
<ChatFrame>
|
||||
<ChatHeader chatIsOpen>
|
||||
<Label weight="400" size={24}>
|
||||
Chat
|
||||
</Label>
|
||||
<CloseBox colour={colours.white} size={18} onClick={toggleChatOpen} />
|
||||
</ChatHeader>
|
||||
<iframe
|
||||
src="https://titanembeds.com/embed/803918964082212905?css=215&defaultchannel=817134294199566356&lang=en_EN"
|
||||
height="500"
|
||||
height={(height / 4) * 3}
|
||||
width="350"
|
||||
frameBorder="0"
|
||||
title="discord-chat"
|
||||
class="titanembed"
|
||||
className="titanembed"
|
||||
/>
|
||||
</ChatFrame>
|
||||
</ChatWrapper>
|
||||
) : (
|
||||
<ChatHeader chatIsOpen={false} onClick={toggleChatOpen}>
|
||||
<Label weight="400" size={24}>
|
||||
Chat
|
||||
</Label>
|
||||
</ChatHeader>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,55 @@
|
||||
import styled from 'styled-components'
|
||||
import { colours, ui } from '../../assets/theme'
|
||||
import CrossSvg from '../Svg/Cross'
|
||||
import { Label } from '../Text'
|
||||
|
||||
export const ChatFrame = styled.div`
|
||||
/* border: 2px solid ${colours.white}; */
|
||||
/* padding: 20px; */
|
||||
`
|
||||
|
||||
export const ChatWrapper = styled.div`
|
||||
position: fixed;
|
||||
z-index: 10;
|
||||
bottom: 0;
|
||||
right: 32px;
|
||||
bottom: -5px;
|
||||
right: 0;
|
||||
backdrop-filter: blur(20px);
|
||||
background-color: ${colours.midnight}40;
|
||||
/* padding: 20px; */
|
||||
border-radius: ${ui.borderRadius}px;
|
||||
`
|
||||
|
||||
export const ChatHeader = styled.div`
|
||||
position: absolute;
|
||||
bottom: ${props => (props.chatIsOpen ? 'initial' : 0)};
|
||||
top: ${props => (props.chatIsOpen ? '4px' : 'initial')};
|
||||
/* cursor: ${props => (props.dragging ? 'grabbing' : 'grab')}; */
|
||||
border-radius: ${ui.borderRadius}px 0 0 0;
|
||||
|
||||
|
||||
height: 32px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: ${props => (props.chatIsOpen ? '100%' : 'fit-content')};
|
||||
|
||||
justify-content: space-between;
|
||||
padding: 0px 0px 3px 0px;
|
||||
right: 0;
|
||||
box-sizing: content-box;
|
||||
border: ${props =>
|
||||
props.chatIsOpen ? 'none' : `1px solid ${colours.white}`};
|
||||
border-bottom: ${props =>
|
||||
props.chatIsOpen ? `1px solid ${colours.white}75` : 'none'};
|
||||
border-right: none;
|
||||
|
||||
label {
|
||||
margin-left: 12px;
|
||||
margin-right: ${props => (props.chatIsOpen ? '0' : '12px')}
|
||||
}
|
||||
`
|
||||
|
||||
export const CloseBox = styled(CrossSvg)`
|
||||
padding: 12px;
|
||||
cursor: pointer;
|
||||
`
|
||||
|
@ -1,39 +1,55 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import { h, Fragment } from 'preact'
|
||||
import { useEffect, useRef, useState } from 'preact/hooks'
|
||||
import { isBefore } from 'date-fns'
|
||||
import { isFuture, isPast } from 'date-fns'
|
||||
|
||||
import { P } from '../Text'
|
||||
import translations from '../../data/strings'
|
||||
import InfoLayout from '../InfoLayout'
|
||||
import { VideoCard, Title, InfoContent } from './styles'
|
||||
import {
|
||||
VideoCard,
|
||||
Title,
|
||||
InfoContent,
|
||||
PositionedCross as CrossSvg,
|
||||
} from './styles'
|
||||
|
||||
const Info = ({ data, loading }) => {
|
||||
const now = new Date()
|
||||
const Info = ({ data, loading, infoActive, setInfoActive, currentVideo }) => {
|
||||
const pastStreams =
|
||||
data && data.length
|
||||
? data.filter(feeditem => isBefore(new Date(feeditem.end), now))
|
||||
? data.filter(feeditem => isPast(new Date(feeditem.end)))
|
||||
: []
|
||||
|
||||
const futureStreams =
|
||||
data && data.length
|
||||
? data.filter(feeditem => isBefore(now, new Date(feeditem.start)))
|
||||
? data.filter(
|
||||
feeditem =>
|
||||
feeditem.id !== (currentVideo && currentVideo.id) &&
|
||||
isFuture(new Date(feeditem.start))
|
||||
)
|
||||
: []
|
||||
|
||||
console.log({ currentVideo })
|
||||
|
||||
return (
|
||||
<InfoLayout
|
||||
title={
|
||||
data && data.length
|
||||
? `${translations.en.nextStream}:`
|
||||
: translations.en.noStreams
|
||||
}
|
||||
loading={loading}
|
||||
>
|
||||
<InfoLayout loading={loading}>
|
||||
{infoActive && <CrossSvg onClick={() => setInfoActive(false)} />}
|
||||
{!loading && (
|
||||
<InfoContent>
|
||||
{currentVideo && (
|
||||
<Fragment>
|
||||
<Title>{translations.en.nowPlaying}:</Title>
|
||||
<VideoCard {...currentVideo} />
|
||||
</Fragment>
|
||||
)}
|
||||
|
||||
{futureStreams.length && (
|
||||
<Fragment>
|
||||
<Title>{translations.en.nextStream}:</Title>
|
||||
{futureStreams.map(feeditem => (
|
||||
<VideoCard key={feeditem.start} {...feeditem} />
|
||||
))}
|
||||
</Fragment>
|
||||
)}
|
||||
|
||||
{pastStreams.length ? (
|
||||
<Fragment>
|
||||
<Title>{translations.en.pastStream}:</Title>
|
||||
|
@ -5,8 +5,11 @@ import { colours } from '../../assets/theme'
|
||||
import config from '../../data/config'
|
||||
import Logo from '../Logo'
|
||||
import translations from '../../data/strings'
|
||||
import CrossSvg from '../Svg/Cross'
|
||||
|
||||
import { P, H1, H2, Span, Label } from '../Text'
|
||||
import Link from '../Link'
|
||||
import { bool, instanceOf, string } from 'prop-types'
|
||||
|
||||
export const Wrapper = styled.div`
|
||||
height: 100vh;
|
||||
@ -51,10 +54,24 @@ export const Title = styled(H1)`
|
||||
margin: 0.3em 0;
|
||||
`
|
||||
|
||||
export const PositionedCross = styled(CrossSvg)`
|
||||
position: fixed;
|
||||
right: 2.5em;
|
||||
top: 2em;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
cursor: pointer;
|
||||
stroke: ${colours.midnightDarker};
|
||||
|
||||
&:hover {
|
||||
opacity: 0.5;
|
||||
}
|
||||
`
|
||||
|
||||
const VCWrapper = styled.div`
|
||||
max-width: 600px;
|
||||
margin-bottom: 3em;
|
||||
border-left: 7px solid ${colours.midnightDarker};
|
||||
margin: 0 0 6em 2px;
|
||||
border-left: 5px solid ${colours.midnightDarker};
|
||||
padding-left: 1em;
|
||||
`
|
||||
|
||||
@ -71,18 +88,32 @@ const DateLabel = styled(Label)`
|
||||
display: block;
|
||||
`
|
||||
|
||||
const LinkBlock = styled(Link)`
|
||||
display: block;
|
||||
width: 100%;
|
||||
`
|
||||
|
||||
export const VideoCard = ({
|
||||
name,
|
||||
title,
|
||||
description,
|
||||
start,
|
||||
end,
|
||||
previewPath,
|
||||
hasPassed,
|
||||
}) => {
|
||||
return (
|
||||
videoUrl,
|
||||
}) => (
|
||||
<VCWrapper>
|
||||
<ItemTitle>{name}</ItemTitle>
|
||||
{videoUrl && hasPassed ? (
|
||||
<LinkBlock href={videoUrl}>
|
||||
<ItemTitle>{title}</ItemTitle>
|
||||
<VCImg src={`${config.peertube_root}${previewPath}`} alt="" />
|
||||
</LinkBlock>
|
||||
) : (
|
||||
<Fragment>
|
||||
<ItemTitle>{title}</ItemTitle>
|
||||
<VCImg src={`${config.peertube_root}${previewPath}`} alt="" />
|
||||
</Fragment>
|
||||
)}
|
||||
<DateLabel colour={colours.midnight} size="18">
|
||||
{`${
|
||||
hasPassed
|
||||
@ -96,4 +127,13 @@ export const VideoCard = ({
|
||||
<P>{description}</P>
|
||||
</VCWrapper>
|
||||
)
|
||||
|
||||
VideoCard.propTypes = {
|
||||
title: string,
|
||||
description: string,
|
||||
start: instanceOf(Date),
|
||||
end: instanceOf(Date),
|
||||
previewPath: string,
|
||||
hasPassed: bool,
|
||||
videoUrl: string,
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
Wrapper,
|
||||
PositionedLogo as Logo,
|
||||
TaglineContainer,
|
||||
Title,
|
||||
LoaderWrapper,
|
||||
Content,
|
||||
Fade,
|
||||
} from './styles'
|
||||
@ -16,7 +16,7 @@ import { colours } from '../../assets/theme'
|
||||
import Loader from '../Loader'
|
||||
import { useTimeout } from '../../hooks/timerHooks'
|
||||
|
||||
const InfoLayout = ({ title, children, loading }) => {
|
||||
const InfoLayout = ({ children, loading }) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
<Fade>
|
||||
@ -24,13 +24,12 @@ const InfoLayout = ({ title, children, loading }) => {
|
||||
</Fade>
|
||||
<Content>
|
||||
{loading ? (
|
||||
<div>
|
||||
<LoaderWrapper>
|
||||
<Loader />
|
||||
</div>
|
||||
</LoaderWrapper>
|
||||
) : (
|
||||
<Title>{title}</Title>
|
||||
children
|
||||
)}
|
||||
{children}
|
||||
</Content>
|
||||
|
||||
<TaglineContainer>
|
||||
@ -46,7 +45,6 @@ const InfoLayout = ({ title, children, loading }) => {
|
||||
}
|
||||
|
||||
InfoLayout.propTypes = {
|
||||
title: string,
|
||||
loading: bool,
|
||||
}
|
||||
|
||||
|
@ -59,8 +59,14 @@ export const Fade = styled.div`
|
||||
left: 0;
|
||||
background: ${getGradient('bottom')};
|
||||
`
|
||||
export const Title = styled(H1)`
|
||||
margin: 0.5em 0;
|
||||
export const LoaderWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 50vw;
|
||||
`
|
||||
|
||||
export const Content = styled.div`
|
||||
|
6
src/components/Link/index.js
Normal file
6
src/components/Link/index.js
Normal file
@ -0,0 +1,6 @@
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const Link = styled.a`
|
||||
text-decoration: none;
|
||||
`
|
||||
export default Link
|
16
src/components/Svg/Cross.js
Normal file
16
src/components/Svg/Cross.js
Normal file
@ -0,0 +1,16 @@
|
||||
import { h } from 'preact'
|
||||
import { bool, string } from 'prop-types'
|
||||
|
||||
const Cross = ({ colour = 'inherit', size, ...rest }) => (
|
||||
<svg viewBox="0 0 100 100" height={size} {...rest}>
|
||||
<path
|
||||
stroke={colour}
|
||||
strokeLinecap="none"
|
||||
strokeLinejoin="none"
|
||||
strokeWidth="18"
|
||||
d="M11.354 11.757l77.637 77.636m-77.627 0L89 11.757"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
|
||||
export default Cross
|
@ -4,16 +4,18 @@ import { bool, func, string } from 'prop-types'
|
||||
import 'regenerator-runtime/runtime'
|
||||
import { PeerTubePlayer } from '@peertube/embed-api'
|
||||
|
||||
import Logo from '../Logo'
|
||||
import Chat from '../Chat'
|
||||
import { H2 } from '../Text'
|
||||
import Overlay from '../VideoOverlay'
|
||||
import { useToggle } from '../../hooks/utility'
|
||||
import { VideoWrapper, Iframe } from './styles'
|
||||
|
||||
const Video = ({ playing, setPlaying, src, title, org }) => {
|
||||
const Video = ({ playing, setPlaying, src, title, org, setInfoActive }) => {
|
||||
const videoiFrame = useRef(null)
|
||||
const overlayTimeout = useRef(null)
|
||||
const videoWrapperEl = useRef(null)
|
||||
const [videoReady, setVideoReady] = useState(false)
|
||||
// const [isFullscreen, toggleFullscreen] = useToggle(false)
|
||||
// const [chatActive, setChatActive] = useState(false)
|
||||
const [overlayActive, setOverlayActiveState] = useState(true)
|
||||
const ptVideo = useRef(null)
|
||||
|
||||
@ -43,6 +45,37 @@ const Video = ({ playing, setPlaying, src, title, org }) => {
|
||||
}
|
||||
}, [playing])
|
||||
|
||||
const goFullscreen = () => {
|
||||
// toggleFullscreen()
|
||||
}
|
||||
|
||||
const exitFullscreen = () => {
|
||||
// toggleFullscreen()
|
||||
}
|
||||
|
||||
const handleKeyPress = keyCode => {
|
||||
if (keyCode === 32) {
|
||||
setPlaying(!playing)
|
||||
}
|
||||
// if (keyCode === 70 && !isFullscreen) {
|
||||
// console.log('goFullscreen')
|
||||
// goFullscreen()
|
||||
// }
|
||||
// if (keyCode === 70 && isFullscreen) {
|
||||
// console.log('exitFullscreen')
|
||||
// exitFullscreen()
|
||||
// }
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('keydown', ({ keyCode }) => handleKeyPress(keyCode))
|
||||
|
||||
return () =>
|
||||
window.removeEventListener('keydown', ({ keyCode }) =>
|
||||
handleKeyPress(keyCode)
|
||||
)
|
||||
}, [])
|
||||
|
||||
const activateOverlay = () => {
|
||||
clearTimeout(overlayTimeout.current)
|
||||
setOverlayActiveState(true)
|
||||
@ -58,8 +91,14 @@ const Video = ({ playing, setPlaying, src, title, org }) => {
|
||||
$active={overlayActive || !playing}
|
||||
onClick={() => setPlaying(!playing)}
|
||||
onMouseMove={activateOverlay}
|
||||
// ref={videoWrapperEl}
|
||||
>
|
||||
<Overlay active={overlayActive || !playing} title={title} org={org} />
|
||||
<Overlay
|
||||
active={overlayActive || !playing}
|
||||
title={title}
|
||||
org={org}
|
||||
setInfoActive={setInfoActive}
|
||||
/>
|
||||
<Iframe
|
||||
sandbox="allow-same-origin allow-scripts allow-popups"
|
||||
src={`${src}?api=1&controls=false`}
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { h } from 'preact'
|
||||
import { Fragment, h } from 'preact'
|
||||
import { bool, string } from 'prop-types'
|
||||
|
||||
import Logo from '../Logo'
|
||||
import { P } from '../Text'
|
||||
import { OverlayWrapper, TopLeft } from './styles'
|
||||
import { H2, P } from '../Text'
|
||||
import { InfoButton, OverlayWrapper, TopLeft } from './styles'
|
||||
|
||||
const VideoOverlay = ({ active, title, org }) => {
|
||||
const displayTitle = `${title}${org ? ` — ${org}` : ''}`
|
||||
const VideoOverlay = ({ active, title, org, setInfoActive }) => (
|
||||
// const displayTitle = `${title}${org ? ` — ${org}` : ''}`
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<OverlayWrapper>
|
||||
<TopLeft $active={active}>
|
||||
<Logo active={active} />
|
||||
@ -18,12 +18,13 @@ const VideoOverlay = ({ active, title, org }) => {
|
||||
margin-top: 16px;
|
||||
`}
|
||||
>
|
||||
{displayTitle}
|
||||
{title}
|
||||
</P>
|
||||
</TopLeft>
|
||||
</OverlayWrapper>
|
||||
<InfoButton $active={active} onClick={() => setInfoActive(true)} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
VideoOverlay.propTypes = {
|
||||
active: bool,
|
||||
|
@ -1,4 +1,6 @@
|
||||
import styled, { css } from 'styled-components'
|
||||
import { colours } from '../../assets/theme'
|
||||
import burb from '../../assets/img/IconSM.png'
|
||||
|
||||
export const OverlayWrapper = styled.div`
|
||||
z-index: 2;
|
||||
@ -18,4 +20,39 @@ export const TopLeft = styled.div`
|
||||
transform: translateY(0%);
|
||||
opacity: 1;
|
||||
`};
|
||||
|
||||
p,
|
||||
svg {
|
||||
backdrop-filter: blur(20px);
|
||||
background-color: ${colours.midnight}40;
|
||||
padding: 4px 8px;
|
||||
display: inline-block;
|
||||
margin-right: 45%;
|
||||
border-radius: 5px;
|
||||
}
|
||||
`
|
||||
|
||||
export const InfoButton = styled.img.attrs(() => ({
|
||||
src: burb,
|
||||
}))`
|
||||
opacity: 0.001;
|
||||
transform: translateY(-20%);
|
||||
transition: all 0.2s ease-in-out;
|
||||
transition-delay: 0.2s;
|
||||
position: fixed;
|
||||
right: 2em;
|
||||
top: 2em;
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
z-index: 100;
|
||||
${props =>
|
||||
props.$active &&
|
||||
css`
|
||||
transform: translateY(0%);
|
||||
opacity: 1;
|
||||
`};
|
||||
|
||||
&:hover {
|
||||
filter: invert(1);
|
||||
}
|
||||
`
|
||||
|
@ -2,6 +2,7 @@ export default {
|
||||
en: {
|
||||
nextStream: 'Next streams',
|
||||
pastStream: 'Latest streams',
|
||||
nowPlaying: 'Now playing',
|
||||
noStreams: 'No upcoming streams, check back soon.',
|
||||
underscoreTagline: ['LEAVE THE', 'SURVEILLANCE ECONOMY', '— TOGETHER.'],
|
||||
streamDateFuture: 'Going live at: ',
|
||||
|
@ -1,20 +1,63 @@
|
||||
import { useEffect, useState } from 'preact/hooks'
|
||||
import { useEffect, useState, useRef } from 'preact/hooks'
|
||||
import axios from 'axios'
|
||||
import ical from 'ical'
|
||||
import config from '../data/config'
|
||||
|
||||
export const useCalendar = () => {
|
||||
const [data, setData] = useState(null)
|
||||
export const useEventStream = () => {
|
||||
const [data, setData] = useState([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
async function fetchData() {
|
||||
setLoading(true)
|
||||
|
||||
const { data: responseData } = await axios.get(`${config.calendar}`)
|
||||
const streamsData = Object.values(ical.parseICS(responseData))
|
||||
const calItems = Object.values(ical.parseICS(responseData))
|
||||
.filter(feedItem => feedItem.type === 'VEVENT')
|
||||
.sort((a, b) => new Date(a.start) - new Date(b.start))
|
||||
setData(streamsData)
|
||||
|
||||
await Promise.all(
|
||||
calItems.map(async calItem => {
|
||||
if (calItem.url) {
|
||||
const id = calItem.url.val.split('/').pop()
|
||||
const {
|
||||
data: {
|
||||
account,
|
||||
category,
|
||||
channel,
|
||||
embedPath,
|
||||
language,
|
||||
state,
|
||||
previewPath,
|
||||
views,
|
||||
duration,
|
||||
},
|
||||
data: nesd,
|
||||
} = await axios.get(`https://tv.undersco.re/api/v1/videos/${id}`)
|
||||
|
||||
console.log({ nesd })
|
||||
|
||||
const item = {
|
||||
title: calItem.summary,
|
||||
account,
|
||||
category,
|
||||
channel,
|
||||
description: calItem.description,
|
||||
embedPath,
|
||||
language,
|
||||
state,
|
||||
previewPath,
|
||||
views,
|
||||
start: calItem.start,
|
||||
end: calItem.end,
|
||||
id,
|
||||
duration,
|
||||
videoUrl: calItem?.url?.val,
|
||||
}
|
||||
setData(arr => [...arr, item])
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
@ -24,73 +67,3 @@ export const useCalendar = () => {
|
||||
|
||||
return { loading, data }
|
||||
}
|
||||
|
||||
// export const useCalendar = () => {
|
||||
// const [data, setData] = useState(null)
|
||||
// const [loading, setLoading] = useState(true)
|
||||
|
||||
// async function fetchData() {
|
||||
// setLoading(true)
|
||||
|
||||
// const { data: responseData } = await axios.get(`${config.calendar}`)
|
||||
// const streamsData = Object.values(ical.parseICS(responseData))
|
||||
// .filter(feedItem => feedItem.type === 'VEVENT')
|
||||
// .sort((a, b) => new Date(a.start) - new Date(b.start))
|
||||
// setData(streamsData)
|
||||
// setLoading(false)
|
||||
// }
|
||||
|
||||
// useEffect(() => {
|
||||
// fetchData()
|
||||
// }, [])
|
||||
|
||||
// return { loading, data }
|
||||
// }
|
||||
// useEffect(() => {
|
||||
// const feedPromise =
|
||||
// data &&
|
||||
// data.map(async feedItem => {
|
||||
// if (feedItem.url) {
|
||||
// const id = feedItem.url.val.split('/').pop()
|
||||
|
||||
// const {
|
||||
// data: {
|
||||
// account,
|
||||
// category,
|
||||
// channel,
|
||||
// description,
|
||||
// embedPath,
|
||||
// language,
|
||||
// name,
|
||||
// state,
|
||||
// previewPath,
|
||||
// views,
|
||||
// },
|
||||
// } = await axios.get(`https://tv.undersco.re/api/v1/videos/${id}`)
|
||||
|
||||
// const item = {
|
||||
// name,
|
||||
// account,
|
||||
// category,
|
||||
// channel,
|
||||
// description,
|
||||
// embedPath,
|
||||
// language,
|
||||
// state,
|
||||
// previewPath,
|
||||
// views,
|
||||
// start: feedItem.start,
|
||||
// end: feedItem.end,
|
||||
// }
|
||||
|
||||
// console.log(item)
|
||||
|
||||
// return item
|
||||
// }
|
||||
// return null
|
||||
// })
|
||||
|
||||
// feedPromise.then(result => {
|
||||
// console.log(result)
|
||||
// })
|
||||
// }, [data])
|
||||
|
37
src/hooks/dom.js
Normal file
37
src/hooks/dom.js
Normal file
@ -0,0 +1,37 @@
|
||||
import { useState, useEffect } from 'preact/hooks'
|
||||
|
||||
const getWidth = () =>
|
||||
window.innerWidth ||
|
||||
document.documentElement.clientWidth ||
|
||||
document.body.clientWidth
|
||||
|
||||
const getHeight = () =>
|
||||
window.innerHeight ||
|
||||
document.documentElement.clientHeight ||
|
||||
document.body.clientHeight
|
||||
|
||||
// save current window width in the state object
|
||||
export const useWindowDimensions = () => {
|
||||
const [width, setWidth] = useState(getWidth())
|
||||
const [height, setHeight] = useState(getHeight())
|
||||
|
||||
useEffect(() => {
|
||||
let timeoutId = null
|
||||
const resizeListener = () => {
|
||||
clearTimeout(timeoutId)
|
||||
timeoutId = setTimeout(() => {
|
||||
setWidth(getWidth())
|
||||
setHeight(getHeight())
|
||||
}, 50)
|
||||
}
|
||||
window.addEventListener('resize', resizeListener)
|
||||
|
||||
// clean up function
|
||||
return () => {
|
||||
// remove resize listener
|
||||
window.removeEventListener('resize', resizeListener)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return { width, height }
|
||||
}
|
9
src/hooks/utility.js
Normal file
9
src/hooks/utility.js
Normal file
@ -0,0 +1,9 @@
|
||||
import { useCallback, useState } from 'preact/hooks'
|
||||
|
||||
export const useToggle = (initialValue = false) => {
|
||||
const [value, setValue] = useState(initialValue)
|
||||
const toggle = useCallback(() => {
|
||||
setValue(v => !v)
|
||||
}, [])
|
||||
return [value, toggle]
|
||||
}
|
Loading…
Reference in New Issue
Block a user