@inboxsdk/core 0.2.27 → 0.2.28-alpha.1

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 (552) hide show
  1. package/inboxsdk.d.ts +1 -805
  2. package/inboxsdk.js +299 -57
  3. package/inboxsdk.js.map +1 -1
  4. package/package.json +6 -4
  5. package/pageWorld.js +46 -12
  6. package/pageWorld.js.map +1 -1
  7. package/src/build/exec.d.ts +2 -0
  8. package/src/build/exec.d.ts.map +1 -0
  9. package/src/build/spawn.d.ts +2 -0
  10. package/src/build/spawn.d.ts.map +1 -0
  11. package/src/common/ajax.d.ts +23 -0
  12. package/src/common/ajax.d.ts.map +1 -0
  13. package/src/common/cachebust-url.d.ts +2 -0
  14. package/src/common/cachebust-url.d.ts.map +1 -0
  15. package/src/common/censorHTMLstring.d.ts +3 -0
  16. package/src/common/censorHTMLstring.d.ts.map +1 -0
  17. package/src/common/censorHTMLtree.d.ts +2 -0
  18. package/src/common/censorHTMLtree.d.ts.map +1 -0
  19. package/src/common/censorJSONTree.d.ts +2 -0
  20. package/src/common/censorJSONTree.d.ts.map +1 -0
  21. package/src/common/connectivity-test.d.ts +4 -0
  22. package/src/common/connectivity-test.d.ts.map +1 -0
  23. package/src/common/defer.d.ts +7 -0
  24. package/src/common/defer.d.ts.map +1 -0
  25. package/src/common/find-parent.d.ts +2 -0
  26. package/src/common/find-parent.d.ts.map +1 -0
  27. package/src/common/get-extension-id.d.ts +2 -0
  28. package/src/common/get-extension-id.d.ts.map +1 -0
  29. package/src/common/get-or-fail.d.ts +7 -0
  30. package/src/common/get-or-fail.d.ts.map +1 -0
  31. package/src/common/get-session-id.d.ts +2 -0
  32. package/src/common/get-session-id.d.ts.map +1 -0
  33. package/src/common/get-stack-trace.d.ts +2 -0
  34. package/src/common/get-stack-trace.d.ts.map +1 -0
  35. package/src/common/html-to-text.d.ts +2 -0
  36. package/src/common/html-to-text.d.ts.map +1 -0
  37. package/src/common/isElementVisible.d.ts +2 -0
  38. package/src/common/isElementVisible.d.ts.map +1 -0
  39. package/src/common/load-script.d.ts +7 -0
  40. package/src/common/load-script.d.ts.map +1 -0
  41. package/src/common/log-error.d.ts +11 -0
  42. package/src/common/log-error.d.ts.map +1 -0
  43. package/src/common/quoted-split.d.ts +2 -0
  44. package/src/common/quoted-split.d.ts.map +1 -0
  45. package/src/common/rate-limit-queuer.d.ts +2 -0
  46. package/src/common/rate-limit-queuer.d.ts.map +1 -0
  47. package/src/common/rate-limit.d.ts +2 -0
  48. package/src/common/rate-limit.d.ts.map +1 -0
  49. package/src/common/version.d.ts +2 -0
  50. package/src/common/version.d.ts.map +1 -0
  51. package/src/inboxsdk-js/check-requirements.js +7 -0
  52. package/src/inboxsdk-js/header.js +18 -0
  53. package/src/inboxsdk-js/inboxsdk-NONREMOTE-INTEGRATED-PAGEWORLD.js +10 -0
  54. package/src/inboxsdk-js/inboxsdk-NONREMOTE.js +5 -0
  55. package/src/inboxsdk-js/inboxsdk-REMOTE.js +3 -0
  56. package/src/inboxsdk-js/inboxsdk-TEST.js +5 -0
  57. package/src/inboxsdk-js/inboxsdk.js +41 -0
  58. package/src/inboxsdk-js/loading/load-platform-implementation-DEV.js +19 -0
  59. package/src/inboxsdk-js/loading/platform-implementation-loader.d.ts +8 -0
  60. package/src/inboxsdk-js/loading/platform-implementation-loader.d.ts.map +1 -0
  61. package/src/inboxsdk.d.ts +786 -0
  62. package/src/injected-js/gmail/constants.d.ts +14 -0
  63. package/src/injected-js/gmail/constants.d.ts.map +1 -0
  64. package/src/injected-js/gmail/modify-suggestions.d.ts +24 -0
  65. package/src/injected-js/gmail/modify-suggestions.d.ts.map +1 -0
  66. package/src/injected-js/gmail/modify-suggestions.test.js +21 -0
  67. package/src/injected-js/gmail/setup-gmail-interceptor.d.ts +4 -0
  68. package/src/injected-js/gmail/setup-gmail-interceptor.js +1185 -0
  69. package/src/injected-js/gmail/setup-gmonkey-handler.d.ts +5 -0
  70. package/src/injected-js/gmail/setup-gmonkey-handler.d.ts.map +1 -0
  71. package/src/injected-js/gmail/sync-compose-processor-20220909.d.ts +28 -0
  72. package/src/injected-js/gmail/sync-compose-processor-20220909.d.ts.map +1 -0
  73. package/src/injected-js/gmail/sync-compose-processor.d.ts +16 -0
  74. package/src/injected-js/gmail/sync-compose-processor.d.ts.map +1 -0
  75. package/src/injected-js/gmail/sync-compose-request-processor.d.ts +4 -0
  76. package/src/injected-js/gmail/sync-compose-request-processor.d.ts.map +1 -0
  77. package/src/injected-js/gmail/sync-compose-request-processor.test.js +90 -0
  78. package/src/injected-js/gmail/thread-identifier/click-and-get-popup-url.js +96 -0
  79. package/src/injected-js/gmail/thread-identifier/index.js +157 -0
  80. package/src/injected-js/gmail/thread-identifier/thread-row-parser.js +72 -0
  81. package/src/injected-js/gmail/thread-identifier/thread-row-parser.test.js +57 -0
  82. package/src/injected-js/inbox/setupAjaxInterceptor.js +268 -0
  83. package/src/injected-js/inbox/setupClickAndGetNewIframeSrc.js +80 -0
  84. package/src/injected-js/inbox/setupComposeViewDraftIDFinder.js +51 -0
  85. package/src/injected-js/inbox/setupInboxFakeWindowResizeListener.js +29 -0
  86. package/src/injected-js/injected-logger.d.ts +3 -0
  87. package/src/injected-js/injected-logger.d.ts.map +1 -0
  88. package/src/injected-js/main.js +70 -0
  89. package/src/injected-js/message-metadata-holder.js +141 -0
  90. package/src/injected-js/setup-data-exposer.js +187 -0
  91. package/src/injected-js/setup-error-silencer.js +25 -0
  92. package/src/injected-js/setup-event-reemitter.js +52 -0
  93. package/src/injected-js/setupCustomViewEventAssassin.d.ts +2 -0
  94. package/src/injected-js/setupCustomViewEventAssassin.d.ts.map +1 -0
  95. package/src/injected-js/setupInboxCustomViewLinkFixer.js +31 -0
  96. package/src/injected-js/setupPushStateListener.js +16 -0
  97. package/src/injected-js/xhr-helper.js +86 -0
  98. package/src/injected-js/xhr-proxy-factory.js +739 -0
  99. package/src/injected-js/xhr-proxy-factory.test.js +1219 -0
  100. package/src/platform-implementation-js/constants/nav-item-types.d.ts +17 -0
  101. package/src/platform-implementation-js/constants/nav-item-types.d.ts.map +1 -0
  102. package/src/platform-implementation-js/constants/router.js +53 -0
  103. package/src/platform-implementation-js/constants/toolbars.js +7 -0
  104. package/src/platform-implementation-js/dom-driver/gmail/custom-style.js +22 -0
  105. package/src/platform-implementation-js/dom-driver/gmail/gmail-butter-bar-driver.js +214 -0
  106. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-app-menu-item.d.ts +5 -0
  107. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-app-menu-item.d.ts.map +1 -0
  108. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-collapsible-panel.d.ts +5 -0
  109. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-collapsible-panel.d.ts.map +1 -0
  110. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-nav-item.d.ts +6 -0
  111. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-nav-item.d.ts.map +1 -0
  112. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-support-item.d.ts +4 -0
  113. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-support-item.d.ts.map +1 -0
  114. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-toolbar-button-for-app.js +21 -0
  115. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/create-link.js +78 -0
  116. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/encodeDraftUrlId.d.ts +2 -0
  117. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/encodeDraftUrlId.d.ts.map +1 -0
  118. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/get-draft-id-for-message-id.js +70 -0
  119. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/get-native-nav-item.js +43 -0
  120. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/get-rfc-message-id-for-gmail-message-id.d.ts +3 -0
  121. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/get-rfc-message-id-for-gmail-message-id.d.ts.map +1 -0
  122. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/get-rfc-message-id-for-gmail-thread-id.d.ts +3 -0
  123. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/get-rfc-message-id-for-gmail-thread-id.d.ts.map +1 -0
  124. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/get-url-object.js +33 -0
  125. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/getSyncThreadForOldGmailThreadId.js +38 -0
  126. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/getSyncThreadFromSyncThreadId.js +76 -0
  127. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/gmail-load-event.js +61 -0
  128. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/goto-view.js +72 -0
  129. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/isIntegratedViewGmail.d.ts +2 -0
  130. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/isIntegratedViewGmail.d.ts.map +1 -0
  131. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/keyboard-shortcut-help-modifier.js +226 -0
  132. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/open-compose-window.js +27 -0
  133. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/open-draft-by-message-id.d.ts +5 -0
  134. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/open-draft-by-message-id.d.ts.map +1 -0
  135. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/open-draft-by-message-id.test.js +23 -0
  136. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/override-gmail-back-button.js +92 -0
  137. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/register-search-query-rewriter.js +30 -0
  138. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/register-search-suggestions-provider.js +207 -0
  139. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/setup-compose-view-driver-stream.js +162 -0
  140. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/setup-route-view-driver-stream.js +194 -0
  141. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/setup-route-view-driver-stream.test.js +233 -0
  142. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/show-app-id-warning.js +30 -0
  143. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/show-custom-route-view.js +79 -0
  144. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/show-custom-thread-list.js +516 -0
  145. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/show-custom-thread-list.test.js +404 -0
  146. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/show-native-route-view.js +33 -0
  147. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/suppressAddon.js +50 -0
  148. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/temporary-track-download-url-validity.js +45 -0
  149. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/thread-row-identifier.js +123 -0
  150. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-events.js +171 -0
  151. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-gmail-styles.d.ts +2 -0
  152. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-gmail-styles.d.ts.map +1 -0
  153. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/user-info.js +69 -0
  154. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/user-info.test.js +79 -0
  155. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver.d.ts +108 -0
  156. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver.js +1001 -0
  157. package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter/get-main-content-element-changed-stream.d.ts +4 -0
  158. package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter/get-main-content-element-changed-stream.d.ts.map +1 -0
  159. package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter/wait-for-gmail-mode-to-settle.d.ts +3 -0
  160. package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter/wait-for-gmail-mode-to-settle.d.ts.map +1 -0
  161. package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter.d.ts +46 -0
  162. package/src/platform-implementation-js/dom-driver/gmail/gmail-element-getter.d.ts.map +1 -0
  163. package/src/platform-implementation-js/dom-driver/gmail/gmail-page-communicator.d.ts +33 -0
  164. package/src/platform-implementation-js/dom-driver/gmail/gmail-page-communicator.d.ts.map +1 -0
  165. package/src/platform-implementation-js/dom-driver/gmail/gmail-response-processor.d.ts +56 -0
  166. package/src/platform-implementation-js/dom-driver/gmail/gmail-response-processor.d.ts.map +1 -0
  167. package/src/platform-implementation-js/dom-driver/gmail/gmail-sync-response-processor.d.ts +43 -0
  168. package/src/platform-implementation-js/dom-driver/gmail/gmail-sync-response-processor.d.ts.map +1 -0
  169. package/src/platform-implementation-js/dom-driver/gmail/is-compose-titlebar-light-color.d.ts +3 -0
  170. package/src/platform-implementation-js/dom-driver/gmail/is-compose-titlebar-light-color.d.ts.map +1 -0
  171. package/src/platform-implementation-js/dom-driver/gmail/make-xhr-interceptor.js +98 -0
  172. package/src/platform-implementation-js/dom-driver/gmail/makePageParserTree.d.ts +4 -0
  173. package/src/platform-implementation-js/dom-driver/gmail/makePageParserTree.d.ts.map +1 -0
  174. package/src/platform-implementation-js/dom-driver/gmail/pageParserOptions.d.ts +4 -0
  175. package/src/platform-implementation-js/dom-driver/gmail/pageParserOptions.d.ts.map +1 -0
  176. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-menu-item-view.d.ts +43 -0
  177. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-menu-item-view.d.ts.map +1 -0
  178. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/index.js +133 -0
  179. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/index.test.js +162 -0
  180. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/add-companion-global-icon-area.js +39 -0
  181. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/add-companion-thread-icon-area.js +47 -0
  182. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/add-to-icon-area.js +33 -0
  183. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/index.js +1048 -0
  184. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-toolbar-button-view/monitor-top-banner-size-and-react.js +27 -0
  185. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-toolbar-button-view.js +215 -0
  186. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-attachment-area-view.js +141 -0
  187. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-attachment-card-view.js +422 -0
  188. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-attachment-card-view.test.js +141 -0
  189. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-backdrop.js +34 -0
  190. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-collapsible-section-view.js +909 -0
  191. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-button.js +197 -0
  192. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-compose-notice.js +76 -0
  193. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-inner-sidebar.js +34 -0
  194. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-outer-sidebar.js +46 -0
  195. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-recipient-row.js +97 -0
  196. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-status-bar.d.ts +23 -0
  197. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-status-bar.d.ts.map +1 -0
  198. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-tooltip-to-button.js +125 -0
  199. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/detectClassicRecipientsArea.d.ts +3 -0
  200. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/detectClassicRecipientsArea.d.ts.map +1 -0
  201. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/ensure-app-button-toolbars-are-closed.js +22 -0
  202. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/ensure-grouping-is-open.js +29 -0
  203. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/focus.js +19 -0
  204. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/from-manager.js +82 -0
  205. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-additional-action-toolbar.js +67 -0
  206. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-address-changes-stream.js +151 -0
  207. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-address-information-extractor.d.ts +4 -0
  208. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-address-information-extractor.d.ts.map +1 -0
  209. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-body-changes-stream.js +20 -0
  210. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-formatting-area-offset-left.js +31 -0
  211. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-minimized-stream.js +30 -0
  212. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-recipients.d.ts +5 -0
  213. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-recipients.d.ts.map +1 -0
  214. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-response-type-changes-stream.js +33 -0
  215. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/gmail-compose-button-view.d.ts +50 -0
  216. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/gmail-compose-button-view.d.ts.map +1 -0
  217. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/insert-link-into-body.js +35 -0
  218. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/manage-button-grouping.js +533 -0
  219. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/monitor-selection-range.js +29 -0
  220. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/override-edit-subject.js +92 -0
  221. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/page-parser.d.ts +8 -0
  222. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/page-parser.d.ts.map +1 -0
  223. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/position-formatting-toolbar.js +28 -0
  224. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/set-recipients.d.ts +4 -0
  225. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/set-recipients.d.ts.map +1 -0
  226. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/setupLinkPopovers.d.ts +4 -0
  227. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/setupLinkPopovers.d.ts.map +1 -0
  228. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/size-fixer.js +177 -0
  229. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/update-insert-more-area-left.js +28 -0
  230. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view.d.ts +119 -0
  231. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view.js +1938 -0
  232. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view/attachment-icon.d.ts +6 -0
  233. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view/attachment-icon.d.ts.map +1 -0
  234. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view/get-updated-contact.js +85 -0
  235. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view.js +950 -0
  236. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-nav-item-view.d.ts +107 -0
  237. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-nav-item-view.d.ts.map +1 -0
  238. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-route-view/gmail-route-processor.js +125 -0
  239. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-route-view/gmail-route-view.js +601 -0
  240. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-row-list-view.js +309 -0
  241. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-support-item-view.d.ts +16 -0
  242. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-support-item-view.d.ts.map +1 -0
  243. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-row-view.js +1287 -0
  244. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-sidebar-view/add-icon-area.js +127 -0
  245. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-sidebar-view.js +744 -0
  246. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-sidebar-view.test.js +349 -0
  247. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-view/width-manager.js +49 -0
  248. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-view.js +893 -0
  249. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-toolbar-view.js +591 -0
  250. package/src/platform-implementation-js/dom-driver/gmail/views/native-gmail-nav-item-view.js +360 -0
  251. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/button-color-classes.d.ts +10 -0
  252. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/button-color-classes.d.ts.map +1 -0
  253. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/button-view.d.ts +61 -0
  254. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/button-view.d.ts.map +1 -0
  255. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-accessory-button-view.d.ts +18 -0
  256. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-accessory-button-view.d.ts.map +1 -0
  257. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-parent-accessory-button-view.d.ts +18 -0
  258. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-parent-accessory-button-view.d.ts.map +1 -0
  259. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/inbox-dropdown-button-view.js +32 -0
  260. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/modal-button-view.d.ts +29 -0
  261. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/modal-button-view.d.ts.map +1 -0
  262. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/more-dropdown-button-view.d.ts +8 -0
  263. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/more-dropdown-button-view.d.ts.map +1 -0
  264. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/more-parent-accessory-button-view.d.ts +5 -0
  265. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/more-parent-accessory-button-view.d.ts.map +1 -0
  266. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-action-button-view.js +57 -0
  267. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-dropdown-view.d.ts +9 -0
  268. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-dropdown-view.d.ts.map +1 -0
  269. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-label-view.js +148 -0
  270. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-modal-view-driver.js +179 -0
  271. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-mole-view-driver.js +246 -0
  272. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-tooltip-view.js +504 -0
  273. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-top-message-bar-driver.js +109 -0
  274. package/src/platform-implementation-js/dom-driver/inbox/__mocks__/getSidebarClassnames.js +9 -0
  275. package/src/platform-implementation-js/dom-driver/inbox/addNavItem.js +56 -0
  276. package/src/platform-implementation-js/dom-driver/inbox/addRecipientRow.js +73 -0
  277. package/src/platform-implementation-js/dom-driver/inbox/createLink.js +21 -0
  278. package/src/platform-implementation-js/dom-driver/inbox/createLink.test.js +30 -0
  279. package/src/platform-implementation-js/dom-driver/inbox/custom-style.js +22 -0
  280. package/src/platform-implementation-js/dom-driver/inbox/detection/appToolbarLocation/parser.js +49 -0
  281. package/src/platform-implementation-js/dom-driver/inbox/detection/attachmentCard/parser.js +33 -0
  282. package/src/platform-implementation-js/dom-driver/inbox/detection/attachmentOverlay/parser.js +85 -0
  283. package/src/platform-implementation-js/dom-driver/inbox/detection/chatSidebar/parser.js +33 -0
  284. package/src/platform-implementation-js/dom-driver/inbox/detection/compose/parser.js +220 -0
  285. package/src/platform-implementation-js/dom-driver/inbox/detection/message/parser.js +97 -0
  286. package/src/platform-implementation-js/dom-driver/inbox/detection/nativeDrawer/parser.js +30 -0
  287. package/src/platform-implementation-js/dom-driver/inbox/detection/searchBar/parser.js +28 -0
  288. package/src/platform-implementation-js/dom-driver/inbox/detection/thread/parser.js +60 -0
  289. package/src/platform-implementation-js/dom-driver/inbox/detection/thread-row/parser.js +152 -0
  290. package/src/platform-implementation-js/dom-driver/inbox/getComposeViewDriverLiveSet.js +121 -0
  291. package/src/platform-implementation-js/dom-driver/inbox/getInboxMessageIdForInboxThreadId.js +42 -0
  292. package/src/platform-implementation-js/dom-driver/inbox/getSidebarClassnames.js +171 -0
  293. package/src/platform-implementation-js/dom-driver/inbox/getSidebarClassnames.test.js +74 -0
  294. package/src/platform-implementation-js/dom-driver/inbox/gotoView.js +43 -0
  295. package/src/platform-implementation-js/dom-driver/inbox/gotoView.test.js +29 -0
  296. package/src/platform-implementation-js/dom-driver/inbox/inbox-butter-bar-driver.js +156 -0
  297. package/src/platform-implementation-js/dom-driver/inbox/inbox-driver.js +1164 -0
  298. package/src/platform-implementation-js/dom-driver/inbox/inbox-page-communicator.js +75 -0
  299. package/src/platform-implementation-js/dom-driver/inbox/inboxResponseProcessor.js +15 -0
  300. package/src/platform-implementation-js/dom-driver/inbox/inboxResponseProcessor.test.js +25 -0
  301. package/src/platform-implementation-js/dom-driver/inbox/makePageParserTree.js +42 -0
  302. package/src/platform-implementation-js/dom-driver/inbox/pageParserOptions.js +452 -0
  303. package/src/platform-implementation-js/dom-driver/inbox/registerSearchSuggestionsProvider.js +317 -0
  304. package/src/platform-implementation-js/dom-driver/inbox/setupCustomAutocompleteSelectionHandling.js +251 -0
  305. package/src/platform-implementation-js/dom-driver/inbox/setupRouteViewDriverStream.js +76 -0
  306. package/src/platform-implementation-js/dom-driver/inbox/setupRouteViewDriverStream.test.js +94 -0
  307. package/src/platform-implementation-js/dom-driver/inbox/views/InboxLabelView.js +103 -0
  308. package/src/platform-implementation-js/dom-driver/inbox/views/InboxMoleViewDriver.js +400 -0
  309. package/src/platform-implementation-js/dom-driver/inbox/views/InboxToolbarButtonView.js +105 -0
  310. package/src/platform-implementation-js/dom-driver/inbox/views/InboxToolbarView.js +72 -0
  311. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-app-sidebar-view.js +362 -0
  312. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-app-toolbar-button-view.js +236 -0
  313. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-app-toolbar-tooltip-view.js +75 -0
  314. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-attachment-card-view.js +252 -0
  315. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-attachment-overlay-view.js +108 -0
  316. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-backdrop.js +74 -0
  317. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-chat-sidebar-view.js +55 -0
  318. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-compose-button-view.js +144 -0
  319. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-compose-view.js +1027 -0
  320. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-custom-route-view.js +97 -0
  321. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-custom-route-view.test.js +43 -0
  322. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-drawer-view.js +386 -0
  323. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-dropdown-view.js +26 -0
  324. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-dummy-route-view.js +82 -0
  325. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-message-view.js +348 -0
  326. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-modal-view.js +153 -0
  327. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-route-view.js +123 -0
  328. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-thread-row-view.js +413 -0
  329. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-thread-view.js +308 -0
  330. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-thread-view.test.js +193 -0
  331. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-tooltip-view.js +143 -0
  332. package/src/platform-implementation-js/dom-driver/inbox/views/inboxNavItemView.js +452 -0
  333. package/src/platform-implementation-js/dom-driver/inbox/waitForAnimationClickBlockerGone.js +40 -0
  334. package/src/platform-implementation-js/driver-common/compose/getDiscardStream.js +52 -0
  335. package/src/platform-implementation-js/driver-common/compose/getPresendingStream.js +73 -0
  336. package/src/platform-implementation-js/driver-common/getAccountUrlPart.d.ts +2 -0
  337. package/src/platform-implementation-js/driver-common/getAccountUrlPart.d.ts.map +1 -0
  338. package/src/platform-implementation-js/driver-common/getGmailMessageIdForSyncMessageId.js +30 -0
  339. package/src/platform-implementation-js/driver-common/getGmailThreadIdForRfcMessageId.js +61 -0
  340. package/src/platform-implementation-js/driver-common/getOriginalMessagePage.d.ts +12 -0
  341. package/src/platform-implementation-js/driver-common/getOriginalMessagePage.d.ts.map +1 -0
  342. package/src/platform-implementation-js/driver-common/getRfcMessageIdForSyncMessageId.js +32 -0
  343. package/src/platform-implementation-js/driver-common/getSyncThreadsForSearch.d.ts +9 -0
  344. package/src/platform-implementation-js/driver-common/getSyncThreadsForSearch.d.ts.map +1 -0
  345. package/src/platform-implementation-js/driver-common/getThreadIdFromMessageId.js +21 -0
  346. package/src/platform-implementation-js/driver-common/gmailAjax.d.ts +5 -0
  347. package/src/platform-implementation-js/driver-common/gmailAjax.d.ts.map +1 -0
  348. package/src/platform-implementation-js/driver-common/inboxAjax.js +8 -0
  349. package/src/platform-implementation-js/driver-common/render-custom-icon.d.ts +2 -0
  350. package/src/platform-implementation-js/driver-common/render-custom-icon.d.ts.map +1 -0
  351. package/src/platform-implementation-js/driver-common/requestGmailThread.js +35 -0
  352. package/src/platform-implementation-js/driver-common/sidebar/AppSidebar.js +408 -0
  353. package/src/platform-implementation-js/driver-common/sidebar/ContentPanelViewDriver.js +197 -0
  354. package/src/platform-implementation-js/driver-common/update-icon.d.ts +8 -0
  355. package/src/platform-implementation-js/driver-common/update-icon.d.ts.map +1 -0
  356. package/src/platform-implementation-js/driver-interfaces/compose-view-driver.d.ts +133 -0
  357. package/src/platform-implementation-js/driver-interfaces/compose-view-driver.js +114 -0
  358. package/src/platform-implementation-js/driver-interfaces/driver.d.ts +142 -0
  359. package/src/platform-implementation-js/driver-interfaces/driver.js +131 -0
  360. package/src/platform-implementation-js/driver-interfaces/message-view-driver.js +49 -0
  361. package/src/platform-implementation-js/driver-interfaces/mole-view-driver.js +29 -0
  362. package/src/platform-implementation-js/driver-interfaces/route-view-driver.js +32 -0
  363. package/src/platform-implementation-js/driver-interfaces/thread-row-view-driver.js +11 -0
  364. package/src/platform-implementation-js/lib/ErrorCollector.d.ts +18 -0
  365. package/src/platform-implementation-js/lib/ErrorCollector.d.ts.map +1 -0
  366. package/src/platform-implementation-js/lib/Membrane.d.ts +13 -0
  367. package/src/platform-implementation-js/lib/Membrane.d.ts.map +1 -0
  368. package/src/platform-implementation-js/lib/ScrollableContainByScreen.d.ts +9 -0
  369. package/src/platform-implementation-js/lib/ScrollableContainByScreen.d.ts.map +1 -0
  370. package/src/platform-implementation-js/lib/array-to-lifetimes.js +67 -0
  371. package/src/platform-implementation-js/lib/array-to-lifetimes.test.js +171 -0
  372. package/src/platform-implementation-js/lib/attemptWithRetries.d.ts +2 -0
  373. package/src/platform-implementation-js/lib/attemptWithRetries.d.ts.map +1 -0
  374. package/src/platform-implementation-js/lib/common-page-communicator.d.ts +20 -0
  375. package/src/platform-implementation-js/lib/common-page-communicator.d.ts.map +1 -0
  376. package/src/platform-implementation-js/lib/copyAndValidateAutocompleteResults.js +55 -0
  377. package/src/platform-implementation-js/lib/css-selector-escape.js +8 -0
  378. package/src/platform-implementation-js/lib/delay-asap.d.ts +3 -0
  379. package/src/platform-implementation-js/lib/delay-asap.d.ts.map +1 -0
  380. package/src/platform-implementation-js/lib/delay-idle.d.ts +3 -0
  381. package/src/platform-implementation-js/lib/delay-idle.d.ts.map +1 -0
  382. package/src/platform-implementation-js/lib/dom/block-and-reemit-keyboard-events.d.ts +2 -0
  383. package/src/platform-implementation-js/lib/dom/block-and-reemit-keyboard-events.d.ts.map +1 -0
  384. package/src/platform-implementation-js/lib/dom/element-view-mapper.js +20 -0
  385. package/src/platform-implementation-js/lib/dom/generic-button-view.d.ts +13 -0
  386. package/src/platform-implementation-js/lib/dom/generic-button-view.d.ts.map +1 -0
  387. package/src/platform-implementation-js/lib/dom/get-insert-before-element.d.ts +2 -0
  388. package/src/platform-implementation-js/lib/dom/get-insert-before-element.d.ts.map +1 -0
  389. package/src/platform-implementation-js/lib/dom/get-selection.js +61 -0
  390. package/src/platform-implementation-js/lib/dom/insert-element-in-order.d.ts +2 -0
  391. package/src/platform-implementation-js/lib/dom/insert-element-in-order.d.ts.map +1 -0
  392. package/src/platform-implementation-js/lib/dom/insert-html-at-cursor.js +113 -0
  393. package/src/platform-implementation-js/lib/dom/is-node-in-range.js +19 -0
  394. package/src/platform-implementation-js/lib/dom/keyboard-shortcut-stream.d.ts +3 -0
  395. package/src/platform-implementation-js/lib/dom/keyboard-shortcut-stream.d.ts.map +1 -0
  396. package/src/platform-implementation-js/lib/dom/make-element-child-stream.d.ts +8 -0
  397. package/src/platform-implementation-js/lib/dom/make-element-child-stream.d.ts.map +1 -0
  398. package/src/platform-implementation-js/lib/dom/make-element-stream-merger.d.ts +4 -0
  399. package/src/platform-implementation-js/lib/dom/make-element-stream-merger.d.ts.map +1 -0
  400. package/src/platform-implementation-js/lib/dom/make-element-view-stream.d.ts +8 -0
  401. package/src/platform-implementation-js/lib/dom/make-element-view-stream.d.ts.map +1 -0
  402. package/src/platform-implementation-js/lib/dom/make-mutation-observer-chunked-stream.d.ts +3 -0
  403. package/src/platform-implementation-js/lib/dom/make-mutation-observer-chunked-stream.d.ts.map +1 -0
  404. package/src/platform-implementation-js/lib/dom/make-mutation-observer-stream.d.ts +3 -0
  405. package/src/platform-implementation-js/lib/dom/make-mutation-observer-stream.d.ts.map +1 -0
  406. package/src/platform-implementation-js/lib/dom/on-mouse-down-and-up.js +19 -0
  407. package/src/platform-implementation-js/lib/dom/outsideClicksAndEscape.d.ts +7 -0
  408. package/src/platform-implementation-js/lib/dom/outsideClicksAndEscape.d.ts.map +1 -0
  409. package/src/platform-implementation-js/lib/dom/parentNodes.d.ts +2 -0
  410. package/src/platform-implementation-js/lib/dom/parentNodes.d.ts.map +1 -0
  411. package/src/platform-implementation-js/lib/dom/querySelectorOne.js +16 -0
  412. package/src/platform-implementation-js/lib/dom/querySelectorOrFail.d.ts +2 -0
  413. package/src/platform-implementation-js/lib/dom/querySelectorOrFail.d.ts.map +1 -0
  414. package/src/platform-implementation-js/lib/dom/reemitClickEventForReact.d.ts +2 -0
  415. package/src/platform-implementation-js/lib/dom/reemitClickEventForReact.d.ts.map +1 -0
  416. package/src/platform-implementation-js/lib/dom/set-css.js +21 -0
  417. package/src/platform-implementation-js/lib/dom/set-value-and-dispatch-event.js +14 -0
  418. package/src/platform-implementation-js/lib/dom/simulate-drag-and-drop.js +98 -0
  419. package/src/platform-implementation-js/lib/dom/simulate-key.d.ts +2 -0
  420. package/src/platform-implementation-js/lib/dom/simulate-key.d.ts.map +1 -0
  421. package/src/platform-implementation-js/lib/dom/simulate-mouse-event.d.ts +4 -0
  422. package/src/platform-implementation-js/lib/dom/simulate-mouse-event.d.ts.map +1 -0
  423. package/src/platform-implementation-js/lib/dom/trigger-relay-event.d.ts +12 -0
  424. package/src/platform-implementation-js/lib/dom/trigger-relay-event.d.ts.map +1 -0
  425. package/src/platform-implementation-js/lib/extract-contact-from-email-contact-string.d.ts +3 -0
  426. package/src/platform-implementation-js/lib/extract-contact-from-email-contact-string.d.ts.map +1 -0
  427. package/src/platform-implementation-js/lib/extract-contact-from-email-contact-string.test.js +42 -0
  428. package/src/platform-implementation-js/lib/fake-window-resize.d.ts +2 -0
  429. package/src/platform-implementation-js/lib/fake-window-resize.d.ts.map +1 -0
  430. package/src/platform-implementation-js/lib/from-event-target-capture.d.ts +8 -0
  431. package/src/platform-implementation-js/lib/from-event-target-capture.d.ts.map +1 -0
  432. package/src/platform-implementation-js/lib/fromEventsWithOptions.d.ts +4 -0
  433. package/src/platform-implementation-js/lib/fromEventsWithOptions.d.ts.map +1 -0
  434. package/src/platform-implementation-js/lib/handle-compose-link-chips.js +179 -0
  435. package/src/platform-implementation-js/lib/handler-registry.d.ts +13 -0
  436. package/src/platform-implementation-js/lib/handler-registry.d.ts.map +1 -0
  437. package/src/platform-implementation-js/lib/idMap.d.ts +3 -0
  438. package/src/platform-implementation-js/lib/idMap.d.ts.map +1 -0
  439. package/src/platform-implementation-js/lib/imageRequest.d.ts +2 -0
  440. package/src/platform-implementation-js/lib/imageRequest.d.ts.map +1 -0
  441. package/src/platform-implementation-js/lib/incrementName.d.ts +2 -0
  442. package/src/platform-implementation-js/lib/incrementName.d.ts.map +1 -0
  443. package/src/platform-implementation-js/lib/inject-script-EMBEDDED.d.ts +2 -0
  444. package/src/platform-implementation-js/lib/inject-script-EMBEDDED.d.ts.map +1 -0
  445. package/src/platform-implementation-js/lib/inject-script.d.ts +3 -0
  446. package/src/platform-implementation-js/lib/inject-script.d.ts.map +1 -0
  447. package/src/platform-implementation-js/lib/insert-link-chip-into-body.js +66 -0
  448. package/src/platform-implementation-js/lib/is-valid-app-id.d.ts +2 -0
  449. package/src/platform-implementation-js/lib/is-valid-app-id.d.ts.map +1 -0
  450. package/src/platform-implementation-js/lib/is-valid-email.d.ts +2 -0
  451. package/src/platform-implementation-js/lib/is-valid-email.d.ts.map +1 -0
  452. package/src/platform-implementation-js/lib/isNotNil.d.ts +2 -0
  453. package/src/platform-implementation-js/lib/isNotNil.d.ts.map +1 -0
  454. package/src/platform-implementation-js/lib/isStreakAppId.d.ts +2 -0
  455. package/src/platform-implementation-js/lib/isStreakAppId.d.ts.map +1 -0
  456. package/src/platform-implementation-js/lib/logger.d.ts +29 -0
  457. package/src/platform-implementation-js/lib/logger.d.ts.map +1 -0
  458. package/src/platform-implementation-js/lib/make-revocable-function.js +40 -0
  459. package/src/platform-implementation-js/lib/make-revocable-function.test.js +63 -0
  460. package/src/platform-implementation-js/lib/parseParamsFromRouteID.js +20 -0
  461. package/src/platform-implementation-js/lib/parseParamsFromRouteID.test.js +28 -0
  462. package/src/platform-implementation-js/lib/persistent-queue.d.ts +14 -0
  463. package/src/platform-implementation-js/lib/persistent-queue.d.ts.map +1 -0
  464. package/src/platform-implementation-js/lib/populateRouteID.js +23 -0
  465. package/src/platform-implementation-js/lib/populateRouteID.test.js +31 -0
  466. package/src/platform-implementation-js/lib/react/ElementContainer.js +35 -0
  467. package/src/platform-implementation-js/lib/rewriteCssWithIdMap.js +10 -0
  468. package/src/platform-implementation-js/lib/rewriteCssWithIdMap.test.js +50 -0
  469. package/src/platform-implementation-js/lib/routeIDmatchesHash.js +20 -0
  470. package/src/platform-implementation-js/lib/routeIDmatchesHash.test.js +23 -0
  471. package/src/platform-implementation-js/lib/safe-event-emitter.d.ts +6 -0
  472. package/src/platform-implementation-js/lib/safe-event-emitter.d.ts.map +1 -0
  473. package/src/platform-implementation-js/lib/shared-style.js +22 -0
  474. package/src/platform-implementation-js/lib/stopper-pool.d.ts +11 -0
  475. package/src/platform-implementation-js/lib/stopper-pool.d.ts.map +1 -0
  476. package/src/platform-implementation-js/lib/stream-wait-for.d.ts +10 -0
  477. package/src/platform-implementation-js/lib/stream-wait-for.d.ts.map +1 -0
  478. package/src/platform-implementation-js/lib/toItemWithLifetimeStream.d.ts +7 -0
  479. package/src/platform-implementation-js/lib/toItemWithLifetimeStream.js +18 -0
  480. package/src/platform-implementation-js/lib/toLiveSet.js +31 -0
  481. package/src/platform-implementation-js/lib/wait-for.d.ts +2 -0
  482. package/src/platform-implementation-js/lib/wait-for.d.ts.map +1 -0
  483. package/src/platform-implementation-js/lib/waitForAsync.d.ts +2 -0
  484. package/src/platform-implementation-js/lib/waitForAsync.d.ts.map +1 -0
  485. package/src/platform-implementation-js/main-INTEGRATED-PAGEWORLD.js +8 -0
  486. package/src/platform-implementation-js/main.js +83 -0
  487. package/src/platform-implementation-js/namespaces/app-menu.d.ts +38 -0
  488. package/src/platform-implementation-js/namespaces/app-menu.d.ts.map +1 -0
  489. package/src/platform-implementation-js/namespaces/butter-bar.d.ts +11 -0
  490. package/src/platform-implementation-js/namespaces/butter-bar.d.ts.map +1 -0
  491. package/src/platform-implementation-js/namespaces/compose.js +88 -0
  492. package/src/platform-implementation-js/namespaces/conversations.js +156 -0
  493. package/src/platform-implementation-js/namespaces/global.js +51 -0
  494. package/src/platform-implementation-js/namespaces/keyboard.js +48 -0
  495. package/src/platform-implementation-js/namespaces/lists.js +58 -0
  496. package/src/platform-implementation-js/namespaces/modal.js +45 -0
  497. package/src/platform-implementation-js/namespaces/nav-menu.js +55 -0
  498. package/src/platform-implementation-js/namespaces/router.js +217 -0
  499. package/src/platform-implementation-js/namespaces/search.js +36 -0
  500. package/src/platform-implementation-js/namespaces/toolbars.js +195 -0
  501. package/src/platform-implementation-js/namespaces/user.js +67 -0
  502. package/src/platform-implementation-js/namespaces/widgets.js +89 -0
  503. package/src/platform-implementation-js/platform-implementation.d.ts +133 -0
  504. package/src/platform-implementation-js/platform-implementation.js +309 -0
  505. package/src/platform-implementation-js/views/SimpleElementView.d.ts +8 -0
  506. package/src/platform-implementation-js/views/SimpleElementView.d.ts.map +1 -0
  507. package/src/platform-implementation-js/views/app-menu-item-view.d.ts +23 -0
  508. package/src/platform-implementation-js/views/app-menu-item-view.d.ts.map +1 -0
  509. package/src/platform-implementation-js/views/app-toolbar-button-view.js +73 -0
  510. package/src/platform-implementation-js/views/collapsible-panel-view.d.ts +50 -0
  511. package/src/platform-implementation-js/views/collapsible-panel-view.d.ts.map +1 -0
  512. package/src/platform-implementation-js/views/collapsible-section-view.js +88 -0
  513. package/src/platform-implementation-js/views/compose-button-view.d.ts +25 -0
  514. package/src/platform-implementation-js/views/compose-button-view.d.ts.map +1 -0
  515. package/src/platform-implementation-js/views/compose-view.d.ts +90 -0
  516. package/src/platform-implementation-js/views/compose-view.d.ts.map +1 -0
  517. package/src/platform-implementation-js/views/content-panel-view.js +53 -0
  518. package/src/platform-implementation-js/views/conversations/attachment-card-view.js +69 -0
  519. package/src/platform-implementation-js/views/conversations/custom-message-view.js +165 -0
  520. package/src/platform-implementation-js/views/conversations/message-view.js +288 -0
  521. package/src/platform-implementation-js/views/conversations/thread-view.js +156 -0
  522. package/src/platform-implementation-js/views/keyboard-shortcut-handle.d.ts +8 -0
  523. package/src/platform-implementation-js/views/keyboard-shortcut-handle.d.ts.map +1 -0
  524. package/src/platform-implementation-js/views/native-nav-item-view.js +98 -0
  525. package/src/platform-implementation-js/views/nav-item-view.d.ts +24 -0
  526. package/src/platform-implementation-js/views/nav-item-view.js +191 -0
  527. package/src/platform-implementation-js/views/route-view/custom-route-view.js +32 -0
  528. package/src/platform-implementation-js/views/route-view/dummy-route-view-driver.js +40 -0
  529. package/src/platform-implementation-js/views/route-view/list-route-view.js +78 -0
  530. package/src/platform-implementation-js/views/route-view/route-view.js +68 -0
  531. package/src/platform-implementation-js/views/section-view.js +77 -0
  532. package/src/platform-implementation-js/views/thread-row-view.js +117 -0
  533. package/src/platform-implementation-js/widgets/buttons/basic-button-view-controller.d.ts +26 -0
  534. package/src/platform-implementation-js/widgets/buttons/basic-button-view-controller.d.ts.map +1 -0
  535. package/src/platform-implementation-js/widgets/buttons/dropdown-button-view-controller.d.ts +23 -0
  536. package/src/platform-implementation-js/widgets/buttons/dropdown-button-view-controller.d.ts.map +1 -0
  537. package/src/platform-implementation-js/widgets/buttons/dropdown-view.d.ts +22 -0
  538. package/src/platform-implementation-js/widgets/buttons/dropdown-view.d.ts.map +1 -0
  539. package/src/platform-implementation-js/widgets/drawer-view.js +61 -0
  540. package/src/platform-implementation-js/widgets/modal-view.js +134 -0
  541. package/src/platform-implementation-js/widgets/mole-view.js +47 -0
  542. package/src/platform-implementation-js/widgets/top-message-bar-view.js +20 -0
  543. package/src/types/combokeys-capture.d.ts +1 -0
  544. package/src/types/gulp-add-src.d.ts +7 -0
  545. package/src/types/gulp-dest-atomic.d.ts +4 -0
  546. package/src/types/gulp-streamify.d.ts +1 -0
  547. package/src/types/gulp-terser.d.ts +4 -0
  548. package/src/types/jest-puppeteer.d.ts +11 -0
  549. package/src/types/notp.d.ts +8 -0
  550. package/src/types/sha.d.ts +36 -0
  551. package/src/types/stdio.d.ts +6 -0
  552. package/src/types/thirty-two.d.ts +6 -0
@@ -0,0 +1,1938 @@
1
+ /* @flow */
2
+
3
+ import autoHtml from 'auto-html';
4
+ import t from 'transducers.js';
5
+ import once from 'lodash/once';
6
+ import escape from 'lodash/escape';
7
+ import includes from 'lodash/includes';
8
+ import constant from 'lodash/constant';
9
+ import find from 'lodash/find';
10
+ import asap from 'asap';
11
+ import delay from 'pdelay';
12
+ import * as Kefir from 'kefir';
13
+ import * as ud from 'ud';
14
+ import closest from 'closest-ng';
15
+ import kefirBus from 'kefir-bus';
16
+ import type { Bus } from 'kefir-bus';
17
+ import kefirStopper from 'kefir-stopper';
18
+ import type { Stopper } from 'kefir-stopper';
19
+
20
+ import delayAsap from '../../../lib/delay-asap';
21
+ import { simulateClick } from '../../../lib/dom/simulate-mouse-event';
22
+ import simulateKey from '../../../lib/dom/simulate-key';
23
+ import querySelector from '../../../lib/dom/querySelectorOrFail';
24
+ import isElementVisible from '../../../../common/isElementVisible';
25
+ import makeElementChildStream from '../../../lib/dom/make-element-child-stream';
26
+ import {
27
+ simulateDragOver,
28
+ simulateDrop,
29
+ simulateDragEnd,
30
+ } from '../../../lib/dom/simulate-drag-and-drop';
31
+ import * as GmailResponseProcessor from '../gmail-response-processor';
32
+ import GmailElementGetter from '../gmail-element-getter';
33
+ import setCss from '../../../lib/dom/set-css';
34
+
35
+ import waitFor from '../../../lib/wait-for';
36
+ import streamWaitFor from '../../../lib/stream-wait-for';
37
+ import makeMutationObserverChunkedStream from '../../../lib/dom/make-mutation-observer-chunked-stream';
38
+ import handleComposeLinkChips from '../../../lib/handle-compose-link-chips';
39
+ import insertLinkChipIntoBody from '../../../lib/insert-link-chip-into-body';
40
+ import addComposeNotice from './gmail-compose-view/add-compose-notice';
41
+ import addStatusBar from './gmail-compose-view/add-status-bar';
42
+ import insertHTMLatCursor from '../../../lib/dom/insert-html-at-cursor';
43
+ import ensureGroupingIsOpen from './gmail-compose-view/ensure-grouping-is-open';
44
+ import ensureAppButtonToolbarsAreClosed from './gmail-compose-view/ensure-app-button-toolbars-are-closed';
45
+ import sizeFixer from './gmail-compose-view/size-fixer';
46
+ import addTooltipToButton from './gmail-compose-view/add-tooltip-to-button';
47
+ import addRecipientRow from './gmail-compose-view/add-recipient-row';
48
+ import addButton from './gmail-compose-view/add-button';
49
+ import setRecipients from './gmail-compose-view/set-recipients';
50
+ import focus from './gmail-compose-view/focus';
51
+ // import addOuterSidebar from './gmail-compose-view/add-outer-sidebar';
52
+ import monitorSelectionRange from './gmail-compose-view/monitor-selection-range';
53
+ import manageButtonGrouping from './gmail-compose-view/manage-button-grouping';
54
+ import type { TooltipDescriptor } from '../../../views/compose-button-view';
55
+ import {
56
+ getSelectedHTMLInElement,
57
+ getSelectedTextInElement,
58
+ } from '../../../lib/dom/get-selection';
59
+ import getMinimizedStream from './gmail-compose-view/get-minimized-stream';
60
+ import censorHTMLstring from '../../../../common/censorHTMLstring';
61
+
62
+ import insertLinkIntoBody from './gmail-compose-view/insert-link-into-body';
63
+ import getAddressChangesStream from './gmail-compose-view/get-address-changes-stream';
64
+ import getBodyChangesStream from './gmail-compose-view/get-body-changes-stream';
65
+ import getRecipients from './gmail-compose-view/get-recipients';
66
+ import getResponseTypeChangesStream from './gmail-compose-view/get-response-type-changes-stream';
67
+ import getPresendingStream from '../../../driver-common/compose/getPresendingStream';
68
+ import getDiscardStream from '../../../driver-common/compose/getDiscardStream';
69
+ import updateInsertMoreAreaLeft from './gmail-compose-view/update-insert-more-area-left';
70
+ import setupLinkPopOvers from './gmail-compose-view/setupLinkPopovers';
71
+ import getFormattingAreaOffsetLeft from './gmail-compose-view/get-formatting-area-offset-left';
72
+ import overrideEditSubject from './gmail-compose-view/override-edit-subject';
73
+ import detectClassicRecipientsArea from './gmail-compose-view/detectClassicRecipientsArea';
74
+ import censorHTMLtree from '../../../../common/censorHTMLtree';
75
+ import {
76
+ makePageParser,
77
+ getRecipientRowElements,
78
+ } from './gmail-compose-view/page-parser';
79
+ import PageParserTree from 'page-parser-tree';
80
+ import { TagTree } from 'tag-tree';
81
+
82
+ import * as fromManager from './gmail-compose-view/from-manager';
83
+
84
+ import type {
85
+ ComposeNotice,
86
+ ComposeViewDriver,
87
+ StatusBar,
88
+ } from '../../../driver-interfaces/compose-view-driver';
89
+ import type Logger from '../../../lib/logger';
90
+ import type GmailDriver from '../gmail-driver';
91
+
92
+ let hasReportedMissingBody = false;
93
+
94
+ class GmailComposeView {
95
+ _element: HTMLElement;
96
+ _seenBodyElement: HTMLElement;
97
+ _isInlineReplyForm: boolean;
98
+ _isFullscreen: boolean;
99
+ _isStandalone: boolean;
100
+ _emailWasSent: boolean;
101
+ _driver: GmailDriver;
102
+ _managedViewControllers: Array<{ destroy(): void }>;
103
+ _eventStream: Bus<any>;
104
+ _isTriggeringADraftSavePending: boolean;
105
+ _buttonViewControllerTooltipMap: WeakMap<Object, Object>;
106
+ _composeID: string;
107
+ _messageIDElement: HTMLInputElement;
108
+ _messageId: ?string;
109
+ _finalMessageId: ?string; // Set only after the message is sent.
110
+ _initialMessageId: ?string;
111
+ _targetMessageID: ?string;
112
+ _draftSaving: boolean;
113
+ _draftIDpromise: ?Promise<?string>;
114
+ _threadID: ?string;
115
+ _stopper: Stopper;
116
+ _lastSelectionRange: ?Range;
117
+ _requestModifiers: {
118
+ [key: string]: (composeParams: { body: string }) =>
119
+ | { body: string }
120
+ | Promise<{ body: string }>,
121
+ };
122
+ _isListeningToAjaxInterceptStream: boolean;
123
+ _formattingArea: ?HTMLElement;
124
+ _closedProgrammatically: boolean = false;
125
+ _destroyed: boolean = false;
126
+ _removedFromDOMStopper: Stopper;
127
+ _hasSetupLinkPopOvers: boolean = false;
128
+ _page: PageParserTree;
129
+ tagTree: TagTree<HTMLElement>;
130
+ ready: () => Kefir.Observable<GmailComposeView>;
131
+
132
+ constructor(
133
+ element: HTMLElement,
134
+ xhrInterceptorStream: Kefir.Observable<*>,
135
+ driver: GmailDriver,
136
+ options: {
137
+ isInlineReplyForm: boolean,
138
+ isStandalone: boolean,
139
+ }
140
+ ) {
141
+ (this: ComposeViewDriver);
142
+ this._element = element;
143
+ this._element.classList.add('inboxsdk__compose');
144
+
145
+ if (options.isInlineReplyForm) {
146
+ this._element.classList.add('inboxsdk__compose_inlineReply');
147
+ }
148
+
149
+ this._isInlineReplyForm = options.isInlineReplyForm;
150
+ this._isStandalone = options.isStandalone;
151
+ this._isFullscreen = false;
152
+ this._emailWasSent = false;
153
+ this._messageId = null;
154
+ this._finalMessageId = null;
155
+ this._draftSaving = false;
156
+ this._draftIDpromise = null;
157
+ this._driver = driver;
158
+ this._stopper = kefirStopper();
159
+ this._managedViewControllers = [];
160
+ this._requestModifiers = {};
161
+ this._isListeningToAjaxInterceptStream = false;
162
+
163
+ this._eventStream = kefirBus();
164
+ this._removedFromDOMStopper = kefirStopper();
165
+
166
+ this._isTriggeringADraftSavePending = false;
167
+
168
+ this._page = makePageParser(element, driver.getLogger());
169
+ this.tagTree = this._page.tree;
170
+
171
+ let saveAndSendStream;
172
+ if (this._driver.isUsingSyncAPI()) {
173
+ saveAndSendStream = xhrInterceptorStream
174
+ // we know _getDraftIDfromForm will work because by the time we're
175
+ // getting an ajax event Gmail's JS has generated an ID and added it to the DOM.
176
+ .filter((event) => event.draftID === this._getDraftIDfromForm())
177
+ .map((event) => {
178
+ switch (event.type) {
179
+ case 'emailSending': {
180
+ return { eventName: 'sending' };
181
+ }
182
+ case 'emailSent': {
183
+ let syncThreadID = event.threadID;
184
+ let syncMessageID = event.messageID;
185
+
186
+ if (event.oldMessageID) this._messageId = event.oldMessageID;
187
+ if (event.oldThreadID) this._threadID = event.oldThreadID;
188
+
189
+ driver.removeCachedGmailMessageIdForSyncMessageId(syncMessageID);
190
+ driver.removeCachedOldGmailThreadIdFromSyncThreadId(syncThreadID);
191
+
192
+ return {
193
+ eventName: 'sent',
194
+ data: {
195
+ getThreadID: once(async (): Promise<string> => {
196
+ if (event.oldThreadID) {
197
+ return event.oldThreadID;
198
+ }
199
+ return await driver.getOldGmailThreadIdFromSyncThreadId(
200
+ syncThreadID
201
+ );
202
+ }),
203
+ getMessageID: once(async (): Promise<string> => {
204
+ if (event.oldMessageID) {
205
+ return event.oldMessageID;
206
+ }
207
+ return await driver.getGmailMessageIdForSyncMessageId(
208
+ syncMessageID
209
+ );
210
+ }),
211
+ },
212
+ };
213
+ }
214
+ case 'emailSendFailed': {
215
+ return { eventName: 'sendCanceled' };
216
+ }
217
+ case 'emailDraftReceived': {
218
+ this._messageId = event.oldMessageID;
219
+ this._threadID = event.oldThreadID;
220
+
221
+ return {
222
+ eventName: 'draftSaved',
223
+ data: {
224
+ getThreadID() {
225
+ return Promise.resolve(event.oldThreadID);
226
+ },
227
+ getMessageID() {
228
+ return Promise.resolve(event.oldMessageID);
229
+ },
230
+ },
231
+ };
232
+ }
233
+ default: {
234
+ return null;
235
+ }
236
+ }
237
+ })
238
+ .filter(Boolean);
239
+ } else {
240
+ saveAndSendStream = xhrInterceptorStream
241
+ .filter((event) => event.composeId === this.getComposeID())
242
+ .map((event) => {
243
+ switch (event.type) {
244
+ case 'emailSending': {
245
+ return [{ eventName: 'sending' }];
246
+ }
247
+ case 'emailSent': {
248
+ const response =
249
+ GmailResponseProcessor.interpretSentEmailResponse(
250
+ event.response
251
+ );
252
+ if (includes(['tr', 'eu'], response.messageID)) {
253
+ return [{ eventName: 'sendCanceled' }];
254
+ }
255
+ this._emailWasSent = true;
256
+ if (response.messageID) {
257
+ this._finalMessageId = response.messageID;
258
+ }
259
+ this._messageId = null;
260
+ const data = {
261
+ getThreadID: (): Promise<string> =>
262
+ Promise.resolve(response.threadID),
263
+ getMessageID: (): Promise<string> =>
264
+ Promise.resolve(response.messageID),
265
+ };
266
+ ['threadID', 'gmailThreadId'].forEach((prop) => {
267
+ // These properties are nonenumerable.
268
+ Object.defineProperty((data: any), prop, {
269
+ get: () => {
270
+ this._driver
271
+ .getLogger()
272
+ .deprecationWarning(
273
+ `composeView sent event.${prop}`,
274
+ 'composeView sent event.getThreadID()'
275
+ );
276
+ return response.threadID;
277
+ },
278
+ });
279
+ });
280
+ ['messageID', 'gmailMessageId'].forEach((prop) => {
281
+ Object.defineProperty((data: any), prop, {
282
+ get: () => {
283
+ this._driver
284
+ .getLogger()
285
+ .deprecationWarning(
286
+ `composeView sent event.${prop}`,
287
+ 'composeView sent event.getMessageID()'
288
+ );
289
+ return response.messageID;
290
+ },
291
+ });
292
+ });
293
+ return [{ eventName: 'sent', data }];
294
+ }
295
+ case 'emailDraftSaveSending': {
296
+ this._draftSaving = true;
297
+ return [{ eventName: 'draftSaving' }];
298
+ }
299
+ case 'emailDraftReceived': {
300
+ this._draftSaving = false;
301
+ let response;
302
+ try {
303
+ response = GmailResponseProcessor.interpretSentEmailResponse(
304
+ event.response
305
+ );
306
+ } catch (err) {
307
+ if (this._driver.getAppId() === 'sdk_streak_21e9788951') {
308
+ this._driver.getLogger().error(err, {
309
+ connectionDetails: event.connectionDetails,
310
+ response: event.response,
311
+ });
312
+ throw err;
313
+ } else {
314
+ throw err;
315
+ }
316
+ }
317
+ if (response.messageID === 'eu') {
318
+ return []; // save was canceled
319
+ }
320
+ const events = [{ eventName: 'draftSaved', data: response }];
321
+ if (!response.messageID) {
322
+ this._driver
323
+ .getLogger()
324
+ .error(
325
+ new Error('Missing message id from emailDraftReceived')
326
+ );
327
+ } else if (
328
+ response.messageID &&
329
+ this._messageId !== response.messageID
330
+ ) {
331
+ if (/^[0-9a-f]+$/i.test(response.messageID)) {
332
+ this._messageId = response.messageID;
333
+ events.push({
334
+ eventName: 'messageIDChange',
335
+ data: this._messageId,
336
+ });
337
+ } else {
338
+ this._driver
339
+ .getLogger()
340
+ .error(
341
+ new Error('Invalid message id from emailDraftReceived'),
342
+ {
343
+ value: response.messageID,
344
+ }
345
+ );
346
+ }
347
+ }
348
+ return events;
349
+ }
350
+ default:
351
+ return [];
352
+ }
353
+ })
354
+ .flatten()
355
+ .map((event) => {
356
+ if (this._driver.getLogger().shouldTrackEverything()) {
357
+ driver
358
+ .getLogger()
359
+ .eventSite('compose.debug.xhr', { eventName: event.eventName });
360
+ }
361
+
362
+ return event;
363
+ });
364
+ }
365
+
366
+ this._eventStream.plug(
367
+ Kefir.merge([
368
+ saveAndSendStream,
369
+
370
+ Kefir.fromEvents(this._element, 'buttonAdded').map(() => {
371
+ return {
372
+ eventName: 'buttonAdded',
373
+ };
374
+ }),
375
+
376
+ Kefir.fromEvents(this._element, 'resize').map(() => ({
377
+ eventName: 'resize',
378
+ })),
379
+
380
+ Kefir.fromEvents(this._element, 'composeFullscreenStateChanged').map(
381
+ () => {
382
+ this._updateComposeFullscreenState();
383
+ return {
384
+ eventName: 'fullscreenChanged',
385
+ data: { fullscreen: this._isFullscreen },
386
+ };
387
+ }
388
+ ),
389
+ ])
390
+ );
391
+
392
+ Kefir.fromEvents(this._element, 'closedProgrammatically')
393
+ .takeUntilBy(this._stopper)
394
+ .onValue(() => {
395
+ this._closedProgrammatically = true;
396
+ });
397
+
398
+ this._buttonViewControllerTooltipMap = new WeakMap();
399
+
400
+ const initialBodyElement = this.getMaybeBodyElement();
401
+ this.ready = constant(
402
+ (initialBodyElement
403
+ ? Kefir.constant(initialBodyElement)
404
+ : streamWaitFor(
405
+ () => this.getMaybeBodyElement(),
406
+ 3 * 60 * 1000 //timeout
407
+ )
408
+ )
409
+ .takeUntilBy(this._stopper)
410
+ .map((bodyElement) => {
411
+ this._seenBodyElement = bodyElement;
412
+
413
+ this._composeID = ((this._element.querySelector(
414
+ 'input[name="composeid"]'
415
+ ): any): HTMLInputElement).value;
416
+ this._messageIDElement = (this._element.querySelector(
417
+ 'input[name="draft"]'
418
+ ): any);
419
+ if (!this._messageIDElement) {
420
+ driver
421
+ .getLogger()
422
+ .error(new Error('Could not find compose message id field'));
423
+ // stub so other things don't fail
424
+ this._messageIDElement = document.createElement('input');
425
+ }
426
+
427
+ this._setupIDs();
428
+ this._setupStreams();
429
+ this._setupConsistencyCheckers();
430
+ this._updateComposeFullscreenState();
431
+
432
+ {
433
+ // try and handle the case where the user types in a bad email address
434
+ // we get the presending event but then no other events will pass because
435
+ // a modal comes up informing the user of the bad email address
436
+ this.getEventStream()
437
+ .filter(({ eventName }) => eventName === 'presending')
438
+ .takeUntilBy(this._stopper)
439
+ .onValue(() => {
440
+ makeElementChildStream(((document.body: any): HTMLElement))
441
+ .map((event) => event.el)
442
+ .filter(
443
+ (node) =>
444
+ node.getAttribute &&
445
+ node.getAttribute('role') === 'alertdialog'
446
+ )
447
+ .takeUntilBy(
448
+ Kefir.merge([
449
+ this.getEventStream().filter(
450
+ ({ eventName }) =>
451
+ eventName === 'sendCanceled' ||
452
+ eventName === 'sending'
453
+ ),
454
+ Kefir.later(15),
455
+ ])
456
+ )
457
+ .onValue(() => {
458
+ this._eventStream.emit({ eventName: 'sendCanceled' });
459
+ });
460
+ });
461
+ }
462
+
463
+ return this;
464
+ })
465
+ .toProperty()
466
+ );
467
+
468
+ this.ready().onError((errorObject) => {
469
+ driver.getLogger().error(errorObject, {
470
+ hasForm: !!this.getElement().querySelector('form'),
471
+ class: this.getElement().getAttribute('class'),
472
+ });
473
+ });
474
+
475
+ // v2 Data behaves differently whereby the compose element is removed
476
+ // from the page while the send is in flight instead of waiting for the
477
+ // send to come back, so we have to handle that difference
478
+ if (this._driver.isUsingSyncAPI()) {
479
+ Kefir.merge([
480
+ // if we get a presending then we let the other stream wait for
481
+ // sent. But if we get a sendCanceled, then a regular destroy can
482
+ // pass through
483
+ this._removedFromDOMStopper.filterBy(
484
+ this._eventStream
485
+ .filter(
486
+ ({ eventName }) =>
487
+ eventName === 'presending' || eventName === 'sendCanceled'
488
+ )
489
+ .map(({ eventName }) => eventName === 'sendCanceled')
490
+ .toProperty(() => true)
491
+ ),
492
+
493
+ Kefir.combine([
494
+ this._removedFromDOMStopper,
495
+ this._eventStream.filter(({ eventName }) => eventName === 'sent'),
496
+ ]),
497
+ ])
498
+ .take(1)
499
+ // we delay asap here so that the event stream is not destroyed before listeners here the sent event
500
+ .flatMap(() => delayAsap(null))
501
+ .onValue(() => this._destroy());
502
+ } else {
503
+ this._removedFromDOMStopper.onValue(() => this._destroy());
504
+ }
505
+
506
+ detectClassicRecipientsArea();
507
+ }
508
+
509
+ destroy() {
510
+ // this gets called when the element gets removed from the DOM
511
+ // however we don't want to pass through that destroy event right away
512
+ this._removedFromDOMStopper.destroy();
513
+ this._page.dump();
514
+ }
515
+
516
+ _destroy() {
517
+ this._eventStream.emit({
518
+ eventName: 'destroy',
519
+ data: {
520
+ messageID: this.getMessageID(),
521
+ closedByInboxSDK: this._closedProgrammatically,
522
+ },
523
+ });
524
+ this._eventStream.end();
525
+ this._managedViewControllers.forEach((vc) => {
526
+ vc.destroy();
527
+ });
528
+ this._requestModifiers = {};
529
+ this._managedViewControllers.length = 0;
530
+ this._stopper.destroy();
531
+ this._destroyed = true;
532
+ }
533
+
534
+ getStopper(): Kefir.Observable<null> {
535
+ return this._stopper;
536
+ }
537
+
538
+ getEventStream(): Kefir.Observable<Object> {
539
+ return this._eventStream;
540
+ }
541
+
542
+ getGmailDriver(): GmailDriver {
543
+ return this._driver;
544
+ }
545
+
546
+ isDestroyed(): boolean {
547
+ return this._destroyed;
548
+ }
549
+
550
+ _setupStreams() {
551
+ this._eventStream.plug(getAddressChangesStream(this));
552
+ this._eventStream.plug(getBodyChangesStream(this));
553
+ this._eventStream.plug(getResponseTypeChangesStream(this));
554
+ this._eventStream.plug(
555
+ getPresendingStream({
556
+ element: this.getElement(),
557
+ sendButton: this.getSendButton(),
558
+ sendAndArchive: this.getSendAndArchiveButton(),
559
+ })
560
+ );
561
+
562
+ let discardButton;
563
+ try {
564
+ discardButton = this.getDiscardButton();
565
+ } catch (err) {
566
+ // handle failures of this.getDiscardButton()
567
+ this._driver
568
+ .getLogger()
569
+ .errorSite(new Error('Failed to find discard button'), {
570
+ html: censorHTMLstring(this._element.outerHTML),
571
+ });
572
+ }
573
+ if (discardButton) {
574
+ this._eventStream.plug(
575
+ getDiscardStream({
576
+ element: this.getElement(),
577
+ discardButton,
578
+ })
579
+ );
580
+ }
581
+
582
+ this._eventStream.plug(
583
+ Kefir.fromEvents(this.getElement(), 'inboxSDKsendCanceled').map(() => ({
584
+ eventName: 'sendCanceled',
585
+ }))
586
+ );
587
+
588
+ this._eventStream.plug(
589
+ Kefir.fromEvents(this.getElement(), 'inboxSDKdiscardCanceled').map(
590
+ () => ({ eventName: 'discardCanceled' })
591
+ )
592
+ );
593
+
594
+ this._eventStream.plug(
595
+ Kefir.later(10)
596
+ .flatMap(() => getMinimizedStream(this))
597
+ .changes()
598
+ .map((minimized) => ({
599
+ eventName: minimized ? 'minimized' : 'restored',
600
+ }))
601
+ );
602
+
603
+ if (!this._driver.isUsingSyncAPI()) {
604
+ makeMutationObserverChunkedStream(this._messageIDElement, {
605
+ attributes: true,
606
+ attributeFilter: ['value'],
607
+ })
608
+ .takeUntilBy(
609
+ this._eventStream.filter(() => false).beforeEnd(() => null)
610
+ )
611
+ .map(() => this._getMessageIDfromForm())
612
+ .filter(
613
+ (messageID) =>
614
+ messageID && !this._emailWasSent && this._messageId !== messageID
615
+ )
616
+ .onValue((messageID) => {
617
+ this._messageId = messageID;
618
+ this._eventStream.emit({
619
+ eventName: 'messageIDChange',
620
+ data: this._messageId,
621
+ });
622
+ });
623
+ }
624
+ }
625
+
626
+ _setupConsistencyCheckers() {
627
+ try {
628
+ handleComposeLinkChips(this);
629
+ monitorSelectionRange(this);
630
+ manageButtonGrouping(this);
631
+ sizeFixer(this._driver, this);
632
+ } catch (err) {
633
+ this._driver.getLogger().error(err);
634
+ }
635
+ }
636
+
637
+ _setupIDs() {
638
+ if (this._driver.isUsingSyncAPI()) {
639
+ const syncTargetMessageID = this._getTargetMessageID();
640
+ if (syncTargetMessageID) {
641
+ this._driver
642
+ .getGmailMessageIdForSyncMessageId(syncTargetMessageID)
643
+ .then((gmailMessageId) => (this._targetMessageID = gmailMessageId));
644
+ }
645
+
646
+ const syncMessageId = this._getMessageIDfromForm();
647
+ if (syncMessageId) {
648
+ this._driver
649
+ .getGmailMessageIdForSyncDraftId(syncMessageId)
650
+ .then((gmailMessageId) => {
651
+ this._initialMessageId = gmailMessageId;
652
+ this._messageId = gmailMessageId;
653
+ })
654
+ .catch(() => {
655
+ //do nothing because this means the message hasn't been saved yet
656
+ });
657
+
658
+ this._driver.reportRecentSyncDraftId(syncMessageId);
659
+ this._stopper.onValue(() => {
660
+ this._driver.reportDraftClosed(syncMessageId);
661
+ });
662
+ } else {
663
+ this._driver
664
+ .getLogger()
665
+ .error(new Error('Draft is missing sync draft id'));
666
+ }
667
+
668
+ const legacyThreadIdElement: ?HTMLInputElement =
669
+ (this._element.querySelector('input[name="lts"]'): any);
670
+ if (
671
+ legacyThreadIdElement &&
672
+ typeof legacyThreadIdElement.value === 'string'
673
+ )
674
+ this._threadID = legacyThreadIdElement.value;
675
+ } else {
676
+ this._targetMessageID = this._getTargetMessageID();
677
+ this._messageId = this._initialMessageId = this._getMessageIDfromForm();
678
+ this._threadID = this._getThreadID();
679
+ }
680
+ }
681
+
682
+ _updateComposeFullscreenState() {
683
+ if (this._isInlineReplyForm) {
684
+ this._isFullscreen = false;
685
+ } else {
686
+ if (this._isStandalone) {
687
+ this._isFullscreen = true;
688
+ } else {
689
+ const fullScreenContainer =
690
+ GmailElementGetter.getFullscreenComposeWindowContainer();
691
+ if (!fullScreenContainer) {
692
+ this._isFullscreen = false;
693
+ } else {
694
+ this._isFullscreen = fullScreenContainer.contains(this._element);
695
+ }
696
+ }
697
+ }
698
+ }
699
+
700
+ focus() {
701
+ focus(this);
702
+ }
703
+
704
+ insertBodyTextAtCursor(text: string): ?HTMLElement {
705
+ return this.insertBodyHTMLAtCursor(escape(text).replace(/\n/g, '<br>'));
706
+ }
707
+
708
+ insertBodyHTMLAtCursor(html: string): ?HTMLElement {
709
+ var retVal = insertHTMLatCursor(
710
+ this.getBodyElement(),
711
+ html,
712
+ this.getLastSelectionRange()
713
+ );
714
+ this._triggerDraftSave();
715
+
716
+ // sometimes the html inserted can be quite large, so we need ot make sure that GMail resizes the compose window
717
+ // triggering an enter press forces Gmail to resize compose
718
+ simulateKey(this.getBodyElement(), 13, 13);
719
+
720
+ return retVal;
721
+ }
722
+
723
+ insertLinkIntoBody(text: string, href: string): ?HTMLElement {
724
+ var retVal = insertLinkIntoBody(this, text, href);
725
+
726
+ this._triggerDraftSave();
727
+ return retVal;
728
+ }
729
+
730
+ insertLinkChipIntoBody(options: {
731
+ iconUrl?: string,
732
+ url: string,
733
+ text: string,
734
+ }): HTMLElement {
735
+ var retVal = insertLinkChipIntoBody(this, options);
736
+ this._triggerDraftSave();
737
+ return retVal;
738
+ }
739
+
740
+ setSubject(text: string) {
741
+ (this._element.querySelector('input[name=subjectbox]'): any).value = text;
742
+
743
+ this._triggerDraftSave();
744
+ }
745
+
746
+ setBodyHTML(html: string) {
747
+ this.getBodyElement().innerHTML = html;
748
+
749
+ this._triggerDraftSave();
750
+ }
751
+
752
+ setBodyText(text: string) {
753
+ this.getBodyElement().textContent = text;
754
+
755
+ this._triggerDraftSave();
756
+ }
757
+
758
+ setToRecipients(emails: string[]) {
759
+ setRecipients(this, 'to', emails);
760
+
761
+ this._triggerDraftSave();
762
+ }
763
+
764
+ setCcRecipients(emails: string[]) {
765
+ setRecipients(this, 'cc', emails);
766
+
767
+ this._triggerDraftSave();
768
+ }
769
+
770
+ setBccRecipients(emails: string[]) {
771
+ setRecipients(this, 'bcc', emails);
772
+
773
+ this._triggerDraftSave();
774
+ }
775
+
776
+ addRecipientRow(options: Kefir.Observable<?Object>): () => void {
777
+ return addRecipientRow(this, options);
778
+ }
779
+
780
+ forceRecipientRowsOpen(): () => void {
781
+ this._element.classList.add('inboxsdk__compose_forceRecipientsOpen');
782
+
783
+ return () => {
784
+ this._element.classList.remove('inboxsdk__compose_forceRecipientsOpen');
785
+ };
786
+ }
787
+
788
+ hideNativeRecipientRows(): () => void {
789
+ const nativeRecipientRows = getRecipientRowElements(this._element);
790
+
791
+ nativeRecipientRows.forEach((row) => {
792
+ row.classList.add('inboxsdk__compose_forceRecipientRowHidden');
793
+ });
794
+
795
+ return () => {
796
+ nativeRecipientRows.forEach((row) => {
797
+ row.classList.remove('inboxsdk__compose_forceRecipientRowHidden');
798
+ });
799
+ };
800
+ }
801
+
802
+ hideRecipientArea(): () => void {
803
+ this._element.classList.add('inboxsdk__compose_hideRecipientArea');
804
+
805
+ return () => {
806
+ this._element.classList.remove('inboxsdk__compose_hideRecipientArea');
807
+ };
808
+ }
809
+
810
+ getFromContact() {
811
+ return fromManager.getFromContact(this._driver, this);
812
+ }
813
+
814
+ getFromContactChoices() {
815
+ return fromManager.getFromContactChoices(this._driver, this);
816
+ }
817
+
818
+ setFromEmail(email: string) {
819
+ fromManager.setFromEmail(this._driver, this, email);
820
+ }
821
+
822
+ addButton(
823
+ buttonDescriptor: Kefir.Observable<?Object>,
824
+ groupOrderHint: string,
825
+ extraOnClickOptions: Object
826
+ ): Promise<?Object> {
827
+ return addButton(
828
+ this,
829
+ buttonDescriptor,
830
+ groupOrderHint,
831
+ extraOnClickOptions
832
+ );
833
+ }
834
+
835
+ addTooltipToButton(
836
+ buttonViewController: Object,
837
+ buttonDescriptor: Object,
838
+ tooltipDescriptor: TooltipDescriptor
839
+ ) {
840
+ var tooltip = addTooltipToButton(
841
+ this,
842
+ buttonViewController,
843
+ buttonDescriptor,
844
+ tooltipDescriptor
845
+ );
846
+ this._buttonViewControllerTooltipMap.set(buttonViewController, tooltip);
847
+ }
848
+
849
+ closeButtonTooltip(buttonViewController: Object) {
850
+ if (!this._buttonViewControllerTooltipMap) {
851
+ return;
852
+ }
853
+
854
+ var tooltip =
855
+ this._buttonViewControllerTooltipMap.get(buttonViewController);
856
+ if (tooltip) {
857
+ tooltip.destroy();
858
+ this._buttonViewControllerTooltipMap.delete(buttonViewController);
859
+ }
860
+ }
861
+
862
+ addComposeNotice(
863
+ options: {
864
+ orderHint?: number,
865
+ } = {}
866
+ ): ComposeNotice {
867
+ const composeNotice = addComposeNotice(this, options);
868
+
869
+ this._element.dispatchEvent(
870
+ new CustomEvent('resize', {
871
+ bubbles: false,
872
+ cancelable: false,
873
+ detail: null,
874
+ })
875
+ );
876
+
877
+ Kefir.fromEvents(composeNotice, 'destroy')
878
+ .flatMap(delayAsap)
879
+ .takeUntilBy(this._stopper)
880
+ .onValue(() => {
881
+ this._element.dispatchEvent(
882
+ new CustomEvent('resize', {
883
+ bubbles: false,
884
+ cancelable: false,
885
+ detail: null,
886
+ })
887
+ );
888
+ });
889
+
890
+ return composeNotice;
891
+ }
892
+
893
+ addStatusBar(
894
+ options: {
895
+ height?: number,
896
+ orderHint?: number,
897
+ addAboveNativeStatusBar?: boolean,
898
+ } = {}
899
+ ): StatusBar {
900
+ const statusBar = addStatusBar(this, options);
901
+
902
+ this._element.dispatchEvent(
903
+ new CustomEvent('resize', {
904
+ bubbles: false,
905
+ cancelable: false,
906
+ detail: null,
907
+ })
908
+ );
909
+
910
+ Kefir.fromEvents(statusBar, 'destroy')
911
+ .flatMap(delayAsap)
912
+ .takeUntilBy(this._stopper)
913
+ .onValue(() => {
914
+ this._element.dispatchEvent(
915
+ new CustomEvent('resize', {
916
+ bubbles: false,
917
+ cancelable: false,
918
+ detail: null,
919
+ })
920
+ );
921
+ });
922
+
923
+ return statusBar;
924
+ }
925
+
926
+ hideNativeStatusBar(): () => void {
927
+ const statusArea = this.getStatusArea();
928
+ const nativeStatusBar = querySelector(statusArea, 'table');
929
+ const formattingToolbar = this.getFormattingToolbar();
930
+ const isFormattingToolbarOpen =
931
+ formattingToolbar && formattingToolbar.style.display !== 'none';
932
+
933
+ nativeStatusBar.style.display = 'none';
934
+
935
+ if (formattingToolbar && isFormattingToolbarOpen) {
936
+ formattingToolbar.style.display = 'none';
937
+ }
938
+
939
+ return () => {
940
+ nativeStatusBar.style.display = '';
941
+
942
+ if (formattingToolbar && isFormattingToolbarOpen) {
943
+ formattingToolbar.style.display = '';
944
+ }
945
+ };
946
+ }
947
+
948
+ replaceSendButton(el: HTMLElement): () => void {
949
+ const sendButton = this.getSendButtonGroup();
950
+ const sendAndArchive = this.getSendAndArchiveButton();
951
+
952
+ sendButton.style.display = 'none';
953
+
954
+ const sendAndArchiveParent = sendAndArchive && sendAndArchive.parentElement;
955
+ if (sendAndArchiveParent instanceof HTMLElement) {
956
+ sendAndArchiveParent.style.display = 'none';
957
+ }
958
+
959
+ const container = document.createElement('div');
960
+ container.classList.add('inboxsdk__compose_customSendContainer');
961
+ container.appendChild(el);
962
+
963
+ sendButton.insertAdjacentElement('afterend', container);
964
+ this._element.setAttribute('data-inboxsdk-send-replaced', '');
965
+
966
+ const removalStopper = kefirStopper();
967
+
968
+ Kefir.fromEvents(this.getBodyElement(), 'keydown')
969
+ .takeUntilBy(this._stopper)
970
+ .takeUntilBy(removalStopper)
971
+ .filter(
972
+ (domEvent) =>
973
+ (domEvent.which === 9 || domEvent.keyCode === 9) && !domEvent.shiftKey
974
+ )
975
+ .onValue((domEvent) => {
976
+ // Because of the way the compose DOM is structured, the natural
977
+ // tab order does not flow from the compose body to the status bar.
978
+ // Gmail modifies this flow programatically by focusing the send button,
979
+ // so we have replicate this behavior when the native send button isn't
980
+ // visible.
981
+ const statusArea = this.getStatusArea();
982
+ const focusableEls = statusArea.querySelectorAll('[tabindex]');
983
+ if (focusableEls.length === 0) return;
984
+
985
+ const firstVisibleEl = Array.from(focusableEls).find(
986
+ (el) => el.offsetParent !== null
987
+ );
988
+ if (!firstVisibleEl) return;
989
+
990
+ domEvent.preventDefault();
991
+ domEvent.stopPropagation();
992
+ domEvent.stopImmediatePropagation();
993
+
994
+ firstVisibleEl.focus();
995
+ });
996
+
997
+ return () => {
998
+ removalStopper.destroy();
999
+ container.remove();
1000
+ this._element.removeAttribute('data-inboxsdk-send-replaced');
1001
+
1002
+ sendButton.style.display = '';
1003
+ if (sendAndArchiveParent instanceof HTMLElement) {
1004
+ sendAndArchiveParent.style.display = '';
1005
+ }
1006
+ };
1007
+ }
1008
+
1009
+ hideDiscardButton(): () => void {
1010
+ const discardBtn = this.getDiscardButton();
1011
+
1012
+ discardBtn.style.display = 'none';
1013
+
1014
+ return () => {
1015
+ discardBtn.style.display = '';
1016
+ };
1017
+ }
1018
+
1019
+ ensureFormattingToolbarIsHidden() {
1020
+ const formattingToggleButton = this.getFormattingToolbarToggleButton();
1021
+ const formattingToolbar = this.getFormattingToolbar();
1022
+
1023
+ if (
1024
+ formattingToggleButton &&
1025
+ formattingToolbar &&
1026
+ formattingToolbar.style.display === ''
1027
+ ) {
1028
+ simulateClick(formattingToggleButton);
1029
+ }
1030
+ }
1031
+
1032
+ close() {
1033
+ if (this.isInlineReplyForm()) {
1034
+ // eslint-disable-next-line no-console
1035
+ console.warn("Trying to close an inline reply which doesn't work.");
1036
+ return;
1037
+ }
1038
+
1039
+ this._element.dispatchEvent(
1040
+ new CustomEvent('closedProgrammatically', {
1041
+ bubbles: false,
1042
+ cancelable: false,
1043
+ detail: null,
1044
+ })
1045
+ );
1046
+
1047
+ if (this._isFullscreen) {
1048
+ this._eventStream
1049
+ .filter(({ eventName }) => eventName === 'fullscreenChanged')
1050
+ .onValue(() => simulateClick(this.getCloseButton()));
1051
+
1052
+ simulateClick(this.getMoleSwitchButton());
1053
+ } else {
1054
+ simulateClick(this.getCloseButton());
1055
+ }
1056
+ }
1057
+
1058
+ send({ sendAndArchive }: { sendAndArchive: boolean }) {
1059
+ // asap necessary so if send() is called after presending event.cancel(), the new presending event
1060
+ // must happen after the sendCanceled event (which is also delayed by asap).
1061
+ asap(() => {
1062
+ const sendAndArchiveButton = this.getSendAndArchiveButton();
1063
+
1064
+ if (sendAndArchive && sendAndArchiveButton) {
1065
+ simulateClick(sendAndArchiveButton);
1066
+ } else {
1067
+ simulateClick(this.getSendButton());
1068
+ }
1069
+ });
1070
+ }
1071
+
1072
+ discard() {
1073
+ simulateClick(this.getDiscardButton());
1074
+ }
1075
+
1076
+ popOut() {
1077
+ if (!this.isInlineReplyForm()) {
1078
+ throw new Error('Can only pop out inline reply compose views');
1079
+ }
1080
+ const popOutBtn = querySelector(
1081
+ this._element,
1082
+ '.M9 > [role=menu]:first-child > .SK > [role=menuitem]:last-child'
1083
+ );
1084
+ simulateClick(popOutBtn);
1085
+ }
1086
+
1087
+ overrideEditSubject() {
1088
+ overrideEditSubject(this._driver, this);
1089
+ }
1090
+
1091
+ _hideDropzones() {
1092
+ setCss('compose dropzone hider', 'body > .aC7 .aC9 {visibility: hidden;}');
1093
+ }
1094
+
1095
+ _reenableDropzones() {
1096
+ setCss('compose dropzone hider', null);
1097
+ }
1098
+
1099
+ _dropzonesVisible(): boolean {
1100
+ return (
1101
+ find(
1102
+ document.querySelectorAll('body > .aC7:not(.aWP)'),
1103
+ isElementVisible
1104
+ ) != null
1105
+ );
1106
+ }
1107
+
1108
+ _findDropzoneForThisCompose(inline: boolean): HTMLElement {
1109
+ // Iterate through all the dropzones and find the one visually contained by
1110
+ // this compose.
1111
+ const rect = this._element.getBoundingClientRect();
1112
+ const dropzoneSelector = inline
1113
+ ? 'body > .aC7:not(.aWP)'
1114
+ : 'body > .aC7.aWP';
1115
+ const el: ?HTMLElement = t.toArray(
1116
+ Array.prototype.slice.call(document.querySelectorAll(dropzoneSelector)),
1117
+ t.compose(
1118
+ t.filter(isElementVisible),
1119
+ t.filter((dropzone) => {
1120
+ const top = parseInt(dropzone.style.top, 10);
1121
+ const bottom = top + parseInt(dropzone.style.height, 10);
1122
+ const left = parseInt(dropzone.style.left, 10);
1123
+ const right = left + parseInt(dropzone.style.width, 10);
1124
+ return (
1125
+ top >= rect.top &&
1126
+ left >= rect.left &&
1127
+ right <= rect.right &&
1128
+ bottom <= rect.bottom
1129
+ );
1130
+ }),
1131
+ t.take(1)
1132
+ )
1133
+ )[0];
1134
+ if (!el) {
1135
+ throw new Error('Failed to find dropzone');
1136
+ }
1137
+ return el;
1138
+ }
1139
+
1140
+ async _attachFiles(files: Blob[], inline: boolean): Promise<void> {
1141
+ this._hideDropzones();
1142
+ const endDrag = once(() => simulateDragEnd(this._element, files));
1143
+ try {
1144
+ let firstLoop = true;
1145
+ for (let files of t.partition(files, 3)) {
1146
+ if (firstLoop) {
1147
+ firstLoop = false;
1148
+ } else {
1149
+ await delay(500);
1150
+ }
1151
+
1152
+ simulateDragOver(this._element, files);
1153
+ await waitFor(() => this._dropzonesVisible(), 20 * 1000);
1154
+ const dropzone = this._findDropzoneForThisCompose(inline);
1155
+ simulateDrop(dropzone, files);
1156
+ endDrag();
1157
+ await waitFor(() => !this._dropzonesVisible(), 20 * 1000);
1158
+ }
1159
+ } catch (err) {
1160
+ this._driver.getLogger().error(err);
1161
+ } finally {
1162
+ endDrag();
1163
+ this._reenableDropzones();
1164
+ }
1165
+ }
1166
+
1167
+ attachFiles(files: Blob[]): Promise<void> {
1168
+ return this._attachFiles(files, false);
1169
+ }
1170
+
1171
+ attachInlineFiles(files: Blob[]): Promise<void> {
1172
+ return this._attachFiles(files, true);
1173
+ }
1174
+
1175
+ isForward(): boolean {
1176
+ return Boolean(this._element.querySelector('.Un.J-JN-M-I .mI'));
1177
+ }
1178
+
1179
+ isReply(): boolean {
1180
+ return this._isInlineReplyForm || !!this._element.querySelector('.HQ');
1181
+ }
1182
+
1183
+ isInlineReplyForm(): boolean {
1184
+ return this._isInlineReplyForm;
1185
+ }
1186
+
1187
+ getBodyElement(): HTMLElement {
1188
+ const el = this.getMaybeBodyElement();
1189
+ if (!el) throw new Error('Could not find body element');
1190
+ return el;
1191
+ }
1192
+
1193
+ getMaybeBodyElement(): ?HTMLElement {
1194
+ return this._element.querySelector('.Ap [g_editable=true]');
1195
+ }
1196
+
1197
+ getTopFormElement(): HTMLElement {
1198
+ return querySelector(this._element, 'td > form');
1199
+ }
1200
+
1201
+ getHTMLContent(): string {
1202
+ return this.getBodyElement().innerHTML;
1203
+ }
1204
+
1205
+ getTextContent(): string {
1206
+ return this.getBodyElement().textContent;
1207
+ }
1208
+
1209
+ getSelectedBodyHTML(): ?string {
1210
+ return getSelectedHTMLInElement(
1211
+ this.getBodyElement(),
1212
+ this.getLastSelectionRange()
1213
+ );
1214
+ }
1215
+
1216
+ getSelectedBodyText(): ?string {
1217
+ return getSelectedTextInElement(
1218
+ this.getBodyElement(),
1219
+ this.getLastSelectionRange()
1220
+ );
1221
+ }
1222
+
1223
+ getSubject(): string {
1224
+ return this.getSubjectInput().value;
1225
+ }
1226
+
1227
+ getSubjectInput(): HTMLInputElement {
1228
+ return (this._element: any).querySelector('input[name=subjectbox]');
1229
+ }
1230
+
1231
+ getMetadataFormElement(): HTMLElement {
1232
+ const container = this.getBodyElement().closest('.aoP');
1233
+ if (!container) {
1234
+ throw new Error('Could not find compose container');
1235
+ }
1236
+ return querySelector(container, 'form.bAs');
1237
+ }
1238
+
1239
+ getToRecipients(): Contact[] {
1240
+ return getRecipients(this, 'to');
1241
+ }
1242
+
1243
+ getCcRecipients(): Contact[] {
1244
+ return getRecipients(this, 'cc');
1245
+ }
1246
+
1247
+ getBccRecipients(): Contact[] {
1248
+ return getRecipients(this, 'bcc');
1249
+ }
1250
+
1251
+ getAdditionalActionToolbar(): HTMLElement {
1252
+ return require('./gmail-compose-view/get-additional-action-toolbar').default(
1253
+ this
1254
+ );
1255
+ }
1256
+
1257
+ updateInsertMoreAreaLeft(oldFormattingAreaOffsetLeft: number) {
1258
+ updateInsertMoreAreaLeft(this, oldFormattingAreaOffsetLeft);
1259
+ }
1260
+
1261
+ _getFormattingAreaOffsetLeft(): number {
1262
+ return getFormattingAreaOffsetLeft(this);
1263
+ }
1264
+
1265
+ getFormattingArea(): ?HTMLElement {
1266
+ let formattingArea = this._formattingArea;
1267
+ if (!formattingArea) {
1268
+ formattingArea = this._formattingArea =
1269
+ this._element.querySelector('.oc');
1270
+ }
1271
+ return formattingArea;
1272
+ }
1273
+
1274
+ getFormattingToolbar(): ?HTMLElement {
1275
+ return this._element.querySelector('.aX');
1276
+ }
1277
+
1278
+ getFormattingToolbarArrow(): HTMLElement {
1279
+ const el = this.getFormattingToolbar();
1280
+ if (!el) throw new Error('Failed to find formatting toolbar');
1281
+ return querySelector(el, '.aA4');
1282
+ }
1283
+
1284
+ getFormattingToolbarToggleButton(): HTMLElement {
1285
+ const innerElement = querySelector(this._element, '[role=button] .dv');
1286
+ const btn = closest(innerElement, '[role=button]');
1287
+ if (!btn) throw new Error('failed to find button');
1288
+ return btn;
1289
+ }
1290
+
1291
+ getStatusBarPrependContainer(): ?HTMLElement {
1292
+ return this._element.querySelector(
1293
+ '.inboxsdk__compose_statusBarPrependContainer'
1294
+ );
1295
+ }
1296
+
1297
+ getScrollBody(): HTMLElement {
1298
+ var scrollBody = this._element.querySelector('table .GP');
1299
+ if (!scrollBody) {
1300
+ throw new Error('Failed to find scroll body');
1301
+ }
1302
+ return scrollBody;
1303
+ }
1304
+
1305
+ getStatusArea(): HTMLElement {
1306
+ let statusArea = this._element.querySelector('.aDg .aDj > .aDh');
1307
+ if (!statusArea) throw new Error('Failed to find status area');
1308
+ return statusArea;
1309
+ }
1310
+
1311
+ getInsertMoreArea(): HTMLElement {
1312
+ return querySelector(this._element, '.eq');
1313
+ }
1314
+
1315
+ getInsertLinkButton(): HTMLElement {
1316
+ return querySelector(this._element, '.e5.aaA.aMZ');
1317
+ }
1318
+
1319
+ getSendButton(): HTMLElement {
1320
+ return querySelector(
1321
+ this._element,
1322
+ '.IZ .Up div > div[role=button]:not(.Uo):not([aria-haspopup=true]):not([class^=inboxsdk_])'
1323
+ );
1324
+ }
1325
+
1326
+ // When schedule send is available, this returns the element that contains both buttons.
1327
+ getSendButtonGroup(): HTMLElement {
1328
+ const scheduleSend = this._element.querySelector(
1329
+ '.IZ .Up div > [role=button][aria-haspopup=true]:not([class^=inboxsdk_])'
1330
+ );
1331
+ if (scheduleSend) {
1332
+ return (scheduleSend: any).parentElement;
1333
+ }
1334
+ return this.getSendButton();
1335
+ }
1336
+
1337
+ getSendAndArchiveButton(): ?HTMLElement {
1338
+ if (!this.isReply()) {
1339
+ return null;
1340
+ }
1341
+
1342
+ const sendAndArchiveButton = this._element.querySelector(
1343
+ '.IZ .Up div > div[role=button].Uo:not([aria-haspopup=true]):not([class^=inboxsdk_])'
1344
+ );
1345
+ if (sendAndArchiveButton) {
1346
+ return sendAndArchiveButton;
1347
+ }
1348
+
1349
+ // TODO is the rest of this function necessary?
1350
+
1351
+ const sendButton = this.getSendButton();
1352
+ const parent = sendButton.parentElement;
1353
+ if (!(parent instanceof HTMLElement)) throw new Error('should not happen');
1354
+ if (parent.childElementCount <= 1) {
1355
+ this._driver
1356
+ .getLogger()
1357
+ .eventSdkPassive(
1358
+ 'getSendAndArchiveButton - old method - failed to find, childElementCount <= 1'
1359
+ );
1360
+ return null;
1361
+ }
1362
+
1363
+ const firstNotSendElement =
1364
+ parent.children[0] !== sendButton
1365
+ ? parent.children[0]
1366
+ : parent.children[1];
1367
+ const result = !firstNotSendElement
1368
+ ? null
1369
+ : firstNotSendElement.querySelector('[role=button]');
1370
+ if (result) {
1371
+ this._driver
1372
+ .getLogger()
1373
+ .eventSdkPassive('getSendAndArchiveButton - old method - found');
1374
+ } else {
1375
+ this._driver
1376
+ .getLogger()
1377
+ .eventSdkPassive(
1378
+ 'getSendAndArchiveButton - old method - failed to find'
1379
+ );
1380
+ }
1381
+ return result;
1382
+ }
1383
+
1384
+ getCloseButton(): HTMLElement {
1385
+ return this._element.querySelectorAll('.Hm > img')[2];
1386
+ }
1387
+
1388
+ getMoleSwitchButton(): HTMLElement {
1389
+ return this._element.querySelectorAll('.Hm > img')[1];
1390
+ }
1391
+
1392
+ getBottomBarTable(): HTMLElement {
1393
+ return querySelector(this._element, '.aoP .aDh > table');
1394
+ }
1395
+
1396
+ getBottomToolbarContainer(): HTMLElement {
1397
+ return querySelector(this._element, '.aoP .aDj');
1398
+ }
1399
+
1400
+ getDiscardButton(): HTMLElement {
1401
+ return querySelector(this._element, '.gU .oh');
1402
+ }
1403
+
1404
+ getComposeID(): string {
1405
+ return this._composeID;
1406
+ }
1407
+
1408
+ getInitialMessageID(): ?string {
1409
+ return this._initialMessageId;
1410
+ }
1411
+
1412
+ // For use only when isUsingSyncAPI() is true — gets the draft ID
1413
+ // from the input that used to hold the hex message ID. Still does not
1414
+ // populate until first save.
1415
+ _getDraftIDfromForm(): ?string {
1416
+ const value =
1417
+ (this._messageIDElement && this._messageIDElement.value) || null;
1418
+ if (
1419
+ typeof value === 'string' &&
1420
+ value !== 'undefined' &&
1421
+ value !== 'null'
1422
+ ) {
1423
+ if (this._driver.isUsingSyncAPI()) {
1424
+ return value.replace('#', '').replace('msg-a:', '');
1425
+ } else {
1426
+ this._driver
1427
+ .getLogger()
1428
+ .error(new Error('Invalid draft id in element'), {
1429
+ value,
1430
+ });
1431
+ }
1432
+ }
1433
+ return null;
1434
+ }
1435
+
1436
+ _getMessageIDfromForm(): ?string {
1437
+ const value =
1438
+ (this._messageIDElement && this._messageIDElement.value) || null;
1439
+ if (
1440
+ typeof value === 'string' &&
1441
+ value !== 'undefined' &&
1442
+ value !== 'null'
1443
+ ) {
1444
+ if (this._driver.isUsingSyncAPI()) {
1445
+ return value.replace('#', ''); //annoyingly the hash is included
1446
+ } else {
1447
+ if (/^[0-9a-f]+$/i.test(value)) {
1448
+ return value;
1449
+ } else {
1450
+ this._driver
1451
+ .getLogger()
1452
+ .error(new Error('Invalid message id in element'), {
1453
+ value,
1454
+ });
1455
+ }
1456
+ }
1457
+ }
1458
+ return null;
1459
+ }
1460
+
1461
+ getMessageID(): ?string {
1462
+ return this._messageId;
1463
+ }
1464
+
1465
+ getTargetMessageID(): ?string {
1466
+ return this._targetMessageID;
1467
+ }
1468
+
1469
+ getThreadID(): ?string {
1470
+ return this._threadID;
1471
+ }
1472
+
1473
+ async getCurrentDraftID(): Promise<?string> {
1474
+ if (this._driver.isUsingSyncAPI()) {
1475
+ // This function is mostly a mirror of _getDraftIDimplementation, but
1476
+ // instead of waiting when finding out it's not saved, just returns null.
1477
+
1478
+ const draftID = this._getDraftIDfromForm();
1479
+ if (this._messageId) {
1480
+ return draftID;
1481
+ } else {
1482
+ const syncMessageId = this._getMessageIDfromForm();
1483
+ if (syncMessageId) {
1484
+ try {
1485
+ // If this succeeds, then the draft must exist on the server and we
1486
+ // can safely return the draft id we know.
1487
+ const gmailMessageId =
1488
+ await this._driver.getGmailMessageIdForSyncDraftId(syncMessageId);
1489
+ } catch (e) {
1490
+ // ignore error, it's probably that the draft isn't saved yet.
1491
+ return null;
1492
+ }
1493
+
1494
+ return draftID;
1495
+ }
1496
+ }
1497
+ } else {
1498
+ if (!this.getMessageID()) {
1499
+ return null;
1500
+ } else {
1501
+ return this.getDraftID();
1502
+ }
1503
+ }
1504
+ }
1505
+
1506
+ getDraftID(): Promise<?string> {
1507
+ let draftIDpromise = this._draftIDpromise;
1508
+ if (!draftIDpromise) {
1509
+ draftIDpromise = this._draftIDpromise = this._getDraftIDimplementation();
1510
+ }
1511
+ return draftIDpromise;
1512
+ }
1513
+
1514
+ async _getDraftIDimplementation(): Promise<?string> {
1515
+ if (this._driver.isUsingSyncAPI()) {
1516
+ const draftID = this._getDraftIDfromForm();
1517
+ // we want to keep the semantics that getDraftID doesn't return until
1518
+ // the draft is actually saved on Gmail's servers
1519
+ if (this._messageId) {
1520
+ // if we have a messageId that means there is a draft on the server
1521
+ return draftID;
1522
+ } else {
1523
+ // there may be a draft on the server, so let's find out
1524
+ const syncMessageId = this._getMessageIDfromForm();
1525
+ if (syncMessageId) {
1526
+ try {
1527
+ // If this succeeds, then the draft must exist on the server and we
1528
+ // can safely return the draft id we know.
1529
+ const gmailMessageId =
1530
+ await this._driver.getGmailMessageIdForSyncDraftId(syncMessageId);
1531
+ } catch (e) {
1532
+ // draft doesn't exist so we wait until it does
1533
+ await this._eventStream
1534
+ .filter(({ eventName }) => eventName === 'draftSaved')
1535
+ .beforeEnd(() => null)
1536
+ .map(() => this._getDraftIDfromForm())
1537
+ .take(1)
1538
+ .toPromise();
1539
+ }
1540
+
1541
+ return draftID;
1542
+ }
1543
+ }
1544
+ } else {
1545
+ let i = -1;
1546
+ let lastDebugData = null;
1547
+
1548
+ try {
1549
+ // If this compose view doesn't have a message id yet, wait until it gets
1550
+ // one or it's closed.
1551
+ if (!this._messageId) {
1552
+ await this._eventStream
1553
+ .filter((event) => event.eventName === 'messageIDChange')
1554
+ .beforeEnd(() => null)
1555
+ .take(1)
1556
+ .toPromise();
1557
+
1558
+ if (!this._messageId) {
1559
+ // The compose was closed before it got an id.
1560
+ return null;
1561
+ }
1562
+ }
1563
+
1564
+ // We make an AJAX request against gmail to find the draft ID for our
1565
+ // current message ID. However, our message ID can change before that
1566
+ // request finishes. If we fail to get our draft ID and we see that our
1567
+ // message ID has changed since we made the request, then we try again.
1568
+ let lastMessageId = null;
1569
+ // eslint-disable-next-line no-constant-condition
1570
+ while (true) {
1571
+ i++;
1572
+
1573
+ const messageId = this._messageId;
1574
+ if (!messageId) {
1575
+ throw new Error('Should not happen');
1576
+ }
1577
+ if (lastMessageId === messageId) {
1578
+ // It's possible that the server received a draft save request from us
1579
+ // already, causing the draft id lookup to fail, but we haven't gotten
1580
+ // the draft save response yet. Wait for that response to finish and
1581
+ // keep trying if it looks like that might be the case.
1582
+ if (this._draftSaving) {
1583
+ await this._eventStream
1584
+ .filter((event) => event.eventName === 'messageIDChange')
1585
+ .beforeEnd(() => null)
1586
+ .take(1)
1587
+ .toPromise();
1588
+ continue;
1589
+ }
1590
+
1591
+ // maaaaybe the draft is saving, but we failed to detect that.
1592
+ // Let's log whether things would've worked out a little in the future.
1593
+ setTimeout(async () => {
1594
+ const newMessageId = this._messageId;
1595
+ if (!newMessageId) {
1596
+ throw new Error('Should not happen');
1597
+ }
1598
+ const { draftID, debugData } =
1599
+ await this._driver.getDraftIDForMessageID(newMessageId, true);
1600
+ const err = new Error('Failed to read draft ID -- after check');
1601
+ this._driver.getLogger().error(err, {
1602
+ message: 'getDraftID error -- after check',
1603
+ messageIdChanged: messageId !== newMessageId,
1604
+ gotDraftID: draftID != null,
1605
+ debugData: draftID ? null : debugData,
1606
+ });
1607
+ }, 10 * 1000);
1608
+
1609
+ throw new Error('Failed to read draft ID');
1610
+ }
1611
+ lastMessageId = messageId;
1612
+
1613
+ const { draftID, debugData } =
1614
+ await this._driver.getDraftIDForMessageID(messageId);
1615
+ lastDebugData = debugData;
1616
+ if (draftID) {
1617
+ return draftID;
1618
+ }
1619
+ }
1620
+ } catch (err) {
1621
+ this._driver.getLogger().error(err, {
1622
+ message: 'getDraftID error',
1623
+ removedFromDOM: !document.contains(this._element),
1624
+ destroyed: this._destroyed,
1625
+ isFullscreen: this._isFullscreen,
1626
+ isStandalone: this._isStandalone,
1627
+ emailWasSent: this._emailWasSent,
1628
+ i,
1629
+ lastDebugData,
1630
+ });
1631
+ throw err;
1632
+ }
1633
+ }
1634
+ }
1635
+
1636
+ addManagedViewController(viewController: { destroy(): void }) {
1637
+ this._managedViewControllers.push(viewController);
1638
+ }
1639
+
1640
+ ensureGroupingIsOpen(type: string) {
1641
+ ensureGroupingIsOpen(this._element, type);
1642
+ }
1643
+
1644
+ ensureAppButtonToolbarsAreClosed(): void {
1645
+ ensureAppButtonToolbarsAreClosed(this._element);
1646
+ }
1647
+
1648
+ isMinimized(): boolean {
1649
+ const element = this.getElement();
1650
+ const bodyElement = this.getMaybeBodyElement();
1651
+ const bodyContainer = find(element.children, (child) =>
1652
+ child.contains(bodyElement)
1653
+ );
1654
+ if (!bodyContainer) {
1655
+ if (!hasReportedMissingBody) {
1656
+ hasReportedMissingBody = true;
1657
+ this._driver
1658
+ .getLogger()
1659
+ .error(new Error('isMinimized failed to find bodyContainer'), {
1660
+ bodyElement: !!bodyElement,
1661
+ hasMessageIDElement: !!this._messageIDElement,
1662
+ ended: (this._eventStream: any).ended,
1663
+ bodyElStillInCompose: this._element.contains(this._seenBodyElement),
1664
+ seenBodyElHtml: censorHTMLstring(this._seenBodyElement.outerHTML),
1665
+ composeHtml: censorHTMLstring(element.outerHTML),
1666
+ });
1667
+ }
1668
+ return false;
1669
+ }
1670
+
1671
+ return bodyContainer.style.display !== '';
1672
+ }
1673
+
1674
+ setMinimized(minimized: boolean) {
1675
+ if (minimized !== this.isMinimized()) {
1676
+ if (this._isInlineReplyForm)
1677
+ throw new Error('Not implemented for inline compose views');
1678
+ const minimizeButton = querySelector(this._element, '.Hm > img');
1679
+ simulateClick(minimizeButton);
1680
+ }
1681
+ }
1682
+
1683
+ setFullscreen(fullscreen: boolean) {
1684
+ if (fullscreen !== this.isFullscreen()) {
1685
+ if (this._isInlineReplyForm)
1686
+ throw new Error('Not implemented for inline compose views');
1687
+ const fullscreenButton = querySelector(
1688
+ this._element,
1689
+ '.Hm > img:nth-of-type(2)'
1690
+ );
1691
+ simulateClick(fullscreenButton);
1692
+ }
1693
+ }
1694
+
1695
+ setTitleBarColor(color: string): () => void {
1696
+ const buttonParent = querySelector(
1697
+ this._element,
1698
+ '.nH.Hy.aXJ table.cf.Ht td.Hm'
1699
+ );
1700
+ const elementsToModify = [
1701
+ querySelector(this._element, '.nH.Hy.aXJ .pi > .l.o'),
1702
+ querySelector(this._element, '.nH.Hy.aXJ .l.m'),
1703
+ querySelector(this._element, '.nH.Hy.aXJ .l.m > .l.n'),
1704
+ ];
1705
+
1706
+ buttonParent.classList.add('inboxsdk__compose_customTitleBarColor');
1707
+
1708
+ elementsToModify.forEach((el) => {
1709
+ el.style.backgroundColor = color;
1710
+ });
1711
+
1712
+ return () => {
1713
+ buttonParent.classList.remove('inboxsdk__compose_customTitleBarColor');
1714
+
1715
+ elementsToModify.forEach((el) => {
1716
+ el.style.backgroundColor = '';
1717
+ });
1718
+ };
1719
+ }
1720
+
1721
+ setTitleBarText(text: string): () => void {
1722
+ if (this.isInlineReplyForm()) {
1723
+ throw new Error(
1724
+ 'setTitleBarText() is not supported on inline compose views'
1725
+ );
1726
+ }
1727
+
1728
+ const titleBarTable = querySelector(
1729
+ this._element,
1730
+ '.nH.Hy.aXJ table.cf.Ht'
1731
+ );
1732
+
1733
+ if (
1734
+ titleBarTable.classList.contains(
1735
+ 'inboxsdk__compose_hasCustomTitleBarText'
1736
+ )
1737
+ ) {
1738
+ throw new Error(
1739
+ 'Custom title bar text is already registered for this compose view'
1740
+ );
1741
+ }
1742
+
1743
+ const titleTextParent = querySelector(
1744
+ titleBarTable,
1745
+ 'div.Hp'
1746
+ ).parentElement;
1747
+ if (!(titleTextParent instanceof HTMLElement)) {
1748
+ throw new Error('Could not locate title bar text parent');
1749
+ }
1750
+
1751
+ titleBarTable.classList.add('inboxsdk__compose_hasCustomTitleBarText');
1752
+ titleTextParent.classList.add('inboxsdk__compose_nativeTitleBarText');
1753
+
1754
+ const customTitleText = document.createElement('td');
1755
+ customTitleText.classList.add('inboxsdk__compose_customTitleBarText');
1756
+ customTitleText.innerHTML = autoHtml`
1757
+ <div class="Hp">
1758
+ <h2 class="a3E">
1759
+ <div class="aYF">${text}</div>
1760
+ </h2>
1761
+ </div>
1762
+ `;
1763
+
1764
+ titleTextParent.insertAdjacentElement('afterend', customTitleText);
1765
+
1766
+ return () => {
1767
+ customTitleText.remove();
1768
+
1769
+ titleBarTable.classList.remove('inboxsdk__compose_hasCustomTitleBarText');
1770
+ titleTextParent.classList.remove('inboxsdk__compose_nativeTitleBarText');
1771
+ };
1772
+ }
1773
+
1774
+ _triggerDraftSave() {
1775
+ if (this._isTriggeringADraftSavePending) {
1776
+ return;
1777
+ } else {
1778
+ this._isTriggeringADraftSavePending = true;
1779
+
1780
+ // Done asynchronously with setTimeout because if it's done synchronously
1781
+ // or after an asap step after an inline compose view's creation, Gmail
1782
+ // interprets the fake keypress and decides to add a '¾' character.
1783
+ Kefir.later(0)
1784
+ .takeUntilBy(this._stopper)
1785
+ .onValue(() => {
1786
+ this._isTriggeringADraftSavePending = false;
1787
+
1788
+ const body = this.getMaybeBodyElement();
1789
+ if (body) {
1790
+ const unsilence = this._driver
1791
+ .getPageCommunicator()
1792
+ .silenceGmailErrorsForAMoment();
1793
+ try {
1794
+ simulateKey(body, 190, 0);
1795
+ } finally {
1796
+ unsilence();
1797
+ }
1798
+ }
1799
+ });
1800
+ }
1801
+ }
1802
+
1803
+ // If this compose is a reply, then this gets the message ID of the message
1804
+ // we're replying to.
1805
+ _getTargetMessageID(): ?string {
1806
+ const input: ?HTMLInputElement = (this._element.querySelector(
1807
+ 'input[name="rm"]'
1808
+ ): any);
1809
+ return input &&
1810
+ typeof input.value === 'string' &&
1811
+ input.value != 'undefined'
1812
+ ? input.value.replace('#', '')
1813
+ : null;
1814
+ }
1815
+
1816
+ _getThreadID(): ?string {
1817
+ const targetID = this.getTargetMessageID();
1818
+ try {
1819
+ return targetID ? this._driver.getThreadIDForMessageID(targetID) : null;
1820
+ } catch (err) {
1821
+ this._driver.getLogger().error(err);
1822
+ return null;
1823
+ }
1824
+ }
1825
+
1826
+ getElement(): HTMLElement {
1827
+ return this._element;
1828
+ }
1829
+
1830
+ isFullscreen(): boolean {
1831
+ return this._isFullscreen;
1832
+ }
1833
+
1834
+ getLastSelectionRange(): ?Range {
1835
+ // The selection range can become invalid if the compose view has become expanded or
1836
+ // minimized since the range was set.
1837
+ const range = this._lastSelectionRange;
1838
+ if (
1839
+ range &&
1840
+ !this.getBodyElement().contains(range.commonAncestorContainer)
1841
+ ) {
1842
+ this._lastSelectionRange = undefined;
1843
+ }
1844
+ return this._lastSelectionRange;
1845
+ }
1846
+
1847
+ setLastSelectionRange(lastSelectionRange: ?Range) {
1848
+ this._lastSelectionRange = lastSelectionRange;
1849
+ }
1850
+
1851
+ registerRequestModifier(
1852
+ modifier: (composeParams: { body: string }) =>
1853
+ | { body: string }
1854
+ | Promise<{ body: string }>
1855
+ ) {
1856
+ const keyId = this._driver.isUsingSyncAPI()
1857
+ ? this._getDraftIDfromForm()
1858
+ : this.getComposeID();
1859
+
1860
+ if (!keyId) throw new Error('keyId should be set here');
1861
+
1862
+ const modifierId = this._driver
1863
+ .getPageCommunicator()
1864
+ .registerComposeRequestModifier(keyId, this._driver.getAppId());
1865
+ this._requestModifiers[modifierId] = modifier;
1866
+ this._startListeningForModificationRequests();
1867
+ this._stopper.onValue(() => {
1868
+ this._driver
1869
+ .getPageCommunicator()
1870
+ .unregisterComposeRequestModifier(keyId, modifierId);
1871
+ });
1872
+ }
1873
+
1874
+ _startListeningForModificationRequests() {
1875
+ if (this._isListeningToAjaxInterceptStream) {
1876
+ return;
1877
+ }
1878
+
1879
+ const keyId = this._driver.isUsingSyncAPI()
1880
+ ? this._getDraftIDfromForm()
1881
+ : this.getComposeID();
1882
+
1883
+ if (!keyId) throw new Error('keyId should be set here');
1884
+
1885
+ this._driver
1886
+ .getPageCommunicator()
1887
+ .ajaxInterceptStream.filter(
1888
+ ({ type, composeid, draftID, modifierId }) =>
1889
+ type === 'inboxSDKmodifyComposeRequest' &&
1890
+ (composeid === keyId || keyId === draftID) &&
1891
+ Boolean(this._requestModifiers[modifierId])
1892
+ )
1893
+ .takeUntilBy(this._stopper)
1894
+ .onValue(({ modifierId, composeParams }) => {
1895
+ if (this._driver.getLogger().shouldTrackEverything()) {
1896
+ this._driver.getLogger().eventSite('inboxSDKmodifyComposeRequest');
1897
+ }
1898
+
1899
+ const modifier = this._requestModifiers[modifierId];
1900
+ const result = new Promise((resolve) =>
1901
+ resolve(modifier(composeParams))
1902
+ );
1903
+
1904
+ result
1905
+ .then((newComposeParams) =>
1906
+ this._driver
1907
+ .getPageCommunicator()
1908
+ .modifyComposeRequest(
1909
+ keyId,
1910
+ modifierId,
1911
+ newComposeParams || composeParams
1912
+ )
1913
+ )
1914
+ .then((x) => {
1915
+ if (this._driver.getLogger().shouldTrackEverything()) {
1916
+ this._driver.getLogger().eventSite('composeRequestModified');
1917
+ }
1918
+ return x;
1919
+ })
1920
+ .catch((err) => {
1921
+ this._driver
1922
+ .getPageCommunicator()
1923
+ .modifyComposeRequest(keyId, modifierId, composeParams);
1924
+ this._driver.getLogger().error(err);
1925
+ });
1926
+ });
1927
+
1928
+ this._isListeningToAjaxInterceptStream = true;
1929
+ }
1930
+
1931
+ setupLinkPopOvers(): void {
1932
+ if (!this._hasSetupLinkPopOvers) {
1933
+ this._hasSetupLinkPopOvers = true;
1934
+ this._eventStream.plug(setupLinkPopOvers(this));
1935
+ }
1936
+ }
1937
+ }
1938
+ export default ud.defn(module, GmailComposeView);