mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 00:03:56 +00:00
Merge branch 'master' into patrickhlauke-a11y-patch2
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -151,7 +151,7 @@
|
||||
"message": "Захаваць"
|
||||
},
|
||||
"move": {
|
||||
"message": "Move"
|
||||
"message": "Перамясціць"
|
||||
},
|
||||
"addFolder": {
|
||||
"message": "Дадаць папку"
|
||||
@@ -600,7 +600,7 @@
|
||||
"description": "Light color"
|
||||
},
|
||||
"solarizedDark": {
|
||||
"message": "Solarized Dark",
|
||||
"message": "Цёмная Solarized",
|
||||
"description": "'Solarized' is a noun and the name of a color scheme. It should not be translated."
|
||||
},
|
||||
"exportVault": {
|
||||
@@ -614,7 +614,7 @@
|
||||
"description": "WARNING (should stay in capitalized letters if the language permits)"
|
||||
},
|
||||
"confirmVaultExport": {
|
||||
"message": "Confirm Vault Export"
|
||||
"message": "Пацвердзіць экспарт сховішча"
|
||||
},
|
||||
"exportWarningDesc": {
|
||||
"message": "Экспартуемы файл утрымлівае даныя вашага сховішча ў незашыфраваным фармаце. Яго не варта захоўваць ці адпраўляць па небяспечным каналам (напрыклад, па электроннай пошце). Выдаліце яго адразу пасля выкарыстання."
|
||||
|
||||
@@ -623,7 +623,7 @@
|
||||
"message": "Tento export zašifruje vaše data pomocí šifrovacího klíče vašeho účtu. Pokud někdy změníte šifrovací klíč vašeho účtu, měli by jste vyexportovat data znovu, protože tento exportovaný soubor nebudete moci dešifrovat."
|
||||
},
|
||||
"encExportAccountWarningDesc": {
|
||||
"message": "Šifrovací klíče účtu jsou pro každý uživatelský účet Bitwarden jedinečné, tudíž nelze importovat šifrovaný export do jiného účtu."
|
||||
"message": "Šifrovací klíče účtu jsou pro každý uživatelský účet Bitwarden jedinečné, takže nelze importovat šifrovaný export do jiného účtu."
|
||||
},
|
||||
"exportMasterPassword": {
|
||||
"message": "Zadejte své hlavní heslo pro export dat."
|
||||
@@ -1492,7 +1492,7 @@
|
||||
"message": "Biometrie v prohlížeči není na tomto zařízení podporována."
|
||||
},
|
||||
"nativeMessaginPermissionErrorTitle": {
|
||||
"message": "Povolení nebylo poskytnuto"
|
||||
"message": "Oprávnění nebylo uděleno"
|
||||
},
|
||||
"nativeMessaginPermissionErrorDesc": {
|
||||
"message": "Bez oprávnění ke komunikaci s počítačovou aplikací Bitwarden nelze v rozšíření prohlížeče používat biometrické údaje. Zkuste to prosím znovu."
|
||||
@@ -1543,7 +1543,7 @@
|
||||
"message": "Soubor"
|
||||
},
|
||||
"allSends": {
|
||||
"message": "Všechny Sendy",
|
||||
"message": "Všechny Sends",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"maxAccessCountReached": {
|
||||
@@ -1583,7 +1583,7 @@
|
||||
"message": "Zakázáno"
|
||||
},
|
||||
"removePasswordConfirmation": {
|
||||
"message": "Jste si jisti, že chcete heslo odstranit?"
|
||||
"message": "Jste si jisti, že chcete odstranit heslo?"
|
||||
},
|
||||
"deleteSend": {
|
||||
"message": "Smazat Send",
|
||||
@@ -1616,7 +1616,7 @@
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"expirationDate": {
|
||||
"message": "Datum expirace"
|
||||
"message": "Datum vypršení platnosti"
|
||||
},
|
||||
"expirationDateDesc": {
|
||||
"message": "Je-li nastaveno, přístup k tomuto Send vyprší v daný datum a čas.",
|
||||
@@ -1664,7 +1664,7 @@
|
||||
"message": "Text, který chcete odeslat."
|
||||
},
|
||||
"sendHideText": {
|
||||
"message": "Skrýt ve výchozím stavu obsah tohoto Sendu.",
|
||||
"message": "Skrýt ve výchozím stavu text tohoto Send.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"currentAccessCount": {
|
||||
@@ -1724,10 +1724,10 @@
|
||||
"message": "Uvedené datum odstranění není platné."
|
||||
},
|
||||
"expirationDateAndTimeRequired": {
|
||||
"message": "Je vyžadováno datum a čas vypršení platnosti."
|
||||
"message": "Je vyžadován datum a čas vypršení platnosti."
|
||||
},
|
||||
"deletionDateAndTimeRequired": {
|
||||
"message": "Je vyžadováno datum a čas odstranění."
|
||||
"message": "Je vyžadován datum a čas odstranění."
|
||||
},
|
||||
"dateParsingError": {
|
||||
"message": "Došlo k chybě při ukládání data odstranění a vypršení platnosti."
|
||||
|
||||
@@ -816,7 +816,7 @@
|
||||
"message": "Stecke deinen Sicherheitsschlüssel in den USB-Port deines Computers. Falls ein Knopf vorhanden ist, berühre diesen."
|
||||
},
|
||||
"webAuthnNewTab": {
|
||||
"message": "Fahre mit der WebAuthn 2FA Verifizierung im neuen Tab fort."
|
||||
"message": "Um die WebAuthn 2FA Verifizierung zu starten, klicke auf die Schaltfläche unten, um einen neuen Tab zu öffnen und folge den Anweisungen, die im neuen Tab angezeigt werden."
|
||||
},
|
||||
"webAuthnNewTabOpen": {
|
||||
"message": "Neuen Tab öffnen"
|
||||
@@ -909,7 +909,7 @@
|
||||
"message": "Die URLs der Umgebung wurden gespeichert."
|
||||
},
|
||||
"enableAutoFillOnPageLoad": {
|
||||
"message": "Aktiviere automatisches Ausfüllen beim Laden der Seite"
|
||||
"message": "Auto-Ausfüllen beim Seitenladen aktivieren"
|
||||
},
|
||||
"enableAutoFillOnPageLoadDesc": {
|
||||
"message": "Wenn eine Zugangsmaske erkannt wird, füge automatisch die Zugangsdaten ein während die Webseite lädt."
|
||||
|
||||
@@ -88,6 +88,9 @@
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate Password (copied)"
|
||||
},
|
||||
"copyElementIdentifier": {
|
||||
"message": "Copy Custom Field Name"
|
||||
},
|
||||
"noMatchingLogins": {
|
||||
"message": "No matching logins."
|
||||
},
|
||||
@@ -773,6 +776,9 @@
|
||||
"disableAutoTotpCopyDesc": {
|
||||
"message": "If your login has an authenticator key attached to it, the TOTP verification code is automatically copied to your clipboard whenever you auto-fill the login."
|
||||
},
|
||||
"disableAutoBiometricsPrompt": {
|
||||
"message": "Do not prompt for biometrics on launch"
|
||||
},
|
||||
"premiumRequired": {
|
||||
"message": "Premium Required"
|
||||
},
|
||||
@@ -1752,5 +1758,54 @@
|
||||
},
|
||||
"emailVerificationRequiredDesc": {
|
||||
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
|
||||
},
|
||||
"updatedMasterPassword": {
|
||||
"message": "Updated Master Password"
|
||||
},
|
||||
"updateMasterPassword": {
|
||||
"message": "Update Master Password"
|
||||
},
|
||||
"updateMasterPasswordWarning": {
|
||||
"message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour."
|
||||
},
|
||||
"resetPasswordPolicyAutoEnroll": {
|
||||
"message": "Automatic Enrollment"
|
||||
},
|
||||
"resetPasswordAutoEnrollInviteWarning": {
|
||||
"message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password."
|
||||
},
|
||||
"selectFolder": {
|
||||
"message": "Select folder..."
|
||||
},
|
||||
"ssoCompleteRegistration": {
|
||||
"message": "In order to complete logging in with SSO, please set a master password to access and protect your vault."
|
||||
},
|
||||
"hours": {
|
||||
"message": "Hours"
|
||||
},
|
||||
"minutes": {
|
||||
"message": "Minutes"
|
||||
},
|
||||
"vaultTimeoutPolicyInEffect": {
|
||||
"message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)",
|
||||
"placeholders": {
|
||||
"hours": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
},
|
||||
"minutes": {
|
||||
"content": "$2",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"vaultTimeoutToLarge": {
|
||||
"message": "Your vault timeout exceeds the restrictions set by your organization."
|
||||
},
|
||||
"vaultExportDisabled": {
|
||||
"message": "Vault Export Disabled"
|
||||
},
|
||||
"personalVaultExportPolicyInEffect": {
|
||||
"message": "One or more organization policies prevents you from exporting your personal vault."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
"message": "Guardar"
|
||||
},
|
||||
"move": {
|
||||
"message": "Move"
|
||||
"message": "Mover"
|
||||
},
|
||||
"addFolder": {
|
||||
"message": "Añadir carpeta"
|
||||
@@ -632,19 +632,19 @@
|
||||
"message": "Compartido"
|
||||
},
|
||||
"learnOrg": {
|
||||
"message": "Learn about Organizations"
|
||||
"message": "Aprende sobre Organizaciones"
|
||||
},
|
||||
"learnOrgConfirmation": {
|
||||
"message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?"
|
||||
"message": "Bitwarden te permite compartir tus objetos de bóveda con otros usando una organización. ¿Quieres visitar el sitio web de bitwarden.com para saber más?"
|
||||
},
|
||||
"moveToOrganization": {
|
||||
"message": "Move to Organization"
|
||||
"message": "Mover a la Organización"
|
||||
},
|
||||
"share": {
|
||||
"message": "Compartir"
|
||||
},
|
||||
"movedItemToOrg": {
|
||||
"message": "$ITEMNAME$ moved to $ORGNAME$",
|
||||
"message": "$ITEMNAME$ se desplazó a $ORGNAME$",
|
||||
"placeholders": {
|
||||
"itemname": {
|
||||
"content": "$1",
|
||||
@@ -657,7 +657,7 @@
|
||||
}
|
||||
},
|
||||
"moveToOrgDesc": {
|
||||
"message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved."
|
||||
"message": "Elige una organización a la que deseas mover este objeto. Moviendo a una organización transfiere la propiedad del objeto a esa organización. Ya no serás el dueño directo de este objeto una vez que haya sido movido."
|
||||
},
|
||||
"learnMore": {
|
||||
"message": "Más información"
|
||||
@@ -816,13 +816,13 @@
|
||||
"message": "Inserta tu llave de seguridad en el puerto USB de tu equipo. Si tiene un botón, púlsalo."
|
||||
},
|
||||
"webAuthnNewTab": {
|
||||
"message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab."
|
||||
"message": "Para iniciar la verificación de WebAuthn 2FA. Haga clic en el botón de abajo para abrir una nueva pestaña y siga las instrucciones proporcionadas en la nueva pestaña."
|
||||
},
|
||||
"webAuthnNewTabOpen": {
|
||||
"message": "Open new tab"
|
||||
"message": "Abrir nueva pestaña"
|
||||
},
|
||||
"webAuthnAuthenticate": {
|
||||
"message": "Authenticate WebAuthn"
|
||||
"message": "Autenticar WebAuthn"
|
||||
},
|
||||
"loginUnavailable": {
|
||||
"message": "Entrada no disponible"
|
||||
@@ -867,7 +867,7 @@
|
||||
"message": "FIDO2 WebAuthn"
|
||||
},
|
||||
"webAuthnDesc": {
|
||||
"message": "Use any WebAuthn enabled security key to access your account."
|
||||
"message": "Utilice cualquier clave de seguridad WebAuthn habilitada para acceder a su cuenta."
|
||||
},
|
||||
"emailTitle": {
|
||||
"message": "Correo electrónico"
|
||||
@@ -918,22 +918,22 @@
|
||||
"message": "Esta es una característica experimental. Úsala bajo tu propio riesgo."
|
||||
},
|
||||
"defaultAutoFillOnPageLoad": {
|
||||
"message": "Default autofill setting for login items"
|
||||
"message": "Configuración de autorrelleno por defecto para elementos de inicio de sesión"
|
||||
},
|
||||
"defaultAutoFillOnPageLoadDesc": {
|
||||
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
|
||||
"message": "Después de activar el autorelleno en Carga de página, puede activar o desactivar la función para entradas individuales. Esta es la configuración predeterminada para elementos de inicio de sesión que no están configurados por separado."
|
||||
},
|
||||
"itemAutoFillOnPageLoad": {
|
||||
"message": "Auto-fill on Page Load (if enabled in Options)"
|
||||
"message": "Auto-relleno en carga de página (si está habilitado en opciones)"
|
||||
},
|
||||
"autoFillOnPageLoadUseDefault": {
|
||||
"message": "Use default setting"
|
||||
"message": "Usar configuración predeterminada"
|
||||
},
|
||||
"autoFillOnPageLoadYes": {
|
||||
"message": "Auto-fill on page load"
|
||||
"message": "Autocompletar al cargar la página"
|
||||
},
|
||||
"autoFillOnPageLoadNo": {
|
||||
"message": "Do not auto-fill on page load"
|
||||
"message": "No rellenar automáticamente al cargar la página"
|
||||
},
|
||||
"commandOpenPopup": {
|
||||
"message": "Abrir ventana emergente de la caja fuerte"
|
||||
@@ -990,10 +990,10 @@
|
||||
"message": "Los iconos del sitio web añaden una imagen reconocible al lado de cada entrada de tu caja fuerte."
|
||||
},
|
||||
"disableBadgeCounter": {
|
||||
"message": "Disable Badge Counter"
|
||||
"message": "Desactivar contador de insignias"
|
||||
},
|
||||
"disableBadgeCounterDesc": {
|
||||
"message": "Badge counter indicates how many logins you have for the current page in your vault."
|
||||
"message": "El contador de insinuaciones indica cuántos registros tienes para la página actual en tu bóveda."
|
||||
},
|
||||
"cardholderName": {
|
||||
"message": "Nombre en la tarjeta"
|
||||
@@ -1657,7 +1657,7 @@
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"sendShareDesc": {
|
||||
"message": "Copy this Send's link to clipboard upon save.",
|
||||
"message": "Copiar el enlace del Send en el portapapeles al guardar.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"sendTextDesc": {
|
||||
@@ -1668,7 +1668,7 @@
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"currentAccessCount": {
|
||||
"message": "Current Access Count"
|
||||
"message": "Número de acceso actual"
|
||||
},
|
||||
"createSend": {
|
||||
"message": "Crear Envío nuevo",
|
||||
@@ -1682,7 +1682,7 @@
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"sendDisabledWarning": {
|
||||
"message": "Due to an enterprise policy, you are only able to delete an existing Send.",
|
||||
"message": "Debido a una política empresarial, sólo puede eliminar el existente Send",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"createdSend": {
|
||||
@@ -1694,19 +1694,19 @@
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"sendLinuxChromiumFileWarning": {
|
||||
"message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner."
|
||||
"message": "Para elegir un archivo, abra la extensión en la barra lateral (si es posible) o salga a una nueva ventana haciendo clic en este anouncio."
|
||||
},
|
||||
"sendFirefoxFileWarning": {
|
||||
"message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner."
|
||||
"message": "Para elegir un archivo usando Firefox, abra la extensión en la barra lateral o salga a una nueva ventana haciendo clic en este anouncio."
|
||||
},
|
||||
"sendSafariFileWarning": {
|
||||
"message": "In order to choose a file using Safari, pop out to a new window by clicking this banner."
|
||||
"message": "Para elegir un archivo usando Safari, salga a una nueva ventana haciendo clic en este anouncio."
|
||||
},
|
||||
"sendFileCalloutHeader": {
|
||||
"message": "Before you start"
|
||||
"message": "Antes de empezar"
|
||||
},
|
||||
"sendFirefoxCustomDatePopoutMessage1": {
|
||||
"message": "To use a calendar style date picker",
|
||||
"message": "Para usar un selector de fechas de estilo calendario",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'"
|
||||
},
|
||||
"sendFirefoxCustomDatePopoutMessage2": {
|
||||
@@ -1714,43 +1714,43 @@
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'"
|
||||
},
|
||||
"sendFirefoxCustomDatePopoutMessage3": {
|
||||
"message": "to pop out your window.",
|
||||
"message": "para abrir la ventana.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'"
|
||||
},
|
||||
"expirationDateIsInvalid": {
|
||||
"message": "The expiration date provided is not valid."
|
||||
"message": "La fecha de caducidad proporcionada no es válida."
|
||||
},
|
||||
"deletionDateIsInvalid": {
|
||||
"message": "The deletion date provided is not valid."
|
||||
"message": "La fecha de eliminación proporcionada no es válida."
|
||||
},
|
||||
"expirationDateAndTimeRequired": {
|
||||
"message": "An expiration date and time are required."
|
||||
"message": "Se requiere una fecha y hora de caducidad."
|
||||
},
|
||||
"deletionDateAndTimeRequired": {
|
||||
"message": "A deletion date and time are required."
|
||||
"message": "Se requiere una fecha y hora de eliminación."
|
||||
},
|
||||
"dateParsingError": {
|
||||
"message": "There was an error saving your deletion and expiration dates."
|
||||
"message": "Hubo un error al guardar las fechas de eliminación y caducidad."
|
||||
},
|
||||
"hideEmail": {
|
||||
"message": "Hide my email address from recipients."
|
||||
"message": "Ocultar mi dirección de correo electrónico a los destinatarios."
|
||||
},
|
||||
"sendOptionsPolicyInEffect": {
|
||||
"message": "One or more organization policies are affecting your Send options."
|
||||
"message": "Una o más políticas de organización están afectando sus opciones del Send."
|
||||
},
|
||||
"passwordPrompt": {
|
||||
"message": "Master password re-prompt"
|
||||
"message": "Volver a preguntar contraseña maestra"
|
||||
},
|
||||
"passwordConfirmation": {
|
||||
"message": "Master password confirmation"
|
||||
"message": "Confirmación de contraseña maestra"
|
||||
},
|
||||
"passwordConfirmationDesc": {
|
||||
"message": "This action is protected. To continue, please re-enter your master password to verify your identity."
|
||||
"message": "Esta acción está protegida. Para continuar, vuelva a introducir su contraseña maestra para verificar su identidad."
|
||||
},
|
||||
"emailVerificationRequired": {
|
||||
"message": "Email Verification Required"
|
||||
"message": "Verificación de correo electrónico requerida"
|
||||
},
|
||||
"emailVerificationRequiredDesc": {
|
||||
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
|
||||
"message": "Debes verificar tu correo electrónico para usar esta función. Puedes verificar tu correo electrónico en la bóveda web."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,10 +526,10 @@
|
||||
"description": "This is the folder for uncategorized items"
|
||||
},
|
||||
"disableAddLoginNotification": {
|
||||
"message": "Keela \"Lisa konto andmed\" märguanne"
|
||||
"message": "Keela \"Lisa konto andmed\" teavitus"
|
||||
},
|
||||
"addLoginNotificationDesc": {
|
||||
"message": "\"Lisa konto andmed\" märguanne ilmub pärast esimest sisselogimist ning võimaldab Sul kontoandmeid automaatselt Bitwardenisse lisada."
|
||||
"message": "\"Lisa konto andmed\" teavitus ilmub pärast esimest sisselogimist ning võimaldab kontoandmeid automaatselt Bitwardenisse lisada."
|
||||
},
|
||||
"dontShowCardsCurrentTab": {
|
||||
"message": "Ära kuva \"Kaart\" vaates krediitkaardi andmeid"
|
||||
@@ -564,7 +564,7 @@
|
||||
"message": "Keela Muudetud parooli teavitus"
|
||||
},
|
||||
"disableChangedPasswordNotificationDesc": {
|
||||
"message": "Kui mistahes veebilehel on toimunud parooli vahetamine, annab \"Muudetud parooli teavitus\" sulle märku, et vahetaksid selle ära ka Bitwardeni paroolihoidlas."
|
||||
"message": "Kui mistahes veebilehel on toimunud parooli vahetamine, annab \"Muudetud parooli teavitus\" märku, et värskendaksid seda ka Bitwardeni paroolihoidlas."
|
||||
},
|
||||
"notificationChangeDesc": {
|
||||
"message": "Soovid seda parooli ka Bitwardenis uuendada?"
|
||||
@@ -837,7 +837,7 @@
|
||||
"message": "Kaheastmelise sisselogimise valikud"
|
||||
},
|
||||
"recoveryCodeDesc": {
|
||||
"message": "Sul ei ole ligipääsu ühelegi kaheastmelise kinnitamise teenusele? Kasuta Taastamise koodi, et kaheastmeline kinnitamine oma kontol välja lülitada."
|
||||
"message": "Puudub ligipääs kaheastmelise kinnitamise teenusele? Kasuta Taastamise koodi, et kaheastmeline kinnitamine oma kontol välja lülitada."
|
||||
},
|
||||
"recoveryCodeTitle": {
|
||||
"message": "Taastamise kood"
|
||||
@@ -933,7 +933,7 @@
|
||||
"message": "Täida kontoandmed lehe laadimisel"
|
||||
},
|
||||
"autoFillOnPageLoadNo": {
|
||||
"message": "Ära täida kontoandmed lehe laadimisel"
|
||||
"message": "Ära täida kontoandmeid lehe laadimisel"
|
||||
},
|
||||
"commandOpenPopup": {
|
||||
"message": "Ava hoidla uues aknas"
|
||||
|
||||
@@ -1609,14 +1609,14 @@
|
||||
"message": "Tiedosto, jonka haluat lähettää."
|
||||
},
|
||||
"deletionDate": {
|
||||
"message": "Poistopäivä"
|
||||
"message": "Poistoajankohta"
|
||||
},
|
||||
"deletionDateDesc": {
|
||||
"message": "Send poistetaan pysyvästi määritettynä ajankohtana.",
|
||||
"message": "Send poistuu pysyvästi määritettynä ajankohtana.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"expirationDate": {
|
||||
"message": "Erääntymispäivä"
|
||||
"message": "Erääntymisajankohta"
|
||||
},
|
||||
"expirationDateDesc": {
|
||||
"message": "Jos määritetty, Send erääntyy määritettynä ajankohtana.",
|
||||
@@ -1718,19 +1718,19 @@
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'"
|
||||
},
|
||||
"expirationDateIsInvalid": {
|
||||
"message": "Asetettu erääntymismispäivä on virheellinen."
|
||||
"message": "Määritetty erääntymismisajankohta on virheellinen."
|
||||
},
|
||||
"deletionDateIsInvalid": {
|
||||
"message": "Asetettu poistopäivä on virheellinen."
|
||||
"message": "Määritetty poistoajankohta on virheellinen."
|
||||
},
|
||||
"expirationDateAndTimeRequired": {
|
||||
"message": "Viimeinen voimassaolopäivä ja aika vaaditaan."
|
||||
"message": "Erääntymispäivä ja -aika vaaditaan."
|
||||
},
|
||||
"deletionDateAndTimeRequired": {
|
||||
"message": "Poistopäivä ja -aika vaaditaan."
|
||||
},
|
||||
"dateParsingError": {
|
||||
"message": "Tapahtui virhe tallennettaessa poisto- ja erääntymispäiviä."
|
||||
"message": "Tapahtui virhe tallennettaessa poisto- ja erääntymisajankohtia."
|
||||
},
|
||||
"hideEmail": {
|
||||
"message": "Piilota sähköpostiosoitteeni vastaanottajilta."
|
||||
|
||||
1756
src/_locales/fil/messages.json
Normal file
1756
src/_locales/fil/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -151,7 +151,7 @@
|
||||
"message": "Enregistrer"
|
||||
},
|
||||
"move": {
|
||||
"message": "Move"
|
||||
"message": "Se déplacer"
|
||||
},
|
||||
"addFolder": {
|
||||
"message": "Ajouter un dossier"
|
||||
@@ -632,19 +632,19 @@
|
||||
"message": "Partagé"
|
||||
},
|
||||
"learnOrg": {
|
||||
"message": "Learn about Organizations"
|
||||
"message": "En savoir plus sur les organisations"
|
||||
},
|
||||
"learnOrgConfirmation": {
|
||||
"message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?"
|
||||
"message": "Bitwarden vous permet de partager des éléments de votre coffre avec d'autres personnes en utilisant un compte d'organisation. Souhaitez-vous visiter le site web bitwarden.com pour en savoir plus ?"
|
||||
},
|
||||
"moveToOrganization": {
|
||||
"message": "Move to Organization"
|
||||
"message": "Déplacer vers l'organisation"
|
||||
},
|
||||
"share": {
|
||||
"message": "Partager"
|
||||
},
|
||||
"movedItemToOrg": {
|
||||
"message": "$ITEMNAME$ moved to $ORGNAME$",
|
||||
"message": "$ITEMNAME$ a été déplacé vers $ORGNAME$",
|
||||
"placeholders": {
|
||||
"itemname": {
|
||||
"content": "$1",
|
||||
@@ -657,7 +657,7 @@
|
||||
}
|
||||
},
|
||||
"moveToOrgDesc": {
|
||||
"message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved."
|
||||
"message": "Choisissez une organisation vers laquelle vous souhaitez déplacer cet élément. Déplacer un élément vers une organisation transfère la propriété de l'élément à cette organisation. Vous ne serez plus le propriétaire direct de cet élément une fois qu'il aura été déplacé."
|
||||
},
|
||||
"learnMore": {
|
||||
"message": "En savoir plus"
|
||||
@@ -816,10 +816,10 @@
|
||||
"message": "Insérez votre clé de sécurité dans le port USB de votre ordinateur. S'il dispose d'un bouton, appuyez dessus."
|
||||
},
|
||||
"webAuthnNewTab": {
|
||||
"message": "Poursuivez la vérification 2FA WebAuthn dans le nouvel onglet."
|
||||
"message": "Pour démarrer la vérification 2FA WebAuthn, cliquez sur le bouton ci-dessous et suivez les instructions dans le nouvel onglet."
|
||||
},
|
||||
"webAuthnNewTabOpen": {
|
||||
"message": "Open new tab"
|
||||
"message": "Ouvrir un nouvel onglet"
|
||||
},
|
||||
"webAuthnAuthenticate": {
|
||||
"message": "Authentifier WebAuthn"
|
||||
@@ -909,7 +909,7 @@
|
||||
"message": "Les URLs d'environnement ont été enregistrées."
|
||||
},
|
||||
"enableAutoFillOnPageLoad": {
|
||||
"message": "Activer l’auto-complétion au chargement de la page"
|
||||
"message": "Activer le remplissage automatique au chargement de la page"
|
||||
},
|
||||
"enableAutoFillOnPageLoadDesc": {
|
||||
"message": "Si un formulaire de connexion est détecté, remplir automatiquement les champs au chargement de la page web."
|
||||
@@ -918,22 +918,22 @@
|
||||
"message": "Ceci est actuellement une fonctionnalité expérimentale. À utiliser avec prudence."
|
||||
},
|
||||
"defaultAutoFillOnPageLoad": {
|
||||
"message": "Default autofill setting for login items"
|
||||
"message": "Paramètre de saisie automatique par défaut pour les identifiants"
|
||||
},
|
||||
"defaultAutoFillOnPageLoadDesc": {
|
||||
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
|
||||
"message": "Après avoir activé le remplissage automatique au chargement de la page, vous pourrez activer ou désactiver la fonctionnalité pour chaque identifiant. Ceci est le paramètre par défaut pour les identifiants qui ne sont pas configurés individuellement."
|
||||
},
|
||||
"itemAutoFillOnPageLoad": {
|
||||
"message": "Auto-fill on Page Load (if enabled in Options)"
|
||||
"message": "Remplissage automatique au chargement de la page (si activé dans les options)"
|
||||
},
|
||||
"autoFillOnPageLoadUseDefault": {
|
||||
"message": "Use default setting"
|
||||
"message": "Utiliser le paramètre par défaut"
|
||||
},
|
||||
"autoFillOnPageLoadYes": {
|
||||
"message": "Auto-fill on page load"
|
||||
"message": "Remplissage automatique au chargement de la page"
|
||||
},
|
||||
"autoFillOnPageLoadNo": {
|
||||
"message": "Do not auto-fill on page load"
|
||||
"message": "Ne pas remplir automatiquement au chargement de la page"
|
||||
},
|
||||
"commandOpenPopup": {
|
||||
"message": "Ouvrir la popup du coffre"
|
||||
@@ -1748,9 +1748,9 @@
|
||||
"message": "Cette action est protégée. Pour continuer, veuillez ressaisir votre mot de passe maître pour vérifier votre identité."
|
||||
},
|
||||
"emailVerificationRequired": {
|
||||
"message": "Email Verification Required"
|
||||
"message": "Vérification de l'adresse e-mail nécessaire"
|
||||
},
|
||||
"emailVerificationRequiredDesc": {
|
||||
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
|
||||
"message": "Vous devez vérifier votre adresse e-mail pour utiliser cette fonctionnalité. Vous pouvez vérifier votre adresse e-mail dans le coffre web."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -644,7 +644,7 @@
|
||||
"message": "שתף"
|
||||
},
|
||||
"movedItemToOrg": {
|
||||
"message": "$ITEMNAME$ moved to $ORGNAME$",
|
||||
"message": "$ITEMNAME$ הועבר ל- $ORGNAME$",
|
||||
"placeholders": {
|
||||
"itemname": {
|
||||
"content": "$1",
|
||||
@@ -918,19 +918,19 @@
|
||||
"message": "זוהי אופציה נסיונית. השימוש באופציה זו על אחריותך."
|
||||
},
|
||||
"defaultAutoFillOnPageLoad": {
|
||||
"message": "Default autofill setting for login items"
|
||||
"message": "הגדרת ברירת מחדל למילוי אוטומטי של פרטי התחברות"
|
||||
},
|
||||
"defaultAutoFillOnPageLoadDesc": {
|
||||
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
|
||||
"message": "לאחר הפעלת מילוי אוטומטי של פרטים בעת טעינת דפים, אפשר להפעיל או לכבות את האפשרות לפרטי התחברות ספציפיים. זו הגדרת ברירת המחדל לפרטי התחברות שלא הוגדרו בנפרד."
|
||||
},
|
||||
"itemAutoFillOnPageLoad": {
|
||||
"message": "Auto-fill on Page Load (if enabled in Options)"
|
||||
"message": "מילוי אוטומטי בעת טעינת דפים (אם מופעל בהגדרות)"
|
||||
},
|
||||
"autoFillOnPageLoadUseDefault": {
|
||||
"message": "Use default setting"
|
||||
"message": "שימוש בהגדרות ברירת המחדל"
|
||||
},
|
||||
"autoFillOnPageLoadYes": {
|
||||
"message": "Auto-fill on page load"
|
||||
"message": "מילוי אוטומטי אחרי טעינת דפים"
|
||||
},
|
||||
"autoFillOnPageLoadNo": {
|
||||
"message": "Do not auto-fill on page load"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -151,7 +151,7 @@
|
||||
"message": "Spremi"
|
||||
},
|
||||
"move": {
|
||||
"message": "Move"
|
||||
"message": "Premjesti"
|
||||
},
|
||||
"addFolder": {
|
||||
"message": "Dodaj mapu"
|
||||
@@ -632,19 +632,19 @@
|
||||
"message": "Dijeljeno"
|
||||
},
|
||||
"learnOrg": {
|
||||
"message": "Learn about Organizations"
|
||||
"message": "Više o organizacijama"
|
||||
},
|
||||
"learnOrgConfirmation": {
|
||||
"message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?"
|
||||
"message": "Bitwarden omogućuje dijeljenje trezora s drugima pomoću organizacijskog računa. Želiš li sada posjetiti bitwarden.com za više informacija?"
|
||||
},
|
||||
"moveToOrganization": {
|
||||
"message": "Move to Organization"
|
||||
"message": "Premjesti u organizaciju"
|
||||
},
|
||||
"share": {
|
||||
"message": "Podijeli"
|
||||
},
|
||||
"movedItemToOrg": {
|
||||
"message": "$ITEMNAME$ moved to $ORGNAME$",
|
||||
"message": "$ITEMNAME$ premješteno u $ORGNAME$",
|
||||
"placeholders": {
|
||||
"itemname": {
|
||||
"content": "$1",
|
||||
@@ -657,7 +657,7 @@
|
||||
}
|
||||
},
|
||||
"moveToOrgDesc": {
|
||||
"message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved."
|
||||
"message": "Odaberi organizaciju u koju želiš premjestiti ovu stavku. Premještanje prenosi vlasništvo stavke na organizaciju. Nakon premještanja više nećeš biti izravni vlasnik ove stavke."
|
||||
},
|
||||
"learnMore": {
|
||||
"message": "Saznaj više"
|
||||
@@ -819,7 +819,7 @@
|
||||
"message": "Nastavi na WebAuthn 2FA verifikaciju u novoj kartici."
|
||||
},
|
||||
"webAuthnNewTabOpen": {
|
||||
"message": "Open new tab"
|
||||
"message": "Otvori novu karticu"
|
||||
},
|
||||
"webAuthnAuthenticate": {
|
||||
"message": "Ovjeri WebAuthn"
|
||||
@@ -918,22 +918,22 @@
|
||||
"message": "Ovo je trenutno eksperimentalna značajka. Koristi na vlastitu odgovornost."
|
||||
},
|
||||
"defaultAutoFillOnPageLoad": {
|
||||
"message": "Default autofill setting for login items"
|
||||
"message": "Zadana postvaka Auto-ispune za prijave"
|
||||
},
|
||||
"defaultAutoFillOnPageLoadDesc": {
|
||||
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
|
||||
"message": "Nakon omogućavanja Auto-ispune kod učitavanja stranice, moguće je uključiti/isključiti ovu značajku za svaku pojedinu prijavu. Ovo je zadana postavka za prijave koje nisu pojedinčano određene."
|
||||
},
|
||||
"itemAutoFillOnPageLoad": {
|
||||
"message": "Auto-fill on Page Load (if enabled in Options)"
|
||||
"message": "Auto-ispuna kod učitavanja stranice (ako je uključeno u Postavkama)"
|
||||
},
|
||||
"autoFillOnPageLoadUseDefault": {
|
||||
"message": "Use default setting"
|
||||
"message": "Koristi zadane postavke"
|
||||
},
|
||||
"autoFillOnPageLoadYes": {
|
||||
"message": "Auto-fill on page load"
|
||||
"message": "Auto-ispuna kod učitavanja"
|
||||
},
|
||||
"autoFillOnPageLoadNo": {
|
||||
"message": "Do not auto-fill on page load"
|
||||
"message": "Ne koristi Auto-ispunu kod učitavanja"
|
||||
},
|
||||
"commandOpenPopup": {
|
||||
"message": "Otvori iskočni prozor trezora"
|
||||
@@ -1748,9 +1748,9 @@
|
||||
"message": "Ova radnja je zaštićena. Za nastavak i potvrdu identiteta, unesi svoju glavnu lozinku."
|
||||
},
|
||||
"emailVerificationRequired": {
|
||||
"message": "Email Verification Required"
|
||||
"message": "Potrebna je potvrda e-pošte"
|
||||
},
|
||||
"emailVerificationRequiredDesc": {
|
||||
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
|
||||
"message": "Moraš ovjeriti svoju e-poštu u mrežnom trezoru za koritšenje ove značajke."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
"message": "Verifica in due passaggi"
|
||||
},
|
||||
"logOut": {
|
||||
"message": "Disconnessione"
|
||||
"message": "Esci"
|
||||
},
|
||||
"about": {
|
||||
"message": "Informazioni"
|
||||
@@ -732,7 +732,7 @@
|
||||
"message": "Opzioni addizionali di login in due passaggi come YubiKey, FIDO U2F, e Duo."
|
||||
},
|
||||
"ppremiumSignUpReports": {
|
||||
"message": "Sicurezza delle password, integrità dell'account e rapporti sulla violazione di dati per mantenere sicura la tua cassaforte."
|
||||
"message": "Sicurezza delle password, integrità dell'account e resoconti sulla violazione di dati per mantenere sicura la tua cassaforte."
|
||||
},
|
||||
"ppremiumSignUpTotp": {
|
||||
"message": "Generatore di codice di verifica TOTP (2FA) per i login nella tua cassaforte."
|
||||
@@ -783,7 +783,7 @@
|
||||
"message": "Inserisci il codice di verifica a 6 cifre dalla tua applicazione di autenticazione."
|
||||
},
|
||||
"enterVerificationCodeEmail": {
|
||||
"message": "Inserisci il codice di verifica a 6 cifre ricevuto per email",
|
||||
"message": "Inserisci il codice di verifica a 6 cifrato inviato a $EMAIL$.",
|
||||
"placeholders": {
|
||||
"email": {
|
||||
"content": "$1",
|
||||
@@ -918,22 +918,22 @@
|
||||
"message": "Al momento questa funzionalità è sperimentale. Usala a tuo rischio e pericolo."
|
||||
},
|
||||
"defaultAutoFillOnPageLoad": {
|
||||
"message": "Impostazioni di riempimento automatico predefinito per gli elementi di accesso"
|
||||
"message": "Impostazioni di completamento automatico predefinito per i login"
|
||||
},
|
||||
"defaultAutoFillOnPageLoadDesc": {
|
||||
"message": "Dopo aver abilitato il completamento automatico al caricamento della pagina, è possibile abilitare o disabilitare la funzione per singoli elementi di accesso. Questa è l'impostazione predefinita per gli elementi di accesso che non sono configurati separatamente."
|
||||
"message": "Dopo aver abilitato il completamento automatico al caricamento della pagina, è possibile abilitare o disabilitare la funzione per singoli login. Questa è l'impostazione predefinita per i login che non sono configurati separatamente."
|
||||
},
|
||||
"itemAutoFillOnPageLoad": {
|
||||
"message": "Riempimento automatico al caricamento della pagina (se abilitato nelle opzioni)"
|
||||
"message": "Autocompletamento al caricamento della pagina (se abilitato nelle opzioni)"
|
||||
},
|
||||
"autoFillOnPageLoadUseDefault": {
|
||||
"message": "Usa impostazione predefinita"
|
||||
},
|
||||
"autoFillOnPageLoadYes": {
|
||||
"message": "Riempimento automatico al caricamento della pagina"
|
||||
"message": "Autocompletamento al caricamento della pagina"
|
||||
},
|
||||
"autoFillOnPageLoadNo": {
|
||||
"message": "Non riempire automaticamente al caricamento della pagina"
|
||||
"message": "Non completare automaticamente al caricamento della pagina"
|
||||
},
|
||||
"commandOpenPopup": {
|
||||
"message": "Apri popup cassaforte"
|
||||
@@ -942,10 +942,10 @@
|
||||
"message": "Apri la cassaforte nella barra laterale"
|
||||
},
|
||||
"commandAutofillDesc": {
|
||||
"message": "Auto-completa con l'ultimo login utilizzato sul sito corrente."
|
||||
"message": "Auto-completa con l'ultimo accesso utilizzato sul sito corrente"
|
||||
},
|
||||
"commandGeneratePasswordDesc": {
|
||||
"message": "Genera e copia una nuova password casuale negli appunti."
|
||||
"message": "Genera e copia una nuova password casuale negli appunti"
|
||||
},
|
||||
"commandLockVaultDesc": {
|
||||
"message": "Blocca la cassaforte"
|
||||
@@ -1668,7 +1668,7 @@
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"currentAccessCount": {
|
||||
"message": "Numero di accessi correnti"
|
||||
"message": "Numero di accessi attuale"
|
||||
},
|
||||
"createSend": {
|
||||
"message": "Crea nuovo Send",
|
||||
@@ -1748,7 +1748,7 @@
|
||||
"message": "Questa azione è protetta. Per continuare, inserisci nuovamente la tua password principale per verificare la tua identità."
|
||||
},
|
||||
"emailVerificationRequired": {
|
||||
"message": "Verifica email necessaria"
|
||||
"message": "Verifica email richiesta"
|
||||
},
|
||||
"emailVerificationRequiredDesc": {
|
||||
"message": "Devi verificare la tua email per utilizzare questa funzionalità. Puoi verificare la tua email nella cassaforte web."
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
"message": "저장"
|
||||
},
|
||||
"move": {
|
||||
"message": "Move"
|
||||
"message": "이동"
|
||||
},
|
||||
"addFolder": {
|
||||
"message": "폴더 추가"
|
||||
@@ -632,19 +632,19 @@
|
||||
"message": "공유됨"
|
||||
},
|
||||
"learnOrg": {
|
||||
"message": "Learn about Organizations"
|
||||
"message": "조직에 대해 알아보기"
|
||||
},
|
||||
"learnOrgConfirmation": {
|
||||
"message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?"
|
||||
"message": "Bitwarden은 조직용 계정을 사용하면 사용자의 보관함을 타인에게 공유할 수 있습니다. bitwarden.com 웹 사이트를 방문하여 더 자세히 알아보시겠습니까?"
|
||||
},
|
||||
"moveToOrganization": {
|
||||
"message": "Move to Organization"
|
||||
"message": "조직으로 이동하기"
|
||||
},
|
||||
"share": {
|
||||
"message": "공유"
|
||||
},
|
||||
"movedItemToOrg": {
|
||||
"message": "$ITEMNAME$ moved to $ORGNAME$",
|
||||
"message": "$ITEMNAME$이(가) $ORGNAME$(으)로 이동됨",
|
||||
"placeholders": {
|
||||
"itemname": {
|
||||
"content": "$1",
|
||||
@@ -657,7 +657,7 @@
|
||||
}
|
||||
},
|
||||
"moveToOrgDesc": {
|
||||
"message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved."
|
||||
"message": "이 항목을 이동할 조직을 선택하십시오. 항목이 조직으로 이동되면 소유권이 조직으로 이전됩니다. 일단 이동되면, 더는 이동된 항목의 직접적인 소유자가 아니게 됩니다."
|
||||
},
|
||||
"learnMore": {
|
||||
"message": "더 알아보기"
|
||||
@@ -819,7 +819,7 @@
|
||||
"message": "새 탭에서 WebAuthn 2단계 인증을 계속하세요."
|
||||
},
|
||||
"webAuthnNewTabOpen": {
|
||||
"message": "Open new tab"
|
||||
"message": "새 탭 열기"
|
||||
},
|
||||
"webAuthnAuthenticate": {
|
||||
"message": "WebAuthn 인증"
|
||||
@@ -918,22 +918,22 @@
|
||||
"message": "현재 실험 중인 기능입니다. 위험을 감수하여 사용하세요."
|
||||
},
|
||||
"defaultAutoFillOnPageLoad": {
|
||||
"message": "Default autofill setting for login items"
|
||||
"message": "로그인 항목에 대한 기본 자동 완성 설정"
|
||||
},
|
||||
"defaultAutoFillOnPageLoadDesc": {
|
||||
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
|
||||
"message": "페이지 로드 시 자동 완성을 켠 뒤에는 각 로그인 항목별로 이 기능을 켜거나 끌 수 있습니다. 이 옵션은 해당 기능을 개별적으로 구성하지 않은 항목에 사용되는 기본 설정값입니다."
|
||||
},
|
||||
"itemAutoFillOnPageLoad": {
|
||||
"message": "Auto-fill on Page Load (if enabled in Options)"
|
||||
"message": "페이지 로드 시 자동 완성 (옵션에서 켜져 있을 경우)"
|
||||
},
|
||||
"autoFillOnPageLoadUseDefault": {
|
||||
"message": "Use default setting"
|
||||
"message": "기본 설정 사용"
|
||||
},
|
||||
"autoFillOnPageLoadYes": {
|
||||
"message": "Auto-fill on page load"
|
||||
"message": "페이지 로드 시 자동 완성"
|
||||
},
|
||||
"autoFillOnPageLoadNo": {
|
||||
"message": "Do not auto-fill on page load"
|
||||
"message": "페이지 로드 시 자동 완성 안 함"
|
||||
},
|
||||
"commandOpenPopup": {
|
||||
"message": "보관함 팝업 열기"
|
||||
@@ -1748,9 +1748,9 @@
|
||||
"message": "이 작업은 보호되어 있습니다. 계속하려면 마스터 비밀번호를 입력하여 신원을 인증하세요."
|
||||
},
|
||||
"emailVerificationRequired": {
|
||||
"message": "Email Verification Required"
|
||||
"message": "이메일 인증 필요함"
|
||||
},
|
||||
"emailVerificationRequiredDesc": {
|
||||
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
|
||||
"message": "이 기능을 사용하려면 이메일 인증이 필요합니다. 웹 보관함에서 이메일을 인증할 수 있습니다."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
"message": "Saglabāt"
|
||||
},
|
||||
"move": {
|
||||
"message": "Move"
|
||||
"message": "Pārvietot"
|
||||
},
|
||||
"addFolder": {
|
||||
"message": "Pievienot mapi"
|
||||
@@ -632,19 +632,19 @@
|
||||
"message": "Kopīgots"
|
||||
},
|
||||
"learnOrg": {
|
||||
"message": "Learn about Organizations"
|
||||
"message": "Uzzināt par apvienībām"
|
||||
},
|
||||
"learnOrgConfirmation": {
|
||||
"message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?"
|
||||
"message": "Bitwarden nodrošina iespēju kopīgot glabātavas vienumus ar citiem, kad tiek izmantota apvienība. Vai apmeklēt bitwarden.com tīmekļa vietni, lai uzzinātu vairāk?"
|
||||
},
|
||||
"moveToOrganization": {
|
||||
"message": "Move to Organization"
|
||||
"message": "Pārvietot uz apvienību"
|
||||
},
|
||||
"share": {
|
||||
"message": "Kopīgot"
|
||||
},
|
||||
"movedItemToOrg": {
|
||||
"message": "$ITEMNAME$ moved to $ORGNAME$",
|
||||
"message": "$ITEMNAME$ pārvietots uz $ORGNAME$",
|
||||
"placeholders": {
|
||||
"itemname": {
|
||||
"content": "$1",
|
||||
@@ -657,7 +657,7 @@
|
||||
}
|
||||
},
|
||||
"moveToOrgDesc": {
|
||||
"message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved."
|
||||
"message": "Izvēlies apvienību, uz kuru pārvietot šo vienumu. Pārvietošana nodod šī vienuma piederību apvienībai. Tu vairs nebūsi šī vienuma tiešais īpašnieks pēc tā pārvietošanas."
|
||||
},
|
||||
"learnMore": {
|
||||
"message": "Uzzināt vairāk"
|
||||
@@ -819,7 +819,7 @@
|
||||
"message": "Turpināt WebAuthn 2FA apstiprināšanu jaunā cilnē."
|
||||
},
|
||||
"webAuthnNewTabOpen": {
|
||||
"message": "Open new tab"
|
||||
"message": "Atvērt jaunu cilni"
|
||||
},
|
||||
"webAuthnAuthenticate": {
|
||||
"message": "Autentificēt WebAuthn"
|
||||
@@ -918,22 +918,22 @@
|
||||
"message": "Šī iespēja pašlaik ir izmēģināšanā. Izmantošanas atbildība ir katra paša pārziņā. "
|
||||
},
|
||||
"defaultAutoFillOnPageLoad": {
|
||||
"message": "Default autofill setting for login items"
|
||||
"message": "Noklusējuma automātiskās aizpildes iestatījums pierakstīšanās vienumiem"
|
||||
},
|
||||
"defaultAutoFillOnPageLoadDesc": {
|
||||
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
|
||||
"message": "Pēc automātiskās aizpildes lapas ielādes brīdī iespējošanas šo iespēju var ieslēgt vai izslēgt atsevišķiem pierakstīšanās vienumiem. Šis ir noklusējuma iestatījums visiem ierakstiem, kuriem nav norādīts šis uzstādījums."
|
||||
},
|
||||
"itemAutoFillOnPageLoad": {
|
||||
"message": "Auto-fill on Page Load (if enabled in Options)"
|
||||
"message": "Automātiski aizpildīt lapas ielādes brīdī (ja iespējots iestatījumos)"
|
||||
},
|
||||
"autoFillOnPageLoadUseDefault": {
|
||||
"message": "Use default setting"
|
||||
"message": "Izmantot noklusējuma iestatījumu"
|
||||
},
|
||||
"autoFillOnPageLoadYes": {
|
||||
"message": "Auto-fill on page load"
|
||||
"message": "Automātiski aizpildīt lapas ielādes brīdī"
|
||||
},
|
||||
"autoFillOnPageLoadNo": {
|
||||
"message": "Do not auto-fill on page load"
|
||||
"message": "Neaizpildīt lapas ielādes brīdī"
|
||||
},
|
||||
"commandOpenPopup": {
|
||||
"message": "Atvērt glabātavas uznirstošo logu"
|
||||
@@ -1748,9 +1748,9 @@
|
||||
"message": "Šī darbība ir aizsargāta. Lai turpinātu, ir jāievada galvenā parole, lai apstiprinātu identitāti."
|
||||
},
|
||||
"emailVerificationRequired": {
|
||||
"message": "Email Verification Required"
|
||||
"message": "Nepieciešama e-pasta adreses apstiprināšana"
|
||||
},
|
||||
"emailVerificationRequiredDesc": {
|
||||
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
|
||||
"message": "Ir nepieciešams apstiprināt e-pasta adresi, lai būtu iespējams izmantot šo iespēju. To var izdarīt tīmekļa glabātavā."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
"message": "Lagre"
|
||||
},
|
||||
"move": {
|
||||
"message": "Move"
|
||||
"message": "Flytt"
|
||||
},
|
||||
"addFolder": {
|
||||
"message": "Legg til en mappe"
|
||||
@@ -600,7 +600,7 @@
|
||||
"description": "Light color"
|
||||
},
|
||||
"solarizedDark": {
|
||||
"message": "Solarized Dark",
|
||||
"message": "Solarisert mørk",
|
||||
"description": "'Solarized' is a noun and the name of a color scheme. It should not be translated."
|
||||
},
|
||||
"exportVault": {
|
||||
@@ -620,10 +620,10 @@
|
||||
"message": "Eksporten inneholder dine hvelvdataer i et ukryptert format. Du burde ikke lagre eller sende den eksporterte filen over usikre tjenester (f.eks. E-post). Slett det umiddelbart etter at du er ferdig med å bruke dem."
|
||||
},
|
||||
"encExportKeyWarningDesc": {
|
||||
"message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file."
|
||||
"message": "Denne eksporten krypterer dataene dine ved hjelp av kontoen din sin krypteringsnøkkel. Hvis du noen gang endrer krypteringsnøkkelen til kontoen din, bør du eksportere dataene igjen, ettersom du da ikke vil kunne dekryptere denne eksportfilen."
|
||||
},
|
||||
"encExportAccountWarningDesc": {
|
||||
"message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account."
|
||||
"message": "Kontokrypteringsnøkler er unike for hver Bitwarden sin brukerkonto, og du kan ikke importere en kryptert eksport til en annen konto."
|
||||
},
|
||||
"exportMasterPassword": {
|
||||
"message": "Skriv inn ditt superpassord for å eksportere dine hvelvdataer."
|
||||
@@ -632,19 +632,19 @@
|
||||
"message": "Delt"
|
||||
},
|
||||
"learnOrg": {
|
||||
"message": "Learn about Organizations"
|
||||
"message": "Lær om organisasjoner"
|
||||
},
|
||||
"learnOrgConfirmation": {
|
||||
"message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?"
|
||||
"message": "Bitwarden lar deg dele dine hvelvgjenstander med andre ved å bruke en organisasjon. Vil du besøke bitwarden.com-nettstedet for å lære mer?"
|
||||
},
|
||||
"moveToOrganization": {
|
||||
"message": "Move to Organization"
|
||||
"message": "Flytt til organisasjon"
|
||||
},
|
||||
"share": {
|
||||
"message": "Del"
|
||||
},
|
||||
"movedItemToOrg": {
|
||||
"message": "$ITEMNAME$ moved to $ORGNAME$",
|
||||
"message": "$ITEMNAME$ flyttet til $ORGNAME$",
|
||||
"placeholders": {
|
||||
"itemname": {
|
||||
"content": "$1",
|
||||
@@ -657,7 +657,7 @@
|
||||
}
|
||||
},
|
||||
"moveToOrgDesc": {
|
||||
"message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved."
|
||||
"message": "Velg en organisasjon som du ønsker å flytte denne gjenstanden til. Flytting til en organisasjon overfører eierskap til den aktuelle organisasjonen. Du vil ikke lenger være den direkte eieren av denne varen når den er flyttet."
|
||||
},
|
||||
"learnMore": {
|
||||
"message": "Lær mer"
|
||||
@@ -816,13 +816,13 @@
|
||||
"message": "Sett din sikkerhetsnøkkel inn i din datamaskins USB-uttak. Dersom den har en knapp, trykk på den."
|
||||
},
|
||||
"webAuthnNewTab": {
|
||||
"message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab."
|
||||
"message": "For å starte WebAuthn 2FA bekreftelsen. Klikk på knappen nedenfor for å åpne en ny fane og følge instruksene som er gitt i den nye fanen."
|
||||
},
|
||||
"webAuthnNewTabOpen": {
|
||||
"message": "Open new tab"
|
||||
"message": "Åpne ny fane"
|
||||
},
|
||||
"webAuthnAuthenticate": {
|
||||
"message": "Authenticate WebAuthn"
|
||||
"message": "Autentiser WebAuthn"
|
||||
},
|
||||
"loginUnavailable": {
|
||||
"message": "Innloggingen er utilgjengelig"
|
||||
@@ -867,7 +867,7 @@
|
||||
"message": "FIDO2 WebAuthn"
|
||||
},
|
||||
"webAuthnDesc": {
|
||||
"message": "Use any WebAuthn enabled security key to access your account."
|
||||
"message": "Bruk en hvilken som helst WebAuthn aktivert sikkerhetsnøkkel til å få tilgang til kontoen din."
|
||||
},
|
||||
"emailTitle": {
|
||||
"message": "E-post"
|
||||
@@ -918,10 +918,10 @@
|
||||
"message": "Dette er for øyeblikket en eksperimentell egenskap. Bruk det på din egen risiko."
|
||||
},
|
||||
"defaultAutoFillOnPageLoad": {
|
||||
"message": "Default autofill setting for login items"
|
||||
"message": "Standard autofyll innstilling for innloggingselementer"
|
||||
},
|
||||
"defaultAutoFillOnPageLoadDesc": {
|
||||
"message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured."
|
||||
"message": "Etter aktivering av auto-utfylling på sidelasser, kan du aktivere eller deaktivere funksjonen for individuelle innloggingselementer. Dette er standardinnstillingen for innloggingselementer som ikke er satt opp separat."
|
||||
},
|
||||
"itemAutoFillOnPageLoad": {
|
||||
"message": "Auto-fill on Page Load (if enabled in Options)"
|
||||
@@ -1616,10 +1616,10 @@
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"expirationDate": {
|
||||
"message": "Expiration Date"
|
||||
"message": "Utløpsdato"
|
||||
},
|
||||
"expirationDateDesc": {
|
||||
"message": "If set, access to this Send will expire on the specified date and time.",
|
||||
"message": "Hvis satt, vil tilgang til denne Send gå ut på angitt dato og klokkeslett.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"oneDay": {
|
||||
@@ -1635,25 +1635,25 @@
|
||||
}
|
||||
},
|
||||
"custom": {
|
||||
"message": "Custom"
|
||||
"message": "Egendefinert"
|
||||
},
|
||||
"maximumAccessCount": {
|
||||
"message": "Maximum Access Count"
|
||||
"message": "Maksimal antall tilganger"
|
||||
},
|
||||
"maximumAccessCountDesc": {
|
||||
"message": "If set, users will no longer be able to access this Send once the maximum access count is reached.",
|
||||
"message": "Hvis satt, vil ikke brukere lenger ha tilgang til dette Send når maksimal antall tilgang er nådd.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"sendPasswordDesc": {
|
||||
"message": "Optionally require a password for users to access this Send.",
|
||||
"message": "Eventuelt krever et passord for brukere å få tilgang til denne Send.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"sendNotesDesc": {
|
||||
"message": "Private notes about this Send.",
|
||||
"message": "Private notater om denne Send-en.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"sendDisableDesc": {
|
||||
"message": "Disable this Send so that no one can access it.",
|
||||
"message": "Deaktiver denne Send-en, slik at ingen får tilgang til den.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"sendShareDesc": {
|
||||
@@ -1703,54 +1703,54 @@
|
||||
"message": "In order to choose a file using Safari, pop out to a new window by clicking this banner."
|
||||
},
|
||||
"sendFileCalloutHeader": {
|
||||
"message": "Before you start"
|
||||
"message": "Før du starter"
|
||||
},
|
||||
"sendFirefoxCustomDatePopoutMessage1": {
|
||||
"message": "To use a calendar style date picker",
|
||||
"message": "Hvis du vil bruke en kalenderstil-datovelger",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'"
|
||||
},
|
||||
"sendFirefoxCustomDatePopoutMessage2": {
|
||||
"message": "click here",
|
||||
"message": "kilkk her",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'"
|
||||
},
|
||||
"sendFirefoxCustomDatePopoutMessage3": {
|
||||
"message": "to pop out your window.",
|
||||
"message": "å pope ut vinduet.",
|
||||
"description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'"
|
||||
},
|
||||
"expirationDateIsInvalid": {
|
||||
"message": "The expiration date provided is not valid."
|
||||
"message": "Utløpsdatoen angitt er ikke gyldig."
|
||||
},
|
||||
"deletionDateIsInvalid": {
|
||||
"message": "The deletion date provided is not valid."
|
||||
"message": "Slettingsdatoen som er gitt er ikke gyldig."
|
||||
},
|
||||
"expirationDateAndTimeRequired": {
|
||||
"message": "An expiration date and time are required."
|
||||
"message": "Utløps dato og tid er påkrevd."
|
||||
},
|
||||
"deletionDateAndTimeRequired": {
|
||||
"message": "A deletion date and time are required."
|
||||
"message": "Det kreves en slettingsdato og -tid."
|
||||
},
|
||||
"dateParsingError": {
|
||||
"message": "There was an error saving your deletion and expiration dates."
|
||||
"message": "Det oppstod en feil ved lagring av slettingen og utløpsdatoene."
|
||||
},
|
||||
"hideEmail": {
|
||||
"message": "Hide my email address from recipients."
|
||||
"message": "Skjul min e-postadresse fra mottakere."
|
||||
},
|
||||
"sendOptionsPolicyInEffect": {
|
||||
"message": "One or more organization policies are affecting your Send options."
|
||||
"message": "En eller flere av organisasjons retningslinjer påvirker generatorinnstillingene dine."
|
||||
},
|
||||
"passwordPrompt": {
|
||||
"message": "Master password re-prompt"
|
||||
},
|
||||
"passwordConfirmation": {
|
||||
"message": "Master password confirmation"
|
||||
"message": "Superpassord bekreftelse"
|
||||
},
|
||||
"passwordConfirmationDesc": {
|
||||
"message": "This action is protected. To continue, please re-enter your master password to verify your identity."
|
||||
"message": "Denne handlingen er beskyttet. For å fortsette, skriv inn superpassordet på nytt for å bekrefte identiteten din."
|
||||
},
|
||||
"emailVerificationRequired": {
|
||||
"message": "Email Verification Required"
|
||||
"message": "E-postbekreftelse kreves"
|
||||
},
|
||||
"emailVerificationRequiredDesc": {
|
||||
"message": "You must verify your email to use this feature. You can verify your email in the web vault."
|
||||
"message": "Du må bekrefte e-posten din for å bruke denne funksjonen. Du kan bekrefte e-postadressen din i netthvelvet."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,7 +635,7 @@
|
||||
"message": "Dowiedz się więcej o organizacjach"
|
||||
},
|
||||
"learnOrgConfirmation": {
|
||||
"message": "Bitwarden pozwala na udostępnianie zawartości sejfu innym osobom za pośrednictwem organizacji. Czy chcesz odwiedzić witrynę bitwarden.com, aby dowiedzieć się więcej?"
|
||||
"message": "Bitwarden pozwala na udostępnianie zawartości sejfu innym osobom za pośrednictwem organizacji. Czy chcesz odwiedzić stronę bitwarden.com, aby dowiedzieć się więcej?"
|
||||
},
|
||||
"moveToOrganization": {
|
||||
"message": "Przenieś do organizacji"
|
||||
@@ -644,7 +644,7 @@
|
||||
"message": "Udostępnij"
|
||||
},
|
||||
"movedItemToOrg": {
|
||||
"message": "Element $ITEMNAME$ przeniesiono do organizacji $ORGNAME$",
|
||||
"message": "Element $ITEMNAME$ został przeniesiony do organizacji $ORGNAME$",
|
||||
"placeholders": {
|
||||
"itemname": {
|
||||
"content": "$1",
|
||||
@@ -657,7 +657,7 @@
|
||||
}
|
||||
},
|
||||
"moveToOrgDesc": {
|
||||
"message": "Wybierz organizację, do której chcesz przenieść ten element. Przeniesienie do organizacji przenosi uprawnienia właścicielskie względem elementu na tę organizację. Po przeniesieniu elementu utracisz bezpośrednie uprawnienia właścicielskie."
|
||||
"message": "Wybierz organizację, do której chcesz przenieść ten element. Ta czynność spowoduje utratę własności elementu i przenosi te uprawnienia do organizacji."
|
||||
},
|
||||
"learnMore": {
|
||||
"message": "Dowiedz się więcej"
|
||||
@@ -918,22 +918,22 @@
|
||||
"message": "Obecnie jest to funkcja eksperymentalna. Używaj na własne ryzyko."
|
||||
},
|
||||
"defaultAutoFillOnPageLoad": {
|
||||
"message": "Domyślne ustawienia autouzupełniania dla danych logowania"
|
||||
"message": "Domyślne ustawienie autouzupełniania"
|
||||
},
|
||||
"defaultAutoFillOnPageLoadDesc": {
|
||||
"message": "Gdy włączysz opcję autouzupełniania po wczytaniu strony, możesz włączyć lub wyłączyć tę funkcję dla poszczególnych danych logowania. Jest to domyślne ustawienie dla danych logowania, które nie zostały skonfigurowane oddzielnie."
|
||||
"message": "Po włączeniu autouzupełnianiu po załadowaniu strony, możesz włączyć lub wyłączyć tę funkcję dla poszczególnych wpisów."
|
||||
},
|
||||
"itemAutoFillOnPageLoad": {
|
||||
"message": "Autouzupełnianie po wczytaniu strony (jeśli włączone w Opcjach)"
|
||||
"message": "Automatycznie uzupełniaj po załadowaniu strony (jeśli włączono w opcjach)"
|
||||
},
|
||||
"autoFillOnPageLoadUseDefault": {
|
||||
"message": "Użyj ustawienia domyślnego"
|
||||
"message": "Użyj domyślnego ustawienia"
|
||||
},
|
||||
"autoFillOnPageLoadYes": {
|
||||
"message": "Automatycznie uzupełniaj po wczytaniu strony"
|
||||
"message": "Automatycznie uzupełniaj po załadowaniu strony"
|
||||
},
|
||||
"autoFillOnPageLoadNo": {
|
||||
"message": "Nie uzupełniaj automatycznie po wczytaniu strony"
|
||||
"message": "Nie uzupełniaj automatycznie po załadowaniu strony"
|
||||
},
|
||||
"commandOpenPopup": {
|
||||
"message": "Otwórz sejf w oknie"
|
||||
@@ -990,10 +990,10 @@
|
||||
"message": "Wyświetlaj rozpoznawalną ikonę serwisu obok danych logowania w sejfie."
|
||||
},
|
||||
"disableBadgeCounter": {
|
||||
"message": "Wyłącz licznik danych logowania"
|
||||
"message": "Wyłącz licznik logowań"
|
||||
},
|
||||
"disableBadgeCounterDesc": {
|
||||
"message": "Licznik informuje, ile danych logowania zawiera sejf dla obecnej strony."
|
||||
"message": "Licznik informuje, ile razy zalogowałeś się na obecnej stronie w sejfie."
|
||||
},
|
||||
"cardholderName": {
|
||||
"message": "Właściciel karty"
|
||||
@@ -1694,7 +1694,7 @@
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"sendLinuxChromiumFileWarning": {
|
||||
"message": "Aby wybrać plik, otwórz rozszerzenie w pasku bocznym (jeśli to możliwe) albo w nowym oknie po kliknięciu tego banera."
|
||||
"message": "Aby wybrać plik, otwórz rozszerzenie na pasku bocznym (jeśli to możliwe) lub w nowym oknie."
|
||||
},
|
||||
"sendFirefoxFileWarning": {
|
||||
"message": "Aby wybrać plik za pomocą przeglądarki Firefox, otwórz rozszerzenie w nowym oknie."
|
||||
@@ -1748,9 +1748,9 @@
|
||||
"message": "Ta operacja jest chroniona. Aby kontynuować, wpisz ponownie hasło główne."
|
||||
},
|
||||
"emailVerificationRequired": {
|
||||
"message": "Wymagana weryfikacja adresu e-mail"
|
||||
"message": "Weryfikacja adresu e-mail jest wymagana"
|
||||
},
|
||||
"emailVerificationRequiredDesc": {
|
||||
"message": "Musisz zweryfikować swój adres e-mail, aby korzystać z tej funkcji. Swój adres e-mail możesz zweryfikować w sejfie internetowym."
|
||||
"message": "Musisz zweryfikować adres e-mail, aby korzystać z tej funkcji. Adres możesz zweryfikować w sejfie internetowym."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
"message": "Submit"
|
||||
},
|
||||
"emailAddress": {
|
||||
"message": "Email Address"
|
||||
"message": "වි-තැපැල් ලිපිනය"
|
||||
},
|
||||
"masterPass": {
|
||||
"message": "Master Password"
|
||||
@@ -56,7 +56,7 @@
|
||||
"message": "My Vault"
|
||||
},
|
||||
"tools": {
|
||||
"message": "Tools"
|
||||
"message": "මෙවලම්"
|
||||
},
|
||||
"settings": {
|
||||
"message": "සැකසුම්"
|
||||
@@ -65,25 +65,25 @@
|
||||
"message": "Current Tab"
|
||||
},
|
||||
"copyPassword": {
|
||||
"message": "Copy Password"
|
||||
"message": "මුරපදය පිටපත් කරන්න"
|
||||
},
|
||||
"copyNote": {
|
||||
"message": "Copy Note"
|
||||
"message": "සටහන පිටපත් කරන්න"
|
||||
},
|
||||
"copyUri": {
|
||||
"message": "Copy URI"
|
||||
},
|
||||
"copyUsername": {
|
||||
"message": "Copy Username"
|
||||
"message": "පරිශීලකනාමය පිටපත් කරන්න"
|
||||
},
|
||||
"copyNumber": {
|
||||
"message": "Copy Number"
|
||||
"message": "අංකය පිටපත් කරන්න"
|
||||
},
|
||||
"copySecurityCode": {
|
||||
"message": "Copy Security Code"
|
||||
"message": "ආරක්ෂක කේතය පිටපත් කරන්න"
|
||||
},
|
||||
"autoFill": {
|
||||
"message": "Auto-fill"
|
||||
"message": "ස්වයං-පිරවීම"
|
||||
},
|
||||
"generatePasswordCopied": {
|
||||
"message": "Generate Password (copied)"
|
||||
@@ -101,7 +101,7 @@
|
||||
"message": "There are no logins available to auto-fill for the current browser tab."
|
||||
},
|
||||
"addLogin": {
|
||||
"message": "Add a Login"
|
||||
"message": "පිවිසුමක් එකතු කරන්න"
|
||||
},
|
||||
"addItem": {
|
||||
"message": "Add Item"
|
||||
@@ -116,13 +116,13 @@
|
||||
"message": "Get master password hint"
|
||||
},
|
||||
"continue": {
|
||||
"message": "Continue"
|
||||
"message": "ඉදිරියට"
|
||||
},
|
||||
"verificationCode": {
|
||||
"message": "Verification Code"
|
||||
},
|
||||
"account": {
|
||||
"message": "Account"
|
||||
"message": "ගිණුම"
|
||||
},
|
||||
"changeMasterPassword": {
|
||||
"message": "Change Master Password"
|
||||
@@ -139,25 +139,25 @@
|
||||
"message": "Two-step Login"
|
||||
},
|
||||
"logOut": {
|
||||
"message": "Log Out"
|
||||
"message": "නික්මෙන්න"
|
||||
},
|
||||
"about": {
|
||||
"message": "About"
|
||||
"message": "පිලිබඳව"
|
||||
},
|
||||
"version": {
|
||||
"message": "Version"
|
||||
"message": "අනුවාදය"
|
||||
},
|
||||
"save": {
|
||||
"message": "Save"
|
||||
"message": "සුරකින්න"
|
||||
},
|
||||
"move": {
|
||||
"message": "Move"
|
||||
},
|
||||
"addFolder": {
|
||||
"message": "Add Folder"
|
||||
"message": "බහාලුම එකතු කරන්න"
|
||||
},
|
||||
"name": {
|
||||
"message": "Name"
|
||||
"message": "නම"
|
||||
},
|
||||
"editFolder": {
|
||||
"message": "Edit Folder"
|
||||
@@ -166,7 +166,7 @@
|
||||
"message": "Delete Folder"
|
||||
},
|
||||
"folders": {
|
||||
"message": "Folders"
|
||||
"message": "බහාලුම්"
|
||||
},
|
||||
"noFolders": {
|
||||
"message": "There are no folders to list."
|
||||
@@ -240,7 +240,7 @@
|
||||
"message": "Search vault"
|
||||
},
|
||||
"edit": {
|
||||
"message": "Edit"
|
||||
"message": "සංස්කරණය"
|
||||
},
|
||||
"view": {
|
||||
"message": "View"
|
||||
@@ -252,28 +252,28 @@
|
||||
"message": "Item Information"
|
||||
},
|
||||
"username": {
|
||||
"message": "Username"
|
||||
"message": "පරිශීලක නාමය"
|
||||
},
|
||||
"password": {
|
||||
"message": "Password"
|
||||
"message": "මුරපදය"
|
||||
},
|
||||
"passphrase": {
|
||||
"message": "Passphrase"
|
||||
},
|
||||
"favorite": {
|
||||
"message": "Favorite"
|
||||
"message": "ප්රියතමය"
|
||||
},
|
||||
"notes": {
|
||||
"message": "Notes"
|
||||
"message": "සටහන්"
|
||||
},
|
||||
"note": {
|
||||
"message": "Note"
|
||||
"message": "සටහන"
|
||||
},
|
||||
"editItem": {
|
||||
"message": "Edit Item"
|
||||
},
|
||||
"folder": {
|
||||
"message": "Folder"
|
||||
"message": "බහාලුම"
|
||||
},
|
||||
"deleteItem": {
|
||||
"message": "Delete Item"
|
||||
@@ -282,10 +282,10 @@
|
||||
"message": "View Item"
|
||||
},
|
||||
"launch": {
|
||||
"message": "Launch"
|
||||
"message": "දියත්කරන්න"
|
||||
},
|
||||
"website": {
|
||||
"message": "Website"
|
||||
"message": "වියමන අඩවිය"
|
||||
},
|
||||
"toggleVisibility": {
|
||||
"message": "Toggle Visibility"
|
||||
@@ -294,7 +294,7 @@
|
||||
"message": "Manage"
|
||||
},
|
||||
"other": {
|
||||
"message": "Other"
|
||||
"message": "වෙනත්"
|
||||
},
|
||||
"rateExtension": {
|
||||
"message": "Rate the Extension"
|
||||
@@ -312,7 +312,7 @@
|
||||
"message": "Your vault is locked. Verify your master password to continue."
|
||||
},
|
||||
"unlock": {
|
||||
"message": "Unlock"
|
||||
"message": "අගුලුහරින්න"
|
||||
},
|
||||
"loggedInAsOn": {
|
||||
"message": "Logged in as $EMAIL$ on $HOSTNAME$.",
|
||||
@@ -334,40 +334,40 @@
|
||||
"message": "Vault Timeout"
|
||||
},
|
||||
"lockNow": {
|
||||
"message": "Lock Now"
|
||||
"message": "දැන් අගුලුදමන්න"
|
||||
},
|
||||
"immediately": {
|
||||
"message": "Immediately"
|
||||
},
|
||||
"tenSeconds": {
|
||||
"message": "10 seconds"
|
||||
"message": "තත්පර 10"
|
||||
},
|
||||
"twentySeconds": {
|
||||
"message": "20 seconds"
|
||||
"message": "තත්පර 20"
|
||||
},
|
||||
"thirtySeconds": {
|
||||
"message": "30 seconds"
|
||||
"message": "තත්පර 30"
|
||||
},
|
||||
"oneMinute": {
|
||||
"message": "1 minute"
|
||||
"message": "විනාඩි 1"
|
||||
},
|
||||
"twoMinutes": {
|
||||
"message": "2 minutes"
|
||||
"message": "විනාඩි 2"
|
||||
},
|
||||
"fiveMinutes": {
|
||||
"message": "5 minutes"
|
||||
"message": "විනාඩි 5"
|
||||
},
|
||||
"fifteenMinutes": {
|
||||
"message": "15 minutes"
|
||||
"message": "විනාඩි 15"
|
||||
},
|
||||
"thirtyMinutes": {
|
||||
"message": "30 minutes"
|
||||
"message": "විනාඩි 30"
|
||||
},
|
||||
"oneHour": {
|
||||
"message": "1 hour"
|
||||
"message": "පැය 1"
|
||||
},
|
||||
"fourHours": {
|
||||
"message": "4 hours"
|
||||
"message": "පැය 4"
|
||||
},
|
||||
"onLocked": {
|
||||
"message": "On System Lock"
|
||||
@@ -379,7 +379,7 @@
|
||||
"message": "Never"
|
||||
},
|
||||
"security": {
|
||||
"message": "Security"
|
||||
"message": "ආරක්ෂාව"
|
||||
},
|
||||
"errorOccurred": {
|
||||
"message": "An error has occurred"
|
||||
@@ -513,7 +513,7 @@
|
||||
"message": "Are you sure you want to overwrite the current password?"
|
||||
},
|
||||
"searchFolder": {
|
||||
"message": "Search folder"
|
||||
"message": "බහාලුම සොයන්න"
|
||||
},
|
||||
"searchCollection": {
|
||||
"message": "Search collection"
|
||||
@@ -555,7 +555,7 @@
|
||||
"message": "Should Bitwarden remember this password for you?"
|
||||
},
|
||||
"notificationAddSave": {
|
||||
"message": "Yes, Save Now"
|
||||
"message": "ඔව්, දැන් සුරකින්න"
|
||||
},
|
||||
"notificationNeverSave": {
|
||||
"message": "Never for this website"
|
||||
@@ -570,7 +570,7 @@
|
||||
"message": "Do you want to update this password in Bitwarden?"
|
||||
},
|
||||
"notificationChangeSave": {
|
||||
"message": "Yes, Update Now"
|
||||
"message": "ඔව්, දැන් යාවත්කාල කරන්න"
|
||||
},
|
||||
"disableContextMenuItem": {
|
||||
"message": "Disable Context Menu Options"
|
||||
@@ -586,7 +586,7 @@
|
||||
"message": "Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill."
|
||||
},
|
||||
"theme": {
|
||||
"message": "Theme"
|
||||
"message": "තේමාව"
|
||||
},
|
||||
"themeDesc": {
|
||||
"message": "Change the application's color theme."
|
||||
@@ -610,7 +610,7 @@
|
||||
"message": "File Format"
|
||||
},
|
||||
"warning": {
|
||||
"message": "WARNING",
|
||||
"message": "අවවාදයයි",
|
||||
"description": "WARNING (should stay in capitalized letters if the language permits)"
|
||||
},
|
||||
"confirmVaultExport": {
|
||||
@@ -693,7 +693,7 @@
|
||||
"message": "The attachment has been saved."
|
||||
},
|
||||
"file": {
|
||||
"message": "File"
|
||||
"message": "ගොනුව"
|
||||
},
|
||||
"selectFile": {
|
||||
"message": "Select a file."
|
||||
@@ -1014,40 +1014,40 @@
|
||||
"message": "Expiration"
|
||||
},
|
||||
"january": {
|
||||
"message": "January"
|
||||
"message": "දුරුතු"
|
||||
},
|
||||
"february": {
|
||||
"message": "February"
|
||||
"message": "නවම්"
|
||||
},
|
||||
"march": {
|
||||
"message": "March"
|
||||
"message": "මැදින්"
|
||||
},
|
||||
"april": {
|
||||
"message": "April"
|
||||
"message": "බක්"
|
||||
},
|
||||
"may": {
|
||||
"message": "May"
|
||||
"message": "වෙසක්"
|
||||
},
|
||||
"june": {
|
||||
"message": "June"
|
||||
"message": "පොසොන්"
|
||||
},
|
||||
"july": {
|
||||
"message": "July"
|
||||
"message": "ඇසළ"
|
||||
},
|
||||
"august": {
|
||||
"message": "August"
|
||||
"message": "නිකිණි"
|
||||
},
|
||||
"september": {
|
||||
"message": "September"
|
||||
"message": "බිනර"
|
||||
},
|
||||
"october": {
|
||||
"message": "October"
|
||||
"message": "වප්"
|
||||
},
|
||||
"november": {
|
||||
"message": "November"
|
||||
"message": "ඉල්"
|
||||
},
|
||||
"december": {
|
||||
"message": "December"
|
||||
"message": "උඳුවප්"
|
||||
},
|
||||
"securityCode": {
|
||||
"message": "Security Code"
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
"message": "Shrani"
|
||||
},
|
||||
"move": {
|
||||
"message": "Move"
|
||||
"message": "Premakni"
|
||||
},
|
||||
"addFolder": {
|
||||
"message": "Dodaj mapo"
|
||||
@@ -513,10 +513,10 @@
|
||||
"message": "Ali ste prepričani, da želite prepisati vaše trenutno geslo?"
|
||||
},
|
||||
"searchFolder": {
|
||||
"message": "Search folder"
|
||||
"message": "Preišči mapo"
|
||||
},
|
||||
"searchCollection": {
|
||||
"message": "Search collection"
|
||||
"message": "Preišči zbirko"
|
||||
},
|
||||
"searchType": {
|
||||
"message": "Search type"
|
||||
@@ -870,10 +870,10 @@
|
||||
"message": "Use any WebAuthn enabled security key to access your account."
|
||||
},
|
||||
"emailTitle": {
|
||||
"message": "Email"
|
||||
"message": "E-pošta"
|
||||
},
|
||||
"emailDesc": {
|
||||
"message": "Verification codes will be emailed to you."
|
||||
"message": "Potrditvene kode vam bodo posredovane po e-pošti."
|
||||
},
|
||||
"selfHostedEnvironment": {
|
||||
"message": "Self-hosted Environment"
|
||||
@@ -888,10 +888,10 @@
|
||||
"message": "For advanced users. You can specify the base URL of each service independently."
|
||||
},
|
||||
"baseUrl": {
|
||||
"message": "Server URL"
|
||||
"message": "URL naslov strežnika"
|
||||
},
|
||||
"apiUrl": {
|
||||
"message": "API Server URL"
|
||||
"message": "URL naslov API strežnika"
|
||||
},
|
||||
"webVaultUrl": {
|
||||
"message": "Web Vault Server URL"
|
||||
@@ -927,7 +927,7 @@
|
||||
"message": "Auto-fill on Page Load (if enabled in Options)"
|
||||
},
|
||||
"autoFillOnPageLoadUseDefault": {
|
||||
"message": "Use default setting"
|
||||
"message": "Uporabi privzete nastavitve"
|
||||
},
|
||||
"autoFillOnPageLoadYes": {
|
||||
"message": "Auto-fill on page load"
|
||||
@@ -969,10 +969,10 @@
|
||||
"message": "Drag to sort"
|
||||
},
|
||||
"cfTypeText": {
|
||||
"message": "Text"
|
||||
"message": "Besedilo"
|
||||
},
|
||||
"cfTypeHidden": {
|
||||
"message": "Hidden"
|
||||
"message": "Skrito"
|
||||
},
|
||||
"cfTypeBoolean": {
|
||||
"message": "Boolean"
|
||||
@@ -1152,28 +1152,28 @@
|
||||
"message": "Collections"
|
||||
},
|
||||
"favorites": {
|
||||
"message": "Favorites"
|
||||
"message": "Priljubljeno"
|
||||
},
|
||||
"popOutNewWindow": {
|
||||
"message": "Pop out to a new window"
|
||||
},
|
||||
"refresh": {
|
||||
"message": "Refresh"
|
||||
"message": "Osveži"
|
||||
},
|
||||
"cards": {
|
||||
"message": "Cards"
|
||||
"message": "Plačilne kartice"
|
||||
},
|
||||
"identities": {
|
||||
"message": "Identities"
|
||||
"message": "Identitete"
|
||||
},
|
||||
"logins": {
|
||||
"message": "Logins"
|
||||
"message": "Prijave"
|
||||
},
|
||||
"secureNotes": {
|
||||
"message": "Secure Notes"
|
||||
},
|
||||
"clear": {
|
||||
"message": "Clear",
|
||||
"message": "Počisti",
|
||||
"description": "To clear something out. example: To clear browser history."
|
||||
},
|
||||
"checkPassword": {
|
||||
|
||||
@@ -29,6 +29,8 @@ export default class ContextMenusBackground {
|
||||
this.contextMenus.onClicked.addListener(async (info: any, tab: any) => {
|
||||
if (info.menuItemId === 'generate-password') {
|
||||
await this.generatePasswordToClipboard();
|
||||
} else if (info.menuItemId === 'copy-identifier') {
|
||||
await this.getClickedElement();
|
||||
} else if (info.parentMenuItemId === 'autofill' ||
|
||||
info.parentMenuItemId === 'copy-username' ||
|
||||
info.parentMenuItemId === 'copy-password' ||
|
||||
@@ -45,6 +47,15 @@ export default class ContextMenusBackground {
|
||||
this.passwordGenerationService.addHistory(password);
|
||||
}
|
||||
|
||||
private async getClickedElement() {
|
||||
const tab = await BrowserApi.getTabFromCurrentWindow();
|
||||
if (tab == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BrowserApi.tabSendMessageData(tab, 'getClickedElement');
|
||||
}
|
||||
|
||||
private async cipherAction(info: any) {
|
||||
const id = info.menuItemId.split('_')[1];
|
||||
if (id === 'noop') {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
|
||||
import {
|
||||
StorageService,
|
||||
VaultTimeoutService,
|
||||
} from 'jslib-common/abstractions';
|
||||
import { NotificationsService } from 'jslib-common/abstractions/notifications.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
|
||||
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
|
||||
const IdleInterval = 60 * 5; // 5 minutes
|
||||
|
||||
|
||||
@@ -1,69 +1,65 @@
|
||||
import { CipherType } from 'jslib-common/enums';
|
||||
import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType';
|
||||
import { CipherType } from 'jslib-common/enums/cipherType';
|
||||
|
||||
import {
|
||||
ApiService,
|
||||
AppIdService,
|
||||
AuditService,
|
||||
AuthService,
|
||||
CipherService,
|
||||
CollectionService,
|
||||
ConstantsService,
|
||||
ContainerService,
|
||||
EnvironmentService,
|
||||
FolderService,
|
||||
PasswordGenerationService,
|
||||
SettingsService,
|
||||
StateService,
|
||||
SyncService,
|
||||
TokenService,
|
||||
TotpService,
|
||||
UserService,
|
||||
} from 'jslib-common/services';
|
||||
import { ApiService } from 'jslib-common/services/api.service';
|
||||
import { AppIdService } from 'jslib-common/services/appId.service';
|
||||
import { AuditService } from 'jslib-common/services/audit.service';
|
||||
import { AuthService } from 'jslib-common/services/auth.service';
|
||||
import { CipherService } from 'jslib-common/services/cipher.service';
|
||||
import { CollectionService } from 'jslib-common/services/collection.service';
|
||||
import { ConsoleLogService } from 'jslib-common/services/consoleLog.service';
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
import { ContainerService } from 'jslib-common/services/container.service';
|
||||
import { EnvironmentService } from 'jslib-common/services/environment.service';
|
||||
import { EventService } from 'jslib-common/services/event.service';
|
||||
import { ExportService } from 'jslib-common/services/export.service';
|
||||
import { FileUploadService } from 'jslib-common/services/fileUpload.service';
|
||||
import { FolderService } from 'jslib-common/services/folder.service';
|
||||
import { NotificationsService } from 'jslib-common/services/notifications.service';
|
||||
import { PasswordGenerationService } from 'jslib-common/services/passwordGeneration.service';
|
||||
import { PolicyService } from 'jslib-common/services/policy.service';
|
||||
import { SearchService } from 'jslib-common/services/search.service';
|
||||
import { SendService } from 'jslib-common/services/send.service';
|
||||
import { SettingsService } from 'jslib-common/services/settings.service';
|
||||
import { StateService } from 'jslib-common/services/state.service';
|
||||
import { SyncService } from 'jslib-common/services/sync.service';
|
||||
import { SystemService } from 'jslib-common/services/system.service';
|
||||
import { TokenService } from 'jslib-common/services/token.service';
|
||||
import { TotpService } from 'jslib-common/services/totp.service';
|
||||
import { UserService } from 'jslib-common/services/user.service';
|
||||
import { WebCryptoFunctionService } from 'jslib-common/services/webCryptoFunction.service';
|
||||
|
||||
import {
|
||||
ApiService as ApiServiceAbstraction,
|
||||
AppIdService as AppIdServiceAbstraction,
|
||||
AuditService as AuditServiceAbstraction,
|
||||
AuthService as AuthServiceAbstraction,
|
||||
CipherService as CipherServiceAbstraction,
|
||||
CollectionService as CollectionServiceAbstraction,
|
||||
CryptoService as CryptoServiceAbstraction,
|
||||
EnvironmentService as EnvironmentServiceAbstraction,
|
||||
FolderService as FolderServiceAbstraction,
|
||||
I18nService as I18nServiceAbstraction,
|
||||
LogService as LogServiceAbstraction,
|
||||
MessagingService as MessagingServiceAbstraction,
|
||||
PasswordGenerationService as PasswordGenerationServiceAbstraction,
|
||||
PlatformUtilsService as PlatformUtilsServiceAbstraction,
|
||||
SettingsService as SettingsServiceAbstraction,
|
||||
StateService as StateServiceAbstraction,
|
||||
StorageService as StorageServiceAbstraction,
|
||||
SyncService as SyncServiceAbstraction,
|
||||
TokenService as TokenServiceAbstraction,
|
||||
TotpService as TotpServiceAbstraction,
|
||||
UserService as UserServiceAbstraction,
|
||||
VaultTimeoutService as VaultTimeoutServiceAbstraction,
|
||||
} from 'jslib-common/abstractions';
|
||||
import { ApiService as ApiServiceAbstraction } from 'jslib-common/abstractions/api.service';
|
||||
import { AppIdService as AppIdServiceAbstraction } from 'jslib-common/abstractions/appId.service';
|
||||
import { AuditService as AuditServiceAbstraction } from 'jslib-common/abstractions/audit.service';
|
||||
import { AuthService as AuthServiceAbstraction } from 'jslib-common/abstractions/auth.service';
|
||||
import { CipherService as CipherServiceAbstraction } from 'jslib-common/abstractions/cipher.service';
|
||||
import { CollectionService as CollectionServiceAbstraction } from 'jslib-common/abstractions/collection.service';
|
||||
import { CryptoService as CryptoServiceAbstraction } from 'jslib-common/abstractions/crypto.service';
|
||||
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from 'jslib-common/abstractions/cryptoFunction.service';
|
||||
import { EnvironmentService as EnvironmentServiceAbstraction } from 'jslib-common/abstractions/environment.service';
|
||||
import { EventService as EventServiceAbstraction } from 'jslib-common/abstractions/event.service';
|
||||
import { ExportService as ExportServiceAbstraction } from 'jslib-common/abstractions/export.service';
|
||||
import { FileUploadService as FileUploadServiceAbstraction } from 'jslib-common/abstractions/fileUpload.service';
|
||||
import { FolderService as FolderServiceAbstraction } from 'jslib-common/abstractions/folder.service';
|
||||
import { I18nService as I18nServiceAbstraction } from 'jslib-common/abstractions/i18n.service';
|
||||
import { LogService as LogServiceAbstraction } from 'jslib-common/abstractions/log.service';
|
||||
import { MessagingService as MessagingServiceAbstraction } from 'jslib-common/abstractions/messaging.service';
|
||||
import { NotificationsService as NotificationsServiceAbstraction } from 'jslib-common/abstractions/notifications.service';
|
||||
import { PasswordGenerationService as PasswordGenerationServiceAbstraction } from 'jslib-common/abstractions/passwordGeneration.service';
|
||||
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { PolicyService as PolicyServiceAbstraction } from 'jslib-common/abstractions/policy.service';
|
||||
import { SearchService as SearchServiceAbstraction } from 'jslib-common/abstractions/search.service';
|
||||
import { SendService as SendServiceAbstraction } from 'jslib-common/abstractions/send.service';
|
||||
import { SettingsService as SettingsServiceAbstraction } from 'jslib-common/abstractions/settings.service';
|
||||
import { StateService as StateServiceAbstraction } from 'jslib-common/abstractions/state.service';
|
||||
import { StorageService as StorageServiceAbstraction } from 'jslib-common/abstractions/storage.service';
|
||||
import { SyncService as SyncServiceAbstraction } from 'jslib-common/abstractions/sync.service';
|
||||
import { SystemService as SystemServiceAbstraction } from 'jslib-common/abstractions/system.service';
|
||||
import { TokenService as TokenServiceAbstraction } from 'jslib-common/abstractions/token.service';
|
||||
import { TotpService as TotpServiceAbstraction } from 'jslib-common/abstractions/totp.service';
|
||||
import { UserService as UserServiceAbstraction } from 'jslib-common/abstractions/user.service';
|
||||
import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from 'jslib-common/abstractions/vaultTimeout.service';
|
||||
import { AutofillService as AutofillServiceAbstraction } from '../services/abstractions/autofill.service';
|
||||
|
||||
import { Utils } from 'jslib-common/misc/utils';
|
||||
@@ -197,7 +193,7 @@ export default class MainBackground {
|
||||
this.policyService = new PolicyService(this.userService, this.storageService);
|
||||
this.vaultTimeoutService = new VaultTimeoutService(this.cipherService, this.folderService,
|
||||
this.collectionService, this.cryptoService, this.platformUtilsService, this.storageService,
|
||||
this.messagingService, this.searchService, this.userService, this.tokenService,
|
||||
this.messagingService, this.searchService, this.userService, this.tokenService, this.policyService,
|
||||
async () => {
|
||||
if (this.notificationsService != null) {
|
||||
this.notificationsService.updateConnection(false);
|
||||
@@ -244,7 +240,7 @@ export default class MainBackground {
|
||||
this.runtimeBackground = new RuntimeBackground(this, this.autofillService, this.cipherService,
|
||||
this.platformUtilsService as BrowserPlatformUtilsService, this.storageService, this.i18nService,
|
||||
this.notificationsService, this.systemService, this.vaultTimeoutService,
|
||||
this.environmentService, this.policyService, this.userService, this.messagingService);
|
||||
this.environmentService, this.policyService, this.userService, this.messagingService, this.folderService);
|
||||
this.nativeMessagingBackground = new NativeMessagingBackground(this.storageService, this.cryptoService, this.cryptoFunctionService,
|
||||
this.vaultTimeoutService, this.runtimeBackground, this.i18nService, this.userService, this.messagingService, this.appIdService,
|
||||
this.platformUtilsService);
|
||||
@@ -512,6 +508,14 @@ export default class MainBackground {
|
||||
title: this.i18nService.t('generatePasswordCopied'),
|
||||
});
|
||||
|
||||
await this.contextMenusCreate({
|
||||
type: 'normal',
|
||||
id: 'copy-identifier',
|
||||
parentId: 'root',
|
||||
contexts: ['all'],
|
||||
title: this.i18nService.t('copyElementIdentifier'),
|
||||
});
|
||||
|
||||
this.buildingContextMenu = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.serv
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
|
||||
import { Utils } from 'jslib-common/misc/utils';
|
||||
import { SymmetricCryptoKey } from 'jslib-common/models/domain';
|
||||
import { SymmetricCryptoKey } from 'jslib-common/models/domain/symmetricCryptoKey';
|
||||
|
||||
import { BrowserApi } from '../browser/browserApi';
|
||||
import RuntimeBackground from './runtime.background';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CipherType } from 'jslib-common/enums';
|
||||
import { CipherType } from 'jslib-common/enums/cipherType';
|
||||
|
||||
import { CipherView } from 'jslib-common/models/view/cipherView';
|
||||
import { LoginUriView } from 'jslib-common/models/view/loginUriView';
|
||||
@@ -6,6 +6,7 @@ import { LoginView } from 'jslib-common/models/view/loginView';
|
||||
|
||||
import { CipherService } from 'jslib-common/abstractions/cipher.service';
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { FolderService } from 'jslib-common/abstractions/folder.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||
import { NotificationsService } from 'jslib-common/abstractions/notifications.service';
|
||||
@@ -24,7 +25,6 @@ import MainBackground from './main.background';
|
||||
|
||||
import { Utils } from 'jslib-common/misc/utils';
|
||||
|
||||
import { OrganizationUserStatusType } from 'jslib-common/enums/organizationUserStatusType';
|
||||
import { PolicyType } from 'jslib-common/enums/policyType';
|
||||
|
||||
export default class RuntimeBackground {
|
||||
@@ -39,7 +39,8 @@ export default class RuntimeBackground {
|
||||
private notificationsService: NotificationsService,
|
||||
private systemService: SystemService, private vaultTimeoutService: VaultTimeoutService,
|
||||
private environmentService: EnvironmentService, private policyService: PolicyService,
|
||||
private userService: UserService, private messagingService: MessagingService) {
|
||||
private userService: UserService, private messagingService: MessagingService,
|
||||
private folderService: FolderService) {
|
||||
|
||||
// onInstalled listener must be wired up before anything else, so we do it in the ctor
|
||||
chrome.runtime.onInstalled.addListener((details: any) => {
|
||||
@@ -107,7 +108,7 @@ export default class RuntimeBackground {
|
||||
this.removeTabFromNotificationQueue(sender.tab);
|
||||
break;
|
||||
case 'bgAddSave':
|
||||
await this.saveAddLogin(sender.tab);
|
||||
await this.saveAddLogin(sender.tab, msg.folder);
|
||||
break;
|
||||
case 'bgChangeSave':
|
||||
await this.saveChangePassword(sender.tab);
|
||||
@@ -195,6 +196,8 @@ export default class RuntimeBackground {
|
||||
type: 'info',
|
||||
});
|
||||
break;
|
||||
case 'getClickedElementResponse':
|
||||
this.platformUtilsService.copyToClipboard(msg.identifier, { window: window });
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -216,7 +219,7 @@ export default class RuntimeBackground {
|
||||
this.pageDetailsToAutoFill = [];
|
||||
}
|
||||
|
||||
private async saveAddLogin(tab: any) {
|
||||
private async saveAddLogin(tab: any, folderId: string) {
|
||||
if (await this.vaultTimeoutService.isLocked()) {
|
||||
return;
|
||||
}
|
||||
@@ -247,6 +250,13 @@ export default class RuntimeBackground {
|
||||
model.type = CipherType.Login;
|
||||
model.login = loginModel;
|
||||
|
||||
if (!Utils.isNullOrWhitespace(folderId)) {
|
||||
const folders = await this.folderService.getAllDecrypted();
|
||||
if (folders.some(x => x.id === folderId)) {
|
||||
model.folderId = folderId;
|
||||
}
|
||||
}
|
||||
|
||||
const cipher = await this.cipherService.encrypt(model);
|
||||
await this.cipherService.saveWithServer(cipher);
|
||||
}
|
||||
@@ -450,24 +460,14 @@ export default class RuntimeBackground {
|
||||
notificationChangeSave: this.i18nService.t('notificationChangeSave'),
|
||||
notificationChangeDesc: this.i18nService.t('notificationChangeDesc'),
|
||||
};
|
||||
} else if (responseCommand === 'notificationBarGetFoldersList') {
|
||||
responseData.folders = await this.folderService.getAllDecrypted();
|
||||
}
|
||||
|
||||
await BrowserApi.tabSendMessageData(tab, responseCommand, responseData);
|
||||
}
|
||||
|
||||
private async allowPersonalOwnership(): Promise<boolean> {
|
||||
const personalOwnershipPolicies = await this.policyService.getAll(PolicyType.PersonalOwnership);
|
||||
if (personalOwnershipPolicies != null) {
|
||||
for (const policy of personalOwnershipPolicies) {
|
||||
if (policy.enabled) {
|
||||
const org = await this.userService.getOrganization(policy.organizationId);
|
||||
if (org != null && org.enabled && org.usePolicies && !org.canManagePolicies
|
||||
&& org.status === OrganizationUserStatusType.Confirmed) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return !await this.policyService.policyAppliesToUser(PolicyType.PersonalOwnership);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { CipherService } from 'jslib-common/abstractions/cipher.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
|
||||
|
||||
import { UriMatchType } from 'jslib-common/enums';
|
||||
import { UriMatchType } from 'jslib-common/enums/uriMatchType';
|
||||
|
||||
export default class WebRequestBackground {
|
||||
private pendingAuthRequests: any[] = [];
|
||||
|
||||
@@ -835,12 +835,14 @@
|
||||
|
||||
document.elementForOPID = getElementByOpId;
|
||||
|
||||
// normalize the event since firefox handles events differently than others
|
||||
// normalize the event based on API support
|
||||
function normalizeEvent(el, eventName) {
|
||||
var ev;
|
||||
if (isFirefox) {
|
||||
ev = document.createEvent('KeyboardEvent');
|
||||
ev.initKeyEvent(eventName, true, false, null, false, false, false, false, 0, 0);
|
||||
if ('KeyboardEvent' in window) {
|
||||
ev = new window.KeyboardEvent(eventName, {
|
||||
bubbles: true,
|
||||
cancelable: false,
|
||||
});
|
||||
}
|
||||
else {
|
||||
ev = el.ownerDocument.createEvent('Events');
|
||||
|
||||
45
src/content/contextMenuHandler.ts
Normal file
45
src/content/contextMenuHandler.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
const inputTags = ['input', 'textarea', 'select'];
|
||||
const attributes = ['id', 'name', 'label-aria', 'placeholder'];
|
||||
let clickedEl: HTMLElement = null;
|
||||
|
||||
// Find the best attribute to be used as the Name for an element in a custom field.
|
||||
function getClickedElementIdentifier() {
|
||||
if (clickedEl == null) {
|
||||
return 'Unable to identify clicked element.';
|
||||
}
|
||||
|
||||
if (!inputTags.includes(clickedEl.nodeName.toLowerCase())) {
|
||||
return 'Invalid element type.';
|
||||
}
|
||||
|
||||
for (const attr of attributes) {
|
||||
const attributeValue = clickedEl.getAttribute(attr);
|
||||
const selector = '[' + attr + '="' + attributeValue + '"]';
|
||||
if (!isNullOrEmpty(attributeValue) && document.querySelectorAll(selector)?.length === 1) {
|
||||
return attributeValue;
|
||||
}
|
||||
}
|
||||
return 'No unique identifier found.';
|
||||
}
|
||||
|
||||
function isNullOrEmpty(s: string) {
|
||||
return s == null || s === '';
|
||||
}
|
||||
|
||||
// We only have access to the element that's been clicked when the context menu is first opened.
|
||||
// Remember it for use later.
|
||||
document.addEventListener('contextmenu', event => {
|
||||
clickedEl = event.target as HTMLElement;
|
||||
});
|
||||
|
||||
// Runs when the 'Copy Custom Field Name' context menu item is actually clicked.
|
||||
chrome.runtime.onMessage.addListener(event => {
|
||||
if (event.command === 'getClickedElement') {
|
||||
const identifier = getClickedElementIdentifier();
|
||||
chrome.runtime.sendMessage({
|
||||
command: 'getClickedElementResponse',
|
||||
sender: 'contextMenuHandler',
|
||||
identifier: identifier,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -2,7 +2,7 @@
|
||||
"manifest_version": 2,
|
||||
"name": "__MSG_extName__",
|
||||
"short_name": "__MSG_appName__",
|
||||
"version": "1.51.1",
|
||||
"version": "1.52.1",
|
||||
"description": "__MSG_extDesc__",
|
||||
"default_locale": "en",
|
||||
"author": "Bitwarden Inc.",
|
||||
@@ -20,7 +20,8 @@
|
||||
"js": [
|
||||
"content/autofill.js",
|
||||
"content/autofiller.js",
|
||||
"content/notificationBar.js"
|
||||
"content/notificationBar.js",
|
||||
"content/contextMenuHandler.js"
|
||||
],
|
||||
"matches": [
|
||||
"http://*/*",
|
||||
|
||||
@@ -17,7 +17,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
// delay 50ms so that we get proper body dimensions
|
||||
setTimeout(load, 50);
|
||||
|
||||
|
||||
function load() {
|
||||
var closeButton = document.getElementById('close-button'),
|
||||
@@ -34,10 +33,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (bodyRect.width < 768) {
|
||||
document.querySelector('#template-add .add-save').textContent = i18n.yes;
|
||||
document.querySelector('#template-add .never-save').textContent = i18n.never;
|
||||
document.querySelector('#template-add .select-folder').style.display = 'none';
|
||||
document.querySelector('#template-change .change-save').textContent = i18n.yes;
|
||||
} else {
|
||||
document.querySelector('#template-add .add-save').textContent = i18n.notificationAddSave;
|
||||
document.querySelector('#template-add .never-save').textContent = i18n.notificationNeverSave;
|
||||
document.querySelector('#template-add .select-folder').style.display = 'initial';
|
||||
document.querySelector('#template-change .change-save').textContent = i18n.notificationChangeSave;
|
||||
}
|
||||
|
||||
@@ -52,8 +53,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
addButton.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
const folderId = document.querySelector('#template-add-clone .select-folder').value;
|
||||
sendPlatformMessage({
|
||||
command: 'bgAddSave'
|
||||
command: 'bgAddSave',
|
||||
folder: folderId,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -63,6 +66,17 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
command: 'bgNeverSave'
|
||||
});
|
||||
});
|
||||
|
||||
const responseFoldersCommand = 'notificationBarGetFoldersList';
|
||||
chrome.runtime.onMessage.addListener((msg) => {
|
||||
if (msg.command === responseFoldersCommand && msg.data) {
|
||||
fillSelectorWithFolders(msg.data.folders);
|
||||
}
|
||||
});
|
||||
sendPlatformMessage({
|
||||
command: 'bgGetDataForTab',
|
||||
responseCommand: responseFoldersCommand
|
||||
});
|
||||
} else if (getQueryVariable('change')) {
|
||||
setContent(document.getElementById('template-change'));
|
||||
var changeButton = document.querySelector('#template-change-clone .change-save');
|
||||
@@ -120,4 +134,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
function sendPlatformMessage(msg) {
|
||||
chrome.runtime.sendMessage(msg);
|
||||
}
|
||||
|
||||
function fillSelectorWithFolders(folders) {
|
||||
const select = document.querySelector('#template-add-clone .select-folder');
|
||||
select.appendChild(new Option(chrome.i18n.getMessage('selectFolder'), null, true));
|
||||
folders.forEach((folder) => {
|
||||
//Select "No Folder" (id=null) folder by default
|
||||
select.appendChild(new Option(folder.name, folder.id || '', false));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -84,7 +84,7 @@ button.neutral {
|
||||
}
|
||||
|
||||
body[class*='lang-en'] .add-buttons {
|
||||
width: 175px;
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
@@ -98,3 +98,4 @@ body[class*='lang-en'] .add-buttons {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<form #form class="modal-content" (ngSubmit)="submit()">
|
||||
<form #form (ngSubmit)="submit()">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/home">{{'close' | i18n}}</a>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
|
||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
@@ -20,6 +22,8 @@ import Swal from 'sweetalert2';
|
||||
templateUrl: 'lock.component.html',
|
||||
})
|
||||
export class LockComponent extends BaseLockComponent {
|
||||
private isInitialLockScreen: boolean;
|
||||
|
||||
constructor(router: Router, i18nService: I18nService,
|
||||
platformUtilsService: PlatformUtilsService, messagingService: MessagingService,
|
||||
userService: UserService, cryptoService: CryptoService,
|
||||
@@ -29,12 +33,21 @@ export class LockComponent extends BaseLockComponent {
|
||||
super(router, i18nService, platformUtilsService, messagingService, userService, cryptoService,
|
||||
storageService, vaultTimeoutService, environmentService, stateService, apiService);
|
||||
this.successRoute = '/tabs/current';
|
||||
this.isInitialLockScreen = (window as any).previousPopupUrl == null;
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
await super.ngOnInit();
|
||||
window.setTimeout(() => {
|
||||
const disableAutoBiometricsPrompt = await this.storageService.get<boolean>(
|
||||
ConstantsService.disableAutoBiometricsPromptKey) ?? true;
|
||||
|
||||
window.setTimeout(async () => {
|
||||
document.getElementById(this.pinLock ? 'pin' : 'masterPassword').focus();
|
||||
if (this.biometricLock && !disableAutoBiometricsPrompt && this.isInitialLockScreen) {
|
||||
if (await this.vaultTimeoutService.isLocked()) {
|
||||
await this.unlockBiometric();
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
|
||||
import { LoginComponent as BaseLoginComponent } from 'jslib-angular/components/login.component';
|
||||
|
||||
@@ -23,10 +24,14 @@ export class LoginComponent extends BaseLoginComponent {
|
||||
protected stateService: StateService, protected environmentService: EnvironmentService,
|
||||
protected passwordGenerationService: PasswordGenerationService,
|
||||
protected cryptoFunctionService: CryptoFunctionService, storageService: StorageService,
|
||||
syncService: SyncService) {
|
||||
syncService: SyncService, private userService: UserService) {
|
||||
super(authService, router, platformUtilsService, i18nService, stateService, environmentService, passwordGenerationService, cryptoFunctionService, storageService);
|
||||
super.onSuccessfulLogin = () => {
|
||||
return syncService.fullSync(true);
|
||||
super.onSuccessfulLogin = async () => {
|
||||
await syncService.fullSync(true).then(async () => {
|
||||
if (await this.userService.getForcePasswordReset()) {
|
||||
this.router.navigate(['update-temp-password']);
|
||||
}
|
||||
});
|
||||
};
|
||||
super.successRoute = '/tabs/vault';
|
||||
}
|
||||
|
||||
@@ -20,22 +20,11 @@
|
||||
<div *ngIf="!syncLoading">
|
||||
<div class="box">
|
||||
<app-callout type="tip">{{'ssoCompleteRegistration' | i18n}}</app-callout>
|
||||
<app-callout type="info" *ngIf="enforcedPolicyOptions">
|
||||
{{'masterPasswordPolicyInEffect' | i18n}}
|
||||
<ul>
|
||||
<li *ngIf="enforcedPolicyOptions?.minComplexity > 0">
|
||||
{{'policyInEffectMinComplexity' | i18n : getPasswordScoreAlertDisplay()}}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.minLength > 0">
|
||||
{{'policyInEffectMinLength' | i18n : enforcedPolicyOptions?.minLength.toString()}}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireUpper">{{'policyInEffectUppercase' | i18n}}</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireLower">{{'policyInEffectLowercase' | i18n}}</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireNumbers">{{'policyInEffectNumbers' | i18n}}</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireSpecial">
|
||||
{{'policyInEffectSpecial' | i18n : '!@#$%^&*'}}
|
||||
</li>
|
||||
</ul>
|
||||
<app-callout type="warning" title="{{'resetPasswordPolicyAutoEnroll' | i18n}}"
|
||||
*ngIf="resetPasswordAutoEnroll">
|
||||
{{'resetPasswordAutoEnrollInviteWarning' | i18n}}
|
||||
</app-callout>
|
||||
<app-callout type="info" [enforcedPolicyOptions]="enforcedPolicyOptions" *ngIf="enforcedPolicyOptions">
|
||||
</app-callout>
|
||||
</div>
|
||||
<div class="box">
|
||||
|
||||
@@ -31,6 +31,13 @@ export class SetPasswordComponent extends BaseSetPasswordComponent {
|
||||
syncService: SyncService, route: ActivatedRoute) {
|
||||
super(i18nService, cryptoService, messagingService, userService, passwordGenerationService,
|
||||
platformUtilsService, policyService, router, apiService, syncService, route);
|
||||
super.onSuccessfulChangePassword = async () => {
|
||||
if (await this.userService.getForcePasswordReset()) {
|
||||
this.router.navigate(['update-temp-password']);
|
||||
} else {
|
||||
this.router.navigate([this.successRoute]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
get masterPasswordScoreWidth() {
|
||||
|
||||
@@ -15,6 +15,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
|
||||
import { SsoComponent as BaseSsoComponent } from 'jslib-angular/components/sso.component';
|
||||
import { BrowserApi } from '../../browser/browserApi';
|
||||
@@ -29,7 +30,7 @@ export class SsoComponent extends BaseSsoComponent {
|
||||
storageService: StorageService, stateService: StateService,
|
||||
platformUtilsService: PlatformUtilsService, apiService: ApiService,
|
||||
cryptoFunctionService: CryptoFunctionService, passwordGenerationService: PasswordGenerationService,
|
||||
syncService: SyncService, environmentService: EnvironmentService) {
|
||||
syncService: SyncService, environmentService: EnvironmentService, private userService: UserService) {
|
||||
super(authService, router, i18nService, route, storageService, stateService, platformUtilsService,
|
||||
apiService, cryptoFunctionService, environmentService, passwordGenerationService);
|
||||
|
||||
@@ -44,5 +45,13 @@ export class SsoComponent extends BaseSsoComponent {
|
||||
const thisWindow = window.open('', '_self');
|
||||
thisWindow.close();
|
||||
};
|
||||
|
||||
super.onSuccessfulLoginNavigate = async () => {
|
||||
if (await this.userService.getForcePasswordReset()) {
|
||||
this.router.navigate(['update-temp-password']);
|
||||
} else {
|
||||
this.router.navigate([this.successRoute]);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.WebAuthn && !webAuthnNewTab">
|
||||
<div id="web-authn-frame"><iframe id="webauthn_iframe"></iframe></div>
|
||||
<div id="web-authn-frame"><iframe id="webauthn_iframe" [allow]="webAuthnAllow"></iframe></div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
|
||||
@@ -20,6 +20,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
|
||||
@@ -44,11 +45,16 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
||||
environmentService: EnvironmentService, private ngZone: NgZone,
|
||||
private broadcasterService: BroadcasterService, private changeDetectorRef: ChangeDetectorRef,
|
||||
private popupUtilsService: PopupUtilsService, stateService: StateService,
|
||||
storageService: StorageService, route: ActivatedRoute, private messagingService: MessagingService) {
|
||||
storageService: StorageService, route: ActivatedRoute, private messagingService: MessagingService,
|
||||
private userService: UserService) {
|
||||
super(authService, router, i18nService, apiService, platformUtilsService, window, environmentService,
|
||||
stateService, storageService, route);
|
||||
super.onSuccessfulLogin = () => {
|
||||
return syncService.fullSync(true);
|
||||
super.onSuccessfulLogin = async () => {
|
||||
return syncService.fullSync(true).then(async () => {
|
||||
if (await this.userService.getForcePasswordReset()) {
|
||||
this.router.navigate(['update-temp-password']);
|
||||
}
|
||||
});
|
||||
};
|
||||
super.successRoute = '/tabs/vault';
|
||||
this.webAuthnNewTab = this.platformUtilsService.isFirefox() || this.platformUtilsService.isSafari();
|
||||
|
||||
86
src/popup/accounts/update-temp-password.component.html
Normal file
86
src/popup/accounts/update-temp-password.component.html
Normal file
@@ -0,0 +1,86 @@
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a (click)="logOut()">{{'logOut' | i18n}}</a>
|
||||
</div>
|
||||
<div class="center">
|
||||
<span class="title">{{'updateMasterPassword' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{'submit' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<app-callout type="warning" title="{{'updateMasterPassword' | i18n}}">
|
||||
{{'updateMasterPasswordWarning' | i18n}}
|
||||
</app-callout>
|
||||
<app-callout type="info" [enforcedPolicyOptions]="enforcedPolicyOptions" *ngIf="enforcedPolicyOptions">
|
||||
</app-callout>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<div class="box-content-row-flex">
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">
|
||||
{{'masterPass' | i18n}}
|
||||
<strong class="sub-label text-{{masterPasswordScoreStyle.Color}}"
|
||||
*ngIf="masterPasswordScoreStyle.Text">
|
||||
{{masterPasswordScoreStyle.Text}}
|
||||
</strong>
|
||||
</label>
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}"
|
||||
name="MasterPassword" class="monospaced" [(ngModel)]="masterPassword" required
|
||||
appInputVerbatim (input)="updatePasswordStrength()">
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-{{masterPasswordScoreStyle.Color}}" role="progressbar"
|
||||
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"
|
||||
[ngStyle]="{width: (masterPasswordScoreStyle.Width + '%')}"
|
||||
attr.aria-valuenow="{{masterPasswordScoreStyle.Width}}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPasswordRetype">{{'reTypeMasterPass' | i18n}}</label>
|
||||
<input id="masterPasswordRetype" type="{{showPassword ? 'text' : 'password'}}"
|
||||
name="MasterPasswordRetype" class="monospaced" [(ngModel)]="masterPasswordRetype" required
|
||||
appInputVerbatim>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(true)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="hint">{{'masterPassHint' | i18n}}</label>
|
||||
<input id="hint" type="text" name="Hint" [(ngModel)]="hint">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'masterPassHintDesc' | i18n}}
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
</form>
|
||||
62
src/popup/accounts/update-temp-password.component.ts
Normal file
62
src/popup/accounts/update-temp-password.component.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { PolicyService } from 'jslib-common/abstractions/policy.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
|
||||
import { UpdateTempPasswordComponent as BaseUpdateTempPasswordComponent } from 'jslib-angular/components/update-temp-password.component';
|
||||
|
||||
interface MasterPasswordScore {
|
||||
Color: string;
|
||||
Text: string;
|
||||
Width: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-update-temp-password',
|
||||
templateUrl: 'update-temp-password.component.html',
|
||||
})
|
||||
export class UpdateTempPasswordComponent extends BaseUpdateTempPasswordComponent {
|
||||
get masterPasswordScoreStyle(): MasterPasswordScore {
|
||||
const scoreWidth = this.masterPasswordScore == null ? 0 : (this.masterPasswordScore + 1) * 20;
|
||||
switch (this.masterPasswordScore) {
|
||||
case 4:
|
||||
return {
|
||||
Color: 'bg-success',
|
||||
Text: 'strong',
|
||||
Width: scoreWidth,
|
||||
};
|
||||
case 3:
|
||||
return {
|
||||
Color: 'bg-primary',
|
||||
Text: 'good',
|
||||
Width: scoreWidth,
|
||||
};
|
||||
case 2:
|
||||
return {
|
||||
Color: 'bg-warning',
|
||||
Text: 'weak',
|
||||
Width: scoreWidth,
|
||||
};
|
||||
default:
|
||||
return {
|
||||
Color: 'bg-danger',
|
||||
Text: 'weak',
|
||||
Width: scoreWidth,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
constructor(i18nService: I18nService, platformUtilsService: PlatformUtilsService,
|
||||
passwordGenerationService: PasswordGenerationService, policyService: PolicyService,
|
||||
cryptoService: CryptoService, userService: UserService,
|
||||
messagingService: MessagingService, apiService: ApiService) {
|
||||
super(i18nService, platformUtilsService, passwordGenerationService, policyService, cryptoService,
|
||||
userService, messagingService, apiService);
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import { SetPasswordComponent } from './accounts/set-password.component';
|
||||
import { SsoComponent } from './accounts/sso.component';
|
||||
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
|
||||
import { TwoFactorComponent } from './accounts/two-factor.component';
|
||||
import { UpdateTempPasswordComponent } from './accounts/update-temp-password.component';
|
||||
|
||||
import { PasswordGeneratorHistoryComponent } from './generator/password-generator-history.component';
|
||||
import { PasswordGeneratorComponent } from './generator/password-generator.component';
|
||||
@@ -261,6 +262,12 @@ const routes: Routes = [
|
||||
canActivate: [AuthGuardService],
|
||||
data: { state: 'edit-send' },
|
||||
},
|
||||
{
|
||||
path: 'update-temp-password',
|
||||
component: UpdateTempPasswordComponent,
|
||||
canActivate: [AuthGuardService],
|
||||
data: { state: 'update-temp-password' },
|
||||
},
|
||||
{
|
||||
path: 'tabs',
|
||||
component: TabsComponent,
|
||||
|
||||
@@ -106,8 +106,6 @@ export class AppComponent implements OnInit {
|
||||
});
|
||||
} else if (msg.command === 'showDialog') {
|
||||
await this.showDialog(msg);
|
||||
} else if (msg.command === 'showPasswordDialog') {
|
||||
await this.showPasswordDialog(msg);
|
||||
} else if (msg.command === 'showToast') {
|
||||
this.ngZone.run(() => {
|
||||
this.showToast(msg);
|
||||
@@ -251,30 +249,4 @@ export class AppComponent implements OnInit {
|
||||
confirmed: confirmed.value,
|
||||
});
|
||||
}
|
||||
|
||||
private async showPasswordDialog(msg: any) {
|
||||
const platformUtils = this.platformUtilsService as BrowserPlatformUtilsService;
|
||||
const result = await Swal.fire({
|
||||
heightAuto: false,
|
||||
titleText: msg.title,
|
||||
input: 'password',
|
||||
text: msg.body,
|
||||
confirmButtonText: this.i18nService.t('ok'),
|
||||
showCancelButton: true,
|
||||
cancelButtonText: this.i18nService.t('cancel'),
|
||||
inputAttributes: {
|
||||
autocapitalize: 'off',
|
||||
autocorrect: 'off',
|
||||
},
|
||||
inputValidator: async (value: string): Promise<any> => {
|
||||
if (await platformUtils.resolvePasswordDialogPromise(msg.dialogId, false, value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.i18nService.t('invalidMasterPassword');
|
||||
},
|
||||
});
|
||||
|
||||
platformUtils.resolvePasswordDialogPromise(msg.dialogId, true, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { A11yModule } from '@angular/cdk/a11y';
|
||||
import { DragDropModule } from '@angular/cdk/drag-drop';
|
||||
import { ScrollingModule } from '@angular/cdk/scrolling';
|
||||
import { ToasterModule } from 'angular2-toaster';
|
||||
@@ -20,6 +21,7 @@ import { SetPasswordComponent } from './accounts/set-password.component';
|
||||
import { SsoComponent } from './accounts/sso.component';
|
||||
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
|
||||
import { TwoFactorComponent } from './accounts/two-factor.component';
|
||||
import { UpdateTempPasswordComponent } from './accounts/update-temp-password.component';
|
||||
|
||||
import { PasswordGeneratorHistoryComponent } from './generator/password-generator-history.component';
|
||||
import { PasswordGeneratorComponent } from './generator/password-generator.component';
|
||||
@@ -36,6 +38,7 @@ import { OptionsComponent } from './settings/options.component';
|
||||
import { PremiumComponent } from './settings/premium.component';
|
||||
import { SettingsComponent } from './settings/settings.component';
|
||||
import { SyncComponent } from './settings/sync.component';
|
||||
import { VaultTimeoutInputComponent } from './settings/vault-timeout-input.component';
|
||||
|
||||
import { AddEditComponent } from './vault/add-edit.component';
|
||||
import { AttachmentsComponent } from './vault/attachments.component';
|
||||
@@ -57,6 +60,7 @@ import { ApiActionDirective } from 'jslib-angular/directives/api-action.directiv
|
||||
import { AutofocusDirective } from 'jslib-angular/directives/autofocus.directive';
|
||||
import { BlurClickDirective } from 'jslib-angular/directives/blur-click.directive';
|
||||
import { BoxRowDirective } from 'jslib-angular/directives/box-row.directive';
|
||||
import { CipherListVirtualScroll } from 'jslib-angular/directives/cipherListVirtualScroll.directive';
|
||||
import { FallbackSrcDirective } from 'jslib-angular/directives/fallback-src.directive';
|
||||
import { InputVerbatimDirective } from 'jslib-angular/directives/input-verbatim.directive';
|
||||
import { SelectCopyDirective } from 'jslib-angular/directives/select-copy.directive';
|
||||
@@ -70,8 +74,10 @@ import { SearchCiphersPipe } from 'jslib-angular/pipes/search-ciphers.pipe';
|
||||
|
||||
import { ActionButtonsComponent } from './components/action-buttons.component';
|
||||
import { CipherRowComponent } from './components/cipher-row.component';
|
||||
import { PasswordRepromptComponent } from './components/password-reprompt.component';
|
||||
import { PopOutComponent } from './components/pop-out.component';
|
||||
import { SendListComponent } from './components/send-list.component';
|
||||
import { SetPinComponent } from './components/set-pin.component';
|
||||
|
||||
import { CalloutComponent } from 'jslib-angular/components/callout.component';
|
||||
import { IconComponent } from 'jslib-angular/components/icon.component';
|
||||
@@ -169,6 +175,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
A11yModule,
|
||||
AppRoutingModule,
|
||||
BrowserAnimationsModule,
|
||||
BrowserModule,
|
||||
@@ -190,6 +197,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
|
||||
BlurClickDirective,
|
||||
BoxRowDirective,
|
||||
CalloutComponent,
|
||||
CipherListVirtualScroll,
|
||||
CipherRowComponent,
|
||||
CiphersComponent,
|
||||
CollectionsComponent,
|
||||
@@ -224,8 +232,10 @@ registerLocaleData(localeZhTw, 'zh-TW');
|
||||
SendGroupingsComponent,
|
||||
SendListComponent,
|
||||
SendTypeComponent,
|
||||
SetPasswordComponent,
|
||||
SettingsComponent,
|
||||
ShareComponent,
|
||||
SsoComponent,
|
||||
StopClickDirective,
|
||||
StopPropDirective,
|
||||
SyncComponent,
|
||||
@@ -233,9 +243,11 @@ registerLocaleData(localeZhTw, 'zh-TW');
|
||||
TrueFalseValueDirective,
|
||||
TwoFactorOptionsComponent,
|
||||
TwoFactorComponent,
|
||||
SsoComponent,
|
||||
UpdateTempPasswordComponent,
|
||||
ViewComponent,
|
||||
SetPasswordComponent,
|
||||
PasswordRepromptComponent,
|
||||
SetPinComponent,
|
||||
VaultTimeoutInputComponent,
|
||||
],
|
||||
entryComponents: [],
|
||||
providers: [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<a (click)="selectCipher(cipher)" (dblclick)="launchCipher(cipher)" href="#" appStopClick
|
||||
title="{{title}} - {{cipher.name}}" class="box-content-row box-content-row-flex">
|
||||
title="{{title}} - {{cipher.name}}" class="box-content-row box-content-row-flex virtual-scroll-item">
|
||||
<div class="row-main">
|
||||
<app-vault-icon [cipher]="cipher"></app-vault-icon>
|
||||
<div class="row-main-content">
|
||||
|
||||
38
src/popup/components/password-reprompt.component.html
Normal file
38
src/popup/components/password-reprompt.component.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true">
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<form class="modal-content" #form (ngSubmit)="submit()">
|
||||
<div class="modal-body">
|
||||
<div class="box">
|
||||
<div class="box-header">{{'passwordConfirmation' | i18n}}</div>
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">{{'masterPass' | i18n}}</label>
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword"
|
||||
class="monospaced" [(ngModel)]="masterPassword" required appAutofocus>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick role="button"
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword()">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'passwordConfirmationDesc' | i18n}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary btn-submit" appBlurClick>
|
||||
<span>{{'ok' | i18n}}</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
|
||||
{{'cancel' | i18n}}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
8
src/popup/components/password-reprompt.component.ts
Normal file
8
src/popup/components/password-reprompt.component.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { PasswordRepromptComponent as BasePasswordRepromptComponent } from 'jslib-angular/components/password-reprompt.component';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'password-reprompt.component.html',
|
||||
})
|
||||
export class PasswordRepromptComponent extends BasePasswordRepromptComponent {}
|
||||
44
src/popup/components/set-pin.component.html
Normal file
44
src/popup/components/set-pin.component.html
Normal file
@@ -0,0 +1,44 @@
|
||||
<div class="modal fade" tabindex="-1" role="dialog" aria-modal="true" cdkTrapFocus cdkTrapFocusAutoCapture>
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<form class="modal-content" #form (ngSubmit)="submit()">
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
{{'setYourPinCode' | i18n}}
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="pin">{{'pin' | i18n}}</label>
|
||||
<input id="pin" type="{{showPin ? 'text' : 'password'}}" name="Pin"
|
||||
class="monospaced" [(ngModel)]="pin" required appInputVerbatim cdkFocusInitial>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
(click)="toggleVisibility()">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPin, 'fa-eye-slash': showPin}"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label for="masterPasswordOnRestart">
|
||||
<input type="checkbox" id="masterPasswordOnRestart" name="MasterPasswordOnRestart"
|
||||
[(ngModel)]="masterPassOnRestart">
|
||||
<span>{{'lockWithMasterPassOnRestart' | i18n}}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary btn-submit" appBlurClick>
|
||||
<span>{{'ok' | i18n}}</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
|
||||
{{'cancel' | i18n}}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
8
src/popup/components/set-pin.component.ts
Normal file
8
src/popup/components/set-pin.component.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { SetPinComponent as BaseSetPinComponent } from 'jslib-angular/components/set-pin.component';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'set-pin.component.html',
|
||||
})
|
||||
export class SetPinComponent extends BaseSetPinComponent {}
|
||||
@@ -200,6 +200,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.last:last-child:before {
|
||||
border-bottom: 1px solid #000000;
|
||||
@include themify($themes) {
|
||||
border-bottom-color: themed('boxBorderColor');
|
||||
}
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
|
||||
11
src/popup/scss/grid.scss
Normal file
11
src/popup/scss/grid.scss
Normal file
@@ -0,0 +1,11 @@
|
||||
.row {
|
||||
display: flex;
|
||||
margin: 0 -15px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.col {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
padding: 0 15px;
|
||||
}
|
||||
@@ -339,6 +339,11 @@ app-vault-icon {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.enforced-policy-options ul {
|
||||
padding-left: 30px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="password"]::-ms-reveal {
|
||||
|
||||
351
src/popup/scss/modal.scss
Normal file
351
src/popup/scss/modal.scss
Normal file
@@ -0,0 +1,351 @@
|
||||
@import "variables.scss";
|
||||
|
||||
$white: white;
|
||||
$black: black;
|
||||
$line-height-base: 14px;
|
||||
$border-radius-lg: $border-radius;
|
||||
|
||||
// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_variables.scss
|
||||
|
||||
$grid-breakpoints: ( xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px ) !default;
|
||||
|
||||
$zindex-modal-backdrop: 1040 !default;
|
||||
$zindex-modal: 1050 !default;
|
||||
|
||||
// Padding applied to the modal body
|
||||
$modal-inner-padding: 10px !default;
|
||||
|
||||
$modal-dialog-margin: .5rem !default;
|
||||
$modal-dialog-margin-y-sm-up: 1.75rem !default;
|
||||
|
||||
$modal-title-line-height: $line-height-base !default;
|
||||
|
||||
//$modal-content-bg: $background-color-alt !default;
|
||||
$modal-content-border-color: rgba($black, .2) !default;
|
||||
$modal-content-border-width: 1px !default;
|
||||
$modal-content-box-shadow-xs: none;
|
||||
$modal-content-box-shadow-sm-up: none;
|
||||
|
||||
$modal-backdrop-bg: $black !default;
|
||||
$modal-backdrop-opacity: .5 !default;
|
||||
$modal-header-border-color: $border-color-dark !default;
|
||||
$modal-footer-border-color: $modal-header-border-color !default;
|
||||
$modal-header-border-width: $modal-content-border-width !default;
|
||||
$modal-footer-border-width: $modal-header-border-width !default;
|
||||
$modal-header-padding: 12px !default;
|
||||
|
||||
$modal-lg: 800px !default;
|
||||
$modal-md: 500px !default;
|
||||
$modal-sm: 300px !default;
|
||||
|
||||
$modal-transition: transform .3s ease-out !default;
|
||||
|
||||
$close-font-size: $font-size-base * 1.5 !default;
|
||||
$close-font-weight: bold !default;
|
||||
$close-color: $black !default;
|
||||
$close-text-shadow: 0 1px 0 $white !default;
|
||||
|
||||
// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/mixins/_breakpoints.scss
|
||||
|
||||
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
|
||||
$min: breakpoint-min($name, $breakpoints);
|
||||
|
||||
@if $min {
|
||||
@media (min-width: $min) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
@else {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
|
||||
$min: map-get($breakpoints, $name);
|
||||
@return if($min != 0, $min, null);
|
||||
}
|
||||
|
||||
// Custom Added CSS animations
|
||||
|
||||
@keyframes modalshow {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate(0, -25%);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes backdropshow {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: $modal-backdrop-opacity;
|
||||
}
|
||||
}
|
||||
|
||||
// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_modal.scss
|
||||
|
||||
// .modal-open - body class for killing the scroll
|
||||
// .modal - container to scroll within
|
||||
// .modal-dialog - positioning shell for the actual modal
|
||||
// .modal-content - actual modal w/ bg and corners and stuff
|
||||
|
||||
|
||||
// Kill the scroll on the body
|
||||
.modal-open {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// Container that the modal scrolls within
|
||||
.modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: $zindex-modal;
|
||||
//display: none;
|
||||
overflow: hidden;
|
||||
// Prevent Chrome on Windows from adding a focus outline. For details, see
|
||||
// https://github.com/twbs/bootstrap/pull/10951.
|
||||
outline: 0;
|
||||
// We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a
|
||||
// gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342
|
||||
// See also https://github.com/twbs/bootstrap/issues/17695
|
||||
.modal-open & {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// Shell div to position the modal with bottom padding
|
||||
.modal-dialog {
|
||||
position: relative;
|
||||
width: auto;
|
||||
margin: $modal-dialog-margin;
|
||||
// allow clicks to pass through for custom click handling to close modal
|
||||
pointer-events: none;
|
||||
// When fading in the modal, animate it to slide down
|
||||
.modal.fade & {
|
||||
//@include transition($modal-transition);
|
||||
//transform: translate(0, -25%);
|
||||
animation: modalshow 0.3s ease-in;
|
||||
}
|
||||
//.modal.show & {
|
||||
// transform: translate(0, 0);
|
||||
//}
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
|
||||
.modal-dialog-centered {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: calc(100% - (#{$modal-dialog-margin} * 2));
|
||||
}
|
||||
|
||||
// Actual modal
|
||||
.modal-content {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%; // Ensure `.modal-content` extends the full width of the parent `.modal-dialog`
|
||||
// counteract the pointer-events: none; in the .modal-dialog
|
||||
pointer-events: auto;
|
||||
//background-color: $modal-content-bg;
|
||||
background-clip: padding-box;
|
||||
border: $modal-content-border-width solid $modal-content-border-color;
|
||||
//@include border-radius($border-radius-lg);
|
||||
//@include box-shadow($modal-content-box-shadow-xs);
|
||||
border-radius: $border-radius-lg;
|
||||
box-shadow: $modal-content-box-shadow-xs;
|
||||
// Remove focus outline from opened modal
|
||||
outline: 0;
|
||||
|
||||
@include themify($themes) {
|
||||
background-color: themed('backgroundColorAlt');
|
||||
}
|
||||
}
|
||||
|
||||
// Modal background
|
||||
.modal-backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: $zindex-modal-backdrop;
|
||||
background-color: $modal-backdrop-bg;
|
||||
// Fade for backdrop
|
||||
&.fade {
|
||||
//opacity: 0;
|
||||
animation: backdropshow 0.1s ease-in;
|
||||
}
|
||||
//&.show {
|
||||
// opacity: $modal-backdrop-opacity;
|
||||
//}
|
||||
opacity: $modal-backdrop-opacity;
|
||||
}
|
||||
|
||||
// Modal header
|
||||
// Top section of the modal w/ title and dismiss
|
||||
.modal-header {
|
||||
display: flex;
|
||||
align-items: flex-start; // so the close btn always stays on the upper right corner
|
||||
justify-content: space-between; // Put modal header elements (title and dismiss) on opposite ends
|
||||
padding: $modal-header-padding $modal-inner-padding;
|
||||
border-bottom: $modal-header-border-width solid $modal-header-border-color;
|
||||
//@include border-top-radius($border-radius-lg);
|
||||
|
||||
@include themify($themes) {
|
||||
border-bottom-color: themed('borderColor');
|
||||
}
|
||||
|
||||
.close {
|
||||
padding: $modal-header-padding $modal-inner-padding;
|
||||
// auto on the left force icon to the right even when there is no .modal-title
|
||||
margin: (-$modal-header-padding) (-$modal-inner-padding) (-$modal-header-padding) auto;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: $font-size-base;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.fa {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Title text within header
|
||||
.modal-title {
|
||||
margin-bottom: 0;
|
||||
line-height: $modal-title-line-height;
|
||||
}
|
||||
|
||||
// Modal body
|
||||
// Where all modal content resides (sibling of .modal-header and .modal-footer)
|
||||
.modal-body {
|
||||
position: relative;
|
||||
// Enable `flex-grow: 1` so that the body take up as much space as possible
|
||||
// when should there be a fixed height on `.modal-dialog`.
|
||||
flex: 1 1 auto;
|
||||
padding: $modal-inner-padding;
|
||||
}
|
||||
|
||||
// Footer (for actions)
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
align-items: center; // vertically center
|
||||
//justify-content: flex-end; // Right align buttons with flex property because text-align doesn't work on flex items
|
||||
padding: $modal-inner-padding;
|
||||
border-top: $modal-footer-border-width solid $modal-footer-border-color;
|
||||
|
||||
@include themify($themes) {
|
||||
border-top-color: themed('borderColor');
|
||||
}
|
||||
|
||||
// Easily place margin between footer elements
|
||||
button {
|
||||
margin-right: 10px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
// Measure scrollbar width for padding body during modal show/hide
|
||||
.modal-scrollbar-measure {
|
||||
position: absolute;
|
||||
top: -9999px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
// Scale up the modal
|
||||
@include media-breakpoint-up(sm) {
|
||||
// Automatically set modal's width for larger viewports
|
||||
.modal-dialog {
|
||||
max-width: $modal-md;
|
||||
margin: $modal-dialog-margin-y-sm-up auto;
|
||||
}
|
||||
|
||||
.modal-dialog-centered {
|
||||
min-height: calc(100% - (#{$modal-dialog-margin-y-sm-up} * 2));
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
//@include box-shadow($modal-content-box-shadow-sm-up);
|
||||
box-shadow: $modal-content-box-shadow-sm-up;
|
||||
}
|
||||
|
||||
.modal-sm {
|
||||
max-width: $modal-sm;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
.modal-lg {
|
||||
max-width: $modal-lg;
|
||||
}
|
||||
}
|
||||
|
||||
// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_close.scss
|
||||
|
||||
.close {
|
||||
float: right;
|
||||
font-size: $close-font-size;
|
||||
font-weight: $close-font-weight;
|
||||
line-height: 1;
|
||||
color: $close-color;
|
||||
text-shadow: $close-text-shadow;
|
||||
opacity: .5;
|
||||
|
||||
&:hover, &:focus {
|
||||
color: $close-color;
|
||||
text-decoration: none;
|
||||
opacity: .75;
|
||||
}
|
||||
// Opinionated: add "hand" cursor to non-disabled .close elements
|
||||
&:not(:disabled):not(.disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
// Additional properties for button version
|
||||
// iOS requires the button element instead of an anchor tag.
|
||||
// If you want the anchor version, it requires `href="#"`.
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
|
||||
|
||||
// stylelint-disable property-no-vendor-prefix, selector-no-qualifying-type
|
||||
button.close {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
// stylelint-enable
|
||||
|
||||
// box
|
||||
|
||||
.modal-content .box {
|
||||
margin-top: 20px;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
@import "../css/webfonts.css";
|
||||
@import "variables.scss";
|
||||
@import "base.scss";
|
||||
@import "grid.scss";
|
||||
@import "box.scss";
|
||||
@import "buttons.scss";
|
||||
@import "misc.scss";
|
||||
@import "modal.scss";
|
||||
@import "plugins.scss";
|
||||
@import "environment.scss";
|
||||
@import "pages.scss";
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
<i *ngIf="showOptions" class="fa fa-chevron-up fa-sm icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="showOptions">
|
||||
<div [hidden]="!showOptions">
|
||||
<app-send-efflux-dates
|
||||
[initialDeletionDate]="send.deletionDate" [initialExpirationDate]="send.expirationDate"
|
||||
[editMode]="editMode" [disabled]="disableSend" (datesChanged)="setDates($event)" (popOutWindow)="popOutWindow()">
|
||||
@@ -200,7 +200,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
<!-- Delete -->
|
||||
<div class="box list" *ngIf="editMode">
|
||||
<div class="box-content single-line">
|
||||
|
||||
11
src/popup/services/password-reprompt.service.ts
Normal file
11
src/popup/services/password-reprompt.service.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { PasswordRepromptService as BasePasswordRepromptService } from 'jslib-angular/services/passwordReprompt.service';
|
||||
|
||||
import { PasswordRepromptComponent } from '../components/password-reprompt.component';
|
||||
|
||||
@Injectable()
|
||||
export class PasswordRepromptService extends BasePasswordRepromptService {
|
||||
component = PasswordRepromptComponent;
|
||||
}
|
||||
@@ -9,10 +9,12 @@ import { ToasterModule } from 'angular2-toaster';
|
||||
import { DebounceNavigationService } from './debounceNavigationService';
|
||||
import { LaunchGuardService } from './launch-guard.service';
|
||||
import { LockGuardService } from './lock-guard.service';
|
||||
import { PasswordRepromptService } from './password-reprompt.service';
|
||||
import { UnauthGuardService } from './unauth-guard.service';
|
||||
|
||||
import { AuthGuardService } from 'jslib-angular/services/auth-guard.service';
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
import { ModalService } from 'jslib-angular/services/modal.service';
|
||||
import { ValidationService } from 'jslib-angular/services/validation.service';
|
||||
|
||||
import { BrowserApi } from '../../browser/browserApi';
|
||||
@@ -48,7 +50,6 @@ import { TokenService } from 'jslib-common/abstractions/token.service';
|
||||
import { TotpService } from 'jslib-common/abstractions/totp.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
|
||||
import { PasswordRepromptService } from 'jslib-common/services/passwordReprompt.service';
|
||||
|
||||
import { AutofillService } from '../../services/abstractions/autofill.service';
|
||||
import BrowserMessagingService from '../../services/browserMessaging.service';
|
||||
@@ -76,8 +77,6 @@ const messagingService = new BrowserMessagingService();
|
||||
const searchService = isPrivateMode ? null : new PopupSearchService(getBgService<SearchService>('searchService')(),
|
||||
getBgService<CipherService>('cipherService')(), getBgService<ConsoleLogService>('consoleLogService')(),
|
||||
getBgService<I18nService>('i18nService')());
|
||||
const passwordRepromptService = isPrivateMode ? null : new PasswordRepromptService(getBgService<I18nService>('i18nService')(),
|
||||
getBgService<CryptoService>('cryptoService')(), getBgService<PlatformUtilsService>('platformUtilsService')());
|
||||
|
||||
export function initFactory(platformUtilsService: PlatformUtilsService, i18nService: I18nService, storageService: StorageService,
|
||||
popupUtilsService: PopupUtilsService): Function {
|
||||
@@ -126,6 +125,7 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ
|
||||
DebounceNavigationService,
|
||||
PopupUtilsService,
|
||||
BroadcasterService,
|
||||
ModalService,
|
||||
{ provide: MessagingService, useValue: messagingService },
|
||||
{ provide: AuthServiceAbstraction, useFactory: getBgService<AuthService>('authService'), deps: [] },
|
||||
{ provide: StateServiceAbstraction, useValue: stateService },
|
||||
@@ -188,7 +188,7 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ
|
||||
useFactory: () => isPrivateMode ? null : getBgService<I18nService>('i18nService')().translationLocale,
|
||||
deps: [],
|
||||
},
|
||||
{ provide: PasswordRepromptServiceAbstraction, useValue: passwordRepromptService },
|
||||
{ provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService },
|
||||
],
|
||||
})
|
||||
export class ServicesModule {
|
||||
|
||||
@@ -10,15 +10,19 @@
|
||||
<span class="title">{{'exportVault' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button appBlurClick type="submit">{{'submit' | i18n}}</button>
|
||||
<button appBlurClick type="submit" [disabled]="disabledByPolicy">{{'submit' | i18n}}</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<app-callout type="warning" title="{{'vaultExportDisabled' | i18n}}" *ngIf="disabledByPolicy">
|
||||
{{'personalVaultExportPolicyInEffect' | i18n}}
|
||||
</app-callout>
|
||||
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="format">{{'fileFormat' | i18n}}</label>
|
||||
<select id="format" name="Format" [(ngModel)]="format">
|
||||
<select id="format" name="Format" [(ngModel)]="format" [disabled]="disabledByPolicy">
|
||||
<option value="json">.json</option>
|
||||
<option value="csv">.csv</option>
|
||||
<option value="encrypted_json">.json (Encrypted)</option>
|
||||
@@ -28,7 +32,8 @@
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">{{'masterPass' | i18n}}</label>
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword"
|
||||
class="monospaced" [(ngModel)]="masterPassword" required appInputVerbatim appAutofocus>
|
||||
class="monospaced" [(ngModel)]="masterPassword" required appInputVerbatim appAutofocus
|
||||
[disabled]="disabledByPolicy">
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
|
||||
@@ -6,6 +6,7 @@ import { EventService } from 'jslib-common/abstractions/event.service';
|
||||
import { ExportService } from 'jslib-common/abstractions/export.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { PolicyService } from 'jslib-common/abstractions/policy.service';
|
||||
|
||||
import { ExportComponent as BaseExportComponent } from 'jslib-angular/components/export.component';
|
||||
|
||||
@@ -16,8 +17,8 @@ import { ExportComponent as BaseExportComponent } from 'jslib-angular/components
|
||||
export class ExportComponent extends BaseExportComponent {
|
||||
constructor(cryptoService: CryptoService, i18nService: I18nService,
|
||||
platformUtilsService: PlatformUtilsService, exportService: ExportService,
|
||||
eventService: EventService, private router: Router) {
|
||||
super(cryptoService, i18nService, platformUtilsService, exportService, eventService, window);
|
||||
eventService: EventService, policyService: PolicyService, private router: Router) {
|
||||
super(cryptoService, i18nService, platformUtilsService, exportService, eventService, policyService, window);
|
||||
}
|
||||
|
||||
protected saved() {
|
||||
|
||||
@@ -28,13 +28,7 @@
|
||||
<div class="box list">
|
||||
<div class="box-header">{{'security' | i18n}}</div>
|
||||
<div class="box-content single-line">
|
||||
<div class="box-content-row display-block" appBoxRow>
|
||||
<label for="vaultTimeout">{{'vaultTimeout' | i18n}}</label>
|
||||
<select #vaultTimeoutSelect id="vaultTimeout" name="VaultTimeouts" [ngModel]="vaultTimeout"
|
||||
(ngModelChange)="saveVaultTimeout($event)">
|
||||
<option *ngFor="let o of vaultTimeouts" [ngValue]="o.value">{{o.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<app-vault-timeout-input [vaultTimeouts]="vaultTimeouts" [formControl]="vaultTimeout" ngDefaultControl></app-vault-timeout-input>
|
||||
<div class="box-content-row display-block" appBoxRow>
|
||||
<label for="vaultTimeoutAction">{{'vaultTimeoutAction' | i18n}}</label>
|
||||
<select #vaultTimeoutActionSelect id="vaultTimeoutAction" name="VaultTimeoutActions"
|
||||
@@ -50,6 +44,10 @@
|
||||
<label for="biometric">{{'unlockWithBiometrics' | i18n}}</label>
|
||||
<input id="biometric" type="checkbox" (change)="updateBiometric()" [(ngModel)]="biometric">
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow *ngIf="supportsBiometric">
|
||||
<label for="autoBiometricsPrompt">{{'disableAutoBiometricsPrompt' | i18n}}</label>
|
||||
<input id="autoBiometricsPrompt" type="checkbox" (change)="updateAutoBiometricsPrompt()" [disabled]="!biometric" [(ngModel)]="disableAutoBiometricsPrompt">
|
||||
</div>
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="lock()">
|
||||
<div class="row-main">{{'lockNow' | i18n}}</div>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import Swal from 'sweetalert2/src/sweetalert2.js';
|
||||
|
||||
import {
|
||||
Component,
|
||||
ElementRef,
|
||||
OnInit,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { ToasterService } from 'angular2-toaster';
|
||||
import Swal from 'sweetalert2/src/sweetalert2.js';
|
||||
|
||||
import { BrowserApi } from '../../browser/browserApi';
|
||||
|
||||
@@ -24,6 +25,10 @@ import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
|
||||
import { PopupUtilsService } from '../services/popup-utils.service';
|
||||
|
||||
import { ModalService } from 'jslib-angular/services/modal.service';
|
||||
|
||||
import { SetPinComponent } from '../components/set-pin.component';
|
||||
|
||||
const RateUrls = {
|
||||
[DeviceType.ChromeExtension]:
|
||||
'https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews',
|
||||
@@ -44,22 +49,24 @@ const RateUrls = {
|
||||
templateUrl: 'settings.component.html',
|
||||
})
|
||||
export class SettingsComponent implements OnInit {
|
||||
@ViewChild('vaultTimeoutSelect', { read: ElementRef, static: true }) vaultTimeoutSelectRef: ElementRef;
|
||||
@ViewChild('vaultTimeoutActionSelect', { read: ElementRef, static: true }) vaultTimeoutActionSelectRef: ElementRef;
|
||||
vaultTimeouts: any[];
|
||||
vaultTimeout: number = null;
|
||||
vaultTimeoutActions: any[];
|
||||
vaultTimeoutAction: string;
|
||||
pin: boolean = null;
|
||||
supportsBiometric: boolean;
|
||||
biometric: boolean = false;
|
||||
disableAutoBiometricsPrompt = true;
|
||||
previousVaultTimeout: number = null;
|
||||
|
||||
vaultTimeout: FormControl = new FormControl(null);
|
||||
|
||||
constructor(private platformUtilsService: PlatformUtilsService, private i18nService: I18nService,
|
||||
private vaultTimeoutService: VaultTimeoutService, private storageService: StorageService,
|
||||
public messagingService: MessagingService, private router: Router,
|
||||
private environmentService: EnvironmentService, private cryptoService: CryptoService,
|
||||
private userService: UserService, private popupUtilsService: PopupUtilsService) {
|
||||
private userService: UserService, private popupUtilsService: PopupUtilsService,
|
||||
private modalService: ModalService, private toasterService: ToasterService) {
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -89,14 +96,18 @@ export class SettingsComponent implements OnInit {
|
||||
{ name: this.i18nService.t('logOut'), value: 'logOut' },
|
||||
];
|
||||
|
||||
let timeout = await this.storageService.get<number>(ConstantsService.vaultTimeoutKey);
|
||||
let timeout = await this.vaultTimeoutService.getVaultTimeout();
|
||||
if (timeout != null) {
|
||||
if (timeout === -2 && !showOnLocked) {
|
||||
timeout = -1;
|
||||
}
|
||||
this.vaultTimeout = timeout;
|
||||
this.vaultTimeout.setValue(timeout);
|
||||
}
|
||||
this.previousVaultTimeout = this.vaultTimeout;
|
||||
this.previousVaultTimeout = this.vaultTimeout.value;
|
||||
this.vaultTimeout.valueChanges.subscribe(value => {
|
||||
this.saveVaultTimeout(value);
|
||||
});
|
||||
|
||||
const action = await this.storageService.get<string>(ConstantsService.vaultTimeoutActionKey);
|
||||
this.vaultTimeoutAction = action == null ? 'lock' : action;
|
||||
|
||||
@@ -105,6 +116,8 @@ export class SettingsComponent implements OnInit {
|
||||
|
||||
this.supportsBiometric = await this.platformUtilsService.supportsBiometric();
|
||||
this.biometric = await this.vaultTimeoutService.isBiometricLockSet();
|
||||
this.disableAutoBiometricsPrompt = await this.storageService.get<boolean>(
|
||||
ConstantsService.disableAutoBiometricsPromptKey) ?? true;
|
||||
}
|
||||
|
||||
async saveVaultTimeout(newValue: number) {
|
||||
@@ -113,18 +126,19 @@ export class SettingsComponent implements OnInit {
|
||||
this.i18nService.t('neverLockWarning'), null,
|
||||
this.i18nService.t('yes'), this.i18nService.t('cancel'), 'warning');
|
||||
if (!confirmed) {
|
||||
this.vaultTimeouts.forEach((option: any, i) => {
|
||||
if (option.value === this.vaultTimeout) {
|
||||
this.vaultTimeoutSelectRef.nativeElement.value = i + ': ' + this.vaultTimeout;
|
||||
}
|
||||
});
|
||||
this.vaultTimeout.setValue(this.previousVaultTimeout);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.previousVaultTimeout = this.vaultTimeout;
|
||||
this.vaultTimeout = newValue;
|
||||
await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout != null ? this.vaultTimeout : null,
|
||||
this.vaultTimeoutAction);
|
||||
|
||||
if (!this.vaultTimeout.valid) {
|
||||
this.toasterService.popAsync('error', null, this.i18nService.t('vaultTimeoutToLarge'));
|
||||
return;
|
||||
}
|
||||
|
||||
this.previousVaultTimeout = this.vaultTimeout.value;
|
||||
|
||||
await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout.value, this.vaultTimeoutAction);
|
||||
if (this.previousVaultTimeout == null) {
|
||||
this.messagingService.send('bgReseedStorage');
|
||||
}
|
||||
@@ -145,65 +159,27 @@ export class SettingsComponent implements OnInit {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.vaultTimeout.valid) {
|
||||
this.toasterService.popAsync('error', null, this.i18nService.t('vaultTimeoutToLarge'));
|
||||
return;
|
||||
}
|
||||
|
||||
this.vaultTimeoutAction = newValue;
|
||||
await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout != null ? this.vaultTimeout : null,
|
||||
this.vaultTimeoutAction);
|
||||
await this.vaultTimeoutService.setVaultTimeoutOptions(this.vaultTimeout.value, this.vaultTimeoutAction);
|
||||
}
|
||||
|
||||
async updatePin() {
|
||||
if (this.pin) {
|
||||
const div = document.createElement('div');
|
||||
const label = document.createElement('label');
|
||||
label.className = 'checkbox';
|
||||
const checkboxText = document.createElement('span');
|
||||
const restartText = document.createTextNode(this.i18nService.t('lockWithMasterPassOnRestart'));
|
||||
checkboxText.appendChild(restartText);
|
||||
label.innerHTML = '<input type="checkbox" id="master-pass-restart" checked>';
|
||||
label.appendChild(checkboxText);
|
||||
const ref = this.modalService.open(SetPinComponent, { allowMultipleModals: true });
|
||||
|
||||
div.innerHTML =
|
||||
`<div class="swal2-text">${this.i18nService.t('setYourPinCode')}</div>` +
|
||||
'<input type="text" class="swal2-input" id="pin-val" autocomplete="off" ' +
|
||||
'autocapitalize="none" autocorrect="none" spellcheck="false" inputmode="verbatim">';
|
||||
|
||||
(div.querySelector('#pin-val') as HTMLInputElement).placeholder = this.i18nService.t('pin');
|
||||
div.appendChild(label);
|
||||
|
||||
const submitted = await Swal.fire({
|
||||
heightAuto: false,
|
||||
buttonsStyling: false,
|
||||
html: div,
|
||||
showCancelButton: true,
|
||||
cancelButtonText: this.i18nService.t('cancel'),
|
||||
showConfirmButton: true,
|
||||
confirmButtonText: this.i18nService.t('submit'),
|
||||
});
|
||||
|
||||
let pin: string = null;
|
||||
let masterPassOnRestart: boolean = null;
|
||||
if (submitted.value) {
|
||||
pin = (document.getElementById('pin-val') as HTMLInputElement).value;
|
||||
masterPassOnRestart = (document.getElementById('master-pass-restart') as HTMLInputElement).checked;
|
||||
}
|
||||
if (pin != null && pin.trim() !== '') {
|
||||
const kdf = await this.userService.getKdf();
|
||||
const kdfIterations = await this.userService.getKdfIterations();
|
||||
const email = await this.userService.getEmail();
|
||||
const pinKey = await this.cryptoService.makePinKey(pin, email, kdf, kdfIterations);
|
||||
const key = await this.cryptoService.getKey();
|
||||
const pinProtectedKey = await this.cryptoService.encrypt(key.key, pinKey);
|
||||
if (masterPassOnRestart) {
|
||||
const encPin = await this.cryptoService.encrypt(pin);
|
||||
await this.storageService.save(ConstantsService.protectedPin, encPin.encryptedString);
|
||||
this.vaultTimeoutService.pinProtectedKey = pinProtectedKey;
|
||||
} else {
|
||||
await this.storageService.save(ConstantsService.pinProtectedKey, pinProtectedKey.encryptedString);
|
||||
}
|
||||
} else {
|
||||
if (ref == null) {
|
||||
this.pin = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!this.pin) {
|
||||
|
||||
this.pin = await ref.onClosedPromise();
|
||||
} else {
|
||||
await this.cryptoService.clearPinProtectedKey();
|
||||
await this.vaultTimeoutService.clear();
|
||||
}
|
||||
@@ -277,6 +253,10 @@ export class SettingsComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
async updateAutoBiometricsPrompt() {
|
||||
await this.storageService.save(ConstantsService.disableAutoBiometricsPromptKey, this.disableAutoBiometricsPrompt);
|
||||
}
|
||||
|
||||
async lock() {
|
||||
await this.vaultTimeoutService.lock(true);
|
||||
}
|
||||
|
||||
29
src/popup/settings/vault-timeout-input.component.html
Normal file
29
src/popup/settings/vault-timeout-input.component.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<app-callout type="info" *ngIf="vaultTimeoutPolicy">
|
||||
{{'vaultTimeoutPolicyInEffect' | i18n : vaultTimeoutPolicyHours : vaultTimeoutPolicyMinutes}}
|
||||
</app-callout>
|
||||
|
||||
<div [formGroup]="form">
|
||||
<div class="box-content-row last display-block" appBoxRow>
|
||||
<label for="vaultTimeout">{{'vaultTimeout' | i18n}}</label>
|
||||
<select id="vaultTimeout" name="VaultTimeout" formControlName="vaultTimeout" class="form-control">
|
||||
<option *ngFor="let o of vaultTimeouts" [ngValue]="o.value">{{o.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="box-content-row last" *ngIf="showCustom">
|
||||
<div formGroupName="custom" class="row">
|
||||
<div class="col">
|
||||
<div class="display-block" appBoxRow>
|
||||
<label for="customVaultTimeout">{{'hours' | i18n }}</label>
|
||||
<input id="hours" class="form-control" type="number" min="0" name="hours" formControlName="hours">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="display-block" appBoxRow>
|
||||
<label for="customVaultTimeout">{{'minutes' | i18n }}</label>
|
||||
<input id="minutes" class="form-control" type="number" min="0" max="59" name="minutes"
|
||||
formControlName="minutes">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
28
src/popup/settings/vault-timeout-input.component.ts
Normal file
28
src/popup/settings/vault-timeout-input.component.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {
|
||||
NG_VALIDATORS,
|
||||
NG_VALUE_ACCESSOR,
|
||||
} from '@angular/forms';
|
||||
|
||||
import {
|
||||
VaultTimeoutInputComponent as VaultTimeoutInputComponentBase
|
||||
} from 'jslib-angular/components/settings/vault-timeout-input.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-vault-timeout-input',
|
||||
templateUrl: 'vault-timeout-input.component.html',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
multi: true,
|
||||
useExisting: VaultTimeoutInputComponent,
|
||||
},
|
||||
{
|
||||
provide: NG_VALIDATORS,
|
||||
multi: true,
|
||||
useExisting: VaultTimeoutInputComponent,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class VaultTimeoutInputComponent extends VaultTimeoutInputComponentBase {
|
||||
}
|
||||
@@ -63,7 +63,8 @@
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
<cdk-virtual-scroll-viewport itemSize="46" *ngIf="ciphers.length" #virtualScrollViewport>
|
||||
<cdk-virtual-scroll-viewport itemSize="46" minBufferPx="400" maxBufferPx="600" *ngIf="ciphers.length"
|
||||
#virtualScrollViewport>
|
||||
<div class="box list only-list">
|
||||
<div class="box-header">
|
||||
{{groupingTitle}}
|
||||
|
||||
@@ -145,7 +145,8 @@
|
||||
<div class="no-items" *ngIf="!ciphers || !ciphers.length">
|
||||
<p>{{'noItemsInList' | i18n}}</p>
|
||||
</div>
|
||||
<cdk-virtual-scroll-viewport itemSize="46" *ngIf="ciphers && ciphers.length > 0">
|
||||
<cdk-virtual-scroll-viewport itemSize="46" minBufferPx="400" maxBufferPx="600"
|
||||
*ngIf="ciphers && ciphers.length > 0">
|
||||
<div class="box list full-list">
|
||||
<div class="box-content">
|
||||
<app-cipher-row *cdkVirtualFor="let searchedCipher of ciphers" [cipher]="searchedCipher"
|
||||
|
||||
@@ -21,18 +21,19 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se
|
||||
import { TokenService } from 'jslib-common/abstractions/token.service';
|
||||
import { TotpService } from 'jslib-common/abstractions/totp.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
import { Cipher } from 'jslib-common/models/domain';
|
||||
import { LoginUriView } from 'jslib-common/models/view';
|
||||
|
||||
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
|
||||
|
||||
import { Cipher } from 'jslib-common/models/domain/cipher';
|
||||
import { LoginUriView } from 'jslib-common/models/view/loginUriView';
|
||||
|
||||
import { CipherType } from 'jslib-common/enums/cipherType';
|
||||
|
||||
import { ViewComponent as BaseViewComponent } from 'jslib-angular/components/view.component';
|
||||
import { BrowserApi } from '../../browser/browserApi';
|
||||
import { AutofillService } from '../../services/abstractions/autofill.service';
|
||||
import { PopupUtilsService } from '../services/popup-utils.service';
|
||||
|
||||
import { CipherType } from 'jslib-common/enums';
|
||||
|
||||
const BroadcasterSubscriptionId = 'ChildViewComponent';
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import {
|
||||
CipherType,
|
||||
FieldType,
|
||||
} from 'jslib-common/enums';
|
||||
import { CipherService } from 'jslib-common/abstractions/cipher.service';
|
||||
import { EventService } from 'jslib-common/abstractions/event.service';
|
||||
import { TotpService } from 'jslib-common/abstractions/totp.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
|
||||
import { CipherView } from 'jslib-common/models/view';
|
||||
import { AutofillService as AutofillServiceInterface } from './abstractions/autofill.service';
|
||||
|
||||
import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType';
|
||||
import { CipherType } from 'jslib-common/enums/cipherType';
|
||||
import { EventType } from 'jslib-common/enums/eventType';
|
||||
import { FieldType } from 'jslib-common/enums/fieldType';
|
||||
|
||||
import { CipherView } from 'jslib-common/models/view/cipherView';
|
||||
|
||||
import AutofillField from '../models/autofillField';
|
||||
import AutofillPageDetails from '../models/autofillPageDetails';
|
||||
@@ -11,18 +18,6 @@ import AutofillScript from '../models/autofillScript';
|
||||
|
||||
import { BrowserApi } from '../browser/browserApi';
|
||||
|
||||
import { AutofillService as AutofillServiceInterface } from './abstractions/autofill.service';
|
||||
|
||||
import {
|
||||
CipherService,
|
||||
TotpService,
|
||||
UserService,
|
||||
} from 'jslib-common/abstractions';
|
||||
|
||||
import { EventService } from 'jslib-common/abstractions/event.service';
|
||||
import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType';
|
||||
import { EventType } from 'jslib-common/enums/eventType';
|
||||
|
||||
const CardAttributes: string[] = ['autoCompleteType', 'data-stripe', 'htmlName', 'htmlID', 'label-tag',
|
||||
'placeholder', 'label-left', 'label-top', 'data-recurly'];
|
||||
|
||||
|
||||
@@ -150,33 +150,6 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||
});
|
||||
}
|
||||
|
||||
async showPasswordDialog(title: string, body: string, passwordValidation: (value: string) => Promise<boolean>) {
|
||||
const dialogId = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
|
||||
|
||||
this.messagingService.send('showPasswordDialog', {
|
||||
title: title,
|
||||
body: body,
|
||||
dialogId: dialogId,
|
||||
});
|
||||
|
||||
return new Promise<boolean>(resolve => {
|
||||
this.passwordDialogResolves.set(dialogId, {
|
||||
tryResolve: async (canceled: boolean, password: string) => {
|
||||
if (canceled) {
|
||||
resolve(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (await passwordValidation(password)) {
|
||||
resolve(true);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
date: new Date(),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
isDev(): boolean {
|
||||
return process.env.ENV === 'development';
|
||||
}
|
||||
|
||||
@@ -8,8 +8,9 @@ export default class I18nService extends BaseI18nService {
|
||||
return await file.json();
|
||||
});
|
||||
|
||||
// Please leave 'en' where it is, as it's our fallback language in case no translation can be found
|
||||
this.supportedTranslationLocales = [
|
||||
'az', 'en', 'be', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en-GB', 'en-IN', 'es', 'et', 'fa', 'fi', 'fr', 'he', 'hr', 'hu',
|
||||
'en', 'az', 'be', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en-GB', 'en-IN', 'es', 'et', 'fa', 'fi', 'fr', 'he', 'hr', 'hu',
|
||||
'id', 'it', 'ja', 'kn', 'ko', 'lv', 'ml', 'nb', 'nl', 'pl', 'pt-BR', 'pt-PT', 'ro', 'ru', 'sk', 'sr', 'sv', 'th', 'tr', 'uk',
|
||||
'vi', 'zh-CN', 'zh-TW',
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user