kleckrelay/src/components/AuthContext/use-extension-handler.ts
2023-05-06 22:40:52 +02:00

137 lines
3.0 KiB
TypeScript

import {useCallback, useRef, useState} from "react"
import {useNavigate} from "react-router-dom"
import {useEventListener} from "@react-hookz/web"
import {ExtensionKleckEvent} from "~/extension-types"
import {User} from "~/server-types"
import {AUTHENTICATION_PATHS} from "~/constants/values"
import {queryClient} from "~/constants/react-query"
export interface UseExtensionHandlerResult {
sharePassword: () => void
dispatchPasswordStatus: () => void
closeDialog: (doNotAskAgain: boolean) => void
showDialog: boolean
}
export default function useExtensionHandler(
encryptionPassword: string,
user: User,
): UseExtensionHandlerResult {
const navigate = useNavigate()
const $enterPasswordAmount = useRef<number>(0)
const [doNotAskForPassword, setDoNotAskForPassword] = useState<boolean>(false)
const [askForPassword, setAskForPassword] = useState<boolean>(false)
const dispatchPasswordStatus = useCallback(() => {
window.dispatchEvent(
new CustomEvent("kleckrelay-blob", {
detail: {
type: "password-status",
data: {
status: (() => {
if (doNotAskForPassword) {
return "denied"
}
if (encryptionPassword) {
return "can-ask"
}
return "not-entered"
})(),
},
},
}),
)
}, [doNotAskForPassword, encryptionPassword])
// Handle extension password request
const handleExtensionEvent = useCallback(
(event: ExtensionKleckEvent) => {
switch (event.detail.type) {
case "password-status":
dispatchPasswordStatus()
break
case "ask-for-password":
setAskForPassword(true)
break
case "get-user":
window.dispatchEvent(
new CustomEvent("kleckrelay-blob", {
detail: {
type: "get-user",
data: {
user,
masterPasswordAvailable: Boolean(encryptionPassword),
},
},
}),
)
break
case "enter-password":
if (
$enterPasswordAmount.current < 1 &&
!AUTHENTICATION_PATHS.includes(location.pathname)
) {
$enterPasswordAmount.current += 1
navigate("/enter-password")
}
break
case "refetch-aliases":
if (document.visibilityState !== "visible") {
return
}
;(async () => {
await Promise.allSettled([
queryClient.invalidateQueries({
queryKey: ["get_alias"],
}),
queryClient.invalidateQueries({
queryKey: ["get_aliases"],
}),
])
})()
}
},
[dispatchPasswordStatus],
)
useEventListener(window, "kleckrelay-kleck", handleExtensionEvent, {
passive: true,
})
return {
sharePassword: () => {
setAskForPassword(false)
if (doNotAskForPassword) {
return
}
window.dispatchEvent(
new CustomEvent("kleckrelay-blob", {
detail: {
type: "password",
data: {
password: encryptionPassword,
},
},
}),
)
},
dispatchPasswordStatus,
closeDialog: (doNotAskAgain = false) => {
setDoNotAskForPassword(doNotAskAgain)
setAskForPassword(false)
},
showDialog: askForPassword && !doNotAskForPassword,
}
}