@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.
Files changed (138) hide show
  1. package/inboxsdk.js +1 -1
  2. package/inboxsdk.js.map +1 -1
  3. package/package.json +1 -1
  4. package/src/build/exec.js +26 -0
  5. package/src/build/spawn.js +17 -0
  6. package/src/common/ajax.js +90 -0
  7. package/src/common/cachebust-url.js +10 -0
  8. package/src/common/censorHTMLstring.js +37 -0
  9. package/src/common/censorHTMLtree.js +28 -0
  10. package/src/common/censorJSONTree.js +15 -0
  11. package/src/common/connectivity-test.js +21 -0
  12. package/src/common/defer.js +11 -0
  13. package/src/common/find-parent.js +10 -0
  14. package/src/common/get-extension-id.js +7 -0
  15. package/src/common/get-or-fail.js +8 -0
  16. package/src/common/get-session-id.js +14 -0
  17. package/src/common/get-stack-trace.js +6 -0
  18. package/src/common/html-to-text.js +7 -0
  19. package/src/common/isElementVisible.js +6 -0
  20. package/src/common/load-script.js +127 -0
  21. package/src/common/log-error.js +191 -0
  22. package/src/common/quoted-split.js +18 -0
  23. package/src/common/rate-limit-queuer.js +57 -0
  24. package/src/common/rate-limit.js +14 -0
  25. package/src/common/version.js +6 -0
  26. package/src/inboxsdk-js/loading/platform-implementation-loader.js +27 -0
  27. package/src/inboxsdk.d.ts +2 -0
  28. package/src/injected-js/gmail/constants.js +2 -0
  29. package/src/injected-js/gmail/modify-suggestions.js +106 -0
  30. package/src/injected-js/gmail/setup-gmonkey-handler.js +49 -0
  31. package/src/injected-js/gmail/sync-compose-processor-20220909.js +298 -0
  32. package/src/injected-js/gmail/sync-compose-processor.js +55 -0
  33. package/src/injected-js/gmail/sync-compose-request-processor.js +110 -0
  34. package/src/injected-js/injected-logger.js +50 -0
  35. package/src/injected-js/setupCustomViewEventAssassin.js +90 -0
  36. package/src/platform-implementation-js/constants/nav-item-types.js +19 -0
  37. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-app-menu-item.js +21 -0
  38. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-collapsible-panel.js +28 -0
  39. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-nav-item.js +98 -0
  40. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-support-item.js +4 -0
  41. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/encodeDraftUrlId.js +8 -0
  42. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/get-rfc-message-id-for-gmail-message-id.js +12 -0
  43. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/get-rfc-message-id-for-gmail-thread-id.js +33 -0
  44. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/isIntegratedViewGmail.js +4 -0
  45. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/open-draft-by-message-id.js +44 -0
  46. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-gmail-styles.js +95 -0
  47. package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter/get-main-content-element-changed-stream.js +38 -0
  48. package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter/wait-for-gmail-mode-to-settle.js +12 -0
  49. package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter.js +253 -0
  50. package/src/platform-implementation-js/dom-driver/gmail/gmail-page-communicator.js +200 -0
  51. package/src/platform-implementation-js/dom-driver/gmail/gmail-response-processor.js +533 -0
  52. package/src/platform-implementation-js/dom-driver/gmail/gmail-sync-response-processor.js +289 -0
  53. package/src/platform-implementation-js/dom-driver/gmail/is-compose-titlebar-light-color.js +21 -0
  54. package/src/platform-implementation-js/dom-driver/gmail/makePageParserTree.js +28 -0
  55. package/src/platform-implementation-js/dom-driver/gmail/pageParserOptions.js +19 -0
  56. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-menu-item-view.js +126 -0
  57. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-status-bar.js +101 -0
  58. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/detectClassicRecipientsArea.js +38 -0
  59. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-address-information-extractor.js +28 -0
  60. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-recipients.js +22 -0
  61. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/gmail-compose-button-view.js +233 -0
  62. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/page-parser.js +223 -0
  63. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/set-recipients.js +157 -0
  64. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/setupLinkPopovers.js +109 -0
  65. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view/attachment-icon.js +5 -0
  66. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-nav-item-view.js +759 -0
  67. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-support-item-view.js +84 -0
  68. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/button-color-classes.js +33 -0
  69. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/button-view.js +325 -0
  70. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-accessory-button-view.js +58 -0
  71. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-parent-accessory-button-view.js +55 -0
  72. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/modal-button-view.js +96 -0
  73. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/more-dropdown-button-view.js +30 -0
  74. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/more-parent-accessory-button-view.js +10 -0
  75. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-dropdown-view.js +22 -0
  76. package/src/platform-implementation-js/driver-common/getAccountUrlPart.js +17 -0
  77. package/src/platform-implementation-js/driver-common/getOriginalMessagePage.js +33 -0
  78. package/src/platform-implementation-js/driver-common/getSyncThreadsForSearch.js +49 -0
  79. package/src/platform-implementation-js/driver-common/gmailAjax.js +65 -0
  80. package/src/platform-implementation-js/driver-common/render-custom-icon.js +16 -0
  81. package/src/platform-implementation-js/driver-common/update-icon.js +90 -0
  82. package/src/platform-implementation-js/lib/ErrorCollector.js +47 -0
  83. package/src/platform-implementation-js/lib/Membrane.js +22 -0
  84. package/src/platform-implementation-js/lib/ScrollableContainByScreen.js +30 -0
  85. package/src/platform-implementation-js/lib/attemptWithRetries.js +16 -0
  86. package/src/platform-implementation-js/lib/common-page-communicator.js +137 -0
  87. package/src/platform-implementation-js/lib/delay-asap.js +12 -0
  88. package/src/platform-implementation-js/lib/delay-idle.js +16 -0
  89. package/src/platform-implementation-js/lib/dom/block-and-reemit-keyboard-events.js +36 -0
  90. package/src/platform-implementation-js/lib/dom/generic-button-view.js +39 -0
  91. package/src/platform-implementation-js/lib/dom/get-insert-before-element.js +39 -0
  92. package/src/platform-implementation-js/lib/dom/insert-element-in-order.js +38 -0
  93. package/src/platform-implementation-js/lib/dom/keyboard-shortcut-stream.js +12 -0
  94. package/src/platform-implementation-js/lib/dom/make-element-child-stream.js +79 -0
  95. package/src/platform-implementation-js/lib/dom/make-element-stream-merger.js +28 -0
  96. package/src/platform-implementation-js/lib/dom/make-element-view-stream.js +15 -0
  97. package/src/platform-implementation-js/lib/dom/make-mutation-observer-chunked-stream.js +15 -0
  98. package/src/platform-implementation-js/lib/dom/make-mutation-observer-stream.js +5 -0
  99. package/src/platform-implementation-js/lib/dom/outsideClicksAndEscape.js +39 -0
  100. package/src/platform-implementation-js/lib/dom/parentNodes.js +8 -0
  101. package/src/platform-implementation-js/lib/dom/querySelectorOrFail.js +6 -0
  102. package/src/platform-implementation-js/lib/dom/reemitClickEventForReact.js +22 -0
  103. package/src/platform-implementation-js/lib/dom/simulate-key.js +46 -0
  104. package/src/platform-implementation-js/lib/dom/simulate-mouse-event.js +16 -0
  105. package/src/platform-implementation-js/lib/dom/trigger-relay-event.js +7 -0
  106. package/src/platform-implementation-js/lib/extract-contact-from-email-contact-string.js +25 -0
  107. package/src/platform-implementation-js/lib/fake-window-resize.js +5 -0
  108. package/src/platform-implementation-js/lib/from-event-target-capture.js +12 -0
  109. package/src/platform-implementation-js/lib/fromEventsWithOptions.js +10 -0
  110. package/src/platform-implementation-js/lib/handler-registry.js +67 -0
  111. package/src/platform-implementation-js/lib/idMap.js +45 -0
  112. package/src/platform-implementation-js/lib/imageRequest.js +8 -0
  113. package/src/platform-implementation-js/lib/incrementName.js +7 -0
  114. package/src/platform-implementation-js/lib/inject-script-EMBEDDED.js +14 -0
  115. package/src/platform-implementation-js/lib/inject-script.js +33 -0
  116. package/src/platform-implementation-js/lib/is-valid-app-id.js +27 -0
  117. package/src/platform-implementation-js/lib/is-valid-email.js +14 -0
  118. package/src/platform-implementation-js/lib/isNotNil.js +5 -0
  119. package/src/platform-implementation-js/lib/isStreakAppId.js +11 -0
  120. package/src/platform-implementation-js/lib/logger.js +441 -0
  121. package/src/platform-implementation-js/lib/persistent-queue.js +107 -0
  122. package/src/platform-implementation-js/lib/safe-event-emitter.js +17 -0
  123. package/src/platform-implementation-js/lib/stopper-pool.js +41 -0
  124. package/src/platform-implementation-js/lib/stream-wait-for.js +30 -0
  125. package/src/platform-implementation-js/lib/wait-for.js +28 -0
  126. package/src/platform-implementation-js/lib/waitForAsync.js +19 -0
  127. package/src/platform-implementation-js/namespaces/app-menu.d.ts.map +1 -1
  128. package/src/platform-implementation-js/namespaces/app-menu.js +31 -0
  129. package/src/platform-implementation-js/namespaces/butter-bar.js +163 -0
  130. package/src/platform-implementation-js/views/SimpleElementView.js +16 -0
  131. package/src/platform-implementation-js/views/app-menu-item-view.js +257 -0
  132. package/src/platform-implementation-js/views/collapsible-panel-view.js +222 -0
  133. package/src/platform-implementation-js/views/compose-button-view.js +45 -0
  134. package/src/platform-implementation-js/views/compose-view.js +312 -0
  135. package/src/platform-implementation-js/views/keyboard-shortcut-handle.js +14 -0
  136. package/src/platform-implementation-js/widgets/buttons/basic-button-view-controller.js +39 -0
  137. package/src/platform-implementation-js/widgets/buttons/dropdown-button-view-controller.js +98 -0
  138. 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
+ }