mirror of
https://github.com/Myzel394/kleckrelay-website.git
synced 2025-06-18 23:45:26 +02:00
improved extension integration
This commit is contained in:
parent
cf21360509
commit
35e4630b51
@ -4,6 +4,7 @@ import {useEvent} from "react-use"
|
||||
|
||||
import {ExtensionKleckEvent} from "~/extension-types"
|
||||
import {User} from "~/server-types"
|
||||
import {AUTHENTICATION_PATHS} from "~/constants/values"
|
||||
|
||||
export interface UseExtensionHandlerResult {
|
||||
sharePassword: () => void
|
||||
@ -69,7 +70,10 @@ export default function useExtensionHandler(
|
||||
)
|
||||
break
|
||||
case "enter-password":
|
||||
if ($enterPasswordAmount.current < 1) {
|
||||
if (
|
||||
$enterPasswordAmount.current < 1 &&
|
||||
!AUTHENTICATION_PATHS.includes(location.pathname)
|
||||
) {
|
||||
$enterPasswordAmount.current += 1
|
||||
|
||||
navigate("/enter-password")
|
||||
|
@ -15,3 +15,4 @@ export const DEFAULT_ALIAS_NOTE: AliasNote = {
|
||||
}
|
||||
export const ERROR_SNACKBAR_SHOW_DURATION = 5000
|
||||
export const SUCCESS_SNACKBAR_SHOW_DURATION = 2000
|
||||
export const AUTHENTICATION_PATHS = ["/auth/login", "/auth/signup", "/auth/complete-account"]
|
||||
|
@ -14,3 +14,5 @@ export * from "./use-error-success-snacks"
|
||||
export {default as useErrorSuccessSnacks} from "./use-error-success-snacks"
|
||||
export * from "./use-is-any-input-focused"
|
||||
export {default as useIsAnyInputFocused} from "./use-is-any-input-focused"
|
||||
export * from "./use-extension-handler"
|
||||
export {default as useExtensionHandler} from "./use-extension-handler"
|
||||
|
23
src/hooks/use-extension-handler.ts
Normal file
23
src/hooks/use-extension-handler.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import {useCallback} from "react"
|
||||
import {useEvent} from "react-use"
|
||||
|
||||
import {ExtensionKleckEvent} from "~/extension-types"
|
||||
|
||||
export interface UseExtensionHandlerData {
|
||||
onEnterPassword?: () => void
|
||||
}
|
||||
|
||||
export default function useExtensionHandler({onEnterPassword}: UseExtensionHandlerData): void {
|
||||
const handleExtensionEvent = useCallback(
|
||||
(event: ExtensionKleckEvent) => {
|
||||
switch (event.detail.type) {
|
||||
case "enter-password":
|
||||
onEnterPassword?.()
|
||||
break
|
||||
}
|
||||
},
|
||||
[onEnterPassword],
|
||||
)
|
||||
|
||||
useEvent("kleckrelay-kleck", handleExtensionEvent)
|
||||
}
|
@ -2,14 +2,9 @@ import {useLocation, useNavigate} from "react-router-dom"
|
||||
import {useContext, useLayoutEffect} from "react"
|
||||
|
||||
import {ServerUser, User} from "~/server-types"
|
||||
import {AUTHENTICATION_PATHS} from "~/constants/values"
|
||||
import AuthContext from "~/AuthContext/AuthContext"
|
||||
|
||||
const AUTHENTICATION_PATHS = [
|
||||
"/auth/login",
|
||||
"/auth/signup",
|
||||
"/auth/complete-account",
|
||||
]
|
||||
|
||||
/// Returns the currently authenticated user.
|
||||
// If the user is not authenticated, it will automatically redirect to the login page.
|
||||
export default function useUser(): ServerUser | User {
|
||||
@ -18,10 +13,7 @@ export default function useUser(): ServerUser | User {
|
||||
const {user, isAuthenticated} = useContext(AuthContext)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (
|
||||
!isAuthenticated &&
|
||||
!AUTHENTICATION_PATHS.includes(location.pathname)
|
||||
) {
|
||||
if (!isAuthenticated && !AUTHENTICATION_PATHS.includes(location.pathname)) {
|
||||
navigate("/auth/login")
|
||||
}
|
||||
}, [isAuthenticated, navigate])
|
||||
|
@ -6,13 +6,13 @@ import {AxiosError} from "axios"
|
||||
import {useTranslation} from "react-i18next"
|
||||
import {Box, InputAdornment} from "@mui/material"
|
||||
import {useMutation} from "@tanstack/react-query"
|
||||
import React, {ReactElement, useContext, useMemo} from "react"
|
||||
import React, {ReactElement, useCallback, useContext, useMemo, useRef} from "react"
|
||||
import passwordGenerator from "secure-random-password"
|
||||
|
||||
import {PasswordField, SimpleForm} from "~/components"
|
||||
import {buildEncryptionPassword, encryptString} from "~/utils"
|
||||
import {isDev} from "~/constants/development"
|
||||
import {useSystemPreferredTheme, useUser} from "~/hooks"
|
||||
import {useExtensionHandler, useSystemPreferredTheme, useUser} from "~/hooks"
|
||||
import {MASTER_PASSWORD_LENGTH} from "~/constants/values"
|
||||
import {AuthenticationDetails, UserNote} from "~/server-types"
|
||||
import {UpdateAccountData, updateAccount} from "~/apis"
|
||||
@ -34,6 +34,8 @@ export default function PasswordForm({onDone}: PasswordFormProps): ReactElement
|
||||
const user = useUser()
|
||||
const theme = useSystemPreferredTheme()
|
||||
|
||||
const $password = useRef<HTMLInputElement | null>(null)
|
||||
const $passwordConfirmation = useRef<HTMLInputElement | null>(null)
|
||||
const schema = yup.object().shape({
|
||||
password: yup.string().required(),
|
||||
passwordConfirmation: yup
|
||||
@ -113,6 +115,17 @@ export default function PasswordForm({onDone}: PasswordFormProps): ReactElement
|
||||
}
|
||||
},
|
||||
})
|
||||
const focusPassword = useCallback(() => {
|
||||
if ($password.current?.value !== "") {
|
||||
$passwordConfirmation.current?.focus()
|
||||
} else {
|
||||
$password.current?.focus()
|
||||
}
|
||||
}, [])
|
||||
|
||||
useExtensionHandler({
|
||||
onEnterPassword: focusPassword,
|
||||
})
|
||||
|
||||
return (
|
||||
<Box maxWidth="80vw">
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as yup from "yup"
|
||||
import {ReactElement} from "react"
|
||||
import {ReactElement, useCallback, useRef} from "react"
|
||||
import {AxiosError} from "axios"
|
||||
import {useFormik} from "formik"
|
||||
import {MdEmail} from "react-icons/md"
|
||||
@ -11,6 +11,7 @@ import {InputAdornment, TextField} from "@mui/material"
|
||||
import {LoginWithEmailResult, loginWithEmail} from "~/apis"
|
||||
import {parseFastAPIError} from "~/utils"
|
||||
import {MultiStepFormElement, SimpleForm} from "~/components"
|
||||
import {useExtensionHandler} from "~/hooks"
|
||||
|
||||
export interface EmailFormProps {
|
||||
onLogin: (email: string, sameRequestToken: string) => void
|
||||
@ -24,6 +25,7 @@ interface Form {
|
||||
export default function EmailForm({onLogin}: EmailFormProps): ReactElement {
|
||||
const {t} = useTranslation()
|
||||
|
||||
const $password = useRef<HTMLInputElement | null>(null)
|
||||
const schema = yup.object().shape({
|
||||
email: yup
|
||||
.string()
|
||||
@ -50,6 +52,12 @@ export default function EmailForm({onLogin}: EmailFormProps): ReactElement {
|
||||
},
|
||||
})
|
||||
|
||||
const focusPassword = useCallback(() => $password.current?.focus(), [])
|
||||
|
||||
useExtensionHandler({
|
||||
onEnterPassword: focusPassword,
|
||||
})
|
||||
|
||||
return (
|
||||
<MultiStepFormElement>
|
||||
<form onSubmit={formik.handleSubmit}>
|
||||
@ -68,6 +76,7 @@ export default function EmailForm({onLogin}: EmailFormProps): ReactElement {
|
||||
id="email"
|
||||
label="Email"
|
||||
placeholder={t("routes.LoginRoute.forms.email.form.email.placeholder")}
|
||||
inputRef={$password}
|
||||
inputMode="email"
|
||||
value={formik.values.email}
|
||||
onChange={formik.handleChange}
|
||||
|
@ -3,7 +3,7 @@ import {useFormik} from "formik"
|
||||
import {MdEmail} from "react-icons/md"
|
||||
import {AxiosError} from "axios"
|
||||
import {useTranslation} from "react-i18next"
|
||||
import React, {ReactElement} from "react"
|
||||
import React, {ReactElement, useCallback, useRef} from "react"
|
||||
|
||||
import {InputAdornment, TextField} from "@mui/material"
|
||||
import {useMutation} from "@tanstack/react-query"
|
||||
@ -13,6 +13,7 @@ import {SignupResult, checkIsDomainDisposable, signup} from "~/apis"
|
||||
import {parseFastAPIError} from "~/utils"
|
||||
import {ServerSettings} from "~/server-types"
|
||||
|
||||
import {useExtensionHandler} from "~/hooks"
|
||||
import DetectEmailAutofillService from "./DetectEmailAutofillService"
|
||||
|
||||
export interface EmailFormProps {
|
||||
@ -28,6 +29,7 @@ interface Form {
|
||||
export default function EmailForm({onSignUp, serverSettings}: EmailFormProps): ReactElement {
|
||||
const {t} = useTranslation()
|
||||
|
||||
const $password = useRef<HTMLInputElement | null>(null)
|
||||
const schema = yup.object().shape({
|
||||
email: yup
|
||||
.string()
|
||||
@ -69,6 +71,11 @@ export default function EmailForm({onSignUp, serverSettings}: EmailFormProps): R
|
||||
}
|
||||
},
|
||||
})
|
||||
const focusPassword = useCallback(() => $password.current?.focus(), [])
|
||||
|
||||
useExtensionHandler({
|
||||
onEnterPassword: focusPassword,
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -92,6 +99,7 @@ export default function EmailForm({onSignUp, serverSettings}: EmailFormProps): R
|
||||
"routes.SignupRoute.forms.email.form.email.placeholder",
|
||||
)}
|
||||
inputMode="email"
|
||||
inputRef={$password}
|
||||
value={formik.values.email}
|
||||
onChange={formik.handleChange}
|
||||
disabled={formik.isSubmitting}
|
||||
|
Loading…
x
Reference in New Issue
Block a user