Merge pull request #433 from ykdojo/improve-slack-clone

Improve the Slack clone example
This commit is contained in:
Copple authored and GitHub committed 2020-12-24 12:32:22 +01:00
commit 400f6b3be3
6 files changed
+127 -199

No files matched your search

+1 -1
View File
@@ -127,8 +127,8 @@ export const fetchMessages = async (channelId, setState) => {
try {
let { body } = await supabase
.from('messages')
.eq('channel_id', channelId)
.select(`*, author:user_id(*)`)
.eq('channel_id', channelId)
.order('inserted_at', true)
if (setState) setState(body)
return body
+59 -135
View File
@@ -135,14 +135,6 @@
}
}
},
"@babel/runtime": {
"version": "7.11.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz",
"integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
},
"@babel/types": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz",
@@ -242,32 +234,60 @@
"resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-10.0.3.tgz",
"integrity": "sha512-XtzzPX2R4+MIyu1waEQUo2tiNwWVEkmObA6pboRCDTPOs4Ri8ckaIE08lN5A5opyF6GVN+IEq/J8KQrgsePsZQ=="
},
"@supabase/postgrest-js": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-0.17.0.tgz",
"integrity": "sha512-7Dt7ALli+bOQK51JMolraI08sJg2UweNuGFghr8MrX4nc3WoDwL5PP6fNZwy+j/7f7nvvM6s1OUtqNTvqiW+5Q==",
"@supabase/gotrue-js": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-1.9.2.tgz",
"integrity": "sha512-RpspDVQdVX4suaODoA+amURn5d8O3zxfRrzMFYX0OV2Ys9wIx5ItoiMrZMQB0badMBn5eCiGUquk3blubiTUJw==",
"requires": {
"superagent": "^5.2.1"
"cross-fetch": "^3.0.6"
},
"dependencies": {
"cross-fetch": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.6.tgz",
"integrity": "sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ==",
"requires": {
"node-fetch": "2.6.1"
}
}
}
},
"@supabase/postgrest-js": {
"version": "0.21.2",
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-0.21.2.tgz",
"integrity": "sha512-ww7aa4GHu788T2QxZlLiRfi+MHJ+EXbNurzTgaG/3nWmOEEy/gmNTLwgyHUAO92MRE2IrLiZyln3QJDZwGQwrw==",
"requires": {
"cross-fetch": "^3.0.6"
},
"dependencies": {
"cross-fetch": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.6.tgz",
"integrity": "sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ==",
"requires": {
"node-fetch": "2.6.1"
}
}
}
},
"@supabase/realtime-js": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-0.9.0.tgz",
"integrity": "sha512-aYkVsD2hNgD7QPPBV+LALJTexNf8pVhIh9qJC13NnOLYZpudtHbof+rg0dgq5+GIhYa8HzqUMdf+OwwlQVJgsw==",
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-1.0.6.tgz",
"integrity": "sha512-qzYYBzXteYsqQYlLzoYwee2OloWn3w8YzUFbDYFUPdkUwLs01OIqsm+lRCzKDivmyn2G0FJQjloWcF4BF5TyBg==",
"requires": {
"@babel/runtime": "^7.9.2",
"@types/websocket": "^1.0.1",
"query-string": "^6.12.1",
"websocket": "^1.0.31"
}
},
"@supabase/supabase-js": {
"version": "0.36.5",
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-0.36.5.tgz",
"integrity": "sha512-iiY5lDIrbhQjT8grRgXbUfIU5omD8CfNI4Iio3z/DHjsdrzYNf9o0/kRAzVVITPOuqlN9g0QhPt7bzRQKxLbwA==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-1.1.2.tgz",
"integrity": "sha512-NGseFj/ZJc0ftEnoaQ7jnTWoOhGGMNLiyxBw65NqaLhGUWrq1nRijYP9TfEg/VmF7sYe9CDyLonTxpX+YkkROA==",
"requires": {
"@supabase/postgrest-js": "^0.17.0",
"@supabase/realtime-js": "^0.9.0",
"superagent": "^5.2.1"
"@supabase/gotrue-js": "^1.9.1",
"@supabase/postgrest-js": "^0.21.2",
"@supabase/realtime-js": "^1.0.6"
}
},
"@types/color-name": {
@@ -280,6 +300,19 @@
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz",
"integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw=="
},
"@types/node": {
"version": "14.14.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.14.tgz",
"integrity": "sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ=="
},
"@types/websocket": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.1.tgz",
"integrity": "sha512-f5WLMpezwVxCLm1xQe/kdPpQIOmL0TXYx2O15VYfYzc7hTIdxiOoOvez+McSIw3b7z/1zGovew9YSL7+h4h7/Q==",
"requires": {
"@types/node": "*"
}
},
"@webassemblyjs/ast": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
@@ -711,11 +744,6 @@
"integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
"optional": true
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"atob": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
@@ -1308,14 +1336,6 @@
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz",
"integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw=="
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
@@ -1415,11 +1435,6 @@
}
}
},
"cookiejar": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
"integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA=="
},
"copy-concurrently": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
@@ -1737,11 +1752,6 @@
"resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
"integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM="
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
@@ -2222,11 +2232,6 @@
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"fast-safe-stringify": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz",
"integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
},
"figgy-pudding": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
@@ -2308,21 +2313,6 @@
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
"integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
},
"form-data": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"formidable": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
"integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q=="
},
"fragment-cache": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
@@ -3064,11 +3054,6 @@
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
},
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@@ -3187,24 +3172,6 @@
}
}
},
"mime": {
"version": "2.4.6",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
"integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA=="
},
"mime-db": {
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
},
"mime-types": {
"version": "2.1.27",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
"requires": {
"mime-db": "1.44.0"
}
},
"mimic-response": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
@@ -4303,11 +4270,6 @@
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"qs": {
"version": "6.9.4",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz",
"integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ=="
},
"query-string": {
"version": "6.13.7",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.13.7.tgz",
@@ -5182,44 +5144,6 @@
"resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz",
"integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw=="
},
"superagent": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz",
"integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==",
"requires": {
"component-emitter": "^1.3.0",
"cookiejar": "^2.1.2",
"debug": "^4.1.1",
"fast-safe-stringify": "^2.0.7",
"form-data": "^3.0.0",
"formidable": "^1.2.2",
"methods": "^1.1.2",
"mime": "^2.4.6",
"qs": "^6.9.4",
"readable-stream": "^3.6.0",
"semver": "^7.3.2"
},
"dependencies": {
"debug": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
"integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
"requires": {
"ms": "2.1.2"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"semver": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
}
}
},
"supports-color": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
@@ -6085,9 +6009,9 @@
}
},
"websocket": {
"version": "1.0.32",
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.32.tgz",
"integrity": "sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q==",
"version": "1.0.33",
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.33.tgz",
"integrity": "sha512-XwNqM2rN5eh3G2CUQE3OHZj+0xfdH42+OFK6LdC2yqiC0YU8e5UK0nYre220T0IyyN031V/XOvtHvXozvJYFWA==",
"requires": {
"bufferutil": "^4.0.1",
"debug": "^2.2.0",
+1 -1
View File
@@ -9,7 +9,7 @@
"start": "next start"
},
"dependencies": {
"@supabase/supabase-js": "^0.36.5",
"@supabase/supabase-js": "^1.1.2",
"next": "latest",
"react": "^16.7.0",
"react-dom": "^16.7.0",
+57 -48
View File
@@ -1,59 +1,68 @@
import '~/styles/style.scss'
import React from 'react'
import App from 'next/app'
import React, { useState, useEffect } from 'react'
import Router from 'next/router'
import UserContext from 'lib/UserContext'
import { supabase } from 'lib/Store'
export default class SupabaseSlackClone extends App {
state = {
authLoaded: false,
user: null,
}
export default function SupabaseSlackClone({Component, pageProps}){
const [userLoaded, setUserLoaded] = useState(false)
const [user, setUser] = useState(null)
const [session, setSession] = useState(null);
componentDidMount = () => {
const user = localStorage.getItem('supabase-slack-clone')
if (user) this.setState({ user, authLoaded: true })
else Router.push('/')
}
signIn = async (id, username) => {
try {
let { body } = await supabase.from('users').match({ username }).select('id, username')
const existing = body[0]
const { body: user } = existing?.id
? await supabase.from('users').update({ id, username }).match({ id }).single()
: await supabase.from('users').insert([{ id, username }]).single()
localStorage.setItem('supabase-slack-clone', user.id)
this.setState({ user: user.id }, () => {
Router.push('/channels/[id]', '/channels/1')
})
} catch (error) {
console.log('error', error)
useEffect(() => {
const session = supabase.auth.session();
setSession(session);
setUser(session?.user ?? null);
setUserLoaded(session ? true : false)
if (user) {
signIn(user.id, user.email)
Router.push('/channels/[id]', '/channels/1')
}
}
signOut = () => {
supabase.auth.logout()
localStorage.removeItem('supabase-slack-clone')
this.setState({ user: null })
Router.push('/')
}
render() {
const { Component, pageProps } = this.props
return (
<UserContext.Provider
value={{
authLoaded: this.state.authLoaded,
user: this.state.user,
signIn: this.signIn,
signOut: this.signOut,
}}
>
<Component {...pageProps} />
</UserContext.Provider>
const { data: authListener } = supabase.auth.onAuthStateChange(
async (event, session) => {
setSession(session);
const currentUser = session?.user
setUser(currentUser ?? null);
setUserLoaded(!!currentUser)
if (currentUser) {
signIn(currentUser.id, currentUser.email)
Router.push('/channels/[id]', '/channels/1')
}
}
)
return () => {
authListener.unsubscribe()
}
}, [user])
const signIn = async (id, username) => {
const { body } = await supabase.from('users').select('id, username').eq('id', id)
const result = body[0]
// If the user exists in the users table, update the username.
// If not, create a new row.
result?.id
? await supabase.from('users').update({ id, username }).match({ id }).single()
: await supabase.from('users').insert([{ id, username }]).single()
}
const signOut = async () => {
const result = await supabase.auth.signOut()
Router.push('/')
}
return (
<UserContext.Provider
value={{
userLoaded,
user,
signIn,
signOut
}}
>
<Component {...pageProps} />
</UserContext.Provider>
)
}
@@ -11,12 +11,6 @@ const ChannelsPage = (props) => {
const { user, authLoaded, signOut } = useContext(UserContext)
const messagesEndRef = useRef(null)
// Redirect if not signed in.
useEffect(() => {
if (authLoaded && !user) signOut()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [user, router])
// Else load up the page
const { id: channelId } = router.query
const { messages, channels } = useStore({ channelId })
@@ -41,7 +35,7 @@ const ChannelsPage = (props) => {
</div>
</div>
<div className="p-2 absolute bottom-0 left-0 w-full">
<MessageInput onSubmit={async (text) => addMessage(text, channelId, user)} />
<MessageInput onSubmit={async (text) => addMessage(text, channelId, user.id)} />
</div>
</div>
</Layout>
+8 -7
View File
@@ -9,16 +9,17 @@ const Home = () => {
const handleLogin = async (type, username, password) => {
try {
const {
body: { user },
} =
const { error, user } =
type === 'LOGIN'
? await supabase.auth.login(username, password)
: await supabase.auth.signup(username, password)
? await supabase.auth.signIn({email: username, password})
: await supabase.auth.signUp({email: username, password})
// If the user doesn't exist here and an error hasn't been raised yet,
// that must mean that a confirmation email has been sent.
if (!user) alert('Signup successful, confirmation mail should be sent soon!')
if (!!user) signIn(user.id, user.email)
// NOTE: Confirming your email address is required by default.
if (error) {
alert('Error with auth: ' + error.message)
}
else if (!user) alert('Signup successful, confirmation mail should be sent soon!')
} catch (error) {
console.log('error', error)
alert(error.error_description || error)