diff --git a/CHANGELOG.md b/CHANGELOG.md index 369e0a7f..c8cda741 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- fixed: When password login is locked out for some time period, show the time instead of "Invalid password". + ## 3.18.0 (2024-08-22) - changed: "" changed to: "Guest Account ([last 3 loginId characters])" diff --git a/src/common/locales/strings/enUS.json b/src/common/locales/strings/enUS.json index ad15265c..a699e2a2 100644 --- a/src/common/locales/strings/enUS.json +++ b/src/common/locales/strings/enUS.json @@ -138,6 +138,7 @@ "password_recovery": "Password Recovery", "password_requirements": "Password Requirements", "password": "Password", + "password_wait_1s": "Please try again in %1$s", "pin_changed": "PIN Changed", "pin_desc_alt": "Your PIN is a 4 digit code used to quickly log back into your account.", "pin_desc": "Your PIN is a 4 digit code used to quickly log back into your account.\n\nPIN login is only usable on a device after first login with password.", diff --git a/src/components/scenes/PasswordLoginScene.tsx b/src/components/scenes/PasswordLoginScene.tsx index 14db4fdc..eb2b89b9 100644 --- a/src/components/scenes/PasswordLoginScene.tsx +++ b/src/components/scenes/PasswordLoginScene.tsx @@ -29,6 +29,7 @@ import { lstrings } from '../../common/locales/strings' import { useHandler } from '../../hooks/useHandler' import { useImports } from '../../hooks/useImports' import { LoginUserInfo, useLocalUsers } from '../../hooks/useLocalUsers' +import { formatWait } from '../../locales/intl' import { Branding } from '../../types/Branding' import { useDispatch } from '../../types/ReduxTypes' import { SceneProps } from '../../types/routerTypes' @@ -232,7 +233,14 @@ export const PasswordLoginScene = (props: Props) => { const passwordError = asMaybePasswordError(error) if (passwordError != null) { - setPasswordErrorMessage(lstrings.invalid_password) + const { wait } = passwordError + if (wait != null) { + setPasswordErrorMessage( + sprintf(lstrings.password_wait_1s, formatWait(wait)) + ) + } else { + setPasswordErrorMessage(lstrings.invalid_password) + } return } diff --git a/src/locales/intl.ts b/src/locales/intl.ts index 87f1b82a..a13a74f4 100644 --- a/src/locales/intl.ts +++ b/src/locales/intl.ts @@ -264,6 +264,16 @@ export function formatTime(date: Date): string { return format(date, 'h:mm bb') } +/** + * Formats a time duration, such as 1.5 minutes or 2 hours + */ +export function formatWait(seconds: number): string { + if (seconds > 90 * 60) return (seconds / (60 * 60)).toFixed(1) + 'h' + if (seconds > 90) return (seconds / 60).toFixed(1) + 'm' + if (seconds > 1) return seconds.toFixed(1) + 's' + return (1000 * seconds).toFixed(1) + 'ms' +} + /** * Returns 'h:mm am/pm, date' string depending on locale. */