webapp/src/context/following.tsx

151 lines
4.7 KiB
TypeScript
Raw Normal View History

2024-02-04 11:25:21 +00:00
import { Accessor, JSX, createContext, createEffect, createSignal, useContext } from 'solid-js'
2024-01-31 12:34:15 +00:00
import { createStore } from 'solid-js/store'
import { apiClient } from '../graphql/client/core'
2024-03-11 05:20:00 +00:00
import { Author, AuthorFollows, Community, FollowingEntity, Topic } from "../graphql/schema/core.gen";
2024-01-31 12:34:15 +00:00
import { useSession } from './session'
2024-03-11 05:20:00 +00:00
export type SubscriptionsData = {
topics?: Topic[]
authors?: Author[]
communities?: Community[]
}
type SubscribeAction = { slug: string; type: 'subscribe' | 'unsubscribe' }
2024-01-31 12:34:15 +00:00
interface FollowingContextType {
loading: Accessor<boolean>
subscriptions: AuthorFollows
setSubscriptions: (subscriptions: AuthorFollows) => void
2024-01-31 12:34:15 +00:00
setFollowing: (what: FollowingEntity, slug: string, value: boolean) => void
loadSubscriptions: () => void
follow: (what: FollowingEntity, slug: string) => Promise<void>
unfollow: (what: FollowingEntity, slug: string) => Promise<void>
2024-02-08 09:11:52 +00:00
isOwnerSubscribed: (id: number | string) => boolean
2024-03-11 05:20:00 +00:00
// followers: Accessor<Author[]>
subscribeInAction?: Accessor<SubscribeAction>
2024-01-31 12:34:15 +00:00
}
const FollowingContext = createContext<FollowingContextType>()
export function useFollowing() {
return useContext(FollowingContext)
}
const EMPTY_SUBSCRIPTIONS: AuthorFollows = {
2024-01-31 12:34:15 +00:00
topics: [],
authors: [],
communities: [],
}
export const FollowingProvider = (props: { children: JSX.Element }) => {
const [loading, setLoading] = createSignal<boolean>(false)
2024-03-11 05:20:00 +00:00
const [subscriptions, setSubscriptions] = createStore<SubscriptionsData>(EMPTY_SUBSCRIPTIONS)
const { session, author } = useSession()
const [subscribeInAction, setSubscribeInAction] = createSignal<SubscribeAction>()
2024-01-31 12:34:15 +00:00
const fetchData = async () => {
setLoading(true)
try {
if (apiClient.private) {
console.debug('[context.following] fetching subs data...')
const result = await apiClient.getAuthorFollows({ user: session()?.user.id })
2024-01-31 12:34:15 +00:00
setSubscriptions(result || EMPTY_SUBSCRIPTIONS)
console.info('[context.following] subs:', subscriptions)
}
} catch (error) {
console.info('[context.following] cannot get subs', error)
} finally {
setLoading(false)
}
}
const follow = async (what: FollowingEntity, slug: string) => {
2024-03-11 05:20:00 +00:00
console.log("!!! flw:", author());
// if (!author()) return
setSubscribeInAction({ slug, type: 'subscribe' })
2024-01-31 12:34:15 +00:00
try {
2024-03-11 05:20:00 +00:00
const result = async () => {
await apiClient.follow({ what, slug })
}
console.log("!!! follow result:", result());
2024-01-31 12:34:15 +00:00
setSubscriptions((prevSubscriptions) => {
const updatedSubs = { ...prevSubscriptions }
if (!updatedSubs[what]) updatedSubs[what] = []
const exists = updatedSubs[what]?.some((entity) => entity.slug === slug)
if (!exists) updatedSubs[what].push(slug)
return updatedSubs
})
} catch (error) {
console.error(error)
2024-03-11 05:20:00 +00:00
} finally {
setSubscribeInAction()
2024-01-31 12:34:15 +00:00
}
}
const unfollow = async (what: FollowingEntity, slug: string) => {
if (!author()) return
try {
2024-03-11 05:20:00 +00:00
setSubscribeInAction({ slug: slug, type: 'unsubscribe' })
2024-01-31 12:34:15 +00:00
await apiClient.unfollow({ what, slug })
} catch (error) {
console.error(error)
2024-03-11 05:20:00 +00:00
} finally {
setSubscribeInAction()
2024-01-31 12:34:15 +00:00
}
}
2024-03-11 05:20:00 +00:00
2024-01-31 14:59:03 +00:00
createEffect(() => {
2024-03-11 05:20:00 +00:00
console.log("!!! cone setSubscribeInAction:", subscribeInAction());
2024-01-31 15:35:40 +00:00
if (author()) {
2024-01-31 15:46:34 +00:00
console.debug('[context.following] author update detect')
fetchData()
2024-01-31 12:34:15 +00:00
}
})
const setFollowing = (what: FollowingEntity, slug: string, value = true) => {
setSubscriptions((prevSubscriptions) => {
const updatedSubs = { ...prevSubscriptions }
if (!updatedSubs[what]) updatedSubs[what] = []
if (value) {
const exists = updatedSubs[what]?.some((entity) => entity.slug === slug)
if (!exists) updatedSubs[what].push(slug)
} else {
updatedSubs[what] = (updatedSubs[what] || []).filter((x) => x !== slug)
}
return updatedSubs
})
try {
;(value ? follow : unfollow)(what, slug)
} catch (error) {
console.error(error)
} finally {
fetchData()
}
}
2024-02-08 09:11:52 +00:00
const isOwnerSubscribed = (id?: number | string) => {
if (!author() || !subscriptions) return
const isAuthorSubscribed = subscriptions.authors?.some((authorEntity) => authorEntity.id === id)
const isTopicSubscribed = subscriptions.topics?.some((topicEntity) => topicEntity.slug === id)
return !!isAuthorSubscribed || !!isTopicSubscribed
2024-02-05 12:34:47 +00:00
}
2024-01-31 12:34:15 +00:00
const value: FollowingContextType = {
loading,
subscriptions,
setSubscriptions,
2024-02-05 12:34:47 +00:00
isOwnerSubscribed,
2024-01-31 12:34:15 +00:00
setFollowing,
loadSubscriptions: fetchData,
follow,
unfollow,
2024-03-11 05:20:00 +00:00
// followers,
subscribeInAction,
2024-01-31 12:34:15 +00:00
}
return <FollowingContext.Provider value={value}>{props.children}</FollowingContext.Provider>
}