app-tutor-ai-consumer 1.24.3 → 1.25.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 +16 -0
- package/package.json +1 -1
- package/src/lib/components/icons/icon-names.d.ts +1 -0
- package/src/lib/components/icons/waveforms.svg +6 -0
- package/src/modules/messages/components/chat-input/chat-input.spec.tsx +0 -6
- package/src/modules/messages/components/chat-input/chat-input.tsx +1 -20
- package/src/modules/messages/components/message-content-type-renderer/index.ts +2 -0
- package/src/modules/messages/components/message-content-type-renderer/message-content-type-renderer.tsx +47 -0
- package/src/modules/messages/components/message-item/message-item.tsx +12 -19
- package/src/modules/messages/components/messages-container/messages-container.tsx +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## [1.25.1](https://github.com/Hotmart-Org/app-tutor-ai-consumer/compare/v1.25.0...v1.25.1) (2025-08-12)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- qa issues part 2 ([203cb3c](https://github.com/Hotmart-Org/app-tutor-ai-consumer/commit/203cb3c87d0abbdc6024e53c27ff3f91294a0bdb))
|
|
6
|
+
|
|
7
|
+
# [1.25.0](https://github.com/Hotmart-Org/app-tutor-ai-consumer/compare/v1.24.3...v1.25.0) (2025-08-12)
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
- cr issues ([ec25121](https://github.com/Hotmart-Org/app-tutor-ai-consumer/commit/ec25121f4271f305c4b288586fcba125fa4f77e6))
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
- add Tutor voice messages support ([3024d7c](https://github.com/Hotmart-Org/app-tutor-ai-consumer/commit/3024d7c74bb8e07593f28d4b5b554f0d5d6495d1))
|
|
16
|
+
|
|
1
17
|
## [1.24.3](https://github.com/Hotmart-Org/app-tutor-ai-consumer/compare/v1.24.2...v1.24.3) (2025-08-12)
|
|
2
18
|
|
|
3
19
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg aria-hidden="true" focusable="false"
|
|
2
|
+
role="img" xmlns="http://www.w3.org/2000/svg"
|
|
3
|
+
viewBox="0 0 640 512">
|
|
4
|
+
<path fill="currentColor"
|
|
5
|
+
d="M328 0h-16a16 16 0 0 0-16 16v480a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16V16a16 16 0 0 0-16-16zm-96 96h-16a16 16 0 0 0-16 16v288a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16V112a16 16 0 0 0-16-16zm192 32h-16a16 16 0 0 0-16 16v224a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16V144a16 16 0 0 0-16-16zm96-64h-16a16 16 0 0 0-16 16v352a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zM136 192h-16a16 16 0 0 0-16 16v96a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16v-96a16 16 0 0 0-16-16zm-96 32H24a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm576 0h-16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z"></path>
|
|
6
|
+
</svg>
|
|
@@ -21,12 +21,6 @@ describe('ChatInput', () => {
|
|
|
21
21
|
])
|
|
22
22
|
})
|
|
23
23
|
|
|
24
|
-
it('should call focus when rendering the input', () => {
|
|
25
|
-
renderComponent()
|
|
26
|
-
|
|
27
|
-
expect(ref.current).toHaveFocus()
|
|
28
|
-
})
|
|
29
|
-
|
|
30
24
|
it('should call setValue when ref change event is called', () => {
|
|
31
25
|
renderComponent()
|
|
32
26
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { forwardRef,
|
|
1
|
+
import { forwardRef, useImperativeHandle, useRef } from 'react'
|
|
2
2
|
import clsx from 'clsx'
|
|
3
3
|
import type { ChangeEvent, KeyboardEvent } from 'react'
|
|
4
4
|
import { useTranslation } from 'react-i18next'
|
|
@@ -40,25 +40,6 @@ const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
const setInputFocus = useCallback(() => {
|
|
44
|
-
if (inputDisabled) return
|
|
45
|
-
|
|
46
|
-
const input = ref?.current
|
|
47
|
-
|
|
48
|
-
if (input === document.activeElement) return
|
|
49
|
-
|
|
50
|
-
if (input) {
|
|
51
|
-
input.focus()
|
|
52
|
-
|
|
53
|
-
const position = input.textLength ?? 0
|
|
54
|
-
input.setSelectionRange(position, position)
|
|
55
|
-
}
|
|
56
|
-
}, [inputDisabled])
|
|
57
|
-
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
setInputFocus()
|
|
60
|
-
}, [setInputFocus])
|
|
61
|
-
|
|
62
43
|
return (
|
|
63
44
|
<div
|
|
64
45
|
className={clsx(
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useTranslation } from 'react-i18next'
|
|
2
|
+
import type { Components } from 'react-markdown'
|
|
3
|
+
|
|
4
|
+
import { Icon, MarkdownRenderer } from '@/src/lib/components'
|
|
5
|
+
import type { ParsedMessage } from '../../types'
|
|
6
|
+
import { MessageImg } from '../message-img'
|
|
7
|
+
|
|
8
|
+
export const imgComponent: Components['img'] = ({ src }) => {
|
|
9
|
+
return <MessageImg message={{ thumbnails: {}, url: src, dimensions: {} } as ParsedMessage} />
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function MediaVoiceMessage() {
|
|
13
|
+
const { t } = useTranslation()
|
|
14
|
+
return (
|
|
15
|
+
<div className='flex items-center gap-2 py-3 text-xs/normal'>
|
|
16
|
+
<Icon name='waveforms' className='inline-flex h-4 w-4 shrink-0' />
|
|
17
|
+
<span>{t('chat_page.messages.audio')}</span>
|
|
18
|
+
</div>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function TextMessage({ message }: { message: ParsedMessage }) {
|
|
23
|
+
return (
|
|
24
|
+
<MarkdownRenderer
|
|
25
|
+
content={message?.text ?? message?.name}
|
|
26
|
+
imgComponent={imgComponent}
|
|
27
|
+
className='w-full'
|
|
28
|
+
/>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function MessageContentTypeRenderer({ message }: { message: ParsedMessage }) {
|
|
33
|
+
const messageFromAi = message.metadata.author === 'ai'
|
|
34
|
+
const messageType = message.type
|
|
35
|
+
const isMediaVoice = messageType === 'media/voice'
|
|
36
|
+
|
|
37
|
+
if (messageFromAi && isMediaVoice) return null
|
|
38
|
+
|
|
39
|
+
switch (message.type) {
|
|
40
|
+
case 'media/voice':
|
|
41
|
+
return <MediaVoiceMessage />
|
|
42
|
+
default:
|
|
43
|
+
return <TextMessage message={message} />
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default MessageContentTypeRenderer
|
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
import clsx from 'clsx'
|
|
2
|
-
import type { Components } from 'react-markdown'
|
|
3
2
|
|
|
4
|
-
import { MarkdownRenderer } from '@/src/lib/components'
|
|
5
3
|
import type { ParsedMessage } from '../../types'
|
|
6
4
|
import { MessageActions } from '../message-actions'
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
const imgComponent: Components['img'] = ({ src }) => {
|
|
10
|
-
return <MessageImg message={{ thumbnails: {}, url: src, dimensions: {} } as ParsedMessage} />
|
|
11
|
-
}
|
|
5
|
+
import { MessageContentTypeRenderer } from '../message-content-type-renderer'
|
|
12
6
|
|
|
13
7
|
function MessageItem({ message }: { message: ParsedMessage }) {
|
|
14
8
|
const messageFromUser = message.metadata.author === 'user'
|
|
15
9
|
const messageFromAi = message.metadata.author === 'ai'
|
|
10
|
+
const isMediaVoice = message.type === 'media/voice'
|
|
16
11
|
|
|
17
12
|
return (
|
|
18
13
|
<div
|
|
@@ -28,19 +23,17 @@ function MessageItem({ message }: { message: ParsedMessage }) {
|
|
|
28
23
|
'max-w-max bg-[rgb(from_var(--hc-color-neutral-300)_r_g_b_/_0.8)]': messageFromUser,
|
|
29
24
|
'bg-neutral-200': messageFromAi
|
|
30
25
|
})}>
|
|
31
|
-
<
|
|
32
|
-
content={message?.text ?? message?.name}
|
|
33
|
-
imgComponent={imgComponent}
|
|
34
|
-
className='w-full'
|
|
35
|
-
/>
|
|
26
|
+
<MessageContentTypeRenderer message={message} />
|
|
36
27
|
</div>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
'
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
28
|
+
{messageFromAi && isMediaVoice ? null : (
|
|
29
|
+
<MessageActions
|
|
30
|
+
className={clsx('flex items-center justify-between gap-2', {
|
|
31
|
+
'w-full': messageFromAi
|
|
32
|
+
})}
|
|
33
|
+
message={message}
|
|
34
|
+
showActions={messageFromAi}
|
|
35
|
+
/>
|
|
36
|
+
)}
|
|
44
37
|
</div>
|
|
45
38
|
)
|
|
46
39
|
}
|
|
@@ -66,7 +66,7 @@ const MessagesContainer = forwardRef<HTMLDivElement, MessagesContainerProps>(
|
|
|
66
66
|
className='flex h-full flex-col gap-2 overflow-auto max-md:p-[1.125rem] md:p-5'>
|
|
67
67
|
<div className='mb-auto flex-1 self-center'>
|
|
68
68
|
<Button
|
|
69
|
-
className='max-w-max rounded-full border border-neutral-300 bg-neutral-200 px-2 py-1 text-xs/normal tracking-wide text-neutral-900'
|
|
69
|
+
className='max-w-max rounded-full border border-neutral-300 bg-neutral-200 px-2 py-1 text-xs/normal tracking-wide text-neutral-900 hover:text-neutral-900 focus:text-neutral-900 active:text-neutral-900'
|
|
70
70
|
onClick={handleClickShowMore}
|
|
71
71
|
loading={loading}
|
|
72
72
|
show={showButton}>
|