Remember password settings in form restore logic (#1473)

This commit is contained in:
Leendert de Borst
2026-01-23 11:40:10 +01:00
parent 18164fa868
commit 736c691970
2 changed files with 35 additions and 8 deletions

View File

@@ -16,6 +16,10 @@ interface IPasswordFieldProps {
error?: string;
showPassword?: boolean;
onShowPasswordChange?: (show: boolean) => void;
/** Initial password settings to use (e.g., from persisted form state) */
initialSettings?: PasswordSettings;
/** Callback when password settings change */
onSettingsChange?: (settings: PasswordSettings) => void;
}
/**
@@ -29,7 +33,9 @@ const PasswordField: React.FC<IPasswordFieldProps> = ({
placeholder,
error,
showPassword: controlledShowPassword,
onShowPasswordChange
onShowPasswordChange,
initialSettings,
onSettingsChange
}) => {
const { t } = useTranslation();
const dbContext = useDb();
@@ -56,12 +62,18 @@ const PasswordField: React.FC<IPasswordFieldProps> = ({
useEffect(() => {
/**
* Load password settings from the database.
* If initialSettings is provided (e.g., from persisted form state), use it instead of the database default.
*/
const loadSettings = async (): Promise<void> => {
try {
if (dbContext.sqliteClient) {
const settings = dbContext.sqliteClient.settings.getPasswordSettings();
setCurrentSettings(settings);
// Use initialSettings if provided, otherwise use database settings
if (initialSettings !== undefined) {
setCurrentSettings(initialSettings);
} else {
const settings = dbContext.sqliteClient.settings.getPasswordSettings();
setCurrentSettings(settings);
}
setIsLoaded(true);
}
} catch (error) {
@@ -69,7 +81,7 @@ const PasswordField: React.FC<IPasswordFieldProps> = ({
}
};
void loadSettings();
}, [dbContext.sqliteClient]);
}, [dbContext.sqliteClient, initialSettings]);
const generatePassword = useCallback((settings: PasswordSettings) => {
try {
@@ -90,9 +102,12 @@ const PasswordField: React.FC<IPasswordFieldProps> = ({
const newSettings = { ...currentSettings, Length: length };
setCurrentSettings(newSettings);
// Notify parent of settings change for persistence
onSettingsChange?.(newSettings);
// Always generate password when length changes
generatePassword(newSettings);
}, [currentSettings, generatePassword]);
}, [currentSettings, generatePassword, onSettingsChange]);
const handleRegeneratePassword = useCallback(() => {
if (!currentSettings) {
@@ -108,7 +123,9 @@ const PasswordField: React.FC<IPasswordFieldProps> = ({
const handleAdvancedSettingsChange = useCallback((newSettings: PasswordSettings) => {
setCurrentSettings(newSettings);
}, []);
// Notify parent of settings change for persistence
onSettingsChange?.(newSettings);
}, [onSettingsChange]);
const togglePasswordVisibility = useCallback(() => {
setShowPassword(!showPassword);

View File

@@ -29,7 +29,7 @@ import useServiceDetection from '@/entrypoints/popup/hooks/useServiceDetection';
import { useVaultMutate } from '@/entrypoints/popup/hooks/useVaultMutate';
import { SKIP_FORM_RESTORE_KEY } from '@/utils/Constants';
import type { Item, ItemField, ItemType, FieldType, Attachment, TotpCode } from '@/utils/dist/core/models/vault';
import type { Item, ItemField, ItemType, FieldType, Attachment, TotpCode, PasswordSettings } from '@/utils/dist/core/models/vault';
import { FieldCategories, FieldTypes, ItemTypes, getSystemFieldsForItemType, getOptionalFieldsForItemType, isFieldShownByDefault, getSystemField, fieldAppliesToType } from '@/utils/dist/core/models/vault';
import { FaviconService } from '@/utils/FaviconService';
@@ -71,6 +71,7 @@ type PersistedFormData = {
showAttachments: boolean;
manuallyAddedFields: string[];
isLoginEmailInEmailMode?: boolean;
passwordSettings?: PasswordSettings;
};
/**
@@ -152,6 +153,9 @@ const ItemAddEdit: React.FC = () => {
// Track email field mode for Login type (true = free text "Email", false = domain chooser "Alias")
const [isLoginEmailInEmailMode, setIsLoginEmailInEmailMode] = useState(true);
// Track password settings for persistence (so slider position and options are remembered)
const [passwordSettings, setPasswordSettings] = useState<PasswordSettings | undefined>(undefined);
// Track whether to skip form restoration (set during initialization)
const [skipFormRestore] = useState(false);
@@ -184,6 +188,9 @@ const ItemAddEdit: React.FC = () => {
if (data.isLoginEmailInEmailMode !== undefined) {
setIsLoginEmailInEmailMode(data.isLoginEmailInEmailMode);
}
if (data.passwordSettings !== undefined) {
setPasswordSettings(data.passwordSettings);
}
}, []);
/**
@@ -202,6 +209,7 @@ const ItemAddEdit: React.FC = () => {
showAttachments,
manuallyAddedFields: Array.from(manuallyAddedFields),
isLoginEmailInEmailMode,
passwordSettings,
},
onRestore: handleFormRestore,
skipRestore: skipFormRestore,
@@ -1026,6 +1034,8 @@ const ItemAddEdit: React.FC = () => {
onChange={(val) => handleFieldChange(fieldKey, val)}
showPassword={showPassword}
onShowPasswordChange={setShowPassword}
initialSettings={passwordSettings}
onSettingsChange={setPasswordSettings}
/>
);
@@ -1103,7 +1113,7 @@ const ItemAddEdit: React.FC = () => {
);
}
}, [fieldValues, handleFieldChange, showPassword, t, handleGenerateAliasEmail, aliasFieldsShownByDefault, generateRandomUsername, isLoginEmailInEmailMode]);
}, [fieldValues, handleFieldChange, showPassword, t, handleGenerateAliasEmail, aliasFieldsShownByDefault, generateRandomUsername, isLoginEmailInEmailMode, passwordSettings]);
/**
* Handle form submission via Enter key.