forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {createContext, useCallback, useContext, useState} from 'react'
2
3import {type FeedDescriptor} from '#/state/queries/post-feed'
4import {useSession} from '#/state/session'
5import {IS_WEB} from '#/env'
6import {account} from '#/storage'
7
8type StateContext = FeedDescriptor | null
9type SetContext = (v: FeedDescriptor) => void
10
11const stateContext = createContext<StateContext>(null)
12stateContext.displayName = 'SelectedFeedStateContext'
13const setContext = createContext<SetContext>((_: string) => {})
14setContext.displayName = 'SelectedFeedSetContext'
15
16function getInitialFeed(did?: string): FeedDescriptor | null {
17 if (IS_WEB) {
18 if (window.location.pathname === '/') {
19 const params = new URLSearchParams(window.location.search)
20 const feedFromUrl = params.get('feed')
21 if (feedFromUrl) {
22 // If explicitly booted from a link like /?feed=..., prefer that.
23 return feedFromUrl as FeedDescriptor
24 }
25 }
26
27 const feedFromSession = sessionStorage.getItem('lastSelectedHomeFeed')
28 if (feedFromSession) {
29 // Fall back to a previously chosen feed for this browser tab.
30 return feedFromSession as FeedDescriptor
31 }
32 }
33
34 if (did) {
35 const feedFromStorage = account.get([did, 'lastSelectedHomeFeed'])
36 if (feedFromStorage) {
37 // Fall back to the last chosen one across all tabs.
38 return feedFromStorage as FeedDescriptor
39 }
40 }
41
42 return null
43}
44
45export function Provider({children}: React.PropsWithChildren<{}>) {
46 const {currentAccount} = useSession()
47 const [state, setState] = useState(() => getInitialFeed(currentAccount?.did))
48
49 const saveState = useCallback(
50 (feed: FeedDescriptor) => {
51 setState(feed)
52 if (IS_WEB) {
53 try {
54 sessionStorage.setItem('lastSelectedHomeFeed', feed)
55 } catch {}
56 }
57 if (currentAccount?.did) {
58 account.set([currentAccount?.did, 'lastSelectedHomeFeed'], feed)
59 }
60 },
61 [currentAccount?.did],
62 )
63
64 return (
65 <stateContext.Provider value={state}>
66 <setContext.Provider value={saveState}>{children}</setContext.Provider>
67 </stateContext.Provider>
68 )
69}
70
71export function useSelectedFeed() {
72 return useContext(stateContext)
73}
74
75export function useSetSelectedFeed() {
76 return useContext(setContext)
77}