app-tutor-ai-consumer 1.33.0 → 1.33.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/CHANGELOG.md +6 -0
- package/config/vitest/__mocks__/sparkie.tsx +1 -1
- package/package.json +2 -2
- package/src/@types/index.d.ts +2 -3
- package/src/config/tanstack/query-provider.tsx +3 -7
- package/src/index.tsx +11 -64
- package/src/lib/components/icons/icon-names.d.ts +1 -0
- package/src/lib/components/icons/tutor-logo.svg +9 -0
- package/src/modules/global-providers/global-providers.tsx +6 -1
- package/src/modules/messages/__tests__/imessage-with-sender-data.builder.ts +1 -1
- package/src/modules/messages/components/chat-input/chat-input.tsx +1 -1
- package/src/modules/messages/components/message-item/message-item.tsx +1 -2
- package/src/modules/messages/hooks/use-subscribe-message-received-event/use-subscribe-message-received-event.tsx +54 -119
- package/src/modules/messages/service.direct.ts +1 -1
- package/src/modules/messages/service.ts +2 -3
- package/src/modules/messages/types.ts +1 -1
- package/src/modules/messages/utils/set-messages-cache/utils.ts +1 -1
- package/src/modules/sparkie/hooks/use-init-sparkie/use-init-sparkie.tsx +6 -20
- package/src/modules/sparkie/service.ts +3 -2
- package/src/modules/widget/components/ai-disclaimer/ai-disclaimer.tsx +19 -0
- package/src/modules/widget/components/ai-disclaimer/index.ts +1 -0
- package/src/modules/widget/components/chat-page/chat-page.tsx +30 -71
- package/src/modules/widget/components/constants.tsx +1 -3
- package/src/modules/widget/components/container/container.tsx +14 -0
- package/src/modules/widget/components/greetings-card/greetings-card.tsx +9 -2
- package/src/modules/widget/components/starter-page/starter-page.tsx +63 -34
- package/src/modules/widget/store/widget-tabs.atom.ts +1 -31
- package/src/types.ts +0 -9
- package/src/index.backup.tsx +0 -61
- package/src/lib/hooks/use-response-timeout/index.ts +0 -1
- package/src/lib/hooks/use-response-timeout/use-response-timeout.tsx +0 -42
- package/src/modules/sparkie/store/index.ts +0 -1
- package/src/modules/sparkie/store/sparkie-state.atom.ts +0 -13
- package/src/modules/widget/components/error-page/error-page.spec.tsx +0 -17
- package/src/modules/widget/components/error-page/error-page.tsx +0 -10
- package/src/modules/widget/components/error-page/index.ts +0 -1
- package/src/modules/widget/components/starter-page/starter-page-actions/index.ts +0 -1
- package/src/modules/widget/components/starter-page/starter-page-actions/starter-page-actions.spec.tsx +0 -68
- package/src/modules/widget/components/starter-page/starter-page-actions/starter-page-actions.tsx +0 -33
- package/src/modules/widget/components/starter-page/starter-page-content/index.ts +0 -1
- package/src/modules/widget/components/starter-page/starter-page-content/starter-page-content.spec.tsx +0 -62
- package/src/modules/widget/components/starter-page/starter-page-content/starter-page-content.tsx +0 -57
- package/src/modules/widget/components/starter-page/starter-page-header/index.ts +0 -1
- package/src/modules/widget/components/starter-page/starter-page-header/starter-page-header.spec.tsx +0 -41
- package/src/modules/widget/components/starter-page/starter-page-header/starter-page-header.tsx +0 -34
- package/src/wrapper.tsx +0 -32
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [1.33.1](https://github.com/Hotmart-Org/app-tutor-ai-consumer/compare/v1.33.0...v1.33.1) (2025-10-22)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- markdownrenderer ([ae8c08a](https://github.com/Hotmart-Org/app-tutor-ai-consumer/commit/ae8c08a0620cd95a54a787ac00ddab78640d3f45))
|
|
6
|
+
|
|
1
7
|
# [1.33.0](https://github.com/Hotmart-Org/app-tutor-ai-consumer/compare/v1.32.3...v1.33.0) (2025-10-16)
|
|
2
8
|
|
|
3
9
|
### Features
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
SparkieMessageServiceMock,
|
|
5
5
|
SparkieCursorServiceMock
|
|
6
6
|
} from '@/src/modules/sparkie/__tests__/sparkie.mock'
|
|
7
|
-
import MessageService from '@hotmart
|
|
7
|
+
import MessageService from '@hotmart/sparkie/dist/MessageService'
|
|
8
8
|
|
|
9
9
|
vi.mock('@hotmart/sparkie', () => ({ default: SparkieMock }))
|
|
10
10
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "app-tutor-ai-consumer",
|
|
3
|
-
"version": "1.33.
|
|
3
|
+
"version": "1.33.1",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "rspack serve --env=development --config config/rspack/rspack.config.js",
|
|
@@ -108,8 +108,8 @@
|
|
|
108
108
|
"dependencies": {
|
|
109
109
|
"@hot-observability-js/react": "~1.1.0",
|
|
110
110
|
"@hotmart-org-ca/hot-observability-js": "~1.1.0",
|
|
111
|
-
"@hotmart-org-ca/sparkie": "~5.1.4",
|
|
112
111
|
"@hotmart/event-agent-js": "~1.1.2",
|
|
112
|
+
"@hotmart/sparkie": "~5.1.0",
|
|
113
113
|
"@optimizely/react-sdk": "~3.2.4",
|
|
114
114
|
"@tanstack/query-sync-storage-persister": "~5.80.7",
|
|
115
115
|
"@tanstack/react-query": "~5.80.6",
|
package/src/@types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { StartTutorWidgetProps
|
|
1
|
+
import type { StartTutorWidgetProps } from '@/src/types'
|
|
2
2
|
|
|
3
3
|
export {}
|
|
4
4
|
|
|
@@ -13,8 +13,7 @@ declare global {
|
|
|
13
13
|
elementId: StartTutorWidgetProps['elementId'],
|
|
14
14
|
settings: StartTutorWidgetProps['settings']
|
|
15
15
|
) => Promise<void>
|
|
16
|
-
closeChatWidget: () =>
|
|
17
|
-
__CHAT_WIDGET_INSTANCE__?: WidgetInstance
|
|
16
|
+
closeChatWidget: () => void
|
|
18
17
|
TOKEN: string
|
|
19
18
|
}
|
|
20
19
|
}
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import type { QueryClient } from '@tanstack/react-query'
|
|
2
1
|
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
|
|
3
2
|
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
|
|
4
3
|
import type { PropsWithChildren } from 'react'
|
|
5
4
|
|
|
6
|
-
import { persister } from './query-client'
|
|
5
|
+
import { persister, queryClient } from './query-client'
|
|
7
6
|
|
|
8
|
-
export type QueryProviderProps = PropsWithChildren<{
|
|
9
|
-
showDevTools?: boolean
|
|
10
|
-
queryClient: QueryClient
|
|
11
|
-
}>
|
|
7
|
+
export type QueryProviderProps = PropsWithChildren<{ showDevTools?: boolean }>
|
|
12
8
|
|
|
13
|
-
function QueryProvider({ children,
|
|
9
|
+
function QueryProvider({ children, showDevTools = true }: QueryProviderProps) {
|
|
14
10
|
return (
|
|
15
11
|
<PersistQueryClientProvider client={queryClient} persistOptions={{ persister }}>
|
|
16
12
|
{children}
|
package/src/index.tsx
CHANGED
|
@@ -4,15 +4,14 @@ import './config/styles/index.css'
|
|
|
4
4
|
import { StrictMode } from 'react'
|
|
5
5
|
import { createRoot } from 'react-dom/client'
|
|
6
6
|
|
|
7
|
-
import { queryClient, QueryProvider } from '@/src/config/tanstack'
|
|
8
7
|
import { initTheme } from '@/src/config/theme'
|
|
9
8
|
import { version } from '../package.json'
|
|
10
9
|
|
|
11
10
|
import { initLanguage } from './config/i18n'
|
|
12
11
|
import { devMode, productionMode } from './lib/utils'
|
|
13
|
-
import {
|
|
12
|
+
import { Main } from './main'
|
|
13
|
+
import { TutorWidgetEvents } from './modules/widget'
|
|
14
14
|
import type { Theme, WidgetSettingProps } from './types'
|
|
15
|
-
import Wrapper from './wrapper'
|
|
16
15
|
|
|
17
16
|
const loadMainStyles = () => {
|
|
18
17
|
const isProduction = productionMode
|
|
@@ -34,80 +33,28 @@ window.startChatWidget = async (
|
|
|
34
33
|
elementId = 'tutor-chat-app-widget',
|
|
35
34
|
settings: WidgetSettingProps
|
|
36
35
|
) => {
|
|
37
|
-
if (window.__CHAT_WIDGET_INSTANCE__) {
|
|
38
|
-
await window.closeChatWidget()
|
|
39
|
-
}
|
|
40
|
-
|
|
41
36
|
if (!devMode) {
|
|
42
37
|
loadMainStyles()
|
|
43
38
|
}
|
|
44
39
|
|
|
45
|
-
const
|
|
40
|
+
const rootElement = document.getElementById(elementId) as HTMLElement
|
|
46
41
|
|
|
47
|
-
if (!
|
|
42
|
+
if (!rootElement) return
|
|
48
43
|
|
|
49
|
-
|
|
50
|
-
const theme = (
|
|
44
|
+
rootElement.setAttribute('id', 'hotmart-app-tutor-ai-consumer-root')
|
|
45
|
+
const theme = (rootElement.getAttribute('data-theme') ?? 'dark') as Theme
|
|
46
|
+
const root = createRoot(rootElement)
|
|
51
47
|
|
|
52
|
-
|
|
48
|
+
await initLanguage(settings.locale)
|
|
49
|
+
initTheme(theme)
|
|
53
50
|
|
|
54
51
|
if (root) {
|
|
55
|
-
initTheme(theme)
|
|
56
|
-
await initLanguage(settings.locale)
|
|
57
|
-
|
|
58
52
|
root.render(
|
|
59
53
|
<StrictMode>
|
|
60
|
-
<
|
|
61
|
-
<Wrapper settings={{ ...settings, config: { ...settings.config, theme } }} />
|
|
62
|
-
</QueryProvider>
|
|
54
|
+
<Main settings={{ ...settings, config: { ...settings.config, theme } }} />
|
|
63
55
|
</StrictMode>
|
|
64
56
|
)
|
|
65
|
-
|
|
66
|
-
window.__CHAT_WIDGET_INSTANCE__ = { root, container, queryClient }
|
|
67
57
|
}
|
|
68
58
|
}
|
|
69
59
|
|
|
70
|
-
window.closeChatWidget =
|
|
71
|
-
const chatWidgetInstance = window.__CHAT_WIDGET_INSTANCE__
|
|
72
|
-
|
|
73
|
-
if (!chatWidgetInstance) return
|
|
74
|
-
|
|
75
|
-
const { root, container, queryClient } = chatWidgetInstance
|
|
76
|
-
|
|
77
|
-
try {
|
|
78
|
-
await queryClient.cancelQueries()
|
|
79
|
-
} catch (err) {
|
|
80
|
-
console.error('Error cancelling queries on widget close', err)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
try {
|
|
84
|
-
root.unmount()
|
|
85
|
-
} catch (err) {
|
|
86
|
-
console.warn('Error unmounting widget root', err)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (typeof queryClient.clear === 'function') {
|
|
90
|
-
try {
|
|
91
|
-
queryClient.clear()
|
|
92
|
-
} catch {
|
|
93
|
-
queryClient.getQueryCache().clear()
|
|
94
|
-
queryClient.getMutationCache().clear()
|
|
95
|
-
}
|
|
96
|
-
} else {
|
|
97
|
-
queryClient.getQueryCache().clear()
|
|
98
|
-
queryClient.getMutationCache().clear()
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
container.remove()
|
|
103
|
-
} catch {
|
|
104
|
-
// ignore
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
try {
|
|
108
|
-
await SparkieService.destroySparkie()
|
|
109
|
-
window.__CHAT_WIDGET_INSTANCE__ = undefined
|
|
110
|
-
} catch (err) {
|
|
111
|
-
console.error('Error destroying Sparkie instance', err)
|
|
112
|
-
}
|
|
113
|
-
}
|
|
60
|
+
window.closeChatWidget = () => TutorWidgetEvents['c3po-app-widget-close'].dispatch()
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M0.896914 6.12971C0.779441 6.10837 0.779442 5.89161 0.896914 5.87028C5.07103 5.11209 5.67461 2.64887 5.90592 0.812118C5.92066 0.695019 6.07934 0.695018 6.09408 0.812117C6.32539 2.64887 6.92897 5.11209 11.1031 5.87028C11.2206 5.89161 11.2206 6.10837 11.1031 6.12971C6.92897 6.8879 6.32539 9.35112 6.09408 11.1879C6.07934 11.305 5.92066 11.305 5.90592 11.1879C5.67461 9.35112 5.07103 6.8879 0.896914 6.12971Z" fill="url(#paint0_linear_7672_1716)"/>
|
|
3
|
+
<defs>
|
|
4
|
+
<linearGradient id="paint0_linear_7672_1716" x1="1.125" y1="-0.0649467" x2="10.634" y2="12.0859" gradientUnits="userSpaceOnUse">
|
|
5
|
+
<stop stop-color="#44D0FF"/>
|
|
6
|
+
<stop offset="1" stop-color="#B48EFF"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
</defs>
|
|
9
|
+
</svg>
|
|
@@ -2,6 +2,7 @@ import { type PropsWithChildren, useEffect } from 'react'
|
|
|
2
2
|
import { v4 } from 'uuid'
|
|
3
3
|
|
|
4
4
|
import { OptimizelyProvider } from '@/src/config/optimizely'
|
|
5
|
+
import { QueryProvider } from '@/src/config/tanstack'
|
|
5
6
|
import { useWidgetSettingsAtom } from '@/src/modules/widget'
|
|
6
7
|
import type { WidgetSettingProps } from '@/src/types'
|
|
7
8
|
|
|
@@ -20,7 +21,11 @@ function GlobalProviders({ children, settings }: GlobalProvidersProps) {
|
|
|
20
21
|
setWidgetSettings(settings)
|
|
21
22
|
}, [setWidgetSettings, settings])
|
|
22
23
|
|
|
23
|
-
return
|
|
24
|
+
return (
|
|
25
|
+
<OptimizelyProvider settings={settings}>
|
|
26
|
+
<QueryProvider>{children}</QueryProvider>
|
|
27
|
+
</OptimizelyProvider>
|
|
28
|
+
)
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
export default GlobalProviders
|
|
@@ -57,7 +57,7 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
|
|
|
57
57
|
),
|
|
58
58
|
{ 'cursor-not-allowed opacity-40': inputDisabled }
|
|
59
59
|
)}
|
|
60
|
-
placeholder={t('send_message.field.
|
|
60
|
+
placeholder={t('send_message.field.placeholder_v2')}
|
|
61
61
|
value={value}
|
|
62
62
|
onChange={handleChange}
|
|
63
63
|
onKeyDown={handleKeyDown}
|
|
@@ -22,8 +22,7 @@ function MessageItem({ message }: { message: ParsedMessage }) {
|
|
|
22
22
|
<div
|
|
23
23
|
data-test='messages-item'
|
|
24
24
|
className={clsx('w-full overflow-x-hidden rounded-lg p-3', {
|
|
25
|
-
'max-w-max bg-[rgb(from_var(--hc-color-neutral-300)_r_g_b_/_0.8)]': messageFromUser
|
|
26
|
-
'bg-neutral-200': messageFromAi
|
|
25
|
+
'max-w-max bg-[rgb(from_var(--hc-color-neutral-300)_r_g_b_/_0.8)]': messageFromUser
|
|
27
26
|
})}>
|
|
28
27
|
<MessageContentTypeRenderer message={message} />
|
|
29
28
|
</div>
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo } from 'react'
|
|
2
|
-
import type { InfiniteData
|
|
2
|
+
import type { InfiniteData } from '@tanstack/react-query'
|
|
3
3
|
import { useQueryClient } from '@tanstack/react-query'
|
|
4
4
|
import { produce } from 'immer'
|
|
5
5
|
|
|
6
6
|
import { ComponentSource, DataHubService } from '@/src/config/datahub'
|
|
7
7
|
import { ViewTutorAnswerMessageSchema } from '@/src/config/datahub/schemas/tutor'
|
|
8
|
-
import { useResponseTimeout } from '@/src/lib/hooks/use-response-timeout'
|
|
9
8
|
import { useUpdateCursor } from '@/src/modules/cursor/hooks'
|
|
10
9
|
import { useGetProfile } from '@/src/modules/profile'
|
|
11
10
|
import { SparkieService } from '@/src/modules/sparkie'
|
|
@@ -18,59 +17,6 @@ import { useMessagesMaxCount, useUnreadMessagesSetAtom } from '../../store'
|
|
|
18
17
|
import type { FetchMessagesResponse, IMessageWithSenderData } from '../../types'
|
|
19
18
|
import { getAllMessagesQuery } from '../use-infinite-get-messages'
|
|
20
19
|
|
|
21
|
-
export type MessageReceivedProps = {
|
|
22
|
-
data: IMessageWithSenderData
|
|
23
|
-
queryClient: QueryClient
|
|
24
|
-
conversationId: string
|
|
25
|
-
profileId: string
|
|
26
|
-
limit: number
|
|
27
|
-
messageIsMineCallback?: (data: IMessageWithSenderData) => void
|
|
28
|
-
messageIsNotMineCallback?: (data: IMessageWithSenderData) => void
|
|
29
|
-
errorCallback?: (error: unknown) => void
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const messageReceivedUtil = ({
|
|
33
|
-
queryClient,
|
|
34
|
-
data,
|
|
35
|
-
conversationId,
|
|
36
|
-
profileId,
|
|
37
|
-
limit,
|
|
38
|
-
messageIsMineCallback,
|
|
39
|
-
messageIsNotMineCallback,
|
|
40
|
-
errorCallback
|
|
41
|
-
}: MessageReceivedProps) => {
|
|
42
|
-
try {
|
|
43
|
-
const messagesQueryConfig = getAllMessagesQuery({ conversationId, profileId, limit })
|
|
44
|
-
const queryData = queryClient.getQueryData<InfiniteData<FetchMessagesResponse>>(
|
|
45
|
-
messagesQueryConfig.queryKey
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
const idsList = new Set(
|
|
49
|
-
queryData?.pages.flatMap((items) => items.messages.map((msg) => msg.id))
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
if (idsList.has(data.id)) return
|
|
53
|
-
|
|
54
|
-
queryClient.setQueryData<InfiniteData<FetchMessagesResponse>>(
|
|
55
|
-
messagesQueryConfig.queryKey,
|
|
56
|
-
(oldData) =>
|
|
57
|
-
produce(oldData, (draft) => {
|
|
58
|
-
draft?.pages.at(-1)?.messages?.push(data)
|
|
59
|
-
return draft
|
|
60
|
-
})
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
const isMine = data.contactId === profileId
|
|
64
|
-
|
|
65
|
-
if (isMine) {
|
|
66
|
-
return messageIsMineCallback?.(data)
|
|
67
|
-
}
|
|
68
|
-
messageIsNotMineCallback?.(data)
|
|
69
|
-
} catch (error) {
|
|
70
|
-
errorCallback?.(error)
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
20
|
const useSubscribeMessageReceivedEvent = () => {
|
|
75
21
|
const [settings] = useWidgetSettingsAtom()
|
|
76
22
|
const [, setWidgetLoading] = useWidgetLoadingAtom()
|
|
@@ -80,78 +26,75 @@ const useSubscribeMessageReceivedEvent = () => {
|
|
|
80
26
|
const useUpdateCursorMutation = useUpdateCursor()
|
|
81
27
|
const limit = useMessagesMaxCount()
|
|
82
28
|
const isAgentMode = useIsAgentParentAtomValue()
|
|
83
|
-
const { reset: resetLoadingTimeout, startTimeout } = useResponseTimeout()
|
|
84
29
|
|
|
85
30
|
const conversationId = useMemo(() => String(settings?.conversationId), [settings?.conversationId])
|
|
86
31
|
const profileId = useMemo(() => String(profileQuery?.data?.id), [profileQuery?.data?.id])
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
32
|
+
const messagesQueryConfig = useMemo(
|
|
33
|
+
() =>
|
|
34
|
+
getAllMessagesQuery({
|
|
35
|
+
conversationId,
|
|
36
|
+
profileId,
|
|
37
|
+
limit
|
|
38
|
+
}),
|
|
39
|
+
[conversationId, limit, profileId]
|
|
94
40
|
)
|
|
95
41
|
|
|
96
|
-
const
|
|
42
|
+
const messageReceived = useCallback(
|
|
97
43
|
(data: IMessageWithSenderData) => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
44
|
+
if (data.conversationId !== conversationId) return
|
|
45
|
+
|
|
46
|
+
const queryData = queryClient.getQueryData<InfiniteData<FetchMessagesResponse>>(
|
|
47
|
+
messagesQueryConfig.queryKey
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
const idsList = new Set(
|
|
51
|
+
queryData?.pages.flatMap((items) => items.messages.map((msg) => msg.id))
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
if (idsList.has(data.id)) return
|
|
55
|
+
|
|
56
|
+
queryClient.setQueryData<InfiniteData<FetchMessagesResponse>>(
|
|
57
|
+
messagesQueryConfig.queryKey,
|
|
58
|
+
(oldData) => {
|
|
59
|
+
return produce(oldData, (draft) => {
|
|
60
|
+
draft?.pages.at(-1)?.messages?.push(data)
|
|
61
|
+
return draft
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
const isMine = data.contactId === profileId
|
|
67
|
+
|
|
68
|
+
if (!isMine) {
|
|
69
|
+
DataHubService.sendEvent({
|
|
70
|
+
schema: new ViewTutorAnswerMessageSchema({
|
|
71
|
+
correlationId: data.metadata.correlationId,
|
|
72
|
+
messageId: data.id,
|
|
73
|
+
componentSource: isAgentMode
|
|
74
|
+
? ComponentSource.PRODUCT_AGENT
|
|
75
|
+
: ComponentSource.HOTMART_TUTOR
|
|
76
|
+
})
|
|
107
77
|
})
|
|
108
|
-
})
|
|
109
78
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const errorCallback = useCallback(
|
|
116
|
-
(error: unknown) => {
|
|
117
|
-
if (error) {
|
|
118
|
-
setWidgetLoading(false)
|
|
119
|
-
console.error(error)
|
|
120
|
-
throw new Error('Error getting realtime messages')
|
|
79
|
+
addUnreadMessagesToSet({ itemId: data.id })
|
|
80
|
+
setTimeout(() => setWidgetLoading(false), 100)
|
|
81
|
+
} else {
|
|
82
|
+
// The cursor should update only with my messages
|
|
83
|
+
useUpdateCursorMutation.mutate(data.conversationId)
|
|
121
84
|
}
|
|
122
85
|
},
|
|
123
|
-
[setWidgetLoading]
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
const messageReceived = useCallback(
|
|
127
|
-
(data: IMessageWithSenderData) => {
|
|
128
|
-
if (data.conversationId === conversationId)
|
|
129
|
-
messageReceivedUtil({
|
|
130
|
-
queryClient,
|
|
131
|
-
data,
|
|
132
|
-
conversationId,
|
|
133
|
-
profileId,
|
|
134
|
-
limit,
|
|
135
|
-
messageIsMineCallback,
|
|
136
|
-
messageIsNotMineCallback,
|
|
137
|
-
errorCallback
|
|
138
|
-
})
|
|
139
|
-
},
|
|
140
86
|
[
|
|
87
|
+
addUnreadMessagesToSet,
|
|
141
88
|
conversationId,
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
messageIsMineCallback,
|
|
145
|
-
messageIsNotMineCallback,
|
|
89
|
+
isAgentMode,
|
|
90
|
+
messagesQueryConfig.queryKey,
|
|
146
91
|
profileId,
|
|
147
|
-
queryClient
|
|
92
|
+
queryClient,
|
|
93
|
+
setWidgetLoading,
|
|
94
|
+
useUpdateCursorMutation
|
|
148
95
|
]
|
|
149
96
|
)
|
|
150
97
|
|
|
151
|
-
const startLoadingTimeout = useCallback(() => {
|
|
152
|
-
startTimeout(() => setWidgetLoading(false))
|
|
153
|
-
}, [setWidgetLoading, startTimeout])
|
|
154
|
-
|
|
155
98
|
useEffect(() => {
|
|
156
99
|
SparkieService.subscribeEvents({ messageReceived })
|
|
157
100
|
|
|
@@ -159,14 +102,6 @@ const useSubscribeMessageReceivedEvent = () => {
|
|
|
159
102
|
SparkieService.removeEventSubscription({ messageReceived })
|
|
160
103
|
}
|
|
161
104
|
}, [messageReceived])
|
|
162
|
-
|
|
163
|
-
useEffect(() => {
|
|
164
|
-
startLoadingTimeout()
|
|
165
|
-
|
|
166
|
-
return () => {
|
|
167
|
-
resetLoadingTimeout()
|
|
168
|
-
}
|
|
169
|
-
}, [resetLoadingTimeout, startLoadingTimeout])
|
|
170
105
|
}
|
|
171
106
|
|
|
172
107
|
export default useSubscribeMessageReceivedEvent
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { Message } from '@hotmart
|
|
2
|
-
import type MessageService from '@hotmart-org-ca/sparkie/dist/MessageService'
|
|
1
|
+
import type { Message } from '@hotmart/sparkie/dist/MessageService'
|
|
3
2
|
|
|
4
3
|
import { ApiError } from '@/src/config/request'
|
|
5
4
|
import { HttpCodes } from '@/src/lib/utils'
|
|
@@ -16,7 +15,7 @@ import type {
|
|
|
16
15
|
} from './types'
|
|
17
16
|
|
|
18
17
|
class MessagesService {
|
|
19
|
-
async getSparkieMessageService()
|
|
18
|
+
async getSparkieMessageService() {
|
|
20
19
|
try {
|
|
21
20
|
const messageService = await SparkieService.getMessageService()
|
|
22
21
|
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState } from 'react'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useWidgetSettingsAtomValue } from '@/src/modules/widget'
|
|
4
4
|
import { SparkieService } from '../..'
|
|
5
|
-
import { useSparkieStateAtom } from '../../store'
|
|
6
5
|
|
|
7
6
|
function useInitSparkie() {
|
|
8
7
|
const [isSuccess, setIsSuccess] = useState(false)
|
|
9
8
|
const settings = useWidgetSettingsAtomValue()
|
|
10
|
-
const [sparkieState, setSparkieState] = useSparkieStateAtom()
|
|
11
|
-
const isAgentMode = useIsAgentParentAtomValue()
|
|
12
9
|
|
|
13
10
|
const init = useCallback(async () => {
|
|
14
11
|
if (!settings?.hotmartToken) return
|
|
15
12
|
|
|
16
13
|
try {
|
|
17
|
-
setSparkieState('initializing')
|
|
18
14
|
await SparkieService.initSparkie({
|
|
19
15
|
token: settings?.hotmartToken,
|
|
20
16
|
skipPresenceSetup: true,
|
|
@@ -26,26 +22,16 @@ function useInitSparkie() {
|
|
|
26
22
|
})
|
|
27
23
|
await SparkieService.ensureInitialized()
|
|
28
24
|
setIsSuccess(true)
|
|
29
|
-
setSparkieState('initialized')
|
|
30
25
|
} catch {
|
|
31
26
|
setIsSuccess(false)
|
|
32
|
-
|
|
27
|
+
// TODO: Create Error PAGE and setTab
|
|
28
|
+
// setTab('information')
|
|
33
29
|
}
|
|
34
|
-
}, [
|
|
35
|
-
|
|
36
|
-
const checkState = useCallback(() => {
|
|
37
|
-
if (!isAgentMode && sparkieState === 'idle') {
|
|
38
|
-
return init()
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (sparkieState === 'initialized') {
|
|
42
|
-
setIsSuccess(true)
|
|
43
|
-
}
|
|
44
|
-
}, [init, isAgentMode, sparkieState])
|
|
30
|
+
}, [settings?.hotmartToken])
|
|
45
31
|
|
|
46
32
|
useEffect(() => {
|
|
47
|
-
void
|
|
48
|
-
}, [
|
|
33
|
+
void init()
|
|
34
|
+
}, [init])
|
|
49
35
|
|
|
50
36
|
return isSuccess
|
|
51
37
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Sparkie from '@hotmart
|
|
1
|
+
import Sparkie from '@hotmart/sparkie'
|
|
2
2
|
|
|
3
3
|
import { MSG_MAX_COUNT } from '../messages'
|
|
4
4
|
|
|
@@ -110,7 +110,8 @@ class SparkieService {
|
|
|
110
110
|
|
|
111
111
|
while (attempt <= maxRetries) {
|
|
112
112
|
try {
|
|
113
|
-
if (!token
|
|
113
|
+
if (!token || !token.trim())
|
|
114
|
+
throw new Error('Invalid or missing token for Sparkie initialization')
|
|
114
115
|
|
|
115
116
|
const sparkie = this.sparkieInstance
|
|
116
117
|
const service = await sparkie.init(token, { skipPresenceSetup })
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useTranslation } from 'react-i18next'
|
|
2
|
+
|
|
3
|
+
import { Icon } from '@/src/lib/components/icons'
|
|
4
|
+
|
|
5
|
+
const AIDisclaimer = () => {
|
|
6
|
+
const { t } = useTranslation()
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div className='mt-4 flex w-full items-center gap-1 text-xs text-neutral-500'>
|
|
10
|
+
<p className='mb-0'>{t('ai_disclaimer.technology')}</p>
|
|
11
|
+
|
|
12
|
+
<Icon name='tutor-logo' className='inline-flex h-3 w-3 align-middle' />
|
|
13
|
+
|
|
14
|
+
<p className='mb-0'>{t('ai_disclaimer.hotmart_ai')}</p>
|
|
15
|
+
</div>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default AIDisclaimer
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as AIDisclaimer } from './ai-disclaimer'
|