@inboxsdk/core 1.1.6 → 1.1.7

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 (483) hide show
  1. package/background.js +1 -0
  2. package/inboxsdk.js +31 -36
  3. package/inboxsdk.js.map +1 -1
  4. package/package.json +1 -1
  5. package/pageWorld.js +1 -1
  6. package/pageWorld.js.map +1 -1
  7. package/src/inboxsdk-js/header.d.ts +19 -0
  8. package/src/inboxsdk-js/header.d.ts.map +1 -0
  9. package/src/inboxsdk-js/header.js +1 -1
  10. package/src/inboxsdk.d.ts +8 -3
  11. package/src/injected-js/gmail/constants.d.ts +1 -1
  12. package/src/injected-js/gmail/constants.d.ts.map +1 -1
  13. package/src/injected-js/gmail/setup-gmail-interceptor.d.ts +3 -4
  14. package/src/injected-js/gmail/setup-gmail-interceptor.d.ts.map +1 -0
  15. package/src/injected-js/gmail/setup-gmail-interceptor.js +896 -896
  16. package/src/injected-js/gmail/sync-compose-processor-20220909.d.ts +1 -1
  17. package/src/injected-js/gmail/sync-compose-processor-20220909.d.ts.map +1 -1
  18. package/src/injected-js/gmail/sync-compose-processor.d.ts +3 -3
  19. package/src/injected-js/gmail/sync-compose-request-processor.d.ts.map +1 -1
  20. package/src/injected-js/gmail/sync-compose-request-processor.js +0 -1
  21. package/src/injected-js/gmail/thread-identifier/click-and-get-popup-url.d.ts +2 -0
  22. package/src/injected-js/gmail/thread-identifier/click-and-get-popup-url.d.ts.map +1 -0
  23. package/src/injected-js/gmail/thread-identifier/click-and-get-popup-url.js +66 -78
  24. package/src/injected-js/gmail/thread-identifier/index.d.ts +3 -0
  25. package/src/injected-js/gmail/thread-identifier/index.d.ts.map +1 -0
  26. package/src/injected-js/gmail/thread-identifier/index.js +100 -98
  27. package/src/injected-js/gmail/thread-identifier/thread-row-parser.d.ts +7 -0
  28. package/src/injected-js/gmail/thread-identifier/thread-row-parser.d.ts.map +1 -0
  29. package/src/injected-js/gmail/thread-identifier/thread-row-parser.js +51 -61
  30. package/src/injected-js/main.d.ts +2 -0
  31. package/src/injected-js/main.d.ts.map +1 -0
  32. package/src/injected-js/main.js +44 -43
  33. package/src/injected-js/message-metadata-holder.d.ts +7 -0
  34. package/src/injected-js/message-metadata-holder.d.ts.map +1 -0
  35. package/src/injected-js/message-metadata-holder.js +89 -97
  36. package/src/injected-js/setup-data-exposer.d.ts +2 -0
  37. package/src/injected-js/setup-data-exposer.d.ts.map +1 -0
  38. package/src/injected-js/setup-data-exposer.js +126 -118
  39. package/src/injected-js/setup-error-silencer.d.ts +2 -0
  40. package/src/injected-js/setup-error-silencer.d.ts.map +1 -0
  41. package/src/injected-js/setup-error-silencer.js +16 -24
  42. package/src/injected-js/setup-event-reemitter.d.ts +2 -0
  43. package/src/injected-js/setup-event-reemitter.d.ts.map +1 -0
  44. package/src/injected-js/setup-event-reemitter.js +46 -59
  45. package/src/injected-js/setupInboxCustomViewLinkFixer.d.ts +2 -0
  46. package/src/injected-js/setupInboxCustomViewLinkFixer.d.ts.map +1 -0
  47. package/src/injected-js/setupInboxCustomViewLinkFixer.js +24 -26
  48. package/src/injected-js/setupPushStateListener.d.ts +2 -0
  49. package/src/injected-js/setupPushStateListener.d.ts.map +1 -0
  50. package/src/injected-js/setupPushStateListener.js +14 -23
  51. package/src/injected-js/xhr-helper.d.ts +2 -0
  52. package/src/injected-js/xhr-helper.d.ts.map +1 -0
  53. package/src/injected-js/xhr-helper.js +73 -83
  54. package/src/injected-js/xhr-proxy-factory.d.ts +97 -0
  55. package/src/injected-js/xhr-proxy-factory.d.ts.map +1 -0
  56. package/src/injected-js/xhr-proxy-factory.js +503 -451
  57. package/src/platform-implementation-js/constants/router.d.ts +37 -5
  58. package/src/platform-implementation-js/constants/router.d.ts.map +1 -0
  59. package/src/platform-implementation-js/constants/router.js +57 -60
  60. package/src/platform-implementation-js/constants/toolbars.d.ts +2 -0
  61. package/src/platform-implementation-js/constants/toolbars.d.ts.map +1 -0
  62. package/src/platform-implementation-js/constants/toolbars.js +4 -11
  63. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-toolbar-button-for-app.d.ts.map +1 -1
  64. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/add-toolbar-button-for-app.js +0 -1
  65. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/get-url-object.d.ts.map +1 -1
  66. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/get-url-object.js +0 -1
  67. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/getSyncThreadForOldGmailThreadId.d.ts.map +1 -1
  68. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/getSyncThreadForOldGmailThreadId.js +0 -1
  69. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/getSyncThreadFromSyncThreadId.d.ts +4 -6
  70. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/getSyncThreadFromSyncThreadId.d.ts.map +1 -0
  71. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/getSyncThreadFromSyncThreadId.js +55 -62
  72. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/gmail-load-event.d.ts.map +1 -1
  73. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/gmail-load-event.js +0 -1
  74. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/goto-view.d.ts.map +1 -1
  75. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/goto-view.js +0 -1
  76. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/setup-route-view-driver-stream.d.ts.map +1 -1
  77. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/setup-route-view-driver-stream.js +4 -5
  78. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/thread-row-identifier.d.ts.map +1 -1
  79. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/thread-row-identifier.js +4 -9
  80. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-events.d.ts.map +1 -1
  81. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/track-events.js +1 -0
  82. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/user-info.d.ts +2 -1
  83. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/user-info.d.ts.map +1 -1
  84. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/user-info.js +1 -1
  85. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver.d.ts +4 -3
  86. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver.d.ts.map +1 -1
  87. package/src/platform-implementation-js/dom-driver/gmail/make-xhr-interceptor.d.ts.map +1 -1
  88. package/src/platform-implementation-js/dom-driver/gmail/make-xhr-interceptor.js +0 -1
  89. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/index.d.ts +19 -6
  90. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/index.d.ts.map +1 -0
  91. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/index.js +75 -80
  92. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/add-companion-global-icon-area.d.ts +5 -0
  93. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/add-companion-global-icon-area.d.ts.map +1 -0
  94. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/add-companion-global-icon-area.js +13 -22
  95. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/add-companion-thread-icon-area.d.ts +5 -0
  96. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/add-companion-thread-icon-area.d.ts.map +1 -0
  97. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/add-companion-thread-icon-area.js +18 -26
  98. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/add-to-icon-area.d.ts +5 -0
  99. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/add-to-icon-area.d.ts.map +1 -0
  100. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/add-to-icon-area.js +13 -30
  101. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/index.d.ts +44 -0
  102. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/index.d.ts.map +1 -0
  103. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/primary/index.js +681 -601
  104. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-toolbar-button-view/monitor-top-banner-size-and-react.d.ts +2 -0
  105. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-toolbar-button-view/monitor-top-banner-size-and-react.d.ts.map +1 -0
  106. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-toolbar-button-view/monitor-top-banner-size-and-react.js +23 -24
  107. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-toolbar-button-view.d.ts +19 -3
  108. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-toolbar-button-view.d.ts.map +1 -0
  109. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-toolbar-button-view.js +156 -150
  110. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-attachment-area-view.d.ts +20 -0
  111. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-attachment-area-view.d.ts.map +1 -0
  112. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-attachment-area-view.js +101 -96
  113. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-attachment-card-view.d.ts +40 -0
  114. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-attachment-card-view.d.ts.map +1 -0
  115. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-attachment-card-view.js +287 -265
  116. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-collapsible-section-view.d.ts +61 -0
  117. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-collapsible-section-view.d.ts.map +1 -0
  118. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-collapsible-section-view.js +689 -524
  119. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-button.d.ts +5 -0
  120. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-button.d.ts.map +1 -0
  121. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-button.js +124 -118
  122. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-compose-notice.d.ts +15 -0
  123. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-compose-notice.d.ts.map +1 -0
  124. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-compose-notice.js +47 -51
  125. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-inner-sidebar.d.ts +8 -0
  126. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-inner-sidebar.d.ts.map +1 -0
  127. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-inner-sidebar.js +8 -16
  128. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-outer-sidebar.d.ts +8 -0
  129. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-outer-sidebar.d.ts.map +1 -0
  130. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-outer-sidebar.js +23 -31
  131. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-recipient-row.d.ts +4 -0
  132. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-recipient-row.d.ts.map +1 -0
  133. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-recipient-row.js +61 -66
  134. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-tooltip-to-button.d.ts +6 -0
  135. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-tooltip-to-button.d.ts.map +1 -0
  136. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/add-tooltip-to-button.js +64 -48
  137. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/ensure-app-button-toolbars-are-closed.d.ts +2 -0
  138. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/ensure-app-button-toolbars-are-closed.d.ts.map +1 -0
  139. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/ensure-app-button-toolbars-are-closed.js +10 -17
  140. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/ensure-grouping-is-open.d.ts +2 -0
  141. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/ensure-grouping-is-open.d.ts.map +1 -0
  142. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/ensure-grouping-is-open.js +14 -23
  143. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/focus.d.ts +3 -0
  144. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/focus.d.ts.map +1 -0
  145. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/focus.js +13 -16
  146. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/from-manager.d.ts +7 -0
  147. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/from-manager.d.ts.map +1 -0
  148. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/from-manager.js +57 -59
  149. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-additional-action-toolbar.d.ts +3 -0
  150. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-additional-action-toolbar.d.ts.map +1 -0
  151. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-additional-action-toolbar.js +49 -49
  152. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-address-changes-stream.d.ts +4 -0
  153. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-address-changes-stream.d.ts.map +1 -0
  154. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-address-changes-stream.js +89 -89
  155. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-address-information-extractor.d.ts +1 -1
  156. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-address-information-extractor.d.ts.map +1 -1
  157. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-body-changes-stream.d.ts +4 -0
  158. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-body-changes-stream.d.ts.map +1 -0
  159. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-body-changes-stream.js +13 -21
  160. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-formatting-area-offset-left.d.ts +3 -0
  161. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-formatting-area-offset-left.d.ts.map +1 -0
  162. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-formatting-area-offset-left.js +16 -23
  163. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-minimized-stream.d.ts +4 -0
  164. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-minimized-stream.d.ts.map +1 -0
  165. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-minimized-stream.js +14 -22
  166. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-recipients.d.ts +1 -1
  167. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-recipients.d.ts.map +1 -1
  168. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-response-type-changes-stream.d.ts +4 -0
  169. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-response-type-changes-stream.d.ts.map +1 -0
  170. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/get-response-type-changes-stream.js +23 -29
  171. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/insert-link-into-body.d.ts +3 -0
  172. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/insert-link-into-body.d.ts.map +1 -0
  173. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/insert-link-into-body.js +17 -25
  174. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/manage-button-grouping.d.ts +4 -0
  175. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/manage-button-grouping.d.ts.map +1 -0
  176. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/manage-button-grouping.js +317 -252
  177. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/monitor-selection-range.d.ts +3 -0
  178. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/monitor-selection-range.d.ts.map +1 -0
  179. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/monitor-selection-range.js +22 -18
  180. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/override-edit-subject.d.ts +4 -0
  181. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/override-edit-subject.d.ts.map +1 -0
  182. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/override-edit-subject.js +57 -50
  183. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/position-formatting-toolbar.d.ts +3 -0
  184. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/position-formatting-toolbar.d.ts.map +1 -0
  185. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/position-formatting-toolbar.js +18 -20
  186. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/size-fixer.d.ts +3 -0
  187. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/size-fixer.d.ts.map +1 -0
  188. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/size-fixer.js +114 -113
  189. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/update-insert-more-area-left.d.ts +3 -0
  190. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/update-insert-more-area-left.d.ts.map +1 -0
  191. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view/update-insert-more-area-left.js +15 -18
  192. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view.d.ts +189 -118
  193. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view.d.ts.map +1 -0
  194. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-compose-view.js +1480 -1333
  195. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view/attachment-icon.d.ts +1 -2
  196. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view/attachment-icon.d.ts.map +1 -1
  197. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view/attachment-icon.js +1 -2
  198. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view/get-updated-contact.d.ts +3 -0
  199. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view/get-updated-contact.d.ts.map +1 -0
  200. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view/get-updated-contact.js +69 -70
  201. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view.d.ts +67 -6
  202. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view.d.ts.map +1 -0
  203. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-message-view.js +715 -637
  204. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-route-view/gmail-route-processor.d.ts +44 -6
  205. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-route-view/gmail-route-processor.d.ts.map +1 -0
  206. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-route-view/gmail-route-processor.js +100 -101
  207. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-route-view/gmail-route-view.d.ts +72 -3
  208. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-route-view/gmail-route-view.d.ts.map +1 -0
  209. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-route-view/gmail-route-view.js +502 -438
  210. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-row-list-view.d.ts +39 -8
  211. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-row-list-view.d.ts.map +1 -0
  212. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-row-list-view.js +229 -211
  213. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-row-view.d.ts +117 -5
  214. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-row-view.d.ts.map +1 -0
  215. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-row-view.js +938 -821
  216. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-sidebar-view/add-icon-area.d.ts +5 -0
  217. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-sidebar-view/add-icon-area.d.ts.map +1 -0
  218. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-sidebar-view/add-icon-area.js +66 -61
  219. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-sidebar-view.d.ts +18 -0
  220. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-sidebar-view.d.ts.map +1 -0
  221. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-sidebar-view.js +520 -457
  222. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-view/width-manager.d.ts +7 -0
  223. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-view/width-manager.d.ts.map +1 -0
  224. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-view/width-manager.js +24 -27
  225. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-view.d.ts +69 -7
  226. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-view.d.ts.map +1 -0
  227. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-view.js +646 -523
  228. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-toolbar-view.d.ts +58 -11
  229. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-toolbar-view.d.ts.map +1 -0
  230. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-toolbar-view.js +436 -383
  231. package/src/platform-implementation-js/dom-driver/gmail/views/native-gmail-nav-item-view.d.ts +35 -7
  232. package/src/platform-implementation-js/dom-driver/gmail/views/native-gmail-nav-item-view.d.ts.map +1 -0
  233. package/src/platform-implementation-js/dom-driver/gmail/views/native-gmail-nav-item-view.js +265 -235
  234. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-accessory-button-view.d.ts +2 -0
  235. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-accessory-button-view.d.ts.map +1 -1
  236. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-accessory-button-view.js +4 -0
  237. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-parent-accessory-button-view.d.ts +2 -0
  238. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-parent-accessory-button-view.d.ts.map +1 -1
  239. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/create-parent-accessory-button-view.js +4 -0
  240. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/inbox-dropdown-button-view.d.ts +7 -0
  241. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/inbox-dropdown-button-view.d.ts.map +1 -0
  242. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/inbox-dropdown-button-view.js +22 -30
  243. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/modal-button-view.d.ts +4 -0
  244. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/modal-button-view.d.ts.map +1 -1
  245. package/src/platform-implementation-js/dom-driver/gmail/widgets/buttons/modal-button-view.js +6 -0
  246. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-action-button-view.d.ts +11 -0
  247. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-action-button-view.d.ts.map +1 -0
  248. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-action-button-view.js +35 -41
  249. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-label-view.d.ts +18 -0
  250. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-label-view.d.ts.map +1 -0
  251. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-label-view.js +96 -97
  252. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-mole-view-driver.d.ts +18 -15
  253. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-mole-view-driver.d.ts.map +1 -0
  254. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-mole-view-driver.js +170 -170
  255. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-tooltip-view.d.ts +47 -0
  256. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-tooltip-view.d.ts.map +1 -0
  257. package/src/platform-implementation-js/dom-driver/gmail/widgets/gmail-tooltip-view.js +325 -279
  258. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-backdrop.d.ts +16 -0
  259. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-backdrop.d.ts.map +1 -0
  260. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-backdrop.js +56 -61
  261. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-drawer-view.d.ts +31 -3
  262. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-drawer-view.d.ts.map +1 -0
  263. package/src/platform-implementation-js/dom-driver/inbox/views/inbox-drawer-view.js +275 -252
  264. package/src/platform-implementation-js/driver-common/compose/getDiscardStream.d.ts +6 -0
  265. package/src/platform-implementation-js/driver-common/compose/getDiscardStream.d.ts.map +1 -0
  266. package/src/platform-implementation-js/driver-common/compose/getDiscardStream.js +27 -32
  267. package/src/platform-implementation-js/driver-common/compose/getPresendingStream.d.ts +7 -0
  268. package/src/platform-implementation-js/driver-common/compose/getPresendingStream.d.ts.map +1 -0
  269. package/src/platform-implementation-js/driver-common/compose/getPresendingStream.js +45 -43
  270. package/src/platform-implementation-js/driver-common/getGmailMessageIdForSyncMessageId.d.ts +5 -6
  271. package/src/platform-implementation-js/driver-common/getGmailMessageIdForSyncMessageId.d.ts.map +1 -0
  272. package/src/platform-implementation-js/driver-common/getGmailMessageIdForSyncMessageId.js +11 -19
  273. package/src/platform-implementation-js/driver-common/getGmailThreadIdForRfcMessageId.d.ts +5 -6
  274. package/src/platform-implementation-js/driver-common/getGmailThreadIdForRfcMessageId.d.ts.map +1 -0
  275. package/src/platform-implementation-js/driver-common/getGmailThreadIdForRfcMessageId.js +39 -48
  276. package/src/platform-implementation-js/driver-common/getRfcMessageIdForSyncMessageId.d.ts +5 -0
  277. package/src/platform-implementation-js/driver-common/getRfcMessageIdForSyncMessageId.d.ts.map +1 -0
  278. package/src/platform-implementation-js/driver-common/getRfcMessageIdForSyncMessageId.js +12 -20
  279. package/src/platform-implementation-js/driver-common/getThreadIdFromMessageId.d.ts +5 -0
  280. package/src/platform-implementation-js/driver-common/getThreadIdFromMessageId.d.ts.map +1 -0
  281. package/src/platform-implementation-js/driver-common/getThreadIdFromMessageId.js +11 -19
  282. package/src/platform-implementation-js/driver-common/inboxAjax.d.ts +4 -0
  283. package/src/platform-implementation-js/driver-common/inboxAjax.d.ts.map +1 -0
  284. package/src/platform-implementation-js/driver-common/inboxAjax.js +5 -13
  285. package/src/platform-implementation-js/driver-common/requestGmailThread.d.ts +4 -0
  286. package/src/platform-implementation-js/driver-common/requestGmailThread.d.ts.map +1 -0
  287. package/src/platform-implementation-js/driver-common/requestGmailThread.js +22 -32
  288. package/src/platform-implementation-js/driver-common/sidebar/AppSidebar.d.ts +50 -0
  289. package/src/platform-implementation-js/driver-common/sidebar/AppSidebar.d.ts.map +1 -0
  290. package/src/platform-implementation-js/driver-common/sidebar/AppSidebar.js +228 -279
  291. package/src/platform-implementation-js/driver-common/sidebar/ContentPanelViewDriver.d.ts +25 -1
  292. package/src/platform-implementation-js/driver-common/sidebar/ContentPanelViewDriver.d.ts.map +1 -0
  293. package/src/platform-implementation-js/driver-common/sidebar/ContentPanelViewDriver.js +142 -147
  294. package/src/platform-implementation-js/driver-interfaces/compose-view-driver.d.ts +106 -133
  295. package/src/platform-implementation-js/driver-interfaces/compose-view-driver.d.ts.map +1 -0
  296. package/src/platform-implementation-js/driver-interfaces/compose-view-driver.js +1 -1
  297. package/src/platform-implementation-js/driver-interfaces/driver.d.ts +31 -139
  298. package/src/platform-implementation-js/driver-interfaces/driver.d.ts.map +1 -0
  299. package/src/platform-implementation-js/driver-interfaces/driver.js +1 -1
  300. package/src/platform-implementation-js/driver-interfaces/message-view-driver.d.ts +44 -0
  301. package/src/platform-implementation-js/driver-interfaces/message-view-driver.d.ts.map +1 -0
  302. package/src/platform-implementation-js/driver-interfaces/message-view-driver.js +1 -5
  303. package/src/platform-implementation-js/driver-interfaces/mole-view-driver.d.ts +18 -20
  304. package/src/platform-implementation-js/driver-interfaces/mole-view-driver.d.ts.map +1 -0
  305. package/src/platform-implementation-js/driver-interfaces/mole-view-driver.js +1 -1
  306. package/src/platform-implementation-js/driver-interfaces/route-view-driver.d.ts +19 -0
  307. package/src/platform-implementation-js/driver-interfaces/route-view-driver.d.ts.map +1 -0
  308. package/src/platform-implementation-js/driver-interfaces/route-view-driver.js +1 -1
  309. package/src/platform-implementation-js/driver-interfaces/thread-row-view-driver.d.ts +11 -0
  310. package/src/platform-implementation-js/driver-interfaces/thread-row-view-driver.d.ts.map +1 -0
  311. package/src/platform-implementation-js/driver-interfaces/thread-row-view-driver.js +1 -1
  312. package/src/platform-implementation-js/lib/css-selector-escape.d.ts +2 -0
  313. package/src/platform-implementation-js/lib/css-selector-escape.d.ts.map +1 -0
  314. package/src/platform-implementation-js/lib/css-selector-escape.js +6 -12
  315. package/src/platform-implementation-js/lib/delay-asap.d.ts +1 -1
  316. package/src/platform-implementation-js/lib/delay-asap.d.ts.map +1 -1
  317. package/src/platform-implementation-js/lib/delay-asap.js +0 -2
  318. package/src/platform-implementation-js/lib/dom/get-selection.d.ts +3 -0
  319. package/src/platform-implementation-js/lib/dom/get-selection.d.ts.map +1 -0
  320. package/src/platform-implementation-js/lib/dom/get-selection.js +22 -24
  321. package/src/platform-implementation-js/lib/dom/insert-html-at-cursor.d.ts +3 -0
  322. package/src/platform-implementation-js/lib/dom/insert-html-at-cursor.d.ts.map +1 -0
  323. package/src/platform-implementation-js/lib/dom/insert-html-at-cursor.js +78 -75
  324. package/src/platform-implementation-js/lib/dom/is-node-in-range.d.ts +2 -0
  325. package/src/platform-implementation-js/lib/dom/is-node-in-range.d.ts.map +1 -0
  326. package/src/platform-implementation-js/lib/dom/is-node-in-range.js +12 -17
  327. package/src/platform-implementation-js/lib/dom/make-element-stream-merger.d.ts.map +1 -1
  328. package/src/platform-implementation-js/lib/dom/set-css.d.ts +2 -0
  329. package/src/platform-implementation-js/lib/dom/set-css.d.ts.map +1 -0
  330. package/src/platform-implementation-js/lib/dom/set-css.js +18 -23
  331. package/src/platform-implementation-js/lib/dom/set-value-and-dispatch-event.d.ts +2 -0
  332. package/src/platform-implementation-js/lib/dom/set-value-and-dispatch-event.d.ts.map +1 -0
  333. package/src/platform-implementation-js/lib/dom/set-value-and-dispatch-event.js +6 -12
  334. package/src/platform-implementation-js/lib/dom/simulate-drag-and-drop.d.ts +4 -0
  335. package/src/platform-implementation-js/lib/dom/simulate-drag-and-drop.d.ts.map +1 -0
  336. package/src/platform-implementation-js/lib/dom/simulate-drag-and-drop.js +84 -93
  337. package/src/platform-implementation-js/lib/extract-contact-from-email-contact-string.d.ts +1 -1
  338. package/src/platform-implementation-js/lib/extract-contact-from-email-contact-string.d.ts.map +1 -1
  339. package/src/platform-implementation-js/lib/handle-compose-link-chips.d.ts +4 -0
  340. package/src/platform-implementation-js/lib/handle-compose-link-chips.d.ts.map +1 -0
  341. package/src/platform-implementation-js/lib/handle-compose-link-chips.js +106 -97
  342. package/src/platform-implementation-js/lib/inject-script-EMBEDDED.d.ts.map +1 -1
  343. package/src/platform-implementation-js/lib/inject-script-EMBEDDED.js +1 -1
  344. package/src/platform-implementation-js/lib/insert-link-chip-into-body.d.ts +4 -0
  345. package/src/platform-implementation-js/lib/insert-link-chip-into-body.d.ts.map +1 -0
  346. package/src/platform-implementation-js/lib/insert-link-chip-into-body.js +32 -39
  347. package/src/platform-implementation-js/lib/logger.d.ts +1 -0
  348. package/src/platform-implementation-js/lib/logger.d.ts.map +1 -1
  349. package/src/platform-implementation-js/lib/parseParamsFromRouteID.d.ts +2 -0
  350. package/src/platform-implementation-js/lib/parseParamsFromRouteID.d.ts.map +1 -0
  351. package/src/platform-implementation-js/lib/parseParamsFromRouteID.js +12 -18
  352. package/src/platform-implementation-js/lib/populateRouteID.d.ts +2 -5
  353. package/src/platform-implementation-js/lib/populateRouteID.d.ts.map +1 -0
  354. package/src/platform-implementation-js/lib/populateRouteID.js +16 -21
  355. package/src/platform-implementation-js/lib/react/ElementContainer.d.ts +15 -0
  356. package/src/platform-implementation-js/lib/react/ElementContainer.d.ts.map +1 -0
  357. package/src/platform-implementation-js/lib/react/ElementContainer.js +24 -36
  358. package/src/platform-implementation-js/lib/routeIDmatchesHash.d.ts +2 -4
  359. package/src/platform-implementation-js/lib/routeIDmatchesHash.d.ts.map +1 -0
  360. package/src/platform-implementation-js/lib/routeIDmatchesHash.js +8 -15
  361. package/src/platform-implementation-js/lib/toItemWithLifetimeStream.d.ts +2 -4
  362. package/src/platform-implementation-js/lib/toItemWithLifetimeStream.d.ts.map +1 -0
  363. package/src/platform-implementation-js/lib/toItemWithLifetimeStream.js +12 -19
  364. package/src/platform-implementation-js/main-INTEGRATED-PAGEWORLD.js +1 -1
  365. package/src/platform-implementation-js/main.d.ts.map +1 -1
  366. package/src/platform-implementation-js/main.js +1 -4
  367. package/src/platform-implementation-js/namespaces/compose.d.ts +13 -0
  368. package/src/platform-implementation-js/namespaces/compose.d.ts.map +1 -0
  369. package/src/platform-implementation-js/namespaces/compose.js +56 -61
  370. package/src/platform-implementation-js/namespaces/conversations.d.ts +24 -0
  371. package/src/platform-implementation-js/namespaces/conversations.d.ts.map +1 -0
  372. package/src/platform-implementation-js/namespaces/conversations.js +79 -78
  373. package/src/platform-implementation-js/namespaces/global.d.ts +11 -0
  374. package/src/platform-implementation-js/namespaces/global.d.ts.map +1 -0
  375. package/src/platform-implementation-js/namespaces/global.js +28 -36
  376. package/src/platform-implementation-js/namespaces/keyboard.d.ts +11 -0
  377. package/src/platform-implementation-js/namespaces/keyboard.d.ts.map +1 -0
  378. package/src/platform-implementation-js/namespaces/keyboard.js +27 -40
  379. package/src/platform-implementation-js/namespaces/lists.d.ts +14 -0
  380. package/src/platform-implementation-js/namespaces/lists.d.ts.map +1 -0
  381. package/src/platform-implementation-js/namespaces/lists.js +38 -50
  382. package/src/platform-implementation-js/namespaces/modal.d.ts +10 -0
  383. package/src/platform-implementation-js/namespaces/modal.d.ts.map +1 -0
  384. package/src/platform-implementation-js/namespaces/modal.js +40 -48
  385. package/src/platform-implementation-js/namespaces/nav-menu.d.ts +16 -0
  386. package/src/platform-implementation-js/namespaces/nav-menu.d.ts.map +1 -0
  387. package/src/platform-implementation-js/namespaces/nav-menu.js +29 -36
  388. package/src/platform-implementation-js/namespaces/router.d.ts +50 -1
  389. package/src/platform-implementation-js/namespaces/router.d.ts.map +1 -0
  390. package/src/platform-implementation-js/namespaces/router.js +126 -137
  391. package/src/platform-implementation-js/namespaces/search.d.ts +7 -0
  392. package/src/platform-implementation-js/namespaces/search.d.ts.map +1 -0
  393. package/src/platform-implementation-js/namespaces/search.js +25 -34
  394. package/src/platform-implementation-js/namespaces/toolbars.d.ts +15 -0
  395. package/src/platform-implementation-js/namespaces/toolbars.d.ts.map +1 -0
  396. package/src/platform-implementation-js/namespaces/toolbars.js +138 -140
  397. package/src/platform-implementation-js/namespaces/user.d.ts +13 -0
  398. package/src/platform-implementation-js/namespaces/user.d.ts.map +1 -0
  399. package/src/platform-implementation-js/namespaces/user.js +53 -62
  400. package/src/platform-implementation-js/namespaces/widgets.d.ts +16 -0
  401. package/src/platform-implementation-js/namespaces/widgets.d.ts.map +1 -0
  402. package/src/platform-implementation-js/namespaces/widgets.js +68 -77
  403. package/src/platform-implementation-js/platform-implementation.d.ts +54 -126
  404. package/src/platform-implementation-js/platform-implementation.d.ts.map +1 -0
  405. package/src/platform-implementation-js/platform-implementation.js +176 -147
  406. package/src/platform-implementation-js/views/app-toolbar-button-view.d.ts +11 -0
  407. package/src/platform-implementation-js/views/app-toolbar-button-view.d.ts.map +1 -0
  408. package/src/platform-implementation-js/views/app-toolbar-button-view.js +42 -51
  409. package/src/platform-implementation-js/views/collapsible-section-view.d.ts +12 -0
  410. package/src/platform-implementation-js/views/collapsible-section-view.d.ts.map +1 -0
  411. package/src/platform-implementation-js/views/collapsible-section-view.js +58 -86
  412. package/src/platform-implementation-js/views/compose-view.d.ts +2 -1
  413. package/src/platform-implementation-js/views/compose-view.d.ts.map +1 -1
  414. package/src/platform-implementation-js/views/content-panel-view.d.ts +12 -0
  415. package/src/platform-implementation-js/views/content-panel-view.d.ts.map +1 -0
  416. package/src/platform-implementation-js/views/content-panel-view.js +35 -50
  417. package/src/platform-implementation-js/views/conversations/attachment-card-view.d.ts +18 -0
  418. package/src/platform-implementation-js/views/conversations/attachment-card-view.d.ts.map +1 -0
  419. package/src/platform-implementation-js/views/conversations/attachment-card-view.js +39 -44
  420. package/src/platform-implementation-js/views/conversations/custom-message-view.d.ts +28 -0
  421. package/src/platform-implementation-js/views/conversations/custom-message-view.d.ts.map +1 -0
  422. package/src/platform-implementation-js/views/conversations/custom-message-view.js +115 -103
  423. package/src/platform-implementation-js/views/conversations/message-view.d.ts +34 -0
  424. package/src/platform-implementation-js/views/conversations/message-view.d.ts.map +1 -0
  425. package/src/platform-implementation-js/views/conversations/message-view.js +197 -209
  426. package/src/platform-implementation-js/views/conversations/thread-view.d.ts +23 -0
  427. package/src/platform-implementation-js/views/conversations/thread-view.d.ts.map +1 -0
  428. package/src/platform-implementation-js/views/conversations/thread-view.js +93 -100
  429. package/src/platform-implementation-js/views/native-nav-item-view.d.ts +11 -0
  430. package/src/platform-implementation-js/views/native-nav-item-view.d.ts.map +1 -0
  431. package/src/platform-implementation-js/views/native-nav-item-view.js +56 -62
  432. package/src/platform-implementation-js/views/nav-item-view.d.ts +12 -22
  433. package/src/platform-implementation-js/views/nav-item-view.d.ts.map +1 -0
  434. package/src/platform-implementation-js/views/nav-item-view.js +123 -124
  435. package/src/platform-implementation-js/views/route-view/custom-route-view.d.ts +9 -0
  436. package/src/platform-implementation-js/views/route-view/custom-route-view.d.ts.map +1 -0
  437. package/src/platform-implementation-js/views/route-view/custom-route-view.js +24 -36
  438. package/src/platform-implementation-js/views/route-view/dummy-route-view-driver.d.ts +14 -0
  439. package/src/platform-implementation-js/views/route-view/dummy-route-view-driver.d.ts.map +1 -0
  440. package/src/platform-implementation-js/views/route-view/dummy-route-view-driver.js +27 -38
  441. package/src/platform-implementation-js/views/route-view/list-route-view.d.ts +13 -0
  442. package/src/platform-implementation-js/views/route-view/list-route-view.d.ts.map +1 -0
  443. package/src/platform-implementation-js/views/route-view/list-route-view.js +41 -51
  444. package/src/platform-implementation-js/views/route-view/route-view.d.ts +11 -0
  445. package/src/platform-implementation-js/views/route-view/route-view.d.ts.map +1 -0
  446. package/src/platform-implementation-js/views/route-view/route-view.js +41 -51
  447. package/src/platform-implementation-js/views/section-view.d.ts +11 -0
  448. package/src/platform-implementation-js/views/section-view.d.ts.map +1 -0
  449. package/src/platform-implementation-js/views/section-view.js +56 -81
  450. package/src/platform-implementation-js/views/thread-row-view.d.ts +27 -0
  451. package/src/platform-implementation-js/views/thread-row-view.d.ts.map +1 -0
  452. package/src/platform-implementation-js/views/thread-row-view.js +87 -94
  453. package/src/platform-implementation-js/widgets/buttons/basic-button-view-controller.d.ts +4 -0
  454. package/src/platform-implementation-js/widgets/buttons/basic-button-view-controller.d.ts.map +1 -1
  455. package/src/platform-implementation-js/widgets/drawer-view.d.ts +13 -0
  456. package/src/platform-implementation-js/widgets/drawer-view.d.ts.map +1 -0
  457. package/src/platform-implementation-js/widgets/drawer-view.js +46 -53
  458. package/src/platform-implementation-js/widgets/modal-view.d.ts +18 -0
  459. package/src/platform-implementation-js/widgets/modal-view.d.ts.map +1 -0
  460. package/src/platform-implementation-js/widgets/modal-view.js +95 -91
  461. package/src/platform-implementation-js/widgets/mole-view.d.ts +12 -0
  462. package/src/platform-implementation-js/widgets/mole-view.d.ts.map +1 -0
  463. package/src/platform-implementation-js/widgets/mole-view.js +37 -46
  464. package/src/platform-implementation-js/widgets/top-message-bar-view.d.ts +8 -0
  465. package/src/platform-implementation-js/widgets/top-message-bar-view.d.ts.map +1 -0
  466. package/src/platform-implementation-js/widgets/top-message-bar-view.js +13 -21
  467. package/src/injected-js/gmail/modify-suggestions.test.js +0 -20
  468. package/src/injected-js/gmail/sync-compose-request-processor.test.js +0 -80
  469. package/src/injected-js/gmail/thread-identifier/thread-row-parser.test.js +0 -41
  470. package/src/injected-js/xhr-proxy-factory.test.js +0 -1052
  471. package/src/platform-implementation-js/dom-driver/gmail/gmail-driver/open-draft-by-message-id.test.js +0 -22
  472. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-app-sidebar-view/index.test.js +0 -125
  473. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-attachment-card-view.test.js +0 -141
  474. package/src/platform-implementation-js/dom-driver/gmail/views/gmail-thread-sidebar-view.test.js +0 -209
  475. package/src/platform-implementation-js/lib/array-to-lifetimes.js +0 -69
  476. package/src/platform-implementation-js/lib/array-to-lifetimes.test.js +0 -155
  477. package/src/platform-implementation-js/lib/dom/querySelectorOne.js +0 -13
  478. package/src/platform-implementation-js/lib/extract-contact-from-email-contact-string.test.js +0 -39
  479. package/src/platform-implementation-js/lib/make-revocable-function.js +0 -38
  480. package/src/platform-implementation-js/lib/make-revocable-function.test.js +0 -61
  481. package/src/platform-implementation-js/lib/parseParamsFromRouteID.test.js +0 -19
  482. package/src/platform-implementation-js/lib/populateRouteID.test.js +0 -32
  483. package/src/platform-implementation-js/lib/routeIDmatchesHash.test.js +0 -17
@@ -1,1379 +1,1526 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.default = void 0;
8
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
- var _autoHtml = _interopRequireDefault(require("auto-html"));
10
- var _transducers = _interopRequireDefault(require("transducers.js"));
11
- var _once = _interopRequireDefault(require("lodash/once"));
12
- var _escape = _interopRequireDefault(require("lodash/escape"));
13
- var _includes = _interopRequireDefault(require("lodash/includes"));
14
- var _constant = _interopRequireDefault(require("lodash/constant"));
15
- var _find = _interopRequireDefault(require("lodash/find"));
16
- var _asap = _interopRequireDefault(require("asap"));
17
- var _pdelay = _interopRequireDefault(require("pdelay"));
18
- var Kefir = _interopRequireWildcard(require("kefir"));
19
- var ud = _interopRequireWildcard(require("ud"));
20
- var _closestNg = _interopRequireDefault(require("closest-ng"));
21
- var _kefirBus = _interopRequireDefault(require("kefir-bus"));
22
- var _kefirStopper = _interopRequireDefault(require("kefir-stopper"));
23
- var _delayAsap = _interopRequireDefault(require("../../../lib/delay-asap"));
24
- var _simulateMouseEvent = require("../../../lib/dom/simulate-mouse-event");
25
- var _simulateKey = _interopRequireDefault(require("../../../lib/dom/simulate-key"));
26
- var _querySelectorOrFail = _interopRequireDefault(require("../../../lib/dom/querySelectorOrFail"));
27
- var _isElementVisible = _interopRequireDefault(require("../../../../common/isElementVisible"));
28
- var _makeElementChildStream = _interopRequireDefault(require("../../../lib/dom/make-element-child-stream"));
29
- var _simulateDragAndDrop = require("../../../lib/dom/simulate-drag-and-drop");
30
- var GmailResponseProcessor = _interopRequireWildcard(require("../gmail-response-processor"));
31
- var _gmailElementGetter = _interopRequireDefault(require("../gmail-element-getter"));
32
- var _setCss = _interopRequireDefault(require("../../../lib/dom/set-css"));
33
- var _waitFor = _interopRequireDefault(require("../../../lib/wait-for"));
34
- var _streamWaitFor = _interopRequireDefault(require("../../../lib/stream-wait-for"));
35
- var _makeMutationObserverChunkedStream = _interopRequireDefault(require("../../../lib/dom/make-mutation-observer-chunked-stream"));
36
- var _handleComposeLinkChips = _interopRequireDefault(require("../../../lib/handle-compose-link-chips"));
37
- var _insertLinkChipIntoBody = _interopRequireDefault(require("../../../lib/insert-link-chip-into-body"));
38
- var _addComposeNotice = _interopRequireDefault(require("./gmail-compose-view/add-compose-notice"));
39
- var _addStatusBar = _interopRequireDefault(require("./gmail-compose-view/add-status-bar"));
40
- var _insertHtmlAtCursor = _interopRequireDefault(require("../../../lib/dom/insert-html-at-cursor"));
41
- var _ensureGroupingIsOpen = _interopRequireDefault(require("./gmail-compose-view/ensure-grouping-is-open"));
42
- var _ensureAppButtonToolbarsAreClosed = _interopRequireDefault(require("./gmail-compose-view/ensure-app-button-toolbars-are-closed"));
43
- var _sizeFixer = _interopRequireDefault(require("./gmail-compose-view/size-fixer"));
44
- var _addTooltipToButton = _interopRequireDefault(require("./gmail-compose-view/add-tooltip-to-button"));
45
- var _addRecipientRow = _interopRequireDefault(require("./gmail-compose-view/add-recipient-row"));
46
- var _addButton = _interopRequireDefault(require("./gmail-compose-view/add-button"));
47
- var _setRecipients = _interopRequireDefault(require("./gmail-compose-view/set-recipients"));
48
- var _focus = _interopRequireDefault(require("./gmail-compose-view/focus"));
49
- var _monitorSelectionRange = _interopRequireDefault(require("./gmail-compose-view/monitor-selection-range"));
50
- var _manageButtonGrouping = _interopRequireDefault(require("./gmail-compose-view/manage-button-grouping"));
51
- var _getSelection = require("../../../lib/dom/get-selection");
52
- var _getMinimizedStream = _interopRequireDefault(require("./gmail-compose-view/get-minimized-stream"));
53
- var _censorHTMLstring = _interopRequireDefault(require("../../../../common/censorHTMLstring"));
54
- var _insertLinkIntoBody = _interopRequireDefault(require("./gmail-compose-view/insert-link-into-body"));
55
- var _getAddressChangesStream = _interopRequireDefault(require("./gmail-compose-view/get-address-changes-stream"));
56
- var _getBodyChangesStream = _interopRequireDefault(require("./gmail-compose-view/get-body-changes-stream"));
57
- var _getRecipients = _interopRequireDefault(require("./gmail-compose-view/get-recipients"));
58
- var _getResponseTypeChangesStream = _interopRequireDefault(require("./gmail-compose-view/get-response-type-changes-stream"));
59
- var _getPresendingStream = _interopRequireDefault(require("../../../driver-common/compose/getPresendingStream"));
60
- var _getDiscardStream = _interopRequireDefault(require("../../../driver-common/compose/getDiscardStream"));
61
- var _updateInsertMoreAreaLeft = _interopRequireDefault(require("./gmail-compose-view/update-insert-more-area-left"));
62
- var _setupLinkPopovers = _interopRequireDefault(require("./gmail-compose-view/setupLinkPopovers"));
63
- var _getFormattingAreaOffsetLeft = _interopRequireDefault(require("./gmail-compose-view/get-formatting-area-offset-left"));
64
- var _overrideEditSubject = _interopRequireDefault(require("./gmail-compose-view/override-edit-subject"));
65
- var _detectClassicRecipientsArea = _interopRequireDefault(require("./gmail-compose-view/detectClassicRecipientsArea"));
66
- var _censorHTMLtree = _interopRequireDefault(require("../../../../common/censorHTMLtree"));
67
- var _pageParser = require("./gmail-compose-view/page-parser");
68
- var _pageParserTree = _interopRequireDefault(require("page-parser-tree"));
69
- var _tagTree = require("tag-tree");
70
- var fromManager = _interopRequireWildcard(require("./gmail-compose-view/from-manager"));
71
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
72
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
1
+ /* eslint-disable @typescript-eslint/no-var-requires */
2
+ /* eslint-disable @typescript-eslint/no-unused-vars */
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 closest from 'closest-ng';
14
+ import kefirBus from 'kefir-bus';
15
+ import kefirStopper from 'kefir-stopper';
16
+ import delayAsap from '../../../lib/delay-asap';
17
+ import { simulateClick } from '../../../lib/dom/simulate-mouse-event';
18
+ import simulateKey from '../../../lib/dom/simulate-key';
19
+ import querySelector from '../../../lib/dom/querySelectorOrFail';
20
+ import isElementVisible from '../../../../common/isElementVisible';
21
+ import makeElementChildStream from '../../../lib/dom/make-element-child-stream';
22
+ import { simulateDragOver, simulateDrop, simulateDragEnd, } from '../../../lib/dom/simulate-drag-and-drop';
23
+ import * as GmailResponseProcessor from '../gmail-response-processor';
24
+ import GmailElementGetter from '../gmail-element-getter';
25
+ import setCss from '../../../lib/dom/set-css';
26
+ import waitFor from '../../../lib/wait-for';
27
+ import streamWaitFor from '../../../lib/stream-wait-for';
28
+ import makeMutationObserverChunkedStream from '../../../lib/dom/make-mutation-observer-chunked-stream';
29
+ import handleComposeLinkChips from '../../../lib/handle-compose-link-chips';
30
+ import insertLinkChipIntoBody from '../../../lib/insert-link-chip-into-body';
31
+ import addComposeNotice from './gmail-compose-view/add-compose-notice';
32
+ import addStatusBar from './gmail-compose-view/add-status-bar';
33
+ import insertHTMLatCursor from '../../../lib/dom/insert-html-at-cursor';
34
+ import ensureGroupingIsOpen from './gmail-compose-view/ensure-grouping-is-open';
35
+ import ensureAppButtonToolbarsAreClosed from './gmail-compose-view/ensure-app-button-toolbars-are-closed';
36
+ import sizeFixer from './gmail-compose-view/size-fixer';
37
+ import addTooltipToButton from './gmail-compose-view/add-tooltip-to-button';
38
+ import addRecipientRow from './gmail-compose-view/add-recipient-row';
39
+ import addButton from './gmail-compose-view/add-button';
40
+ import setRecipients from './gmail-compose-view/set-recipients';
41
+ import focus from './gmail-compose-view/focus';
73
42
  // import addOuterSidebar from './gmail-compose-view/add-outer-sidebar';
43
+ import monitorSelectionRange from './gmail-compose-view/monitor-selection-range';
44
+ import manageButtonGrouping from './gmail-compose-view/manage-button-grouping';
45
+ import { getSelectedHTMLInElement, getSelectedTextInElement, } from '../../../lib/dom/get-selection';
46
+ import getMinimizedStream from './gmail-compose-view/get-minimized-stream';
47
+ import censorHTMLstring from '../../../../common/censorHTMLstring';
48
+ import insertLinkIntoBody from './gmail-compose-view/insert-link-into-body';
49
+ import getAddressChangesStream from './gmail-compose-view/get-address-changes-stream';
50
+ import getBodyChangesStream from './gmail-compose-view/get-body-changes-stream';
51
+ import getRecipients from './gmail-compose-view/get-recipients';
52
+ import getResponseTypeChangesStream from './gmail-compose-view/get-response-type-changes-stream';
53
+ import getPresendingStream from '../../../driver-common/compose/getPresendingStream';
54
+ import getDiscardStream from '../../../driver-common/compose/getDiscardStream';
55
+ import updateInsertMoreAreaLeft from './gmail-compose-view/update-insert-more-area-left';
56
+ import setupLinkPopOvers from './gmail-compose-view/setupLinkPopovers';
57
+ import getFormattingAreaOffsetLeft from './gmail-compose-view/get-formatting-area-offset-left';
58
+ import overrideEditSubject from './gmail-compose-view/override-edit-subject';
59
+ import detectClassicRecipientsArea from './gmail-compose-view/detectClassicRecipientsArea';
60
+ import { makePageParser, getRecipientRowElements, } from './gmail-compose-view/page-parser';
61
+ import * as fromManager from './gmail-compose-view/from-manager';
74
62
  let hasReportedMissingBody = false;
75
63
  class GmailComposeView {
76
- // Set only after the message is sent.
77
-
78
- constructor(element, xhrInterceptorStream, driver, options) {
79
- (0, _defineProperty2.default)(this, "_closedProgrammatically", false);
80
- (0, _defineProperty2.default)(this, "_destroyed", false);
81
- (0, _defineProperty2.default)(this, "_hasSetupLinkPopOvers", false);
82
- this;
83
- this._element = element;
84
- this._element.classList.add('inboxsdk__compose');
85
- if (options.isInlineReplyForm) {
86
- this._element.classList.add('inboxsdk__compose_inlineReply');
87
- }
88
- this._isInlineReplyForm = options.isInlineReplyForm;
89
- this._isStandalone = options.isStandalone;
90
- this._isFullscreen = false;
91
- this._emailWasSent = false;
92
- this._messageId = null;
93
- this._finalMessageId = null;
94
- this._draftSaving = false;
95
- this._draftIDpromise = null;
96
- this._driver = driver;
97
- this._stopper = (0, _kefirStopper.default)();
98
- this._managedViewControllers = [];
99
- this._requestModifiers = {};
100
- this._isListeningToAjaxInterceptStream = false;
101
- this._eventStream = (0, _kefirBus.default)();
102
- this._removedFromDOMStopper = (0, _kefirStopper.default)();
103
- this._isTriggeringADraftSavePending = false;
104
- this._page = (0, _pageParser.makePageParser)(element, driver.getLogger());
105
- this.tagTree = this._page.tree;
106
- let saveAndSendStream;
107
- if (this._driver.isUsingSyncAPI()) {
108
- saveAndSendStream = xhrInterceptorStream
109
- // we know _getDraftIDfromForm will work because by the time we're
110
- // getting an ajax event Gmail's JS has generated an ID and added it to the DOM.
111
- .filter(event => event.draftID === this._getDraftIDfromForm()).map(event => {
112
- switch (event.type) {
113
- case 'emailSending':
114
- {
115
- return {
116
- eventName: 'sending'
117
- };
118
- }
119
- case 'emailSent':
120
- {
121
- let syncThreadID = event.threadID;
122
- let syncMessageID = event.messageID;
123
- if (event.oldMessageID) this._messageId = event.oldMessageID;
124
- if (event.oldThreadID) this._threadID = event.oldThreadID;
125
- driver.removeCachedGmailMessageIdForSyncMessageId(syncMessageID);
126
- driver.removeCachedOldGmailThreadIdFromSyncThreadId(syncThreadID);
127
- return {
128
- eventName: 'sent',
129
- data: {
130
- getThreadID: (0, _once.default)(async () => {
131
- if (event.oldThreadID) {
132
- return event.oldThreadID;
64
+ _element;
65
+ _seenBodyElement;
66
+ _isInlineReplyForm;
67
+ _isFullscreen;
68
+ _isStandalone;
69
+ _emailWasSent;
70
+ _driver;
71
+ _managedViewControllers;
72
+ _eventStream;
73
+ _isTriggeringADraftSavePending;
74
+ _buttonViewControllerTooltipMap;
75
+ _composeID;
76
+ _messageIDElement;
77
+ _messageId;
78
+ _finalMessageId; // Set only after the message is sent.
79
+ _initialMessageId;
80
+ _targetMessageID;
81
+ _draftSaving;
82
+ _draftIDpromise;
83
+ _threadID;
84
+ _stopper;
85
+ _lastSelectionRange;
86
+ _requestModifiers;
87
+ _isListeningToAjaxInterceptStream;
88
+ _formattingArea;
89
+ _closedProgrammatically = false;
90
+ _destroyed = false;
91
+ _removedFromDOMStopper;
92
+ _hasSetupLinkPopOvers = false;
93
+ _page;
94
+ tagTree;
95
+ ready;
96
+ constructor(element, xhrInterceptorStream, driver, options) {
97
+ this;
98
+ this._element = element;
99
+ this._element.classList.add('inboxsdk__compose');
100
+ if (options.isInlineReplyForm) {
101
+ this._element.classList.add('inboxsdk__compose_inlineReply');
102
+ }
103
+ this._isInlineReplyForm = options.isInlineReplyForm;
104
+ this._isStandalone = options.isStandalone;
105
+ this._isFullscreen = false;
106
+ this._emailWasSent = false;
107
+ this._messageId = null;
108
+ this._finalMessageId = null;
109
+ this._draftSaving = false;
110
+ this._draftIDpromise = null;
111
+ this._driver = driver;
112
+ this._stopper = kefirStopper();
113
+ this._managedViewControllers = [];
114
+ this._requestModifiers = {};
115
+ this._isListeningToAjaxInterceptStream = false;
116
+ this._eventStream = kefirBus();
117
+ this._removedFromDOMStopper = kefirStopper();
118
+ this._isTriggeringADraftSavePending = false;
119
+ this._page = makePageParser(element, driver.getLogger());
120
+ this.tagTree = this._page.tree;
121
+ let saveAndSendStream;
122
+ if (this._driver.isUsingSyncAPI()) {
123
+ saveAndSendStream = xhrInterceptorStream // we know _getDraftIDfromForm will work because by the time we're
124
+ // getting an ajax event Gmail's JS has generated an ID and added it to the DOM.
125
+ .filter((event) => event.draftID === this._getDraftIDfromForm())
126
+ .map((event) => {
127
+ switch (event.type) {
128
+ case 'emailSending': {
129
+ return {
130
+ eventName: 'sending',
131
+ };
132
+ }
133
+ case 'emailSent': {
134
+ const syncThreadID = event.threadID;
135
+ const syncMessageID = event.messageID;
136
+ if (event.oldMessageID)
137
+ this._messageId = event.oldMessageID;
138
+ if (event.oldThreadID)
139
+ this._threadID = event.oldThreadID;
140
+ driver.removeCachedGmailMessageIdForSyncMessageId(syncMessageID);
141
+ driver.removeCachedOldGmailThreadIdFromSyncThreadId(syncThreadID);
142
+ return {
143
+ eventName: 'sent',
144
+ data: {
145
+ getThreadID: once(async () => {
146
+ if (event.oldThreadID) {
147
+ return event.oldThreadID;
148
+ }
149
+ return await driver.getOldGmailThreadIdFromSyncThreadId(syncThreadID);
150
+ }),
151
+ getMessageID: once(async () => {
152
+ if (event.oldMessageID) {
153
+ return event.oldMessageID;
154
+ }
155
+ return await driver.getGmailMessageIdForSyncMessageId(syncMessageID);
156
+ }),
157
+ },
158
+ };
159
+ }
160
+ case 'emailSendFailed': {
161
+ return {
162
+ eventName: 'sendCanceled',
163
+ };
164
+ }
165
+ case 'emailDraftReceived': {
166
+ this._messageId = event.oldMessageID;
167
+ this._threadID = event.oldThreadID;
168
+ return {
169
+ eventName: 'draftSaved',
170
+ data: {
171
+ getThreadID() {
172
+ return Promise.resolve(event.oldThreadID);
173
+ },
174
+ getMessageID() {
175
+ return Promise.resolve(event.oldMessageID);
176
+ },
177
+ },
178
+ };
133
179
  }
134
- return await driver.getOldGmailThreadIdFromSyncThreadId(syncThreadID);
135
- }),
136
- getMessageID: (0, _once.default)(async () => {
137
- if (event.oldMessageID) {
138
- return event.oldMessageID;
180
+ default: {
181
+ return null;
139
182
  }
140
- return await driver.getGmailMessageIdForSyncMessageId(syncMessageID);
141
- })
142
183
  }
143
- };
144
- }
145
- case 'emailSendFailed':
146
- {
147
- return {
148
- eventName: 'sendCanceled'
149
- };
150
- }
151
- case 'emailDraftReceived':
152
- {
153
- this._messageId = event.oldMessageID;
154
- this._threadID = event.oldThreadID;
155
- return {
156
- eventName: 'draftSaved',
157
- data: {
158
- getThreadID() {
159
- return Promise.resolve(event.oldThreadID);
160
- },
161
- getMessageID() {
162
- return Promise.resolve(event.oldMessageID);
163
- }
184
+ })
185
+ .filter(Boolean);
186
+ }
187
+ else {
188
+ saveAndSendStream = xhrInterceptorStream
189
+ .filter((event) => event.composeId === this.getComposeID())
190
+ .map((event) => {
191
+ switch (event.type) {
192
+ case 'emailSending': {
193
+ return [
194
+ {
195
+ eventName: 'sending',
196
+ },
197
+ ];
198
+ }
199
+ case 'emailSent': {
200
+ const response = GmailResponseProcessor.interpretSentEmailResponse(event.response);
201
+ if (includes(['tr', 'eu'], response.messageID)) {
202
+ return [
203
+ {
204
+ eventName: 'sendCanceled',
205
+ },
206
+ ];
207
+ }
208
+ this._emailWasSent = true;
209
+ if (response.messageID) {
210
+ this._finalMessageId = response.messageID;
211
+ }
212
+ this._messageId = null;
213
+ const data = {
214
+ getThreadID: () => Promise.resolve(response.threadID),
215
+ getMessageID: () => Promise.resolve(response.messageID),
216
+ };
217
+ ['threadID', 'gmailThreadId'].forEach((prop) => {
218
+ // These properties are nonenumerable.
219
+ Object.defineProperty(data, prop, {
220
+ get: () => {
221
+ this._driver
222
+ .getLogger()
223
+ .deprecationWarning(`composeView sent event.${prop}`, 'composeView sent event.getThreadID()');
224
+ return response.threadID;
225
+ },
226
+ });
227
+ });
228
+ ['messageID', 'gmailMessageId'].forEach((prop) => {
229
+ Object.defineProperty(data, prop, {
230
+ get: () => {
231
+ this._driver
232
+ .getLogger()
233
+ .deprecationWarning(`composeView sent event.${prop}`, 'composeView sent event.getMessageID()');
234
+ return response.messageID;
235
+ },
236
+ });
237
+ });
238
+ return [
239
+ {
240
+ eventName: 'sent',
241
+ data,
242
+ },
243
+ ];
244
+ }
245
+ case 'emailDraftSaveSending': {
246
+ this._draftSaving = true;
247
+ return [
248
+ {
249
+ eventName: 'draftSaving',
250
+ },
251
+ ];
252
+ }
253
+ case 'emailDraftReceived': {
254
+ this._draftSaving = false;
255
+ let response;
256
+ try {
257
+ response = GmailResponseProcessor.interpretSentEmailResponse(event.response);
258
+ }
259
+ catch (err) {
260
+ if (this._driver.getAppId() === 'sdk_streak_21e9788951') {
261
+ this._driver.getLogger().error(err, {
262
+ connectionDetails: event.connectionDetails,
263
+ response: event.response,
264
+ });
265
+ throw err;
266
+ }
267
+ else {
268
+ throw err;
269
+ }
270
+ }
271
+ if (response.messageID === 'eu') {
272
+ return []; // save was canceled
273
+ }
274
+ const events = [
275
+ {
276
+ eventName: 'draftSaved',
277
+ data: response,
278
+ },
279
+ ];
280
+ if (!response.messageID) {
281
+ this._driver
282
+ .getLogger()
283
+ .error(new Error('Missing message id from emailDraftReceived'));
284
+ }
285
+ else if (response.messageID &&
286
+ this._messageId !== response.messageID) {
287
+ if (/^[0-9a-f]+$/i.test(response.messageID)) {
288
+ this._messageId = response.messageID;
289
+ events.push({
290
+ eventName: 'messageIDChange',
291
+ data: this._messageId,
292
+ });
293
+ }
294
+ else {
295
+ this._driver
296
+ .getLogger()
297
+ .error(new Error('Invalid message id from emailDraftReceived'), {
298
+ value: response.messageID,
299
+ });
300
+ }
301
+ }
302
+ return events;
303
+ }
304
+ default:
305
+ return [];
306
+ }
307
+ })
308
+ .flatten()
309
+ .map((event) => {
310
+ if (this._driver.getLogger().shouldTrackEverything()) {
311
+ driver.getLogger().eventSite('compose.debug.xhr', {
312
+ eventName: event.eventName,
313
+ });
164
314
  }
165
- };
315
+ return event;
316
+ });
317
+ }
318
+ this._eventStream.plug(Kefir.merge([
319
+ saveAndSendStream,
320
+ Kefir.fromEvents(this._element, 'buttonAdded').map(() => {
321
+ return {
322
+ eventName: 'buttonAdded',
323
+ };
324
+ }),
325
+ Kefir.fromEvents(this._element, 'resize').map(() => ({
326
+ eventName: 'resize',
327
+ })),
328
+ Kefir.fromEvents(this._element, 'composeFullscreenStateChanged').map(() => {
329
+ this._updateComposeFullscreenState();
330
+ return {
331
+ eventName: 'fullscreenChanged',
332
+ data: {
333
+ fullscreen: this._isFullscreen,
334
+ },
335
+ };
336
+ }),
337
+ ]));
338
+ Kefir.fromEvents(this._element, 'closedProgrammatically')
339
+ .takeUntilBy(this._stopper)
340
+ .onValue(() => {
341
+ this._closedProgrammatically = true;
342
+ });
343
+ this._buttonViewControllerTooltipMap = new WeakMap();
344
+ const initialBodyElement = this.getMaybeBodyElement();
345
+ this.ready = constant((initialBodyElement
346
+ ? Kefir.constant(initialBodyElement)
347
+ : streamWaitFor(() => this.getMaybeBodyElement(), 3 * 60 * 1000 //timeout
348
+ ))
349
+ .takeUntilBy(this._stopper)
350
+ .map((bodyElement) => {
351
+ this._seenBodyElement = bodyElement;
352
+ this._composeID = this._element.querySelector('input[name="composeid"]').value;
353
+ this._messageIDElement = this._element.querySelector('input[name="draft"]');
354
+ if (!this._messageIDElement) {
355
+ driver
356
+ .getLogger()
357
+ .error(new Error('Could not find compose message id field'));
358
+ // stub so other things don't fail
359
+ this._messageIDElement = document.createElement('input');
166
360
  }
167
- default:
361
+ this._setupIDs();
362
+ this._setupStreams();
363
+ this._setupConsistencyCheckers();
364
+ this._updateComposeFullscreenState();
168
365
  {
169
- return null;
366
+ // try and handle the case where the user types in a bad email address
367
+ // we get the presending event but then no other events will pass because
368
+ // a modal comes up informing the user of the bad email address
369
+ this.getEventStream()
370
+ .filter(({ eventName }) => eventName === 'presending')
371
+ .takeUntilBy(this._stopper)
372
+ .onValue(() => {
373
+ makeElementChildStream(document.body)
374
+ .map((event) => event.el)
375
+ .filter((node) => node.getAttribute &&
376
+ node.getAttribute('role') === 'alertdialog')
377
+ .takeUntilBy(Kefir.merge([
378
+ this.getEventStream().filter(({ eventName }) => eventName === 'sendCanceled' ||
379
+ eventName === 'sending'),
380
+ Kefir.later(15, undefined),
381
+ ]))
382
+ .onValue(() => {
383
+ this._eventStream.emit({
384
+ eventName: 'sendCanceled',
385
+ });
386
+ });
387
+ });
170
388
  }
389
+ return this;
390
+ })
391
+ .toProperty());
392
+ this.ready().onError((errorObject) => {
393
+ driver.getLogger().error(errorObject, {
394
+ hasForm: !!this.getElement().querySelector('form'),
395
+ class: this.getElement().getAttribute('class'),
396
+ });
397
+ });
398
+ // v2 Data behaves differently whereby the compose element is removed
399
+ // from the page while the send is in flight instead of waiting for the
400
+ // send to come back, so we have to handle that difference
401
+ if (this._driver.isUsingSyncAPI()) {
402
+ Kefir.merge([
403
+ // if we get a presending then we let the other stream wait for
404
+ // sent. But if we get a sendCanceled, then a regular destroy can
405
+ // pass through
406
+ this._removedFromDOMStopper.filterBy(this._eventStream
407
+ .filter(({ eventName }) => eventName === 'presending' || eventName === 'sendCanceled')
408
+ .map(({ eventName }) => eventName === 'sendCanceled')
409
+ .toProperty(() => true)),
410
+ Kefir.combine([
411
+ this._removedFromDOMStopper,
412
+ this._eventStream.filter(({ eventName }) => eventName === 'sent'),
413
+ ]),
414
+ ])
415
+ .take(1) // we delay asap here so that the event stream is not destroyed before listeners here the sent event
416
+ .flatMap(() => delayAsap(null))
417
+ .onValue(() => this._destroy());
171
418
  }
172
- }).filter(Boolean);
173
- } else {
174
- saveAndSendStream = xhrInterceptorStream.filter(event => event.composeId === this.getComposeID()).map(event => {
175
- switch (event.type) {
176
- case 'emailSending':
177
- {
178
- return [{
179
- eventName: 'sending'
180
- }];
419
+ else {
420
+ this._removedFromDOMStopper.onValue(() => this._destroy());
421
+ }
422
+ detectClassicRecipientsArea();
423
+ }
424
+ destroy() {
425
+ // this gets called when the element gets removed from the DOM
426
+ // however we don't want to pass through that destroy event right away
427
+ this._removedFromDOMStopper.destroy();
428
+ this._page.dump();
429
+ }
430
+ _destroy() {
431
+ this._eventStream.emit({
432
+ eventName: 'destroy',
433
+ data: {
434
+ messageID: this.getMessageID(),
435
+ closedByInboxSDK: this._closedProgrammatically,
436
+ },
437
+ });
438
+ this._eventStream.end();
439
+ this._managedViewControllers.forEach((vc) => {
440
+ vc.destroy();
441
+ });
442
+ this._requestModifiers = {};
443
+ this._managedViewControllers.length = 0;
444
+ this._stopper.destroy();
445
+ this._destroyed = true;
446
+ }
447
+ getStopper() {
448
+ return this._stopper;
449
+ }
450
+ getEventStream() {
451
+ return this._eventStream;
452
+ }
453
+ getGmailDriver() {
454
+ return this._driver;
455
+ }
456
+ isDestroyed() {
457
+ return this._destroyed;
458
+ }
459
+ _setupStreams() {
460
+ this._eventStream.plug(getAddressChangesStream(this));
461
+ this._eventStream.plug(getBodyChangesStream(this));
462
+ this._eventStream.plug(getResponseTypeChangesStream(this));
463
+ this._eventStream.plug(getPresendingStream({
464
+ element: this.getElement(),
465
+ sendButton: this.getSendButton(),
466
+ sendAndArchive: this.getSendAndArchiveButton(),
467
+ }));
468
+ let discardButton;
469
+ try {
470
+ discardButton = this.getDiscardButton();
471
+ }
472
+ catch (err) {
473
+ // handle failures of this.getDiscardButton()
474
+ this._driver
475
+ .getLogger()
476
+ .errorSite(new Error('Failed to find discard button'), {
477
+ html: censorHTMLstring(this._element.outerHTML),
478
+ });
479
+ }
480
+ if (discardButton) {
481
+ this._eventStream.plug(getDiscardStream({
482
+ element: this.getElement(),
483
+ discardButton,
484
+ }));
485
+ }
486
+ this._eventStream.plug(Kefir.fromEvents(this.getElement(), 'inboxSDKsendCanceled').map(() => ({
487
+ eventName: 'sendCanceled',
488
+ })));
489
+ this._eventStream.plug(Kefir.fromEvents(this.getElement(), 'inboxSDKdiscardCanceled').map(() => ({
490
+ eventName: 'discardCanceled',
491
+ })));
492
+ this._eventStream.plug(Kefir.later(10, undefined)
493
+ .flatMap(() => getMinimizedStream(this))
494
+ .changes()
495
+ .map((minimized) => ({
496
+ eventName: minimized ? 'minimized' : 'restored',
497
+ })));
498
+ if (!this._driver.isUsingSyncAPI()) {
499
+ makeMutationObserverChunkedStream(this._messageIDElement, {
500
+ attributes: true,
501
+ attributeFilter: ['value'],
502
+ })
503
+ .takeUntilBy(this._eventStream.filter(() => false).beforeEnd(() => null))
504
+ .map(() => this._getMessageIDfromForm())
505
+ .filter((messageID) => messageID &&
506
+ !this._emailWasSent &&
507
+ this._messageId !== messageID)
508
+ .onValue((messageID) => {
509
+ this._messageId = messageID;
510
+ this._eventStream.emit({
511
+ eventName: 'messageIDChange',
512
+ data: this._messageId,
513
+ });
514
+ });
515
+ }
516
+ }
517
+ _setupConsistencyCheckers() {
518
+ try {
519
+ handleComposeLinkChips(this);
520
+ monitorSelectionRange(this);
521
+ manageButtonGrouping(this);
522
+ sizeFixer(this._driver, this);
523
+ }
524
+ catch (err) {
525
+ this._driver.getLogger().error(err);
526
+ }
527
+ }
528
+ _setupIDs() {
529
+ if (this._driver.isUsingSyncAPI()) {
530
+ const syncTargetMessageID = this._getTargetMessageID();
531
+ if (syncTargetMessageID) {
532
+ this._driver
533
+ .getGmailMessageIdForSyncMessageId(syncTargetMessageID)
534
+ .then((gmailMessageId) => (this._targetMessageID = gmailMessageId));
181
535
  }
182
- case 'emailSent':
183
- {
184
- const response = GmailResponseProcessor.interpretSentEmailResponse(event.response);
185
- if ((0, _includes.default)(['tr', 'eu'], response.messageID)) {
186
- return [{
187
- eventName: 'sendCanceled'
188
- }];
189
- }
190
- this._emailWasSent = true;
191
- if (response.messageID) {
192
- this._finalMessageId = response.messageID;
193
- }
194
- this._messageId = null;
195
- const data = {
196
- getThreadID: () => Promise.resolve(response.threadID),
197
- getMessageID: () => Promise.resolve(response.messageID)
198
- };
199
- ['threadID', 'gmailThreadId'].forEach(prop => {
200
- // These properties are nonenumerable.
201
- Object.defineProperty(data, prop, {
202
- get: () => {
203
- this._driver.getLogger().deprecationWarning(`composeView sent event.${prop}`, 'composeView sent event.getThreadID()');
204
- return response.threadID;
205
- }
536
+ const syncMessageId = this._getMessageIDfromForm();
537
+ if (syncMessageId) {
538
+ this._driver
539
+ .getGmailMessageIdForSyncDraftId(syncMessageId)
540
+ .then((gmailMessageId) => {
541
+ this._initialMessageId = gmailMessageId;
542
+ this._messageId = gmailMessageId;
543
+ })
544
+ .catch(() => {
545
+ //do nothing because this means the message hasn't been saved yet
206
546
  });
207
- });
208
- ['messageID', 'gmailMessageId'].forEach(prop => {
209
- Object.defineProperty(data, prop, {
210
- get: () => {
211
- this._driver.getLogger().deprecationWarning(`composeView sent event.${prop}`, 'composeView sent event.getMessageID()');
212
- return response.messageID;
213
- }
547
+ this._driver.reportRecentSyncDraftId(syncMessageId);
548
+ this._stopper.onValue(() => {
549
+ this._driver.reportDraftClosed(syncMessageId);
214
550
  });
215
- });
216
- return [{
217
- eventName: 'sent',
218
- data
219
- }];
220
551
  }
221
- case 'emailDraftSaveSending':
222
- {
223
- this._draftSaving = true;
224
- return [{
225
- eventName: 'draftSaving'
226
- }];
552
+ else {
553
+ this._driver
554
+ .getLogger()
555
+ .error(new Error('Draft is missing sync draft id'));
227
556
  }
228
- case 'emailDraftReceived':
229
- {
230
- this._draftSaving = false;
231
- let response;
232
- try {
233
- response = GmailResponseProcessor.interpretSentEmailResponse(event.response);
234
- } catch (err) {
235
- if (this._driver.getAppId() === 'sdk_streak_21e9788951') {
236
- this._driver.getLogger().error(err, {
237
- connectionDetails: event.connectionDetails,
238
- response: event.response
239
- });
240
- throw err;
241
- } else {
242
- throw err;
557
+ const legacyThreadIdElement = this._element.querySelector('input[name="lts"]');
558
+ if (legacyThreadIdElement &&
559
+ typeof legacyThreadIdElement.value === 'string')
560
+ this._threadID = legacyThreadIdElement.value;
561
+ }
562
+ else {
563
+ this._targetMessageID = this._getTargetMessageID();
564
+ this._messageId = this._initialMessageId = this._getMessageIDfromForm();
565
+ this._threadID = this._getThreadID();
566
+ }
567
+ }
568
+ _updateComposeFullscreenState() {
569
+ if (this._isInlineReplyForm) {
570
+ this._isFullscreen = false;
571
+ }
572
+ else {
573
+ if (this._isStandalone) {
574
+ this._isFullscreen = true;
575
+ }
576
+ else {
577
+ const fullScreenContainer = GmailElementGetter.getFullscreenComposeWindowContainer();
578
+ if (!fullScreenContainer) {
579
+ this._isFullscreen = false;
243
580
  }
244
- }
245
- if (response.messageID === 'eu') {
246
- return []; // save was canceled
247
- }
248
-
249
- const events = [{
250
- eventName: 'draftSaved',
251
- data: response
252
- }];
253
- if (!response.messageID) {
254
- this._driver.getLogger().error(new Error('Missing message id from emailDraftReceived'));
255
- } else if (response.messageID && this._messageId !== response.messageID) {
256
- if (/^[0-9a-f]+$/i.test(response.messageID)) {
257
- this._messageId = response.messageID;
258
- events.push({
259
- eventName: 'messageIDChange',
260
- data: this._messageId
261
- });
262
- } else {
263
- this._driver.getLogger().error(new Error('Invalid message id from emailDraftReceived'), {
264
- value: response.messageID
265
- });
581
+ else {
582
+ this._isFullscreen = fullScreenContainer.contains(this._element);
266
583
  }
267
- }
268
- return events;
269
584
  }
270
- default:
271
- return [];
272
585
  }
273
- }).flatten().map(event => {
274
- if (this._driver.getLogger().shouldTrackEverything()) {
275
- driver.getLogger().eventSite('compose.debug.xhr', {
276
- eventName: event.eventName
277
- });
586
+ }
587
+ focus() {
588
+ focus(this);
589
+ }
590
+ insertBodyTextAtCursor(text) {
591
+ return this.insertBodyHTMLAtCursor(escape(text).replace(/\n/g, '<br>'));
592
+ }
593
+ insertBodyHTMLAtCursor(html) {
594
+ var retVal = insertHTMLatCursor(this.getBodyElement(), html, this.getLastSelectionRange());
595
+ this._triggerDraftSave();
596
+ // sometimes the html inserted can be quite large, so we need ot make sure that GMail resizes the compose window
597
+ // triggering an enter press forces Gmail to resize compose
598
+ simulateKey(this.getBodyElement(), 13, 13);
599
+ return retVal;
600
+ }
601
+ insertLinkIntoBody(text, href) {
602
+ var retVal = insertLinkIntoBody(this, text, href);
603
+ this._triggerDraftSave();
604
+ return retVal;
605
+ }
606
+ insertLinkChipIntoBody(options) {
607
+ var retVal = insertLinkChipIntoBody(this, options);
608
+ this._triggerDraftSave();
609
+ return retVal;
610
+ }
611
+ setSubject(text) {
612
+ this._element.querySelector('input[name=subjectbox]').value = text;
613
+ this._triggerDraftSave();
614
+ }
615
+ setBodyHTML(html) {
616
+ this.getBodyElement().innerHTML = html;
617
+ this._triggerDraftSave();
618
+ }
619
+ setBodyText(text) {
620
+ this.getBodyElement().textContent = text;
621
+ this._triggerDraftSave();
622
+ }
623
+ setToRecipients(emails) {
624
+ setRecipients(this, 'to', emails);
625
+ this._triggerDraftSave();
626
+ }
627
+ setCcRecipients(emails) {
628
+ setRecipients(this, 'cc', emails);
629
+ this._triggerDraftSave();
630
+ }
631
+ setBccRecipients(emails) {
632
+ setRecipients(this, 'bcc', emails);
633
+ this._triggerDraftSave();
634
+ }
635
+ addRecipientRow(options) {
636
+ return addRecipientRow(this, options);
637
+ }
638
+ forceRecipientRowsOpen() {
639
+ this._element.classList.add('inboxsdk__compose_forceRecipientsOpen');
640
+ return () => {
641
+ this._element.classList.remove('inboxsdk__compose_forceRecipientsOpen');
642
+ };
643
+ }
644
+ hideNativeRecipientRows() {
645
+ const nativeRecipientRows = getRecipientRowElements(this._element);
646
+ nativeRecipientRows.forEach((row) => {
647
+ row.classList.add('inboxsdk__compose_forceRecipientRowHidden');
648
+ });
649
+ return () => {
650
+ nativeRecipientRows.forEach((row) => {
651
+ row.classList.remove('inboxsdk__compose_forceRecipientRowHidden');
652
+ });
653
+ };
654
+ }
655
+ hideRecipientArea() {
656
+ this._element.classList.add('inboxsdk__compose_hideRecipientArea');
657
+ return () => {
658
+ this._element.classList.remove('inboxsdk__compose_hideRecipientArea');
659
+ };
660
+ }
661
+ getFromContact() {
662
+ return fromManager.getFromContact(this._driver, this);
663
+ }
664
+ getFromContactChoices() {
665
+ return fromManager.getFromContactChoices(this._driver, this);
666
+ }
667
+ setFromEmail(email) {
668
+ fromManager.setFromEmail(this._driver, this, email);
669
+ }
670
+ addButton(buttonDescriptor, groupOrderHint, extraOnClickOptions) {
671
+ return addButton(this, buttonDescriptor, groupOrderHint, extraOnClickOptions);
672
+ }
673
+ addTooltipToButton(buttonViewController, buttonDescriptor, tooltipDescriptor) {
674
+ var tooltip = addTooltipToButton(this, buttonViewController, buttonDescriptor, tooltipDescriptor);
675
+ this._buttonViewControllerTooltipMap.set(buttonViewController, tooltip);
676
+ }
677
+ closeButtonTooltip(buttonViewController) {
678
+ if (!this._buttonViewControllerTooltipMap) {
679
+ return;
278
680
  }
279
- return event;
280
- });
281
- }
282
- this._eventStream.plug(Kefir.merge([saveAndSendStream, Kefir.fromEvents(this._element, 'buttonAdded').map(() => {
283
- return {
284
- eventName: 'buttonAdded'
285
- };
286
- }), Kefir.fromEvents(this._element, 'resize').map(() => ({
287
- eventName: 'resize'
288
- })), Kefir.fromEvents(this._element, 'composeFullscreenStateChanged').map(() => {
289
- this._updateComposeFullscreenState();
290
- return {
291
- eventName: 'fullscreenChanged',
292
- data: {
293
- fullscreen: this._isFullscreen
681
+ var tooltip = this._buttonViewControllerTooltipMap.get(buttonViewController);
682
+ if (tooltip) {
683
+ tooltip.destroy();
684
+ this._buttonViewControllerTooltipMap.delete(buttonViewController);
294
685
  }
295
- };
296
- })]));
297
- Kefir.fromEvents(this._element, 'closedProgrammatically').takeUntilBy(this._stopper).onValue(() => {
298
- this._closedProgrammatically = true;
299
- });
300
- this._buttonViewControllerTooltipMap = new WeakMap();
301
- const initialBodyElement = this.getMaybeBodyElement();
302
- this.ready = (0, _constant.default)((initialBodyElement ? Kefir.constant(initialBodyElement) : (0, _streamWaitFor.default)(() => this.getMaybeBodyElement(), 3 * 60 * 1000 //timeout
303
- )).takeUntilBy(this._stopper).map(bodyElement => {
304
- this._seenBodyElement = bodyElement;
305
- this._composeID = this._element.querySelector('input[name="composeid"]').value;
306
- this._messageIDElement = this._element.querySelector('input[name="draft"]');
307
- if (!this._messageIDElement) {
308
- driver.getLogger().error(new Error('Could not find compose message id field'));
309
- // stub so other things don't fail
310
- this._messageIDElement = document.createElement('input');
311
- }
312
- this._setupIDs();
313
- this._setupStreams();
314
- this._setupConsistencyCheckers();
315
- this._updateComposeFullscreenState();
316
- {
317
- // try and handle the case where the user types in a bad email address
318
- // we get the presending event but then no other events will pass because
319
- // a modal comes up informing the user of the bad email address
320
- this.getEventStream().filter(_ref => {
321
- let {
322
- eventName
323
- } = _ref;
324
- return eventName === 'presending';
325
- }).takeUntilBy(this._stopper).onValue(() => {
326
- (0, _makeElementChildStream.default)(document.body).map(event => event.el).filter(node => node.getAttribute && node.getAttribute('role') === 'alertdialog').takeUntilBy(Kefir.merge([this.getEventStream().filter(_ref2 => {
327
- let {
328
- eventName
329
- } = _ref2;
330
- return eventName === 'sendCanceled' || eventName === 'sending';
331
- }), Kefir.later(15)])).onValue(() => {
332
- this._eventStream.emit({
333
- eventName: 'sendCanceled'
334
- });
335
- });
336
- });
337
- }
338
- return this;
339
- }).toProperty());
340
- this.ready().onError(errorObject => {
341
- driver.getLogger().error(errorObject, {
342
- hasForm: !!this.getElement().querySelector('form'),
343
- class: this.getElement().getAttribute('class')
344
- });
345
- });
346
-
347
- // v2 Data behaves differently whereby the compose element is removed
348
- // from the page while the send is in flight instead of waiting for the
349
- // send to come back, so we have to handle that difference
350
- if (this._driver.isUsingSyncAPI()) {
351
- Kefir.merge([
352
- // if we get a presending then we let the other stream wait for
353
- // sent. But if we get a sendCanceled, then a regular destroy can
354
- // pass through
355
- this._removedFromDOMStopper.filterBy(this._eventStream.filter(_ref3 => {
356
- let {
357
- eventName
358
- } = _ref3;
359
- return eventName === 'presending' || eventName === 'sendCanceled';
360
- }).map(_ref4 => {
361
- let {
362
- eventName
363
- } = _ref4;
364
- return eventName === 'sendCanceled';
365
- }).toProperty(() => true)), Kefir.combine([this._removedFromDOMStopper, this._eventStream.filter(_ref5 => {
366
- let {
367
- eventName
368
- } = _ref5;
369
- return eventName === 'sent';
370
- })])]).take(1)
371
- // we delay asap here so that the event stream is not destroyed before listeners here the sent event
372
- .flatMap(() => (0, _delayAsap.default)(null)).onValue(() => this._destroy());
373
- } else {
374
- this._removedFromDOMStopper.onValue(() => this._destroy());
375
- }
376
- (0, _detectClassicRecipientsArea.default)();
377
- }
378
- destroy() {
379
- // this gets called when the element gets removed from the DOM
380
- // however we don't want to pass through that destroy event right away
381
- this._removedFromDOMStopper.destroy();
382
- this._page.dump();
383
- }
384
- _destroy() {
385
- this._eventStream.emit({
386
- eventName: 'destroy',
387
- data: {
388
- messageID: this.getMessageID(),
389
- closedByInboxSDK: this._closedProgrammatically
390
- }
391
- });
392
- this._eventStream.end();
393
- this._managedViewControllers.forEach(vc => {
394
- vc.destroy();
395
- });
396
- this._requestModifiers = {};
397
- this._managedViewControllers.length = 0;
398
- this._stopper.destroy();
399
- this._destroyed = true;
400
- }
401
- getStopper() {
402
- return this._stopper;
403
- }
404
- getEventStream() {
405
- return this._eventStream;
406
- }
407
- getGmailDriver() {
408
- return this._driver;
409
- }
410
- isDestroyed() {
411
- return this._destroyed;
412
- }
413
- _setupStreams() {
414
- this._eventStream.plug((0, _getAddressChangesStream.default)(this));
415
- this._eventStream.plug((0, _getBodyChangesStream.default)(this));
416
- this._eventStream.plug((0, _getResponseTypeChangesStream.default)(this));
417
- this._eventStream.plug((0, _getPresendingStream.default)({
418
- element: this.getElement(),
419
- sendButton: this.getSendButton(),
420
- sendAndArchive: this.getSendAndArchiveButton()
421
- }));
422
- let discardButton;
423
- try {
424
- discardButton = this.getDiscardButton();
425
- } catch (err) {
426
- // handle failures of this.getDiscardButton()
427
- this._driver.getLogger().errorSite(new Error('Failed to find discard button'), {
428
- html: (0, _censorHTMLstring.default)(this._element.outerHTML)
429
- });
430
- }
431
- if (discardButton) {
432
- this._eventStream.plug((0, _getDiscardStream.default)({
433
- element: this.getElement(),
434
- discardButton
435
- }));
436
- }
437
- this._eventStream.plug(Kefir.fromEvents(this.getElement(), 'inboxSDKsendCanceled').map(() => ({
438
- eventName: 'sendCanceled'
439
- })));
440
- this._eventStream.plug(Kefir.fromEvents(this.getElement(), 'inboxSDKdiscardCanceled').map(() => ({
441
- eventName: 'discardCanceled'
442
- })));
443
- this._eventStream.plug(Kefir.later(10).flatMap(() => (0, _getMinimizedStream.default)(this)).changes().map(minimized => ({
444
- eventName: minimized ? 'minimized' : 'restored'
445
- })));
446
- if (!this._driver.isUsingSyncAPI()) {
447
- (0, _makeMutationObserverChunkedStream.default)(this._messageIDElement, {
448
- attributes: true,
449
- attributeFilter: ['value']
450
- }).takeUntilBy(this._eventStream.filter(() => false).beforeEnd(() => null)).map(() => this._getMessageIDfromForm()).filter(messageID => messageID && !this._emailWasSent && this._messageId !== messageID).onValue(messageID => {
451
- this._messageId = messageID;
452
- this._eventStream.emit({
453
- eventName: 'messageIDChange',
454
- data: this._messageId
686
+ }
687
+ addComposeNotice(options = {}) {
688
+ const composeNotice = addComposeNotice(this, options);
689
+ this._element.dispatchEvent(new CustomEvent('resize', {
690
+ bubbles: false,
691
+ cancelable: false,
692
+ detail: null,
693
+ }));
694
+ Kefir.fromEvents(composeNotice, 'destroy')
695
+ .flatMap(delayAsap)
696
+ .takeUntilBy(this._stopper)
697
+ .onValue(() => {
698
+ this._element.dispatchEvent(new CustomEvent('resize', {
699
+ bubbles: false,
700
+ cancelable: false,
701
+ detail: null,
702
+ }));
455
703
  });
456
- });
457
- }
458
- }
459
- _setupConsistencyCheckers() {
460
- try {
461
- (0, _handleComposeLinkChips.default)(this);
462
- (0, _monitorSelectionRange.default)(this);
463
- (0, _manageButtonGrouping.default)(this);
464
- (0, _sizeFixer.default)(this._driver, this);
465
- } catch (err) {
466
- this._driver.getLogger().error(err);
467
- }
468
- }
469
- _setupIDs() {
470
- if (this._driver.isUsingSyncAPI()) {
471
- const syncTargetMessageID = this._getTargetMessageID();
472
- if (syncTargetMessageID) {
473
- this._driver.getGmailMessageIdForSyncMessageId(syncTargetMessageID).then(gmailMessageId => this._targetMessageID = gmailMessageId);
474
- }
475
- const syncMessageId = this._getMessageIDfromForm();
476
- if (syncMessageId) {
477
- this._driver.getGmailMessageIdForSyncDraftId(syncMessageId).then(gmailMessageId => {
478
- this._initialMessageId = gmailMessageId;
479
- this._messageId = gmailMessageId;
480
- }).catch(() => {
481
- //do nothing because this means the message hasn't been saved yet
704
+ return composeNotice;
705
+ }
706
+ addStatusBar(options = {}) {
707
+ const statusBar = addStatusBar(this, options);
708
+ this._element.dispatchEvent(new CustomEvent('resize', {
709
+ bubbles: false,
710
+ cancelable: false,
711
+ detail: null,
712
+ }));
713
+ Kefir.fromEvents(statusBar, 'destroy')
714
+ .flatMap(delayAsap)
715
+ .takeUntilBy(this._stopper)
716
+ .onValue(() => {
717
+ this._element.dispatchEvent(new CustomEvent('resize', {
718
+ bubbles: false,
719
+ cancelable: false,
720
+ detail: null,
721
+ }));
482
722
  });
483
- this._driver.reportRecentSyncDraftId(syncMessageId);
484
- this._stopper.onValue(() => {
485
- this._driver.reportDraftClosed(syncMessageId);
723
+ return statusBar;
724
+ }
725
+ hideNativeStatusBar() {
726
+ const statusArea = this.getStatusArea();
727
+ const nativeStatusBar = querySelector(statusArea, 'table');
728
+ const formattingToolbar = this.getFormattingToolbar();
729
+ const isFormattingToolbarOpen = formattingToolbar && formattingToolbar.style.display !== 'none';
730
+ nativeStatusBar.style.display = 'none';
731
+ if (formattingToolbar && isFormattingToolbarOpen) {
732
+ formattingToolbar.style.display = 'none';
733
+ }
734
+ return () => {
735
+ nativeStatusBar.style.display = '';
736
+ if (formattingToolbar && isFormattingToolbarOpen) {
737
+ formattingToolbar.style.display = '';
738
+ }
739
+ };
740
+ }
741
+ replaceSendButton(el) {
742
+ const sendButton = this.getSendButtonGroup();
743
+ const sendAndArchive = this.getSendAndArchiveButton();
744
+ sendButton.style.display = 'none';
745
+ const sendAndArchiveParent = sendAndArchive && sendAndArchive.parentElement;
746
+ if (sendAndArchiveParent instanceof HTMLElement) {
747
+ sendAndArchiveParent.style.display = 'none';
748
+ }
749
+ const container = document.createElement('div');
750
+ container.classList.add('inboxsdk__compose_customSendContainer');
751
+ container.appendChild(el);
752
+ sendButton.insertAdjacentElement('afterend', container);
753
+ this._element.setAttribute('data-inboxsdk-send-replaced', '');
754
+ const removalStopper = kefirStopper();
755
+ Kefir.fromEvents(this.getBodyElement(), 'keydown')
756
+ .takeUntilBy(this._stopper)
757
+ .takeUntilBy(removalStopper)
758
+ .filter((domEvent) => (domEvent.which === 9 || domEvent.keyCode === 9) && !domEvent.shiftKey)
759
+ .onValue((domEvent) => {
760
+ // Because of the way the compose DOM is structured, the natural
761
+ // tab order does not flow from the compose body to the status bar.
762
+ // Gmail modifies this flow programatically by focusing the send button,
763
+ // so we have replicate this behavior when the native send button isn't
764
+ // visible.
765
+ const statusArea = this.getStatusArea();
766
+ const focusableEls = statusArea.querySelectorAll('[tabindex]');
767
+ if (focusableEls.length === 0)
768
+ return;
769
+ const firstVisibleEl = Array.from(focusableEls).find((el) => el.offsetParent !== null);
770
+ if (!firstVisibleEl)
771
+ return;
772
+ domEvent.preventDefault();
773
+ domEvent.stopPropagation();
774
+ domEvent.stopImmediatePropagation();
775
+ firstVisibleEl.focus();
486
776
  });
487
- } else {
488
- this._driver.getLogger().error(new Error('Draft is missing sync draft id'));
489
- }
490
- const legacyThreadIdElement = this._element.querySelector('input[name="lts"]');
491
- if (legacyThreadIdElement && typeof legacyThreadIdElement.value === 'string') this._threadID = legacyThreadIdElement.value;
492
- } else {
493
- this._targetMessageID = this._getTargetMessageID();
494
- this._messageId = this._initialMessageId = this._getMessageIDfromForm();
495
- this._threadID = this._getThreadID();
496
- }
497
- }
498
- _updateComposeFullscreenState() {
499
- if (this._isInlineReplyForm) {
500
- this._isFullscreen = false;
501
- } else {
502
- if (this._isStandalone) {
503
- this._isFullscreen = true;
504
- } else {
505
- const fullScreenContainer = _gmailElementGetter.default.getFullscreenComposeWindowContainer();
506
- if (!fullScreenContainer) {
507
- this._isFullscreen = false;
508
- } else {
509
- this._isFullscreen = fullScreenContainer.contains(this._element);
777
+ return () => {
778
+ removalStopper.destroy();
779
+ container.remove();
780
+ this._element.removeAttribute('data-inboxsdk-send-replaced');
781
+ sendButton.style.display = '';
782
+ if (sendAndArchiveParent instanceof HTMLElement) {
783
+ sendAndArchiveParent.style.display = '';
784
+ }
785
+ };
786
+ }
787
+ hideDiscardButton() {
788
+ const discardBtn = this.getDiscardButton();
789
+ discardBtn.style.display = 'none';
790
+ return () => {
791
+ discardBtn.style.display = '';
792
+ };
793
+ }
794
+ ensureFormattingToolbarIsHidden() {
795
+ const formattingToggleButton = this.getFormattingToolbarToggleButton();
796
+ const formattingToolbar = this.getFormattingToolbar();
797
+ if (formattingToggleButton &&
798
+ formattingToolbar &&
799
+ formattingToolbar.style.display === '') {
800
+ simulateClick(formattingToggleButton);
510
801
  }
511
- }
512
- }
513
- }
514
- focus() {
515
- (0, _focus.default)(this);
516
- }
517
- insertBodyTextAtCursor(text) {
518
- return this.insertBodyHTMLAtCursor((0, _escape.default)(text).replace(/\n/g, '<br>'));
519
- }
520
- insertBodyHTMLAtCursor(html) {
521
- var retVal = (0, _insertHtmlAtCursor.default)(this.getBodyElement(), html, this.getLastSelectionRange());
522
- this._triggerDraftSave();
523
-
524
- // sometimes the html inserted can be quite large, so we need ot make sure that GMail resizes the compose window
525
- // triggering an enter press forces Gmail to resize compose
526
- (0, _simulateKey.default)(this.getBodyElement(), 13, 13);
527
- return retVal;
528
- }
529
- insertLinkIntoBody(text, href) {
530
- var retVal = (0, _insertLinkIntoBody.default)(this, text, href);
531
- this._triggerDraftSave();
532
- return retVal;
533
- }
534
- insertLinkChipIntoBody(options) {
535
- var retVal = (0, _insertLinkChipIntoBody.default)(this, options);
536
- this._triggerDraftSave();
537
- return retVal;
538
- }
539
- setSubject(text) {
540
- this._element.querySelector('input[name=subjectbox]').value = text;
541
- this._triggerDraftSave();
542
- }
543
- setBodyHTML(html) {
544
- this.getBodyElement().innerHTML = html;
545
- this._triggerDraftSave();
546
- }
547
- setBodyText(text) {
548
- this.getBodyElement().textContent = text;
549
- this._triggerDraftSave();
550
- }
551
- setToRecipients(emails) {
552
- (0, _setRecipients.default)(this, 'to', emails);
553
- this._triggerDraftSave();
554
- }
555
- setCcRecipients(emails) {
556
- (0, _setRecipients.default)(this, 'cc', emails);
557
- this._triggerDraftSave();
558
- }
559
- setBccRecipients(emails) {
560
- (0, _setRecipients.default)(this, 'bcc', emails);
561
- this._triggerDraftSave();
562
- }
563
- addRecipientRow(options) {
564
- return (0, _addRecipientRow.default)(this, options);
565
- }
566
- forceRecipientRowsOpen() {
567
- this._element.classList.add('inboxsdk__compose_forceRecipientsOpen');
568
- return () => {
569
- this._element.classList.remove('inboxsdk__compose_forceRecipientsOpen');
570
- };
571
- }
572
- hideNativeRecipientRows() {
573
- const nativeRecipientRows = (0, _pageParser.getRecipientRowElements)(this._element);
574
- nativeRecipientRows.forEach(row => {
575
- row.classList.add('inboxsdk__compose_forceRecipientRowHidden');
576
- });
577
- return () => {
578
- nativeRecipientRows.forEach(row => {
579
- row.classList.remove('inboxsdk__compose_forceRecipientRowHidden');
580
- });
581
- };
582
- }
583
- hideRecipientArea() {
584
- this._element.classList.add('inboxsdk__compose_hideRecipientArea');
585
- return () => {
586
- this._element.classList.remove('inboxsdk__compose_hideRecipientArea');
587
- };
588
- }
589
- getFromContact() {
590
- return fromManager.getFromContact(this._driver, this);
591
- }
592
- getFromContactChoices() {
593
- return fromManager.getFromContactChoices(this._driver, this);
594
- }
595
- setFromEmail(email) {
596
- fromManager.setFromEmail(this._driver, this, email);
597
- }
598
- addButton(buttonDescriptor, groupOrderHint, extraOnClickOptions) {
599
- return (0, _addButton.default)(this, buttonDescriptor, groupOrderHint, extraOnClickOptions);
600
- }
601
- addTooltipToButton(buttonViewController, buttonDescriptor, tooltipDescriptor) {
602
- var tooltip = (0, _addTooltipToButton.default)(this, buttonViewController, buttonDescriptor, tooltipDescriptor);
603
- this._buttonViewControllerTooltipMap.set(buttonViewController, tooltip);
604
- }
605
- closeButtonTooltip(buttonViewController) {
606
- if (!this._buttonViewControllerTooltipMap) {
607
- return;
608
- }
609
- var tooltip = this._buttonViewControllerTooltipMap.get(buttonViewController);
610
- if (tooltip) {
611
- tooltip.destroy();
612
- this._buttonViewControllerTooltipMap.delete(buttonViewController);
613
- }
614
- }
615
- addComposeNotice() {
616
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
617
- const composeNotice = (0, _addComposeNotice.default)(this, options);
618
- this._element.dispatchEvent(new CustomEvent('resize', {
619
- bubbles: false,
620
- cancelable: false,
621
- detail: null
622
- }));
623
- Kefir.fromEvents(composeNotice, 'destroy').flatMap(_delayAsap.default).takeUntilBy(this._stopper).onValue(() => {
624
- this._element.dispatchEvent(new CustomEvent('resize', {
625
- bubbles: false,
626
- cancelable: false,
627
- detail: null
628
- }));
629
- });
630
- return composeNotice;
631
- }
632
- addStatusBar() {
633
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
634
- const statusBar = (0, _addStatusBar.default)(this, options);
635
- this._element.dispatchEvent(new CustomEvent('resize', {
636
- bubbles: false,
637
- cancelable: false,
638
- detail: null
639
- }));
640
- Kefir.fromEvents(statusBar, 'destroy').flatMap(_delayAsap.default).takeUntilBy(this._stopper).onValue(() => {
641
- this._element.dispatchEvent(new CustomEvent('resize', {
642
- bubbles: false,
643
- cancelable: false,
644
- detail: null
645
- }));
646
- });
647
- return statusBar;
648
- }
649
- hideNativeStatusBar() {
650
- const statusArea = this.getStatusArea();
651
- const nativeStatusBar = (0, _querySelectorOrFail.default)(statusArea, 'table');
652
- const formattingToolbar = this.getFormattingToolbar();
653
- const isFormattingToolbarOpen = formattingToolbar && formattingToolbar.style.display !== 'none';
654
- nativeStatusBar.style.display = 'none';
655
- if (formattingToolbar && isFormattingToolbarOpen) {
656
- formattingToolbar.style.display = 'none';
657
- }
658
- return () => {
659
- nativeStatusBar.style.display = '';
660
- if (formattingToolbar && isFormattingToolbarOpen) {
661
- formattingToolbar.style.display = '';
662
- }
663
- };
664
- }
665
- replaceSendButton(el) {
666
- const sendButton = this.getSendButtonGroup();
667
- const sendAndArchive = this.getSendAndArchiveButton();
668
- sendButton.style.display = 'none';
669
- const sendAndArchiveParent = sendAndArchive && sendAndArchive.parentElement;
670
- if (sendAndArchiveParent instanceof HTMLElement) {
671
- sendAndArchiveParent.style.display = 'none';
672
- }
673
- const container = document.createElement('div');
674
- container.classList.add('inboxsdk__compose_customSendContainer');
675
- container.appendChild(el);
676
- sendButton.insertAdjacentElement('afterend', container);
677
- this._element.setAttribute('data-inboxsdk-send-replaced', '');
678
- const removalStopper = (0, _kefirStopper.default)();
679
- Kefir.fromEvents(this.getBodyElement(), 'keydown').takeUntilBy(this._stopper).takeUntilBy(removalStopper).filter(domEvent => (domEvent.which === 9 || domEvent.keyCode === 9) && !domEvent.shiftKey).onValue(domEvent => {
680
- // Because of the way the compose DOM is structured, the natural
681
- // tab order does not flow from the compose body to the status bar.
682
- // Gmail modifies this flow programatically by focusing the send button,
683
- // so we have replicate this behavior when the native send button isn't
684
- // visible.
685
- const statusArea = this.getStatusArea();
686
- const focusableEls = statusArea.querySelectorAll('[tabindex]');
687
- if (focusableEls.length === 0) return;
688
- const firstVisibleEl = Array.from(focusableEls).find(el => el.offsetParent !== null);
689
- if (!firstVisibleEl) return;
690
- domEvent.preventDefault();
691
- domEvent.stopPropagation();
692
- domEvent.stopImmediatePropagation();
693
- firstVisibleEl.focus();
694
- });
695
- return () => {
696
- removalStopper.destroy();
697
- container.remove();
698
- this._element.removeAttribute('data-inboxsdk-send-replaced');
699
- sendButton.style.display = '';
700
- if (sendAndArchiveParent instanceof HTMLElement) {
701
- sendAndArchiveParent.style.display = '';
702
- }
703
- };
704
- }
705
- hideDiscardButton() {
706
- const discardBtn = this.getDiscardButton();
707
- discardBtn.style.display = 'none';
708
- return () => {
709
- discardBtn.style.display = '';
710
- };
711
- }
712
- ensureFormattingToolbarIsHidden() {
713
- const formattingToggleButton = this.getFormattingToolbarToggleButton();
714
- const formattingToolbar = this.getFormattingToolbar();
715
- if (formattingToggleButton && formattingToolbar && formattingToolbar.style.display === '') {
716
- (0, _simulateMouseEvent.simulateClick)(formattingToggleButton);
717
- }
718
- }
719
- close() {
720
- if (this.isInlineReplyForm()) {
721
- console.warn("Trying to close an inline reply which doesn't work.");
722
- return;
723
- }
724
- this._element.dispatchEvent(new CustomEvent('closedProgrammatically', {
725
- bubbles: false,
726
- cancelable: false,
727
- detail: null
728
- }));
729
- if (this._isFullscreen) {
730
- this._eventStream.filter(_ref6 => {
731
- let {
732
- eventName
733
- } = _ref6;
734
- return eventName === 'fullscreenChanged';
735
- }).onValue(() => (0, _simulateMouseEvent.simulateClick)(this.getCloseButton()));
736
- (0, _simulateMouseEvent.simulateClick)(this.getMoleSwitchButton());
737
- } else {
738
- (0, _simulateMouseEvent.simulateClick)(this.getCloseButton());
739
- }
740
- }
741
- send(_ref7) {
742
- let {
743
- sendAndArchive
744
- } = _ref7;
745
- // asap necessary so if send() is called after presending event.cancel(), the new presending event
746
- // must happen after the sendCanceled event (which is also delayed by asap).
747
- (0, _asap.default)(() => {
748
- const sendAndArchiveButton = this.getSendAndArchiveButton();
749
- if (sendAndArchive && sendAndArchiveButton) {
750
- (0, _simulateMouseEvent.simulateClick)(sendAndArchiveButton);
751
- } else {
752
- (0, _simulateMouseEvent.simulateClick)(this.getSendButton());
753
- }
754
- });
755
- }
756
- discard() {
757
- (0, _simulateMouseEvent.simulateClick)(this.getDiscardButton());
758
- }
759
- popOut() {
760
- if (!this.isInlineReplyForm()) {
761
- throw new Error('Can only pop out inline reply compose views');
762
- }
763
- const popOutBtn = (0, _querySelectorOrFail.default)(this._element, '.M9 > [role=menu]:first-child > .SK > [role=menuitem]:last-child');
764
- (0, _simulateMouseEvent.simulateClick)(popOutBtn);
765
- }
766
- overrideEditSubject() {
767
- (0, _overrideEditSubject.default)(this._driver, this);
768
- }
769
- _hideDropzones() {
770
- (0, _setCss.default)('compose dropzone hider', 'body > .aC7 .aC9 {visibility: hidden;}');
771
- }
772
- _reenableDropzones() {
773
- (0, _setCss.default)('compose dropzone hider', null);
774
- }
775
- _dropzonesVisible() {
776
- return (0, _find.default)(document.querySelectorAll('body > .aC7:not(.aWP)'), _isElementVisible.default) != null;
777
- }
778
- _findDropzoneForThisCompose(inline) {
779
- // Iterate through all the dropzones and find the one visually contained by
780
- // this compose.
781
- const rect = this._element.getBoundingClientRect();
782
- const dropzoneSelector = inline ? 'body > .aC7:not(.aWP)' : 'body > .aC7.aWP';
783
- const el = _transducers.default.toArray(Array.prototype.slice.call(document.querySelectorAll(dropzoneSelector)), _transducers.default.compose(_transducers.default.filter(_isElementVisible.default), _transducers.default.filter(dropzone => {
784
- const top = parseInt(dropzone.style.top, 10);
785
- const bottom = top + parseInt(dropzone.style.height, 10);
786
- const left = parseInt(dropzone.style.left, 10);
787
- const right = left + parseInt(dropzone.style.width, 10);
788
- return top >= rect.top && left >= rect.left && right <= rect.right && bottom <= rect.bottom;
789
- }), _transducers.default.take(1)))[0];
790
- if (!el) {
791
- throw new Error('Failed to find dropzone');
792
- }
793
- return el;
794
- }
795
- async _attachFiles(files, inline) {
796
- this._hideDropzones();
797
- const endDrag = (0, _once.default)(() => (0, _simulateDragAndDrop.simulateDragEnd)(this._element, files));
798
- try {
799
- let firstLoop = true;
800
- for (let partitionedFiles of _transducers.default.partition(files, 3)) {
801
- if (firstLoop) {
802
- firstLoop = false;
803
- } else {
804
- await (0, _pdelay.default)(500);
802
+ }
803
+ close() {
804
+ if (this.isInlineReplyForm()) {
805
+ console.warn("Trying to close an inline reply which doesn't work.");
806
+ return;
805
807
  }
806
- (0, _simulateDragAndDrop.simulateDragOver)(this._element, partitionedFiles);
807
- await (0, _waitFor.default)(() => this._dropzonesVisible(), 20 * 1000);
808
- const dropzone = this._findDropzoneForThisCompose(inline);
809
- (0, _simulateDragAndDrop.simulateDrop)(dropzone, partitionedFiles);
810
- endDrag();
811
- await (0, _waitFor.default)(() => !this._dropzonesVisible(), 20 * 1000);
812
- }
813
- } catch (err) {
814
- this._driver.getLogger().error(err);
815
- } finally {
816
- endDrag();
817
- this._reenableDropzones();
818
- }
819
- }
820
- attachFiles(files) {
821
- return this._attachFiles(files, false);
822
- }
823
- attachInlineFiles(files) {
824
- return this._attachFiles(files, true);
825
- }
826
- isForward() {
827
- return Boolean(this._element.querySelector('.Un.J-JN-M-I .mI'));
828
- }
829
- isReply() {
830
- return this._isInlineReplyForm || !!this._element.querySelector('.HQ');
831
- }
832
- isInlineReplyForm() {
833
- return this._isInlineReplyForm;
834
- }
835
- getBodyElement() {
836
- const el = this.getMaybeBodyElement();
837
- if (!el) throw new Error('Could not find body element');
838
- return el;
839
- }
840
- getMaybeBodyElement() {
841
- return this._element.querySelector('.Ap [g_editable=true]');
842
- }
843
- getTopFormElement() {
844
- return (0, _querySelectorOrFail.default)(this._element, 'td > form');
845
- }
846
- getHTMLContent() {
847
- return this.getBodyElement().innerHTML;
848
- }
849
- getTextContent() {
850
- return this.getBodyElement().textContent;
851
- }
852
- getSelectedBodyHTML() {
853
- return (0, _getSelection.getSelectedHTMLInElement)(this.getBodyElement(), this.getLastSelectionRange());
854
- }
855
- getSelectedBodyText() {
856
- return (0, _getSelection.getSelectedTextInElement)(this.getBodyElement(), this.getLastSelectionRange());
857
- }
858
- getSubject() {
859
- return this.getSubjectInput().value;
860
- }
861
- getSubjectInput() {
862
- return this._element.querySelector('input[name=subjectbox]');
863
- }
864
- getMetadataFormElement() {
865
- const container = this.getBodyElement().closest('.aoP');
866
- if (!container) {
867
- throw new Error('Could not find compose container');
868
- }
869
- return (0, _querySelectorOrFail.default)(container, 'form.bAs');
870
- }
871
- getToRecipients() {
872
- return (0, _getRecipients.default)(this, 'to');
873
- }
874
- getCcRecipients() {
875
- return (0, _getRecipients.default)(this, 'cc');
876
- }
877
- getBccRecipients() {
878
- return (0, _getRecipients.default)(this, 'bcc');
879
- }
880
- getAdditionalActionToolbar() {
881
- return require('./gmail-compose-view/get-additional-action-toolbar').default(this);
882
- }
883
- updateInsertMoreAreaLeft(oldFormattingAreaOffsetLeft) {
884
- (0, _updateInsertMoreAreaLeft.default)(this, oldFormattingAreaOffsetLeft);
885
- }
886
- _getFormattingAreaOffsetLeft() {
887
- return (0, _getFormattingAreaOffsetLeft.default)(this);
888
- }
889
- getFormattingArea() {
890
- let formattingArea = this._formattingArea;
891
- if (!formattingArea) {
892
- formattingArea = this._formattingArea = this._element.querySelector('.oc');
893
- }
894
- return formattingArea;
895
- }
896
- getFormattingToolbar() {
897
- return this._element.querySelector('.aX');
898
- }
899
- getFormattingToolbarArrow() {
900
- const el = this.getFormattingToolbar();
901
- if (!el) throw new Error('Failed to find formatting toolbar');
902
- return (0, _querySelectorOrFail.default)(el, '.aA4');
903
- }
904
- getFormattingToolbarToggleButton() {
905
- const innerElement = (0, _querySelectorOrFail.default)(this._element, '[role=button] .dv');
906
- const btn = (0, _closestNg.default)(innerElement, '[role=button]');
907
- if (!btn) throw new Error('failed to find button');
908
- return btn;
909
- }
910
- getStatusBarPrependContainer() {
911
- return this._element.querySelector('.inboxsdk__compose_statusBarPrependContainer');
912
- }
913
- getScrollBody() {
914
- var scrollBody = this._element.querySelector('table .GP');
915
- if (!scrollBody) {
916
- throw new Error('Failed to find scroll body');
917
- }
918
- return scrollBody;
919
- }
920
- getStatusArea() {
921
- let statusArea = this._element.querySelector('.aDg .aDj > .aDh');
922
- if (!statusArea) throw new Error('Failed to find status area');
923
- return statusArea;
924
- }
925
- getInsertMoreArea() {
926
- return (0, _querySelectorOrFail.default)(this._element, '.eq');
927
- }
928
- getInsertLinkButton() {
929
- return (0, _querySelectorOrFail.default)(this._element, '.e5.aaA.aMZ');
930
- }
931
- getSendButton() {
932
- return (0, _querySelectorOrFail.default)(this._element, '.IZ .Up div > div[role=button]:not(.Uo):not([aria-haspopup=true]):not([class^=inboxsdk_])');
933
- }
934
-
935
- // When schedule send is available, this returns the element that contains both buttons.
936
- getSendButtonGroup() {
937
- const scheduleSend = this._element.querySelector('.IZ .Up div > [role=button][aria-haspopup=true]:not([class^=inboxsdk_])');
938
- if (scheduleSend) {
939
- return scheduleSend.parentElement;
940
- }
941
- return this.getSendButton();
942
- }
943
- getSendAndArchiveButton() {
944
- if (!this.isReply()) {
945
- return null;
946
- }
947
- const sendAndArchiveButton = this._element.querySelector('.IZ .Up div > div[role=button].Uo:not([aria-haspopup=true]):not([class^=inboxsdk_])');
948
- if (sendAndArchiveButton) {
949
- return sendAndArchiveButton;
950
- }
951
-
952
- // TODO is the rest of this function necessary?
953
-
954
- const sendButton = this.getSendButton();
955
- const parent = sendButton.parentElement;
956
- if (!(parent instanceof HTMLElement)) throw new Error('should not happen');
957
- if (parent.childElementCount <= 1) {
958
- this._driver.getLogger().eventSdkPassive('getSendAndArchiveButton - old method - failed to find, childElementCount <= 1');
959
- return null;
960
- }
961
- const firstNotSendElement = parent.children[0] !== sendButton ? parent.children[0] : parent.children[1];
962
- const result = !firstNotSendElement ? null : firstNotSendElement.querySelector('[role=button]');
963
- if (result) {
964
- this._driver.getLogger().eventSdkPassive('getSendAndArchiveButton - old method - found');
965
- } else {
966
- this._driver.getLogger().eventSdkPassive('getSendAndArchiveButton - old method - failed to find');
967
- }
968
- return result;
969
- }
970
- getCloseButton() {
971
- return this._element.querySelectorAll('.Hm > img')[2];
972
- }
973
- getMoleSwitchButton() {
974
- return this._element.querySelectorAll('.Hm > img')[1];
975
- }
976
- getBottomBarTable() {
977
- return (0, _querySelectorOrFail.default)(this._element, '.aoP .aDh > table');
978
- }
979
- getBottomToolbarContainer() {
980
- return (0, _querySelectorOrFail.default)(this._element, '.aoP .aDj');
981
- }
982
- getDiscardButton() {
983
- return (0, _querySelectorOrFail.default)(this._element, '.gU .oh');
984
- }
985
- getComposeID() {
986
- return this._composeID;
987
- }
988
- getInitialMessageID() {
989
- return this._initialMessageId;
990
- }
991
-
992
- // For use only when isUsingSyncAPI() is true — gets the draft ID
993
- // from the input that used to hold the hex message ID. Still does not
994
- // populate until first save.
995
- _getDraftIDfromForm() {
996
- const value = this._messageIDElement && this._messageIDElement.value || null;
997
- if (typeof value === 'string' && value !== 'undefined' && value !== 'null') {
998
- if (this._driver.isUsingSyncAPI()) {
999
- return value.replace('#', '').replace('msg-a:', '');
1000
- } else {
1001
- this._driver.getLogger().error(new Error('Invalid draft id in element'), {
1002
- value
808
+ this._element.dispatchEvent(new CustomEvent('closedProgrammatically', {
809
+ bubbles: false,
810
+ cancelable: false,
811
+ detail: null,
812
+ }));
813
+ if (this._isFullscreen) {
814
+ this._eventStream
815
+ .filter(({ eventName }) => eventName === 'fullscreenChanged')
816
+ .onValue(() => simulateClick(this.getCloseButton()));
817
+ simulateClick(this.getMoleSwitchButton());
818
+ }
819
+ else {
820
+ simulateClick(this.getCloseButton());
821
+ }
822
+ }
823
+ send({ sendAndArchive }) {
824
+ // asap necessary so if send() is called after presending event.cancel(), the new presending event
825
+ // must happen after the sendCanceled event (which is also delayed by asap).
826
+ asap(() => {
827
+ const sendAndArchiveButton = this.getSendAndArchiveButton();
828
+ if (sendAndArchive && sendAndArchiveButton) {
829
+ simulateClick(sendAndArchiveButton);
830
+ }
831
+ else {
832
+ simulateClick(this.getSendButton());
833
+ }
1003
834
  });
1004
- }
1005
- }
1006
- return null;
1007
- }
1008
- _getMessageIDfromForm() {
1009
- const value = this._messageIDElement && this._messageIDElement.value || null;
1010
- if (typeof value === 'string' && value !== 'undefined' && value !== 'null') {
1011
- if (this._driver.isUsingSyncAPI()) {
1012
- return value.replace('#', ''); //annoyingly the hash is included
1013
- } else {
1014
- if (/^[0-9a-f]+$/i.test(value)) {
1015
- return value;
1016
- } else {
1017
- this._driver.getLogger().error(new Error('Invalid message id in element'), {
1018
- value
1019
- });
835
+ }
836
+ discard() {
837
+ simulateClick(this.getDiscardButton());
838
+ }
839
+ popOut() {
840
+ if (!this.isInlineReplyForm()) {
841
+ throw new Error('Can only pop out inline reply compose views');
842
+ }
843
+ const popOutBtn = querySelector(this._element, '.M9 > [role=menu]:first-child > .SK > [role=menuitem]:last-child');
844
+ simulateClick(popOutBtn);
845
+ }
846
+ overrideEditSubject() {
847
+ overrideEditSubject(this._driver, this);
848
+ }
849
+ _hideDropzones() {
850
+ setCss('compose dropzone hider', 'body > .aC7 .aC9 {visibility: hidden;}');
851
+ }
852
+ _reenableDropzones() {
853
+ setCss('compose dropzone hider', null);
854
+ }
855
+ _dropzonesVisible() {
856
+ return (find(document.querySelectorAll('body > .aC7:not(.aWP)'), isElementVisible) != null);
857
+ }
858
+ _findDropzoneForThisCompose(inline) {
859
+ // Iterate through all the dropzones and find the one visually contained by
860
+ // this compose.
861
+ const rect = this._element.getBoundingClientRect();
862
+ const dropzoneSelector = inline
863
+ ? 'body > .aC7:not(.aWP)'
864
+ : 'body > .aC7.aWP';
865
+ const el = t.toArray(Array.prototype.slice.call(document.querySelectorAll(dropzoneSelector)), t.compose(t.filter(isElementVisible), t.filter((dropzone) => {
866
+ const top = parseInt(dropzone.style.top, 10);
867
+ const bottom = top + parseInt(dropzone.style.height, 10);
868
+ const left = parseInt(dropzone.style.left, 10);
869
+ const right = left + parseInt(dropzone.style.width, 10);
870
+ return (top >= rect.top &&
871
+ left >= rect.left &&
872
+ right <= rect.right &&
873
+ bottom <= rect.bottom);
874
+ }), t.take(1)))[0];
875
+ if (!el) {
876
+ throw new Error('Failed to find dropzone');
1020
877
  }
1021
- }
1022
- }
1023
- return null;
1024
- }
1025
- getMessageID() {
1026
- return this._messageId;
1027
- }
1028
- getTargetMessageID() {
1029
- return this._targetMessageID;
1030
- }
1031
- getThreadID() {
1032
- return this._threadID;
1033
- }
1034
- async getCurrentDraftID() {
1035
- if (this._driver.isUsingSyncAPI()) {
1036
- // This function is mostly a mirror of _getDraftIDimplementation, but
1037
- // instead of waiting when finding out it's not saved, just returns null.
1038
-
1039
- const draftID = this._getDraftIDfromForm();
1040
- if (this._messageId) {
1041
- return draftID;
1042
- } else {
1043
- const syncMessageId = this._getMessageIDfromForm();
1044
- if (syncMessageId) {
1045
- try {
1046
- // If this succeeds, then the draft must exist on the server and we
1047
- // can safely return the draft id we know.
1048
- const gmailMessageId = await this._driver.getGmailMessageIdForSyncDraftId(syncMessageId);
1049
- } catch (e) {
1050
- // ignore error, it's probably that the draft isn't saved yet.
878
+ return el;
879
+ }
880
+ async _attachFiles(files, inline) {
881
+ this._hideDropzones();
882
+ const endDrag = once(() => simulateDragEnd(this._element, files));
883
+ try {
884
+ let firstLoop = true;
885
+ for (const partitionedFiles of t.partition(files, 3)) {
886
+ if (firstLoop) {
887
+ firstLoop = false;
888
+ }
889
+ else {
890
+ await delay(500);
891
+ }
892
+ simulateDragOver(this._element, partitionedFiles);
893
+ await waitFor(() => this._dropzonesVisible(), 20 * 1000);
894
+ const dropzone = this._findDropzoneForThisCompose(inline);
895
+ simulateDrop(dropzone, partitionedFiles);
896
+ endDrag();
897
+ await waitFor(() => !this._dropzonesVisible(), 20 * 1000);
898
+ }
899
+ }
900
+ catch (err) {
901
+ this._driver.getLogger().error(err);
902
+ }
903
+ finally {
904
+ endDrag();
905
+ this._reenableDropzones();
906
+ }
907
+ }
908
+ attachFiles(files) {
909
+ return this._attachFiles(files, false);
910
+ }
911
+ attachInlineFiles(files) {
912
+ return this._attachFiles(files, true);
913
+ }
914
+ isForward() {
915
+ return Boolean(this._element.querySelector('.Un.J-JN-M-I .mI'));
916
+ }
917
+ isReply() {
918
+ return this._isInlineReplyForm || !!this._element.querySelector('.HQ');
919
+ }
920
+ isInlineReplyForm() {
921
+ return this._isInlineReplyForm;
922
+ }
923
+ getBodyElement() {
924
+ const el = this.getMaybeBodyElement();
925
+ if (!el)
926
+ throw new Error('Could not find body element');
927
+ return el;
928
+ }
929
+ getMaybeBodyElement() {
930
+ return this._element.querySelector('.Ap [g_editable=true]');
931
+ }
932
+ getTopFormElement() {
933
+ return querySelector(this._element, 'td > form');
934
+ }
935
+ getHTMLContent() {
936
+ return this.getBodyElement().innerHTML;
937
+ }
938
+ getTextContent() {
939
+ return this.getBodyElement().textContent;
940
+ }
941
+ getSelectedBodyHTML() {
942
+ return getSelectedHTMLInElement(this.getBodyElement(), this.getLastSelectionRange());
943
+ }
944
+ getSelectedBodyText() {
945
+ return getSelectedTextInElement(this.getBodyElement(), this.getLastSelectionRange());
946
+ }
947
+ getSubject() {
948
+ return this.getSubjectInput().value;
949
+ }
950
+ getSubjectInput() {
951
+ return this._element.querySelector('input[name=subjectbox]');
952
+ }
953
+ getMetadataFormElement() {
954
+ const container = this.getBodyElement().closest('.aoP');
955
+ if (!container) {
956
+ throw new Error('Could not find compose container');
957
+ }
958
+ return querySelector(container, 'form.bAs');
959
+ }
960
+ getToRecipients() {
961
+ return getRecipients(this, 'to');
962
+ }
963
+ getCcRecipients() {
964
+ return getRecipients(this, 'cc');
965
+ }
966
+ getBccRecipients() {
967
+ return getRecipients(this, 'bcc');
968
+ }
969
+ getAdditionalActionToolbar() {
970
+ return require('./gmail-compose-view/get-additional-action-toolbar').default(this);
971
+ }
972
+ updateInsertMoreAreaLeft(oldFormattingAreaOffsetLeft) {
973
+ updateInsertMoreAreaLeft(this, oldFormattingAreaOffsetLeft);
974
+ }
975
+ _getFormattingAreaOffsetLeft() {
976
+ return getFormattingAreaOffsetLeft(this);
977
+ }
978
+ getFormattingArea() {
979
+ let formattingArea = this._formattingArea;
980
+ if (!formattingArea) {
981
+ formattingArea = this._formattingArea =
982
+ this._element.querySelector('.oc');
983
+ }
984
+ return formattingArea;
985
+ }
986
+ getFormattingToolbar() {
987
+ return this._element.querySelector('.aX');
988
+ }
989
+ getFormattingToolbarArrow() {
990
+ const el = this.getFormattingToolbar();
991
+ if (!el)
992
+ throw new Error('Failed to find formatting toolbar');
993
+ return querySelector(el, '.aA4');
994
+ }
995
+ getFormattingToolbarToggleButton() {
996
+ const innerElement = querySelector(this._element, '[role=button] .dv');
997
+ const btn = closest(innerElement, '[role=button]');
998
+ if (!btn)
999
+ throw new Error('failed to find button');
1000
+ return btn;
1001
+ }
1002
+ getStatusBarPrependContainer() {
1003
+ return this._element.querySelector('.inboxsdk__compose_statusBarPrependContainer');
1004
+ }
1005
+ getScrollBody() {
1006
+ var scrollBody = this._element.querySelector('table .GP');
1007
+ if (!scrollBody) {
1008
+ throw new Error('Failed to find scroll body');
1009
+ }
1010
+ return scrollBody;
1011
+ }
1012
+ getStatusArea() {
1013
+ const statusArea = this._element.querySelector('.aDg .aDj > .aDh');
1014
+ if (!statusArea)
1015
+ throw new Error('Failed to find status area');
1016
+ return statusArea;
1017
+ }
1018
+ getInsertMoreArea() {
1019
+ return querySelector(this._element, '.eq');
1020
+ }
1021
+ getInsertLinkButton() {
1022
+ return querySelector(this._element, '.e5.aaA.aMZ');
1023
+ }
1024
+ getSendButton() {
1025
+ return querySelector(this._element, '.IZ .Up div > div[role=button]:not(.Uo):not([aria-haspopup=true]):not([class^=inboxsdk_])');
1026
+ }
1027
+ // When schedule send is available, this returns the element that contains both buttons.
1028
+ getSendButtonGroup() {
1029
+ const scheduleSend = this._element.querySelector('.IZ .Up div > [role=button][aria-haspopup=true]:not([class^=inboxsdk_])');
1030
+ if (scheduleSend) {
1031
+ return scheduleSend.parentElement;
1032
+ }
1033
+ return this.getSendButton();
1034
+ }
1035
+ getSendAndArchiveButton() {
1036
+ if (!this.isReply()) {
1051
1037
  return null;
1052
- }
1053
- return draftID;
1054
1038
  }
1055
- }
1056
- } else {
1057
- if (!this.getMessageID()) {
1058
- return null;
1059
- } else {
1060
- return this.getDraftID();
1061
- }
1062
- }
1063
- }
1064
- getDraftID() {
1065
- let draftIDpromise = this._draftIDpromise;
1066
- if (!draftIDpromise) {
1067
- draftIDpromise = this._draftIDpromise = this._getDraftIDimplementation();
1068
- }
1069
- return draftIDpromise;
1070
- }
1071
- async _getDraftIDimplementation() {
1072
- if (this._driver.isUsingSyncAPI()) {
1073
- const draftID = this._getDraftIDfromForm();
1074
- // we want to keep the semantics that getDraftID doesn't return until
1075
- // the draft is actually saved on Gmail's servers
1076
- if (this._messageId) {
1077
- // if we have a messageId that means there is a draft on the server
1078
- return draftID;
1079
- } else {
1080
- // there may be a draft on the server, so let's find out
1081
- const syncMessageId = this._getMessageIDfromForm();
1082
- if (syncMessageId) {
1083
- try {
1084
- // If this succeeds, then the draft must exist on the server and we
1085
- // can safely return the draft id we know.
1086
- const gmailMessageId = await this._driver.getGmailMessageIdForSyncDraftId(syncMessageId);
1087
- } catch (e) {
1088
- // draft doesn't exist so we wait until it does
1089
- await this._eventStream.filter(_ref8 => {
1090
- let {
1091
- eventName
1092
- } = _ref8;
1093
- return eventName === 'draftSaved';
1094
- }).beforeEnd(() => null).map(() => this._getDraftIDfromForm()).take(1).toPromise();
1095
- }
1096
- return draftID;
1039
+ const sendAndArchiveButton = this._element.querySelector('.IZ .Up div > div[role=button].Uo:not([aria-haspopup=true]):not([class^=inboxsdk_])');
1040
+ if (sendAndArchiveButton) {
1041
+ return sendAndArchiveButton;
1097
1042
  }
1098
- }
1099
- } else {
1100
- let i = -1;
1101
- let lastDebugData = null;
1102
- try {
1103
- // If this compose view doesn't have a message id yet, wait until it gets
1104
- // one or it's closed.
1105
- if (!this._messageId) {
1106
- await this._eventStream.filter(event => event.eventName === 'messageIDChange').beforeEnd(() => null).take(1).toPromise();
1107
- if (!this._messageId) {
1108
- // The compose was closed before it got an id.
1043
+ // TODO is the rest of this function necessary?
1044
+ const sendButton = this.getSendButton();
1045
+ const parent = sendButton.parentElement;
1046
+ if (!(parent instanceof HTMLElement))
1047
+ throw new Error('should not happen');
1048
+ if (parent.childElementCount <= 1) {
1049
+ this._driver
1050
+ .getLogger()
1051
+ .eventSdkPassive('getSendAndArchiveButton - old method - failed to find, childElementCount <= 1');
1109
1052
  return null;
1110
- }
1111
1053
  }
1112
-
1113
- // We make an AJAX request against gmail to find the draft ID for our
1114
- // current message ID. However, our message ID can change before that
1115
- // request finishes. If we fail to get our draft ID and we see that our
1116
- // message ID has changed since we made the request, then we try again.
1117
- let lastMessageId = null;
1118
- // eslint-disable-next-line no-constant-condition
1119
- while (true) {
1120
- i++;
1121
- const messageId = this._messageId;
1122
- if (!messageId) {
1123
- throw new Error('Should not happen');
1124
- }
1125
- if (lastMessageId === messageId) {
1126
- // It's possible that the server received a draft save request from us
1127
- // already, causing the draft id lookup to fail, but we haven't gotten
1128
- // the draft save response yet. Wait for that response to finish and
1129
- // keep trying if it looks like that might be the case.
1130
- if (this._draftSaving) {
1131
- await this._eventStream.filter(event => event.eventName === 'messageIDChange').beforeEnd(() => null).take(1).toPromise();
1132
- continue;
1054
+ const firstNotSendElement = parent.children[0] !== sendButton
1055
+ ? parent.children[0]
1056
+ : parent.children[1];
1057
+ const result = !firstNotSendElement
1058
+ ? null
1059
+ : firstNotSendElement.querySelector('[role=button]');
1060
+ if (result) {
1061
+ this._driver
1062
+ .getLogger()
1063
+ .eventSdkPassive('getSendAndArchiveButton - old method - found');
1064
+ }
1065
+ else {
1066
+ this._driver
1067
+ .getLogger()
1068
+ .eventSdkPassive('getSendAndArchiveButton - old method - failed to find');
1069
+ }
1070
+ return result;
1071
+ }
1072
+ getCloseButton() {
1073
+ return this._element.querySelectorAll('.Hm > img')[2];
1074
+ }
1075
+ getMoleSwitchButton() {
1076
+ return this._element.querySelectorAll('.Hm > img')[1];
1077
+ }
1078
+ getBottomBarTable() {
1079
+ return querySelector(this._element, '.aoP .aDh > table');
1080
+ }
1081
+ getBottomToolbarContainer() {
1082
+ return querySelector(this._element, '.aoP .aDj');
1083
+ }
1084
+ getDiscardButton() {
1085
+ return querySelector(this._element, '.gU .oh');
1086
+ }
1087
+ getComposeID() {
1088
+ return this._composeID;
1089
+ }
1090
+ getInitialMessageID() {
1091
+ return this._initialMessageId;
1092
+ }
1093
+ // For use only when isUsingSyncAPI() is true — gets the draft ID
1094
+ // from the input that used to hold the hex message ID. Still does not
1095
+ // populate until first save.
1096
+ _getDraftIDfromForm() {
1097
+ const value = (this._messageIDElement && this._messageIDElement.value) || null;
1098
+ if (typeof value === 'string' &&
1099
+ value !== 'undefined' &&
1100
+ value !== 'null') {
1101
+ if (this._driver.isUsingSyncAPI()) {
1102
+ return value.replace('#', '').replace('msg-a:', '');
1103
+ }
1104
+ else {
1105
+ this._driver
1106
+ .getLogger()
1107
+ .error(new Error('Invalid draft id in element'), {
1108
+ value,
1109
+ });
1133
1110
  }
1134
-
1135
- // maaaaybe the draft is saving, but we failed to detect that.
1136
- // Let's log whether things would've worked out a little in the future.
1137
- setTimeout(async () => {
1138
- const newMessageId = this._messageId;
1139
- if (!newMessageId) {
1140
- throw new Error('Should not happen');
1141
- }
1142
- const {
1143
- draftID,
1144
- debugData
1145
- } = await this._driver.getDraftIDForMessageID(newMessageId, true);
1146
- const err = new Error('Failed to read draft ID -- after check');
1147
- this._driver.getLogger().error(err, {
1148
- message: 'getDraftID error -- after check',
1149
- messageIdChanged: messageId !== newMessageId,
1150
- gotDraftID: draftID != null,
1151
- debugData: draftID ? null : debugData
1152
- });
1153
- }, 10 * 1000);
1154
- throw new Error('Failed to read draft ID');
1155
- }
1156
- lastMessageId = messageId;
1157
- const {
1158
- draftID,
1159
- debugData
1160
- } = await this._driver.getDraftIDForMessageID(messageId);
1161
- lastDebugData = debugData;
1162
- if (draftID) {
1163
- return draftID;
1164
- }
1165
1111
  }
1166
- } catch (err) {
1167
- this._driver.getLogger().error(err, {
1168
- message: 'getDraftID error',
1169
- removedFromDOM: !document.contains(this._element),
1170
- destroyed: this._destroyed,
1171
- isFullscreen: this._isFullscreen,
1172
- isStandalone: this._isStandalone,
1173
- emailWasSent: this._emailWasSent,
1174
- i,
1175
- lastDebugData
1176
- });
1177
- throw err;
1178
- }
1179
- }
1180
- }
1181
- addManagedViewController(viewController) {
1182
- this._managedViewControllers.push(viewController);
1183
- }
1184
- ensureGroupingIsOpen(type) {
1185
- (0, _ensureGroupingIsOpen.default)(this._element, type);
1186
- }
1187
- ensureAppButtonToolbarsAreClosed() {
1188
- (0, _ensureAppButtonToolbarsAreClosed.default)(this._element);
1189
- }
1190
- isMinimized() {
1191
- const element = this.getElement();
1192
- const bodyElement = this.getMaybeBodyElement();
1193
- const bodyContainer = (0, _find.default)(element.children, child => child.contains(bodyElement));
1194
- if (!bodyContainer) {
1195
- if (!hasReportedMissingBody) {
1196
- hasReportedMissingBody = true;
1197
- this._driver.getLogger().error(new Error('isMinimized failed to find bodyContainer'), {
1198
- bodyElement: !!bodyElement,
1199
- hasMessageIDElement: !!this._messageIDElement,
1200
- ended: this._eventStream.ended,
1201
- bodyElStillInCompose: this._element.contains(this._seenBodyElement),
1202
- seenBodyElHtml: (0, _censorHTMLstring.default)(this._seenBodyElement.outerHTML),
1203
- composeHtml: (0, _censorHTMLstring.default)(element.outerHTML)
1112
+ return null;
1113
+ }
1114
+ _getMessageIDfromForm() {
1115
+ const value = (this._messageIDElement && this._messageIDElement.value) || null;
1116
+ if (typeof value === 'string' &&
1117
+ value !== 'undefined' &&
1118
+ value !== 'null') {
1119
+ if (this._driver.isUsingSyncAPI()) {
1120
+ return value.replace('#', ''); //annoyingly the hash is included
1121
+ }
1122
+ else {
1123
+ if (/^[0-9a-f]+$/i.test(value)) {
1124
+ return value;
1125
+ }
1126
+ else {
1127
+ this._driver
1128
+ .getLogger()
1129
+ .error(new Error('Invalid message id in element'), {
1130
+ value,
1131
+ });
1132
+ }
1133
+ }
1134
+ }
1135
+ return null;
1136
+ }
1137
+ getMessageID() {
1138
+ return this._messageId;
1139
+ }
1140
+ getTargetMessageID() {
1141
+ return this._targetMessageID;
1142
+ }
1143
+ getThreadID() {
1144
+ return this._threadID;
1145
+ }
1146
+ async getCurrentDraftID() {
1147
+ if (this._driver.isUsingSyncAPI()) {
1148
+ // This function is mostly a mirror of _getDraftIDimplementation, but
1149
+ // instead of waiting when finding out it's not saved, just returns null.
1150
+ const draftID = this._getDraftIDfromForm();
1151
+ if (this._messageId) {
1152
+ return draftID;
1153
+ }
1154
+ else {
1155
+ const syncMessageId = this._getMessageIDfromForm();
1156
+ if (syncMessageId) {
1157
+ try {
1158
+ // If this succeeds, then the draft must exist on the server and we
1159
+ // can safely return the draft id we know.
1160
+ const gmailMessageId = await this._driver.getGmailMessageIdForSyncDraftId(syncMessageId);
1161
+ }
1162
+ catch (e) {
1163
+ // ignore error, it's probably that the draft isn't saved yet.
1164
+ return null;
1165
+ }
1166
+ return draftID;
1167
+ }
1168
+ }
1169
+ }
1170
+ else {
1171
+ if (!this.getMessageID()) {
1172
+ return null;
1173
+ }
1174
+ else {
1175
+ return this.getDraftID();
1176
+ }
1177
+ }
1178
+ }
1179
+ getDraftID() {
1180
+ let draftIDpromise = this._draftIDpromise;
1181
+ if (!draftIDpromise) {
1182
+ draftIDpromise = this._draftIDpromise = this._getDraftIDimplementation();
1183
+ }
1184
+ return draftIDpromise;
1185
+ }
1186
+ async _getDraftIDimplementation() {
1187
+ if (this._driver.isUsingSyncAPI()) {
1188
+ const draftID = this._getDraftIDfromForm();
1189
+ // we want to keep the semantics that getDraftID doesn't return until
1190
+ // the draft is actually saved on Gmail's servers
1191
+ if (this._messageId) {
1192
+ // if we have a messageId that means there is a draft on the server
1193
+ return draftID;
1194
+ }
1195
+ else {
1196
+ // there may be a draft on the server, so let's find out
1197
+ const syncMessageId = this._getMessageIDfromForm();
1198
+ if (syncMessageId) {
1199
+ try {
1200
+ // If this succeeds, then the draft must exist on the server and we
1201
+ // can safely return the draft id we know.
1202
+ const gmailMessageId = await this._driver.getGmailMessageIdForSyncDraftId(syncMessageId);
1203
+ }
1204
+ catch (e) {
1205
+ // draft doesn't exist so we wait until it does
1206
+ await this._eventStream
1207
+ .filter(({ eventName }) => eventName === 'draftSaved')
1208
+ .beforeEnd(() => null)
1209
+ .map(() => this._getDraftIDfromForm())
1210
+ .take(1)
1211
+ .toPromise();
1212
+ }
1213
+ return draftID;
1214
+ }
1215
+ }
1216
+ }
1217
+ else {
1218
+ let i = -1;
1219
+ let lastDebugData = null;
1220
+ try {
1221
+ // If this compose view doesn't have a message id yet, wait until it gets
1222
+ // one or it's closed.
1223
+ if (!this._messageId) {
1224
+ await this._eventStream
1225
+ .filter((event) => event.eventName === 'messageIDChange')
1226
+ .beforeEnd(() => null)
1227
+ .take(1)
1228
+ .toPromise();
1229
+ if (!this._messageId) {
1230
+ // The compose was closed before it got an id.
1231
+ return null;
1232
+ }
1233
+ }
1234
+ // We make an AJAX request against gmail to find the draft ID for our
1235
+ // current message ID. However, our message ID can change before that
1236
+ // request finishes. If we fail to get our draft ID and we see that our
1237
+ // message ID has changed since we made the request, then we try again.
1238
+ let lastMessageId = null;
1239
+ // eslint-disable-next-line no-constant-condition
1240
+ while (true) {
1241
+ i++;
1242
+ const messageId = this._messageId;
1243
+ if (!messageId) {
1244
+ throw new Error('Should not happen');
1245
+ }
1246
+ if (lastMessageId === messageId) {
1247
+ // It's possible that the server received a draft save request from us
1248
+ // already, causing the draft id lookup to fail, but we haven't gotten
1249
+ // the draft save response yet. Wait for that response to finish and
1250
+ // keep trying if it looks like that might be the case.
1251
+ if (this._draftSaving) {
1252
+ await this._eventStream
1253
+ .filter((event) => event.eventName === 'messageIDChange')
1254
+ .beforeEnd(() => null)
1255
+ .take(1)
1256
+ .toPromise();
1257
+ continue;
1258
+ }
1259
+ // maaaaybe the draft is saving, but we failed to detect that.
1260
+ // Let's log whether things would've worked out a little in the future.
1261
+ setTimeout(async () => {
1262
+ const newMessageId = this._messageId;
1263
+ if (!newMessageId) {
1264
+ throw new Error('Should not happen');
1265
+ }
1266
+ const { draftID, debugData } = await this._driver.getDraftIDForMessageID(newMessageId, true);
1267
+ const err = new Error('Failed to read draft ID -- after check');
1268
+ this._driver.getLogger().error(err, {
1269
+ message: 'getDraftID error -- after check',
1270
+ messageIdChanged: messageId !== newMessageId,
1271
+ gotDraftID: draftID != null,
1272
+ debugData: draftID ? null : debugData,
1273
+ });
1274
+ }, 10 * 1000);
1275
+ throw new Error('Failed to read draft ID');
1276
+ }
1277
+ lastMessageId = messageId;
1278
+ const { draftID, debugData } = await this._driver.getDraftIDForMessageID(messageId);
1279
+ lastDebugData = debugData;
1280
+ if (draftID) {
1281
+ return draftID;
1282
+ }
1283
+ }
1284
+ }
1285
+ catch (err) {
1286
+ this._driver.getLogger().error(err, {
1287
+ message: 'getDraftID error',
1288
+ removedFromDOM: !document.contains(this._element),
1289
+ destroyed: this._destroyed,
1290
+ isFullscreen: this._isFullscreen,
1291
+ isStandalone: this._isStandalone,
1292
+ emailWasSent: this._emailWasSent,
1293
+ i,
1294
+ lastDebugData,
1295
+ });
1296
+ throw err;
1297
+ }
1298
+ }
1299
+ }
1300
+ addManagedViewController(viewController) {
1301
+ this._managedViewControllers.push(viewController);
1302
+ }
1303
+ ensureGroupingIsOpen(type) {
1304
+ ensureGroupingIsOpen(this._element, type);
1305
+ }
1306
+ ensureAppButtonToolbarsAreClosed() {
1307
+ ensureAppButtonToolbarsAreClosed(this._element);
1308
+ }
1309
+ isMinimized() {
1310
+ const element = this.getElement();
1311
+ const bodyElement = this.getMaybeBodyElement();
1312
+ const bodyContainer = find(element.children, (child) => child.contains(bodyElement));
1313
+ if (!bodyContainer) {
1314
+ if (!hasReportedMissingBody) {
1315
+ hasReportedMissingBody = true;
1316
+ this._driver
1317
+ .getLogger()
1318
+ .error(new Error('isMinimized failed to find bodyContainer'), {
1319
+ bodyElement: !!bodyElement,
1320
+ hasMessageIDElement: !!this._messageIDElement,
1321
+ ended: this._eventStream.ended,
1322
+ bodyElStillInCompose: this._element.contains(this._seenBodyElement),
1323
+ seenBodyElHtml: censorHTMLstring(this._seenBodyElement.outerHTML),
1324
+ composeHtml: censorHTMLstring(element.outerHTML),
1325
+ });
1326
+ }
1327
+ return false;
1328
+ }
1329
+ return bodyContainer.style.display !== '';
1330
+ }
1331
+ setMinimized(minimized) {
1332
+ if (minimized !== this.isMinimized()) {
1333
+ if (this._isInlineReplyForm)
1334
+ throw new Error('Not implemented for inline compose views');
1335
+ const minimizeButton = querySelector(this._element, '.Hm > img');
1336
+ simulateClick(minimizeButton);
1337
+ }
1338
+ }
1339
+ setFullscreen(fullscreen) {
1340
+ if (fullscreen !== this.isFullscreen()) {
1341
+ if (this._isInlineReplyForm)
1342
+ throw new Error('Not implemented for inline compose views');
1343
+ const fullscreenButton = querySelector(this._element, '.Hm > img:nth-of-type(2)');
1344
+ simulateClick(fullscreenButton);
1345
+ }
1346
+ }
1347
+ setTitleBarColor(color) {
1348
+ const buttonParent = querySelector(this._element, '.nH.Hy.aXJ table.cf.Ht td.Hm');
1349
+ const elementsToModify = [
1350
+ querySelector(this._element, '.nH.Hy.aXJ .pi > .l.o'),
1351
+ querySelector(this._element, '.nH.Hy.aXJ .l.m'),
1352
+ querySelector(this._element, '.nH.Hy.aXJ .l.m > .l.n'),
1353
+ ];
1354
+ buttonParent.classList.add('inboxsdk__compose_customTitleBarColor');
1355
+ elementsToModify.forEach((el) => {
1356
+ el.style.backgroundColor = color;
1204
1357
  });
1205
- }
1206
- return false;
1207
- }
1208
- return bodyContainer.style.display !== '';
1209
- }
1210
- setMinimized(minimized) {
1211
- if (minimized !== this.isMinimized()) {
1212
- if (this._isInlineReplyForm) throw new Error('Not implemented for inline compose views');
1213
- const minimizeButton = (0, _querySelectorOrFail.default)(this._element, '.Hm > img');
1214
- (0, _simulateMouseEvent.simulateClick)(minimizeButton);
1215
- }
1216
- }
1217
- setFullscreen(fullscreen) {
1218
- if (fullscreen !== this.isFullscreen()) {
1219
- if (this._isInlineReplyForm) throw new Error('Not implemented for inline compose views');
1220
- const fullscreenButton = (0, _querySelectorOrFail.default)(this._element, '.Hm > img:nth-of-type(2)');
1221
- (0, _simulateMouseEvent.simulateClick)(fullscreenButton);
1222
- }
1223
- }
1224
- setTitleBarColor(color) {
1225
- const buttonParent = (0, _querySelectorOrFail.default)(this._element, '.nH.Hy.aXJ table.cf.Ht td.Hm');
1226
- const elementsToModify = [(0, _querySelectorOrFail.default)(this._element, '.nH.Hy.aXJ .pi > .l.o'), (0, _querySelectorOrFail.default)(this._element, '.nH.Hy.aXJ .l.m'), (0, _querySelectorOrFail.default)(this._element, '.nH.Hy.aXJ .l.m > .l.n')];
1227
- buttonParent.classList.add('inboxsdk__compose_customTitleBarColor');
1228
- elementsToModify.forEach(el => {
1229
- el.style.backgroundColor = color;
1230
- });
1231
- return () => {
1232
- buttonParent.classList.remove('inboxsdk__compose_customTitleBarColor');
1233
- elementsToModify.forEach(el => {
1234
- el.style.backgroundColor = '';
1235
- });
1236
- };
1237
- }
1238
- setTitleBarText(text) {
1239
- if (this.isInlineReplyForm()) {
1240
- throw new Error('setTitleBarText() is not supported on inline compose views');
1241
- }
1242
- const titleBarTable = (0, _querySelectorOrFail.default)(this._element, '.nH.Hy.aXJ table.cf.Ht');
1243
- if (titleBarTable.classList.contains('inboxsdk__compose_hasCustomTitleBarText')) {
1244
- throw new Error('Custom title bar text is already registered for this compose view');
1245
- }
1246
- const titleTextParent = (0, _querySelectorOrFail.default)(titleBarTable, 'div.Hp').parentElement;
1247
- if (!(titleTextParent instanceof HTMLElement)) {
1248
- throw new Error('Could not locate title bar text parent');
1249
- }
1250
- titleBarTable.classList.add('inboxsdk__compose_hasCustomTitleBarText');
1251
- titleTextParent.classList.add('inboxsdk__compose_nativeTitleBarText');
1252
- const customTitleText = document.createElement('td');
1253
- customTitleText.classList.add('inboxsdk__compose_customTitleBarText');
1254
- customTitleText.innerHTML = (0, _autoHtml.default)`
1358
+ return () => {
1359
+ buttonParent.classList.remove('inboxsdk__compose_customTitleBarColor');
1360
+ elementsToModify.forEach((el) => {
1361
+ el.style.backgroundColor = '';
1362
+ });
1363
+ };
1364
+ }
1365
+ setTitleBarText(text) {
1366
+ if (this.isInlineReplyForm()) {
1367
+ throw new Error('setTitleBarText() is not supported on inline compose views');
1368
+ }
1369
+ const titleBarTable = querySelector(this._element, '.nH.Hy.aXJ table.cf.Ht');
1370
+ if (titleBarTable.classList.contains('inboxsdk__compose_hasCustomTitleBarText')) {
1371
+ throw new Error('Custom title bar text is already registered for this compose view');
1372
+ }
1373
+ const titleTextParent = querySelector(titleBarTable, 'div.Hp').parentElement;
1374
+ if (!(titleTextParent instanceof HTMLElement)) {
1375
+ throw new Error('Could not locate title bar text parent');
1376
+ }
1377
+ titleBarTable.classList.add('inboxsdk__compose_hasCustomTitleBarText');
1378
+ titleTextParent.classList.add('inboxsdk__compose_nativeTitleBarText');
1379
+ const customTitleText = document.createElement('td');
1380
+ customTitleText.classList.add('inboxsdk__compose_customTitleBarText');
1381
+ customTitleText.innerHTML = autoHtml `
1255
1382
  <div class="Hp">
1256
1383
  <h2 class="a3E">
1257
1384
  <div class="aYF">${text}</div>
1258
1385
  </h2>
1259
1386
  </div>
1260
1387
  `;
1261
- titleTextParent.insertAdjacentElement('afterend', customTitleText);
1262
- return () => {
1263
- customTitleText.remove();
1264
- titleBarTable.classList.remove('inboxsdk__compose_hasCustomTitleBarText');
1265
- titleTextParent.classList.remove('inboxsdk__compose_nativeTitleBarText');
1266
- };
1267
- }
1268
- _triggerDraftSave() {
1269
- if (this._isTriggeringADraftSavePending) {
1270
- return;
1271
- } else {
1272
- this._isTriggeringADraftSavePending = true;
1273
-
1274
- // Done asynchronously with setTimeout because if it's done synchronously
1275
- // or after an asap step after an inline compose view's creation, Gmail
1276
- // interprets the fake keypress and decides to add a '¾' character.
1277
- Kefir.later(0).takeUntilBy(this._stopper).onValue(() => {
1278
- this._isTriggeringADraftSavePending = false;
1279
- const body = this.getMaybeBodyElement();
1280
- if (body) {
1281
- const unsilence = this._driver.getPageCommunicator().silenceGmailErrorsForAMoment();
1282
- try {
1283
- (0, _simulateKey.default)(body, 190, 0);
1284
- } finally {
1285
- unsilence();
1286
- }
1388
+ titleTextParent.insertAdjacentElement('afterend', customTitleText);
1389
+ return () => {
1390
+ customTitleText.remove();
1391
+ titleBarTable.classList.remove('inboxsdk__compose_hasCustomTitleBarText');
1392
+ titleTextParent.classList.remove('inboxsdk__compose_nativeTitleBarText');
1393
+ };
1394
+ }
1395
+ _triggerDraftSave() {
1396
+ if (this._isTriggeringADraftSavePending) {
1397
+ return;
1398
+ }
1399
+ else {
1400
+ this._isTriggeringADraftSavePending = true;
1401
+ // Done asynchronously with setTimeout because if it's done synchronously
1402
+ // or after an asap step after an inline compose view's creation, Gmail
1403
+ // interprets the fake keypress and decides to add a '¾' character.
1404
+ Kefir.later(0, undefined)
1405
+ .takeUntilBy(this._stopper)
1406
+ .onValue(() => {
1407
+ this._isTriggeringADraftSavePending = false;
1408
+ const body = this.getMaybeBodyElement();
1409
+ if (body) {
1410
+ const unsilence = this._driver
1411
+ .getPageCommunicator()
1412
+ .silenceGmailErrorsForAMoment();
1413
+ try {
1414
+ simulateKey(body, 190, 0);
1415
+ }
1416
+ finally {
1417
+ unsilence();
1418
+ }
1419
+ }
1420
+ });
1421
+ }
1422
+ }
1423
+ // If this compose is a reply, then this gets the message ID of the message
1424
+ // we're replying to.
1425
+ _getTargetMessageID() {
1426
+ const input = this._element.querySelector('input[name="rm"]');
1427
+ return input &&
1428
+ typeof input.value === 'string' &&
1429
+ input.value != 'undefined'
1430
+ ? input.value.replace('#', '')
1431
+ : null;
1432
+ }
1433
+ _getThreadID() {
1434
+ const targetID = this.getTargetMessageID();
1435
+ try {
1436
+ return targetID ? this._driver.getThreadIDForMessageID(targetID) : null;
1287
1437
  }
1288
- });
1289
- }
1290
- }
1291
-
1292
- // If this compose is a reply, then this gets the message ID of the message
1293
- // we're replying to.
1294
- _getTargetMessageID() {
1295
- const input = this._element.querySelector('input[name="rm"]');
1296
- return input && typeof input.value === 'string' && input.value != 'undefined' ? input.value.replace('#', '') : null;
1297
- }
1298
- _getThreadID() {
1299
- const targetID = this.getTargetMessageID();
1300
- try {
1301
- return targetID ? this._driver.getThreadIDForMessageID(targetID) : null;
1302
- } catch (err) {
1303
- this._driver.getLogger().error(err);
1304
- return null;
1305
- }
1306
- }
1307
- getElement() {
1308
- return this._element;
1309
- }
1310
- isFullscreen() {
1311
- return this._isFullscreen;
1312
- }
1313
- getLastSelectionRange() {
1314
- // The selection range can become invalid if the compose view has become expanded or
1315
- // minimized since the range was set.
1316
- const range = this._lastSelectionRange;
1317
- if (range && !this.getBodyElement().contains(range.commonAncestorContainer)) {
1318
- this._lastSelectionRange = undefined;
1319
- }
1320
- return this._lastSelectionRange;
1321
- }
1322
- setLastSelectionRange(lastSelectionRange) {
1323
- this._lastSelectionRange = lastSelectionRange;
1324
- }
1325
- registerRequestModifier(modifier) {
1326
- const keyId = this._driver.isUsingSyncAPI() ? this._getDraftIDfromForm() : this.getComposeID();
1327
- if (!keyId) throw new Error('keyId should be set here');
1328
- const modifierId = this._driver.getPageCommunicator().registerComposeRequestModifier(keyId, this._driver.getAppId());
1329
- this._requestModifiers[modifierId] = modifier;
1330
- this._startListeningForModificationRequests();
1331
- this._stopper.onValue(() => {
1332
- this._driver.getPageCommunicator().unregisterComposeRequestModifier(keyId, modifierId);
1333
- });
1334
- }
1335
- _startListeningForModificationRequests() {
1336
- if (this._isListeningToAjaxInterceptStream) {
1337
- return;
1338
- }
1339
- const keyId = this._driver.isUsingSyncAPI() ? this._getDraftIDfromForm() : this.getComposeID();
1340
- if (!keyId) throw new Error('keyId should be set here');
1341
- this._driver.getPageCommunicator().ajaxInterceptStream.filter(_ref9 => {
1342
- let {
1343
- type,
1344
- composeid,
1345
- draftID,
1346
- modifierId
1347
- } = _ref9;
1348
- return type === 'inboxSDKmodifyComposeRequest' && (composeid === keyId || keyId === draftID) && Boolean(this._requestModifiers[modifierId]);
1349
- }).takeUntilBy(this._stopper).onValue(_ref10 => {
1350
- let {
1351
- modifierId,
1352
- composeParams
1353
- } = _ref10;
1354
- if (this._driver.getLogger().shouldTrackEverything()) {
1355
- this._driver.getLogger().eventSite('inboxSDKmodifyComposeRequest');
1356
- }
1357
- const modifier = this._requestModifiers[modifierId];
1358
- const result = new Promise(resolve => resolve(modifier(composeParams)));
1359
- result.then(newComposeParams => this._driver.getPageCommunicator().modifyComposeRequest(keyId, modifierId, newComposeParams || composeParams)).then(x => {
1360
- if (this._driver.getLogger().shouldTrackEverything()) {
1361
- this._driver.getLogger().eventSite('composeRequestModified');
1438
+ catch (err) {
1439
+ this._driver.getLogger().error(err);
1440
+ return null;
1362
1441
  }
1363
- return x;
1364
- }).catch(err => {
1365
- this._driver.getPageCommunicator().modifyComposeRequest(keyId, modifierId, composeParams);
1366
- this._driver.getLogger().error(err);
1367
- });
1368
- });
1369
- this._isListeningToAjaxInterceptStream = true;
1370
- }
1371
- setupLinkPopOvers() {
1372
- if (!this._hasSetupLinkPopOvers) {
1373
- this._hasSetupLinkPopOvers = true;
1374
- this._eventStream.plug((0, _setupLinkPopovers.default)(this));
1375
- }
1376
- }
1442
+ }
1443
+ getElement() {
1444
+ return this._element;
1445
+ }
1446
+ isFullscreen() {
1447
+ return this._isFullscreen;
1448
+ }
1449
+ getLastSelectionRange() {
1450
+ // The selection range can become invalid if the compose view has become expanded or
1451
+ // minimized since the range was set.
1452
+ const range = this._lastSelectionRange;
1453
+ if (range &&
1454
+ !this.getBodyElement().contains(range.commonAncestorContainer)) {
1455
+ this._lastSelectionRange = undefined;
1456
+ }
1457
+ return this._lastSelectionRange;
1458
+ }
1459
+ setLastSelectionRange(lastSelectionRange) {
1460
+ this._lastSelectionRange = lastSelectionRange;
1461
+ }
1462
+ registerRequestModifier(modifier) {
1463
+ const keyId = this._driver.isUsingSyncAPI()
1464
+ ? this._getDraftIDfromForm()
1465
+ : this.getComposeID();
1466
+ if (!keyId)
1467
+ throw new Error('keyId should be set here');
1468
+ const modifierId = this._driver
1469
+ .getPageCommunicator()
1470
+ .registerComposeRequestModifier(keyId, this._driver.getAppId());
1471
+ this._requestModifiers[modifierId] = modifier;
1472
+ this._startListeningForModificationRequests();
1473
+ this._stopper.onValue(() => {
1474
+ this._driver
1475
+ .getPageCommunicator()
1476
+ .unregisterComposeRequestModifier(keyId, modifierId);
1477
+ });
1478
+ }
1479
+ _startListeningForModificationRequests() {
1480
+ if (this._isListeningToAjaxInterceptStream) {
1481
+ return;
1482
+ }
1483
+ const keyId = this._driver.isUsingSyncAPI()
1484
+ ? this._getDraftIDfromForm()
1485
+ : this.getComposeID();
1486
+ if (!keyId)
1487
+ throw new Error('keyId should be set here');
1488
+ this._driver
1489
+ .getPageCommunicator()
1490
+ .ajaxInterceptStream.filter(({ type, composeid, draftID, modifierId }) => type === 'inboxSDKmodifyComposeRequest' &&
1491
+ (composeid === keyId || keyId === draftID) &&
1492
+ Boolean(this._requestModifiers[modifierId]))
1493
+ .takeUntilBy(this._stopper)
1494
+ .onValue(({ modifierId, composeParams }) => {
1495
+ if (this._driver.getLogger().shouldTrackEverything()) {
1496
+ this._driver.getLogger().eventSite('inboxSDKmodifyComposeRequest');
1497
+ }
1498
+ const modifier = this._requestModifiers[modifierId];
1499
+ const result = new Promise((resolve) => resolve(modifier(composeParams)));
1500
+ result
1501
+ .then((newComposeParams) => this._driver
1502
+ .getPageCommunicator()
1503
+ .modifyComposeRequest(keyId, modifierId, newComposeParams || composeParams))
1504
+ .then((x) => {
1505
+ if (this._driver.getLogger().shouldTrackEverything()) {
1506
+ this._driver.getLogger().eventSite('composeRequestModified');
1507
+ }
1508
+ return x;
1509
+ })
1510
+ .catch((err) => {
1511
+ this._driver
1512
+ .getPageCommunicator()
1513
+ .modifyComposeRequest(keyId, modifierId, composeParams);
1514
+ this._driver.getLogger().error(err);
1515
+ });
1516
+ });
1517
+ this._isListeningToAjaxInterceptStream = true;
1518
+ }
1519
+ setupLinkPopOvers() {
1520
+ if (!this._hasSetupLinkPopOvers) {
1521
+ this._hasSetupLinkPopOvers = true;
1522
+ this._eventStream.plug(setupLinkPopOvers(this));
1523
+ }
1524
+ }
1377
1525
  }
1378
- var _default = ud.defn(module, GmailComposeView);
1379
- exports.default = _default;
1526
+ export default GmailComposeView;