mirror of
https://github.com/System-End/site.git
synced 2026-04-19 22:05:11 +00:00
Add Slack events to homepage
This commit is contained in:
parent
f0b848b72a
commit
d158c07038
4 changed files with 209 additions and 59 deletions
117
components/home/slack-events.js
Normal file
117
components/home/slack-events.js
Normal 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>
|
||||
)
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
145
pages/index.js
145
pages/index.js
|
|
@ -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 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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue