From 18b61029eaf469a0b0e968a8c1904c9ddf132ae2 Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Sat, 14 Feb 2026 21:16:02 +0100 Subject: [PATCH] Increase max password generator length to 256 chars in mobile app (#1701) --- .../(tabs)/settings/password-generator.tsx | 32 +++++------ .../components/form/AdvancedPasswordField.tsx | 34 +++++------ apps/mobile-app/utils/passwordLengthSlider.ts | 57 +++++++++++++++++++ 3 files changed, 90 insertions(+), 33 deletions(-) create mode 100644 apps/mobile-app/utils/passwordLengthSlider.ts diff --git a/apps/mobile-app/app/(tabs)/settings/password-generator.tsx b/apps/mobile-app/app/(tabs)/settings/password-generator.tsx index d3cfe1364..b34d9c237 100644 --- a/apps/mobile-app/app/(tabs)/settings/password-generator.tsx +++ b/apps/mobile-app/app/(tabs)/settings/password-generator.tsx @@ -7,6 +7,7 @@ import { StyleSheet, View, TouchableOpacity, Switch, Platform } from 'react-nati import type { PasswordSettings } from '@/utils/dist/core/models/vault'; import { CreatePasswordGenerator } from '@/utils/dist/core/password-generator'; +import { sliderToLength, lengthToSlider, SLIDER_MIN, SLIDER_MAX } from '@/utils/passwordLengthSlider'; import { useColors } from '@/hooks/useColorScheme'; import { useVaultMutate } from '@/hooks/useVaultMutate'; @@ -60,7 +61,7 @@ export default function PasswordGeneratorSettingsScreen(): React.ReactNode { const passwordSettings = await dbContext.sqliteClient!.getPasswordSettings(); setSettings(passwordSettings); - setSliderValue(passwordSettings.Length); + setSliderValue(lengthToSlider(passwordSettings.Length)); initialValues.current = passwordSettings; // Generate initial preview password only once @@ -119,19 +120,19 @@ export default function PasswordGeneratorSettingsScreen(): React.ReactNode { * Handle slider value change. */ const handleSliderChange = useCallback((value: number): void => { - const roundedLength = Math.round(value); - setSliderValue(roundedLength); + setSliderValue(value); + const passwordLength = sliderToLength(value); // Only generate if value actually changed and we're actively sliding - if (roundedLength !== lastGeneratedLength.current && isSliding.current && settings) { - lastGeneratedLength.current = roundedLength; + if (passwordLength !== lastGeneratedLength.current && isSliding.current && settings) { + lastGeneratedLength.current = passwordLength; // Update settings and regenerate password - const newSettings = { ...settings, Length: roundedLength }; + const newSettings = { ...settings, Length: passwordLength }; setSettings(newSettings); // Track the change - pendingChanges.current = { ...pendingChanges.current, Length: roundedLength }; + pendingChanges.current = { ...pendingChanges.current, Length: passwordLength }; // Generate new preview password try { @@ -149,7 +150,7 @@ export default function PasswordGeneratorSettingsScreen(): React.ReactNode { */ const handleSliderStart = useCallback((): void => { isSliding.current = true; - lastGeneratedLength.current = sliderValue ?? 0; + lastGeneratedLength.current = sliderToLength(sliderValue ?? 0); }, [sliderValue]); /** @@ -157,18 +158,18 @@ export default function PasswordGeneratorSettingsScreen(): React.ReactNode { */ const handleSliderComplete = useCallback((value: number): void => { isSliding.current = false; - const roundedLength = Math.round(value); + const passwordLength = sliderToLength(value); if (!settings) { return; } // Update settings with final value - const newSettings = { ...settings, Length: roundedLength }; + const newSettings = { ...settings, Length: passwordLength }; setSettings(newSettings); // Track the change - pendingChanges.current = { ...pendingChanges.current, Length: roundedLength }; + pendingChanges.current = { ...pendingChanges.current, Length: passwordLength }; // Generate password with final value try { @@ -325,7 +326,7 @@ export default function PasswordGeneratorSettingsScreen(): React.ReactNode { {t('settings.passwordGeneratorSettings.preview')} - {previewPassword} + {previewPassword} {t('items.passwordLength')} - {sliderValue ?? 0} + {sliderToLength(sliderValue ?? 0)} (() => { if (initialSettings) { - return initialSettings.Length; + return lengthToSlider(initialSettings.Length); } if (!isNewCredential && value && value.length > 0) { - return value.length; + return lengthToSlider(value.length); } - return 16; + return lengthToSlider(16); }); const lastGeneratedLength = useRef(0); const isSliding = useRef(false); @@ -92,7 +93,7 @@ const AdvancedPasswordFieldComponent = forwardRef { if (!hasSetInitialLength.current) { if (!isNewCredential && value && value.length > 0) { - setSliderValue(value.length); + setSliderValue(lengthToSlider(value.length)); hasSetInitialLength.current = true; } else if (isNewCredential) { hasSetInitialLength.current = true; @@ -146,17 +147,17 @@ const AdvancedPasswordFieldComponent = forwardRef { - const roundedLength = Math.round(sliderVal); - setSliderValue(roundedLength); + setSliderValue(sliderVal); + const passwordLength = sliderToLength(sliderVal); - if (roundedLength !== lastGeneratedLength.current && isSliding.current) { - lastGeneratedLength.current = roundedLength; + if (passwordLength !== lastGeneratedLength.current && isSliding.current) { + lastGeneratedLength.current = passwordLength; if (!showPassword) { setShowPasswordState(true); } - const newSettings = { ...(currentSettings || {}), Length: roundedLength } as PasswordSettings; + const newSettings = { ...(currentSettings || {}), Length: passwordLength } as PasswordSettings; if (currentSettings) { const password = generatePassword(newSettings); if (password) { @@ -168,14 +169,14 @@ const AdvancedPasswordFieldComponent = forwardRef { isSliding.current = true; - lastGeneratedLength.current = sliderValue; + lastGeneratedLength.current = sliderToLength(sliderValue); }, [sliderValue]); const handleSliderComplete = useCallback((sliderVal: number) => { isSliding.current = false; - const roundedLength = Math.round(sliderVal); + const passwordLength = sliderToLength(sliderVal); if (currentSettings) { - const newSettings = { ...currentSettings, Length: roundedLength }; + const newSettings = { ...currentSettings, Length: passwordLength }; setCurrentSettings(newSettings); } lastGeneratedLength.current = 0; @@ -531,7 +532,7 @@ const AdvancedPasswordFieldComponent = forwardRef {t('items.passwordLength')} - {sliderValue} + {sliderToLength(sliderValue)}