2021-12-08 16:42:50 +00:00
|
|
|
import { app } from './init'
|
|
|
|
import { getFirestore, doc, setDoc, getDoc } from 'firebase/firestore'
|
|
|
|
import { getAuth } from 'firebase/auth'
|
|
|
|
import { ref, getStorage, uploadBytes, getDownloadURL } from 'firebase/storage'
|
|
|
|
import {
|
|
|
|
onAuthStateChanged,
|
|
|
|
GoogleAuthProvider,
|
|
|
|
signInWithPopup,
|
|
|
|
} from 'firebase/auth'
|
|
|
|
|
|
|
|
export type User = {
|
|
|
|
id: string
|
|
|
|
email: string
|
|
|
|
name: string
|
|
|
|
username: string
|
|
|
|
avatarUrl: string
|
2021-12-13 17:58:47 +00:00
|
|
|
balance: number
|
2021-12-08 16:42:50 +00:00
|
|
|
createdTime: number
|
|
|
|
lastUpdatedTime: number
|
|
|
|
}
|
|
|
|
|
|
|
|
const db = getFirestore(app)
|
|
|
|
export const auth = getAuth(app)
|
|
|
|
|
|
|
|
export async function getUser(userId: string) {
|
|
|
|
const docSnap = await getDoc(doc(db, 'users', userId))
|
|
|
|
return docSnap.data() as User
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function setUser(userId: string, user: User) {
|
|
|
|
await setDoc(doc(db, 'users', userId), user)
|
|
|
|
}
|
|
|
|
|
|
|
|
const CACHED_USER_KEY = 'CACHED_USER_KEY'
|
2021-12-09 23:37:26 +00:00
|
|
|
export function listenForLogin(onUser: (_user: User | null) => void) {
|
2021-12-08 16:42:50 +00:00
|
|
|
// Immediately load any persisted user object from browser cache.
|
|
|
|
const cachedUser = localStorage.getItem(CACHED_USER_KEY)
|
|
|
|
if (cachedUser) {
|
|
|
|
onUser(JSON.parse(cachedUser))
|
|
|
|
}
|
|
|
|
|
2021-12-09 23:33:01 +00:00
|
|
|
return onAuthStateChanged(auth, async (user) => {
|
2021-12-08 16:42:50 +00:00
|
|
|
if (user) {
|
|
|
|
let fetchedUser = await getUser(user.uid)
|
|
|
|
if (!fetchedUser) {
|
|
|
|
// User just created an account; save them to our database.
|
|
|
|
fetchedUser = {
|
|
|
|
id: user.uid,
|
|
|
|
name: user.displayName || 'Default Name',
|
|
|
|
username: user.displayName?.replace(/\s+/g, '') || 'DefaultUsername',
|
|
|
|
avatarUrl: user.photoURL || '',
|
|
|
|
email: user.email || 'default@blah.com',
|
2021-12-13 17:58:47 +00:00
|
|
|
balance: 10000,
|
2021-12-08 16:42:50 +00:00
|
|
|
// TODO: use Firestore timestamp?
|
|
|
|
createdTime: Date.now(),
|
|
|
|
lastUpdatedTime: Date.now(),
|
|
|
|
}
|
|
|
|
await setUser(user.uid, fetchedUser)
|
|
|
|
}
|
|
|
|
onUser(fetchedUser)
|
|
|
|
|
|
|
|
// Persist to local storage, to reduce login blink next time.
|
|
|
|
// Note: Cap on localStorage size is ~5mb
|
|
|
|
localStorage.setItem(CACHED_USER_KEY, JSON.stringify(fetchedUser))
|
|
|
|
} else {
|
2021-12-09 23:37:26 +00:00
|
|
|
// User logged out; reset to null
|
|
|
|
onUser(null)
|
2021-12-13 18:20:31 +00:00
|
|
|
localStorage.removeItem(CACHED_USER_KEY)
|
2021-12-08 16:42:50 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function firebaseLogin() {
|
|
|
|
const provider = new GoogleAuthProvider()
|
|
|
|
signInWithPopup(auth, provider)
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function firebaseLogout() {
|
|
|
|
auth.signOut()
|
|
|
|
}
|
|
|
|
|
|
|
|
const storage = getStorage(app)
|
|
|
|
// Example: uploadData('avatars/ajfi8iejsf.png', data)
|
|
|
|
export async function uploadData(
|
|
|
|
path: string,
|
|
|
|
data: ArrayBuffer | Blob | Uint8Array
|
|
|
|
) {
|
|
|
|
const uploadRef = ref(storage, path)
|
|
|
|
// Uploaded files should be cached for 1 day, then revalidated
|
|
|
|
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
|
|
|
|
const metadata = { cacheControl: 'public, max-age=86400, must-revalidate' }
|
|
|
|
await uploadBytes(uploadRef, data, metadata)
|
|
|
|
return await getDownloadURL(uploadRef)
|
|
|
|
}
|