manifold/web/hooks/use-fold.ts

118 lines
3.2 KiB
TypeScript
Raw Permalink Normal View History

import { isEqual, sortBy } from 'lodash'
2022-01-23 06:51:19 +00:00
import { useEffect, useState } from 'react'
import { Fold } from 'common/fold'
import { User } from 'common/user'
2022-01-26 20:03:32 +00:00
import {
listAllFolds,
2022-01-26 20:03:32 +00:00
listenForFold,
listenForFolds,
2022-02-06 22:55:14 +00:00
listenForFoldsWithTags,
2022-01-26 20:03:32 +00:00
listenForFollow,
listenForFollowedFolds,
} from 'web/lib/firebase/folds'
2022-01-23 06:51:19 +00:00
2022-01-27 06:38:22 +00:00
export const useFold = (foldId: string | undefined) => {
2022-01-23 06:51:19 +00:00
const [fold, setFold] = useState<Fold | null | undefined>()
useEffect(() => {
2022-01-27 06:38:22 +00:00
if (foldId) return listenForFold(foldId, setFold)
2022-01-23 06:51:19 +00:00
}, [foldId])
return fold
}
2022-01-24 05:47:20 +00:00
export const useFolds = () => {
const [folds, setFolds] = useState<Fold[] | undefined>()
useEffect(() => {
return listenForFolds(setFolds)
}, [])
return folds
}
2022-01-26 20:03:32 +00:00
2022-02-06 22:55:14 +00:00
export const useFoldsWithTags = (tags: string[] | undefined) => {
const [folds, setFolds] = useState<Fold[] | undefined>()
const tagsKey = tags?.join(',')
2022-02-06 22:55:14 +00:00
useEffect(() => {
if (tags && tags.length > 0) return listenForFoldsWithTags(tags, setFolds)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [tagsKey])
2022-02-06 22:55:14 +00:00
return folds
}
2022-01-26 20:03:32 +00:00
export const useFollowingFold = (fold: Fold, user: User | null | undefined) => {
const [following, setFollowing] = useState<boolean | undefined>()
const foldId = fold?.id
const userId = user?.id
2022-01-26 20:03:32 +00:00
useEffect(() => {
if (userId) return listenForFollow(foldId, userId, setFollowing)
}, [foldId, userId])
2022-01-26 20:03:32 +00:00
return following
}
// Note: We cache followedFoldIds in localstorage to speed up the initial load
export const useFollowedFoldIds = (user: User | null | undefined) => {
const [followedFoldIds, setFollowedFoldIds] = useState<string[] | undefined>(
undefined
)
useEffect(() => {
if (user) {
const key = `followed-folds-${user.id}`
const followedFoldJson = localStorage.getItem(key)
if (followedFoldJson) {
setFollowedFoldIds(JSON.parse(followedFoldJson))
}
return listenForFollowedFolds(user.id, (foldIds) => {
setFollowedFoldIds(foldIds)
localStorage.setItem(key, JSON.stringify(foldIds))
})
}
}, [user])
return followedFoldIds
}
// We also cache followedFolds directly in JSON.
// TODO: Extract out localStorage caches to a utility
export const useFollowedFolds = (user: User | null | undefined) => {
const [followedFolds, setFollowedFolds] = useState<Fold[] | undefined>()
const ids = useFollowedFoldIds(user)
useEffect(() => {
if (user && ids) {
const key = `followed-full-folds-${user.id}`
const followedFoldJson = localStorage.getItem(key)
if (followedFoldJson) {
setFollowedFolds(JSON.parse(followedFoldJson))
// Exit early if ids and followedFoldIds have all the same elements.
if (
isEqual(
sortBy(ids),
sortBy(JSON.parse(followedFoldJson).map((f: Fold) => f.id))
)
) {
return
}
}
// Otherwise, fetch the full contents of all folds
listAllFolds().then((folds) => {
const followedFolds = folds.filter((fold) => ids.includes(fold.id))
setFollowedFolds(followedFolds)
localStorage.setItem(key, JSON.stringify(followedFolds))
})
}
}, [user, ids])
return followedFolds
}