Merge branch 'main' into 1548-add-support-to-block-specific-unsupported-client-versions-in-server-api

This commit is contained in:
Leendert de Borst
2026-01-31 15:57:06 +00:00
committed by GitHub
4 changed files with 77 additions and 20 deletions
@@ -308,8 +308,20 @@ export class FormFiller {
* @param securityResults Security validation results for each field.
*/
private async fillBasicFields(credential: Credential, securityResults: Map<HTMLElement, boolean>): Promise<void> {
if (this.form.usernameField && credential.Username && securityResults.get(this.form.usernameField) !== false) {
await this.fillTextFieldWithTyping(this.form.usernameField, credential.Username);
if (this.form.usernameField && securityResults.get(this.form.usernameField) !== false) {
if (credential.Username) {
await this.fillTextFieldWithTyping(this.form.usernameField, credential.Username);
} else if (credential.Alias?.Email && !this.form.emailField) {
/*
* If current form has no email field AND the credential has an email
* then we can assume the email should be used as the username.
*
* This applies to the usecase where the credential only has email/password
* (no explicit username) and the login form uses a username field for the
* email/login identifier.
*/
await this.fillTextFieldWithTyping(this.form.usernameField, credential.Alias.Email);
}
}
if (this.form.emailField && (credential.Alias?.Email !== undefined || credential.Username !== undefined) && securityResults.get(this.form.emailField) !== false) {
+5 -4
View File
@@ -3,6 +3,7 @@ import { Alert, Platform } from 'react-native';
import { ConfirmDialog, type IConfirmDialogButton } from '@/components/common/ConfirmDialog';
import { dialogEventEmitter } from '@/events/DialogEventEmitter';
import i18n from '@/i18n';
interface DialogConfig {
title: string;
@@ -138,7 +139,7 @@ export function DialogProvider({ children }: DialogProviderProps): React.ReactNo
// On iOS, use native Alert
if (Platform.OS === 'ios') {
Alert.alert(title, message, [{
text: 'OK',
text: i18n.t('common.ok'),
style: 'default',
onPress: onOk,
}]);
@@ -150,7 +151,7 @@ export function DialogProvider({ children }: DialogProviderProps): React.ReactNo
title,
message,
buttons: [{
text: 'OK',
text: i18n.t('common.ok'),
style: 'default',
onPress: (): void => {
onOk?.();
@@ -181,7 +182,7 @@ export function DialogProvider({ children }: DialogProviderProps): React.ReactNo
// On iOS, use native Alert
if (Platform.OS === 'ios') {
Alert.alert(title, message, [
{ text: options?.cancelText ?? 'Cancel', style: 'cancel' },
{ text: options?.cancelText ?? i18n.t('common.cancel'), style: 'cancel' },
{
text: confirmText,
style: options?.confirmStyle ?? 'default',
@@ -196,7 +197,7 @@ export function DialogProvider({ children }: DialogProviderProps): React.ReactNo
message,
buttons: [
{
text: options?.cancelText ?? 'Cancel',
text: options?.cancelText ?? i18n.t('common.cancel'),
style: 'cancel',
onPress: (): void => setDialogConfig(null),
},
@@ -89,25 +89,25 @@
@if (DuplicateCredentialsCount > 0)
{
<div class="p-4 mb-4 text-blue-700 bg-blue-100 rounded-lg dark:bg-blue-800/30 dark:text-blue-300" role="alert">
<p>@DuplicateCredentialsCount duplicate credential(s) were found and will not be imported.</p>
<p>@string.Format(Localizer["DuplicateCredentialsWarning"], DuplicateCredentialsCount)</p>
</div>
}
@if (ImportedCredentials.Count == 0)
{
<div class="p-4 mb-4 text-amber-700 bg-amber-100 rounded-lg dark:bg-amber-800/30 dark:text-amber-300" role="alert">
<p>No new credentials were found to import.</p>
<p>@Localizer["NoNewCredentials"]</p>
</div>
}
else
{
<p class="mb-4 text-gray-700 dark:text-gray-300">Check if the following detected credentials look correct before continuing:</p>
<p class="mb-4 text-gray-700 dark:text-gray-300">@Localizer["PreviewInstructions"]</p>
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Service</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Username</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Password</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">@Localizer["ServiceColumn"]</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">@Localizer["UsernameColumn"]</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">@Localizer["PasswordColumn"]</th>
</tr>
</thead>
<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
@@ -123,7 +123,7 @@
</table>
@if (ImportedCredentials.Count > 3)
{
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">... and @(ImportedCredentials.Count - 3) more credentials</p>
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">@string.Format(Localizer["MoreCredentials"], ImportedCredentials.Count - 3)</p>
}
}
</div>
@@ -132,7 +132,7 @@
<div class="mb-4 space-y-2">
<label class="flex items-center">
<input type="checkbox" @bind="ExtractFavicons" class="form-checkbox h-4 w-4 text-primary-600 rounded border-gray-300 dark:border-gray-600 dark:bg-gray-700">
<span class="ml-2 text-gray-700 dark:text-gray-300">Extract favicons for services with URLs</span>
<span class="ml-2 text-gray-700 dark:text-gray-300">@Localizer["ExtractFaviconsLabel"]</span>
</label>
@if (DetectedFolderCount > 0)
{
@@ -145,7 +145,7 @@
</div>
}
<div class="flex justify-end mt-6 space-x-2">
<Button OnClick="@HandlePreviousStep" Color="secondary">Back</Button>
<Button OnClick="@HandlePreviousStep" Color="secondary">@Localizer["BackButton"]</Button>
@if (ImportedCredentials.Count > 0)
{
<Button OnClick="@HandleNextStep" Color="primary">@Localizer["NextButton"]</Button>
@@ -161,9 +161,9 @@
{
<div class="text-center">
<LoadingIndicator />
<p class="mt-4 text-gray-700 dark:text-gray-300">Extracting favicons... @(FaviconExtractionProgress) / @(TotalFaviconsToExtract)</p>
<p class="mt-4 text-gray-700 dark:text-gray-300">@string.Format(Localizer["ExtractingFavicons"], FaviconExtractionProgress, TotalFaviconsToExtract)</p>
<div class="mt-4">
<Button OnClick="@CancelFaviconExtraction" Color="secondary">Cancel</Button>
<Button OnClick="@CancelFaviconExtraction" Color="secondary">@Localizer["CancelButton"]</Button>
</div>
</div>
}
@@ -174,11 +174,11 @@
}
else {
<div class="mb-4">
<p class="mb-4 text-gray-700 dark:text-gray-300">Are you sure you want to import (@ImportedCredentials.Count) credentials? Note: the import process can take a short while.</p>
<p class="mb-4 text-gray-700 dark:text-gray-300">@string.Format(Localizer["ConfirmImportText"], ImportedCredentials.Count)</p>
@if (ExtractFavicons)
{
<div class="p-4 mb-4 text-amber-700 bg-amber-100 rounded-lg dark:bg-amber-800/30 dark:text-amber-300" role="alert">
<p>Note: Favicon extraction is enabled. This process can take several minutes depending on the number of credentials with URLs. Please keep the page open.</p>
<p>@Localizer["FaviconExtractionNote"]</p>
</div>
}
</div>
@@ -87,11 +87,55 @@
<comment>Import button text</comment>
</data>
<data name="ImportFoldersLabel" xml:space="preserve">
<value>Import folders (if available)</value>
<value>Import folders</value>
<comment>Checkbox label for importing folder structure from the source password manager</comment>
</data>
<data name="FoldersDetected" xml:space="preserve">
<value>{0} folder(s) detected</value>
<comment>Info text showing number of folders detected in the import. {0} is the count</comment>
</data>
<data name="DuplicateCredentialsWarning" xml:space="preserve">
<value>{0} duplicate credential(s) were found and will not be imported.</value>
<comment>Warning text when duplicate credentials are detected. {0} is the count</comment>
</data>
<data name="NoNewCredentials" xml:space="preserve">
<value>No new credentials were found to import.</value>
<comment>Warning text when no new credentials are available for import</comment>
</data>
<data name="PreviewInstructions" xml:space="preserve">
<value>Check if the following detected credentials look correct before continuing:</value>
<comment>Instructions shown before the credential preview table</comment>
</data>
<data name="ServiceColumn" xml:space="preserve">
<value>Service</value>
<comment>Column header for service name in credential preview table</comment>
</data>
<data name="UsernameColumn" xml:space="preserve">
<value>Username</value>
<comment>Column header for username in credential preview table</comment>
</data>
<data name="PasswordColumn" xml:space="preserve">
<value>Password</value>
<comment>Column header for password in credential preview table</comment>
</data>
<data name="MoreCredentials" xml:space="preserve">
<value>... and {0} more credentials</value>
<comment>Text showing additional credentials not displayed. {0} is the count</comment>
</data>
<data name="ExtractFaviconsLabel" xml:space="preserve">
<value>Extract favicons for services with URLs</value>
<comment>Checkbox label for favicon extraction option</comment>
</data>
<data name="ConfirmImportText" xml:space="preserve">
<value>Are you sure you want to import ({0}) credentials? Note: the import process can take a short while.</value>
<comment>Confirmation text before importing. {0} is the credential count</comment>
</data>
<data name="FaviconExtractionNote" xml:space="preserve">
<value>Note: Favicon extraction is enabled. This process can take several minutes depending on the number of credentials with URLs. Please keep the page open.</value>
<comment>Warning note about favicon extraction duration</comment>
</data>
<data name="ExtractingFavicons" xml:space="preserve">
<value>Extracting favicons... {0} / {1}</value>
<comment>Progress text during favicon extraction. {0} is current progress, {1} is total</comment>
</data>
</root>