@inboxsdk/core 0.2.29-alpha.4 → 0.2.29-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/inboxsdk.js +35 -35
- package/inboxsdk.js.map +1 -1
- package/package.json +2 -1
- package/src/inboxsdk.d.ts +3 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-app-menu-item.d.ts.map +1 -1
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-app-menu-item.js +3 -4
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-collapsible-panel.d.ts +1 -1
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-collapsible-panel.d.ts.map +1 -1
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-collapsible-panel.js +13 -2
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-gmail-styles.d.ts +5 -1
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-gmail-styles.d.ts.map +1 -1
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-gmail-styles.js +32 -20
- package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter.d.ts.map +1 -1
- package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter.js +3 -0
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-menu-item-view.d.ts +4 -12
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-menu-item-view.d.ts.map +1 -1
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-menu-item-view.js +28 -17
- package/src/platform-implementation-js/namespaces/app-menu.d.ts +11 -4
- package/src/platform-implementation-js/namespaces/app-menu.d.ts.map +1 -1
- package/src/platform-implementation-js/views/app-menu-item-view.d.ts.map +1 -1
- package/src/platform-implementation-js/views/app-menu-item-view.js +25 -4
- package/src/platform-implementation-js/views/collapsible-panel-view.d.ts.map +1 -1
- package/src/platform-implementation-js/views/collapsible-panel-view.js +68 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inboxsdk/core",
|
|
3
|
-
"version": "0.2.29-alpha.
|
|
3
|
+
"version": "0.2.29-alpha.6",
|
|
4
4
|
"description": "Library for building browser extensions for Gmail",
|
|
5
5
|
"main": "inboxsdk.js",
|
|
6
6
|
"author": "Streak",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"@types/kefir": "^3.8.6",
|
|
32
32
|
"@types/node": "*",
|
|
33
33
|
"asap": "^2.0.3",
|
|
34
|
+
"fast-deep-equal": "^3.1.3",
|
|
34
35
|
"kefir-cast": "^3.3.0",
|
|
35
36
|
"sha.js": "^2.4.0",
|
|
36
37
|
"tag-tree": "^1.0.0",
|
package/src/inboxsdk.d.ts
CHANGED
|
@@ -106,6 +106,9 @@ export interface ButterBar {
|
|
|
106
106
|
// export interface DropdownButtonAccessoryDescriptor {}
|
|
107
107
|
|
|
108
108
|
export { AppMenu };
|
|
109
|
+
export type { AppMenuItemView } from './platform-implementation-js/views/app-menu-item-view';
|
|
110
|
+
export type { AppMenuItemPanelDescriptor } from './platform-implementation-js/namespaces/app-menu';
|
|
111
|
+
export type { CollapsiblePanelView } from './platform-implementation-js/views/collapsible-panel-view';
|
|
109
112
|
|
|
110
113
|
export interface NativeNavItemView extends EventEmitter {
|
|
111
114
|
addNavItem(descriptor: NavItemDescriptor): NavItemView;
|
package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-app-menu-item.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add-app-menu-item.d.ts","sourceRoot":"","sources":["../../../../../../../src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-app-menu-item.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAI1C,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,kBAAkB,EAAE,qBAAqB,
|
|
1
|
+
{"version":3,"file":"add-app-menu-item.d.ts","sourceRoot":"","sources":["../../../../../../../src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-app-menu-item.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAI1C,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,kBAAkB,EAAE,qBAAqB,6CAyB1C"}
|
|
@@ -3,12 +3,11 @@ import GmailElementGetter from '../gmail-element-getter';
|
|
|
3
3
|
import Logger from '../../../lib/logger';
|
|
4
4
|
export async function addAppMenuItem(driver, menuItemDescriptor) {
|
|
5
5
|
const appMenuInjectionContainer = await GmailElementGetter.getAppMenuAsync();
|
|
6
|
-
const gmailAppMenuItemView = new GmailAppMenuItemView(driver);
|
|
7
|
-
gmailAppMenuItemView.setMenuItemDescriptor(menuItemDescriptor);
|
|
6
|
+
const gmailAppMenuItemView = new GmailAppMenuItemView(driver, menuItemDescriptor);
|
|
8
7
|
try {
|
|
9
|
-
if (!appMenuInjectionContainer
|
|
8
|
+
if (!appMenuInjectionContainer)
|
|
10
9
|
return;
|
|
11
|
-
const siblingElement = menuItemDescriptor.insertIndex
|
|
10
|
+
const siblingElement = Number.isInteger(menuItemDescriptor.insertIndex)
|
|
12
11
|
? appMenuInjectionContainer.childNodes[menuItemDescriptor.insertIndex] ??
|
|
13
12
|
null
|
|
14
13
|
: null;
|
package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-collapsible-panel.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AppMenuItemPanelDescriptor } from '../../../namespaces/app-menu';
|
|
2
2
|
import { CollapsiblePanelView } from '../../../views/collapsible-panel-view';
|
|
3
3
|
import GmailDriver from '../gmail-driver';
|
|
4
|
-
export declare function addCollapsiblePanel(driver: GmailDriver, panelDescriptor: AppMenuItemPanelDescriptor): Promise<CollapsiblePanelView | undefined>;
|
|
4
|
+
export declare function addCollapsiblePanel(driver: GmailDriver, panelDescriptor: AppMenuItemPanelDescriptor, insertIndex?: number): Promise<CollapsiblePanelView | undefined>;
|
|
5
5
|
//# sourceMappingURL=add-collapsible-panel.d.ts.map
|
package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-collapsible-panel.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add-collapsible-panel.d.ts","sourceRoot":"","sources":["../../../../../../../src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-collapsible-panel.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAI1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAE1C,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,WAAW,EACnB,eAAe,EAAE,0BAA0B,
|
|
1
|
+
{"version":3,"file":"add-collapsible-panel.d.ts","sourceRoot":"","sources":["../../../../../../../src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-collapsible-panel.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAI1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAE1C,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,WAAW,EACnB,eAAe,EAAE,0BAA0B,EAC3C,WAAW,CAAC,EAAE,MAAM,6CAmCrB"}
|
package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-collapsible-panel.js
CHANGED
|
@@ -3,7 +3,7 @@ import GmailElementGetter from '../gmail-element-getter';
|
|
|
3
3
|
import waitFor from '../../../lib/wait-for';
|
|
4
4
|
import Logger from '../../../lib/logger';
|
|
5
5
|
import { CollapsiblePanelView } from '../../../views/collapsible-panel-view';
|
|
6
|
-
export async function addCollapsiblePanel(driver, panelDescriptor) {
|
|
6
|
+
export async function addCollapsiblePanel(driver, panelDescriptor, insertIndex) {
|
|
7
7
|
const injectionContainer = await waitForAppMenuParentReady();
|
|
8
8
|
const collapsiblePanelView = new CollapsiblePanelView(driver, panelDescriptor);
|
|
9
9
|
if (!injectionContainer || !collapsiblePanelView.element)
|
|
@@ -11,7 +11,18 @@ export async function addCollapsiblePanel(driver, panelDescriptor) {
|
|
|
11
11
|
const appMenu = await GmailElementGetter.getAppMenuAsync();
|
|
12
12
|
if (!appMenu)
|
|
13
13
|
return;
|
|
14
|
-
|
|
14
|
+
const panelNodes = injectionContainer.querySelectorAll(CollapsiblePanelView.elementSelectors.NATIVE) ?? [];
|
|
15
|
+
const siblingElement = Number.isInteger(insertIndex)
|
|
16
|
+
? panelNodes[insertIndex] ?? null
|
|
17
|
+
: null;
|
|
18
|
+
if (siblingElement) {
|
|
19
|
+
siblingElement.insertAdjacentElement('beforebegin', collapsiblePanelView.element);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
[...panelNodes]
|
|
23
|
+
.at(-1)
|
|
24
|
+
?.insertAdjacentElement('afterend', collapsiblePanelView.element);
|
|
25
|
+
}
|
|
15
26
|
return collapsiblePanelView;
|
|
16
27
|
}
|
|
17
28
|
const waitForAppMenuParentReady = once(async () => {
|
package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-gmail-styles.d.ts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const stylesStream: import("kefir-bus").Bus<{
|
|
2
|
+
type: 'theme';
|
|
3
|
+
isDarkMode: boolean;
|
|
4
|
+
}, unknown>;
|
|
5
|
+
export default function trackGmailStyles(): Promise<void>;
|
|
2
6
|
//# sourceMappingURL=track-gmail-styles.d.ts.map
|
package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-gmail-styles.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-gmail-styles.d.ts","sourceRoot":"","sources":["../../../../../../../src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-gmail-styles.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"track-gmail-styles.d.ts","sourceRoot":"","sources":["../../../../../../../src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-gmail-styles.ts"],"names":[],"mappings":"AAyDA,eAAO,MAAM,YAAY;UACf,OAAO;gBAAc,OAAO;WAEnC,CAAC;AAEJ,wBAA8B,gBAAgB,kBAmE7C"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import kefirBus from 'kefir-bus';
|
|
1
2
|
import Logger from '../../../lib/logger';
|
|
2
3
|
import waitFor from '../../../lib/wait-for';
|
|
3
4
|
import GmailElementGetter from '../gmail-element-getter';
|
|
@@ -21,10 +22,11 @@ function getDensity() {
|
|
|
21
22
|
return 'compact';
|
|
22
23
|
}
|
|
23
24
|
}
|
|
25
|
+
const navItemSelector = '.aio';
|
|
24
26
|
function isDarkTheme() {
|
|
25
27
|
// get the color of the left-nav-menu entries to determine whether Gmail is
|
|
26
28
|
// in dark theme mode.
|
|
27
|
-
const navItem = document.querySelector(
|
|
29
|
+
const navItem = document.querySelector(navItemSelector);
|
|
28
30
|
if (!navItem) {
|
|
29
31
|
Logger.error(new Error('Failed to find nav item'));
|
|
30
32
|
return false;
|
|
@@ -45,7 +47,8 @@ function isDarkTheme() {
|
|
|
45
47
|
}
|
|
46
48
|
return r > 128;
|
|
47
49
|
}
|
|
48
|
-
export
|
|
50
|
+
export const stylesStream = kefirBus();
|
|
51
|
+
export default async function trackGmailStyles() {
|
|
49
52
|
if (document.head.hasAttribute('data-inboxsdk-gmail-style-tracker') ||
|
|
50
53
|
GmailElementGetter.isStandalone()) {
|
|
51
54
|
return;
|
|
@@ -71,25 +74,34 @@ export default function trackGmailStyles() {
|
|
|
71
74
|
else {
|
|
72
75
|
document.body.classList.remove('inboxsdk__gmail_dark_theme');
|
|
73
76
|
}
|
|
77
|
+
stylesStream.emit({
|
|
78
|
+
type: 'theme',
|
|
79
|
+
isDarkMode: newDarkTheme,
|
|
80
|
+
});
|
|
74
81
|
}
|
|
75
82
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const options = {
|
|
82
|
-
characterData: true,
|
|
83
|
-
childList: true,
|
|
84
|
-
};
|
|
85
|
-
Array.from(document.styleSheets).forEach((sheet) => {
|
|
86
|
-
if (sheet.ownerNode.tagName == 'STYLE') {
|
|
87
|
-
observer.observe(sheet.ownerNode, options);
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
checkStyles();
|
|
91
|
-
})
|
|
92
|
-
.catch((err) => {
|
|
83
|
+
try {
|
|
84
|
+
await waitFor(() => document.querySelector('.TO .TN') &&
|
|
85
|
+
document.querySelector(navItemSelector));
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
93
88
|
Logger.error(err);
|
|
94
|
-
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// Gmail changes an inline <style> sheet when the display density changes.
|
|
92
|
+
// Watch for changes to all <style> elements.
|
|
93
|
+
const observer = new MutationObserver(checkStyles);
|
|
94
|
+
const options = {
|
|
95
|
+
characterData: true,
|
|
96
|
+
childList: true,
|
|
97
|
+
};
|
|
98
|
+
for (const sheet of document.styleSheets) {
|
|
99
|
+
if (!(sheet.ownerNode instanceof Element)) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (sheet.ownerNode.tagName == 'STYLE') {
|
|
103
|
+
observer.observe(sheet.ownerNode, options);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
checkStyles();
|
|
95
107
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gmail-element-getter.d.ts","sourceRoot":"","sources":["../../../../../../src/platform-implementation-js/dom-driver/gmail/gmail-element-getter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAA+B,EAC7B,mBAAmB,EACpB,MAAM,yCAAyC,CAAC;AAmBjD,QAAA,MAAM,kBAAkB;yBACD,WAAW,GAAG,IAAI;uCAcJ,WAAW,GAAG,IAAI;kDAKP,WAAW,GAAG,IAAI;+CAKrB,WAAW,GAAG,IAAI;wBAIzC,WAAW,GAAG,IAAI;iCAOT,WAAW,GAAG,IAAI;gCAInB,WAAW,GAAG,SAAS,GAAG,IAAI;2CA8BnB,WAAW,GAAG,IAAI;iDAIZ,MAAM,UAAU,CAC3D,mBAAmB,EACnB,KAAK,CACN;uBAgBkB,WAAW,GAAG,IAAI;kCAIP,WAAW,GAAG,IAAI;+
|
|
1
|
+
{"version":3,"file":"gmail-element-getter.d.ts","sourceRoot":"","sources":["../../../../../../src/platform-implementation-js/dom-driver/gmail/gmail-element-getter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAA+B,EAC7B,mBAAmB,EACpB,MAAM,yCAAyC,CAAC;AAmBjD,QAAA,MAAM,kBAAkB;yBACD,WAAW,GAAG,IAAI;uCAcJ,WAAW,GAAG,IAAI;kDAKP,WAAW,GAAG,IAAI;+CAKrB,WAAW,GAAG,IAAI;wBAIzC,WAAW,GAAG,IAAI;iCAOT,WAAW,GAAG,IAAI;gCAInB,WAAW,GAAG,SAAS,GAAG,IAAI;2CA8BnB,WAAW,GAAG,IAAI;iDAIZ,MAAM,UAAU,CAC3D,mBAAmB,EACnB,KAAK,CACN;uBAgBkB,WAAW,GAAG,IAAI;kCAIP,WAAW,GAAG,IAAI;+BAUrB,WAAW,GAAG,IAAI;0CAIP,WAAW,GAAG,IAAI;+BAI7B,WAAW,GAAG,IAAI;+CAQrC,GAAG,KACR,MAAM,UAAU,CAAC,WAAW,EAAE,KAAK,CAAC;qBAItB,WAAW,GAAG,IAAI;+BAOR,OAAO;;;;;;uDAgFiB,WAAW,GAAG,IAAI;mDAItB,WAAW,GAAG,IAAI;0BAQ3C,WAAW,EAAE;0BAIb,WAAW,GAAG,IAAI;sBAItB,gBAAgB,GAAG,IAAI;qCAMR,WAAW,GAAG,IAAI;kCAIrB,WAAW,GAAG,IAAI;2BAIzB,WAAW,GAAG,IAAI;iCAWZ,WAAW,GAAG,IAAI;yBAI1B,WAAW;8BAIN,WAAW,GAAG,IAAI;sBAM1B,OAAO;mBAaV,OAAO;qBAIL,OAAO;oBAIR,OAAO;iCAIM,OAAO;gCAOR,OAAO;;qCASJ,WAAW,GAAG,IAAI;;gCAKrB,QAAQ,IAAI,CAAC;CAG1C,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -89,6 +89,9 @@ const GmailElementGetter = {
|
|
|
89
89
|
return document.querySelector('.aeN .aj5.J-KU-Jg');
|
|
90
90
|
},
|
|
91
91
|
getLeftNavContainerElement() {
|
|
92
|
+
if (this.getAppMenu()) {
|
|
93
|
+
return this.getAppMenuContainer()?.querySelector('.aqn.aIH') ?? null;
|
|
94
|
+
}
|
|
92
95
|
if (isIntegratedViewGmail()) {
|
|
93
96
|
return document.querySelector('div[role=navigation] + div.aqn');
|
|
94
97
|
}
|
|
@@ -17,19 +17,11 @@ export declare class GmailAppMenuItemView extends GmailAppMenuItemView_base {
|
|
|
17
17
|
readonly HOVER: "aIk";
|
|
18
18
|
readonly ACTIVE: "apV";
|
|
19
19
|
};
|
|
20
|
-
get element(): HTMLElement
|
|
21
|
-
|
|
22
|
-
get menuItemDescriptor(): AppMenuItemDescriptor
|
|
23
|
-
constructor(driver: GmailDriver);
|
|
20
|
+
get element(): HTMLElement;
|
|
21
|
+
set menuItemDescriptor(newMenuItemDescriptor: AppMenuItemDescriptor);
|
|
22
|
+
get menuItemDescriptor(): AppMenuItemDescriptor;
|
|
23
|
+
constructor(driver: GmailDriver, menuItemDescriptor: AppMenuItemDescriptor);
|
|
24
24
|
remove(): void;
|
|
25
|
-
/**
|
|
26
|
-
* @internal
|
|
27
|
-
*/
|
|
28
|
-
blur(): void;
|
|
29
|
-
/**
|
|
30
|
-
* @internal
|
|
31
|
-
*/
|
|
32
|
-
hover(): void;
|
|
33
25
|
}
|
|
34
26
|
export {};
|
|
35
27
|
//# sourceMappingURL=gmail-app-menu-item-view.d.ts.map
|
package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-menu-item-view.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gmail-app-menu-item-view.d.ts","sourceRoot":"","sources":["../../../../../../../src/platform-implementation-js/dom-driver/gmail/views/gmail-app-menu-item-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAE1C,OAAO,iBAAiB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"gmail-app-menu-item-view.d.ts","sourceRoot":"","sources":["../../../../../../../src/platform-implementation-js/dom-driver/gmail/views/gmail-app-menu-item-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAE1C,OAAO,iBAAiB,MAAM,eAAe,CAAC;AAO9C,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IAC/B,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IAC9B,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,YAAY,MAAgB,CAAC;AAC1C,eAAO,MAAM,cAAc,yBAAmC,CAAC;AAC/D,eAAO,MAAM,aAAa,4BAA+C,CAAC;mDAOL,kBAAkB,aAAa,CAAC;AAArG,qBAAa,oBAAqB,SAAQ,yBAA4D;;IACpG,MAAM,CAAC,UAAU;;;MAGN;IAOX,IAAI,OAAO,gBAEV;IAED,IAAI,kBAAkB,CAAC,qBAAqB,uBAAA,EAG3C;IAED,IAAI,kBAAkB,0BAErB;gBAEW,MAAM,EAAE,WAAW,EAAE,kBAAkB,EAAE,qBAAqB;IAwB1E,MAAM;CA6GP"}
|
|
@@ -2,6 +2,8 @@ import querySelector from '../../../lib/dom/querySelectorOrFail';
|
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
3
|
import cx from 'classnames';
|
|
4
4
|
import GmailElementGetter from '../gmail-element-getter';
|
|
5
|
+
import { stylesStream } from '../gmail-driver/track-gmail-styles';
|
|
6
|
+
import isEqual from 'fast-deep-equal';
|
|
5
7
|
export const NATIVE_CLASS = 'Xa';
|
|
6
8
|
export const INBOXSDK_CLASS = 'inboxsdk__appMenuItem';
|
|
7
9
|
export const ELEMENT_CLASS = `${NATIVE_CLASS} ${INBOXSDK_CLASS}`;
|
|
@@ -21,17 +23,26 @@ export class GmailAppMenuItemView extends EventEmitter {
|
|
|
21
23
|
get element() {
|
|
22
24
|
return this.#element;
|
|
23
25
|
}
|
|
24
|
-
|
|
26
|
+
set menuItemDescriptor(newMenuItemDescriptor) {
|
|
25
27
|
this.#menuItemDescriptor = newMenuItemDescriptor;
|
|
26
28
|
this.#update();
|
|
27
29
|
}
|
|
28
30
|
get menuItemDescriptor() {
|
|
29
31
|
return this.#menuItemDescriptor;
|
|
30
32
|
}
|
|
31
|
-
constructor(driver) {
|
|
33
|
+
constructor(driver, menuItemDescriptor) {
|
|
32
34
|
super();
|
|
33
35
|
this.#element = this.#setupElement();
|
|
34
36
|
this.#driver = driver;
|
|
37
|
+
this.#menuItemDescriptor = menuItemDescriptor;
|
|
38
|
+
this.#update();
|
|
39
|
+
stylesStream
|
|
40
|
+
.skipDuplicates((a, b) => isEqual(a, b))
|
|
41
|
+
.onValue(({ type }) => {
|
|
42
|
+
if (type === 'theme') {
|
|
43
|
+
this.#update();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
35
46
|
driver.getStopper().onValue(() => this.remove());
|
|
36
47
|
this.#element.addEventListener('click', (e) => this.#onClick(e));
|
|
37
48
|
this.#element.addEventListener('mouseleave', this.#onBlur);
|
|
@@ -44,21 +55,6 @@ export class GmailAppMenuItemView extends EventEmitter {
|
|
|
44
55
|
this.element?.remove();
|
|
45
56
|
this.emit('destroy');
|
|
46
57
|
}
|
|
47
|
-
/**
|
|
48
|
-
* @internal
|
|
49
|
-
*/
|
|
50
|
-
blur() {
|
|
51
|
-
this.element?.classList.remove(GmailAppMenuItemView.elementCss.HOVER);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* @internal
|
|
55
|
-
*/
|
|
56
|
-
hover() {
|
|
57
|
-
if (this.element?.classList.contains(GmailAppMenuItemView.elementCss.ACTIVE)) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
this.element?.classList.add(GmailAppMenuItemView.elementCss.HOVER);
|
|
61
|
-
}
|
|
62
58
|
#setupElement() {
|
|
63
59
|
const element = document.createElement('div');
|
|
64
60
|
element.className = ELEMENT_CLASS;
|
|
@@ -82,6 +78,7 @@ export class GmailAppMenuItemView extends EventEmitter {
|
|
|
82
78
|
const headingElement = querySelector(element, HEADING_ELEMENT_SELECTOR);
|
|
83
79
|
headingElement.textContent = this.#menuItemDescriptor?.name ?? '';
|
|
84
80
|
}
|
|
81
|
+
static #preloadedIcons = new Set();
|
|
85
82
|
#updateIcon(element) {
|
|
86
83
|
const iconContainerEl = querySelector(element, ICON_ELEMENT_SELECTOR);
|
|
87
84
|
const { iconUrl, iconClassName } = this.#menuItemDescriptor ?? {};
|
|
@@ -89,8 +86,22 @@ export class GmailAppMenuItemView extends EventEmitter {
|
|
|
89
86
|
const rawTheme = GmailElementGetter.isDarkTheme()
|
|
90
87
|
? iconUrl.darkTheme
|
|
91
88
|
: iconUrl.lightTheme;
|
|
89
|
+
if (!rawTheme)
|
|
90
|
+
return;
|
|
92
91
|
const theme = typeof rawTheme === 'string' ? rawTheme : rawTheme.default;
|
|
93
92
|
const activeImg = typeof rawTheme === 'string' ? rawTheme : rawTheme.active;
|
|
93
|
+
// alleviate FOUC when switching between active and default icons
|
|
94
|
+
// https://stackoverflow.com/a/68521953/1924257
|
|
95
|
+
for (const url of [theme, activeImg]) {
|
|
96
|
+
if (GmailAppMenuItemView.#preloadedIcons.has(url))
|
|
97
|
+
continue;
|
|
98
|
+
GmailAppMenuItemView.#preloadedIcons.add(url);
|
|
99
|
+
var link = document.createElement('link');
|
|
100
|
+
link.rel = 'preload';
|
|
101
|
+
link.as = 'image';
|
|
102
|
+
link.href = url;
|
|
103
|
+
document.head.appendChild(link);
|
|
104
|
+
}
|
|
94
105
|
iconContainerEl.style.setProperty('--background-image', `url(${theme})`);
|
|
95
106
|
iconContainerEl.style.setProperty('--background-image--active', `url(${activeImg})`);
|
|
96
107
|
}
|
|
@@ -8,8 +8,8 @@ type ThemedIcon = string | {
|
|
|
8
8
|
export type AppMenuItemDescriptor = {
|
|
9
9
|
name: string;
|
|
10
10
|
iconUrl?: {
|
|
11
|
-
darkTheme
|
|
12
|
-
lightTheme
|
|
11
|
+
darkTheme?: ThemedIcon;
|
|
12
|
+
lightTheme?: ThemedIcon;
|
|
13
13
|
};
|
|
14
14
|
className?: string;
|
|
15
15
|
iconClassName?: string;
|
|
@@ -28,6 +28,13 @@ export type AppMenuItemDescriptor = {
|
|
|
28
28
|
*/
|
|
29
29
|
isRouteActive: (routeView: RouteView) => boolean;
|
|
30
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* In dark themes, Gmail has different colored primary buttons depending on hover or active state
|
|
33
|
+
*/
|
|
34
|
+
type PanelPrimaryButtonThemedIcon = string | {
|
|
35
|
+
panelHovered: string;
|
|
36
|
+
panelDefault: string;
|
|
37
|
+
};
|
|
31
38
|
export type AppMenuItemPanelDescriptor = {
|
|
32
39
|
className?: string;
|
|
33
40
|
/** In the form of HTML as a string.
|
|
@@ -38,8 +45,8 @@ export type AppMenuItemPanelDescriptor = {
|
|
|
38
45
|
name: string;
|
|
39
46
|
onClick: (e: MouseEvent) => void;
|
|
40
47
|
iconUrl?: {
|
|
41
|
-
darkTheme
|
|
42
|
-
lightTheme
|
|
48
|
+
darkTheme?: PanelPrimaryButtonThemedIcon;
|
|
49
|
+
lightTheme?: PanelPrimaryButtonThemedIcon;
|
|
43
50
|
};
|
|
44
51
|
className?: string;
|
|
45
52
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-menu.d.ts","sourceRoot":"","sources":["../../../../../src/platform-implementation-js/namespaces/app-menu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,KAAK,UAAU,GACX,MAAM,GACN;IACE,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE;QACR,SAAS,EAAE,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"app-menu.d.ts","sourceRoot":"","sources":["../../../../../src/platform-implementation-js/namespaces/app-menu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,KAAK,UAAU,GACX,MAAM,GACN;IACE,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,UAAU,CAAC;QACvB,UAAU,CAAC,EAAE,UAAU,CAAC;KACzB,CAAC;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1C,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAC;IAC1C;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,EAAE,CAAC;IACjB;;;;OAIG;IACH,aAAa,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC;CAClD,CAAC;AAEF;;GAEG;AACH,KAAK,4BAA4B,GAC7B,MAAM,GACN;IACE,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEN,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;0EAEsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE;QACd,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;QACjC,OAAO,CAAC,EAAE;YACR,SAAS,CAAC,EAAE,4BAA4B,CAAC;YACzC,UAAU,CAAC,EAAE,4BAA4B,CAAC;SAC3C,CAAC;QACF,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,OAAO;;gBAGd,MAAM,EAAE,WAAW;IAI/B,WAAW,CAAC,kBAAkB,EAAE,qBAAqB,GAAG,eAAe;IAKjE,OAAO;CAId"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-menu-item-view.d.ts","sourceRoot":"","sources":["../../../../../src/platform-implementation-js/views/app-menu-item-view.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAWzC,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAEL,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAK3D,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;8CA0C8D,aAAa,aAAa,CAAC;AAH3F;;GAEG;AACH,qBAAa,eAAgB,SAAQ,oBAAuD;;
|
|
1
|
+
{"version":3,"file":"app-menu-item-view.d.ts","sourceRoot":"","sources":["../../../../../src/platform-implementation-js/views/app-menu-item-view.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAWzC,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAEL,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAK3D,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;8CA0C8D,aAAa,aAAa,CAAC;AAH3F;;GAEG;AACH,qBAAa,eAAgB,SAAQ,oBAAuD;;IA8W1F,IAAI,kBAAkB,0BAErB;gBAQW,MAAM,EAAE,WAAW,EAAE,kBAAkB,EAAE,qBAAqB;IAsDpE,mBAAmB,CAAC,eAAe,EAAE,0BAA0B;IA2C/D,MAAM,CAAC,kBAAkB,EAAE,qBAAqB;IAMtD,MAAM;CAaP"}
|
|
@@ -60,6 +60,26 @@ export class AppMenuItemView extends EventEmitter {
|
|
|
60
60
|
const activePanel = AppMenuItemView.#getActivePanel();
|
|
61
61
|
return !activePanel;
|
|
62
62
|
}
|
|
63
|
+
static #adjustTooltipNub() {
|
|
64
|
+
// adjust all menu items' collapsible panel's tooltip nub position
|
|
65
|
+
const appMenuElement = GmailElementGetter.getAppMenu();
|
|
66
|
+
for (const menuItem of appMenuElement?.querySelectorAll(`.${NATIVE_CLASS}`) ?? []) {
|
|
67
|
+
const panel = AppMenuItemView.#menuItemToPanelMap.get(menuItem);
|
|
68
|
+
if (!panel)
|
|
69
|
+
continue;
|
|
70
|
+
const nubElement = panel?.querySelector('* > .aTV');
|
|
71
|
+
const iconElement = menuItem?.querySelector('.V6');
|
|
72
|
+
const iconElementBox = iconElement?.getBoundingClientRect();
|
|
73
|
+
const offsetTop = (iconElement?.offsetTop ?? 0) + (iconElementBox?.height ?? 0) * 0.5;
|
|
74
|
+
const nubSide = 17;
|
|
75
|
+
const nubDiagonal = nubSide * Math.sqrt(2);
|
|
76
|
+
const offsetNub = nubDiagonal / 4;
|
|
77
|
+
const offset = offsetTop - offsetNub;
|
|
78
|
+
if (nubElement && offset) {
|
|
79
|
+
nubElement.style.top = `${offset}px`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
63
83
|
static #setUpRouteViewDriverStream(driver) {
|
|
64
84
|
if (AppMenuItemView.#routeViewDriverStream)
|
|
65
85
|
return;
|
|
@@ -298,6 +318,7 @@ export class AppMenuItemView extends EventEmitter {
|
|
|
298
318
|
const gmailElement = gmailView.element;
|
|
299
319
|
if (gmailElement) {
|
|
300
320
|
AppMenuItemView.#menuItemToPanelMap.set(gmailElement, undefined);
|
|
321
|
+
AppMenuItemView.#adjustTooltipNub();
|
|
301
322
|
}
|
|
302
323
|
gmailView.on('destroy', () => {
|
|
303
324
|
this.remove();
|
|
@@ -335,7 +356,7 @@ export class AppMenuItemView extends EventEmitter {
|
|
|
335
356
|
[CollapsiblePanelView.elementCss.PANEL_LESS]: AppMenuItemView.#isPanelLess(),
|
|
336
357
|
}),
|
|
337
358
|
};
|
|
338
|
-
const collapsiblePanel = await addCollapsiblePanel(this.#driver, descriptor);
|
|
359
|
+
const collapsiblePanel = await addCollapsiblePanel(this.#driver, descriptor, this.menuItemDescriptor.insertIndex);
|
|
339
360
|
if (collapsiblePanel) {
|
|
340
361
|
this.#gmailViewPromise.then((gmailView) => {
|
|
341
362
|
const gmailElement = gmailView.element;
|
|
@@ -347,9 +368,8 @@ export class AppMenuItemView extends EventEmitter {
|
|
|
347
368
|
e,
|
|
348
369
|
]);
|
|
349
370
|
});
|
|
350
|
-
}
|
|
351
|
-
if (gmailElement && collapsiblePanel) {
|
|
352
371
|
AppMenuItemView.#menuItemToPanelMap.set(gmailElement, collapsiblePanel.element);
|
|
372
|
+
AppMenuItemView.#adjustTooltipNub();
|
|
353
373
|
}
|
|
354
374
|
});
|
|
355
375
|
}
|
|
@@ -358,7 +378,7 @@ export class AppMenuItemView extends EventEmitter {
|
|
|
358
378
|
}
|
|
359
379
|
async update(menuItemDescriptor) {
|
|
360
380
|
const gmailView = await this.#gmailViewPromise;
|
|
361
|
-
gmailView.
|
|
381
|
+
gmailView.menuItemDescriptor = menuItemDescriptor;
|
|
362
382
|
this.#menuItemDescriptor = menuItemDescriptor;
|
|
363
383
|
}
|
|
364
384
|
remove() {
|
|
@@ -371,6 +391,7 @@ export class AppMenuItemView extends EventEmitter {
|
|
|
371
391
|
gmailView.element &&
|
|
372
392
|
AppMenuItemView.#menuItemToPanelMap.delete(gmailView.element);
|
|
373
393
|
gmailView.remove();
|
|
394
|
+
AppMenuItemView.#adjustTooltipNub();
|
|
374
395
|
});
|
|
375
396
|
AppMenuItemView.#appMenuItemViews.delete(this);
|
|
376
397
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collapsible-panel-view.d.ts","sourceRoot":"","sources":["../../../../../src/platform-implementation-js/views/collapsible-panel-view.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAEzC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAIpE,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,WAAW,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"collapsible-panel-view.d.ts","sourceRoot":"","sources":["../../../../../src/platform-implementation-js/views/collapsible-panel-view.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAEzC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAIpE,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAI1C,eAAO,MAAM,YAAY,OAAiB,CAAC;AAC3C,eAAO,MAAM,cAAc,8BAAwC,CAAC;AAcpE,KAAK,aAAa,GAAG;IACnB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;CAC/B,CAAC;mDAEmE,aAAa,aAAa,CAAC;AAAhG,qBAAa,oBAAqB,SAAQ,yBAAuD;;IAC/F,MAAM,CAAC,gBAAgB;;;MAGZ;IACX,MAAM,CAAC,UAAU;;;QAGf,kDAAkD;;;;MAIzC;IASX,IAAI,OAAO,YAEV;IAED,UAAU,CAAC,OAAO,EAAE,OAAO;IAS3B,IAAI,eAAe,+BAElB;IAED,IAAI,eAAe,CAAC,eAAe,4BAAA,EAGlC;IAED,IAAI,OAAO,gBAEV;IAED,IAAI,qBAAqB,mBAExB;gBAGC,MAAM,EAAE,WAAW,EACnB,eAAe,EAAE,0BAA0B;IAmB7C,MAAM;IAON,UAAU,CACR,iBAAiB,EACb,iBAAiB,GACjB,KAAK,CAAC,UAAU,CAAC,iBAAiB,EAAE,GAAG,CAAC;CA+N/C"}
|
|
@@ -6,6 +6,8 @@ import autoHtml from 'auto-html';
|
|
|
6
6
|
import querySelector from '../lib/dom/querySelectorOrFail';
|
|
7
7
|
import GmailElementGetter from '../dom-driver/gmail/gmail-element-getter';
|
|
8
8
|
import NavItemView from './nav-item-view';
|
|
9
|
+
import { stylesStream } from '../dom-driver/gmail/gmail-driver/track-gmail-styles';
|
|
10
|
+
import isEqual from 'fast-deep-equal';
|
|
9
11
|
export const NATIVE_CLASS = 'aqn';
|
|
10
12
|
export const INBOXSDK_CLASS = 'inboxsdk__collapsiblePanel';
|
|
11
13
|
const ELEMENT_CLASS = `${NATIVE_CLASS} ${INBOXSDK_CLASS} oy8Mbf`;
|
|
@@ -14,6 +16,7 @@ const PRIMARY_BUTTON_ELEMENT_SELECTOR = '.T-I.T-I-KE.L3';
|
|
|
14
16
|
const scrollablePanelClass = 'at9';
|
|
15
17
|
const scrollablePanelSelector = `.${scrollablePanelClass}`;
|
|
16
18
|
const loadingElementClass = 'inboxsdk__collapsiblePanel_loading_container';
|
|
19
|
+
const panelLoadingClass = `${loadingElementClass}--active`;
|
|
17
20
|
const loadingElementSelector = `.${loadingElementClass}`;
|
|
18
21
|
const NAV_MENU_CONTAINER_ELEMENT_SELECTOR = '.at9 .n3 .TK';
|
|
19
22
|
export class CollapsiblePanelView extends EventEmitter {
|
|
@@ -68,6 +71,13 @@ export class CollapsiblePanelView extends EventEmitter {
|
|
|
68
71
|
this.#element.addEventListener('mouseleave', (e) => {
|
|
69
72
|
this.emit('blur', e);
|
|
70
73
|
});
|
|
74
|
+
stylesStream
|
|
75
|
+
.skipDuplicates((a, b) => isEqual(a, b))
|
|
76
|
+
.onValue(({ type }) => {
|
|
77
|
+
if (type === 'theme') {
|
|
78
|
+
this.#update();
|
|
79
|
+
}
|
|
80
|
+
});
|
|
71
81
|
}
|
|
72
82
|
remove() {
|
|
73
83
|
if (this.#destroyed)
|
|
@@ -86,22 +96,41 @@ export class CollapsiblePanelView extends EventEmitter {
|
|
|
86
96
|
const navItemView = new NavItemView(appId, this.#driver, navItemDescriptorPropertyStream, gmailNavItemView);
|
|
87
97
|
return navItemView;
|
|
88
98
|
}
|
|
99
|
+
#extractPrimaryButtonTheme() {
|
|
100
|
+
const { iconUrl } = this.panelDescriptor.primaryButton ?? {};
|
|
101
|
+
if (!iconUrl) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const theme = GmailElementGetter.isDarkTheme()
|
|
105
|
+
? iconUrl.darkTheme
|
|
106
|
+
: iconUrl.lightTheme;
|
|
107
|
+
if (!theme) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (typeof theme === 'string') {
|
|
111
|
+
return {
|
|
112
|
+
panelHovered: theme,
|
|
113
|
+
panelDefault: theme,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
return {
|
|
118
|
+
panelDefault: theme.panelDefault,
|
|
119
|
+
panelHovered: theme.panelHovered,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
89
123
|
#setupElement() {
|
|
90
124
|
const { panelDescriptor } = this;
|
|
91
125
|
const { loadingIcon } = panelDescriptor;
|
|
92
|
-
const {
|
|
126
|
+
const { className, name = '' } = panelDescriptor?.primaryButton ?? {};
|
|
93
127
|
const element = document.createElement('div');
|
|
94
128
|
element.className = cx(ELEMENT_CLASS, this.panelDescriptor.className);
|
|
95
129
|
const primaryButtonClass = cx(PRIMARY_BUTTON_ELEMENT_CLASS, className);
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
iconUrl = themedIcons.lightTheme;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
130
|
+
const loadingElClass = cx(loadingElementClass, {
|
|
131
|
+
[panelLoadingClass]: this.#loading,
|
|
132
|
+
});
|
|
133
|
+
const { panelDefault: defaultIconUrl, panelHovered: hoverPanelIconUrl } = this.#extractPrimaryButtonTheme() ?? {};
|
|
105
134
|
element.innerHTML = autoHtml `
|
|
106
135
|
<div class="aBO">
|
|
107
136
|
<div class="aic">
|
|
@@ -112,7 +141,7 @@ export class CollapsiblePanelView extends EventEmitter {
|
|
|
112
141
|
</div>
|
|
113
142
|
</div>
|
|
114
143
|
<div class="${scrollablePanelClass}">
|
|
115
|
-
<div class="${
|
|
144
|
+
<div class="${loadingElClass}">${loadingIcon ? { __html: loadingIcon } : ''}</div>
|
|
116
145
|
<div class="Ls77Lb aZ6">
|
|
117
146
|
<div class="pp" style="user-select: none;">
|
|
118
147
|
<div>
|
|
@@ -136,10 +165,11 @@ export class CollapsiblePanelView extends EventEmitter {
|
|
|
136
165
|
</div>
|
|
137
166
|
</div>
|
|
138
167
|
</div>
|
|
139
|
-
<div class="aTV"
|
|
168
|
+
<div class="aTV"></div>
|
|
140
169
|
`.trim();
|
|
141
170
|
const primaryBtnEl = querySelector(element, PRIMARY_BUTTON_ELEMENT_SELECTOR);
|
|
142
|
-
primaryBtnEl.style.setProperty('--background-image',
|
|
171
|
+
primaryBtnEl.style.setProperty('--background-image', defaultIconUrl ? `url(${defaultIconUrl})` : 'unset');
|
|
172
|
+
primaryBtnEl.style.setProperty('--background-image--hover', hoverPanelIconUrl ? `url(${hoverPanelIconUrl})` : 'unset');
|
|
143
173
|
primaryBtnEl.addEventListener('click', this.#onPrimaryButtonClick);
|
|
144
174
|
return element;
|
|
145
175
|
}
|
|
@@ -156,18 +186,35 @@ export class CollapsiblePanelView extends EventEmitter {
|
|
|
156
186
|
this.#updateIcon(element);
|
|
157
187
|
this.#updateScrollablePanelLoading(element);
|
|
158
188
|
}
|
|
189
|
+
static #preloadedIcons = new Set();
|
|
159
190
|
#updateIcon(element) {
|
|
160
191
|
const iconContainerEl = querySelector(element, PRIMARY_BUTTON_ELEMENT_SELECTOR);
|
|
161
|
-
const {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
192
|
+
const { panelDefault, panelHovered } = this.#extractPrimaryButtonTheme() ?? {};
|
|
193
|
+
// alleviate FOUC when switching between active and default icons
|
|
194
|
+
// https://stackoverflow.com/a/68521953/1924257
|
|
195
|
+
for (const url of [panelHovered, panelDefault]) {
|
|
196
|
+
if (!url || CollapsiblePanelView.#preloadedIcons.has(url)) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
CollapsiblePanelView.#preloadedIcons.add(url);
|
|
200
|
+
var link = document.createElement('link');
|
|
201
|
+
link.rel = 'preload';
|
|
202
|
+
link.as = 'image';
|
|
203
|
+
link.href = url;
|
|
204
|
+
document.head.appendChild(link);
|
|
167
205
|
}
|
|
168
|
-
|
|
169
|
-
|
|
206
|
+
for (const [key, value] of Object.entries({
|
|
207
|
+
'--background-image--hover': panelHovered,
|
|
208
|
+
'--background-image': panelDefault,
|
|
209
|
+
})) {
|
|
210
|
+
if (value) {
|
|
211
|
+
iconContainerEl.style.setProperty(key, `url(${value})`);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
iconContainerEl.style.removeProperty(key);
|
|
215
|
+
}
|
|
170
216
|
}
|
|
217
|
+
const { className } = this.panelDescriptor.primaryButton ?? {};
|
|
171
218
|
iconContainerEl.className = cx(PRIMARY_BUTTON_ELEMENT_CLASS, className);
|
|
172
219
|
}
|
|
173
220
|
#updateName(element) {
|
|
@@ -182,7 +229,6 @@ export class CollapsiblePanelView extends EventEmitter {
|
|
|
182
229
|
if (!scrollablePanelLoadingEl) {
|
|
183
230
|
return;
|
|
184
231
|
}
|
|
185
|
-
const panelLoadingClass = `${loadingElementClass}--active`;
|
|
186
232
|
if (this.loading) {
|
|
187
233
|
scrollablePanelLoadingEl.classList.add(panelLoadingClass);
|
|
188
234
|
}
|