|
|
|
@ -6,6 +6,7 @@ import { apiFetch, incrementMetric, setUnraidCsrfToken } from "src/api"
|
|
|
|
|
import { ExitNode, noExitNode, runAsExitNode } from "src/hooks/exit-nodes"
|
|
|
|
|
import { VersionInfo } from "src/hooks/self-update"
|
|
|
|
|
import { assertNever } from "src/utils/util"
|
|
|
|
|
import useSWR from "swr"
|
|
|
|
|
|
|
|
|
|
export type NodeData = {
|
|
|
|
|
Profile: UserProfile
|
|
|
|
@ -120,19 +121,12 @@ type RoutesPOSTData = {
|
|
|
|
|
|
|
|
|
|
// useNodeData returns basic data about the current node.
|
|
|
|
|
export default function useNodeData() {
|
|
|
|
|
const [data, setData] = useState<NodeData>()
|
|
|
|
|
const { data, mutate } = useSWR<NodeData>("/data")
|
|
|
|
|
const [isPosting, setIsPosting] = useState<boolean>(false)
|
|
|
|
|
|
|
|
|
|
const refreshData = useCallback(
|
|
|
|
|
() =>
|
|
|
|
|
apiFetch("/data", "GET")
|
|
|
|
|
.then((r) => r.json())
|
|
|
|
|
.then((d: NodeData) => {
|
|
|
|
|
setData(d)
|
|
|
|
|
setUnraidCsrfToken(d.IsUnraid ? d.UnraidToken : undefined)
|
|
|
|
|
})
|
|
|
|
|
.catch((error) => console.error(error)),
|
|
|
|
|
[setData]
|
|
|
|
|
useEffect(
|
|
|
|
|
() => setUnraidCsrfToken(data?.IsUnraid ? data.UnraidToken : undefined),
|
|
|
|
|
[data]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const prefsPATCH = useCallback(
|
|
|
|
@ -147,12 +141,12 @@ export default function useNodeData() {
|
|
|
|
|
// then make the prefs PATCH. If the request fails,
|
|
|
|
|
// data will be updated to it's previous value in
|
|
|
|
|
// onComplete below.
|
|
|
|
|
setData(optimisticUpdates)
|
|
|
|
|
mutate(optimisticUpdates, false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const onComplete = () => {
|
|
|
|
|
setIsPosting(false)
|
|
|
|
|
refreshData() // refresh data after PATCH finishes
|
|
|
|
|
mutate() // refresh data after PATCH finishes
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return apiFetch("/local/v0/prefs", "PATCH", d)
|
|
|
|
@ -163,7 +157,7 @@ export default function useNodeData() {
|
|
|
|
|
throw err
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
[setIsPosting, refreshData, setData, data]
|
|
|
|
|
[data, mutate]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const routesPOST = useCallback(
|
|
|
|
@ -171,7 +165,7 @@ export default function useNodeData() {
|
|
|
|
|
setIsPosting(true)
|
|
|
|
|
const onComplete = () => {
|
|
|
|
|
setIsPosting(false)
|
|
|
|
|
refreshData() // refresh data after POST finishes
|
|
|
|
|
mutate() // refresh data after POST finishes
|
|
|
|
|
}
|
|
|
|
|
const updateMetrics = () => {
|
|
|
|
|
// only update metrics if values have changed
|
|
|
|
@ -195,26 +189,7 @@ export default function useNodeData() {
|
|
|
|
|
throw err
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
[setIsPosting, refreshData, data?.AdvertisingExitNode]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
useEffect(
|
|
|
|
|
() => {
|
|
|
|
|
// Initial data load.
|
|
|
|
|
refreshData()
|
|
|
|
|
|
|
|
|
|
// Refresh on browser tab focus.
|
|
|
|
|
const onVisibilityChange = () => {
|
|
|
|
|
document.visibilityState === "visible" && refreshData()
|
|
|
|
|
}
|
|
|
|
|
window.addEventListener("visibilitychange", onVisibilityChange)
|
|
|
|
|
return () => {
|
|
|
|
|
// Cleanup browser tab listener.
|
|
|
|
|
window.removeEventListener("visibilitychange", onVisibilityChange)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// Run once.
|
|
|
|
|
[refreshData]
|
|
|
|
|
[mutate, data?.AdvertisingExitNode]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const nodeUpdaters: NodeUpdaters = useMemo(
|
|
|
|
@ -245,5 +220,5 @@ export default function useNodeData() {
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return { data, refreshData, nodeUpdaters, isPosting }
|
|
|
|
|
return { data, refreshData: mutate, nodeUpdaters, isPosting }
|
|
|
|
|
}
|
|
|
|
|