@seamly/web-ui 20.8.1 → 21.0.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/dist/lib/components.js +14855 -20
- package/build/dist/lib/components.min.js +2 -1
- package/build/dist/lib/components.min.js.LICENSE.txt +48 -0
- package/build/dist/lib/config.js +9 -3
- package/build/dist/lib/config.min.js +1 -1
- package/build/dist/lib/contexts.js +14 -5
- package/build/dist/lib/contexts.min.js +1 -1
- package/build/dist/lib/deprecated-view.js +1 -1
- package/build/dist/lib/hooks.js +8446 -20
- package/build/dist/lib/hooks.min.js +2 -1
- package/build/dist/lib/hooks.min.js.LICENSE.txt +38 -0
- package/build/dist/lib/index.debug.js +585 -584
- package/build/dist/lib/index.debug.min.js +1 -1
- package/build/dist/lib/index.debug.min.js.LICENSE.txt +110 -110
- package/build/dist/lib/index.js +20279 -26454
- package/build/dist/lib/index.min.js +1 -1
- package/build/dist/lib/index.min.js.LICENSE.txt +6 -1
- package/build/dist/lib/standalone.js +27823 -34681
- package/build/dist/lib/standalone.min.js +1 -1
- package/build/dist/lib/standalone.min.js.LICENSE.txt +1 -1
- package/build/dist/lib/storage.js +6 -15
- package/build/dist/lib/style-guide.js +23181 -7921
- package/build/dist/lib/style-guide.min.js +1 -1
- package/build/dist/lib/style-guide.min.js.LICENSE.txt +10 -0
- package/build/dist/lib/styles-default-implementation.js +1 -1
- package/build/dist/lib/styles.js +1 -1
- package/build/dist/lib/utils.js +22149 -17
- package/build/dist/lib/utils.min.js +2 -1
- package/build/dist/lib/utils.min.js.LICENSE.txt +48 -0
- package/package.json +54 -52
- package/src/icons/icon_check-16.svg +14 -0
- package/src/icons/icon_check-32.svg +14 -0
- package/src/javascripts/api/conversation-connector.ts +149 -0
- package/src/javascripts/api/errors/seamly-base-error.js +19 -0
- package/src/javascripts/api/errors/seamly-unavailable-error.js +5 -7
- package/src/javascripts/api/{index.js → index.ts} +163 -116
- package/src/javascripts/config.types.ts +5 -4
- package/src/javascripts/domains/app/actions.ts +47 -46
- package/src/javascripts/domains/app/hooks.js +1 -1
- package/src/javascripts/domains/config/actions.ts +2 -8
- package/src/javascripts/domains/config/hooks.ts +1 -1
- package/src/javascripts/domains/config/selectors.ts +6 -6
- package/src/javascripts/domains/config/slice.ts +3 -3
- package/src/javascripts/domains/errors/index.ts +66 -0
- package/src/javascripts/domains/forms/context.ts +1 -1
- package/src/javascripts/domains/forms/forms.types.ts +3 -3
- package/src/javascripts/domains/forms/hooks.ts +10 -10
- package/src/javascripts/domains/forms/provider.tsx +9 -9
- package/src/javascripts/domains/i18n/actions.ts +11 -5
- package/src/javascripts/domains/i18n/hooks.ts +11 -8
- package/src/javascripts/domains/i18n/selectors.ts +10 -4
- package/src/javascripts/domains/i18n/slice.ts +0 -1
- package/src/javascripts/domains/interrupt/hooks.ts +1 -1
- package/src/javascripts/domains/interrupt/middleware.ts +1 -1
- package/src/javascripts/domains/store/index.ts +1 -1
- package/src/javascripts/domains/store/selectors.ts +16 -0
- package/src/javascripts/domains/store/slice.ts +47 -41
- package/src/javascripts/domains/store/store.types.ts +38 -10
- package/src/javascripts/domains/translations/components/{options-button.js → options-button.tsx} +30 -20
- package/src/javascripts/domains/translations/components/options-dialog/index.tsx +33 -0
- package/src/javascripts/domains/translations/components/options-dialog/translation-option.tsx +42 -0
- package/src/javascripts/domains/translations/components/options-dialog/translation-options.tsx +81 -0
- package/src/javascripts/domains/translations/components/translation-status.tsx +15 -0
- package/src/javascripts/domains/translations/hooks.ts +77 -11
- package/src/javascripts/domains/translations/slice.ts +20 -9
- package/src/javascripts/domains/translations/translations.types.ts +4 -2
- package/src/javascripts/domains/visibility/actions.ts +6 -10
- package/src/javascripts/domains/visibility/hooks.ts +33 -14
- package/src/javascripts/domains/visibility/selectors.ts +3 -2
- package/src/javascripts/domains/visibility/slice.ts +2 -6
- package/src/javascripts/index.ts +18 -22
- package/src/javascripts/lib/engine/{index.js → index.tsx} +25 -7
- package/src/javascripts/lib/url-helpers.ts +112 -0
- package/src/javascripts/package/components.js +15 -1
- package/src/javascripts/package/config.js +1 -1
- package/src/javascripts/package/contexts.js +5 -3
- package/src/javascripts/package/hooks.js +19 -1
- package/src/javascripts/package/utils.js +13 -3
- package/src/javascripts/schema.ts +28 -0
- package/src/javascripts/style-guide/components/app.js +16 -12
- package/src/javascripts/style-guide/components/links.js +6 -6
- package/src/javascripts/style-guide/components/static-core.js +14 -9
- package/src/javascripts/style-guide/components/view.js +2 -2
- package/src/javascripts/style-guide/states.js +132 -36
- package/src/javascripts/style-guide/style-guide-engine.js +2 -1
- package/src/javascripts/style-guide/style-guide-external-api.js +1 -1
- package/src/javascripts/ui/components/app-options/index.js +25 -6
- package/src/javascripts/ui/components/chat-app.js +1 -1
- package/src/javascripts/ui/components/chat-status/chat-status-action.tsx +30 -0
- package/src/javascripts/ui/components/chat-status/index.tsx +61 -0
- package/src/javascripts/ui/components/conversation/component-filter.js +9 -9
- package/src/javascripts/ui/components/conversation/{conversation.js → conversation.tsx} +32 -41
- package/src/javascripts/ui/components/conversation/event/card-component.js +2 -2
- package/src/javascripts/ui/components/conversation/event/card-message.js +1 -1
- package/src/javascripts/ui/components/conversation/event/carousel-component/components/controls.js +2 -2
- package/src/javascripts/ui/components/conversation/event/carousel-component/index.js +4 -4
- package/src/javascripts/ui/components/conversation/event/carousel-message/components/slide.js +2 -2
- package/src/javascripts/ui/components/conversation/event/carousel-message/index.js +1 -1
- package/src/javascripts/ui/components/conversation/event/chat-scroll/chat-scroll-context.ts +12 -0
- package/src/javascripts/ui/components/conversation/event/chat-scroll/chat-scroll-provider.tsx +46 -0
- package/src/javascripts/ui/components/conversation/event/chat-scroll/unread-messages-button.tsx +30 -0
- package/src/javascripts/ui/components/conversation/event/choice-prompt.js +12 -8
- package/src/javascripts/ui/components/conversation/event/conversation-suggestions.js +6 -6
- package/src/javascripts/ui/components/conversation/event/cta.js +2 -2
- package/src/javascripts/ui/components/conversation/event/divider/index.js +0 -1
- package/src/javascripts/ui/components/conversation/event/divider/variants/default.js +1 -1
- package/src/javascripts/ui/components/conversation/event/divider/variants/new-translation.js +17 -22
- package/src/javascripts/ui/components/conversation/event/divider/variants/time-indicator.js +2 -2
- package/src/javascripts/ui/components/conversation/event/event-participant.js +1 -1
- package/src/javascripts/ui/components/conversation/event/event.tsx +66 -0
- package/src/javascripts/ui/components/conversation/event/hooks/use-event-link-click-handler.js +1 -1
- package/src/javascripts/ui/components/conversation/event/hooks/use-formatted-date.js +1 -1
- package/src/javascripts/ui/components/conversation/event/image-lightbox.js +1 -1
- package/src/javascripts/ui/components/conversation/event/image.js +2 -2
- package/src/javascripts/ui/components/conversation/event/splash.js +1 -1
- package/src/javascripts/ui/components/conversation/event/translation.js +1 -1
- package/src/javascripts/ui/components/conversation/event/upload.js +2 -2
- package/src/javascripts/ui/components/conversation/event/video.js +2 -2
- package/src/javascripts/ui/components/conversation/event-divider.js +1 -1
- package/src/javascripts/ui/components/conversation/message-container.js +1 -1
- package/src/javascripts/ui/components/conversation/use-chat-scroll.ts +108 -0
- package/src/javascripts/ui/components/core/{seamly-activity-monitor.js → seamly-activity-monitor.tsx} +12 -5
- package/src/javascripts/ui/components/core/seamly-api-context.ts +7 -0
- package/src/javascripts/ui/components/core/seamly-chat.tsx +8 -0
- package/src/javascripts/ui/components/core/{seamly-core.js → seamly-core.tsx} +27 -14
- package/src/javascripts/ui/components/core/seamly-event-subscriber.ts +340 -0
- package/src/javascripts/ui/components/core/seamly-file-upload.js +2 -2
- package/src/javascripts/ui/components/core/seamly-idle-detach-counter.js +1 -1
- package/src/javascripts/ui/components/core/seamly-instance-functions-loader.js +24 -11
- package/src/javascripts/ui/components/core/seamly-live-region.js +4 -4
- package/src/javascripts/ui/components/core/seamly-new-notifications.js +3 -3
- package/src/javascripts/ui/components/core/seamly-read-state.js +2 -33
- package/src/javascripts/ui/components/entry/deprecated-toggle-button.js +4 -4
- package/src/javascripts/ui/components/entry/entry-container.js +8 -8
- package/src/javascripts/ui/components/entry/text-entry/hooks.js +3 -3
- package/src/javascripts/ui/components/entry/text-entry/index.js +3 -3
- package/src/javascripts/ui/components/entry/text-entry/text-entry-form.js +4 -4
- package/src/javascripts/ui/components/entry/upload/file-upload-form.js +3 -3
- package/src/javascripts/ui/components/entry/upload/index.js +5 -5
- package/src/javascripts/ui/components/entry/upload-toggle.js +6 -6
- package/src/javascripts/ui/components/faq/faq.js +14 -14
- package/src/javascripts/ui/components/form-controls/error.js +2 -2
- package/src/javascripts/ui/components/form-controls/file-input.js +3 -3
- package/src/javascripts/ui/components/layout/agent-info.js +3 -3
- package/src/javascripts/ui/components/layout/chat-frame.js +20 -12
- package/src/javascripts/ui/components/layout/chat.js +5 -5
- package/src/javascripts/ui/components/layout/deprecated-app-frame.js +6 -6
- package/src/javascripts/ui/components/layout/deprecated-chat-frame.js +34 -0
- package/src/javascripts/ui/components/layout/header.js +2 -2
- package/src/javascripts/ui/components/layout/icon.js +11 -9
- package/src/javascripts/ui/components/layout/interrupt.js +7 -5
- package/src/javascripts/ui/components/layout/pre-chat-messages.js +1 -1
- package/src/javascripts/ui/components/layout/privacy-disclaimer.js +2 -2
- package/src/javascripts/ui/components/options/options-button.js +5 -5
- package/src/javascripts/ui/components/options/{options-frame.js → options-frame.tsx} +52 -18
- package/src/javascripts/ui/components/options/transcript/index.js +9 -10
- package/src/javascripts/ui/components/options/transcript/transcript-form.js +2 -2
- package/src/javascripts/ui/components/suggestions/index.js +8 -8
- package/src/javascripts/ui/components/suggestions/suggestions-item.js +1 -1
- package/src/javascripts/{domains/translations/components/chat-status.js → ui/components/translation-chat-status/index.tsx} +13 -14
- package/src/javascripts/ui/components/translation-proposal/index.tsx +36 -0
- package/src/javascripts/ui/components/view/app-view.js +2 -7
- package/src/javascripts/ui/components/view/deprecated-view.js +8 -10
- package/src/javascripts/ui/components/view/index.js +6 -6
- package/src/javascripts/ui/components/view/inline-view.js +4 -8
- package/src/javascripts/ui/components/view/window-view/collapse-button.js +2 -2
- package/src/javascripts/ui/components/view/window-view/index.js +11 -17
- package/src/javascripts/ui/components/view/window-view/window-open-button.js +6 -6
- package/src/javascripts/ui/components/warnings/idle-detach-warning.js +3 -3
- package/src/javascripts/ui/components/warnings/prompt.js +1 -1
- package/src/javascripts/ui/components/warnings/resume-conversation-prompt.js +4 -4
- package/src/javascripts/ui/components/widgets/in-out-transition.js +20 -18
- package/src/javascripts/ui/components/widgets/lightbox.js +3 -3
- package/src/javascripts/ui/components/widgets/modal.js +2 -2
- package/src/javascripts/ui/components/widgets/upload-progress.js +2 -2
- package/src/javascripts/ui/hooks/file-upload-hooks.js +1 -1
- package/src/javascripts/ui/hooks/focus-helper-hooks.js +1 -1
- package/src/javascripts/ui/hooks/seamly-entry-hooks.js +6 -6
- package/src/javascripts/ui/hooks/seamly-hooks.js +11 -10
- package/src/javascripts/ui/hooks/seamly-option-hooks.js +6 -6
- package/src/javascripts/ui/hooks/{seamly-state-hooks.js → seamly-state-hooks.ts} +9 -6
- package/src/javascripts/ui/hooks/use-click-outside.ts +29 -0
- package/src/javascripts/ui/hooks/use-event-component-mapping.js +11 -10
- package/src/javascripts/ui/hooks/use-interval.js +1 -1
- package/src/javascripts/ui/hooks/use-seamly-actions.ts +29 -29
- package/src/javascripts/ui/hooks/use-seamly-chat.js +14 -24
- package/src/javascripts/ui/hooks/use-seamly-commands.js +20 -15
- package/src/javascripts/ui/hooks/use-seamly-idle-detach-countdown.js +8 -8
- package/src/javascripts/ui/hooks/use-seamly-resume-conversation-prompt.js +2 -2
- package/src/javascripts/ui/hooks/use-single-file-upload.js +1 -1
- package/src/javascripts/ui/hooks/utility-hooks.js +1 -1
- package/src/javascripts/ui/utils/general-utils.js +0 -23
- package/src/javascripts/ui/utils/seamly-utils.ts +10 -1
- package/src/javascripts/ui/utils/seamly-utils.types.ts +9 -0
- package/src/stylesheets/1-settings/_config.scss +1 -1
- package/src/stylesheets/3-chat/_chat.scss +24 -9
- package/src/stylesheets/5-components/_chat-status.scss +72 -16
- package/src/stylesheets/5-components/_conversation.scss +35 -1
- package/src/stylesheets/5-components/_disclaimer.scss +0 -5
- package/src/stylesheets/5-components/_options.scss +16 -6
- package/src/stylesheets/5-components/_translation-options.scss +51 -0
- package/src/stylesheets/6-default-implementation/_scrollbar.scss +1 -1
- package/src/stylesheets/7-deprecated/3-app/_app.scss +19 -4
- package/src/stylesheets/7-deprecated/5-components/_chat-status.scss +5 -0
- package/src/stylesheets/7-deprecated/5-components/_options.scss +1 -4
- package/src/stylesheets/7-deprecated/5-components/_translation-options.scss +49 -0
- package/src/stylesheets/deprecated-view.scss +1 -0
- package/src/stylesheets/styles.scss +1 -0
- package/webpack/config.common.js +4 -4
- package/webpack/config.package.js +10 -16
- package/webpack/config.site.js +4 -1
- package/webpack/config.test.js +2 -1
- package/build/dist/lib/deprecated-view.css +0 -1
- package/build/dist/lib/styles-default-implementation.css +0 -1
- package/build/dist/lib/styles.css +0 -1
- package/src/.DS_Store +0 -0
- package/src/javascripts/api/event-producer.js +0 -20
- package/src/javascripts/api/producer.js +0 -136
- package/src/javascripts/domains/errors/index.js +0 -37
- package/src/javascripts/domains/translations/components/options-dialog/form.js +0 -70
- package/src/javascripts/domains/translations/components/options-dialog/index.js +0 -87
- package/src/javascripts/ui/components/chat-status/index.js +0 -38
- package/src/javascripts/ui/components/conversation/event/event.js +0 -36
- package/src/javascripts/ui/components/core/seamly-api-context.js +0 -5
- package/src/javascripts/ui/components/core/seamly-event-subscriber.js +0 -279
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
visibilityStates,
|
|
6
|
-
} from '@seamly/web-ui'
|
|
1
|
+
import SeamlyGeneralError from 'api/errors/seamly-general-error'
|
|
2
|
+
import SeamlyOfflineError from 'api/errors/seamly-offline-error'
|
|
3
|
+
import { visibilityStates } from 'domains/visibility/constants'
|
|
4
|
+
import { randomId } from 'lib/id'
|
|
7
5
|
import { addTranslationData } from './state-helpers'
|
|
8
6
|
|
|
9
7
|
const baseState = {
|
|
@@ -107,8 +105,10 @@ const newTranslationDividerStart = {
|
|
|
107
105
|
payload: {
|
|
108
106
|
body: {
|
|
109
107
|
language: 'Nederlands',
|
|
108
|
+
restartButtonText: null,
|
|
110
109
|
subtype: 'new_translation',
|
|
111
110
|
text: '[NL] Automatic translation to Dutch started. Please note that automatic translations may contain errors.',
|
|
111
|
+
title: '[NL] Translating to Dutch',
|
|
112
112
|
translationEnabled: true,
|
|
113
113
|
translationLocale: 'nl',
|
|
114
114
|
},
|
|
@@ -158,8 +158,10 @@ const newTranslationDividerStop = {
|
|
|
158
158
|
payload: {
|
|
159
159
|
body: {
|
|
160
160
|
language: 'Nederlands',
|
|
161
|
+
restartButtonText: '[NL] Start again',
|
|
161
162
|
subtype: 'new_translation',
|
|
162
|
-
text:
|
|
163
|
+
text: null,
|
|
164
|
+
title: '[NL] Automatic translation to Dutch ended',
|
|
163
165
|
translationEnabled: false,
|
|
164
166
|
translationLocale: 'nl',
|
|
165
167
|
},
|
|
@@ -762,6 +764,7 @@ const translationsSlice = {
|
|
|
762
764
|
isActive: false,
|
|
763
765
|
currentLocale: undefined,
|
|
764
766
|
isAvailable: false,
|
|
767
|
+
showTranslationProposal: false,
|
|
765
768
|
languages: [],
|
|
766
769
|
translatedEventGroups: {},
|
|
767
770
|
containerId: randomId(),
|
|
@@ -1720,6 +1723,30 @@ const standardState = {
|
|
|
1720
1723
|
languages: [
|
|
1721
1724
|
{ locale: 'nl', nativeName: 'Dutch' },
|
|
1722
1725
|
{ locale: 'en', nativeName: 'English' },
|
|
1726
|
+
{ locale: 'ar', nativeName: 'Arabic' },
|
|
1727
|
+
{ locale: 'bg', nativeName: 'Bulgarian' },
|
|
1728
|
+
{ locale: 'zh', nativeName: 'Chinese' },
|
|
1729
|
+
{ locale: 'cs', nativeName: 'Czech' },
|
|
1730
|
+
{ locale: 'da', nativeName: 'Danish' },
|
|
1731
|
+
{ locale: 'et', nativeName: 'Estonian' },
|
|
1732
|
+
{ locale: 'fi', nativeName: 'Finnish' },
|
|
1733
|
+
{ locale: 'fr', nativeName: 'French' },
|
|
1734
|
+
{ locale: 'de-informal', nativeName: 'German' },
|
|
1735
|
+
{ locale: 'el', nativeName: 'Greek' },
|
|
1736
|
+
{ locale: 'hu', nativeName: 'Hungarian' },
|
|
1737
|
+
{ locale: 'it', nativeName: 'Italian' },
|
|
1738
|
+
{ locale: 'ja', nativeName: 'Japanese' },
|
|
1739
|
+
{ locale: 'lv', nativeName: 'Latvian' },
|
|
1740
|
+
{ locale: 'pl', nativeName: 'Polish' },
|
|
1741
|
+
{ locale: 'ro', nativeName: 'Romanian' },
|
|
1742
|
+
{ locale: 'ru', nativeName: 'Russian' },
|
|
1743
|
+
{ locale: 'sk', nativeName: 'Slovak' },
|
|
1744
|
+
{ locale: 'sl', nativeName: 'Slovenian' },
|
|
1745
|
+
{ locale: 'es-informal', nativeName: 'Spanish' },
|
|
1746
|
+
{ locale: 'sv', nativeName: 'Swedish' },
|
|
1747
|
+
{ locale: 'ti', nativeName: 'Tigrinya' },
|
|
1748
|
+
{ locale: 'tr', nativeName: 'Turkish' },
|
|
1749
|
+
{ locale: 'uk', nativeName: 'Ukrainian' },
|
|
1723
1750
|
],
|
|
1724
1751
|
},
|
|
1725
1752
|
},
|
|
@@ -1823,6 +1850,63 @@ const standardState = {
|
|
|
1823
1850
|
],
|
|
1824
1851
|
},
|
|
1825
1852
|
},
|
|
1853
|
+
translationProposal: {
|
|
1854
|
+
category: categoryKeys.translations,
|
|
1855
|
+
headingText: 'Show translation proposal',
|
|
1856
|
+
description: '',
|
|
1857
|
+
...baseState,
|
|
1858
|
+
events: [shortTextMessage, userMessage, userMessageLong],
|
|
1859
|
+
config: {
|
|
1860
|
+
...baseState.config,
|
|
1861
|
+
showDisclaimer: true,
|
|
1862
|
+
context: {
|
|
1863
|
+
locale: 'nl-informal',
|
|
1864
|
+
},
|
|
1865
|
+
},
|
|
1866
|
+
translations: {
|
|
1867
|
+
...translationsSlice,
|
|
1868
|
+
translationProposal: {
|
|
1869
|
+
buttonLabel: 'Activate',
|
|
1870
|
+
proposedLocale: 'en-GB',
|
|
1871
|
+
srDismissButtonText: 'Dismiss translation proposal',
|
|
1872
|
+
titleLabel: 'Do you want to chat in English?',
|
|
1873
|
+
},
|
|
1874
|
+
isAvailable: true,
|
|
1875
|
+
isActive: false,
|
|
1876
|
+
languages: [
|
|
1877
|
+
{ locale: 'nl-informal', nativeName: 'Dutch' },
|
|
1878
|
+
{ locale: 'en-GB', nativeName: 'English' },
|
|
1879
|
+
],
|
|
1880
|
+
},
|
|
1881
|
+
},
|
|
1882
|
+
translationProposalWithoutTitle: {
|
|
1883
|
+
category: categoryKeys.translations,
|
|
1884
|
+
headingText: 'Show translation proposal without title',
|
|
1885
|
+
description: '',
|
|
1886
|
+
...baseState,
|
|
1887
|
+
events: [shortTextMessage, userMessage, userMessageLong],
|
|
1888
|
+
config: {
|
|
1889
|
+
...baseState.config,
|
|
1890
|
+
showDisclaimer: true,
|
|
1891
|
+
context: {
|
|
1892
|
+
locale: 'nl-informal',
|
|
1893
|
+
},
|
|
1894
|
+
},
|
|
1895
|
+
translations: {
|
|
1896
|
+
...translationsSlice,
|
|
1897
|
+
translationProposal: {
|
|
1898
|
+
buttonLabel: 'Activate',
|
|
1899
|
+
proposedLocale: 'en-GB',
|
|
1900
|
+
srDismissButtonText: 'Dismiss translation proposal',
|
|
1901
|
+
},
|
|
1902
|
+
isAvailable: true,
|
|
1903
|
+
isActive: false,
|
|
1904
|
+
languages: [
|
|
1905
|
+
{ locale: 'nl-informal', nativeName: 'Dutch' },
|
|
1906
|
+
{ locale: 'en-GB', nativeName: 'English' },
|
|
1907
|
+
],
|
|
1908
|
+
},
|
|
1909
|
+
},
|
|
1826
1910
|
}
|
|
1827
1911
|
|
|
1828
1912
|
const inlineInterface = {
|
|
@@ -1955,7 +2039,10 @@ const standardWindowStates = {
|
|
|
1955
2039
|
description: '',
|
|
1956
2040
|
window: {
|
|
1957
2041
|
...baseState,
|
|
1958
|
-
config: {
|
|
2042
|
+
config: {
|
|
2043
|
+
...baseState.config,
|
|
2044
|
+
layoutMode: 'window',
|
|
2045
|
+
},
|
|
1959
2046
|
visibility: {
|
|
1960
2047
|
...baseState.visibility,
|
|
1961
2048
|
visibility: visibilityStates.minimized,
|
|
@@ -1968,7 +2055,10 @@ const standardWindowStates = {
|
|
|
1968
2055
|
description: '',
|
|
1969
2056
|
window: {
|
|
1970
2057
|
...baseState,
|
|
1971
|
-
config: {
|
|
2058
|
+
config: {
|
|
2059
|
+
...baseState.config,
|
|
2060
|
+
layoutMode: 'window',
|
|
2061
|
+
},
|
|
1972
2062
|
visibility: {
|
|
1973
2063
|
...baseState.visibility,
|
|
1974
2064
|
visibility: visibilityStates.minimized,
|
|
@@ -2048,6 +2138,7 @@ const buildStandardState = (
|
|
|
2048
2138
|
return Object.keys(intermediateState).reduce((acc, key) => {
|
|
2049
2139
|
const { headingText, category, description, ...rest } =
|
|
2050
2140
|
intermediateState[key]
|
|
2141
|
+
|
|
2051
2142
|
return {
|
|
2052
2143
|
...acc,
|
|
2053
2144
|
[key]: {
|
|
@@ -2057,7 +2148,10 @@ const buildStandardState = (
|
|
|
2057
2148
|
...layoutModes.reduce(
|
|
2058
2149
|
(comb, layoutMode) => ({
|
|
2059
2150
|
...comb,
|
|
2060
|
-
[layoutMode]: {
|
|
2151
|
+
[layoutMode]: {
|
|
2152
|
+
...rest,
|
|
2153
|
+
config: { ...rest.config, layoutMode },
|
|
2154
|
+
},
|
|
2061
2155
|
}),
|
|
2062
2156
|
{},
|
|
2063
2157
|
),
|
|
@@ -2074,31 +2168,33 @@ export const getDeprecatedStateObj = (
|
|
|
2074
2168
|
...(layoutModes.indexOf('window') !== -1 ? standardWindowStates : {}),
|
|
2075
2169
|
})
|
|
2076
2170
|
|
|
2077
|
-
export const getStateObj = (layoutModes, customComponentEventBodies) =>
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2171
|
+
export const getStateObj = (layoutModes, customComponentEventBodies) => {
|
|
2172
|
+
return {
|
|
2173
|
+
...buildStandardState(layoutModes, customComponentEventBodies, true),
|
|
2174
|
+
...(layoutModes.indexOf('window') !== -1
|
|
2175
|
+
? {
|
|
2176
|
+
...standardWindowStates,
|
|
2177
|
+
minimizedWindowPrechat: {
|
|
2178
|
+
category: categoryKeys.minimizedWindow,
|
|
2179
|
+
headingText: 'Minimized with pre-chat messages',
|
|
2180
|
+
description: '',
|
|
2181
|
+
window: {
|
|
2182
|
+
...baseState,
|
|
2183
|
+
config: {
|
|
2184
|
+
...baseState.config,
|
|
2185
|
+
layoutMode: 'window',
|
|
2186
|
+
preChatEvents: [splashMessage],
|
|
2187
|
+
},
|
|
2188
|
+
visibility: {
|
|
2189
|
+
...baseState.visibility,
|
|
2190
|
+
visibility: visibilityStates.minimized,
|
|
2191
|
+
},
|
|
2192
|
+
participantInfo,
|
|
2193
|
+
headerTitles,
|
|
2096
2194
|
},
|
|
2097
|
-
participantInfo,
|
|
2098
|
-
headerTitles,
|
|
2099
2195
|
},
|
|
2100
|
-
}
|
|
2101
|
-
}
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
}
|
|
2196
|
+
}
|
|
2197
|
+
: {}),
|
|
2198
|
+
...inlineInterface,
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
@@ -1,19 +1,35 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { className } from 'lib/css'
|
|
1
|
+
import Icon from 'ui/components/layout/icon'
|
|
3
2
|
import OptionsButton from 'ui/components/options/options-button'
|
|
4
|
-
import {
|
|
3
|
+
import { useSeamlyOptions } from 'ui/hooks/seamly-hooks'
|
|
4
|
+
import { useI18n } from 'domains/i18n/hooks'
|
|
5
|
+
import { useInterrupt } from 'domains/interrupt/hooks'
|
|
5
6
|
import TranslationsOptionsButton from 'domains/translations/components/options-button'
|
|
7
|
+
import {
|
|
8
|
+
useLocaleNativeName,
|
|
9
|
+
useTranslations,
|
|
10
|
+
} from 'domains/translations/hooks'
|
|
11
|
+
import { className } from 'lib/css'
|
|
6
12
|
|
|
7
13
|
export default function AppOptions() {
|
|
8
14
|
const { menuOptions, allowOptionSelection } = useSeamlyOptions()
|
|
9
15
|
const { isAvailable: isTranslationsAvailable } = useTranslations()
|
|
16
|
+
const { hasInterrupt } = useInterrupt()
|
|
17
|
+
const { t, locale } = useI18n()
|
|
18
|
+
const localeNativeName = useLocaleNativeName(locale)
|
|
19
|
+
|
|
10
20
|
if (
|
|
11
|
-
!isTranslationsAvailable &&
|
|
12
|
-
|
|
21
|
+
(!isTranslationsAvailable &&
|
|
22
|
+
(!allowOptionSelection || !menuOptions.length)) ||
|
|
23
|
+
hasInterrupt
|
|
13
24
|
) {
|
|
14
25
|
return null
|
|
15
26
|
}
|
|
16
27
|
|
|
28
|
+
const openButtonText = t('translations.settings.openButtonText', {
|
|
29
|
+
hasLanguage: !!localeNativeName,
|
|
30
|
+
language: localeNativeName,
|
|
31
|
+
})
|
|
32
|
+
|
|
17
33
|
return (
|
|
18
34
|
<div className={className('chat__options')}>
|
|
19
35
|
{isTranslationsAvailable && (
|
|
@@ -23,7 +39,10 @@ export default function AppOptions() {
|
|
|
23
39
|
'chat__options-item--left',
|
|
24
40
|
)}
|
|
25
41
|
>
|
|
26
|
-
<TranslationsOptionsButton
|
|
42
|
+
<TranslationsOptionsButton classNames={['button--secondary']}>
|
|
43
|
+
<Icon alt={openButtonText} name="newTranslation" size="16" />
|
|
44
|
+
<span className={className('button__text')}>{openButtonText}</span>
|
|
45
|
+
</TranslationsOptionsButton>
|
|
27
46
|
</div>
|
|
28
47
|
)}
|
|
29
48
|
{allowOptionSelection && (
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import Icon from 'ui/components/layout/icon'
|
|
2
|
+
import { className } from 'lib/css'
|
|
3
|
+
|
|
4
|
+
type ChatStatusActionProps = {
|
|
5
|
+
handleClick: () => void
|
|
6
|
+
icon: string
|
|
7
|
+
title: string
|
|
8
|
+
srButtonText?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const ChatStatusAction = ({
|
|
12
|
+
handleClick,
|
|
13
|
+
icon,
|
|
14
|
+
title,
|
|
15
|
+
srButtonText,
|
|
16
|
+
}: ChatStatusActionProps) => (
|
|
17
|
+
<button
|
|
18
|
+
type="button"
|
|
19
|
+
onClick={handleClick}
|
|
20
|
+
className={className('button', 'button--primary', 'chat-status__button')}
|
|
21
|
+
>
|
|
22
|
+
<Icon name={icon} size="16" alt="" />
|
|
23
|
+
{title}
|
|
24
|
+
{srButtonText && (
|
|
25
|
+
<span className={className('visually-hidden')}>{srButtonText}</span>
|
|
26
|
+
)}
|
|
27
|
+
</button>
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
export default ChatStatusAction
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { FC } from 'preact/compat'
|
|
2
|
+
import Icon from 'ui/components/layout/icon'
|
|
3
|
+
import { useGeneratedId } from 'ui/hooks/utility-hooks'
|
|
4
|
+
import { className } from 'lib/css'
|
|
5
|
+
|
|
6
|
+
type ChatStatusProps = {
|
|
7
|
+
handleClose: () => void
|
|
8
|
+
title: string
|
|
9
|
+
closeButtonText?: string
|
|
10
|
+
srCloseButtonText?: string
|
|
11
|
+
id: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const ChatStatus: FC<ChatStatusProps> = ({
|
|
15
|
+
children,
|
|
16
|
+
handleClose,
|
|
17
|
+
title,
|
|
18
|
+
closeButtonText,
|
|
19
|
+
srCloseButtonText,
|
|
20
|
+
id,
|
|
21
|
+
}) => {
|
|
22
|
+
const headingId = useGeneratedId()
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<section
|
|
26
|
+
tabIndex={-1}
|
|
27
|
+
id={id}
|
|
28
|
+
aria-labelledby={title ? headingId : undefined}
|
|
29
|
+
className={className('chat-status', !title && 'chat-status--condensed')}
|
|
30
|
+
>
|
|
31
|
+
<div className={className('chat-status__body')}>
|
|
32
|
+
{title ? (
|
|
33
|
+
<h2 className={className('chat-status__title')} id={headingId}>
|
|
34
|
+
{title}
|
|
35
|
+
</h2>
|
|
36
|
+
) : null}
|
|
37
|
+
{children}
|
|
38
|
+
</div>
|
|
39
|
+
{typeof handleClose === 'function' && (
|
|
40
|
+
<button
|
|
41
|
+
type="button"
|
|
42
|
+
onClick={handleClose}
|
|
43
|
+
className={className(
|
|
44
|
+
'button',
|
|
45
|
+
'button--tertiary',
|
|
46
|
+
'chat-status__close',
|
|
47
|
+
)}
|
|
48
|
+
>
|
|
49
|
+
{closeButtonText || <Icon name="close" size="16" alt="" />}
|
|
50
|
+
{srCloseButtonText && (
|
|
51
|
+
<span className={className('visually-hidden')}>
|
|
52
|
+
{srCloseButtonText}
|
|
53
|
+
</span>
|
|
54
|
+
)}
|
|
55
|
+
</button>
|
|
56
|
+
)}
|
|
57
|
+
</section>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default ChatStatus
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { useMemo } from 'preact/hooks'
|
|
2
2
|
import { useConfig } from 'domains/config/hooks'
|
|
3
3
|
import ComponentContext from './component-context'
|
|
4
|
+
import CardMessage from './event/card-message'
|
|
5
|
+
import CarouselMessage from './event/carousel-message'
|
|
4
6
|
import ChoicePrompt from './event/choice-prompt'
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import Video from './event/video'
|
|
7
|
+
import ConversationSuggestions from './event/conversation-suggestions'
|
|
8
|
+
import Cta from './event/cta'
|
|
8
9
|
import Divider from './event/divider'
|
|
9
|
-
import
|
|
10
|
+
import TimeIndicator from './event/divider/variants/time-indicator'
|
|
11
|
+
import Image from './event/image'
|
|
10
12
|
import Participant from './event/participant'
|
|
11
13
|
import Splash from './event/splash'
|
|
14
|
+
import Text from './event/text'
|
|
15
|
+
import Translation from './event/translation'
|
|
12
16
|
import Upload from './event/upload'
|
|
13
|
-
import
|
|
14
|
-
import TimeIndicator from './event/divider/variants/time-indicator'
|
|
15
|
-
import CarouselMessage from './event/carousel-message'
|
|
16
|
-
import CardMessage from './event/card-message'
|
|
17
|
-
import ConversationSuggestions from './event/conversation-suggestions'
|
|
17
|
+
import Video from './event/video'
|
|
18
18
|
|
|
19
19
|
const eventTypeMapping = {
|
|
20
20
|
message: {
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import { useI18n } from 'domains/i18n/hooks'
|
|
2
|
-
import { useVisibility } from 'domains/visibility/hooks'
|
|
3
|
-
import { className } from 'lib/css'
|
|
4
|
-
import { useLayoutEffect, useRef } from 'preact/hooks'
|
|
5
1
|
import PrivacyDisclaimer from 'ui/components/layout/privacy-disclaimer'
|
|
6
|
-
import { timeout } from 'ui/hooks/focus-helper-hooks'
|
|
7
2
|
import {
|
|
8
3
|
useSeamlyIsLoading,
|
|
9
4
|
useSkiplink,
|
|
10
5
|
useSkiplinkTargetFocusing,
|
|
11
6
|
} from 'ui/hooks/seamly-hooks'
|
|
12
|
-
import { useEvents
|
|
7
|
+
import { useEvents } from 'ui/hooks/seamly-state-hooks'
|
|
8
|
+
import { useI18n } from 'domains/i18n/hooks'
|
|
9
|
+
import { useVisibility } from 'domains/visibility/hooks'
|
|
10
|
+
import { className } from 'lib/css'
|
|
13
11
|
import ComponentFilter from './component-filter'
|
|
14
12
|
import Event from './event/event'
|
|
15
13
|
import Loader from './loader'
|
|
@@ -18,49 +16,41 @@ const Events = () => {
|
|
|
18
16
|
const events = useEvents()
|
|
19
17
|
|
|
20
18
|
let prevParticipant = null
|
|
21
|
-
return
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
19
|
+
return (
|
|
20
|
+
<>
|
|
21
|
+
{events.map((event) => {
|
|
22
|
+
const { type, payload } = event
|
|
23
|
+
|
|
24
|
+
let participantChanged = false
|
|
25
|
+
if (type !== 'participant' && type !== 'service_data') {
|
|
26
|
+
const { participant, fromClient } = payload
|
|
27
|
+
const currentParticipant = fromClient
|
|
28
|
+
? 'seamly-client-participant'
|
|
29
|
+
: participant
|
|
30
|
+
if (event.type !== 'info' && prevParticipant !== currentParticipant) {
|
|
31
|
+
participantChanged = true
|
|
32
|
+
}
|
|
33
|
+
prevParticipant = currentParticipant
|
|
34
|
+
}
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
return (
|
|
37
|
+
<Event
|
|
38
|
+
key={event.payload.key || event.payload.id}
|
|
39
|
+
event={event}
|
|
40
|
+
newParticipant={participantChanged}
|
|
41
|
+
/>
|
|
42
|
+
)
|
|
43
|
+
})}
|
|
44
|
+
</>
|
|
45
|
+
)
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
const Conversation = () => {
|
|
46
49
|
const { t } = useI18n()
|
|
47
|
-
const chatBodyContainer = useRef(null)
|
|
48
|
-
const events = useEvents()
|
|
49
50
|
const isLoading = useSeamlyIsLoading()
|
|
50
51
|
const { isOpen } = useVisibility()
|
|
51
52
|
const skiplinkTargetId = useSkiplink()
|
|
52
53
|
const focusSkiplinkTarget = useSkiplinkTargetFocusing()
|
|
53
|
-
const loadedImageEventIds = useLoadedImageEventIds()
|
|
54
|
-
|
|
55
|
-
useLayoutEffect(() => {
|
|
56
|
-
const containerElement = chatBodyContainer.current
|
|
57
|
-
if (containerElement) {
|
|
58
|
-
requestAnimationFrame(async () => {
|
|
59
|
-
await timeout(30) // Wait for next frame tick
|
|
60
|
-
containerElement.scrollTop = containerElement.scrollHeight
|
|
61
|
-
})
|
|
62
|
-
}
|
|
63
|
-
}, [events, isLoading, isOpen, loadedImageEventIds])
|
|
64
54
|
|
|
65
55
|
const onClickHandler = (e) => {
|
|
66
56
|
e.preventDefault()
|
|
@@ -78,7 +68,8 @@ const Conversation = () => {
|
|
|
78
68
|
{t('skiplinkText')}
|
|
79
69
|
</a>
|
|
80
70
|
)}
|
|
81
|
-
|
|
71
|
+
|
|
72
|
+
<div className={className('chat__body')}>
|
|
82
73
|
<div className={className('conversation__container')}>
|
|
83
74
|
<PrivacyDisclaimer />
|
|
84
75
|
<ol className={className('conversation')}>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef } from 'preact/hooks'
|
|
2
|
-
import { className } from 'lib/css'
|
|
3
2
|
import { useGeneratedId, useSeamlyCommands } from 'ui/hooks/seamly-hooks'
|
|
4
|
-
import {
|
|
3
|
+
import { actionTypes, cardTypes } from 'ui/utils/seamly-utils'
|
|
4
|
+
import { className } from 'lib/css'
|
|
5
5
|
|
|
6
6
|
const CardComponent = ({
|
|
7
7
|
id,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useGeneratedId } from 'ui/hooks/seamly-hooks'
|
|
2
1
|
import MessageContainer from 'ui/components/conversation/message-container'
|
|
2
|
+
import { useGeneratedId } from 'ui/hooks/seamly-hooks'
|
|
3
3
|
import { useTranslatedEventData } from 'domains/translations/hooks'
|
|
4
4
|
import CardComponent from './card-component'
|
|
5
5
|
|
package/src/javascripts/ui/components/conversation/event/carousel-component/components/controls.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { className } from 'lib/css'
|
|
2
|
-
import { useI18n } from 'domains/i18n/hooks'
|
|
3
1
|
import Icon from 'ui/components/layout/icon'
|
|
2
|
+
import { useI18n } from 'domains/i18n/hooks'
|
|
3
|
+
import { className } from 'lib/css'
|
|
4
4
|
|
|
5
5
|
export default function CarouselControls({
|
|
6
6
|
items,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createRef } from 'preact'
|
|
2
|
-
import {
|
|
3
|
-
import { className } from 'lib/css'
|
|
4
|
-
import { useGeneratedId } from 'ui/hooks/utility-hooks'
|
|
2
|
+
import { useEffect, useMemo, useRef, useState } from 'preact/hooks'
|
|
5
3
|
import CarouselMessageSlide from 'ui/components/conversation/event/carousel-message/components/slide'
|
|
6
|
-
import
|
|
4
|
+
import { useGeneratedId } from 'ui/hooks/utility-hooks'
|
|
5
|
+
import { className } from 'lib/css'
|
|
7
6
|
import CarouselControls from './components/controls'
|
|
7
|
+
import CarouselPagination from './components/pagination'
|
|
8
8
|
|
|
9
9
|
const defaultGetItemKey = (item, idx, prefix) => `${prefix}${idx}`
|
|
10
10
|
const defaultGetItemLabel = (item) => item.label
|
package/src/javascripts/ui/components/conversation/event/carousel-message/components/slide.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { className } from 'lib/css'
|
|
2
|
-
import { useI18n } from 'domains/i18n/hooks'
|
|
3
1
|
import CardComponent from 'ui/components/conversation/event/card-component'
|
|
2
|
+
import { useI18n } from 'domains/i18n/hooks'
|
|
3
|
+
import { className } from 'lib/css'
|
|
4
4
|
|
|
5
5
|
export default function CarouselMessageSlide({
|
|
6
6
|
item: slide,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import MessageContainer from 'ui/components/conversation/message-container'
|
|
2
1
|
import CarouselComponent from 'ui/components/conversation/event/carousel-component'
|
|
2
|
+
import MessageContainer from 'ui/components/conversation/message-container'
|
|
3
3
|
import { useTranslatedEventData } from 'domains/translations/hooks'
|
|
4
4
|
import CarouselMessageSlide from './components/slide'
|
|
5
5
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { RefObject, createContext } from 'preact'
|
|
2
|
+
import { MutableRef } from 'preact/hooks'
|
|
3
|
+
|
|
4
|
+
const ChatScrollContext = createContext<{
|
|
5
|
+
eventRefs: Record<string, RefObject<HTMLElement>>
|
|
6
|
+
unreadIds: string[]
|
|
7
|
+
scrollToRef: () => void
|
|
8
|
+
scrollToBottom: () => void
|
|
9
|
+
containerRef: MutableRef<HTMLDivElement>
|
|
10
|
+
}>(null)
|
|
11
|
+
|
|
12
|
+
export default ChatScrollContext
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { RefObject, createRef } from 'preact'
|
|
2
|
+
import { useMemo } from 'preact/hooks'
|
|
3
|
+
import ChatScrollContext from 'ui/components/conversation/event/chat-scroll/chat-scroll-context'
|
|
4
|
+
import UnreadMessagesButton from 'ui/components/conversation/event/chat-scroll/unread-messages-button'
|
|
5
|
+
import useChatScroll from 'ui/components/conversation/use-chat-scroll'
|
|
6
|
+
import { useEvents } from 'ui/hooks/seamly-hooks'
|
|
7
|
+
import { className } from 'lib/css'
|
|
8
|
+
|
|
9
|
+
const ChatScrollProvider = ({ children }) => {
|
|
10
|
+
const events = useEvents()
|
|
11
|
+
const eventRefs = useMemo(
|
|
12
|
+
() =>
|
|
13
|
+
events.reduce<Record<string, RefObject<HTMLElement>>>((acc, value) => {
|
|
14
|
+
acc[value.payload.id] = createRef()
|
|
15
|
+
return acc
|
|
16
|
+
}, {}),
|
|
17
|
+
[events],
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
const { scrollToRef, scrollToBottom, containerRef, unreadIds } =
|
|
21
|
+
useChatScroll(eventRefs)
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<ChatScrollContext.Provider
|
|
25
|
+
value={{
|
|
26
|
+
eventRefs,
|
|
27
|
+
unreadIds,
|
|
28
|
+
scrollToRef,
|
|
29
|
+
scrollToBottom,
|
|
30
|
+
containerRef,
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
<div className={className('chat__container')}>
|
|
34
|
+
<div
|
|
35
|
+
className={className('chat__container__scroll-area')}
|
|
36
|
+
ref={containerRef}
|
|
37
|
+
>
|
|
38
|
+
{children}
|
|
39
|
+
</div>
|
|
40
|
+
<UnreadMessagesButton />
|
|
41
|
+
</div>
|
|
42
|
+
</ChatScrollContext.Provider>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default ChatScrollProvider
|