2024-05-20 11:16:54 +00:00
|
|
|
import { Accessor, JSX, createContext, createEffect, createSignal, on, 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-05-20 11:16:54 +00:00
|
|
|
import { Author, AuthorFollowsResult, FollowingEntity } from '../graphql/schema/core.gen'
|
2024-01-31 12:34:15 +00:00
|
|
|
|
|
|
|
import { useSession } from './session'
|
|
|
|
|
2024-05-20 11:16:54 +00:00
|
|
|
type FollowingData = { slug: string; type: 'follow' | 'unfollow' }
|
2024-03-11 05:20:00 +00:00
|
|
|
|
2024-01-31 12:34:15 +00:00
|
|
|
interface FollowingContextType {
|
|
|
|
loading: Accessor<boolean>
|
2024-05-20 11:16:54 +00:00
|
|
|
|
2024-05-05 16:13:48 +00:00
|
|
|
followers: Accessor<Author[]>
|
2024-05-20 11:16:54 +00:00
|
|
|
setFollows: (follows: AuthorFollowsResult) => void
|
|
|
|
|
|
|
|
following: Accessor<FollowingData>
|
|
|
|
changeFollowing: (what: FollowingEntity, slug: string, value: boolean) => void
|
|
|
|
|
|
|
|
follows: AuthorFollowsResult
|
|
|
|
loadFollows: () => void
|
|
|
|
|
2024-01-31 12:34:15 +00:00
|
|
|
follow: (what: FollowingEntity, slug: string) => Promise<void>
|
|
|
|
unfollow: (what: FollowingEntity, slug: string) => Promise<void>
|
|
|
|
}
|
|
|
|
|
|
|
|
const FollowingContext = createContext<FollowingContextType>()
|
|
|
|
|
|
|
|
export function useFollowing() {
|
|
|
|
return useContext(FollowingContext)
|
|
|
|
}
|
|
|
|
|
2024-03-29 09:58:32 +00:00
|
|
|
const EMPTY_SUBSCRIPTIONS: AuthorFollowsResult = {
|
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-05-05 16:13:48 +00:00
|
|
|
const [followers, setFollowers] = createSignal<Author[]>([])
|
2024-05-20 11:16:54 +00:00
|
|
|
const [follows, setFollows] = createStore<AuthorFollowsResult>(EMPTY_SUBSCRIPTIONS)
|
2024-02-21 14:25:28 +00:00
|
|
|
const { author, session } = useSession()
|
2024-01-31 12:34:15 +00:00
|
|
|
|
|
|
|
const fetchData = async () => {
|
|
|
|
setLoading(true)
|
|
|
|
try {
|
|
|
|
if (apiClient.private) {
|
|
|
|
console.debug('[context.following] fetching subs data...')
|
2024-02-21 14:25:28 +00:00
|
|
|
const result = await apiClient.getAuthorFollows({ user: session()?.user.id })
|
2024-05-20 11:16:54 +00:00
|
|
|
setFollows(result || EMPTY_SUBSCRIPTIONS)
|
2024-01-31 12:34:15 +00:00
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.info('[context.following] cannot get subs', error)
|
|
|
|
} finally {
|
|
|
|
setLoading(false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-20 11:16:54 +00:00
|
|
|
const [following, setFollowing] = createSignal<FollowingData>()
|
2024-01-31 12:34:15 +00:00
|
|
|
const follow = async (what: FollowingEntity, slug: string) => {
|
2024-03-15 14:57:03 +00:00
|
|
|
if (!author()) return
|
2024-05-20 11:16:54 +00:00
|
|
|
setFollowing({ slug, type: 'follow' })
|
2024-01-31 12:34:15 +00:00
|
|
|
try {
|
2024-05-20 11:16:54 +00:00
|
|
|
const result = await apiClient.follow({ what, slug })
|
|
|
|
setFollows((subs) => {
|
|
|
|
if (result.authors) subs['authors'] = result.authors || []
|
|
|
|
if (result.topics) subs['topics'] = result.topics || []
|
|
|
|
return subs
|
2024-03-15 14:57:03 +00:00
|
|
|
})
|
2024-01-31 12:34:15 +00:00
|
|
|
} catch (error) {
|
2024-03-15 14:57:03 +00:00
|
|
|
console.error(error)
|
2024-03-11 05:20:00 +00:00
|
|
|
} finally {
|
2024-05-20 11:16:54 +00:00
|
|
|
setFollowing() // Сбрасываем состояние действия подписки.
|
2024-01-31 12:34:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const unfollow = async (what: FollowingEntity, slug: string) => {
|
|
|
|
if (!author()) return
|
2024-05-20 11:16:54 +00:00
|
|
|
setFollowing({ slug: slug, type: 'unfollow' })
|
2024-01-31 12:34:15 +00:00
|
|
|
try {
|
2024-05-20 11:16:54 +00:00
|
|
|
const result = await apiClient.unfollow({ what, slug })
|
|
|
|
setFollows((subs) => {
|
|
|
|
if (result.authors) subs['authors'] = result.authors || []
|
|
|
|
if (result.topics) subs['topics'] = result.topics || []
|
|
|
|
return subs
|
|
|
|
})
|
2024-01-31 12:34:15 +00:00
|
|
|
} catch (error) {
|
|
|
|
console.error(error)
|
2024-03-11 05:20:00 +00:00
|
|
|
} finally {
|
2024-05-20 11:16:54 +00:00
|
|
|
setFollowing()
|
2024-01-31 12:34:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-20 11:16:54 +00:00
|
|
|
createEffect(
|
|
|
|
on(
|
|
|
|
() => author(),
|
|
|
|
(a) => {
|
|
|
|
if (a?.id) {
|
|
|
|
try {
|
|
|
|
const appdata = session()?.user.app_data
|
|
|
|
if (appdata) {
|
|
|
|
const { authors, followers, topics } = appdata
|
|
|
|
setFollows({ authors, topics })
|
|
|
|
setFollowers(followers)
|
|
|
|
if (!authors) fetchData()
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e)
|
|
|
|
}
|
2024-04-17 15:47:24 +00:00
|
|
|
}
|
2024-05-20 11:16:54 +00:00
|
|
|
},
|
|
|
|
),
|
|
|
|
)
|
2024-01-31 12:34:15 +00:00
|
|
|
|
2024-05-20 11:16:54 +00:00
|
|
|
const changeFollowing = (what: FollowingEntity, slug: string, value = true) => {
|
|
|
|
setFollows((fff) => {
|
|
|
|
const updatedSubs = { ...fff }
|
2024-01-31 12:34:15 +00:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const value: FollowingContextType = {
|
|
|
|
loading,
|
2024-05-20 11:16:54 +00:00
|
|
|
follows,
|
|
|
|
setFollows,
|
|
|
|
following,
|
|
|
|
changeFollowing,
|
2024-04-08 12:49:40 +00:00
|
|
|
followers,
|
2024-05-20 11:16:54 +00:00
|
|
|
loadFollows: fetchData,
|
2024-01-31 12:34:15 +00:00
|
|
|
follow,
|
|
|
|
unfollow,
|
|
|
|
}
|
|
|
|
|
|
|
|
return <FollowingContext.Provider value={value}>{props.children}</FollowingContext.Provider>
|
|
|
|
}
|