Add Slack events to homepage

This commit is contained in:
Lachlan Campbell 2020-04-23 21:10:19 -04:00
parent f0b848b72a
commit d158c07038
4 changed files with 209 additions and 59 deletions

View file

@ -0,0 +1,117 @@
import React, { useState, useMemo, useRef, useEffect } from 'react'
import useWebSocket from 'react-use-websocket'
import { Box, Text, Spinner } from 'theme-ui'
import { take, sample } from 'lodash'
import { Slide } from 'react-reveal'
const types = {
user_typing: 'typing',
reaction_added: 'reaction',
unmarshalling_error: 'message',
message: 'message'
}
const emoji = ['🚀', '🥳', '😂', '💖', '👀']
const colors = ['red', 'orange', 'yellow', 'green', 'cyan', 'blue']
const Channel = ({ color, channel }) => (
<Text as="strong" color={color} children={channel} />
)
export default ({ sx, ...props }) => {
const didUnmount = useRef(false)
const [events, setEvents] = useState([])
const STATIC_OPTIONS = useMemo(
() => ({
shouldReconnect: () => !didUnmount.current,
reconnectInterval: 3000
}),
[]
)
const [sendEvent, lastEvent, readyState, getWebSocket] = useWebSocket(
'wss://streambot-hackclub.herokuapp.com/',
STATIC_OPTIONS
)
useEffect(() => {
let e = lastEvent?.data
if (e) {
try {
e = JSON.parse(e)
if (Object.keys(types).includes(e.type)) {
e.type = types[e.type]
e.color = sample(colors)
if (e.type === 'reaction') e.emoji = sample(emoji)
setEvents((prev) => [e, ...prev])
}
} catch (err) {
true
}
}
}, [lastEvent])
useEffect(() => {
return () => {
didUnmount.current = true
}
})
return (
<Box
as="ol"
sx={{
minHeight: '2em',
height: '100%',
maxHeight: ['12em', 'none'],
overflow: 'hidden',
listStyle: 'none',
lineHeight: 'heading',
pl: 0,
color: 'black',
fontSize: 2,
overflowY: 'auto',
position: 'relative',
':after': {
content: '""',
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
display: 'block',
height: '2em',
backgroundImage: (theme) =>
`linear-gradient(rgba(255,255,255,0), ${theme.colors.white})`
},
div: { mb: [1, 2] },
'circle:last-of-type': { animationDuration: '1s' },
...sx
}}
aria-hidden="true"
{...props}
>
{events.length === 0 && <Spinner color="cyan" />}
{take(events, 3).map(({ timestamp, type, emoji, ...channel }) => (
<Slide top duration={256} key={timestamp}>
<>
Someone{' '}
{type === 'message' && (
<>
sent a message in <Channel {...channel} />
</>
)}
{type === 'typing' && (
<>
is typing in <Channel {...channel} />
</>
)}
{type === 'reaction' && (
<>
in <Channel {...channel} /> reacted with {emoji}
</>
)}
</>
</Slide>
))}
</Box>
)
}

View file

@ -24,6 +24,7 @@
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-reveal": "^1.2.2",
"react-use-websocket": "^1.7.3",
"theme-ui": "^0.3.1"
}
}

View file

@ -17,6 +17,7 @@ import {
import { Slide } from 'react-reveal'
import JoinForm from '../components/JoinForm'
import ForceTheme from '../components/force-theme'
import SlackEvents from '../components/home/slack-events'
const CardLink = (props) => (
<Link
@ -196,11 +197,21 @@ export default () => (
</Grid>
</Box>
<Slide up>
<Card sx={{ p: [0, 0], lineHeight: 0 }}>
<Card
sx={{
p: [0, 0],
boxShadow: 'elevated',
lineHeight: 0,
border: '1px solid',
borderColor: 'black'
}}
>
<Box
sx={{
bg: 'muted',
backgroundImage: (theme) => `linear-gradient(#C0CCDA, #8492A6)`,
color: 'smoke',
backgroundImage: (theme) =>
`linear-gradient(${theme.colors.darkless}, ${theme.colors.darker})`,
p: 2,
lineHeight: 'body',
textAlign: 'center'
@ -211,7 +222,6 @@ export default () => (
<Box
as="video"
src="https://d2wkqk610zk1ag.cloudfront.net/items/0k222h2k1Z2h1S1y3t0u/chris-cox-ama.mov"
controls
muted
autoPlay
loop
@ -222,7 +232,7 @@ export default () => (
mt: '-2px'
}}
>
chris-cox-ama.mov
Clip from our Chris Cox AMA
</Box>
</Card>
</Slide>
@ -241,19 +251,33 @@ export default () => (
>
<Box
sx={{
position: 'relative',
backgroundColor: 'rgba(255,255,255,0.875)',
'@supports (-webkit-backdrop-filter: none) or (backdrop-filter: none)': {
backgroundColor: 'rgba(255,255,255,0.5)',
WebkitBackdropFilter: 'saturate(180%) brightness(90%) blur(20px)'
backdropFilter: 'blur(20px) saturate(180%)',
WebkitBackdropFilter: 'blur(20px) saturate(180%)'
},
':after': {
content: '""',
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
display: 'block',
height: 256,
backgroundImage: (theme) =>
`linear-gradient(rgba(255,255,255,0), ${theme.colors.white})`
},
py: [4, 5]
}}
>
<Container>
<Container sx={{ position: 'relative', zIndex: 2 }}>
<Heading
as="h2"
variant="title"
sx={{
color: 'white',
color: 'black',
maxWidth: 'copyUltra'
}}
>
@ -274,32 +298,56 @@ export default () => (
</Box>
<Box
as="section"
sx={{ bg: 'snow', color: 'black', position: 'relative', py: [4, 5] }}
sx={{ bg: 'white', color: 'black', position: 'relative', pb: [4, 5] }}
>
<Container>
<Heading
as="h2"
variant="title"
sx={{
fontSize: [4, 5],
color: 'red',
textTransform: 'uppercase',
letterSpacing: 'headline'
}}
>
Channels on our Slack
</Heading>
<Grid
columns={[null, 2]}
gap={[3, 4]}
columns={[2, 15]}
gap={3}
sx={{
py: [3, 4],
div: { color: 'white' },
h3: { my: 0 }
h3: { my: 0 },
'> div': {
px: [2, 3],
py: [4, 4],
display: 'flex',
flexDirection: 'column',
gridColumn: ['span 1', 'span 3'],
position: 'relative'
},
h3: {
variant: 'text.headline',
color: 'white',
lineHeight: 'title',
my: 0
}
}}
>
<Card
<Box
as="aside"
sx={{
gridRow: [null, 'span 2'],
gridColumn: ['span 2', 'span 3']
}}
>
<Heading
as="h2"
variant="headline"
sx={{
mt: 0,
color: 'red',
textTransform: 'uppercase',
letterSpacing: 'headline'
}}
>
Live from our&nbsp;Slack
</Heading>
<SlackEvents />
</Box>
<Card
as="aside"
sx={{
gridColumn: ['span 2', 'span 6'],
bg: 'blue',
backgroundImage: (theme) => `radial-gradient(
ellipse farthest-corner at top left, ${theme.colors.cyan}, ${theme.colors.blue})`
@ -308,59 +356,44 @@ export default () => (
<Heading as="h3" variant="headline">
#ship
</Heading>
<Text as="p" sx={{ color: 'smoke', fontSize: 2 }}>
<Text as="p" sx={{ color: 'smoke', fontSize: 2, mt: 1 }}>
Share your latest projects & get feedback
</Text>
</Card>
<Card
as="aside"
sx={{
gridColumn: ['span 2', 'span 6'],
bg: 'dark',
backgroundImage: (theme) => `radial-gradient(
ellipse farthest-corner at top left, ${theme.colors.darkless}, ${theme.colors.darker})`
backgroundImage: 'url(https://hackclub.com/photos/night.jpg)',
backgroundPosition: 'top center',
backgroundSize: 'cover'
}}
>
<Heading as="h3" variant="headline">
#hack-night
</Heading>
<Text as="p" sx={{ color: 'smoke', fontSize: 2 }}>
<Text as="p" sx={{ color: 'smoke', fontSize: 2, mt: 1 }}>
Biweekly mini-hackathon & video call hangout
</Text>
</Card>
</Grid>
<Grid
columns={[2, 3, 5]}
gap={3}
sx={{
'> div': {
px: [3, 3],
py: [4, 4],
minHeight: 12 * 16,
display: 'flex',
flexDirection: 'column',
// justifyContent: 'center',
position: 'relative'
},
h3: {
variant: 'text.headline',
color: 'white',
mt: 0
}
}}
>
<Card bg="cyan">
<h3>#lounge</h3>
</Card>
<Card bg="orange">
<h3>#support</h3>
</Card>
<Card bg="blue">
<h3>#code</h3>
</Card>
<Card bg="orange">
<h3>#support</h3>
<Card bg="red">
<h3>#lgbtq</h3>
</Card>
<Card bg="dark">
<h3>#gamedev</h3>
</Card>
<Card bg="red">
<h3>#lgbtq</h3>
<h3>#design</h3>
</Card>
<Card bg="green">
<h3>
@ -372,15 +405,9 @@ export default () => (
<Card bg="yellow">
<h3>#dogs</h3>
</Card>
<Card bg="red">
<h3>#design</h3>
</Card>
<Card bg="green">
<h3>#music</h3>
</Card>
<Card bg="orange">
<h3>#lounge</h3>
</Card>
</Grid>
</Container>
</Box>

View file

@ -5404,6 +5404,11 @@ react-reveal@^1.2.2:
dependencies:
prop-types "^15.5.10"
react-use-websocket@^1.7.3:
version "1.7.3"
resolved "https://registry.yarnpkg.com/react-use-websocket/-/react-use-websocket-1.7.3.tgz#1f67d3b5140761f14b1a65ee2329071e9082597a"
integrity sha512-m2hlmcKkp3F0ksa+awEF3R8oFXbbnb2+wcfPWNWOIOVAB1kkfJCXDXmCI3M4lho+yW4yRwTAYIhLXx4iOQJ/Mw==
react@^16.13.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"