[PM-1829] Allow Safari popup to be full height in Safari >= 16.1 (#5226)
* Logic for calculating if we should apply height fix for safari * Revert safari height fix for safari >= 16.1 * Deprecate static isBrowser funcions, using them directly is incorrect * Changes based on feedback * Update CSS to use & selector --------- Co-authored-by: Hinton <hinton@users.noreply.github.com>
This commit is contained in:
parent
c763415edf
commit
1b9c4a9c11
|
@ -1,10 +1,18 @@
|
||||||
import { enableProdMode } from "@angular/core";
|
import { enableProdMode } from "@angular/core";
|
||||||
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
|
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
|
||||||
|
|
||||||
|
import BrowserPlatformUtilsService from "../services/browserPlatformUtils.service";
|
||||||
|
|
||||||
require("./scss/popup.scss");
|
require("./scss/popup.scss");
|
||||||
|
|
||||||
import { AppModule } from "./app.module";
|
import { AppModule } from "./app.module";
|
||||||
|
|
||||||
|
// We put this first to minimize the delay in window changing.
|
||||||
|
// Should be removed once we deprecate support for Safari 16.0 and older. See Jira ticket [PM-1861]
|
||||||
|
if (BrowserPlatformUtilsService.shouldApplySafariHeightFix(window)) {
|
||||||
|
document.documentElement.classList.add("safari_height_fix");
|
||||||
|
}
|
||||||
|
|
||||||
if (process.env.ENV === "production") {
|
if (process.env.ENV === "production") {
|
||||||
enableProdMode();
|
enableProdMode();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
@import "variables.scss";
|
@import "variables.scss";
|
||||||
|
|
||||||
html.browser_safari {
|
html.browser_safari {
|
||||||
|
&.safari_height_fix {
|
||||||
body {
|
body {
|
||||||
height: 360px !important;
|
height: 360px !important;
|
||||||
|
|
||||||
|
@ -12,6 +13,7 @@ html.browser_safari {
|
||||||
height: 100% !important;
|
height: 100% !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
.search .bwi {
|
.search .bwi {
|
||||||
|
|
|
@ -22,6 +22,7 @@ describe("Browser Utils Service", () => {
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
window.matchMedia = undefined;
|
window.matchMedia = undefined;
|
||||||
(window as any).chrome = undefined;
|
(window as any).chrome = undefined;
|
||||||
|
(BrowserPlatformUtilsService as any).deviceCache = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should detect chrome", () => {
|
it("should detect chrome", () => {
|
||||||
|
@ -86,3 +87,73 @@ describe("Browser Utils Service", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Safari Height Fix", () => {
|
||||||
|
const originalUserAgent = navigator.userAgent;
|
||||||
|
|
||||||
|
// Reset the userAgent.
|
||||||
|
afterAll(() => {
|
||||||
|
Object.defineProperty(navigator, "userAgent", {
|
||||||
|
value: originalUserAgent,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
(BrowserPlatformUtilsService as any).deviceCache = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each([
|
||||||
|
[
|
||||||
|
"safari 15.6.1",
|
||||||
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.6.1 Safari/605.1.15",
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"safari 16.0",
|
||||||
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15",
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
|
||||||
|
[
|
||||||
|
"safari 16.1",
|
||||||
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15",
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"safari 16.4",
|
||||||
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.4 Safari/605.1.15",
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"safari 17.0 (future release)",
|
||||||
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15",
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"chrome",
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36",
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"firefox",
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0",
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"opera",
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3175.3 Safari/537.36 OPR/49.0.2695.0 (Edition developer)",
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"edge",
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.74 Safari/537.36 Edg/79.0.309.43",
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
])("Apply fix for %s", (name, userAgent, expected) => {
|
||||||
|
Object.defineProperty(navigator, "userAgent", {
|
||||||
|
configurable: true,
|
||||||
|
value: userAgent,
|
||||||
|
});
|
||||||
|
expect(BrowserPlatformUtilsService.shouldApplySafariHeightFix(window)).toBe(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -13,7 +13,7 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||||
number,
|
number,
|
||||||
{ tryResolve: (canceled: boolean, password: string) => Promise<boolean>; date: Date }
|
{ tryResolve: (canceled: boolean, password: string) => Promise<boolean>; date: Date }
|
||||||
>();
|
>();
|
||||||
private deviceCache: DeviceType = null;
|
private static deviceCache: DeviceType = null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
|
@ -22,28 +22,32 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||||
private win: Window & typeof globalThis
|
private win: Window & typeof globalThis
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
getDevice(): DeviceType {
|
static getDevice(win: Window & typeof globalThis): DeviceType {
|
||||||
if (this.deviceCache) {
|
if (this.deviceCache) {
|
||||||
return this.deviceCache;
|
return this.deviceCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BrowserPlatformUtilsService.isFirefox()) {
|
if (BrowserPlatformUtilsService.isFirefox()) {
|
||||||
this.deviceCache = DeviceType.FirefoxExtension;
|
this.deviceCache = DeviceType.FirefoxExtension;
|
||||||
} else if (BrowserPlatformUtilsService.isOpera(this.win)) {
|
} else if (BrowserPlatformUtilsService.isOpera(win)) {
|
||||||
this.deviceCache = DeviceType.OperaExtension;
|
this.deviceCache = DeviceType.OperaExtension;
|
||||||
} else if (BrowserPlatformUtilsService.isEdge()) {
|
} else if (BrowserPlatformUtilsService.isEdge()) {
|
||||||
this.deviceCache = DeviceType.EdgeExtension;
|
this.deviceCache = DeviceType.EdgeExtension;
|
||||||
} else if (BrowserPlatformUtilsService.isVivaldi()) {
|
} else if (BrowserPlatformUtilsService.isVivaldi()) {
|
||||||
this.deviceCache = DeviceType.VivaldiExtension;
|
this.deviceCache = DeviceType.VivaldiExtension;
|
||||||
} else if (BrowserPlatformUtilsService.isChrome(this.win)) {
|
} else if (BrowserPlatformUtilsService.isChrome(win)) {
|
||||||
this.deviceCache = DeviceType.ChromeExtension;
|
this.deviceCache = DeviceType.ChromeExtension;
|
||||||
} else if (BrowserPlatformUtilsService.isSafari(this.win)) {
|
} else if (BrowserPlatformUtilsService.isSafari(win)) {
|
||||||
this.deviceCache = DeviceType.SafariExtension;
|
this.deviceCache = DeviceType.SafariExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.deviceCache;
|
return this.deviceCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDevice(): DeviceType {
|
||||||
|
return BrowserPlatformUtilsService.getDevice(this.win);
|
||||||
|
}
|
||||||
|
|
||||||
getDeviceString(): string {
|
getDeviceString(): string {
|
||||||
const device = DeviceType[this.getDevice()].toLowerCase();
|
const device = DeviceType[this.getDevice()].toLowerCase();
|
||||||
return device.replace("extension", "");
|
return device.replace("extension", "");
|
||||||
|
@ -53,6 +57,9 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||||
return ClientType.Browser;
|
return ClientType.Browser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Do not call this directly, use getDevice() instead
|
||||||
|
*/
|
||||||
static isFirefox(): boolean {
|
static isFirefox(): boolean {
|
||||||
return (
|
return (
|
||||||
navigator.userAgent.indexOf(" Firefox/") !== -1 ||
|
navigator.userAgent.indexOf(" Firefox/") !== -1 ||
|
||||||
|
@ -64,7 +71,10 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||||
return this.getDevice() === DeviceType.FirefoxExtension;
|
return this.getDevice() === DeviceType.FirefoxExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isChrome(win: Window & typeof globalThis): boolean {
|
/**
|
||||||
|
* @deprecated Do not call this directly, use getDevice() instead
|
||||||
|
*/
|
||||||
|
private static isChrome(win: Window & typeof globalThis): boolean {
|
||||||
return win.chrome && navigator.userAgent.indexOf(" Chrome/") !== -1;
|
return win.chrome && navigator.userAgent.indexOf(" Chrome/") !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +82,10 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||||
return this.getDevice() === DeviceType.ChromeExtension;
|
return this.getDevice() === DeviceType.ChromeExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isEdge(): boolean {
|
/**
|
||||||
|
* @deprecated Do not call this directly, use getDevice() instead
|
||||||
|
*/
|
||||||
|
private static isEdge(): boolean {
|
||||||
return navigator.userAgent.indexOf(" Edg/") !== -1;
|
return navigator.userAgent.indexOf(" Edg/") !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +93,10 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||||
return this.getDevice() === DeviceType.EdgeExtension;
|
return this.getDevice() === DeviceType.EdgeExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isOpera(win: Window & typeof globalThis): boolean {
|
/**
|
||||||
|
* @deprecated Do not call this directly, use getDevice() instead
|
||||||
|
*/
|
||||||
|
private static isOpera(win: Window & typeof globalThis): boolean {
|
||||||
return (
|
return (
|
||||||
(!!win.opr && !!win.opr.addons) || !!win.opera || navigator.userAgent.indexOf(" OPR/") >= 0
|
(!!win.opr && !!win.opr.addons) || !!win.opera || navigator.userAgent.indexOf(" OPR/") >= 0
|
||||||
);
|
);
|
||||||
|
@ -90,7 +106,10 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||||
return this.getDevice() === DeviceType.OperaExtension;
|
return this.getDevice() === DeviceType.OperaExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isVivaldi(): boolean {
|
/**
|
||||||
|
* @deprecated Do not call this directly, use getDevice() instead
|
||||||
|
*/
|
||||||
|
private static isVivaldi(): boolean {
|
||||||
return navigator.userAgent.indexOf(" Vivaldi/") !== -1;
|
return navigator.userAgent.indexOf(" Vivaldi/") !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +117,9 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||||
return this.getDevice() === DeviceType.VivaldiExtension;
|
return this.getDevice() === DeviceType.VivaldiExtension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Do not call this directly, use getDevice() instead
|
||||||
|
*/
|
||||||
static isSafari(win: Window & typeof globalThis): boolean {
|
static isSafari(win: Window & typeof globalThis): boolean {
|
||||||
// Opera masquerades as Safari, so make sure we're not there first
|
// Opera masquerades as Safari, so make sure we're not there first
|
||||||
return (
|
return (
|
||||||
|
@ -105,6 +127,24 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static safariVersion(): string {
|
||||||
|
return navigator.userAgent.match("Version/([0-9.]*)")?.[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safari previous to version 16.1 had a bug which caused artifacts on hover in large extension popups.
|
||||||
|
* https://bugs.webkit.org/show_bug.cgi?id=218704
|
||||||
|
*/
|
||||||
|
static shouldApplySafariHeightFix(win: Window & typeof globalThis): boolean {
|
||||||
|
if (BrowserPlatformUtilsService.getDevice(win) !== DeviceType.SafariExtension) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const version = BrowserPlatformUtilsService.safariVersion();
|
||||||
|
const parts = version?.split(".")?.map((v) => Number(v));
|
||||||
|
return parts?.[0] < 16 || (parts?.[0] === 16 && parts?.[1] === 0);
|
||||||
|
}
|
||||||
|
|
||||||
isSafari(): boolean {
|
isSafari(): boolean {
|
||||||
return this.getDevice() === DeviceType.SafariExtension;
|
return this.getDevice() === DeviceType.SafariExtension;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue