@inboxsdk/core 0.2.28-alpha.2 → 0.2.28-alpha.4
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 +1 -1
- package/inboxsdk.js.map +1 -1
- package/package.json +1 -1
- package/src/build/exec.js +26 -0
- package/src/build/spawn.js +17 -0
- package/src/common/ajax.js +90 -0
- package/src/common/cachebust-url.js +10 -0
- package/src/common/censorHTMLstring.js +37 -0
- package/src/common/censorHTMLtree.js +28 -0
- package/src/common/censorJSONTree.js +15 -0
- package/src/common/connectivity-test.js +21 -0
- package/src/common/defer.js +11 -0
- package/src/common/find-parent.js +10 -0
- package/src/common/get-extension-id.js +7 -0
- package/src/common/get-or-fail.js +8 -0
- package/src/common/get-session-id.js +14 -0
- package/src/common/get-stack-trace.js +6 -0
- package/src/common/html-to-text.js +7 -0
- package/src/common/isElementVisible.js +6 -0
- package/src/common/load-script.js +127 -0
- package/src/common/log-error.js +191 -0
- package/src/common/quoted-split.js +18 -0
- package/src/common/rate-limit-queuer.js +57 -0
- package/src/common/rate-limit.js +14 -0
- package/src/common/version.js +6 -0
- package/src/inboxsdk-js/loading/platform-implementation-loader.js +27 -0
- package/src/inboxsdk.d.ts +2 -0
- package/src/injected-js/gmail/constants.js +2 -0
- package/src/injected-js/gmail/modify-suggestions.js +106 -0
- package/src/injected-js/gmail/setup-gmonkey-handler.js +49 -0
- package/src/injected-js/gmail/sync-compose-processor-20220909.js +298 -0
- package/src/injected-js/gmail/sync-compose-processor.js +55 -0
- package/src/injected-js/gmail/sync-compose-request-processor.js +110 -0
- package/src/injected-js/injected-logger.js +50 -0
- package/src/injected-js/setupCustomViewEventAssassin.js +90 -0
- package/src/platform-implementation-js/constants/nav-item-types.js +19 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-app-menu-item.js +21 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-collapsible-panel.js +28 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-nav-item.js +98 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-support-item.js +4 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/encodeDraftUrlId.js +8 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/get-rfc-message-id-for-gmail-message-id.js +12 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/get-rfc-message-id-for-gmail-thread-id.js +33 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/isIntegratedViewGmail.js +4 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/open-draft-by-message-id.js +44 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-gmail-styles.js +95 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter/get-main-content-element-changed-stream.js +38 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter/wait-for-gmail-mode-to-settle.js +12 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter.js +253 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-page-communicator.js +200 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-response-processor.js +533 -0
- package/src/platform-implementation-js/dom-driver/gmail/gmail-sync-response-processor.js +289 -0
- package/src/platform-implementation-js/dom-driver/gmail/is-compose-titlebar-light-color.js +21 -0
- package/src/platform-implementation-js/dom-driver/gmail/makePageParserTree.js +28 -0
- package/src/platform-implementation-js/dom-driver/gmail/pageParserOptions.js +19 -0
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-menu-item-view.js +126 -0
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-status-bar.js +101 -0
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/detectClassicRecipientsArea.js +38 -0
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-address-information-extractor.js +28 -0
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-recipients.js +22 -0
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/gmail-compose-button-view.js +233 -0
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/page-parser.js +223 -0
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/set-recipients.js +157 -0
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/setupLinkPopovers.js +109 -0
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view/attachment-icon.js +5 -0
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-nav-item-view.js +759 -0
- package/src/platform-implementation-js/dom-driver/gmail/views/gmail-support-item-view.js +84 -0
- package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/button-color-classes.js +33 -0
- package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/button-view.js +325 -0
- package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-accessory-button-view.js +58 -0
- package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-parent-accessory-button-view.js +55 -0
- package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/modal-button-view.js +96 -0
- package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/more-dropdown-button-view.js +30 -0
- package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/more-parent-accessory-button-view.js +10 -0
- package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-dropdown-view.js +22 -0
- package/src/platform-implementation-js/driver-common/getAccountUrlPart.js +17 -0
- package/src/platform-implementation-js/driver-common/getOriginalMessagePage.js +33 -0
- package/src/platform-implementation-js/driver-common/getSyncThreadsForSearch.js +49 -0
- package/src/platform-implementation-js/driver-common/gmailAjax.js +65 -0
- package/src/platform-implementation-js/driver-common/render-custom-icon.js +16 -0
- package/src/platform-implementation-js/driver-common/update-icon.js +90 -0
- package/src/platform-implementation-js/lib/ErrorCollector.js +47 -0
- package/src/platform-implementation-js/lib/Membrane.js +22 -0
- package/src/platform-implementation-js/lib/ScrollableContainByScreen.js +30 -0
- package/src/platform-implementation-js/lib/attemptWithRetries.js +16 -0
- package/src/platform-implementation-js/lib/common-page-communicator.js +137 -0
- package/src/platform-implementation-js/lib/delay-asap.js +12 -0
- package/src/platform-implementation-js/lib/delay-idle.js +16 -0
- package/src/platform-implementation-js/lib/dom/block-and-reemit-keyboard-events.js +36 -0
- package/src/platform-implementation-js/lib/dom/generic-button-view.js +39 -0
- package/src/platform-implementation-js/lib/dom/get-insert-before-element.js +39 -0
- package/src/platform-implementation-js/lib/dom/insert-element-in-order.js +38 -0
- package/src/platform-implementation-js/lib/dom/keyboard-shortcut-stream.js +12 -0
- package/src/platform-implementation-js/lib/dom/make-element-child-stream.js +79 -0
- package/src/platform-implementation-js/lib/dom/make-element-stream-merger.js +28 -0
- package/src/platform-implementation-js/lib/dom/make-element-view-stream.js +15 -0
- package/src/platform-implementation-js/lib/dom/make-mutation-observer-chunked-stream.js +15 -0
- package/src/platform-implementation-js/lib/dom/make-mutation-observer-stream.js +5 -0
- package/src/platform-implementation-js/lib/dom/outsideClicksAndEscape.js +39 -0
- package/src/platform-implementation-js/lib/dom/parentNodes.js +8 -0
- package/src/platform-implementation-js/lib/dom/querySelectorOrFail.js +6 -0
- package/src/platform-implementation-js/lib/dom/reemitClickEventForReact.js +22 -0
- package/src/platform-implementation-js/lib/dom/simulate-key.js +46 -0
- package/src/platform-implementation-js/lib/dom/simulate-mouse-event.js +16 -0
- package/src/platform-implementation-js/lib/dom/trigger-relay-event.js +7 -0
- package/src/platform-implementation-js/lib/extract-contact-from-email-contact-string.js +25 -0
- package/src/platform-implementation-js/lib/fake-window-resize.js +5 -0
- package/src/platform-implementation-js/lib/from-event-target-capture.js +12 -0
- package/src/platform-implementation-js/lib/fromEventsWithOptions.js +10 -0
- package/src/platform-implementation-js/lib/handler-registry.js +67 -0
- package/src/platform-implementation-js/lib/idMap.js +45 -0
- package/src/platform-implementation-js/lib/imageRequest.js +8 -0
- package/src/platform-implementation-js/lib/incrementName.js +7 -0
- package/src/platform-implementation-js/lib/inject-script-EMBEDDED.js +14 -0
- package/src/platform-implementation-js/lib/inject-script.js +33 -0
- package/src/platform-implementation-js/lib/is-valid-app-id.js +27 -0
- package/src/platform-implementation-js/lib/is-valid-email.js +14 -0
- package/src/platform-implementation-js/lib/isNotNil.js +5 -0
- package/src/platform-implementation-js/lib/isStreakAppId.js +11 -0
- package/src/platform-implementation-js/lib/logger.js +441 -0
- package/src/platform-implementation-js/lib/persistent-queue.js +107 -0
- package/src/platform-implementation-js/lib/safe-event-emitter.js +17 -0
- package/src/platform-implementation-js/lib/stopper-pool.js +41 -0
- package/src/platform-implementation-js/lib/stream-wait-for.js +30 -0
- package/src/platform-implementation-js/lib/wait-for.js +28 -0
- package/src/platform-implementation-js/lib/waitForAsync.js +19 -0
- package/src/platform-implementation-js/namespaces/app-menu.d.ts.map +1 -1
- package/src/platform-implementation-js/namespaces/app-menu.js +31 -0
- package/src/platform-implementation-js/namespaces/butter-bar.js +163 -0
- package/src/platform-implementation-js/views/SimpleElementView.js +16 -0
- package/src/platform-implementation-js/views/app-menu-item-view.js +257 -0
- package/src/platform-implementation-js/views/collapsible-panel-view.js +222 -0
- package/src/platform-implementation-js/views/compose-button-view.js +45 -0
- package/src/platform-implementation-js/views/compose-view.js +312 -0
- package/src/platform-implementation-js/views/keyboard-shortcut-handle.js +14 -0
- package/src/platform-implementation-js/widgets/buttons/basic-button-view-controller.js +39 -0
- package/src/platform-implementation-js/widgets/buttons/dropdown-button-view-controller.js +98 -0
- package/src/platform-implementation-js/widgets/buttons/dropdown-view.js +122 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import cx from 'classnames';
|
|
2
|
+
import * as Kefir from 'kefir';
|
|
3
|
+
import kefirCast from 'kefir-cast';
|
|
4
|
+
import EventEmitter from '../lib/safe-event-emitter';
|
|
5
|
+
import autoHtml from 'auto-html';
|
|
6
|
+
import querySelector from '../lib/dom/querySelectorOrFail';
|
|
7
|
+
import GmailElementGetter from '../dom-driver/gmail/gmail-element-getter';
|
|
8
|
+
import NavItemView from './nav-item-view';
|
|
9
|
+
const ELEMENT_CLASS = 'aqn oy8Mbf inboxsdk__collapsiblePanel';
|
|
10
|
+
// const ELEMENT_CLASS_ACTIVE = `aqn oy8Mbf ${ACTIVE_CLASS_NAME_TOKEN}` as const;
|
|
11
|
+
// const ELEMENT_CLASS_COLLAPSED =
|
|
12
|
+
// `aqn oy8Mbf ${COLLAPSED_CLASS_NAME_TOKEN}` as const;
|
|
13
|
+
const PRIMARY_BUTTON_ELEMENT_CLASS = 'T-I T-I-KE L3';
|
|
14
|
+
const PRIMARY_BUTTON_ELEMENT_SELECTOR = '.T-I.T-I-KE.L3';
|
|
15
|
+
const NAV_MENU_CONTAINER_ELEMENT_SELECTOR = '.at9 .n3 .TK';
|
|
16
|
+
export class CollapsiblePanelView extends EventEmitter {
|
|
17
|
+
static elementSelectors = {
|
|
18
|
+
NATIVE: '.aqn.oy8Mbf',
|
|
19
|
+
CUSTOM: '.inboxsdk__collapsiblePanel',
|
|
20
|
+
};
|
|
21
|
+
static elementCss = {
|
|
22
|
+
ACTIVE: 'apV',
|
|
23
|
+
COLLAPSED: 'aBa',
|
|
24
|
+
/** A hover popover has both ACTIVE _and_ HOVER */
|
|
25
|
+
HOVER: 'aJu',
|
|
26
|
+
};
|
|
27
|
+
#panelDescriptor;
|
|
28
|
+
#element;
|
|
29
|
+
#destroyed = false;
|
|
30
|
+
#id = Math.random().toFixed(3);
|
|
31
|
+
#ARIA_LABELLED_BY_ID = Math.random().toFixed(3);
|
|
32
|
+
#driver;
|
|
33
|
+
get element() {
|
|
34
|
+
return this.#element;
|
|
35
|
+
}
|
|
36
|
+
set panelDescriptor(panelDescriptor) {
|
|
37
|
+
this.#panelDescriptor = panelDescriptor;
|
|
38
|
+
this.#update();
|
|
39
|
+
}
|
|
40
|
+
constructor(driver) {
|
|
41
|
+
super();
|
|
42
|
+
this.#driver = driver;
|
|
43
|
+
this.#element = this.#setupElement();
|
|
44
|
+
this.#element.addEventListener('mouseover', this.#onHover);
|
|
45
|
+
this.#element.addEventListener('mouseout', this.#onBlur);
|
|
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;';
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* @internal
|
|
89
|
+
*/
|
|
90
|
+
activate() {
|
|
91
|
+
const element = this.element;
|
|
92
|
+
if (!element)
|
|
93
|
+
return;
|
|
94
|
+
element?.classList.remove(CollapsiblePanelView.elementCss.HOVER);
|
|
95
|
+
element.classList.add(CollapsiblePanelView.elementCss.ACTIVE);
|
|
96
|
+
}
|
|
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
|
+
remove() {
|
|
107
|
+
if (this.#destroyed)
|
|
108
|
+
return;
|
|
109
|
+
this.#destroyed = true;
|
|
110
|
+
this.element?.remove();
|
|
111
|
+
this.emit('destroy');
|
|
112
|
+
}
|
|
113
|
+
addNavItem(navItemDescriptor) {
|
|
114
|
+
const element = this.element;
|
|
115
|
+
if (!element)
|
|
116
|
+
return;
|
|
117
|
+
const navMenuContainerElement = querySelector(element, NAV_MENU_CONTAINER_ELEMENT_SELECTOR);
|
|
118
|
+
const appId = `collapsible-panel-${this.#id}`;
|
|
119
|
+
const navItemDescriptorPropertyStream = kefirCast(Kefir, navItemDescriptor).toProperty();
|
|
120
|
+
const gmailNavItemView = this.#driver.addNavItem(appId, navItemDescriptorPropertyStream, navMenuContainerElement);
|
|
121
|
+
const navItemView = new NavItemView(appId, this.#driver, navItemDescriptorPropertyStream, gmailNavItemView);
|
|
122
|
+
return navItemView;
|
|
123
|
+
}
|
|
124
|
+
#setupElement() {
|
|
125
|
+
const { iconUrl: themedIcons, className, name = '', } = this.#panelDescriptor?.primaryButton ?? {};
|
|
126
|
+
const element = document.createElement('div');
|
|
127
|
+
element.className = ELEMENT_CLASS;
|
|
128
|
+
const primaryButtonClass = cx(PRIMARY_BUTTON_ELEMENT_CLASS, className);
|
|
129
|
+
let iconUrl;
|
|
130
|
+
if (themedIcons) {
|
|
131
|
+
if (GmailElementGetter.isDarkTheme()) {
|
|
132
|
+
iconUrl = themedIcons.darkTheme;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
iconUrl = themedIcons.lightTheme;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
element.innerHTML = autoHtml `
|
|
139
|
+
<div class="aBO">
|
|
140
|
+
<div class="aic">
|
|
141
|
+
<div class="z0">
|
|
142
|
+
<div class="${primaryButtonClass}" style="user-select: none" role="button" tabindex="0">
|
|
143
|
+
${name}
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
<div class="at9">
|
|
148
|
+
<div class="Ls77Lb aZ6">
|
|
149
|
+
<div class="pp" style="user-select: none;">
|
|
150
|
+
<div>
|
|
151
|
+
<div class="nM">
|
|
152
|
+
<div class="aic"></div>
|
|
153
|
+
<div class="yJ">
|
|
154
|
+
<div class="ajl aib aZ6" aria-labelledby="${this.#ARIA_LABELLED_BY_ID}">
|
|
155
|
+
<h2 class="aWk" id="${this.#ARIA_LABELLED_BY_ID}">Labels</h2>
|
|
156
|
+
<div class="wT">
|
|
157
|
+
<div class="n3">
|
|
158
|
+
<div class="byl">
|
|
159
|
+
<div class="TK"></div>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
<div class="aTV" style="top: 27px;"></div>
|
|
172
|
+
`.trim();
|
|
173
|
+
const primaryBtnEl = querySelector(element, PRIMARY_BUTTON_ELEMENT_SELECTOR);
|
|
174
|
+
primaryBtnEl.style.setProperty('--background-image', iconUrl ? `url(${iconUrl})` : 'unset');
|
|
175
|
+
primaryBtnEl.addEventListener('click', this.#onPrimaryButtonClick);
|
|
176
|
+
return element;
|
|
177
|
+
}
|
|
178
|
+
#onPrimaryButtonClick = (e) => {
|
|
179
|
+
this.#panelDescriptor?.primaryButton?.onClick?.(e);
|
|
180
|
+
};
|
|
181
|
+
#update() {
|
|
182
|
+
const element = this.element;
|
|
183
|
+
if (!element)
|
|
184
|
+
return;
|
|
185
|
+
const { ACTIVE, COLLAPSED } = CollapsiblePanelView.elementCss;
|
|
186
|
+
const isActive = element.classList.contains(ACTIVE);
|
|
187
|
+
const isCollapsed = element.classList.contains(COLLAPSED);
|
|
188
|
+
element.className = cx(ELEMENT_CLASS, this.#panelDescriptor?.className, {
|
|
189
|
+
[ACTIVE]: isActive,
|
|
190
|
+
[COLLAPSED]: isCollapsed,
|
|
191
|
+
});
|
|
192
|
+
this.#updateName(element);
|
|
193
|
+
this.#updateIcon(element);
|
|
194
|
+
}
|
|
195
|
+
#updateIcon(element) {
|
|
196
|
+
const iconContainerEl = querySelector(element, PRIMARY_BUTTON_ELEMENT_SELECTOR);
|
|
197
|
+
const { iconUrl, className } = this.#panelDescriptor?.primaryButton ?? {};
|
|
198
|
+
if (iconUrl) {
|
|
199
|
+
const backgroundImage = `url(${GmailElementGetter.isDarkTheme()
|
|
200
|
+
? iconUrl.darkTheme
|
|
201
|
+
: iconUrl.lightTheme})`;
|
|
202
|
+
iconContainerEl.style.setProperty('--background-image', backgroundImage);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
iconContainerEl.style.setProperty('--background-image', 'unset');
|
|
206
|
+
}
|
|
207
|
+
iconContainerEl.className = cx(PRIMARY_BUTTON_ELEMENT_CLASS, className);
|
|
208
|
+
}
|
|
209
|
+
#updateName(element) {
|
|
210
|
+
const buttonTextEl = element.querySelector(PRIMARY_BUTTON_ELEMENT_SELECTOR);
|
|
211
|
+
if (!buttonTextEl) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
buttonTextEl.textContent = this.#panelDescriptor?.primaryButton?.name ?? '';
|
|
215
|
+
}
|
|
216
|
+
#onBlur = (e) => {
|
|
217
|
+
this.emit('blur', e);
|
|
218
|
+
};
|
|
219
|
+
#onHover = (e) => {
|
|
220
|
+
this.emit('hover', e);
|
|
221
|
+
};
|
|
222
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import EventEmitter from '../lib/safe-event-emitter';
|
|
2
|
+
import get from '../../common/get-or-fail';
|
|
3
|
+
const memberMap = new WeakMap();
|
|
4
|
+
export default class ComposeButtonView extends EventEmitter {
|
|
5
|
+
destroyed = false;
|
|
6
|
+
constructor(optionsPromise, composeViewDriver, driver) {
|
|
7
|
+
super();
|
|
8
|
+
const members = { optionsPromise, composeViewDriver, driver };
|
|
9
|
+
memberMap.set(this, members);
|
|
10
|
+
members.optionsPromise.then((options) => {
|
|
11
|
+
if (!options) {
|
|
12
|
+
_destroy(this);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
members.composeViewDriver.getStopper().onValue(() => {
|
|
16
|
+
_destroy(this);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
showTooltip(tooltipDescriptor) {
|
|
21
|
+
const members = get(memberMap, this);
|
|
22
|
+
members.driver
|
|
23
|
+
.getLogger()
|
|
24
|
+
.eventSdkPassive('ComposeButtonView.showTooltip', {
|
|
25
|
+
keys: Object.keys(tooltipDescriptor),
|
|
26
|
+
});
|
|
27
|
+
members.optionsPromise.then((options) => {
|
|
28
|
+
if (!options)
|
|
29
|
+
return;
|
|
30
|
+
members.composeViewDriver.addTooltipToButton(options.buttonViewController, options.buttonDescriptor, tooltipDescriptor);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
closeTooltip() {
|
|
34
|
+
const members = get(memberMap, this);
|
|
35
|
+
members.optionsPromise.then((options) => {
|
|
36
|
+
if (!options)
|
|
37
|
+
return;
|
|
38
|
+
members.composeViewDriver.closeButtonTooltip(options.buttonViewController);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function _destroy(composeButtonViewInstance) {
|
|
43
|
+
composeButtonViewInstance.destroyed = true;
|
|
44
|
+
composeButtonViewInstance.emit('destroy');
|
|
45
|
+
}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import EventEmitter from '../lib/safe-event-emitter';
|
|
3
|
+
import Kefir from 'kefir';
|
|
4
|
+
import kefirCast from 'kefir-cast';
|
|
5
|
+
import * as ud from 'ud';
|
|
6
|
+
import get from '../../common/get-or-fail';
|
|
7
|
+
import ComposeButtonView from './compose-button-view';
|
|
8
|
+
const memberMap = ud.defonce(module, () => new WeakMap());
|
|
9
|
+
// documented in src/docs/
|
|
10
|
+
export default class ComposeView extends EventEmitter {
|
|
11
|
+
destroyed = false;
|
|
12
|
+
constructor(driver, composeViewImplementation, membrane) {
|
|
13
|
+
super();
|
|
14
|
+
const members = {
|
|
15
|
+
driver,
|
|
16
|
+
membrane,
|
|
17
|
+
composeViewImplementation,
|
|
18
|
+
};
|
|
19
|
+
memberMap.set(this, members);
|
|
20
|
+
this.on('newListener', (eventName) => {
|
|
21
|
+
if (eventName === 'close') {
|
|
22
|
+
driver
|
|
23
|
+
.getLogger()
|
|
24
|
+
.deprecationWarning('composeView close event', 'composeView destroy event');
|
|
25
|
+
if (driver.getOpts().REQUESTED_API_VERSION !== 1) {
|
|
26
|
+
console.error('The composeView close event was removed after API version 1');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else if (eventName === 'messageIDChange') {
|
|
30
|
+
driver
|
|
31
|
+
.getLogger()
|
|
32
|
+
.deprecationWarning('composeView messageIDChange event', 'composeView.getDraftID');
|
|
33
|
+
if (driver.getOpts().REQUESTED_API_VERSION !== 1) {
|
|
34
|
+
console.error('The composeView messageIDChange event was removed after API version 1');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else if (eventName === 'linkPopOver') {
|
|
38
|
+
composeViewImplementation.setupLinkPopOvers();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
members.composeViewImplementation.getEventStream().onValue((event) => {
|
|
42
|
+
if (event.eventName === 'destroy') {
|
|
43
|
+
this.destroyed = true;
|
|
44
|
+
if (driver.getOpts().REQUESTED_API_VERSION === 1) {
|
|
45
|
+
this.emit('close'); /* deprecated */
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else if (event.eventName === 'messageIDChange') {
|
|
49
|
+
if (driver.getOpts().REQUESTED_API_VERSION !== 1) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
this.emit(event.eventName, event.data);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
addButton(buttonDescriptor) {
|
|
57
|
+
const members = get(memberMap, this);
|
|
58
|
+
const buttonDescriptorStream = kefirCast(Kefir, buttonDescriptor);
|
|
59
|
+
const optionsPromise = members.composeViewImplementation.addButton(buttonDescriptorStream, members.driver.getAppId(), { composeView: this });
|
|
60
|
+
return new ComposeButtonView(optionsPromise, members.composeViewImplementation, members.driver);
|
|
61
|
+
}
|
|
62
|
+
/*
|
|
63
|
+
// Incomplete
|
|
64
|
+
addInnerSidebar(options){
|
|
65
|
+
get(memberMap, this).composeViewImplementation.addInnerSidebar(options);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Incomplete
|
|
69
|
+
addOuterSidebar(options){
|
|
70
|
+
get(memberMap, this).composeViewImplementation.addOuterSidebar(options);
|
|
71
|
+
}
|
|
72
|
+
*/
|
|
73
|
+
addComposeNotice(composeNoticeDescriptor) {
|
|
74
|
+
return get(memberMap, this).composeViewImplementation.addComposeNotice(composeNoticeDescriptor);
|
|
75
|
+
}
|
|
76
|
+
addStatusBar(statusBarDescriptor) {
|
|
77
|
+
return get(memberMap, this).composeViewImplementation.addStatusBar(statusBarDescriptor);
|
|
78
|
+
}
|
|
79
|
+
hideNativeStatusBar() {
|
|
80
|
+
return get(memberMap, this).composeViewImplementation.hideNativeStatusBar();
|
|
81
|
+
}
|
|
82
|
+
addRecipientRow(options) {
|
|
83
|
+
return {
|
|
84
|
+
destroy: get(memberMap, this).composeViewImplementation.addRecipientRow(kefirCast(Kefir, options)),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
forceRecipientRowsOpen() {
|
|
88
|
+
return get(memberMap, this).composeViewImplementation.forceRecipientRowsOpen();
|
|
89
|
+
}
|
|
90
|
+
hideNativeRecipientRows() {
|
|
91
|
+
return get(memberMap, this).composeViewImplementation.hideNativeRecipientRows();
|
|
92
|
+
}
|
|
93
|
+
hideRecipientArea() {
|
|
94
|
+
return get(memberMap, this).composeViewImplementation.hideRecipientArea();
|
|
95
|
+
}
|
|
96
|
+
close() {
|
|
97
|
+
get(memberMap, this).composeViewImplementation.close();
|
|
98
|
+
}
|
|
99
|
+
send({ sendAndArchive } = { sendAndArchive: false }) {
|
|
100
|
+
get(memberMap, this).composeViewImplementation.send({ sendAndArchive });
|
|
101
|
+
}
|
|
102
|
+
discard() {
|
|
103
|
+
get(memberMap, this).composeViewImplementation.discard();
|
|
104
|
+
}
|
|
105
|
+
getMetadataForm() {
|
|
106
|
+
return get(memberMap, this).composeViewImplementation.getMetadataFormElement();
|
|
107
|
+
}
|
|
108
|
+
getSubjectInput() {
|
|
109
|
+
return get(memberMap, this).composeViewImplementation.getSubjectInput();
|
|
110
|
+
}
|
|
111
|
+
getBodyElement() {
|
|
112
|
+
return get(memberMap, this).composeViewImplementation.getBodyElement();
|
|
113
|
+
}
|
|
114
|
+
// NOT DOCUMENTED BECAUSE NOT SURE IF API USERS NEED THIS
|
|
115
|
+
// TODO remove?
|
|
116
|
+
getComposeID() {
|
|
117
|
+
const { driver, composeViewImplementation } = get(memberMap, this);
|
|
118
|
+
driver.getLogger().deprecationWarning('composeView.getComposeID');
|
|
119
|
+
if (driver.getOpts().REQUESTED_API_VERSION !== 1) {
|
|
120
|
+
throw new Error('This method was discontinued after API version 1');
|
|
121
|
+
}
|
|
122
|
+
return composeViewImplementation.getComposeID();
|
|
123
|
+
}
|
|
124
|
+
getInitialMessageID() {
|
|
125
|
+
return get(memberMap, this).composeViewImplementation.getInitialMessageID();
|
|
126
|
+
}
|
|
127
|
+
/* deprecated */
|
|
128
|
+
getMessageID() {
|
|
129
|
+
const { driver, composeViewImplementation } = get(memberMap, this);
|
|
130
|
+
driver
|
|
131
|
+
.getLogger()
|
|
132
|
+
.deprecationWarning('composeView.getMessageID', 'composeView.getDraftID');
|
|
133
|
+
if (driver.getOpts().REQUESTED_API_VERSION !== 1) {
|
|
134
|
+
throw new Error('This method was discontinued after API version 1');
|
|
135
|
+
}
|
|
136
|
+
return composeViewImplementation.getMessageID();
|
|
137
|
+
}
|
|
138
|
+
getThreadID() {
|
|
139
|
+
return get(memberMap, this).composeViewImplementation.getThreadID();
|
|
140
|
+
}
|
|
141
|
+
getDraftID() {
|
|
142
|
+
return get(memberMap, this).composeViewImplementation.getDraftID();
|
|
143
|
+
}
|
|
144
|
+
getCurrentDraftID() {
|
|
145
|
+
return get(memberMap, this).composeViewImplementation.getCurrentDraftID();
|
|
146
|
+
}
|
|
147
|
+
getHTMLContent() {
|
|
148
|
+
return get(memberMap, this).composeViewImplementation.getHTMLContent();
|
|
149
|
+
}
|
|
150
|
+
getSelectedBodyHTML() {
|
|
151
|
+
return (get(memberMap, this).composeViewImplementation.getSelectedBodyHTML() || '');
|
|
152
|
+
}
|
|
153
|
+
getSelectedBodyText() {
|
|
154
|
+
return (get(memberMap, this).composeViewImplementation.getSelectedBodyText() || '');
|
|
155
|
+
}
|
|
156
|
+
getSubject() {
|
|
157
|
+
return get(memberMap, this).composeViewImplementation.getSubject();
|
|
158
|
+
}
|
|
159
|
+
getTextContent() {
|
|
160
|
+
return get(memberMap, this).composeViewImplementation.getTextContent();
|
|
161
|
+
}
|
|
162
|
+
getToRecipients() {
|
|
163
|
+
return get(memberMap, this).composeViewImplementation.getToRecipients();
|
|
164
|
+
}
|
|
165
|
+
getCcRecipients() {
|
|
166
|
+
return get(memberMap, this).composeViewImplementation.getCcRecipients();
|
|
167
|
+
}
|
|
168
|
+
getBccRecipients() {
|
|
169
|
+
return get(memberMap, this).composeViewImplementation.getBccRecipients();
|
|
170
|
+
}
|
|
171
|
+
insertTextIntoBodyAtCursor(text) {
|
|
172
|
+
return get(memberMap, this).composeViewImplementation.insertBodyTextAtCursor(text);
|
|
173
|
+
}
|
|
174
|
+
insertHTMLIntoBodyAtCursor(html) {
|
|
175
|
+
return get(memberMap, this).composeViewImplementation.insertBodyHTMLAtCursor(html);
|
|
176
|
+
}
|
|
177
|
+
insertLinkChipIntoBodyAtCursor(text, url, iconUrl) {
|
|
178
|
+
if (!iconUrl ||
|
|
179
|
+
typeof iconUrl !== 'string' ||
|
|
180
|
+
iconUrl.indexOf('http') !== 0) {
|
|
181
|
+
console.warn('You must provide a publicly accessible iconUrl');
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
return get(memberMap, this).composeViewImplementation.insertLinkChipIntoBody({
|
|
185
|
+
text: text,
|
|
186
|
+
url: url,
|
|
187
|
+
iconUrl: iconUrl,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
insertLinkIntoBodyAtCursor(text, url) {
|
|
191
|
+
return get(memberMap, this).composeViewImplementation.insertLinkIntoBody(text, url);
|
|
192
|
+
}
|
|
193
|
+
isForward() {
|
|
194
|
+
return get(memberMap, this).composeViewImplementation.isForward();
|
|
195
|
+
}
|
|
196
|
+
isInlineReplyForm() {
|
|
197
|
+
return get(memberMap, this).composeViewImplementation.isInlineReplyForm();
|
|
198
|
+
}
|
|
199
|
+
isFullscreen() {
|
|
200
|
+
return get(memberMap, this).composeViewImplementation.isFullscreen();
|
|
201
|
+
}
|
|
202
|
+
setFullscreen(fullscreen) {
|
|
203
|
+
get(memberMap, this).composeViewImplementation.setFullscreen(fullscreen);
|
|
204
|
+
}
|
|
205
|
+
isMinimized() {
|
|
206
|
+
return get(memberMap, this).composeViewImplementation.isMinimized();
|
|
207
|
+
}
|
|
208
|
+
setMinimized(minimized) {
|
|
209
|
+
get(memberMap, this).composeViewImplementation.setMinimized(minimized);
|
|
210
|
+
}
|
|
211
|
+
setTitleBarColor(color) {
|
|
212
|
+
return get(memberMap, this).composeViewImplementation.setTitleBarColor(color);
|
|
213
|
+
}
|
|
214
|
+
setTitleBarText(text) {
|
|
215
|
+
return get(memberMap, this).composeViewImplementation.setTitleBarText(text);
|
|
216
|
+
}
|
|
217
|
+
async popOut() {
|
|
218
|
+
const nextComposeViewDriverPromise = get(memberMap, this).driver.getNextComposeViewDriver();
|
|
219
|
+
get(memberMap, this).composeViewImplementation.popOut();
|
|
220
|
+
const nextComposeViewDriver = await nextComposeViewDriverPromise;
|
|
221
|
+
return get(memberMap, this).membrane.get(nextComposeViewDriver);
|
|
222
|
+
}
|
|
223
|
+
isReply() {
|
|
224
|
+
return get(memberMap, this).composeViewImplementation.isReply();
|
|
225
|
+
}
|
|
226
|
+
setToRecipients(emails) {
|
|
227
|
+
get(memberMap, this).composeViewImplementation.setToRecipients(emails);
|
|
228
|
+
}
|
|
229
|
+
setCcRecipients(emails) {
|
|
230
|
+
get(memberMap, this).composeViewImplementation.setCcRecipients(emails);
|
|
231
|
+
}
|
|
232
|
+
setBccRecipients(emails) {
|
|
233
|
+
get(memberMap, this).composeViewImplementation.setBccRecipients(emails);
|
|
234
|
+
}
|
|
235
|
+
getFromContact() {
|
|
236
|
+
return get(memberMap, this).composeViewImplementation.getFromContact();
|
|
237
|
+
}
|
|
238
|
+
getFromContactChoices() {
|
|
239
|
+
return get(memberMap, this).composeViewImplementation.getFromContactChoices();
|
|
240
|
+
}
|
|
241
|
+
setFromEmail(email) {
|
|
242
|
+
get(memberMap, this).composeViewImplementation.setFromEmail(email);
|
|
243
|
+
}
|
|
244
|
+
setSubject(text) {
|
|
245
|
+
get(memberMap, this).composeViewImplementation.setSubject(text);
|
|
246
|
+
}
|
|
247
|
+
setBodyHTML(html) {
|
|
248
|
+
get(memberMap, this).composeViewImplementation.setBodyHTML(html);
|
|
249
|
+
}
|
|
250
|
+
setBodyText(text) {
|
|
251
|
+
get(memberMap, this).composeViewImplementation.setBodyText(text);
|
|
252
|
+
}
|
|
253
|
+
async attachFiles(files) {
|
|
254
|
+
if (files.length === 0) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (!(files[0] instanceof Blob)) {
|
|
258
|
+
throw new Error('parameter must be an array of Blob objects');
|
|
259
|
+
}
|
|
260
|
+
return get(memberMap, this).composeViewImplementation.attachFiles(Array.from(files));
|
|
261
|
+
}
|
|
262
|
+
async attachInlineFiles(files) {
|
|
263
|
+
if (files.length === 0) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (!(files[0] instanceof Blob)) {
|
|
267
|
+
throw new Error('parameter must be an array of Blob objects');
|
|
268
|
+
}
|
|
269
|
+
return get(memberMap, this).composeViewImplementation.attachInlineFiles(Array.from(files));
|
|
270
|
+
}
|
|
271
|
+
// Old alias that we should keep around until we're sure no one is using it.
|
|
272
|
+
dragFilesIntoCompose(files) {
|
|
273
|
+
const { driver } = get(memberMap, this);
|
|
274
|
+
driver
|
|
275
|
+
.getLogger()
|
|
276
|
+
.deprecationWarning('ComposeView.dragFilesIntoCompose', 'ComposeView.attachInlineFiles');
|
|
277
|
+
if (driver.getOpts().REQUESTED_API_VERSION !== 1) {
|
|
278
|
+
throw new Error('This method was discontinued after API version 1');
|
|
279
|
+
}
|
|
280
|
+
return this.attachInlineFiles(files);
|
|
281
|
+
}
|
|
282
|
+
//NOT DOCUMENTED BECAUSE STREAK-ONLY FOR NOW
|
|
283
|
+
getElement() {
|
|
284
|
+
return get(memberMap, this).composeViewImplementation.getElement();
|
|
285
|
+
}
|
|
286
|
+
registerRequestModifier(modifier) {
|
|
287
|
+
get(memberMap, this).composeViewImplementation.registerRequestModifier(modifier);
|
|
288
|
+
}
|
|
289
|
+
replaceSendButton({ el }) {
|
|
290
|
+
return get(memberMap, this).composeViewImplementation.replaceSendButton(el);
|
|
291
|
+
}
|
|
292
|
+
hideDiscardButton() {
|
|
293
|
+
return get(memberMap, this).composeViewImplementation.hideDiscardButton();
|
|
294
|
+
}
|
|
295
|
+
ensureFormattingToolbarIsHidden() {
|
|
296
|
+
get(memberMap, this).composeViewImplementation.ensureFormattingToolbarIsHidden();
|
|
297
|
+
}
|
|
298
|
+
ensureAppButtonToolbarsAreClosed() {
|
|
299
|
+
get(memberMap, this).composeViewImplementation.ensureAppButtonToolbarsAreClosed();
|
|
300
|
+
}
|
|
301
|
+
// TODO remove
|
|
302
|
+
overrideEditSubject() {
|
|
303
|
+
const { driver, composeViewImplementation } = get(memberMap, this);
|
|
304
|
+
driver.getLogger().deprecationWarning('composeView.overrideEditSubject');
|
|
305
|
+
if (driver.getOpts().REQUESTED_API_VERSION !== 1) {
|
|
306
|
+
throw new Error('This method was discontinued after API version 1');
|
|
307
|
+
}
|
|
308
|
+
if (typeof composeViewImplementation.overrideEditSubject === 'function') {
|
|
309
|
+
composeViewImplementation.overrideEditSubject();
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import EventEmitter from '../lib/safe-event-emitter';
|
|
2
|
+
// documented in src/docs/
|
|
3
|
+
export default class KeyboardShortcutHandle extends EventEmitter {
|
|
4
|
+
chord;
|
|
5
|
+
description;
|
|
6
|
+
constructor(chord, description) {
|
|
7
|
+
super();
|
|
8
|
+
this.chord = chord;
|
|
9
|
+
this.description = description;
|
|
10
|
+
}
|
|
11
|
+
remove() {
|
|
12
|
+
this.emit('destroy');
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import kefirStopper from 'kefir-stopper';
|
|
2
|
+
export default class BasicButtonViewController {
|
|
3
|
+
_activateFunction;
|
|
4
|
+
_view;
|
|
5
|
+
_stopper = kefirStopper();
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this._activateFunction = options.activateFunction || options.onClick;
|
|
8
|
+
this._view = options.buttonView;
|
|
9
|
+
this._view
|
|
10
|
+
.getEventStream()
|
|
11
|
+
.filter((event) => event.eventName === 'click')
|
|
12
|
+
.onValue(() => {
|
|
13
|
+
this.activate();
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
getStopper() {
|
|
17
|
+
return this._stopper;
|
|
18
|
+
}
|
|
19
|
+
destroy() {
|
|
20
|
+
this._activateFunction = null;
|
|
21
|
+
this._view.destroy();
|
|
22
|
+
this._stopper.destroy();
|
|
23
|
+
}
|
|
24
|
+
update(options) {
|
|
25
|
+
this.getView().update(options);
|
|
26
|
+
this.setActivateFunction(options && (options.activateFunction || options.onClick));
|
|
27
|
+
}
|
|
28
|
+
getView() {
|
|
29
|
+
return this._view;
|
|
30
|
+
}
|
|
31
|
+
setActivateFunction(f) {
|
|
32
|
+
this._activateFunction = f;
|
|
33
|
+
}
|
|
34
|
+
activate() {
|
|
35
|
+
if (this._activateFunction) {
|
|
36
|
+
this._activateFunction({});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|