@inboxsdk/core 0.2.29-alpha.0 → 0.2.29-alpha.2
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 +14 -14
- package/inboxsdk.js.map +1 -1
- package/package.json +1 -1
- package/src/platform-implementation-js/constants/router.js +8 -3
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-menu-item-view.d.ts +1 -5
- 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 +9 -9
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-route-view/gmail-route-processor.js +3 -1
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-route-view/gmail-route-view.js +35 -0
- package/src/platform-implementation-js/namespaces/app-menu.d.ts +5 -2
- package/src/platform-implementation-js/namespaces/app-menu.d.ts.map +1 -1
- package/src/platform-implementation-js/namespaces/app-menu.js +3 -2
- package/src/platform-implementation-js/views/app-menu-item-view.d.ts +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 +262 -192
- package/src/platform-implementation-js/views/collapsible-panel-view.d.ts +2 -15
- package/src/platform-implementation-js/views/collapsible-panel-view.d.ts.map +1 -1
- package/src/platform-implementation-js/views/collapsible-panel-view.js +6 -61
|
@@ -1,176 +1,294 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import Kefir from 'kefir';
|
|
2
|
+
import kefirStopper from 'kefir-stopper';
|
|
3
|
+
import kefirBus from 'kefir-bus';
|
|
3
4
|
import EventEmitter from '../lib/safe-event-emitter';
|
|
4
5
|
import { GmailAppMenuItemView, NATIVE_CLASS, INBOXSDK_CLASS, } from '../dom-driver/gmail/views/gmail-app-menu-item-view';
|
|
5
|
-
import { CollapsiblePanelView } from './collapsible-panel-view';
|
|
6
|
+
import { NATIVE_CLASS as PANEL_NATIVE_CLASS, CollapsiblePanelView, } from './collapsible-panel-view';
|
|
6
7
|
import { addCollapsiblePanel } from '../dom-driver/gmail/gmail-driver/add-collapsible-panel';
|
|
7
8
|
import GmailElementGetter from '../dom-driver/gmail/gmail-element-getter';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
var NativeAppMenuClassName;
|
|
10
|
+
(function (NativeAppMenuClassName) {
|
|
11
|
+
NativeAppMenuClassName["MAIL"] = "XJ";
|
|
12
|
+
NativeAppMenuClassName["CHAT"] = "ao4";
|
|
13
|
+
NativeAppMenuClassName["SPACES"] = "aIt";
|
|
14
|
+
NativeAppMenuClassName["MEET"] = "adZ";
|
|
15
|
+
})(NativeAppMenuClassName || (NativeAppMenuClassName = {}));
|
|
16
|
+
// Native Gmail menu button => the panel class names mapping
|
|
17
|
+
const nativeButtonToPanelMap = new Map([
|
|
18
|
+
[NativeAppMenuClassName.MAIL, 'aIH'],
|
|
19
|
+
[NativeAppMenuClassName.CHAT, 'arL'],
|
|
20
|
+
[NativeAppMenuClassName.SPACES, 'arM'],
|
|
21
|
+
[NativeAppMenuClassName.MEET, undefined], // Meet
|
|
22
|
+
]);
|
|
23
|
+
/**
|
|
24
|
+
* Mail routes list is not exhaustive
|
|
25
|
+
*/
|
|
26
|
+
const MAIL_ROUTES = ['inbox/:page'];
|
|
27
|
+
const CHAT_ROUTES = ['chat/welcome', 'chat/dm/:chatID'];
|
|
28
|
+
const SPACES_ROUTES = ['rooms/welcome', 'chat/space/:spaceID'];
|
|
29
|
+
const MEET_ROUTES = ['calls'];
|
|
30
|
+
const routeIDtoMenuItemClass = Object.fromEntries([
|
|
31
|
+
...MAIL_ROUTES.map((route) => [route, NativeAppMenuClassName.MAIL]),
|
|
32
|
+
...CHAT_ROUTES.map((route) => [route, NativeAppMenuClassName.CHAT]),
|
|
33
|
+
...SPACES_ROUTES.map((route) => [route, NativeAppMenuClassName.SPACES]),
|
|
34
|
+
...MEET_ROUTES.map((route) => [route, NativeAppMenuClassName.MEET]),
|
|
35
|
+
]);
|
|
36
|
+
const initialRoutingStateStopper = kefirStopper();
|
|
19
37
|
/**
|
|
20
38
|
* Contains both a native Gmail app menu item and a collapsible panel.
|
|
21
39
|
*/
|
|
22
40
|
export class AppMenuItemView extends EventEmitter {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
static #
|
|
27
|
-
static #
|
|
28
|
-
const stream = kefir.stream((emitter) => {
|
|
29
|
-
const observer = new MutationObserver((mutations) => {
|
|
30
|
-
for (const mutation of mutations) {
|
|
31
|
-
const { target } = mutation;
|
|
32
|
-
if (mutation.type === 'attributes' &&
|
|
33
|
-
target instanceof HTMLElement &&
|
|
34
|
-
target.classList.contains(NATIVE_CLASS) &&
|
|
35
|
-
!target.classList.contains(INBOXSDK_CLASS)) {
|
|
36
|
-
if (target.classList.contains(GmailAppMenuItemView.elementCss.ACTIVE)) {
|
|
37
|
-
emitter.emit(['activated', target]);
|
|
38
|
-
}
|
|
39
|
-
else if (target.classList.contains(GmailAppMenuItemView.elementCss.HOVER)) {
|
|
40
|
-
emitter.emit(['hovered', target]);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
const f = async () => {
|
|
46
|
-
const gmailAppMenu = await GmailElementGetter.getAppMenuAsync();
|
|
47
|
-
if (!gmailAppMenu) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
const { ACTIVE } = GmailAppMenuItemView.elementCss;
|
|
51
|
-
const nativeMenuItemSelector = `.${NATIVE_CLASS}.${ACTIVE}:not(.${INBOXSDK_CLASS})`;
|
|
52
|
-
const nativeActivePanel = AppMenuItemView.#getNativeActivePanel();
|
|
53
|
-
setPrevNative({
|
|
54
|
-
menuItem: gmailAppMenu.querySelector(nativeMenuItemSelector),
|
|
55
|
-
panel: nativeActivePanel,
|
|
56
|
-
});
|
|
57
|
-
AppMenuItemView.#activePanel = nativeActivePanel;
|
|
58
|
-
document.addEventListener('mousedown', (e) => {
|
|
59
|
-
const { target } = e;
|
|
60
|
-
if (!(target instanceof Element)) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
if (!gmailAppMenu.contains(target)) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
const closest = target.closest(`.${NATIVE_CLASS}:not(.${INBOXSDK_CLASS})`);
|
|
67
|
-
if (closest) {
|
|
68
|
-
emitter.emit(['mousedown-on-native-el', closest, e]);
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
observer.observe(gmailAppMenu, {
|
|
72
|
-
attributes: true,
|
|
73
|
-
childList: true,
|
|
74
|
-
subtree: true,
|
|
75
|
-
});
|
|
76
|
-
};
|
|
77
|
-
f();
|
|
78
|
-
});
|
|
79
|
-
return stream;
|
|
80
|
-
})();
|
|
81
|
-
static #getNativeActivePanel() {
|
|
41
|
+
static #menuItemChangeStream = Kefir.pool();
|
|
42
|
+
static #routeViewDriverStream;
|
|
43
|
+
static #menuItemToPanelMap = new Map();
|
|
44
|
+
static #appMenuItemViews = new Set();
|
|
45
|
+
static #getActivePanel() {
|
|
82
46
|
const appMenuElement = GmailElementGetter.getAppMenuContainer();
|
|
83
|
-
const { ACTIVE
|
|
84
|
-
const nativePanel = appMenuElement?.querySelector(
|
|
47
|
+
const { ACTIVE } = CollapsiblePanelView.elementCss;
|
|
48
|
+
const nativePanel = appMenuElement?.querySelector(`.${PANEL_NATIVE_CLASS}.${ACTIVE}`);
|
|
85
49
|
return nativePanel;
|
|
86
50
|
}
|
|
87
|
-
static #
|
|
51
|
+
static #getActiveMenuItem() {
|
|
52
|
+
const appMenuElement = GmailElementGetter.getAppMenuContainer();
|
|
53
|
+
const { ACTIVE } = GmailAppMenuItemView.elementCss;
|
|
54
|
+
const button = appMenuElement?.querySelector(`.${NATIVE_CLASS}.${ACTIVE}`);
|
|
55
|
+
return button;
|
|
56
|
+
}
|
|
57
|
+
static #setUpRouteViewDriverStream(driver) {
|
|
58
|
+
if (AppMenuItemView.#routeViewDriverStream)
|
|
59
|
+
return;
|
|
60
|
+
AppMenuItemView.#routeViewDriverStream = driver.getRouteViewDriverStream();
|
|
61
|
+
const bus = kefirBus();
|
|
62
|
+
AppMenuItemView.#menuItemChangeStream.plug(bus);
|
|
63
|
+
AppMenuItemView.#routeViewDriverStream
|
|
64
|
+
.takeUntilBy(initialRoutingStateStopper)
|
|
65
|
+
.onValue(async (routeView) => {
|
|
66
|
+
const routeViewID = routeView.getRouteID();
|
|
67
|
+
const routeType = routeView.getRouteType();
|
|
68
|
+
const routeViewParams = routeView.getParams();
|
|
69
|
+
console.debug({
|
|
70
|
+
routeViewID,
|
|
71
|
+
routeType,
|
|
72
|
+
routeViewParams,
|
|
73
|
+
});
|
|
74
|
+
/* Handling custom app menu items */
|
|
75
|
+
const descriptors = Array.from(AppMenuItemView.#appMenuItemViews, async (appMenuItemView) => {
|
|
76
|
+
const gmailView = await appMenuItemView.#gmailViewPromise;
|
|
77
|
+
return [gmailView.menuItemDescriptor, gmailView];
|
|
78
|
+
});
|
|
79
|
+
const results = await Promise.all(descriptors);
|
|
80
|
+
const [, gmailView] = results.find(([descriptor]) => {
|
|
81
|
+
return descriptor?.isRouteActive(routeView);
|
|
82
|
+
}) ?? [];
|
|
83
|
+
if (gmailView?.element) {
|
|
84
|
+
bus.emit(['click', gmailView.element]);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
/* Handling native app menu items */
|
|
88
|
+
const selector = `.${routeViewID
|
|
89
|
+
? routeIDtoMenuItemClass[routeViewID] ?? NativeAppMenuClassName.MAIL
|
|
90
|
+
: NativeAppMenuClassName.MAIL}`;
|
|
91
|
+
const element = document.querySelector(selector);
|
|
92
|
+
if (element) {
|
|
93
|
+
bus.emit(['click', element]);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
88
98
|
static {
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
(async () => {
|
|
100
|
+
const gmailAppMenu = await GmailElementGetter.getAppMenuAsync();
|
|
101
|
+
if (!gmailAppMenu) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// Set up menu item panel -> menu collapsible panel element mappings
|
|
105
|
+
for (const [menuItemClass, panelClass] of nativeButtonToPanelMap) {
|
|
106
|
+
const menuItemElement = document.querySelector(`.${NATIVE_CLASS}.${menuItemClass}`);
|
|
107
|
+
const panelElement = panelClass
|
|
108
|
+
? document.querySelector(`.${PANEL_NATIVE_CLASS}.${panelClass}`)
|
|
109
|
+
: null;
|
|
110
|
+
if (menuItemElement) {
|
|
111
|
+
AppMenuItemView.#menuItemToPanelMap.set(menuItemElement, panelElement ?? undefined);
|
|
112
|
+
}
|
|
96
113
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
114
|
+
// Set up event listeners we use to control menu UI
|
|
115
|
+
const stream = Kefir.stream((emitter) => {
|
|
116
|
+
// We intercept some events emitted on Gmail (native) menu items to gain full control of the menu (menu items and panels).
|
|
117
|
+
// Thus, some native event handlers won't be invoked so we replicate the Gmail's behavior by ourselves.
|
|
118
|
+
const appMenuElement = GmailElementGetter.getAppMenuContainer();
|
|
119
|
+
for (const nativeMenuItem of appMenuElement?.querySelectorAll(`.${NATIVE_CLASS}:not(.${INBOXSDK_CLASS})`) ?? []) {
|
|
120
|
+
// Gmail uses this listener for panel hover state activation. It's prevented from propagation and we handle UI updates
|
|
121
|
+
nativeMenuItem.addEventListener('mouseenter', (e) => {
|
|
122
|
+
e.stopImmediatePropagation();
|
|
123
|
+
emitter.emit(['mouseenter', nativeMenuItem, e]);
|
|
124
|
+
}, true);
|
|
125
|
+
// Gmail uses this listener for panel hover state deactivation. It's prevented from propagation and we handle UI updates
|
|
126
|
+
nativeMenuItem.addEventListener('mouseleave', (e) => {
|
|
127
|
+
e.stopImmediatePropagation();
|
|
128
|
+
emitter.emit(['mouseleave', nativeMenuItem, e]);
|
|
129
|
+
}, true);
|
|
130
|
+
// Click event isn't prevented from propagation to let Gmail handle routing. The styling is handled by us
|
|
131
|
+
nativeMenuItem.addEventListener('click', () => {
|
|
132
|
+
emitter.emit(['click', nativeMenuItem]);
|
|
133
|
+
});
|
|
134
|
+
// Handle moving cursor out of panel. We use it to enhance the styling since it won't be handled by Gmail
|
|
135
|
+
const panel = AppMenuItemView.#menuItemToPanelMap.get(nativeMenuItem);
|
|
136
|
+
panel?.addEventListener('mouseleave', (e) => {
|
|
137
|
+
emitter.emit(['mouseleave', nativeMenuItem, e]);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
AppMenuItemView.#menuItemChangeStream.plug(stream);
|
|
142
|
+
})();
|
|
143
|
+
}
|
|
144
|
+
static {
|
|
145
|
+
AppMenuItemView.#menuItemChangeStream.onValue(async (v) => {
|
|
146
|
+
const [type, menuItem, mouseEvent] = v;
|
|
147
|
+
const { ACTIVE, HOVER } = GmailAppMenuItemView.elementCss;
|
|
148
|
+
if (type === 'mouseenter') {
|
|
149
|
+
const panel = AppMenuItemView.#menuItemToPanelMap.get(menuItem);
|
|
150
|
+
if (mouseEvent.relatedTarget instanceof Node &&
|
|
151
|
+
(menuItem.contains(mouseEvent.relatedTarget) ||
|
|
152
|
+
panel?.contains(mouseEvent.relatedTarget)))
|
|
153
|
+
return;
|
|
154
|
+
const activeMenuItem = AppMenuItemView.#getActiveMenuItem();
|
|
155
|
+
const activePanel = AppMenuItemView.#getActivePanel();
|
|
156
|
+
if (activeMenuItem === menuItem && activePanel === panel)
|
|
100
157
|
return;
|
|
158
|
+
// deactivate active panel
|
|
159
|
+
if (activePanel) {
|
|
160
|
+
activePanel.style.removeProperty('height');
|
|
161
|
+
activePanel.classList.remove(CollapsiblePanelView.elementCss.ACTIVE);
|
|
162
|
+
activePanel.classList.remove(CollapsiblePanelView.elementCss.HOVER);
|
|
163
|
+
}
|
|
164
|
+
// activate new panel
|
|
165
|
+
if (panel) {
|
|
166
|
+
const height = window.innerHeight - panel.getBoundingClientRect().top;
|
|
167
|
+
panel.style.cssText = `height: ${height}px;`;
|
|
168
|
+
panel.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
|
|
169
|
+
panel.classList.add(CollapsiblePanelView.elementCss.HOVER);
|
|
170
|
+
// hover menu item
|
|
171
|
+
menuItem.classList.add(HOVER);
|
|
101
172
|
}
|
|
102
173
|
else {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
document.location.hash = route;
|
|
107
|
-
}
|
|
108
|
-
menuItem?.classList.add(GmailAppMenuItemView.elementCss.ACTIVE);
|
|
109
|
-
menuItem.classList.remove(GmailAppMenuItemView.elementCss.HOVER);
|
|
174
|
+
// panel doesn't exist (i.e. Meet) so activate active menu item's panel instead (as Gmail currently does -- FEB 2023)
|
|
175
|
+
const panel = activeMenuItem &&
|
|
176
|
+
AppMenuItemView.#menuItemToPanelMap.get(activeMenuItem);
|
|
110
177
|
panel?.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
|
|
111
|
-
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (type === 'mouseleave') {
|
|
181
|
+
const activeMenuItem = AppMenuItemView.#getActiveMenuItem();
|
|
182
|
+
const activePanel = AppMenuItemView.#getActivePanel();
|
|
183
|
+
const activeMenuItemPanel = activeMenuItem &&
|
|
184
|
+
AppMenuItemView.#menuItemToPanelMap.get(activeMenuItem);
|
|
185
|
+
if (mouseEvent.relatedTarget instanceof Node &&
|
|
186
|
+
(menuItem.contains(mouseEvent.relatedTarget) ||
|
|
187
|
+
activePanel?.contains(mouseEvent.relatedTarget)))
|
|
188
|
+
return;
|
|
189
|
+
if (activePanel === activeMenuItemPanel)
|
|
190
|
+
return;
|
|
191
|
+
// unhover menu item
|
|
192
|
+
menuItem.classList.remove(HOVER);
|
|
193
|
+
// deactivate active panel
|
|
194
|
+
if (activePanel) {
|
|
195
|
+
activePanel.style.removeProperty('height');
|
|
196
|
+
activePanel.classList.remove(CollapsiblePanelView.elementCss.ACTIVE);
|
|
197
|
+
activePanel.classList.remove(CollapsiblePanelView.elementCss.HOVER);
|
|
198
|
+
}
|
|
199
|
+
// activate active menu item panel
|
|
200
|
+
if (activeMenuItemPanel) {
|
|
201
|
+
activeMenuItemPanel.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (type === 'click') {
|
|
205
|
+
const appMenuElement = GmailElementGetter.getAppMenuContainer();
|
|
206
|
+
// deactivate active panel
|
|
207
|
+
const activePanel = AppMenuItemView.#getActivePanel();
|
|
208
|
+
if (activePanel) {
|
|
209
|
+
activePanel.style.removeProperty('height');
|
|
210
|
+
activePanel.classList.remove(CollapsiblePanelView.elementCss.ACTIVE);
|
|
211
|
+
activePanel.classList.remove(CollapsiblePanelView.elementCss.HOVER);
|
|
212
|
+
}
|
|
213
|
+
// deactivate menu items
|
|
214
|
+
for (const menuItem_ of appMenuElement?.querySelectorAll(`.${NATIVE_CLASS}`) ?? []) {
|
|
215
|
+
menuItem_.classList.remove(ACTIVE);
|
|
216
|
+
menuItem_.classList.remove(HOVER);
|
|
217
|
+
}
|
|
218
|
+
// activate menu item
|
|
219
|
+
menuItem.classList.add(ACTIVE);
|
|
220
|
+
// activate panel
|
|
221
|
+
const panel = AppMenuItemView.#menuItemToPanelMap.get(menuItem);
|
|
222
|
+
if (panel) {
|
|
223
|
+
panel.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
|
|
112
224
|
}
|
|
113
225
|
}
|
|
114
226
|
});
|
|
115
227
|
}
|
|
228
|
+
get menuItemDescriptor() {
|
|
229
|
+
return this.#menuItemDescriptor;
|
|
230
|
+
}
|
|
116
231
|
#driver;
|
|
117
232
|
#destroyed = false;
|
|
118
233
|
#gmailViewPromise;
|
|
119
234
|
#collapsiblePanel;
|
|
120
|
-
|
|
121
|
-
#
|
|
122
|
-
menuItemDescriptor;
|
|
235
|
+
#appMenuItemStream;
|
|
236
|
+
#collapsiblePanelStream;
|
|
237
|
+
#menuItemDescriptor;
|
|
123
238
|
constructor(driver, menuItemDescriptor) {
|
|
124
239
|
super();
|
|
125
240
|
this.#driver = driver;
|
|
126
|
-
this
|
|
241
|
+
this.#menuItemDescriptor = menuItemDescriptor;
|
|
127
242
|
const gmailAppMenuItemView = this.#driver.addAppMenuItem(menuItemDescriptor);
|
|
128
243
|
this.#gmailViewPromise = gmailAppMenuItemView;
|
|
129
244
|
gmailAppMenuItemView.then((gmailView) => {
|
|
130
245
|
if (this.#destroyed || !gmailView) {
|
|
131
246
|
return; //we have been removed already
|
|
132
247
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
if (activeRouteParams) {
|
|
155
|
-
isActive = isEqual(activeRouteParams, routeViewParams);
|
|
156
|
-
}
|
|
157
|
-
else if (routeParams) {
|
|
158
|
-
isActive = isEqual(routeParams, routeViewParams);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
// deactivation is handled by the native menu item change stream
|
|
162
|
-
if (isActive) {
|
|
163
|
-
this.#activate();
|
|
164
|
-
}
|
|
248
|
+
const gmailElement = gmailView.element;
|
|
249
|
+
if (gmailElement) {
|
|
250
|
+
AppMenuItemView.#menuItemToPanelMap.set(gmailElement, undefined);
|
|
251
|
+
}
|
|
252
|
+
this.#appMenuItemStream = Kefir.stream((emitter) => {
|
|
253
|
+
gmailView.on('destroy', () => {
|
|
254
|
+
emitter.end();
|
|
255
|
+
this.remove();
|
|
256
|
+
});
|
|
257
|
+
gmailView.on('click', () => {
|
|
258
|
+
emitter.emit(['click', gmailElement]);
|
|
259
|
+
this.emit('click');
|
|
260
|
+
});
|
|
261
|
+
gmailView.on('hover', (e) => {
|
|
262
|
+
emitter.emit(['mouseenter', gmailElement, e]);
|
|
263
|
+
this.emit('hover');
|
|
264
|
+
});
|
|
265
|
+
gmailView.on('blur', (e) => {
|
|
266
|
+
emitter.emit(['mouseleave', gmailElement, e]);
|
|
267
|
+
this.emit('blur');
|
|
268
|
+
});
|
|
165
269
|
});
|
|
270
|
+
AppMenuItemView.#menuItemChangeStream.plug(this.#appMenuItemStream);
|
|
271
|
+
AppMenuItemView.#setUpRouteViewDriverStream(driver);
|
|
272
|
+
AppMenuItemView.#appMenuItemViews.add(this);
|
|
166
273
|
});
|
|
167
|
-
AppMenuItemView.#customMenuItems.add(this);
|
|
168
274
|
}
|
|
169
275
|
async addCollapsiblePanel(panelDescriptor) {
|
|
170
276
|
const collapsiblePanel = await addCollapsiblePanel(this.#driver, panelDescriptor);
|
|
171
277
|
if (collapsiblePanel) {
|
|
172
|
-
|
|
173
|
-
|
|
278
|
+
this.#gmailViewPromise.then((gmailView) => {
|
|
279
|
+
const gmailElement = gmailView.element;
|
|
280
|
+
if (gmailElement) {
|
|
281
|
+
this.#collapsiblePanelStream = Kefir.stream((emitter) => {
|
|
282
|
+
collapsiblePanel.on('blur', (e) => {
|
|
283
|
+
emitter.value(['mouseleave', gmailElement, e]);
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
AppMenuItemView.#menuItemChangeStream.plug(this.#collapsiblePanelStream);
|
|
287
|
+
}
|
|
288
|
+
if (gmailElement && collapsiblePanel) {
|
|
289
|
+
AppMenuItemView.#menuItemToPanelMap.set(gmailElement, collapsiblePanel.element);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
174
292
|
}
|
|
175
293
|
this.#collapsiblePanel = collapsiblePanel;
|
|
176
294
|
return collapsiblePanel;
|
|
@@ -183,18 +301,21 @@ export class AppMenuItemView extends EventEmitter {
|
|
|
183
301
|
if (this.#destroyed)
|
|
184
302
|
return;
|
|
185
303
|
this.#destroyed = true;
|
|
186
|
-
AppMenuItemView.#customMenuItems.delete(this);
|
|
187
304
|
this.emit('destroy');
|
|
188
305
|
this.#collapsiblePanel?.remove();
|
|
189
|
-
this.#gmailViewPromise.then((gmailView) =>
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
this.#
|
|
306
|
+
this.#gmailViewPromise.then((gmailView) => {
|
|
307
|
+
gmailView.element &&
|
|
308
|
+
AppMenuItemView.#menuItemToPanelMap.delete(gmailView.element);
|
|
309
|
+
gmailView.remove();
|
|
310
|
+
});
|
|
311
|
+
this.#appMenuItemStream &&
|
|
312
|
+
AppMenuItemView.#menuItemChangeStream.unplug(this.#appMenuItemStream);
|
|
313
|
+
this.#collapsiblePanelStream &&
|
|
314
|
+
AppMenuItemView.#menuItemChangeStream.unplug(this.#collapsiblePanelStream);
|
|
315
|
+
AppMenuItemView.#appMenuItemViews.delete(this);
|
|
316
|
+
initialRoutingStateStopper.destroy();
|
|
195
317
|
}
|
|
196
318
|
async #activate() {
|
|
197
|
-
AppMenuItemView.#activePanel = this.#collapsiblePanel;
|
|
198
319
|
const gmailView = await this.#gmailViewPromise;
|
|
199
320
|
const appMenuElement = GmailElementGetter.getAppMenuContainer();
|
|
200
321
|
const { ACTIVE } = GmailAppMenuItemView.elementCss;
|
|
@@ -205,55 +326,4 @@ export class AppMenuItemView extends EventEmitter {
|
|
|
205
326
|
gmailView.activate();
|
|
206
327
|
this.#collapsiblePanel?.activate();
|
|
207
328
|
}
|
|
208
|
-
#onBlur = async (e) => {
|
|
209
|
-
const gmailView = await this.#gmailViewPromise;
|
|
210
|
-
const { relatedTarget } = e;
|
|
211
|
-
const blurringMenuItem = relatedTarget instanceof Node &&
|
|
212
|
-
gmailView.element?.contains(relatedTarget);
|
|
213
|
-
const blurringPanel = relatedTarget instanceof Node &&
|
|
214
|
-
this.#collapsiblePanel?.element?.contains(relatedTarget);
|
|
215
|
-
if (blurringMenuItem || blurringPanel) {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
this.#hovered = false;
|
|
219
|
-
gmailView.blur();
|
|
220
|
-
const hasActivePanel = this.#hasActivePanel();
|
|
221
|
-
this.#collapsiblePanel?.blur(hasActivePanel);
|
|
222
|
-
if (!hasActivePanel) {
|
|
223
|
-
if (AppMenuItemView.#activePanel instanceof CollapsiblePanelView) {
|
|
224
|
-
AppMenuItemView.#activePanel?.activate();
|
|
225
|
-
}
|
|
226
|
-
else if (AppMenuItemView.#activePanel instanceof HTMLElement) {
|
|
227
|
-
AppMenuItemView.#activePanel.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
this.emit('blur');
|
|
231
|
-
};
|
|
232
|
-
#hasActivePanel() {
|
|
233
|
-
return (this.#collapsiblePanel != null &&
|
|
234
|
-
AppMenuItemView.#activePanel === this.#collapsiblePanel);
|
|
235
|
-
}
|
|
236
|
-
#onHover = async (_e) => {
|
|
237
|
-
if (this.#hovered) {
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
this.#hovered = true;
|
|
241
|
-
const gmailView = await this.#gmailViewPromise;
|
|
242
|
-
gmailView.hover();
|
|
243
|
-
const hasActivePanel = this.#hasActivePanel();
|
|
244
|
-
if (!hasActivePanel) {
|
|
245
|
-
if (AppMenuItemView.#activePanel instanceof CollapsiblePanelView) {
|
|
246
|
-
AppMenuItemView.#activePanel?.deactivate();
|
|
247
|
-
}
|
|
248
|
-
else if (AppMenuItemView.#activePanel instanceof HTMLElement) {
|
|
249
|
-
AppMenuItemView.#activePanel.classList.remove(CollapsiblePanelView.elementCss.ACTIVE);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
this.#collapsiblePanel?.hover(hasActivePanel);
|
|
253
|
-
this.emit('hover');
|
|
254
|
-
};
|
|
255
|
-
#onClick = () => {
|
|
256
|
-
this.#activate();
|
|
257
|
-
this.emit('click');
|
|
258
|
-
};
|
|
259
329
|
}
|
|
@@ -4,11 +4,11 @@ import { AppMenuItemPanelDescriptor } from '../namespaces/app-menu';
|
|
|
4
4
|
import GmailDriver from '../dom-driver/gmail/gmail-driver';
|
|
5
5
|
import { NavItemDescriptor } from '../dom-driver/gmail/views/gmail-nav-item-view';
|
|
6
6
|
import NavItemView from './nav-item-view';
|
|
7
|
+
export declare const NATIVE_CLASS: "aqn";
|
|
8
|
+
export declare const INBOXSDK_CLASS: "inboxsdk__collapsiblePanel";
|
|
7
9
|
type MessageEvents = {
|
|
8
|
-
toggle: (collapsed: boolean) => void;
|
|
9
10
|
destroy: () => void;
|
|
10
11
|
blur: (e: MouseEvent) => void;
|
|
11
|
-
hover: (e: MouseEvent) => void;
|
|
12
12
|
};
|
|
13
13
|
declare const CollapsiblePanelView_base: new () => TypedEmitter<MessageEvents>;
|
|
14
14
|
export declare class CollapsiblePanelView extends CollapsiblePanelView_base {
|
|
@@ -26,23 +26,10 @@ export declare class CollapsiblePanelView extends CollapsiblePanelView_base {
|
|
|
26
26
|
get element(): HTMLElement | undefined;
|
|
27
27
|
set panelDescriptor(panelDescriptor: AppMenuItemPanelDescriptor);
|
|
28
28
|
constructor(driver: GmailDriver);
|
|
29
|
-
toggleCollapse(collapsed: boolean): void;
|
|
30
|
-
/**
|
|
31
|
-
* @internal
|
|
32
|
-
*/
|
|
33
|
-
blur(isActivePanel: boolean): void;
|
|
34
|
-
/**
|
|
35
|
-
* @internal
|
|
36
|
-
*/
|
|
37
|
-
hover(isActivePanel: boolean): void;
|
|
38
29
|
/**
|
|
39
30
|
* @internal
|
|
40
31
|
*/
|
|
41
32
|
activate(): void;
|
|
42
|
-
/**
|
|
43
|
-
* @internal
|
|
44
|
-
*/
|
|
45
|
-
deactivate(): void;
|
|
46
33
|
remove(): void;
|
|
47
34
|
addNavItem(navItemDescriptor: NavItemDescriptor | Kefir.Observable<NavItemDescriptor, any>): NavItemView | undefined;
|
|
48
35
|
}
|
|
@@ -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;AAE1C,eAAO,MAAM,YAAY,OAAiB,CAAC;AAC3C,eAAO,MAAM,cAAc,8BAAwC,CAAC;AAQpE,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;;MAEzC;IAQX,IAAI,OAAO,4BAEV;IAED,IAAI,eAAe,CAAC,eAAe,EAAE,0BAA0B,EAG9D;gBAEW,MAAM,EAAE,WAAW;IAS/B;;OAEG;IACH,QAAQ;IAQR,MAAM;IAON,UAAU,CACR,iBAAiB,EACb,iBAAiB,GACjB,KAAK,CAAC,UAAU,CAAC,iBAAiB,EAAE,GAAG,CAAC;CA+J/C"}
|
|
@@ -6,10 +6,9 @@ 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
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// `aqn oy8Mbf ${COLLAPSED_CLASS_NAME_TOKEN}` as const;
|
|
9
|
+
export const NATIVE_CLASS = 'aqn';
|
|
10
|
+
export const INBOXSDK_CLASS = 'inboxsdk__collapsiblePanel';
|
|
11
|
+
const ELEMENT_CLASS = `${NATIVE_CLASS} ${INBOXSDK_CLASS} oy8Mbf`;
|
|
13
12
|
const PRIMARY_BUTTON_ELEMENT_CLASS = 'T-I T-I-KE L3';
|
|
14
13
|
const PRIMARY_BUTTON_ELEMENT_SELECTOR = '.T-I.T-I-KE.L3';
|
|
15
14
|
const NAV_MENU_CONTAINER_ELEMENT_SELECTOR = '.at9 .n3 .TK';
|
|
@@ -41,48 +40,9 @@ export class CollapsiblePanelView extends EventEmitter {
|
|
|
41
40
|
super();
|
|
42
41
|
this.#driver = driver;
|
|
43
42
|
this.#element = this.#setupElement();
|
|
44
|
-
this.#element.addEventListener('
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
toggleCollapse(collapsed) {
|
|
48
|
-
const element = this.element;
|
|
49
|
-
if (!element)
|
|
50
|
-
return;
|
|
51
|
-
const { COLLAPSED } = CollapsiblePanelView.elementCss;
|
|
52
|
-
if (collapsed) {
|
|
53
|
-
element.classList.add(COLLAPSED);
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
element.classList.remove(COLLAPSED);
|
|
57
|
-
}
|
|
58
|
-
this.emit('toggle', collapsed);
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* @internal
|
|
62
|
-
*/
|
|
63
|
-
blur(isActivePanel) {
|
|
64
|
-
const { element } = this;
|
|
65
|
-
if (!element)
|
|
66
|
-
return;
|
|
67
|
-
element.classList.remove(CollapsiblePanelView.elementCss.HOVER);
|
|
68
|
-
if (!isActivePanel) {
|
|
69
|
-
element.classList.remove(CollapsiblePanelView.elementCss.ACTIVE);
|
|
70
|
-
}
|
|
71
|
-
element.style.removeProperty('height');
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* @internal
|
|
75
|
-
*/
|
|
76
|
-
hover(isActivePanel) {
|
|
77
|
-
const { element } = this;
|
|
78
|
-
const { ACTIVE, HOVER } = CollapsiblePanelView.elementCss;
|
|
79
|
-
if (!element || element.classList.contains(ACTIVE))
|
|
80
|
-
return;
|
|
81
|
-
element.classList.add(HOVER);
|
|
82
|
-
if (!isActivePanel) {
|
|
83
|
-
element.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
|
|
84
|
-
}
|
|
85
|
-
element.style.cssText = 'height: 785px;';
|
|
43
|
+
this.#element.addEventListener('mouseleave', (e) => {
|
|
44
|
+
this.emit('blur', e);
|
|
45
|
+
});
|
|
86
46
|
}
|
|
87
47
|
/**
|
|
88
48
|
* @internal
|
|
@@ -94,15 +54,6 @@ export class CollapsiblePanelView extends EventEmitter {
|
|
|
94
54
|
element?.classList.remove(CollapsiblePanelView.elementCss.HOVER);
|
|
95
55
|
element.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
|
|
96
56
|
}
|
|
97
|
-
/**
|
|
98
|
-
* @internal
|
|
99
|
-
*/
|
|
100
|
-
deactivate() {
|
|
101
|
-
const element = this.element;
|
|
102
|
-
if (!element)
|
|
103
|
-
return;
|
|
104
|
-
element.classList.remove(CollapsiblePanelView.elementCss.ACTIVE);
|
|
105
|
-
}
|
|
106
57
|
remove() {
|
|
107
58
|
if (this.#destroyed)
|
|
108
59
|
return;
|
|
@@ -213,10 +164,4 @@ export class CollapsiblePanelView extends EventEmitter {
|
|
|
213
164
|
}
|
|
214
165
|
buttonTextEl.textContent = this.#panelDescriptor?.primaryButton?.name ?? '';
|
|
215
166
|
}
|
|
216
|
-
#onBlur = (e) => {
|
|
217
|
-
this.emit('blur', e);
|
|
218
|
-
};
|
|
219
|
-
#onHover = (e) => {
|
|
220
|
-
this.emit('hover', e);
|
|
221
|
-
};
|
|
222
167
|
}
|