mirror of
https://github.com/bitwarden/browser
synced 2025-12-06 00:13:28 +00:00
[PM-21456] Notification bar does not appear when user is adding a new login when vault is locked (#14807)
* WiP if vault is locked, prompt to unlock and save with v3 notification * add component handling for unlock notification type * fix header component standalone mode * fix header copy * render unlock notification case on save with locked vault
This commit is contained in:
@@ -1116,6 +1116,10 @@
|
||||
"message": "Update login",
|
||||
"description": "Button text for updating an existing login entry."
|
||||
},
|
||||
"unlockToSave": {
|
||||
"message": "Unlock to save this login",
|
||||
"description": "User prompt to take action in order to save the login they just entered."
|
||||
},
|
||||
"saveLogin": {
|
||||
"message": "Save login",
|
||||
"description": "Prompt asking the user if they want to save their login details."
|
||||
@@ -5336,4 +5340,4 @@
|
||||
"noPermissionsViewPage": {
|
||||
"message": "You do not have permissions to view this page. Try logging in with a different account."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +134,7 @@ export const mockI18n = {
|
||||
saveLogin: "Save login",
|
||||
selectItemAriaLabel: "Select $ITEMTYPE$, $ITEMNAME$",
|
||||
typeLogin: "Login",
|
||||
unlockToSave: "Unlock to save this login",
|
||||
updateLoginAction: "Update login",
|
||||
updateLogin: "Update existing login",
|
||||
vault: "Vault",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { css } from "@emotion/css";
|
||||
import { html } from "lit";
|
||||
import { html, nothing } from "lit";
|
||||
|
||||
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums";
|
||||
|
||||
@@ -47,14 +47,13 @@ export function NotificationContainer({
|
||||
type,
|
||||
}: NotificationContainerProps) {
|
||||
const headerMessage = getHeaderMessage(i18n, type);
|
||||
const showBody = true;
|
||||
const showBody = type !== NotificationTypes.Unlock;
|
||||
|
||||
return html`
|
||||
<div class=${notificationContainerStyles(theme)}>
|
||||
${NotificationHeader({
|
||||
handleCloseNotification,
|
||||
message: headerMessage,
|
||||
standalone: showBody,
|
||||
theme,
|
||||
})}
|
||||
${showBody
|
||||
@@ -65,7 +64,7 @@ export function NotificationContainer({
|
||||
theme,
|
||||
i18n,
|
||||
})
|
||||
: null}
|
||||
: nothing}
|
||||
${NotificationFooter({
|
||||
handleSaveAction,
|
||||
collections,
|
||||
@@ -106,7 +105,7 @@ function getHeaderMessage(i18n: I18n, type?: NotificationType) {
|
||||
case NotificationTypes.Change:
|
||||
return i18n.updateLogin;
|
||||
case NotificationTypes.Unlock:
|
||||
return "";
|
||||
return i18n.unlockToSave;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,13 @@ export function NotificationFooter({
|
||||
handleSaveAction,
|
||||
}: NotificationFooterProps) {
|
||||
const isChangeNotification = notificationType === NotificationTypes.Change;
|
||||
const primaryButtonText = i18n.saveAction;
|
||||
const isUnlockNotification = notificationType === NotificationTypes.Unlock;
|
||||
|
||||
let primaryButtonText = i18n.saveAction;
|
||||
|
||||
if (isUnlockNotification) {
|
||||
primaryButtonText = i18n.notificationUnlock;
|
||||
}
|
||||
|
||||
return html`
|
||||
<div class=${notificationFooterStyles({ isChangeNotification })}>
|
||||
|
||||
@@ -56,8 +56,8 @@ const notificationHeaderStyles = ({
|
||||
white-space: nowrap;
|
||||
|
||||
${standalone
|
||||
? css`
|
||||
? css``
|
||||
: css`
|
||||
border-bottom: 0.5px solid ${themes[theme].secondary["300"]};
|
||||
`
|
||||
: css``}
|
||||
`}
|
||||
`;
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
NotificationBarWindowMessage,
|
||||
NotificationBarIframeInitData,
|
||||
NotificationType,
|
||||
NotificationTypes,
|
||||
} from "./abstractions/notification-bar";
|
||||
|
||||
const logService = new ConsoleLogService(false);
|
||||
@@ -85,6 +86,7 @@ function getI18n() {
|
||||
saveFailureDetails: chrome.i18n.getMessage("saveFailureDetails"),
|
||||
saveLogin: chrome.i18n.getMessage("saveLogin"),
|
||||
typeLogin: chrome.i18n.getMessage("typeLogin"),
|
||||
unlockToSave: chrome.i18n.getMessage("unlockToSave"),
|
||||
updateLoginAction: chrome.i18n.getMessage("updateLoginAction"),
|
||||
updateLogin: chrome.i18n.getMessage("updateLogin"),
|
||||
vault: chrome.i18n.getMessage("vault"),
|
||||
@@ -149,6 +151,27 @@ async function initNotificationBar(message: NotificationBarWindowMessage) {
|
||||
document.body.innerHTML = "";
|
||||
// Current implementations utilize a require for scss files which creates the need to remove the node.
|
||||
document.head.querySelectorAll('link[rel="stylesheet"]').forEach((node) => node.remove());
|
||||
|
||||
if (isVaultLocked) {
|
||||
return render(
|
||||
NotificationContainer({
|
||||
...notificationBarIframeInitData,
|
||||
type: NotificationTypes.Unlock,
|
||||
theme: resolvedTheme,
|
||||
personalVaultIsAllowed: !personalVaultDisallowed,
|
||||
handleCloseNotification,
|
||||
handleSaveAction: (e) => {
|
||||
sendSaveCipherMessage(true);
|
||||
|
||||
// @TODO can't close before vault has finished decrypting, but can't leave open during long decrypt because it looks like the experience has failed
|
||||
},
|
||||
handleEditOrUpdateAction,
|
||||
i18n,
|
||||
}),
|
||||
document.body,
|
||||
);
|
||||
}
|
||||
|
||||
const orgId = selectedVaultSignal.get();
|
||||
await Promise.all([
|
||||
new Promise<OrgView[]>((resolve) =>
|
||||
|
||||
Reference in New Issue
Block a user