forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {useEffect, useState} from 'react'
2import uuid from 'react-native-uuid'
3
4import {onAppStateChange} from '#/lib/appState'
5import {isSessionIdExpired} from '#/analytics/identifiers/util'
6
7const SESSION_ID_KEY = 'bsky_session_id'
8const LAST_EVENT_KEY = 'bsky_session_id_last_event_at'
9
10let sessionId = (() => {
11 const existing = window.sessionStorage.getItem(SESSION_ID_KEY)
12 const lastEventStr = window.sessionStorage.getItem(LAST_EVENT_KEY)
13 const lastEvent = lastEventStr ? Number(lastEventStr) : undefined
14 const id = existing && !isSessionIdExpired(lastEvent) ? existing : uuid.v4()
15 window.sessionStorage.setItem(SESSION_ID_KEY, id)
16 window.sessionStorage.setItem(LAST_EVENT_KEY, String(Date.now()))
17 return id
18})()
19
20export function getInitialSessionId() {
21 return sessionId
22}
23
24/**
25 * Gets the current session ID. Freshness depends on `useSessionId` being
26 * mounted, which handles refreshing this value between foreground/background
27 * transitions. Since that's mounted in `analytics/index.tsx`, this value can
28 * generally be trusted to be up to date.
29 */
30export function getSessionId() {
31 return window.sessionStorage.getItem(SESSION_ID_KEY)
32}
33
34export function useSessionId() {
35 const [id, setId] = useState(() => sessionId)
36
37 useEffect(() => {
38 const sub = onAppStateChange(state => {
39 if (state === 'active') {
40 const lastEventStr = window.sessionStorage.getItem(LAST_EVENT_KEY)
41 const lastEvent = lastEventStr ? Number(lastEventStr) : undefined
42 if (isSessionIdExpired(lastEvent)) {
43 sessionId = uuid.v4()
44 window.sessionStorage.setItem(SESSION_ID_KEY, sessionId)
45 setId(sessionId)
46 }
47 }
48 window.sessionStorage.setItem(LAST_EVENT_KEY, String(Date.now()))
49 })
50 return () => sub.remove()
51 }, [])
52
53 return id
54}