@weavy/uikit-react 12.1.0 → 14.0.0

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 (280) hide show
  1. package/changelog.md +60 -0
  2. package/dist/cjs/index.js +28 -6
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/types/client/WeavyClient.d.ts +8 -1
  5. package/dist/cjs/types/components/Attachment.d.ts +2 -1
  6. package/dist/cjs/types/components/Chat.d.ts +1 -1
  7. package/dist/cjs/types/components/Messages.d.ts +3 -1
  8. package/dist/cjs/types/components/PdfViewer.d.ts +3 -1
  9. package/dist/cjs/types/components/Preview.d.ts +8 -10
  10. package/dist/cjs/types/contexts/PreviewContext.d.ts +2 -1
  11. package/dist/cjs/types/contexts/WeavyContext.d.ts +2 -3
  12. package/dist/cjs/types/hooks/useConversations.d.ts +1 -1
  13. package/dist/cjs/types/hooks/useMutateMessage.d.ts +1 -1
  14. package/dist/cjs/types/hooks/useMutateRead.d.ts +1 -0
  15. package/dist/cjs/types/types/Chat.d.ts +2 -1
  16. package/dist/cjs/types/types/Message.d.ts +2 -0
  17. package/dist/cjs/types/types/types.d.ts +63 -9
  18. package/dist/cjs/types/ui/Spinner.d.ts +10 -0
  19. package/dist/cjs/types/utils/fileUtilities.d.ts +1 -4
  20. package/dist/css/weavy-chat.css +1803 -1041
  21. package/dist/css/weavy-messenger.css +2141 -1360
  22. package/dist/css/weavy.css +1943 -1162
  23. package/dist/esm/index.js +28 -6
  24. package/dist/esm/index.js.map +1 -1
  25. package/dist/esm/types/client/WeavyClient.d.ts +8 -1
  26. package/dist/esm/types/components/Attachment.d.ts +2 -1
  27. package/dist/esm/types/components/Chat.d.ts +1 -1
  28. package/dist/esm/types/components/Messages.d.ts +3 -1
  29. package/dist/esm/types/components/PdfViewer.d.ts +3 -1
  30. package/dist/esm/types/components/Preview.d.ts +8 -10
  31. package/dist/esm/types/contexts/PreviewContext.d.ts +2 -1
  32. package/dist/esm/types/contexts/WeavyContext.d.ts +2 -3
  33. package/dist/esm/types/hooks/useConversations.d.ts +1 -1
  34. package/dist/esm/types/hooks/useMutateMessage.d.ts +1 -1
  35. package/dist/esm/types/hooks/useMutateRead.d.ts +1 -0
  36. package/dist/esm/types/types/Chat.d.ts +2 -1
  37. package/dist/esm/types/types/Message.d.ts +2 -0
  38. package/dist/esm/types/types/types.d.ts +63 -9
  39. package/dist/esm/types/ui/Spinner.d.ts +10 -0
  40. package/dist/esm/types/utils/fileUtilities.d.ts +1 -4
  41. package/dist/index.d.ts +15 -7
  42. package/package.json +2 -2
  43. package/rollup.config.js +3 -1
  44. package/src/client/WeavyClient.ts +105 -29
  45. package/src/components/Attachment.tsx +8 -7
  46. package/src/components/Chat.tsx +8 -7
  47. package/src/components/Conversation.tsx +29 -23
  48. package/src/components/ConversationBadge.tsx +7 -5
  49. package/src/components/ConversationForm.tsx +1 -1
  50. package/src/components/ConversationList.tsx +59 -11
  51. package/src/components/ConversationListItem.tsx +71 -54
  52. package/src/components/FileBrowser.tsx +53 -50
  53. package/src/components/MeetingCard.tsx +35 -13
  54. package/src/components/Meetings.tsx +1 -1
  55. package/src/components/Message.tsx +41 -41
  56. package/src/components/Messages.tsx +62 -61
  57. package/src/components/Messenger.tsx +7 -2
  58. package/src/components/NewConversation.tsx +1 -1
  59. package/src/components/PdfViewer.tsx +93 -88
  60. package/src/components/Preview.tsx +115 -54
  61. package/src/components/Reactions.tsx +11 -5
  62. package/src/components/SearchUsers.tsx +21 -11
  63. package/src/components/SeenBy.tsx +13 -7
  64. package/src/components/Typing.tsx +11 -12
  65. package/src/contexts/PreviewContext.tsx +90 -16
  66. package/src/contexts/UserContext.tsx +1 -1
  67. package/src/contexts/WeavyContext.tsx +10 -7
  68. package/src/hooks/useBadge.ts +2 -6
  69. package/src/hooks/useChat.ts +3 -14
  70. package/src/hooks/useConversation.ts +1 -7
  71. package/src/hooks/useConversations.ts +15 -11
  72. package/src/hooks/useFileUploader.ts +6 -8
  73. package/src/hooks/useMembers.ts +1 -7
  74. package/src/hooks/useMessages.ts +1 -7
  75. package/src/hooks/useMutateChat.ts +6 -11
  76. package/src/hooks/useMutateConversation.ts +7 -10
  77. package/src/hooks/useMutateConversationName.ts +10 -12
  78. package/src/hooks/useMutateDeleteReaction.ts +3 -8
  79. package/src/hooks/useMutateExternalBlobs.ts +6 -11
  80. package/src/hooks/useMutateMeeting.ts +6 -11
  81. package/src/hooks/useMutateMembers.ts +8 -13
  82. package/src/hooks/useMutateMessage.ts +9 -18
  83. package/src/hooks/useMutatePinned.ts +3 -8
  84. package/src/hooks/useMutateReaction.ts +6 -12
  85. package/src/hooks/useMutateRead.ts +5 -12
  86. package/src/hooks/useMutateRemoveMembers.ts +7 -12
  87. package/src/hooks/useMutateTyping.ts +6 -11
  88. package/src/hooks/usePresence.ts +2 -3
  89. package/src/hooks/useReactions.ts +11 -12
  90. package/src/hooks/useSearchUsers.ts +1 -6
  91. package/src/hooks/useUser.ts +3 -14
  92. package/src/scss/theme/_alert.scss +61 -63
  93. package/src/scss/theme/_appbar.scss +105 -28
  94. package/src/scss/theme/_avatar.scss +23 -28
  95. package/src/scss/theme/_badge.scss +26 -18
  96. package/src/scss/theme/_buttons.scss +107 -52
  97. package/src/scss/theme/_card.scss +102 -4
  98. package/src/scss/theme/_checkbox.scss +16 -20
  99. package/src/scss/theme/_code-vscode-dark.scss +184 -0
  100. package/src/scss/theme/_code-vscode-light.scss +179 -0
  101. package/src/scss/theme/_code.scss +9 -114
  102. package/src/scss/theme/_comment-editor-cm.scss +97 -0
  103. package/src/scss/theme/_comment-editor.scss +129 -0
  104. package/src/scss/theme/_comments.scss +66 -0
  105. package/src/scss/theme/_content.scss +33 -5
  106. package/src/scss/theme/_conversations.scss +19 -78
  107. package/src/scss/theme/_dropdown.scss +102 -15
  108. package/src/scss/theme/_embed.scss +135 -0
  109. package/src/scss/theme/_facepile.scss +11 -0
  110. package/src/scss/theme/_filebrowser.scss +1 -1
  111. package/src/scss/theme/_files.scss +77 -48
  112. package/src/scss/theme/_grid.scss +8 -0
  113. package/src/scss/theme/_icons.scss +155 -19
  114. package/src/scss/theme/_image-grid.scss +7 -10
  115. package/src/scss/theme/_input.scss +160 -0
  116. package/src/scss/theme/_item.scss +169 -0
  117. package/src/scss/theme/_list.scss +57 -0
  118. package/src/scss/theme/_meeting.scss +11 -0
  119. package/src/scss/theme/_message-editor-cm.scss +95 -0
  120. package/src/scss/theme/_message-editor.scss +66 -20
  121. package/src/scss/theme/_messages.scss +51 -105
  122. package/src/scss/theme/_meta.scss +12 -0
  123. package/src/scss/theme/_overlays.scss +31 -76
  124. package/src/scss/theme/_pager.scss +5 -1
  125. package/src/scss/theme/_pane.scss +13 -2
  126. package/src/scss/theme/_panels.scss +34 -25
  127. package/src/scss/theme/_picker-list.scss +5 -3
  128. package/src/scss/theme/_placeholder.scss +19 -0
  129. package/src/scss/theme/_poll.scss +49 -0
  130. package/src/scss/theme/_post-editor-cm.scss +100 -0
  131. package/src/scss/theme/_post-editor.scss +127 -0
  132. package/src/scss/theme/_post.scss +83 -0
  133. package/src/scss/theme/_preview-code.scss +14 -0
  134. package/src/scss/theme/_preview-embed.scss +11 -5
  135. package/src/scss/theme/_preview-image.scss +8 -26
  136. package/src/scss/theme/_preview-media.scss +1 -0
  137. package/src/scss/theme/_preview-pdf.scss +10 -15
  138. package/src/scss/theme/_preview-text.scss +1 -1
  139. package/src/scss/theme/_preview.scss +59 -76
  140. package/src/scss/theme/_reactions.scss +48 -17
  141. package/src/scss/theme/_sheet.scss +59 -0
  142. package/src/scss/theme/_sidebar.scss +86 -0
  143. package/src/scss/theme/_spinner.scss +11 -7
  144. package/src/scss/theme/_tab.scss +72 -0
  145. package/src/scss/theme/_tables.scss +70 -23
  146. package/src/scss/theme/_toasts.scss +56 -26
  147. package/src/scss/theme/_type.scss +41 -0
  148. package/src/scss/theme/{mixins → base}/_backdrop.scss +0 -0
  149. package/src/scss/theme/{bootstrap/mixins → base}/_breakpoints.scss +9 -0
  150. package/src/scss/theme/base/_colors.scss +315 -0
  151. package/src/scss/theme/base/_md.scss +19 -0
  152. package/src/scss/theme/base/_palette.scss +130 -0
  153. package/src/scss/theme/{mixins → base}/_position.scss +5 -5
  154. package/src/scss/theme/base/_reboot.scss +51 -0
  155. package/src/scss/theme/base/_scroll.scss +180 -0
  156. package/src/scss/theme/base/_svg.scss +49 -0
  157. package/src/scss/theme/base/_text.scss +23 -0
  158. package/src/scss/theme/base/_vars.scss +203 -0
  159. package/src/scss/theme/{fonts → base/fonts}/_fontmapping-roboto.scss +0 -0
  160. package/src/scss/theme/{fonts → base/fonts}/_fontmapping-segoe-ui.scss +0 -0
  161. package/src/scss/theme/base/fonts/_index.scss +2 -0
  162. package/src/scss/weavy-chat.scss +11 -4
  163. package/src/scss/weavy-messenger.scss +38 -21
  164. package/src/types/Chat.ts +2 -1
  165. package/src/types/Message.ts +3 -1
  166. package/src/types/types.ts +72 -10
  167. package/src/ui/Icon.tsx +1 -1
  168. package/src/ui/Spinner.tsx +19 -0
  169. package/src/utils/fileUtilities.ts +11 -125
  170. package/src/utils/infiniteScroll.js +11 -2
  171. package/src/utils/postal-parent.js +398 -0
  172. package/src/utils/promise.js +187 -0
  173. package/src/utils/scrollbarDetection.js +68 -9
  174. package/src/utils/utils.js +547 -0
  175. package/src/scss/theme/_attachments.scss +0 -74
  176. package/src/scss/theme/_cm-editor.scss +0 -42
  177. package/src/scss/theme/_colors.scss +0 -520
  178. package/src/scss/theme/_config.scss +0 -6
  179. package/src/scss/theme/_inputs.scss +0 -28
  180. package/src/scss/theme/_nav.scss +0 -52
  181. package/src/scss/theme/_palette.scss +0 -165
  182. package/src/scss/theme/_preview-icon.scss +0 -41
  183. package/src/scss/theme/_reboot.scss +0 -41
  184. package/src/scss/theme/_root.scss +0 -2
  185. package/src/scss/theme/_scroll.scss +0 -55
  186. package/src/scss/theme/_search.scss +0 -68
  187. package/src/scss/theme/_turbo.scss +0 -17
  188. package/src/scss/theme/_variables.scss +0 -139
  189. package/src/scss/theme/bootstrap/_accordion.scss +0 -146
  190. package/src/scss/theme/bootstrap/_alert.scss +0 -71
  191. package/src/scss/theme/bootstrap/_badge.scss +0 -38
  192. package/src/scss/theme/bootstrap/_breadcrumb.scss +0 -40
  193. package/src/scss/theme/bootstrap/_button-group.scss +0 -142
  194. package/src/scss/theme/bootstrap/_buttons.scss +0 -186
  195. package/src/scss/theme/bootstrap/_card.scss +0 -234
  196. package/src/scss/theme/bootstrap/_carousel.scss +0 -229
  197. package/src/scss/theme/bootstrap/_close.scss +0 -40
  198. package/src/scss/theme/bootstrap/_containers.scss +0 -41
  199. package/src/scss/theme/bootstrap/_dropdown.scss +0 -248
  200. package/src/scss/theme/bootstrap/_forms.scss +0 -9
  201. package/src/scss/theme/bootstrap/_functions.scss +0 -302
  202. package/src/scss/theme/bootstrap/_grid.scss +0 -33
  203. package/src/scss/theme/bootstrap/_helpers.scss +0 -10
  204. package/src/scss/theme/bootstrap/_images.scss +0 -42
  205. package/src/scss/theme/bootstrap/_list-group.scss +0 -191
  206. package/src/scss/theme/bootstrap/_maps.scss +0 -54
  207. package/src/scss/theme/bootstrap/_mixins.scss +0 -43
  208. package/src/scss/theme/bootstrap/_modal.scss +0 -237
  209. package/src/scss/theme/bootstrap/_nav.scss +0 -172
  210. package/src/scss/theme/bootstrap/_navbar.scss +0 -276
  211. package/src/scss/theme/bootstrap/_offcanvas.scss +0 -143
  212. package/src/scss/theme/bootstrap/_pagination.scss +0 -109
  213. package/src/scss/theme/bootstrap/_placeholders.scss +0 -51
  214. package/src/scss/theme/bootstrap/_popover.scss +0 -196
  215. package/src/scss/theme/bootstrap/_progress.scss +0 -59
  216. package/src/scss/theme/bootstrap/_reboot.scss +0 -610
  217. package/src/scss/theme/bootstrap/_root.scss +0 -73
  218. package/src/scss/theme/bootstrap/_spinners.scss +0 -85
  219. package/src/scss/theme/bootstrap/_tables.scss +0 -164
  220. package/src/scss/theme/bootstrap/_toasts.scss +0 -70
  221. package/src/scss/theme/bootstrap/_tooltip.scss +0 -120
  222. package/src/scss/theme/bootstrap/_transitions.scss +0 -27
  223. package/src/scss/theme/bootstrap/_type.scss +0 -106
  224. package/src/scss/theme/bootstrap/_utilities.scss +0 -647
  225. package/src/scss/theme/bootstrap/_variables.scss +0 -1633
  226. package/src/scss/theme/bootstrap/forms/_floating-labels.scss +0 -74
  227. package/src/scss/theme/bootstrap/forms/_form-check.scss +0 -175
  228. package/src/scss/theme/bootstrap/forms/_form-control.scss +0 -194
  229. package/src/scss/theme/bootstrap/forms/_form-range.scss +0 -91
  230. package/src/scss/theme/bootstrap/forms/_form-select.scss +0 -71
  231. package/src/scss/theme/bootstrap/forms/_form-text.scss +0 -11
  232. package/src/scss/theme/bootstrap/forms/_input-group.scss +0 -129
  233. package/src/scss/theme/bootstrap/forms/_labels.scss +0 -36
  234. package/src/scss/theme/bootstrap/forms/_validation.scss +0 -12
  235. package/src/scss/theme/bootstrap/helpers/_clearfix.scss +0 -3
  236. package/src/scss/theme/bootstrap/helpers/_color-bg.scss +0 -10
  237. package/src/scss/theme/bootstrap/helpers/_colored-links.scss +0 -12
  238. package/src/scss/theme/bootstrap/helpers/_position.scss +0 -36
  239. package/src/scss/theme/bootstrap/helpers/_ratio.scss +0 -26
  240. package/src/scss/theme/bootstrap/helpers/_stacks.scss +0 -15
  241. package/src/scss/theme/bootstrap/helpers/_stretched-link.scss +0 -15
  242. package/src/scss/theme/bootstrap/helpers/_text-truncation.scss +0 -7
  243. package/src/scss/theme/bootstrap/helpers/_visually-hidden.scss +0 -8
  244. package/src/scss/theme/bootstrap/helpers/_vr.scss +0 -8
  245. package/src/scss/theme/bootstrap/mixins/_alert.scss +0 -15
  246. package/src/scss/theme/bootstrap/mixins/_backdrop.scss +0 -14
  247. package/src/scss/theme/bootstrap/mixins/_banner.scss +0 -9
  248. package/src/scss/theme/bootstrap/mixins/_border-radius.scss +0 -78
  249. package/src/scss/theme/bootstrap/mixins/_box-shadow.scss +0 -18
  250. package/src/scss/theme/bootstrap/mixins/_buttons.scss +0 -70
  251. package/src/scss/theme/bootstrap/mixins/_caret.scss +0 -64
  252. package/src/scss/theme/bootstrap/mixins/_clearfix.scss +0 -9
  253. package/src/scss/theme/bootstrap/mixins/_color-scheme.scss +0 -7
  254. package/src/scss/theme/bootstrap/mixins/_container.scss +0 -11
  255. package/src/scss/theme/bootstrap/mixins/_deprecate.scss +0 -10
  256. package/src/scss/theme/bootstrap/mixins/_forms.scss +0 -152
  257. package/src/scss/theme/bootstrap/mixins/_gradients.scss +0 -47
  258. package/src/scss/theme/bootstrap/mixins/_grid.scss +0 -151
  259. package/src/scss/theme/bootstrap/mixins/_image.scss +0 -16
  260. package/src/scss/theme/bootstrap/mixins/_list-group.scss +0 -24
  261. package/src/scss/theme/bootstrap/mixins/_lists.scss +0 -7
  262. package/src/scss/theme/bootstrap/mixins/_pagination.scss +0 -10
  263. package/src/scss/theme/bootstrap/mixins/_reset-text.scss +0 -17
  264. package/src/scss/theme/bootstrap/mixins/_resize.scss +0 -6
  265. package/src/scss/theme/bootstrap/mixins/_table-variants.scss +0 -24
  266. package/src/scss/theme/bootstrap/mixins/_text-truncate.scss +0 -8
  267. package/src/scss/theme/bootstrap/mixins/_transition.scss +0 -26
  268. package/src/scss/theme/bootstrap/mixins/_utilities.scss +0 -97
  269. package/src/scss/theme/bootstrap/mixins/_visually-hidden.scss +0 -29
  270. package/src/scss/theme/bootstrap/utilities/_api.scss +0 -47
  271. package/src/scss/theme/bootstrap/vendor/_rfs.scss +0 -354
  272. package/src/scss/theme/bs/_badge.scss +0 -20
  273. package/src/scss/theme/bs/_buttons.scss +0 -185
  274. package/src/scss/theme/bs/_dropdown.scss +0 -86
  275. package/src/scss/theme/bs/_forms.scss +0 -161
  276. package/src/scss/theme/bs/_list-group.scss +0 -73
  277. package/src/scss/theme/bs/_tables.scss +0 -46
  278. package/src/scss/theme/fonts/_index.scss +0 -2
  279. package/src/scss/theme/mixins/_palette.scss +0 -165
  280. package/src/scss/theme/mixins/_scrollbar.scss +0 -110
@@ -6,8 +6,9 @@ import Messages from './Messages';
6
6
  import useMembers from '../hooks/useMembers';
7
7
  import Typing from './Typing';
8
8
  import useConversation from '../hooks/useConversation';
9
+ import classNames from 'classnames';
9
10
 
10
- const Chat = ({ id }: ChatProps) => {
11
+ const Chat = ({ uid, className }: ChatProps) => {
11
12
  const { client } = useContext(WeavyContext);
12
13
  const [selectedId, setSelectedId] = useState<number | null>(null)
13
14
 
@@ -15,7 +16,7 @@ const Chat = ({ id }: ChatProps) => {
15
16
  throw new Error('Weavy Chat component must be used within an WeavyProvider');
16
17
  }
17
18
 
18
- const { isLoading: isLoadingChat, data: dataChat } = useChat(id, {});
19
+ const { isLoading: isLoadingChat, data: dataChat } = useChat(uid, {});
19
20
 
20
21
  const { isLoading: isLoadingMembers, data: dataMembers } = useMembers(selectedId, {
21
22
  // The query will not execute until the activeConversation exists
@@ -36,8 +37,8 @@ const Chat = ({ id }: ChatProps) => {
36
37
  }, [dataChat]);
37
38
 
38
39
  return (
39
- <div className="wy-messenger-conversation wy-scroll-y">
40
- <header className="wy-appbars">
40
+ <div className={classNames("wy-messenger-conversation wy-scroll-y", className)}>
41
+ <header className="wy-appbars" data-adjust-scrollbar-top>
41
42
  <nav className="wy-appbar">
42
43
  <div></div>
43
44
  {selectedId && dataConversation &&
@@ -51,11 +52,11 @@ const Chat = ({ id }: ChatProps) => {
51
52
  </header>
52
53
 
53
54
  {!isLoadingChat && !dataChat &&
54
- <div>No chat with the contextual id <strong>{id}</strong></div>
55
+ <div>No chat with the contextual id <strong>{uid}</strong></div>
55
56
  }
56
57
 
57
- {selectedId && dataMembers &&
58
- <Messages id={selectedId} members={dataMembers} />
58
+ {selectedId && dataMembers && dataChat &&
59
+ <Messages id={selectedId} chatRoom={true} members={dataMembers} lastMessageId={dataChat.last_message?.id} />
59
60
  }
60
61
  </div>
61
62
  )
@@ -25,10 +25,12 @@ const Conversation = ({ id, showBackButton }: ConversationProps) => {
25
25
  const { selectedConversationId, setSelectedConversationId } = useContext(MessengerContext);
26
26
  const { user } = useContext(UserContext);
27
27
  const [modalAddOpen, setModalAddOpen] = useState(false);
28
- const [modalDetailsOpen, setModalDetailsOpen] = useState(false);
28
+ const [modalDetailsOpen, setModalDetailsOpen] = useState(false);
29
29
  const [title, setTitle] = useState<string>("");
30
+ const [isRoomOrChat, setIsRoomOrChat] = useState<boolean>(false);
30
31
 
31
32
  const ChatRoom = "edb400ac-839b-45a7-b2a8-6a01820d1c44";
33
+ const Chat = "d65dd4bc-418e-403c-9f56-f9cf4da931ed";
32
34
 
33
35
  if (!client) {
34
36
  throw new Error('Weavy Conversation component must be used within an WeavyProvider');
@@ -50,8 +52,8 @@ const Conversation = ({ id, showBackButton }: ConversationProps) => {
50
52
  const updateNameMutation = useMutateConversationName();
51
53
  const removeMembers = useMutateRemoveMembers();
52
54
 
53
- const handleRealtimeAppUpdated = useCallback((data: ConversationType) => {
54
- if (data.id !== selectedConversationId) return;
55
+ const handleRealtimeAppUpdated = useCallback((realtimeEvent: RealtimeApp) => {
56
+ if (realtimeEvent.app.id !== selectedConversationId) return;
55
57
  queryClient.invalidateQueries(['conversation', selectedConversationId]);
56
58
  }, [selectedConversationId]);
57
59
 
@@ -93,14 +95,14 @@ const Conversation = ({ id, showBackButton }: ConversationProps) => {
93
95
  useEffect(() => {
94
96
 
95
97
  if (selectedConversationId) {
96
- client.subscribe(`a${selectedConversationId}`, "app-updated", handleRealtimeAppUpdated);
98
+ client.subscribe(`a${selectedConversationId}`, "app_updated", handleRealtimeAppUpdated);
97
99
  }
98
100
 
99
101
  return () => {
100
102
 
101
103
  if (selectedConversationId) {
102
104
 
103
- client.unsubscribe(`a${selectedConversationId}`, "app-updated", handleRealtimeAppUpdated);
105
+ client.unsubscribe(`a${selectedConversationId}`, "app_updated", handleRealtimeAppUpdated);
104
106
  }
105
107
  }
106
108
  }, [selectedConversationId]);
@@ -109,11 +111,14 @@ const Conversation = ({ id, showBackButton }: ConversationProps) => {
109
111
  if (dataConversation && dataConversation.type === ChatRoom) {
110
112
  setTitle(dataConversation?.display_name);
111
113
  }
114
+ if(dataConversation && (dataConversation.type === ChatRoom || dataConversation.type === Chat)){
115
+ setIsRoomOrChat(true)
116
+ }
112
117
  }, [dataConversation]);
113
118
 
114
119
  return (
115
120
  <>
116
- <header className="wy-appbars">
121
+ <header className="wy-appbars" data-adjust-scrollbar-top>
117
122
  <nav className="wy-appbar">
118
123
  <div>
119
124
  {showBackButton &&
@@ -146,17 +151,17 @@ const Conversation = ({ id, showBackButton }: ConversationProps) => {
146
151
 
147
152
  {!selectedConversationId &&
148
153
  <div className="wy-avatar-header">
149
- <Avatar src={user.avatar_url} name={user.title} presence={user.presence} id={user.id} size={256} />
150
- <h2>Welcome {user.name}!</h2>
154
+ <Avatar src={user.avatar_url} name={user.display_name} presence={user.presence} id={user.id} size={256} />
155
+ <h2 className='wy-title'>Welcome {user.name}!</h2>
151
156
  Create or select a conversation to get started
152
157
  </div>
153
158
  }
154
- {selectedConversationId && dataMembers &&
155
- <Messages id={selectedConversationId} members={dataMembers} displayName={dataConversation?.display_name} avatarUrl={dataConversation?.avatar_url} />
159
+ {selectedConversationId && dataMembers && dataConversation &&
160
+ <Messages id={selectedConversationId} chatRoom={isRoomOrChat} members={dataMembers} displayName={dataConversation?.display_name} avatarUrl={dataConversation?.avatar_url} lastMessageId={dataConversation?.last_message?.id}/>
156
161
  }
157
162
 
158
163
  <Overlay.UI isOpen={modalAddOpen} className="wy-modal">
159
- <header className="wy-appbars">
164
+ <header className="wy-appbars" data-adjust-scrollbar-top>
160
165
  <nav className="wy-appbar">
161
166
  <Button.UI onClick={() => toggleAddModal(false)}><Icon.UI name='close' /></Button.UI>
162
167
  <div className="wy-appbar-text">Add people</div>
@@ -172,11 +177,13 @@ const Conversation = ({ id, showBackButton }: ConversationProps) => {
172
177
  <div className="wy-appbar-text">Conversation details</div>
173
178
  </nav>
174
179
  </header>
175
- <div>
176
- {dataConversation && <div className="wy-avatar-header"><Avatar src={dataConversation?.avatar_url} name={title} size={128} /></div>}
177
- {dataConversation?.type !== ChatRoom &&
178
- <h4 className="wy-avatar-display-name">{dataConversation?.display_name}</h4>
179
- }
180
+ <div className='wy-scroll-y'>
181
+ {dataConversation && <div className="wy-avatar-header">
182
+ <Avatar src={dataConversation?.avatar_url} name={title} size={128} />
183
+ {dataConversation?.type !== ChatRoom &&
184
+ <h3 className="wy-headline">{dataConversation?.display_name}</h3>
185
+ }
186
+ </div>}
180
187
 
181
188
  {dataConversation?.type === ChatRoom && (
182
189
  <>
@@ -184,14 +191,13 @@ const Conversation = ({ id, showBackButton }: ConversationProps) => {
184
191
  <input className="wy-input" value={title} onChange={(e) => handleUpdateTitle(e)} />
185
192
  </div>
186
193
  <div className="wy-pane-group">
187
- <table className="wy-search-result-table">
194
+ <table className="wy-table wy-search-result-table">
188
195
  <tbody>
189
- {dataMembers?.data.map((m: MemberType) => {
196
+ {dataMembers && dataMembers.data && dataMembers.data.map((m: MemberType) => {
190
197
  return (
191
- <tr key={m.id} className="wy-search-result-table-checkbox">
192
- <td className="wy-search-result-table-icon"><Avatar src={m.avatar_url} name={m.display_name} id={m.id} size={24} presence={m.presence} /></td>
193
- <td>{m.display_name}</td>
194
- <td></td>
198
+ <tr key={m.id}>
199
+ <td className="wy-table-cell-icon wy-search-result-table-icon"><Avatar src={m.avatar_url} name={m.display_name} id={m.id} size={24} presence={m.presence} /></td>
200
+ <td className='wy-table-cell-text'>{m.display_name}</td>
195
201
  </tr>
196
202
  )
197
203
  })}
@@ -203,7 +209,7 @@ const Conversation = ({ id, showBackButton }: ConversationProps) => {
203
209
  </div>
204
210
  </Overlay.UI>
205
211
 
206
-
212
+
207
213
  </>
208
214
  )
209
215
  }
@@ -10,10 +10,10 @@ const ConversationBadge = () => {
10
10
  throw new Error('Weavy Badge component must be used within an WeavyProvider');
11
11
  }
12
12
 
13
- const { isLoading, data } = useBadge();
13
+ const { isLoading, data, refetch } = useBadge();
14
14
 
15
- const handleBadge = (data: BadgeType) => {
16
- setBadge(data.private + data.rooms);
15
+ const handleBadge = (data: BadgeType) => {
16
+ refetch();
17
17
  }
18
18
 
19
19
  useEffect(() => {
@@ -23,10 +23,12 @@ const ConversationBadge = () => {
23
23
  }, [data])
24
24
 
25
25
  useEffect(() => {
26
- client.subscribe(null, "conversation-badge", handleBadge);
26
+ client.subscribe(null, "message_created", handleBadge);
27
+ client.subscribe(null, "conversation_marked", handleBadge);
27
28
 
28
29
  return () => {
29
- client.unsubscribe(null, "conversation-badge", handleBadge);
30
+ client.unsubscribe(null, "message_created", handleBadge);
31
+ client.unsubscribe(null, "conversation_marked", handleBadge);
30
32
  }
31
33
  }, [])
32
34
 
@@ -199,7 +199,7 @@ const ConversationForm = ({ conversationId, handleInsert }: Props) => {
199
199
  <textarea rows={1} ref={textInput} className="wy-message-editor-textfield wy-message-editor-textcontent" value={text} onChange={handleChange} onKeyDown={handleInsertMessage} onKeyPress={useThrottle(handleKeyPress, 4000)}></textarea>
200
200
  </div>
201
201
  <div className="wy-message-editor-buttons">
202
- <Button.UI type="button" onClick={handleInsertMessage} ><Icon.UI name="send"/></Button.UI>
202
+ <Button.UI type="button" onClick={handleInsertMessage} ><Icon.UI color="primary" name="send"/></Button.UI>
203
203
  </div>
204
204
  </div>
205
205
  </form>
@@ -1,28 +1,63 @@
1
- import React, { useContext, useEffect } from 'react';
1
+ import React, { useState, useContext, useEffect, useLayoutEffect, useRef } from 'react';
2
2
  import { WeavyContext } from '../contexts/WeavyContext';
3
3
  import useConversations from '../hooks/useConversations';
4
4
  import ConversationListItem from './ConversationListItem';
5
5
  import NewConversation from './NewConversation';
6
6
  import Avatar from './Avatar';
7
7
  import { UserContext } from '../contexts/UserContext';
8
+ import Button from '../ui/Button';
9
+ import { createScroller } from "../utils/infiniteScroll";
8
10
 
9
11
  const ConversationList = () => {
10
12
  const { client } = useContext(WeavyContext);
11
13
  const { user } = useContext(UserContext);
12
- const { data, isLoading, refetch } = useConversations();
14
+ const { data, isLoading, refetch, fetchNextPage, hasNextPage, isFetchingNextPage } = useConversations({});
15
+ const loadMoreRef = useRef<any>();
16
+ const [resolveScrollerFetch, setResolveScrollerFetch] = useState<Function | null>()
17
+ let scroller: IntersectionObserver | null;
13
18
 
14
19
  if (!client) {
15
20
  throw new Error('Weavy ConversationList component must be used within an WeavyProvider');
16
21
  }
17
22
 
23
+
24
+ useLayoutEffect(() => {
25
+ if(!isLoading){
26
+ scroller?.disconnect();
27
+
28
+ scroller = createScroller(loadMoreRef.current, () => {
29
+ if (hasNextPage) {
30
+ return fetchNextPage().then(() => {
31
+ // Wait for useLayoutEffect before resolving
32
+ return new Promise((resolve: Function) => setResolveScrollerFetch(resolve))
33
+ })
34
+ }
35
+ })
36
+ }
37
+
38
+ return () => {
39
+ scroller?.disconnect();
40
+ scroller = null;
41
+ }
42
+
43
+ }, [isLoading]);
44
+
45
+ useLayoutEffect(() => {
46
+ // Resolve fetchNextPage after layout has been painted
47
+ if (!isFetchingNextPage && resolveScrollerFetch) {
48
+ resolveScrollerFetch()
49
+ setResolveScrollerFetch(null);
50
+ }
51
+ }, [data]);
52
+
18
53
  useEffect(() => {
19
54
 
20
- client.subscribe(null, "app-inserted", handleAppInserted);
21
- client.subscribe(null, "member-added", handleAppInserted);
55
+ client.subscribe(null, "app_created", handleAppInserted);
56
+ client.subscribe(null, "member_added", handleAppInserted);
22
57
 
23
58
  return () => {
24
- client.unsubscribe(null, "app-inserted", handleAppInserted);
25
- client.unsubscribe(null, "member-added", handleAppInserted);
59
+ client.unsubscribe(null, "app_created", handleAppInserted);
60
+ client.unsubscribe(null, "member_added", handleAppInserted);
26
61
  }
27
62
  }, []);
28
63
 
@@ -37,21 +72,34 @@ const ConversationList = () => {
37
72
  )
38
73
  }
39
74
 
75
+ let loadMoreButton = <Button.UI onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage} className="wy-message-readmore">Load more</Button.UI>;
76
+
40
77
  return (
41
78
  <>
42
- <header className="wy-appbars">
79
+ <header className="wy-appbars" data-adjust-scrollbar-top>
43
80
  <nav className="wy-appbar">
44
- <Avatar src={user.avatar_url} name={user.title} presence={user.presence} id={user.id} size={24} />
81
+ <Avatar src={user.avatar_url} name={user.display_name} presence={user.presence} id={user.id} size={24} />
45
82
  <div>Messenger</div>
46
83
  <NewConversation />
47
84
  </nav>
48
85
  </header>
49
86
  <div className="wy-conversations">
50
- {data && data.data?.map((item) =>
51
- <ConversationListItem key={item.id} refetchConversations={refetch} item={item} />
87
+ {data && data.pages && data.pages.map((group, i) => {
88
+ return group.data?.map((item) => {
89
+ return < ConversationListItem key={item.id} refetchConversations={refetch} item={item} />
90
+ })
91
+
92
+ }
93
+
52
94
  )}
95
+ <div className="wy-message-readmore" ref={loadMoreRef}>
96
+ {isFetchingNextPage
97
+ ? 'Loading more...'
98
+ : hasNextPage
99
+ ? loadMoreButton
100
+ : ""}
53
101
 
54
- {/* <a className="wy-pager"><svg className="wy-spinner wy-spin" width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><circle fill="none" cx="12" cy="12" r="11" stroke-linecap="butt" stroke-width="2"></circle></svg></a> */}
102
+ </div>
55
103
  </div>
56
104
  </>
57
105
  )
@@ -27,22 +27,40 @@ const ConversationListItem = ({ item, refetchConversations }: ConversationListIt
27
27
 
28
28
  const ChatRoom = "edb400ac-839b-45a7-b2a8-6a01820d1c44";
29
29
 
30
- const handleClick = (e: React.MouseEvent<HTMLAnchorElement>, id: any) => {
31
- e.preventDefault();
32
- setSelectedConversationId(id);
30
+ const handleClick = (e: React.MouseEvent<HTMLDivElement>, id: any) => {
31
+ if (!e.defaultPrevented) {
32
+ e.preventDefault();
33
+ setSelectedConversationId(id);
34
+ }
33
35
  }
34
36
 
35
- const handleAppUpdated = useCallback((data: ConversationType) => {
36
- if (data.id !== item.id) return;
37
+ const handleAppUpdated = useCallback((realtimeEvent: RealtimeApp) => {
38
+ if (realtimeEvent.app.id !== item.id) return;
37
39
  refetchConversations();
38
40
 
39
- }, [item.id])
41
+ }, [item.id]);
42
+
43
+ const handleMessageCreated = useCallback((realtimeEvent: RealtimeMessage) => {
44
+ if (realtimeEvent.message.app_id !== item.id) return;
45
+ refetchConversations();
46
+
47
+ }, [item.id]);
48
+
49
+ const handleMemberAdded = useCallback((realtimeEvent: RealtimeMember) => {
50
+ if (realtimeEvent.app.id !== item.id) return;
51
+ refetchConversations();
52
+
53
+ }, [item.id]);
40
54
 
41
55
  useEffect(() => {
42
- client?.subscribe(`a${item.id}`, "app-updated", handleAppUpdated);
56
+ client?.subscribe(`a${item.id}`, "app_updated", handleAppUpdated);
57
+ client?.subscribe(`a${item.id}`, "message_created", handleMessageCreated);
58
+ client?.subscribe(`a${item.id}`, "member_added", handleMemberAdded);
43
59
 
44
60
  return () => {
45
- client?.unsubscribe(`a${item.id}`, "app-updated", handleAppUpdated);
61
+ client?.unsubscribe(`a${item.id}`, "app_updated", handleAppUpdated);
62
+ client?.unsubscribe(`a${item.id}`, "message_created", handleMessageCreated);
63
+ client?.unsubscribe(`a${item.id}`, "member_added", handleMemberAdded);
46
64
  }
47
65
  }, [item.id])
48
66
 
@@ -50,12 +68,12 @@ const ConversationListItem = ({ item, refetchConversations }: ConversationListIt
50
68
 
51
69
  const handleUnread = (e: React.MouseEvent<HTMLAnchorElement>) => {
52
70
  e.preventDefault();
53
- readMutation.mutate({ id: item.id, read: false });
71
+ readMutation.mutate({ id: item.id, read: false, messageId: null });
54
72
  }
55
73
 
56
74
  const handleRead = (e: React.MouseEvent<HTMLAnchorElement>) => {
57
75
  e.preventDefault();
58
- readMutation.mutate({ id: item.id, read: true });
76
+ readMutation.mutate({ id: item.id, read: true, messageId: item.last_message.id });
59
77
  }
60
78
 
61
79
  const handlePin = (e: React.MouseEvent<HTMLAnchorElement>) => {
@@ -78,18 +96,18 @@ const ConversationListItem = ({ item, refetchConversations }: ConversationListIt
78
96
  // }
79
97
 
80
98
  return (
81
- <div className={classNames('wy-conversation', {"wy-unread": item.is_unread})} key={item.id}>
82
- <a className={classNames('wy-conversation-link', { "wy-active": selectedConversationId === item.id})} href="#" onClick={(e) => handleClick(e, item.id)}>
83
- <Avatar src={item.avatar_url} id={otherId || -1} presence={item.type !== ChatRoom ? "away" : ""} name={item.display_name} />
84
-
85
- <div className="wy-conversation-body">
86
- <div className="wy-conversation-header">
87
- <div className="wy-conversation-title">{item.display_name}</div>
88
- {item.last_message &&
89
- <time className="wy-conversation-time" dateTime={item.last_message.created_at.toString()} title={date.format('LLLL')}>{date.fromNow()}</time>
90
- }
91
- </div>
92
- <div className="wy-conversation-summary">
99
+ <div className={classNames('wy-item wy-item-lg wy-item-hover wy-conversation', {"wy-unread": item.is_unread, "wy-active": selectedConversationId === item.id})} key={item.id} onClick={(e) => handleClick(e, item.id)}>
100
+ <Avatar src={item.avatar_url} id={otherId || -1} presence={item.type !== ChatRoom ? "away" : ""} name={item.display_name} />
101
+
102
+ <div className="wy-item-body">
103
+ <div className="wy-item-row">
104
+ <div className="wy-item-title">{item.display_name}</div>
105
+ {item.last_message &&
106
+ <time className="wy-meta" dateTime={item.last_message.created_at.toString()} title={date.format('LLLL')}>{date.fromNow()}</time>
107
+ }
108
+ </div>
109
+ <div className="wy-item-row">
110
+ <div className="wy-item-text">
93
111
  <Typing id={item.id} context="listitem">
94
112
 
95
113
  {item.last_message?.html &&
@@ -108,44 +126,43 @@ const ConversationListItem = ({ item, refetchConversations }: ConversationListIt
108
126
 
109
127
  </Typing>
110
128
  </div>
111
- </div>
112
- </a>
129
+
113
130
 
114
- <div className="wy-conversation-actions">
115
- {item.is_pinned &&
116
- <Button.UI onClick={handleUnpin}>
117
- <Icon.UI name="pin" size={.75} />
118
- </Button.UI>
119
-
120
- }
121
-
122
- <Dropdown.UI directionX='left'>
123
- <>
124
- {item.is_unread &&
125
- <Dropdown.Item onClick={handleRead}>Mark as read</Dropdown.Item>
126
- }
127
- {!item.is_unread &&
128
- <Dropdown.Item onClick={handleUnread}>Mark as unread</Dropdown.Item>
129
- }
130
- </>
131
- <>
131
+ </div>
132
+ </div>
133
+ <div className="wy-item-actions wy-item-actions-bottom">
132
134
  {item.is_pinned &&
133
- <Dropdown.Item onClick={handleUnpin}>Unpin</Dropdown.Item>
134
- }
135
- {!item.is_pinned &&
136
- <Dropdown.Item onClick={handlePin}>Pin</Dropdown.Item>
137
- }
138
- </>
139
- {item.type === ChatRoom &&
140
- <Dropdown.Item onClick={handleLeaveConversation}>Leave conversation</Dropdown.Item>
141
- }
135
+ <Button.UI onClick={handleUnpin}>
136
+ <Icon.UI name="pin" size={1/1.5} />
137
+ </Button.UI>
142
138
 
143
- {/* <li><Button.UI onClick={handleStar}>Star</Button.UI></li> */}
144
- </Dropdown.UI>
139
+ }
145
140
 
141
+ <Dropdown.UI directionX='left'>
142
+ <>
143
+ {item.is_unread &&
144
+ <Dropdown.Item onClick={handleRead}>Mark as read</Dropdown.Item>
145
+ }
146
+ {!item.is_unread &&
147
+ <Dropdown.Item onClick={handleUnread}>Mark as unread</Dropdown.Item>
148
+ }
149
+ </>
150
+ <>
151
+ {item.is_pinned &&
152
+ <Dropdown.Item onClick={handleUnpin}>Unpin</Dropdown.Item>
153
+ }
154
+ {!item.is_pinned &&
155
+ <Dropdown.Item onClick={handlePin}>Pin</Dropdown.Item>
156
+ }
157
+ </>
158
+ {item.type === ChatRoom &&
159
+ <Dropdown.Item onClick={handleLeaveConversation}>Leave conversation</Dropdown.Item>
160
+ }
146
161
 
162
+ {/* <li><Button.UI onClick={handleStar}>Star</Button.UI></li> */}
163
+ </Dropdown.UI>
147
164
 
148
- </div>
165
+ </div>
149
166
  </div>
150
167
  )
151
168
  }
@@ -1,9 +1,11 @@
1
- import React, { useContext, useEffect } from "react";
1
+ import React, { useContext, useEffect, useState, useRef, useCallback } from "react";
2
2
  import { WeavyContext } from "../contexts/WeavyContext";
3
3
  import Button from '../ui/Button';
4
+ import Spinner from '../ui/Spinner';
4
5
  import Icon from '../ui/Icon';
5
6
  import useMutateExternalBlobs from '../hooks/useMutateExternalBlobs';
6
- import { UserContext } from "../contexts/UserContext";
7
+ import Overlay from '../ui/Overlay';
8
+ import WeavyPostal from "../utils/postal-parent";
7
9
 
8
10
  type Props = {
9
11
  onFileAdded: Function
@@ -12,72 +14,73 @@ type Props = {
12
14
  const FileBrowser = ({ onFileAdded }: Props) => {
13
15
 
14
16
  const { options } = useContext(WeavyContext);
15
- const { user } = useContext(UserContext);
16
-
17
+ const [modalOpen, setModalOpen] = useState(false);
18
+ const [visible, setVisible] = useState(false);
19
+ const [frameSrc, setFrameSrc] = useState("");
17
20
  const addExternalBlobs = useMutateExternalBlobs();
21
+ const fileBrowserUrl = options?.filebrowserUrl || "";
22
+
23
+ const frameRef = useCallback((node: HTMLIFrameElement | null) => {
24
+ if (node !== null && node.contentWindow != null) {
25
+ WeavyPostal.registerContentWindow(node.contentWindow.self, "weavy-filebrowser", "wy-filebrowser", new URL(fileBrowserUrl).origin);
26
+ }
27
+ }, []);
18
28
 
19
29
  useEffect(() => {
20
- window.addEventListener("message", handleFilebrowserMessage);
30
+ const origin = window.top?.document.location.origin;
31
+
32
+ const filebrowserSrc = fileBrowserUrl + "?origin=" + origin + "&v=X&t=" + Date.now().toString() + "&weavyId=wy-filebrowser";
21
33
 
34
+ setFrameSrc(filebrowserSrc)
35
+
36
+ WeavyPostal.on("add-external-blobs", handleFiles);
37
+ WeavyPostal.on("request:file-browser-close", handleClose);
22
38
 
23
39
  return () => {
24
- window.removeEventListener("message", handleFilebrowserMessage);
40
+ WeavyPostal.off("add-external-blobs", handleFiles);
41
+ WeavyPostal.off("request:file-browser-close", handleClose);
25
42
  }
26
- }, []);
43
+ }, [onFileAdded]);
27
44
 
28
- const handleFilebrowserMessage = async (e: any) => {
29
- const messageData = e.data;
30
-
31
- switch (messageData.name) {
32
- case "addExternalBlobs":
33
- var result = await addExternalBlobs.mutateAsync({ blobs: messageData.blobs });
34
- onFileAdded(result);
35
- closeFilebrowser();
36
- break;
37
- case "file-browser-close":
38
- closeFilebrowser();
39
- break;
40
- }
45
+ const toggleModal = (open: boolean) => {
46
+ setModalOpen(open);
41
47
  }
42
48
 
43
- const closeFilebrowser = () => {
44
- let fb = document.getElementById("weavy-filebrowser");
45
- if (fb) {
46
- fb.style.display = "none";
47
- }
49
+ const handleFiles = async (e: Event, message: any) => {
50
+ var result = await addExternalBlobs.mutateAsync({ blobs: message.blobs });
51
+ onFileAdded(result);
52
+ closeFilebrowser();
48
53
  }
49
54
 
50
- const openFilebrowser = () => {
51
- let fb = document.getElementById("weavy-filebrowser");
52
-
53
- if (!fb) {
54
- const origin = window.top?.document.location.origin;
55
- const fileBrowserUrl = options?.filebrowserUrl;
56
- const filebrowserSrc = fileBrowserUrl + "?origin=" + origin + "&v=X&t=" + Date.now().toString() + "&weavyId=-1";
57
-
58
- let $filebrowserFrame = document.createElement("iframe");
59
- $filebrowserFrame.id = "weavy-filebrowser";
60
- $filebrowserFrame.name = "weavy-filebrowser";
61
- $filebrowserFrame.src = filebrowserSrc;
62
- $filebrowserFrame.className = "wy-filebrowser-frame";
63
- $filebrowserFrame.style.cssText = "position: fixed; top: 0; left: 0; height: 100%; width: 100%; background: rgba(1,1,1,.4); z-index: 10000; display:none"
64
-
65
- window.top?.document.body.appendChild($filebrowserFrame);
55
+ const handleClose = () => {
56
+ closeFilebrowser();
57
+ }
66
58
 
67
- $filebrowserFrame.addEventListener('load', () => {
68
- $filebrowserFrame.style.display = "block";
69
- });
59
+ const closeFilebrowser = () => {
60
+ setModalOpen(false);
61
+ setVisible(false);
62
+ }
70
63
 
71
- } else {
72
- fb.style.display = "block";
73
- }
64
+ const handleFrameLoad = () => {
65
+ setVisible(true);
74
66
  }
75
67
 
76
68
  return (
77
69
  <>
78
- {options?.enableCloudFiles &&
79
- <Button.UI onClick={openFilebrowser} title="Add file from cloud"><Icon.UI name="cloud" /></Button.UI>
80
- }
70
+ {options?.enableCloudFiles &&
71
+ <>
72
+ <Button.UI onClick={() => toggleModal(true)} title="Add file from cloud"><Icon.UI name="cloud" /></Button.UI>
73
+
74
+ <Overlay.UI isOpen={modalOpen} className="wy-modal wy-panel wy-loaded">
75
+ {!visible &&
76
+ <Spinner.UI overlay={true} />
77
+ }
78
+
79
+ <iframe ref={frameRef} onLoad={handleFrameLoad} src={frameSrc} className="wy-panel-frame" id="weavy-filebrowser" name="weavy-filebrowser"></iframe>
80
+
81
+ </Overlay.UI>
82
+ </>
83
+ }
81
84
  </>
82
85
  )
83
86
  }