@peers-app/peers-ui 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/README.md +52 -0
- package/.github/workflows/publish.yml +45 -0
- package/babel.config.js +7 -0
- package/dist/app.d.ts +9 -0
- package/dist/app.js +54 -0
- package/dist/command-palette/command-palette-ui.d.ts +2 -0
- package/dist/command-palette/command-palette-ui.js +192 -0
- package/dist/command-palette/command-palette.d.ts +23 -0
- package/dist/command-palette/command-palette.js +371 -0
- package/dist/components/checkbox.d.ts +7 -0
- package/dist/components/checkbox.js +20 -0
- package/dist/components/group-switcher.d.ts +6 -0
- package/dist/components/group-switcher.js +301 -0
- package/dist/components/input-date.d.ts +7 -0
- package/dist/components/input-date.js +19 -0
- package/dist/components/input-datetime.d.ts +7 -0
- package/dist/components/input-datetime.js +35 -0
- package/dist/components/input-number.d.ts +9 -0
- package/dist/components/input-number.js +87 -0
- package/dist/components/input.d.ts +7 -0
- package/dist/components/input.js +20 -0
- package/dist/components/io-schema-values.d.ts +15 -0
- package/dist/components/io-schema-values.js +105 -0
- package/dist/components/io-schema.d.ts +13 -0
- package/dist/components/io-schema.js +163 -0
- package/dist/components/lazy-list.d.ts +13 -0
- package/dist/components/lazy-list.js +91 -0
- package/dist/components/lazy-sortable-list.d.ts +29 -0
- package/dist/components/lazy-sortable-list.js +12 -0
- package/dist/components/left-bar.d.ts +3 -0
- package/dist/components/left-bar.js +130 -0
- package/dist/components/list-screen.d.ts +16 -0
- package/dist/components/list-screen.js +100 -0
- package/dist/components/loading-indicator.d.ts +2 -0
- package/dist/components/loading-indicator.js +12 -0
- package/dist/components/main-content-container.d.ts +2 -0
- package/dist/components/main-content-container.js +90 -0
- package/dist/components/markdown-editor/autolink-plugin.d.ts +2 -0
- package/dist/components/markdown-editor/autolink-plugin.js +29 -0
- package/dist/components/markdown-editor/editor-inline.d.ts +3 -0
- package/dist/components/markdown-editor/editor-inline.js +13 -0
- package/dist/components/markdown-editor/editor.d.ts +18 -0
- package/dist/components/markdown-editor/editor.js +143 -0
- package/dist/components/markdown-editor/markdown-plugin.d.ts +9 -0
- package/dist/components/markdown-editor/markdown-plugin.js +194 -0
- package/dist/components/markdown-editor/mention-node.d.ts +21 -0
- package/dist/components/markdown-editor/mention-node.js +160 -0
- package/dist/components/markdown-editor/mentions-plugin.d.ts +7 -0
- package/dist/components/markdown-editor/mentions-plugin.js +268 -0
- package/dist/components/markdown-editor/theme.d.ts +46 -0
- package/dist/components/markdown-editor/theme.js +48 -0
- package/dist/components/markdown-editor/toolbar.d.ts +10 -0
- package/dist/components/markdown-editor/toolbar.js +112 -0
- package/dist/components/markdown-with-mentions.d.ts +4 -0
- package/dist/components/markdown-with-mentions.js +140 -0
- package/dist/components/message-logs/message-logs.d.ts +6 -0
- package/dist/components/message-logs/message-logs.js +307 -0
- package/dist/components/messages/avatar.d.ts +10 -0
- package/dist/components/messages/avatar.js +65 -0
- package/dist/components/messages/channel-message-list.d.ts +14 -0
- package/dist/components/messages/channel-message-list.js +158 -0
- package/dist/components/messages/channel-view.d.ts +6 -0
- package/dist/components/messages/channel-view.js +82 -0
- package/dist/components/messages/message-compose.d.ts +11 -0
- package/dist/components/messages/message-compose.js +152 -0
- package/dist/components/messages/message-display.d.ts +10 -0
- package/dist/components/messages/message-display.js +152 -0
- package/dist/components/messages/thread-message-list.d.ts +11 -0
- package/dist/components/messages/thread-message-list.js +122 -0
- package/dist/components/messages/thread-view.d.ts +6 -0
- package/dist/components/messages/thread-view.js +174 -0
- package/dist/components/off-canvas.d.ts +13 -0
- package/dist/components/off-canvas.js +89 -0
- package/dist/components/router.d.ts +6 -0
- package/dist/components/router.js +240 -0
- package/dist/components/save-button.d.ts +13 -0
- package/dist/components/save-button.js +75 -0
- package/dist/components/sortable-list.d.ts +36 -0
- package/dist/components/sortable-list.js +77 -0
- package/dist/components/tabs.d.ts +11 -0
- package/dist/components/tabs.js +69 -0
- package/dist/components/text-list-editor.tsx/text-list-editor.d.ts +6 -0
- package/dist/components/text-list-editor.tsx/text-list-editor.js +13 -0
- package/dist/components/tooltip.d.ts +11 -0
- package/dist/components/tooltip.js +20 -0
- package/dist/components/top-bar.d.ts +2 -0
- package/dist/components/top-bar.js +51 -0
- package/dist/components/typeahead/mentions-plugin.d.ts +7 -0
- package/dist/components/typeahead/mentions-plugin.js +203 -0
- package/dist/components/typeahead/typeahead-editor.d.ts +15 -0
- package/dist/components/typeahead/typeahead-editor.js +134 -0
- package/dist/components/typeahead/typeahead.d.ts +12 -0
- package/dist/components/typeahead/typeahead.js +94 -0
- package/dist/components/typeahead.d.ts +22 -0
- package/dist/components/typeahead.js +270 -0
- package/dist/globals.d.ts +29 -0
- package/dist/globals.js +148 -0
- package/dist/hooks.d.ts +34 -0
- package/dist/hooks.js +137 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +20 -0
- package/dist/layout-vars.d.ts +6 -0
- package/dist/layout-vars.js +10 -0
- package/dist/mention-configs.d.ts +18 -0
- package/dist/mention-configs.js +149 -0
- package/dist/screens/assistants/assistant-config.d.ts +5 -0
- package/dist/screens/assistants/assistant-config.js +52 -0
- package/dist/screens/assistants/assistant-details.d.ts +4 -0
- package/dist/screens/assistants/assistant-details.js +85 -0
- package/dist/screens/assistants/assistant-info.d.ts +6 -0
- package/dist/screens/assistants/assistant-info.js +28 -0
- package/dist/screens/assistants/assistant-list.d.ts +2 -0
- package/dist/screens/assistants/assistant-list.js +114 -0
- package/dist/screens/assistants/assistant-tools.d.ts +5 -0
- package/dist/screens/assistants/assistant-tools.js +38 -0
- package/dist/screens/contacts/contact-details.d.ts +6 -0
- package/dist/screens/contacts/contact-details.js +100 -0
- package/dist/screens/contacts/contact-list.d.ts +2 -0
- package/dist/screens/contacts/contact-list.js +213 -0
- package/dist/screens/contacts/index.d.ts +4 -0
- package/dist/screens/contacts/index.js +21 -0
- package/dist/screens/events/cron.d.ts +3 -0
- package/dist/screens/events/cron.js +77 -0
- package/dist/screens/events/event-details.d.ts +6 -0
- package/dist/screens/events/event-details.js +112 -0
- package/dist/screens/events/event-handlers.d.ts +7 -0
- package/dist/screens/events/event-handlers.js +84 -0
- package/dist/screens/events/event-info.d.ts +5 -0
- package/dist/screens/events/event-info.js +19 -0
- package/dist/screens/events/event-list.d.ts +2 -0
- package/dist/screens/events/event-list.js +107 -0
- package/dist/screens/events/event-schedule.d.ts +5 -0
- package/dist/screens/events/event-schedule.js +124 -0
- package/dist/screens/groups/group-details.d.ts +6 -0
- package/dist/screens/groups/group-details.js +218 -0
- package/dist/screens/groups/group-list.d.ts +2 -0
- package/dist/screens/groups/group-list.js +275 -0
- package/dist/screens/groups/group-members.d.ts +8 -0
- package/dist/screens/groups/group-members.js +315 -0
- package/dist/screens/groups/index.d.ts +6 -0
- package/dist/screens/groups/index.js +23 -0
- package/dist/screens/knowledge/knowledge-frame-details.bk.d.ts +6 -0
- package/dist/screens/knowledge/knowledge-frame-details.bk.js +84 -0
- package/dist/screens/knowledge/knowledge-frame-details.d.ts +8 -0
- package/dist/screens/knowledge/knowledge-frame-details.js +143 -0
- package/dist/screens/knowledge/knowledge-frame-list.d.ts +2 -0
- package/dist/screens/knowledge/knowledge-frame-list.js +45 -0
- package/dist/screens/knowledge/knowledge-value-details.d.ts +6 -0
- package/dist/screens/knowledge/knowledge-value-details.js +150 -0
- package/dist/screens/knowledge/knowledge-value-list-item.d.ts +5 -0
- package/dist/screens/knowledge/knowledge-value-list-item.js +39 -0
- package/dist/screens/knowledge/knowledge-value-list.d.ts +3 -0
- package/dist/screens/knowledge/knowledge-value-list.js +123 -0
- package/dist/screens/packages/package-details.d.ts +6 -0
- package/dist/screens/packages/package-details.js +82 -0
- package/dist/screens/packages/package-info.d.ts +5 -0
- package/dist/screens/packages/package-info.js +42 -0
- package/dist/screens/packages/package-list.d.ts +2 -0
- package/dist/screens/packages/package-list.js +182 -0
- package/dist/screens/packages/package-new-local.d.ts +2 -0
- package/dist/screens/packages/package-new-local.js +82 -0
- package/dist/screens/peer-types/peer-type-details.d.ts +10 -0
- package/dist/screens/peer-types/peer-type-details.js +126 -0
- package/dist/screens/peer-types/peer-type-list.d.ts +2 -0
- package/dist/screens/peer-types/peer-type-list.js +57 -0
- package/dist/screens/predicates/predicate-details.d.ts +6 -0
- package/dist/screens/predicates/predicate-details.js +103 -0
- package/dist/screens/predicates/predicate-list.d.ts +2 -0
- package/dist/screens/predicates/predicate-list.js +46 -0
- package/dist/screens/profile.d.ts +2 -0
- package/dist/screens/profile.js +66 -0
- package/dist/screens/search/global-search.d.ts +2 -0
- package/dist/screens/search/global-search.js +186 -0
- package/dist/screens/settings/color-mode-dropdown.d.ts +6 -0
- package/dist/screens/settings/color-mode-dropdown.js +63 -0
- package/dist/screens/settings/settings-page.d.ts +2 -0
- package/dist/screens/settings/settings-page.js +49 -0
- package/dist/screens/setup-user.d.ts +2 -0
- package/dist/screens/setup-user.js +270 -0
- package/dist/screens/tools/tool-code.d.ts +5 -0
- package/dist/screens/tools/tool-code.js +32 -0
- package/dist/screens/tools/tool-details.d.ts +6 -0
- package/dist/screens/tools/tool-details.js +68 -0
- package/dist/screens/tools/tool-info.d.ts +5 -0
- package/dist/screens/tools/tool-info.js +74 -0
- package/dist/screens/tools/tool-list.d.ts +2 -0
- package/dist/screens/tools/tool-list.js +123 -0
- package/dist/screens/tools/tool-schema.d.ts +5 -0
- package/dist/screens/tools/tool-schema.js +30 -0
- package/dist/screens/tools/tool-test-details.d.ts +4 -0
- package/dist/screens/tools/tool-test-details.js +54 -0
- package/dist/screens/tools/tool-test-list.d.ts +4 -0
- package/dist/screens/tools/tool-test-list.js +82 -0
- package/dist/screens/variables/variable-details.d.ts +6 -0
- package/dist/screens/variables/variable-details.js +140 -0
- package/dist/screens/variables/variable-list.d.ts +2 -0
- package/dist/screens/variables/variable-list.js +58 -0
- package/dist/screens/workflows/workflow-details.d.ts +6 -0
- package/dist/screens/workflows/workflow-details.js +122 -0
- package/dist/screens/workflows/workflow-info.d.ts +5 -0
- package/dist/screens/workflows/workflow-info.js +18 -0
- package/dist/screens/workflows/workflow-instructions.d.ts +5 -0
- package/dist/screens/workflows/workflow-instructions.js +118 -0
- package/dist/screens/workflows/workflow-list.d.ts +2 -0
- package/dist/screens/workflows/workflow-list.js +109 -0
- package/dist/screens/workflows/workflow-subscriptions.d.ts +6 -0
- package/dist/screens/workflows/workflow-subscriptions.js +81 -0
- package/dist/setupTests.d.ts +1 -0
- package/dist/setupTests.js +31 -0
- package/dist/system-apps/assistants.app.d.ts +2 -0
- package/dist/system-apps/assistants.app.js +8 -0
- package/dist/system-apps/contacts.app.d.ts +2 -0
- package/dist/system-apps/contacts.app.js +9 -0
- package/dist/system-apps/events.app.d.ts +2 -0
- package/dist/system-apps/events.app.js +8 -0
- package/dist/system-apps/groups.app.d.ts +2 -0
- package/dist/system-apps/groups.app.js +9 -0
- package/dist/system-apps/index.d.ts +19 -0
- package/dist/system-apps/index.js +90 -0
- package/dist/system-apps/knowledge-frames.app.d.ts +2 -0
- package/dist/system-apps/knowledge-frames.app.js +9 -0
- package/dist/system-apps/knowledge-values.app.d.ts +2 -0
- package/dist/system-apps/knowledge-values.app.js +9 -0
- package/dist/system-apps/packages.app.d.ts +2 -0
- package/dist/system-apps/packages.app.js +8 -0
- package/dist/system-apps/predicates.app.d.ts +2 -0
- package/dist/system-apps/predicates.app.js +8 -0
- package/dist/system-apps/profile.app.d.ts +2 -0
- package/dist/system-apps/profile.app.js +8 -0
- package/dist/system-apps/search.app.d.ts +2 -0
- package/dist/system-apps/search.app.js +9 -0
- package/dist/system-apps/settings.app.d.ts +2 -0
- package/dist/system-apps/settings.app.js +8 -0
- package/dist/system-apps/threads.app.d.ts +2 -0
- package/dist/system-apps/threads.app.js +8 -0
- package/dist/system-apps/tools.app.d.ts +2 -0
- package/dist/system-apps/tools.app.js +8 -0
- package/dist/system-apps/types.app.d.ts +2 -0
- package/dist/system-apps/types.app.js +8 -0
- package/dist/system-apps/variables.app.d.ts +2 -0
- package/dist/system-apps/variables.app.js +8 -0
- package/dist/system-apps/workflows.app.d.ts +2 -0
- package/dist/system-apps/workflows.app.js +8 -0
- package/dist/tabs-layout/tabs-layout.d.ts +5 -0
- package/dist/tabs-layout/tabs-layout.js +374 -0
- package/dist/tabs-layout/tabs-state.d.ts +26 -0
- package/dist/tabs-layout/tabs-state.js +239 -0
- package/dist/three-bar-layout/left-bar-content.d.ts +7 -0
- package/dist/three-bar-layout/left-bar-content.js +151 -0
- package/dist/three-bar-layout/right-bar-content.d.ts +2 -0
- package/dist/three-bar-layout/right-bar-content.js +64 -0
- package/dist/three-bar-layout/three-bar-layout.d.ts +5 -0
- package/dist/three-bar-layout/three-bar-layout.js +218 -0
- package/dist/ui-defaults/index.d.ts +2 -0
- package/dist/ui-defaults/index.js +4 -0
- package/dist/ui-defaults/list-screen.d.ts +6 -0
- package/dist/ui-defaults/list-screen.js +74 -0
- package/dist/ui-defaults/notes-editor.d.ts +7 -0
- package/dist/ui-defaults/notes-editor.js +41 -0
- package/dist/ui-router/routes-loader.d.ts +25 -0
- package/dist/ui-router/routes-loader.js +97 -0
- package/dist/ui-router/ui-loader.d.ts +18 -0
- package/dist/ui-router/ui-loader.js +481 -0
- package/dist/utils.d.ts +9 -0
- package/dist/utils.js +250 -0
- package/docs/conversation-tab.md +201 -0
- package/docs/getting-started.md +284 -0
- package/docs/knowledge.md +187 -0
- package/docs/tabs-ui.md +696 -0
- package/docs/user-contacts-ui.md +384 -0
- package/jest.config.js +25 -0
- package/package.json +109 -0
- package/src/app.tsx +59 -0
- package/src/command-palette/command-palette-ui.tsx +264 -0
- package/src/command-palette/command-palette.ts +364 -0
- package/src/components/checkbox.tsx +22 -0
- package/src/components/group-switcher.tsx +469 -0
- package/src/components/input-date.tsx +28 -0
- package/src/components/input-datetime.tsx +41 -0
- package/src/components/input-number.tsx +67 -0
- package/src/components/input.tsx +22 -0
- package/src/components/io-schema-values.tsx +122 -0
- package/src/components/io-schema.tsx +234 -0
- package/src/components/lazy-list.tsx +98 -0
- package/src/components/lazy-sortable-list.tsx +51 -0
- package/src/components/left-bar.tsx +264 -0
- package/src/components/list-screen.tsx +105 -0
- package/src/components/loading-indicator.tsx +9 -0
- package/src/components/main-content-container.tsx +76 -0
- package/src/components/markdown-editor/autolink-plugin.tsx +36 -0
- package/src/components/markdown-editor/editor-inline.tsx +10 -0
- package/src/components/markdown-editor/editor.tsx +152 -0
- package/src/components/markdown-editor/markdown-plugin.tsx +224 -0
- package/src/components/markdown-editor/mention-node.ts +199 -0
- package/src/components/markdown-editor/mentions-plugin.tsx +356 -0
- package/src/components/markdown-editor/theme.ts +47 -0
- package/src/components/markdown-editor/toolbar.tsx +263 -0
- package/src/components/markdown-with-mentions.tsx +183 -0
- package/src/components/message-logs/message-logs.tsx +406 -0
- package/src/components/messages/avatar.tsx +95 -0
- package/src/components/messages/channel-message-list.tsx +177 -0
- package/src/components/messages/channel-view.tsx +74 -0
- package/src/components/messages/message-compose.tsx +162 -0
- package/src/components/messages/message-display.tsx +217 -0
- package/src/components/messages/thread-message-list.tsx +126 -0
- package/src/components/messages/thread-view.tsx +214 -0
- package/src/components/off-canvas.tsx +83 -0
- package/src/components/router.tsx +224 -0
- package/src/components/save-button.tsx +109 -0
- package/src/components/sortable-list.tsx +102 -0
- package/src/components/tabs.tsx +70 -0
- package/src/components/text-list-editor.tsx/text-list-editor.tsx +13 -0
- package/src/components/tooltip.tsx +50 -0
- package/src/components/top-bar.tsx +119 -0
- package/src/components/typeahead/mentions-plugin.tsx +265 -0
- package/src/components/typeahead/typeahead-editor.tsx +140 -0
- package/src/components/typeahead/typeahead.tsx +77 -0
- package/src/components/typeahead.tsx +359 -0
- package/src/globals.tsx +162 -0
- package/src/hooks.ts +144 -0
- package/src/index.tsx +8 -0
- package/src/layout-vars.ts +8 -0
- package/src/mention-configs.ts +166 -0
- package/src/screens/assistants/assistant-config.tsx +80 -0
- package/src/screens/assistants/assistant-details.tsx +77 -0
- package/src/screens/assistants/assistant-info.tsx +45 -0
- package/src/screens/assistants/assistant-list.tsx +115 -0
- package/src/screens/assistants/assistant-tools.tsx +61 -0
- package/src/screens/contacts/contact-details.tsx +175 -0
- package/src/screens/contacts/contact-list.tsx +251 -0
- package/src/screens/contacts/index.ts +6 -0
- package/src/screens/events/cron.ts +74 -0
- package/src/screens/events/event-details.tsx +117 -0
- package/src/screens/events/event-handlers.tsx +61 -0
- package/src/screens/events/event-info.tsx +29 -0
- package/src/screens/events/event-list.tsx +104 -0
- package/src/screens/events/event-schedule.tsx +130 -0
- package/src/screens/groups/group-details.tsx +306 -0
- package/src/screens/groups/group-list.tsx +366 -0
- package/src/screens/groups/group-members.tsx +455 -0
- package/src/screens/groups/index.ts +9 -0
- package/src/screens/knowledge/knowledge-frame-details.bk.tsx +160 -0
- package/src/screens/knowledge/knowledge-frame-details.tsx +176 -0
- package/src/screens/knowledge/knowledge-frame-list.tsx +49 -0
- package/src/screens/knowledge/knowledge-value-details.tsx +181 -0
- package/src/screens/knowledge/knowledge-value-list-item.tsx +48 -0
- package/src/screens/knowledge/knowledge-value-list.tsx +131 -0
- package/src/screens/packages/package-details.tsx +117 -0
- package/src/screens/packages/package-info.tsx +83 -0
- package/src/screens/packages/package-list.tsx +191 -0
- package/src/screens/packages/package-new-local.tsx +93 -0
- package/src/screens/peer-types/peer-type-details.tsx +162 -0
- package/src/screens/peer-types/peer-type-list.tsx +74 -0
- package/src/screens/predicates/predicate-details.tsx +125 -0
- package/src/screens/predicates/predicate-list.tsx +50 -0
- package/src/screens/profile.tsx +68 -0
- package/src/screens/search/global-search.tsx +274 -0
- package/src/screens/settings/color-mode-dropdown.tsx +57 -0
- package/src/screens/settings/settings-page.tsx +76 -0
- package/src/screens/setup-user.tsx +367 -0
- package/src/screens/tools/tool-code.tsx +35 -0
- package/src/screens/tools/tool-details.tsx +101 -0
- package/src/screens/tools/tool-info.tsx +60 -0
- package/src/screens/tools/tool-list.tsx +121 -0
- package/src/screens/tools/tool-schema.tsx +42 -0
- package/src/screens/tools/tool-test-details.tsx +100 -0
- package/src/screens/tools/tool-test-list.tsx +74 -0
- package/src/screens/variables/variable-details.tsx +183 -0
- package/src/screens/variables/variable-list.tsx +74 -0
- package/src/screens/workflows/workflow-details.tsx +130 -0
- package/src/screens/workflows/workflow-info.tsx +29 -0
- package/src/screens/workflows/workflow-instructions.tsx +127 -0
- package/src/screens/workflows/workflow-list.tsx +107 -0
- package/src/screens/workflows/workflow-subscriptions.tsx +58 -0
- package/src/setupTests.ts +32 -0
- package/src/system-apps/assistants.app.ts +7 -0
- package/src/system-apps/contacts.app.ts +8 -0
- package/src/system-apps/events.app.ts +7 -0
- package/src/system-apps/groups.app.ts +8 -0
- package/src/system-apps/index.ts +79 -0
- package/src/system-apps/knowledge-frames.app.ts +8 -0
- package/src/system-apps/knowledge-values.app.ts +8 -0
- package/src/system-apps/packages.app.ts +7 -0
- package/src/system-apps/predicates.app.ts +7 -0
- package/src/system-apps/profile.app.ts +7 -0
- package/src/system-apps/search.app.ts +8 -0
- package/src/system-apps/settings.app.ts +7 -0
- package/src/system-apps/threads.app.ts +7 -0
- package/src/system-apps/tools.app.ts +7 -0
- package/src/system-apps/types.app.ts +7 -0
- package/src/system-apps/variables.app.ts +7 -0
- package/src/system-apps/workflows.app.ts +7 -0
- package/src/tabs-layout/tabs-layout.tsx +672 -0
- package/src/tabs-layout/tabs-state.ts +269 -0
- package/src/three-bar-layout/left-bar-content.tsx +202 -0
- package/src/three-bar-layout/right-bar-content.tsx +67 -0
- package/src/three-bar-layout/three-bar-layout.tsx +297 -0
- package/src/ui-defaults/index.ts +3 -0
- package/src/ui-defaults/list-screen.tsx +92 -0
- package/src/ui-defaults/notes-editor.tsx +51 -0
- package/src/ui-router/routes-loader.ts +98 -0
- package/src/ui-router/ui-loader.tsx +497 -0
- package/src/utils.ts +266 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { DataFilter, IMessage, Messages } from "@peers-app/peers-sdk";
|
|
2
|
+
import { min, sortBy, uniqBy } from 'lodash';
|
|
3
|
+
import React, { Fragment, useEffect, useState } from 'react';
|
|
4
|
+
import InfiniteScroll from 'react-infinite-scroll-component';
|
|
5
|
+
import { me } from '../../globals';
|
|
6
|
+
import { LoadingIndicator } from '../loading-indicator';
|
|
7
|
+
import { } from './message-compose';
|
|
8
|
+
import { MessageDisplay } from './message-display';
|
|
9
|
+
|
|
10
|
+
const windowHeight = () => window.innerHeight
|
|
11
|
+
|
|
12
|
+
interface IProps {
|
|
13
|
+
height: any
|
|
14
|
+
channelId: string
|
|
15
|
+
batchSize: number
|
|
16
|
+
effects?: {
|
|
17
|
+
pushMessage: (message: IMessage) => any,
|
|
18
|
+
}
|
|
19
|
+
scrollChanged?: (isBottomInView: boolean) => any,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const ChannelMessageList = (props: IProps) => {
|
|
23
|
+
const { height, channelId, batchSize } = props;
|
|
24
|
+
|
|
25
|
+
const [messages, setMessages] = useState<IMessage[]>([]);
|
|
26
|
+
const [allMessagesLoaded, setAllMessagesLoaded] = useState(false);
|
|
27
|
+
const messagesEndRef = React.useRef<HTMLDivElement>(null);
|
|
28
|
+
|
|
29
|
+
function scrollToBottom(behavior: 'instant' | 'smooth', delay = 100) {
|
|
30
|
+
setTimeout(() => {
|
|
31
|
+
messagesEndRef.current?.scrollIntoView({ behavior });
|
|
32
|
+
}, delay);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const observer = new IntersectionObserver(
|
|
37
|
+
([entry]) => {
|
|
38
|
+
props?.scrollChanged?.(entry.isIntersecting);
|
|
39
|
+
},
|
|
40
|
+
{ threshold: 1.0 }
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
if (messagesEndRef.current) {
|
|
44
|
+
observer.observe(messagesEndRef.current);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return () => {
|
|
48
|
+
if (messagesEndRef.current) {
|
|
49
|
+
observer.unobserve(messagesEndRef.current);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}, []);
|
|
53
|
+
|
|
54
|
+
function prependItems() {
|
|
55
|
+
const lastMessage = messages[messages.length - 1];
|
|
56
|
+
getMessages(batchSize, channelId, lastMessage)
|
|
57
|
+
.then(fetchedMessages => {
|
|
58
|
+
if (fetchedMessages.length === 0) {
|
|
59
|
+
setAllMessagesLoaded(true);
|
|
60
|
+
} else {
|
|
61
|
+
const _messages = sortBy([...messages, ...fetchedMessages], 'createdAt').reverse()
|
|
62
|
+
setMessages(uniqBy(_messages, 'messageId'));
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
return false
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const minHeightOfMessage = 20;
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (!allMessagesLoaded && (!messages.length || messages.length * minHeightOfMessage < windowHeight())) {
|
|
71
|
+
prependItems();
|
|
72
|
+
}
|
|
73
|
+
}, [channelId, messages]);
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
const [effects] = useState(() => props.effects || ({} as IProps['effects'])!);
|
|
77
|
+
effects.pushMessage = (newMessage: IMessage) => {
|
|
78
|
+
if (
|
|
79
|
+
(messages.length > batchSize && min(messages.map(m => m.createdAt))! > newMessage.createdAt)
|
|
80
|
+
|| messages.find(m => m.messageId === newMessage.messageId)
|
|
81
|
+
) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
let _messages = sortBy([newMessage, ...messages], 'createdAt').reverse();
|
|
85
|
+
setMessages(_messages);
|
|
86
|
+
if (newMessage.userId === me.userId && !newMessage.assistantId) {
|
|
87
|
+
scrollToBottom('instant', 1);
|
|
88
|
+
} else {
|
|
89
|
+
scrollToBottom('smooth');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
const sub = Messages().dataChanged.subscribe(evt => {
|
|
95
|
+
const message: IMessage = evt.dataObject;
|
|
96
|
+
if (message.channelId !== channelId || message.messageParentId) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (evt.op === 'insert') {
|
|
100
|
+
effects.pushMessage(message);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
return () => {
|
|
104
|
+
sub.unsubscribe();
|
|
105
|
+
}
|
|
106
|
+
}, [channelId]);
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<div
|
|
111
|
+
id="scrollableDiv"
|
|
112
|
+
style={{
|
|
113
|
+
height,
|
|
114
|
+
overflow: 'auto',
|
|
115
|
+
display: 'flex',
|
|
116
|
+
flexDirection: 'column-reverse',
|
|
117
|
+
// marginBottom: '70px',
|
|
118
|
+
}}
|
|
119
|
+
>
|
|
120
|
+
<InfiniteScroll
|
|
121
|
+
dataLength={messages.length}
|
|
122
|
+
next={prependItems}
|
|
123
|
+
style={{ display: 'flex', flexDirection: 'column-reverse', overflow: 'hidden' }}
|
|
124
|
+
inverse={true}
|
|
125
|
+
hasMore={!allMessagesLoaded}
|
|
126
|
+
loader={<LoadingIndicator />}
|
|
127
|
+
scrollableTarget="scrollableDiv"
|
|
128
|
+
endMessage={
|
|
129
|
+
<Fragment>
|
|
130
|
+
<div className="d-flex justify-content-center">
|
|
131
|
+
{messages[0] && (
|
|
132
|
+
<div>
|
|
133
|
+
{(new Date(messages[messages.length - 1].createdAt).toLocaleDateString())}
|
|
134
|
+
</div>
|
|
135
|
+
)}
|
|
136
|
+
</div>
|
|
137
|
+
<div className="d-flex justify-content-center">
|
|
138
|
+
<div>
|
|
139
|
+
<i>beginning of messages</i>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
</Fragment>
|
|
143
|
+
}
|
|
144
|
+
>
|
|
145
|
+
{/* <div style={{ marginBottom: '10px' }}></div> */}
|
|
146
|
+
<div ref={messagesEndRef} />
|
|
147
|
+
{messages.map((message, index) => {
|
|
148
|
+
return <MessageDisplay key={message.messageId} message={message} messageAbove={messages[index + 1]} index={index} />
|
|
149
|
+
})}
|
|
150
|
+
</InfiniteScroll>
|
|
151
|
+
</div>
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export async function getMessages(batchSize: number, channelId: string, lastMessage: IMessage | undefined): Promise<IMessage[]> {
|
|
156
|
+
const query: DataFilter<IMessage> = {
|
|
157
|
+
channelId,
|
|
158
|
+
messageParentId: null,
|
|
159
|
+
};
|
|
160
|
+
if (lastMessage) {
|
|
161
|
+
query.messageId = { $lt: lastMessage.messageId };
|
|
162
|
+
}
|
|
163
|
+
const cursor = await Messages().cursor(
|
|
164
|
+
query,
|
|
165
|
+
{
|
|
166
|
+
sortBy: ['-createdAt', '-messageId'],
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const messages: IMessage[] = [];
|
|
170
|
+
for await (const message of cursor) {
|
|
171
|
+
messages.push(message);
|
|
172
|
+
if (messages.length >= batchSize) {
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return messages;
|
|
177
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import React, { useRef, useState } from 'react';
|
|
2
|
+
import { IMessage, Messages } from "@peers-app/peers-sdk";
|
|
3
|
+
import { me, openThread } from '../../globals';
|
|
4
|
+
import { ChannelMessageList } from './channel-message-list';
|
|
5
|
+
import { MessageCompose } from './message-compose';
|
|
6
|
+
import { registerInternalPeersUI } from '../../ui-router/ui-loader';
|
|
7
|
+
|
|
8
|
+
interface IProps {
|
|
9
|
+
channelId?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const ChannelMessages = (props: IProps) => {
|
|
13
|
+
const messagesEndRef = useRef<HTMLDivElement>(null);
|
|
14
|
+
const [effects] = useState<{ pushMessage: (message: IMessage) => any }>(() => ({} as any));
|
|
15
|
+
const [scrolledToBottom, setScrolledToBottom] = useState(true);
|
|
16
|
+
|
|
17
|
+
let channelId = props.channelId;
|
|
18
|
+
// const scrollToBottom = (behavior: 'instant' | 'smooth' = 'instant') => {
|
|
19
|
+
// setTimeout(() => messagesEndRef.current?.scrollIntoView({ behavior }), 500);
|
|
20
|
+
// };
|
|
21
|
+
|
|
22
|
+
const sendMessage = (userMessage: IMessage) => {
|
|
23
|
+
effects.pushMessage(userMessage);
|
|
24
|
+
Messages().save(userMessage).then(message => {
|
|
25
|
+
openThread(message.messageId);
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
channelId = channelId || me.userId;
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div
|
|
33
|
+
className="d-flex flex-column flex-col-reverse"
|
|
34
|
+
style={{
|
|
35
|
+
// height: '100vh',
|
|
36
|
+
height: 'calc(100vh - 50px)',
|
|
37
|
+
// marginTop: '50px',
|
|
38
|
+
}}
|
|
39
|
+
>
|
|
40
|
+
<ChannelMessageList
|
|
41
|
+
batchSize={30}
|
|
42
|
+
channelId={channelId}
|
|
43
|
+
// height="calc(100vh - 50px)"
|
|
44
|
+
height='100vh'
|
|
45
|
+
effects={effects}
|
|
46
|
+
scrollChanged={setScrolledToBottom}
|
|
47
|
+
/>
|
|
48
|
+
<div ref={messagesEndRef} />
|
|
49
|
+
|
|
50
|
+
<div className='p-2 pt-1'
|
|
51
|
+
style={{
|
|
52
|
+
boxShadow: scrolledToBottom ? '' : `0 -10px 11px -10px rgba(0, 0, 0, 0.9)`
|
|
53
|
+
}}
|
|
54
|
+
>
|
|
55
|
+
<MessageCompose
|
|
56
|
+
channelId={channelId}
|
|
57
|
+
onMessageSubmit={sendMessage}
|
|
58
|
+
/>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
registerInternalPeersUI({
|
|
66
|
+
peersUIId: '00m5fsd8d4jma58fgvyr1riny',
|
|
67
|
+
component: ChannelMessages,
|
|
68
|
+
routes: [
|
|
69
|
+
{
|
|
70
|
+
isMatch: (props, context) => context.path === 'threads' || context.path === '',
|
|
71
|
+
uiCategory: 'screen'
|
|
72
|
+
},
|
|
73
|
+
]
|
|
74
|
+
})
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { deviceVar, Observable, observable, Subscription, userVar } from "@peers-app/peers-sdk";
|
|
2
|
+
|
|
3
|
+
import { IFile, IMessage, newid, PersistentVar } from "@peers-app/peers-sdk";
|
|
4
|
+
import React, { useEffect, useState } from 'react';
|
|
5
|
+
import { me } from '../../globals';
|
|
6
|
+
import { useObservable } from "../../hooks";
|
|
7
|
+
import { IEditorEffects, MarkdownEditor } from '../markdown-editor/editor';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const pVarCache: { [key: string]: PersistentVar<string> } = {};
|
|
11
|
+
|
|
12
|
+
export function getContentPersistenceValue(channelId: string, threadId?: string) {
|
|
13
|
+
const contentPersistenceName = `messageCompose-channel-${channelId}${threadId ? '-thread-' + threadId : ''}`;
|
|
14
|
+
if (!pVarCache[contentPersistenceName]) {
|
|
15
|
+
pVarCache[contentPersistenceName] = userVar<string>(contentPersistenceName, { defaultValue: '' });
|
|
16
|
+
}
|
|
17
|
+
return pVarCache[contentPersistenceName];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface IProps {
|
|
21
|
+
channelId: string
|
|
22
|
+
threadId?: string
|
|
23
|
+
onMessageSubmit: (message: IMessage, files?: IFile[]) => any
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const MessageCompose = (props: IProps) => {
|
|
27
|
+
const { channelId, threadId, onMessageSubmit } = props;
|
|
28
|
+
|
|
29
|
+
const [contentObs] = useState(() => observable(''));
|
|
30
|
+
const [mdEffects] = useState<IEditorEffects>(() => ({}));
|
|
31
|
+
const composeBottomRef = React.useRef<HTMLDivElement>(null);
|
|
32
|
+
|
|
33
|
+
function scrollToBottom() {
|
|
34
|
+
if (composeBottomRef?.current) {
|
|
35
|
+
composeBottomRef.current.scrollIntoView({ behavior: 'instant' });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
let disposed = false;
|
|
41
|
+
let sub: Subscription | undefined;
|
|
42
|
+
getContentPersistenceValue(channelId, threadId).loadingPromise.then(pVar => {
|
|
43
|
+
if (!disposed) {
|
|
44
|
+
contentObs(pVar() ?? '');
|
|
45
|
+
sub = contentObs.subscribe(() => pVar(contentObs()));
|
|
46
|
+
setTimeout(() => scrollToBottom(), 100);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return () => {
|
|
50
|
+
disposed = true;
|
|
51
|
+
sub?.dispose();
|
|
52
|
+
}
|
|
53
|
+
}, [channelId, threadId]);
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
const sub = contentObs.subscribe(() => scrollToBottom());
|
|
57
|
+
return () => sub.dispose();
|
|
58
|
+
}, [contentObs]);
|
|
59
|
+
|
|
60
|
+
function submitMessage() {
|
|
61
|
+
const markdown = contentObs() ?? '';
|
|
62
|
+
contentObs('');
|
|
63
|
+
if (!markdown.trim()) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const userMessage: IMessage = {
|
|
67
|
+
messageId: newid(),
|
|
68
|
+
message: markdown,
|
|
69
|
+
userId: me.userId,
|
|
70
|
+
channelId,
|
|
71
|
+
messageParentId: threadId,
|
|
72
|
+
createdAt: new Date(),
|
|
73
|
+
}
|
|
74
|
+
onMessageSubmit(userMessage);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<div className="border rounded border-dark-subtle" style={{ overflowY: 'auto' }}>
|
|
79
|
+
<MarkdownEditor
|
|
80
|
+
value={contentObs}
|
|
81
|
+
effects={mdEffects}
|
|
82
|
+
autoFocus={!!threadId}
|
|
83
|
+
maxHeight={'50vh'}
|
|
84
|
+
/>
|
|
85
|
+
<BottomControls
|
|
86
|
+
submitMessage={submitMessage}
|
|
87
|
+
contentObs={contentObs}
|
|
88
|
+
mdEffects={mdEffects}
|
|
89
|
+
/>
|
|
90
|
+
<div ref={composeBottomRef} />
|
|
91
|
+
</div>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const BottomControls = (props: {
|
|
96
|
+
submitMessage: () => void,
|
|
97
|
+
contentObs: Observable<string>,
|
|
98
|
+
mdEffects: any,
|
|
99
|
+
}) => {
|
|
100
|
+
const { submitMessage, contentObs } = props;
|
|
101
|
+
const [content] = useObservable(contentObs, [contentObs]);
|
|
102
|
+
|
|
103
|
+
const [submitOnEnter] = useState(() => deviceVar<boolean>(`messageCompose-submitOnEnter`, { defaultValue: true }));
|
|
104
|
+
useObservable(submitOnEnter);
|
|
105
|
+
if (isMobile()) {
|
|
106
|
+
submitOnEnter(false);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function onKeyDown(evt: KeyboardEvent) {
|
|
110
|
+
if (evt.code === 'Enter' && !evt.ctrlKey && !evt.shiftKey && !evt.altKey && !evt.metaKey) {
|
|
111
|
+
if (submitOnEnter()) {
|
|
112
|
+
submitMessage();
|
|
113
|
+
evt.preventDefault();
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else if (evt.code === 'Enter' && (evt.ctrlKey || evt.metaKey)) {
|
|
118
|
+
if (!submitOnEnter()) {
|
|
119
|
+
submitMessage();
|
|
120
|
+
evt.preventDefault();
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
props.mdEffects.onKeyDown = onKeyDown;
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<div>
|
|
129
|
+
<div className='float-end small'>
|
|
130
|
+
<span className='small' hidden={isMobile()}>
|
|
131
|
+
<input type="checkbox" id="sendOnEnter" checked={!!submitOnEnter()} onChange={evt => submitOnEnter(evt.target.checked)} /> Send on Enter
|
|
132
|
+
</span>
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
{content.trim()?.length === 0
|
|
136
|
+
? (
|
|
137
|
+
<button className="btn btn-sm btn-outline" type="button" disabled>
|
|
138
|
+
Send
|
|
139
|
+
<i className="bi bi-send-fill"></i>
|
|
140
|
+
</button>
|
|
141
|
+
)
|
|
142
|
+
: (
|
|
143
|
+
<button className="btn btn-sm btn-success" type="button" onClick={props.submitMessage}>
|
|
144
|
+
Send
|
|
145
|
+
<i className="bi bi-send-fill"></i>
|
|
146
|
+
</button>
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function isMobile() {
|
|
155
|
+
if ((navigator as any)?.userAgentData?.mobile) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
let check = false;
|
|
159
|
+
// @ts-ignore
|
|
160
|
+
(function (a) { if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true; })(navigator.userAgent || navigator.vendor || window.opera);
|
|
161
|
+
return check;
|
|
162
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { Avatar } from './avatar';
|
|
3
|
+
// import { FileListDisplay } from './file-list-display';
|
|
4
|
+
import { Assistants, IMessage, IUser, Messages, Observable, observable } from "@peers-app/peers-sdk";
|
|
5
|
+
import moment from 'moment';
|
|
6
|
+
import { openThread, openThreads } from '../../globals';
|
|
7
|
+
import { useObservable, usePromise, useSubscription } from '../../hooks';
|
|
8
|
+
import { MarkdownWithMentions } from '../markdown-with-mentions';
|
|
9
|
+
import { MessageLogs } from '../message-logs/message-logs';
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
interface IProps {
|
|
13
|
+
message: IMessage
|
|
14
|
+
messageAbove?: IMessage
|
|
15
|
+
isThreadParent?: boolean
|
|
16
|
+
index?: number
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const MessageDisplay = (props: IProps) => {
|
|
20
|
+
const { message, messageAbove, isThreadParent } = props;
|
|
21
|
+
|
|
22
|
+
const [messageId, setMessageId] = useState(message.messageId);
|
|
23
|
+
|
|
24
|
+
useSubscription(openThreads, () => {
|
|
25
|
+
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const [user, setUser] = useState<IUser>();
|
|
29
|
+
const [messageChangedTime, setMessageChangedTime] = useState(0);
|
|
30
|
+
const assistant = usePromise(async () => {
|
|
31
|
+
if (message.assistantId) {
|
|
32
|
+
return Assistants().get(message.assistantId);
|
|
33
|
+
}
|
|
34
|
+
}, undefined, [message.assistantId]);
|
|
35
|
+
|
|
36
|
+
const countReplies = usePromise(() => Messages().count({ messageParentId: messageId }), 1, [messageId, messageChangedTime])!;
|
|
37
|
+
|
|
38
|
+
const [showMenu] = useState(() => observable(false));
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
setMessageId(message.messageId);
|
|
42
|
+
const sub = Messages().dataChanged.subscribe((evt) => {
|
|
43
|
+
const changedMessage = evt.dataObject;
|
|
44
|
+
if (changedMessage.messageId === messageId || changedMessage.messageParentId === messageId) {
|
|
45
|
+
setMessageChangedTime(Date.now());
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return () => {
|
|
49
|
+
sub.unsubscribe();
|
|
50
|
+
}
|
|
51
|
+
}, [message]);
|
|
52
|
+
|
|
53
|
+
// calculate short time string
|
|
54
|
+
const messageDate = new Date(message.createdAt)
|
|
55
|
+
let hour: any = messageDate.getHours();
|
|
56
|
+
const minute = messageDate.getMinutes().toString().padStart(2, '0');
|
|
57
|
+
let ampm = "AM";
|
|
58
|
+
if (hour > 11) {
|
|
59
|
+
ampm = "PM";
|
|
60
|
+
}
|
|
61
|
+
if (hour > 12) {
|
|
62
|
+
hour = hour - 12;
|
|
63
|
+
}
|
|
64
|
+
let timeStr = `${hour || 12}:${minute} ${ampm}`
|
|
65
|
+
|
|
66
|
+
const showDateDivider = messageAbove
|
|
67
|
+
&& messageDate.toDateString() !== (new Date(messageAbove.createdAt)).toDateString();
|
|
68
|
+
const showUserInfo = showDateDivider
|
|
69
|
+
|| !messageAbove || !message
|
|
70
|
+
|| messageAbove.userId !== message.userId
|
|
71
|
+
|| messageAbove.assistantId !== message.assistantId
|
|
72
|
+
|| messageDate.getHours() !== (new Date(messageAbove.createdAt)).getHours()
|
|
73
|
+
|| countReplies > 0;
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
// // show time of this message if hour is different than last message
|
|
77
|
+
// const showTime = !showUserInfo
|
|
78
|
+
// && messageDate.getHours() !== (new Date(messageAbove.modified)).getHours();
|
|
79
|
+
|
|
80
|
+
const isThreadView = isThreadParent || message.messageParentId;
|
|
81
|
+
|
|
82
|
+
const dateTimeStr = moment(message.createdAt).calendar().split(' at ')[0] + ' ' + timeStr;
|
|
83
|
+
if (isThreadParent) {
|
|
84
|
+
timeStr = dateTimeStr;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let messageParsed = message.message.trim();
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<div
|
|
91
|
+
className={isThreadParent ? '' : `peers-message-container`}
|
|
92
|
+
onMouseEnter={() => showMenu(true)}
|
|
93
|
+
onMouseLeave={() => showMenu(false)}
|
|
94
|
+
>
|
|
95
|
+
<MessageMenu message={message} showMenu={showMenu} isThreadView={!!isThreadView} />
|
|
96
|
+
|
|
97
|
+
{showDateDivider && (
|
|
98
|
+
<div style={{ marginTop: `20px` }}>
|
|
99
|
+
<hr />
|
|
100
|
+
<div className="d-flex justify-content-center">
|
|
101
|
+
<span
|
|
102
|
+
className='message-display-list-date'
|
|
103
|
+
style={{
|
|
104
|
+
position: 'relative',
|
|
105
|
+
top: '-29px',
|
|
106
|
+
paddingLeft: '11px',
|
|
107
|
+
paddingRight: '11px',
|
|
108
|
+
fontSize: '16px',
|
|
109
|
+
borderRadius: '20px',
|
|
110
|
+
}}
|
|
111
|
+
>
|
|
112
|
+
<strong>
|
|
113
|
+
{
|
|
114
|
+
moment(message.createdAt).calendar().split(' at ')[0].replace('Last', '')
|
|
115
|
+
}
|
|
116
|
+
</strong>
|
|
117
|
+
</span>
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
)}
|
|
121
|
+
|
|
122
|
+
{/* new block so add some padding */}
|
|
123
|
+
{showUserInfo && (
|
|
124
|
+
<div style={{ marginTop: '15px' }}></div>
|
|
125
|
+
)}
|
|
126
|
+
|
|
127
|
+
<div className="d-flex">
|
|
128
|
+
<div className="p-0 flex-shrink-0 justify-content-center align-items-center"
|
|
129
|
+
style={{
|
|
130
|
+
width: '46px',
|
|
131
|
+
height: '20px',
|
|
132
|
+
overflow: 'visible',
|
|
133
|
+
// zIndex: message.modified,
|
|
134
|
+
position: 'relative',
|
|
135
|
+
top: '4px',
|
|
136
|
+
left: '3px',
|
|
137
|
+
}}
|
|
138
|
+
>
|
|
139
|
+
{showUserInfo && <Avatar userId={message.userId} assistantId={message.assistantId} setUser={setUser} />}
|
|
140
|
+
</div>
|
|
141
|
+
<div
|
|
142
|
+
className="p-1 flex-grow-1 justify-content-start text-break"
|
|
143
|
+
style={{
|
|
144
|
+
maxWidth: 'calc(100% - 50px)',
|
|
145
|
+
}}
|
|
146
|
+
>
|
|
147
|
+
|
|
148
|
+
{showUserInfo && (
|
|
149
|
+
<div className="peers-message">
|
|
150
|
+
<span style={{ fontSize: '9pt' }}>
|
|
151
|
+
<b>
|
|
152
|
+
{assistant?.name || message?.assistantId || user?.name || message.userId}
|
|
153
|
+
</b>
|
|
154
|
+
</span>
|
|
155
|
+
{/* TODO show status */}
|
|
156
|
+
<span className="text-muted sub-sup-font-size" style={{ fontSize: '8pt' }} title={dateTimeStr}> {timeStr}</span>
|
|
157
|
+
</div>
|
|
158
|
+
)}
|
|
159
|
+
|
|
160
|
+
{messageParsed.length > 0 && (
|
|
161
|
+
<div className="peers-message">
|
|
162
|
+
<MarkdownWithMentions content={messageParsed} />
|
|
163
|
+
</div>
|
|
164
|
+
)}
|
|
165
|
+
|
|
166
|
+
<MessageLogs key={messageId} messageId={messageId} />
|
|
167
|
+
|
|
168
|
+
{/* replies info and link */}
|
|
169
|
+
{!isThreadView && countReplies > 0 && (
|
|
170
|
+
<div className="d-inline">
|
|
171
|
+
{/* this space prevents the logs and replies indicator from being included when selecting and copying a message text */}
|
|
172
|
+
|
|
173
|
+
<button
|
|
174
|
+
className="btn btn-sm btn-link m-1"
|
|
175
|
+
onClick={() => openThread(message.messageParentId || messageId)}
|
|
176
|
+
tabIndex={props.index}
|
|
177
|
+
>
|
|
178
|
+
{countReplies === 1 ? '1 reply' : countReplies + ' replies'}
|
|
179
|
+
</button>
|
|
180
|
+
</div>
|
|
181
|
+
)}
|
|
182
|
+
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
{message?.fileIds?.length && (
|
|
187
|
+
<div style={{ marginLeft: '46px' }}>
|
|
188
|
+
{/* <FileListDisplay files={message.fileIds} /> */}
|
|
189
|
+
</div>
|
|
190
|
+
) || undefined}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
</div>
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const MessageMenu = (props: { message: IMessage, showMenu: Observable<boolean>, isThreadView: boolean }) => {
|
|
198
|
+
|
|
199
|
+
const { message, isThreadView, showMenu } = props;
|
|
200
|
+
useObservable(showMenu);
|
|
201
|
+
|
|
202
|
+
return (
|
|
203
|
+
<>
|
|
204
|
+
{/* TODO show different menu if it's a thread view */}
|
|
205
|
+
{showMenu() && !isThreadView && (
|
|
206
|
+
<div className="message-hover-menu">
|
|
207
|
+
<button
|
|
208
|
+
className="btn btn-sm btn-link m-1"
|
|
209
|
+
onClick={() => openThread(message.messageParentId || message.messageId)}
|
|
210
|
+
>
|
|
211
|
+
Reply
|
|
212
|
+
</button>
|
|
213
|
+
</div>
|
|
214
|
+
)}
|
|
215
|
+
</>
|
|
216
|
+
)
|
|
217
|
+
}
|