mirror of
https://github.com/bitwarden/browser
synced 2025-12-06 00:13:28 +00:00
PM-14355 (#13110)
- Initial structure - Implement flag where needed - Apply dynamic styling
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
} from "@bitwarden/common/autofill/constants";
|
||||
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||
import { UserNotificationSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/user-notification-settings.service";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { NeverDomains } from "@bitwarden/common/models/domain/domain-service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { ServerConfig } from "@bitwarden/common/platform/abstractions/config/server-config";
|
||||
@@ -80,6 +81,7 @@ export default class NotificationBackground {
|
||||
bgGetExcludedDomains: () => this.getExcludedDomains(),
|
||||
bgGetActiveUserServerConfig: () => this.getActiveUserServerConfig(),
|
||||
getWebVaultUrlForNotification: () => this.getWebVaultUrl(),
|
||||
notificationRefreshFlagValue: () => this.getNotificationFlag(),
|
||||
};
|
||||
|
||||
private activeUserId$ = this.accountService.activeAccount$.pipe(map((a) => a?.id));
|
||||
@@ -137,6 +139,15 @@ export default class NotificationBackground {
|
||||
return await firstValueFrom(this.configService.serverConfig$);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value of the notification refresh feature flag
|
||||
* @returns Promise<boolean> indicating if the feature is enabled
|
||||
*/
|
||||
async getNotificationFlag(): Promise<boolean> {
|
||||
const flagValue = await this.configService.getFeatureFlag(FeatureFlag.NotificationRefresh);
|
||||
return flagValue;
|
||||
}
|
||||
|
||||
private async getAuthStatus() {
|
||||
return await firstValueFrom(this.authService.activeAccountStatus$);
|
||||
}
|
||||
|
||||
@@ -852,10 +852,10 @@ async function loadNotificationBar() {
|
||||
}
|
||||
|
||||
closeBar(false);
|
||||
openBar(type, notificationBarUrl, notificationBarInitData);
|
||||
void openBar(type, notificationBarUrl, notificationBarInitData);
|
||||
}
|
||||
|
||||
function openBar(
|
||||
async function openBar(
|
||||
type: string,
|
||||
barPage: string,
|
||||
notificationBarInitData: NotificationBarIframeInitData,
|
||||
@@ -865,22 +865,38 @@ async function loadNotificationBar() {
|
||||
if (document.body == null) {
|
||||
return;
|
||||
}
|
||||
const useComponentBar: boolean = await sendExtensionMessage("notificationRefreshFlagValue");
|
||||
|
||||
setupInitNotificationBarMessageListener(notificationBarInitData);
|
||||
const barPageUrl: string = chrome.runtime.getURL(barPage);
|
||||
|
||||
function getIframeStyle(useComponentBar: boolean): string {
|
||||
return (
|
||||
(useComponentBar
|
||||
? "height: calc(276px + 25px); width: 450px; right: 0;"
|
||||
: "height: 42px; width: 100%;") + " border: 0; min-height: initial;"
|
||||
);
|
||||
}
|
||||
|
||||
notificationBarIframe = document.createElement("iframe");
|
||||
notificationBarIframe.style.cssText =
|
||||
"height: 42px; width: 100%; border: 0; min-height: initial;";
|
||||
notificationBarIframe.style.cssText = getIframeStyle(useComponentBar);
|
||||
notificationBarIframe.id = "bit-notification-bar-iframe";
|
||||
notificationBarIframe.src = barPageUrl;
|
||||
|
||||
function getFrameStyle(useComponentBar: boolean): string {
|
||||
return (
|
||||
(useComponentBar
|
||||
? "height: calc(276px + 25px); width: 450px; right: 0;"
|
||||
: "height: 42px; width: 100%; left: 0;") +
|
||||
" top: 0; padding: 0; position: fixed;" +
|
||||
" z-index: 2147483647; visibility: visible;"
|
||||
);
|
||||
}
|
||||
|
||||
const frameDiv = document.createElement("div");
|
||||
frameDiv.setAttribute("aria-live", "polite");
|
||||
frameDiv.id = "bit-notification-bar";
|
||||
frameDiv.style.cssText =
|
||||
"height: 42px; width: 100%; top: 0; left: 0; padding: 0; position: fixed; " +
|
||||
"z-index: 2147483647; visibility: visible;";
|
||||
frameDiv.style.cssText = getFrameStyle(useComponentBar);
|
||||
frameDiv.appendChild(notificationBarIframe);
|
||||
document.body.appendChild(frameDiv);
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { ThemeTypes } from "@bitwarden/common/platform/enums";
|
||||
import { render } from "lit";
|
||||
|
||||
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums";
|
||||
import { ConsoleLogService } from "@bitwarden/common/platform/services/console-log.service";
|
||||
import type { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
||||
|
||||
import { AdjustNotificationBarMessageData } from "../background/abstractions/notification.background";
|
||||
import { NotificationContainer } from "../content/components/notification/container";
|
||||
import { buildSvgDomElement } from "../utils";
|
||||
import { circleCheckIcon } from "../utils/svg-icons";
|
||||
|
||||
@@ -12,15 +15,13 @@ import {
|
||||
NotificationBarWindowMessageHandlers,
|
||||
NotificationBarWindowMessage,
|
||||
NotificationBarIframeInitData,
|
||||
NotificationType,
|
||||
} from "./abstractions/notification-bar";
|
||||
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
require("./bar.scss");
|
||||
|
||||
const logService = new ConsoleLogService(false);
|
||||
let notificationBarIframeInitData: NotificationBarIframeInitData = {};
|
||||
let windowMessageOrigin: string;
|
||||
let useComponentBar = false;
|
||||
const notificationBarWindowMessageHandlers: NotificationBarWindowMessageHandlers = {
|
||||
initNotificationBar: ({ message }) => initNotificationBar(message),
|
||||
saveCipherAttemptCompleted: ({ message }) => handleSaveCipherAttemptCompletedMessage(message),
|
||||
@@ -29,6 +30,17 @@ const notificationBarWindowMessageHandlers: NotificationBarWindowMessageHandlers
|
||||
globalThis.addEventListener("load", load);
|
||||
function load() {
|
||||
setupWindowMessageListener();
|
||||
sendPlatformMessage({ command: "notificationRefreshFlagValue" }, (flagValue) => {
|
||||
useComponentBar = flagValue;
|
||||
applyNotificationBarStyle();
|
||||
});
|
||||
}
|
||||
|
||||
function applyNotificationBarStyle() {
|
||||
if (!useComponentBar) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
require("./bar.scss");
|
||||
}
|
||||
postMessageToParent({ command: "initNotificationBar" });
|
||||
}
|
||||
|
||||
@@ -39,12 +51,7 @@ function initNotificationBar(message: NotificationBarWindowMessage) {
|
||||
}
|
||||
|
||||
notificationBarIframeInitData = initData;
|
||||
const { isVaultLocked } = notificationBarIframeInitData;
|
||||
setNotificationBarTheme();
|
||||
|
||||
(document.getElementById("logo") as HTMLImageElement).src = isVaultLocked
|
||||
? chrome.runtime.getURL("images/icon38_locked.png")
|
||||
: chrome.runtime.getURL("images/icon38.png");
|
||||
const { isVaultLocked, theme } = notificationBarIframeInitData;
|
||||
|
||||
const i18n = {
|
||||
appName: chrome.i18n.getMessage("appName"),
|
||||
@@ -58,8 +65,50 @@ function initNotificationBar(message: NotificationBarWindowMessage) {
|
||||
notificationChangeDesc: chrome.i18n.getMessage("notificationChangeDesc"),
|
||||
notificationUnlock: chrome.i18n.getMessage("notificationUnlock"),
|
||||
notificationUnlockDesc: chrome.i18n.getMessage("notificationUnlockDesc"),
|
||||
|
||||
// @TODO move values to message catalog
|
||||
saveAction: "Save",
|
||||
saveAsNewLoginAction: "Save as new login",
|
||||
updateLoginAction: "Update login",
|
||||
saveLoginPrompt: "Save login?",
|
||||
updateLoginPrompt: "Update existing login?",
|
||||
loginSaveSuccess: "Login saved",
|
||||
loginSaveSuccessDetails: "Login saved to Bitwarden.",
|
||||
loginUpdateSuccess: "Login saved",
|
||||
loginUpdateSuccessDetails: "Login updated in Bitwarden.",
|
||||
saveFailure: "Error saving",
|
||||
saveFailureDetails: "Oh no! We couldn't save this. Try entering the details as a New item",
|
||||
};
|
||||
|
||||
if (useComponentBar) {
|
||||
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());
|
||||
|
||||
const themeType = getTheme(globalThis, theme);
|
||||
|
||||
// There are other possible passed theme values, but for now, resolve to dark or light
|
||||
const resolvedTheme: Theme = themeType === ThemeTypes.Dark ? ThemeTypes.Dark : ThemeTypes.Light;
|
||||
|
||||
// @TODO use context to avoid prop drilling
|
||||
return render(
|
||||
NotificationContainer({
|
||||
...notificationBarIframeInitData,
|
||||
type: notificationBarIframeInitData.type as NotificationType,
|
||||
theme: resolvedTheme,
|
||||
handleCloseNotification,
|
||||
i18n,
|
||||
}),
|
||||
document.body,
|
||||
);
|
||||
}
|
||||
|
||||
setNotificationBarTheme();
|
||||
|
||||
(document.getElementById("logo") as HTMLImageElement).src = isVaultLocked
|
||||
? chrome.runtime.getURL("images/icon38_locked.png")
|
||||
: chrome.runtime.getURL("images/icon38.png");
|
||||
|
||||
setupLogoLink(i18n);
|
||||
|
||||
// i18n for "Add" template
|
||||
@@ -106,7 +155,7 @@ function initNotificationBar(message: NotificationBarWindowMessage) {
|
||||
closeButton.title = i18n.close;
|
||||
|
||||
const notificationType = initData.type;
|
||||
if (initData.type === "add") {
|
||||
if (notificationType === "add") {
|
||||
handleTypeAdd();
|
||||
} else if (notificationType === "change") {
|
||||
handleTypeChange();
|
||||
@@ -114,17 +163,19 @@ function initNotificationBar(message: NotificationBarWindowMessage) {
|
||||
handleTypeUnlock();
|
||||
}
|
||||
|
||||
closeButton.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
sendPlatformMessage({
|
||||
command: "bgCloseNotificationBar",
|
||||
});
|
||||
});
|
||||
closeButton.addEventListener("click", handleCloseNotification);
|
||||
|
||||
globalThis.addEventListener("resize", adjustHeight);
|
||||
adjustHeight();
|
||||
}
|
||||
|
||||
function handleCloseNotification(e: Event) {
|
||||
e.preventDefault();
|
||||
sendPlatformMessage({
|
||||
command: "bgCloseNotificationBar",
|
||||
});
|
||||
}
|
||||
|
||||
function handleTypeAdd() {
|
||||
setContent(document.getElementById("template-add") as HTMLTemplateElement);
|
||||
|
||||
@@ -317,14 +368,19 @@ function setupLogoLink(i18n: Record<string, string>) {
|
||||
sendPlatformMessage({ command: "getWebVaultUrlForNotification" }, setWebVaultUrlLink);
|
||||
}
|
||||
|
||||
function setNotificationBarTheme() {
|
||||
let theme = notificationBarIframeInitData.theme;
|
||||
function getTheme(globalThis: any, theme: NotificationBarIframeInitData["theme"]) {
|
||||
if (theme === ThemeTypes.System) {
|
||||
theme = globalThis.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
return globalThis.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
? ThemeTypes.Dark
|
||||
: ThemeTypes.Light;
|
||||
}
|
||||
|
||||
return theme;
|
||||
}
|
||||
|
||||
function setNotificationBarTheme() {
|
||||
const theme = getTheme(globalThis, notificationBarIframeInitData.theme);
|
||||
|
||||
document.documentElement.classList.add(`theme_${theme}`);
|
||||
|
||||
if (notificationBarIframeInitData.applyRedesign) {
|
||||
|
||||
Reference in New Issue
Block a user