@magmamath/students-features 0.11.0-rc.8 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commonjs/features/chatbot/components/Chat/Chat.js +49 -139
- package/dist/commonjs/features/chatbot/components/Chat/Chat.js.map +1 -1
- package/dist/commonjs/features/chatbot/components/ChatControls/ChatControls.js +58 -43
- package/dist/commonjs/features/chatbot/components/ChatControls/ChatControls.js.map +1 -1
- package/dist/commonjs/features/chatbot/components/ChatInput/ChatInput.js +1 -3
- package/dist/commonjs/features/chatbot/components/ChatInput/ChatInput.js.map +1 -1
- package/dist/commonjs/features/chatbot/components/ChatInput/FreeText/ChatTextInput.js +2 -2
- package/dist/commonjs/features/chatbot/components/ChatInput/FreeText/ChatTextInput.js.map +1 -1
- package/dist/commonjs/features/chatbot/components/ChatInput/FreeText/SendMessageButton.js +1 -1
- package/dist/commonjs/features/chatbot/components/ChatInput/RequestHintButton.js.map +1 -1
- package/dist/commonjs/features/chatbot/components/ChatMessage/ChatMessage.js.map +1 -1
- package/dist/commonjs/features/chatbot/components/ChatMessage/MessageButtonsBlock.js.map +1 -1
- package/dist/commonjs/features/chatbot/components/ChatMessage/MessageLoader.js +36 -11
- package/dist/commonjs/features/chatbot/components/ChatMessage/MessageLoader.js.map +1 -1
- package/dist/commonjs/features/chatbot/components/ChatMessage/MessageTextToSpeech.js +8 -48
- package/dist/commonjs/features/chatbot/components/ChatMessage/MessageTextToSpeech.js.map +1 -1
- package/dist/commonjs/features/chatbot/components/ChatMessage/ReceivedMessage.js +20 -14
- package/dist/commonjs/features/chatbot/components/ChatMessage/ReceivedMessage.js.map +1 -1
- package/dist/commonjs/features/chatbot/components/ChatMessage/SentMessage.js +1 -1
- package/dist/commonjs/features/chatbot/components/Chatbot.js +12 -22
- package/dist/commonjs/features/chatbot/components/Chatbot.js.map +1 -1
- package/dist/commonjs/features/chatbot/constants.js +4 -4
- package/dist/commonjs/features/chatbot/constants.js.map +1 -1
- package/dist/commonjs/features/chatbot/helpers.js +1 -8
- package/dist/commonjs/features/chatbot/helpers.js.map +1 -1
- package/dist/commonjs/features/chatbot/index.js.map +1 -1
- package/dist/commonjs/features/chatbot/model/ChatBotModel.js +10 -46
- package/dist/commonjs/features/chatbot/model/ChatBotModel.js.map +1 -1
- package/dist/commonjs/features/chatbot/model/ChatbotApi.js +1 -1
- package/dist/commonjs/features/chatbot/model/ChatbotApi.js.map +1 -1
- package/dist/commonjs/features/chatbot/model/ChatsCacheModel.js +0 -9
- package/dist/commonjs/features/chatbot/model/ChatsCacheModel.js.map +1 -1
- package/dist/commonjs/features/chatbot/types/model.types.js.map +1 -1
- package/dist/commonjs/features/gifCelebrations/helpers.js +1 -0
- package/dist/commonjs/features/gifCelebrations/helpers.js.map +1 -1
- package/dist/commonjs/features/voice/constants.js +23 -0
- package/dist/commonjs/features/voice/constants.js.map +1 -0
- package/dist/commonjs/features/voice/helpers.js +208 -0
- package/dist/commonjs/features/voice/helpers.js.map +1 -0
- package/dist/commonjs/features/voice/index.js +105 -0
- package/dist/commonjs/features/voice/index.js.map +1 -0
- package/dist/commonjs/features/voice/playing/components/VoiceIcon.js +49 -0
- package/dist/commonjs/features/voice/playing/components/VoiceIcon.js.map +1 -0
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdown.js +215 -0
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdown.js.map +1 -0
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdownItem.js +108 -0
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdownItem.js.map +1 -0
- package/dist/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.js +50 -0
- package/dist/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.js.map +1 -0
- package/dist/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.js +34 -0
- package/dist/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.js.map +1 -0
- package/dist/commonjs/features/voice/playing/model/Player.model.js +98 -0
- package/dist/commonjs/features/voice/playing/model/Player.model.js.map +1 -0
- package/dist/commonjs/features/voice/playing/model/TranscriptionsDownloaderModel.js +66 -0
- package/dist/commonjs/features/voice/playing/model/TranscriptionsDownloaderModel.js.map +1 -0
- package/dist/commonjs/features/voice/playing/model/VoiceFileDownloader.model.js +39 -0
- package/dist/commonjs/features/voice/playing/model/VoiceFileDownloader.model.js.map +1 -0
- package/dist/commonjs/features/voice/playing/model/VoicePlayer.model.js +223 -0
- package/dist/commonjs/features/voice/playing/model/VoicePlayer.model.js.map +1 -0
- package/dist/commonjs/features/voice/playing/model/VoiceTranscriptionsCollection.js +41 -0
- package/dist/commonjs/features/voice/playing/model/VoiceTranscriptionsCollection.js.map +1 -0
- package/dist/commonjs/features/voice/playing/model/VoiceTranscriptionsDropdown.model.js +15 -0
- package/dist/commonjs/features/voice/playing/model/VoiceTranscriptionsDropdown.model.js.map +1 -0
- package/dist/commonjs/features/voice/playing/model/index.js +20 -0
- package/dist/commonjs/features/voice/playing/model/index.js.map +1 -0
- package/dist/commonjs/features/voice/recording/components/VoiceRecord.js +74 -0
- package/dist/commonjs/features/voice/recording/components/VoiceRecord.js.map +1 -0
- package/dist/commonjs/features/voice/recording/components/VoiceRecordButton.js +63 -0
- package/dist/commonjs/features/voice/recording/components/VoiceRecordButton.js.map +1 -0
- package/dist/commonjs/features/voice/recording/components/VoiceRecordDeleteButton.js +35 -0
- package/dist/commonjs/features/voice/recording/components/VoiceRecordDeleteButton.js.map +1 -0
- package/dist/commonjs/features/voice/recording/components/VoiceRecordDivider.js +27 -0
- package/dist/commonjs/features/voice/recording/components/VoiceRecordDivider.js.map +1 -0
- package/dist/commonjs/features/voice/recording/components/VoiceRecordTimer.js +50 -0
- package/dist/commonjs/features/voice/recording/components/VoiceRecordTimer.js.map +1 -0
- package/dist/commonjs/features/voice/recording/hooks/useVoiceRecorder.js +59 -0
- package/dist/commonjs/features/voice/recording/hooks/useVoiceRecorder.js.map +1 -0
- package/dist/commonjs/features/voice/recording/hooks/useVoiceRecorderAnimation.js +22 -0
- package/dist/commonjs/features/voice/recording/hooks/useVoiceRecorderAnimation.js.map +1 -0
- package/dist/commonjs/features/voice/recording/modal/ModalFooterButtons.js +53 -0
- package/dist/commonjs/features/voice/recording/modal/ModalFooterButtons.js.map +1 -0
- package/dist/commonjs/features/voice/recording/modal/VoiceRecordDeleteModal.js +78 -0
- package/dist/commonjs/features/voice/recording/modal/VoiceRecordDeleteModal.js.map +1 -0
- package/dist/commonjs/features/voice/recording/modal/VoiceRecordUndoModal.js +51 -0
- package/dist/commonjs/features/voice/recording/modal/VoiceRecordUndoModal.js.map +1 -0
- package/dist/commonjs/features/voice/recording/model/Recorder.model.js +55 -0
- package/dist/commonjs/features/voice/recording/model/Recorder.model.js.map +1 -0
- package/dist/commonjs/features/voice/recording/model/Uploader.model.js +44 -0
- package/dist/commonjs/features/voice/recording/model/Uploader.model.js.map +1 -0
- package/dist/commonjs/features/voice/recording/model/VoiceRecord.model.js +248 -0
- package/dist/commonjs/features/voice/recording/model/VoiceRecord.model.js.map +1 -0
- package/dist/commonjs/features/voice/recording/model/VoiceRecordCollection.js +30 -0
- package/dist/commonjs/features/voice/recording/model/VoiceRecordCollection.js.map +1 -0
- package/dist/commonjs/features/voice/types.js +6 -0
- package/dist/commonjs/features/voice/types.js.map +1 -0
- package/dist/commonjs/index.js +12 -0
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/shared/components/PlayButton.js +70 -0
- package/dist/commonjs/shared/components/PlayButton.js.map +1 -0
- package/dist/commonjs/shared/translation/localization/ca.json +17 -0
- package/dist/commonjs/shared/translation/localization/de.json +17 -0
- package/dist/commonjs/shared/translation/localization/en.json +17 -0
- package/dist/commonjs/shared/translation/localization/gb.json +17 -0
- package/dist/commonjs/shared/translation/localization/sct.json +17 -0
- package/dist/commonjs/shared/translation/localization/sw.json +17 -0
- package/dist/module/features/chatbot/components/Chat/Chat.js +51 -141
- package/dist/module/features/chatbot/components/Chat/Chat.js.map +1 -1
- package/dist/module/features/chatbot/components/ChatControls/ChatControls.js +59 -45
- package/dist/module/features/chatbot/components/ChatControls/ChatControls.js.map +1 -1
- package/dist/module/features/chatbot/components/ChatInput/ChatInput.js +1 -3
- package/dist/module/features/chatbot/components/ChatInput/ChatInput.js.map +1 -1
- package/dist/module/features/chatbot/components/ChatInput/FreeText/ChatTextInput.js +2 -2
- package/dist/module/features/chatbot/components/ChatInput/FreeText/ChatTextInput.js.map +1 -1
- package/dist/module/features/chatbot/components/ChatInput/FreeText/SendMessageButton.js +1 -1
- package/dist/module/features/chatbot/components/ChatInput/RequestHintButton.js.map +1 -1
- package/dist/module/features/chatbot/components/ChatMessage/ChatMessage.js.map +1 -1
- package/dist/module/features/chatbot/components/ChatMessage/MessageButtonsBlock.js.map +1 -1
- package/dist/module/features/chatbot/components/ChatMessage/MessageLoader.js +38 -14
- package/dist/module/features/chatbot/components/ChatMessage/MessageLoader.js.map +1 -1
- package/dist/module/features/chatbot/components/ChatMessage/MessageTextToSpeech.js +9 -49
- package/dist/module/features/chatbot/components/ChatMessage/MessageTextToSpeech.js.map +1 -1
- package/dist/module/features/chatbot/components/ChatMessage/ReceivedMessage.js +21 -15
- package/dist/module/features/chatbot/components/ChatMessage/ReceivedMessage.js.map +1 -1
- package/dist/module/features/chatbot/components/ChatMessage/SentMessage.js +1 -1
- package/dist/module/features/chatbot/components/Chatbot.js +11 -20
- package/dist/module/features/chatbot/components/Chatbot.js.map +1 -1
- package/dist/module/features/chatbot/constants.js +5 -5
- package/dist/module/features/chatbot/constants.js.map +1 -1
- package/dist/module/features/chatbot/helpers.js +1 -8
- package/dist/module/features/chatbot/helpers.js.map +1 -1
- package/dist/module/features/chatbot/index.js.map +1 -1
- package/dist/module/features/chatbot/model/ChatBotModel.js +10 -46
- package/dist/module/features/chatbot/model/ChatBotModel.js.map +1 -1
- package/dist/module/features/chatbot/model/ChatbotApi.js +1 -1
- package/dist/module/features/chatbot/model/ChatbotApi.js.map +1 -1
- package/dist/module/features/chatbot/model/ChatsCacheModel.js +0 -9
- package/dist/module/features/chatbot/model/ChatsCacheModel.js.map +1 -1
- package/dist/module/features/chatbot/types/model.types.js.map +1 -1
- package/dist/module/features/gifCelebrations/helpers.js +1 -0
- package/dist/module/features/gifCelebrations/helpers.js.map +1 -1
- package/dist/module/features/voice/constants.js +19 -0
- package/dist/module/features/voice/constants.js.map +1 -0
- package/dist/module/features/voice/helpers.js +191 -0
- package/dist/module/features/voice/helpers.js.map +1 -0
- package/dist/module/features/voice/index.js +12 -0
- package/dist/module/features/voice/index.js.map +1 -0
- package/dist/module/features/voice/playing/components/VoiceIcon.js +41 -0
- package/dist/module/features/voice/playing/components/VoiceIcon.js.map +1 -0
- package/dist/module/features/voice/playing/components/VoiceTranscriptionsDropdown.js +208 -0
- package/dist/module/features/voice/playing/components/VoiceTranscriptionsDropdown.js.map +1 -0
- package/dist/module/features/voice/playing/components/VoiceTranscriptionsDropdownItem.js +102 -0
- package/dist/module/features/voice/playing/components/VoiceTranscriptionsDropdownItem.js.map +1 -0
- package/dist/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.js +45 -0
- package/dist/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.js.map +1 -0
- package/dist/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.js +29 -0
- package/dist/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.js.map +1 -0
- package/dist/module/features/voice/playing/model/Player.model.js +93 -0
- package/dist/module/features/voice/playing/model/Player.model.js.map +1 -0
- package/dist/module/features/voice/playing/model/TranscriptionsDownloaderModel.js +61 -0
- package/dist/module/features/voice/playing/model/TranscriptionsDownloaderModel.js.map +1 -0
- package/dist/module/features/voice/playing/model/VoiceFileDownloader.model.js +34 -0
- package/dist/module/features/voice/playing/model/VoiceFileDownloader.model.js.map +1 -0
- package/dist/module/features/voice/playing/model/VoicePlayer.model.js +218 -0
- package/dist/module/features/voice/playing/model/VoicePlayer.model.js.map +1 -0
- package/dist/module/features/voice/playing/model/VoiceTranscriptionsCollection.js +36 -0
- package/dist/module/features/voice/playing/model/VoiceTranscriptionsCollection.js.map +1 -0
- package/dist/module/features/voice/playing/model/VoiceTranscriptionsDropdown.model.js +10 -0
- package/dist/module/features/voice/playing/model/VoiceTranscriptionsDropdown.model.js.map +1 -0
- package/dist/module/features/voice/playing/model/index.js +5 -0
- package/dist/module/features/voice/playing/model/index.js.map +1 -0
- package/dist/module/features/voice/recording/components/VoiceRecord.js +67 -0
- package/dist/module/features/voice/recording/components/VoiceRecord.js.map +1 -0
- package/dist/module/features/voice/recording/components/VoiceRecordButton.js +57 -0
- package/dist/module/features/voice/recording/components/VoiceRecordButton.js.map +1 -0
- package/dist/module/features/voice/recording/components/VoiceRecordDeleteButton.js +29 -0
- package/dist/module/features/voice/recording/components/VoiceRecordDeleteButton.js.map +1 -0
- package/dist/module/features/voice/recording/components/VoiceRecordDivider.js +21 -0
- package/dist/module/features/voice/recording/components/VoiceRecordDivider.js.map +1 -0
- package/dist/module/features/voice/recording/components/VoiceRecordTimer.js +44 -0
- package/dist/module/features/voice/recording/components/VoiceRecordTimer.js.map +1 -0
- package/dist/module/features/voice/recording/hooks/useVoiceRecorder.js +54 -0
- package/dist/module/features/voice/recording/hooks/useVoiceRecorder.js.map +1 -0
- package/dist/module/features/voice/recording/hooks/useVoiceRecorderAnimation.js +17 -0
- package/dist/module/features/voice/recording/hooks/useVoiceRecorderAnimation.js.map +1 -0
- package/dist/module/features/voice/recording/modal/ModalFooterButtons.js +47 -0
- package/dist/module/features/voice/recording/modal/ModalFooterButtons.js.map +1 -0
- package/dist/module/features/voice/recording/modal/VoiceRecordDeleteModal.js +71 -0
- package/dist/module/features/voice/recording/modal/VoiceRecordDeleteModal.js.map +1 -0
- package/dist/module/features/voice/recording/modal/VoiceRecordUndoModal.js +45 -0
- package/dist/module/features/voice/recording/modal/VoiceRecordUndoModal.js.map +1 -0
- package/dist/module/features/voice/recording/model/Recorder.model.js +50 -0
- package/dist/module/features/voice/recording/model/Recorder.model.js.map +1 -0
- package/dist/module/features/voice/recording/model/Uploader.model.js +39 -0
- package/dist/module/features/voice/recording/model/Uploader.model.js.map +1 -0
- package/dist/module/features/voice/recording/model/VoiceRecord.model.js +244 -0
- package/dist/module/features/voice/recording/model/VoiceRecord.model.js.map +1 -0
- package/dist/module/features/voice/recording/model/VoiceRecordCollection.js +25 -0
- package/dist/module/features/voice/recording/model/VoiceRecordCollection.js.map +1 -0
- package/dist/module/features/voice/types.js +4 -0
- package/dist/module/features/voice/types.js.map +1 -0
- package/dist/module/index.js +1 -0
- package/dist/module/index.js.map +1 -1
- package/dist/module/shared/components/PlayButton.js +64 -0
- package/dist/module/shared/components/PlayButton.js.map +1 -0
- package/dist/module/shared/translation/localization/ca.json +17 -0
- package/dist/module/shared/translation/localization/de.json +17 -0
- package/dist/module/shared/translation/localization/en.json +17 -0
- package/dist/module/shared/translation/localization/gb.json +17 -0
- package/dist/module/shared/translation/localization/sct.json +17 -0
- package/dist/module/shared/translation/localization/sw.json +17 -0
- package/dist/typescript/commonjs/features/chatbot/components/Chat/Chat.d.ts +1 -2
- package/dist/typescript/commonjs/features/chatbot/components/Chat/Chat.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/components/ChatControls/ChatControls.d.ts +3 -3
- package/dist/typescript/commonjs/features/chatbot/components/ChatControls/ChatControls.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/components/ChatInput/ChatInput.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/components/ChatInput/RequestHintButton.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/ChatMessage.d.ts +1 -0
- package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/ChatMessage.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/MessageButtonsBlock.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/MessageLoader.d.ts +6 -1
- package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/MessageLoader.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/MessageTextToSpeech.d.ts +2 -2
- package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/MessageTextToSpeech.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/ReceivedMessage.d.ts +1 -1
- package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/ReceivedMessage.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/components/Chatbot.d.ts +1 -2
- package/dist/typescript/commonjs/features/chatbot/components/Chatbot.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/constants.d.ts +5 -5
- package/dist/typescript/commonjs/features/chatbot/constants.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/helpers.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/index.d.ts +2 -2
- package/dist/typescript/commonjs/features/chatbot/index.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/model/ChatBotModel.d.ts +1 -2
- package/dist/typescript/commonjs/features/chatbot/model/ChatBotModel.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/model/ChatsCacheModel.d.ts +0 -1
- package/dist/typescript/commonjs/features/chatbot/model/ChatsCacheModel.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/types/api.types.d.ts +17 -19
- package/dist/typescript/commonjs/features/chatbot/types/api.types.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/types/model.types.d.ts +13 -7
- package/dist/typescript/commonjs/features/chatbot/types/model.types.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/chatbot/types/units.types.d.ts +0 -1
- package/dist/typescript/commonjs/features/chatbot/types/units.types.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/gifCelebrations/helpers.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/voice/constants.d.ts +16 -0
- package/dist/typescript/commonjs/features/voice/constants.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/helpers.d.ts +46 -0
- package/dist/typescript/commonjs/features/voice/helpers.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/index.d.ts +10 -0
- package/dist/typescript/commonjs/features/voice/index.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceIcon.d.ts +8 -0
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceIcon.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdown.d.ts +16 -0
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdown.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdownItem.d.ts +12 -0
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdownItem.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.d.ts +16 -0
- package/dist/typescript/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.d.ts +11 -0
- package/dist/typescript/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/model/Player.model.d.ts +23 -0
- package/dist/typescript/commonjs/features/voice/playing/model/Player.model.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/model/TranscriptionsDownloaderModel.d.ts +15 -0
- package/dist/typescript/commonjs/features/voice/playing/model/TranscriptionsDownloaderModel.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/model/VoiceFileDownloader.model.d.ts +17 -0
- package/dist/typescript/commonjs/features/voice/playing/model/VoiceFileDownloader.model.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/model/VoicePlayer.model.d.ts +41 -0
- package/dist/typescript/commonjs/features/voice/playing/model/VoicePlayer.model.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/model/VoiceTranscriptionsCollection.d.ts +13 -0
- package/dist/typescript/commonjs/features/voice/playing/model/VoiceTranscriptionsCollection.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/model/VoiceTranscriptionsDropdown.model.d.ts +7 -0
- package/dist/typescript/commonjs/features/voice/playing/model/VoiceTranscriptionsDropdown.model.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/model/index.d.ts +3 -0
- package/dist/typescript/commonjs/features/voice/playing/model/index.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/components/VoiceRecord.d.ts +10 -0
- package/dist/typescript/commonjs/features/voice/recording/components/VoiceRecord.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/components/VoiceRecordButton.d.ts +10 -0
- package/dist/typescript/commonjs/features/voice/recording/components/VoiceRecordButton.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/components/VoiceRecordDeleteButton.d.ts +8 -0
- package/dist/typescript/commonjs/features/voice/recording/components/VoiceRecordDeleteButton.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/components/VoiceRecordDivider.d.ts +3 -0
- package/dist/typescript/commonjs/features/voice/recording/components/VoiceRecordDivider.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/components/VoiceRecordTimer.d.ts +11 -0
- package/dist/typescript/commonjs/features/voice/recording/components/VoiceRecordTimer.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/hooks/useVoiceRecorder.d.ts +5 -0
- package/dist/typescript/commonjs/features/voice/recording/hooks/useVoiceRecorder.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/hooks/useVoiceRecorderAnimation.d.ts +6 -0
- package/dist/typescript/commonjs/features/voice/recording/hooks/useVoiceRecorderAnimation.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/modal/ModalFooterButtons.d.ts +12 -0
- package/dist/typescript/commonjs/features/voice/recording/modal/ModalFooterButtons.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/modal/VoiceRecordDeleteModal.d.ts +11 -0
- package/dist/typescript/commonjs/features/voice/recording/modal/VoiceRecordDeleteModal.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/modal/VoiceRecordUndoModal.d.ts +11 -0
- package/dist/typescript/commonjs/features/voice/recording/modal/VoiceRecordUndoModal.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/model/Recorder.model.d.ts +19 -0
- package/dist/typescript/commonjs/features/voice/recording/model/Recorder.model.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/model/Uploader.model.d.ts +18 -0
- package/dist/typescript/commonjs/features/voice/recording/model/Uploader.model.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/model/VoiceRecord.model.d.ts +50 -0
- package/dist/typescript/commonjs/features/voice/recording/model/VoiceRecord.model.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/recording/model/VoiceRecordCollection.d.ts +10 -0
- package/dist/typescript/commonjs/features/voice/recording/model/VoiceRecordCollection.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/types.d.ts +72 -0
- package/dist/typescript/commonjs/features/voice/types.d.ts.map +1 -0
- package/dist/typescript/commonjs/index.d.ts +1 -0
- package/dist/typescript/commonjs/index.d.ts.map +1 -1
- package/dist/typescript/commonjs/shared/components/PlayButton.d.ts +18 -0
- package/dist/typescript/commonjs/shared/components/PlayButton.d.ts.map +1 -0
- package/dist/typescript/commonjs/shared/translation/constants.d.ts +102 -0
- package/dist/typescript/commonjs/shared/translation/constants.d.ts.map +1 -1
- package/dist/typescript/commonjs/shared/translation/model.d.ts +34 -0
- package/dist/typescript/commonjs/shared/translation/model.d.ts.map +1 -1
- package/dist/typescript/commonjs/types/common.types.d.ts +3 -0
- package/dist/typescript/commonjs/types/common.types.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/components/Chat/Chat.d.ts +1 -2
- package/dist/typescript/module/features/chatbot/components/Chat/Chat.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/components/ChatControls/ChatControls.d.ts +3 -3
- package/dist/typescript/module/features/chatbot/components/ChatControls/ChatControls.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/components/ChatInput/ChatInput.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/components/ChatInput/RequestHintButton.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/components/ChatMessage/ChatMessage.d.ts +1 -0
- package/dist/typescript/module/features/chatbot/components/ChatMessage/ChatMessage.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/components/ChatMessage/MessageButtonsBlock.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/components/ChatMessage/MessageLoader.d.ts +6 -1
- package/dist/typescript/module/features/chatbot/components/ChatMessage/MessageLoader.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/components/ChatMessage/MessageTextToSpeech.d.ts +2 -2
- package/dist/typescript/module/features/chatbot/components/ChatMessage/MessageTextToSpeech.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/components/ChatMessage/ReceivedMessage.d.ts +1 -1
- package/dist/typescript/module/features/chatbot/components/ChatMessage/ReceivedMessage.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/components/Chatbot.d.ts +1 -2
- package/dist/typescript/module/features/chatbot/components/Chatbot.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/constants.d.ts +5 -5
- package/dist/typescript/module/features/chatbot/constants.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/helpers.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/index.d.ts +2 -2
- package/dist/typescript/module/features/chatbot/index.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/model/ChatBotModel.d.ts +1 -2
- package/dist/typescript/module/features/chatbot/model/ChatBotModel.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/model/ChatsCacheModel.d.ts +0 -1
- package/dist/typescript/module/features/chatbot/model/ChatsCacheModel.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/types/api.types.d.ts +17 -19
- package/dist/typescript/module/features/chatbot/types/api.types.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/types/model.types.d.ts +13 -7
- package/dist/typescript/module/features/chatbot/types/model.types.d.ts.map +1 -1
- package/dist/typescript/module/features/chatbot/types/units.types.d.ts +0 -1
- package/dist/typescript/module/features/chatbot/types/units.types.d.ts.map +1 -1
- package/dist/typescript/module/features/gifCelebrations/helpers.d.ts.map +1 -1
- package/dist/typescript/module/features/voice/constants.d.ts +16 -0
- package/dist/typescript/module/features/voice/constants.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/helpers.d.ts +46 -0
- package/dist/typescript/module/features/voice/helpers.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/index.d.ts +10 -0
- package/dist/typescript/module/features/voice/index.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/components/VoiceIcon.d.ts +8 -0
- package/dist/typescript/module/features/voice/playing/components/VoiceIcon.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscriptionsDropdown.d.ts +16 -0
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscriptionsDropdown.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscriptionsDropdownItem.d.ts +12 -0
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscriptionsDropdownItem.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.d.ts +16 -0
- package/dist/typescript/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.d.ts +11 -0
- package/dist/typescript/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/model/Player.model.d.ts +23 -0
- package/dist/typescript/module/features/voice/playing/model/Player.model.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/model/TranscriptionsDownloaderModel.d.ts +15 -0
- package/dist/typescript/module/features/voice/playing/model/TranscriptionsDownloaderModel.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/model/VoiceFileDownloader.model.d.ts +17 -0
- package/dist/typescript/module/features/voice/playing/model/VoiceFileDownloader.model.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/model/VoicePlayer.model.d.ts +41 -0
- package/dist/typescript/module/features/voice/playing/model/VoicePlayer.model.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/model/VoiceTranscriptionsCollection.d.ts +13 -0
- package/dist/typescript/module/features/voice/playing/model/VoiceTranscriptionsCollection.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/model/VoiceTranscriptionsDropdown.model.d.ts +7 -0
- package/dist/typescript/module/features/voice/playing/model/VoiceTranscriptionsDropdown.model.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/model/index.d.ts +3 -0
- package/dist/typescript/module/features/voice/playing/model/index.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/components/VoiceRecord.d.ts +10 -0
- package/dist/typescript/module/features/voice/recording/components/VoiceRecord.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/components/VoiceRecordButton.d.ts +10 -0
- package/dist/typescript/module/features/voice/recording/components/VoiceRecordButton.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/components/VoiceRecordDeleteButton.d.ts +8 -0
- package/dist/typescript/module/features/voice/recording/components/VoiceRecordDeleteButton.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/components/VoiceRecordDivider.d.ts +3 -0
- package/dist/typescript/module/features/voice/recording/components/VoiceRecordDivider.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/components/VoiceRecordTimer.d.ts +11 -0
- package/dist/typescript/module/features/voice/recording/components/VoiceRecordTimer.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/hooks/useVoiceRecorder.d.ts +5 -0
- package/dist/typescript/module/features/voice/recording/hooks/useVoiceRecorder.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/hooks/useVoiceRecorderAnimation.d.ts +6 -0
- package/dist/typescript/module/features/voice/recording/hooks/useVoiceRecorderAnimation.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/modal/ModalFooterButtons.d.ts +12 -0
- package/dist/typescript/module/features/voice/recording/modal/ModalFooterButtons.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/modal/VoiceRecordDeleteModal.d.ts +11 -0
- package/dist/typescript/module/features/voice/recording/modal/VoiceRecordDeleteModal.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/modal/VoiceRecordUndoModal.d.ts +11 -0
- package/dist/typescript/module/features/voice/recording/modal/VoiceRecordUndoModal.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/model/Recorder.model.d.ts +19 -0
- package/dist/typescript/module/features/voice/recording/model/Recorder.model.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/model/Uploader.model.d.ts +18 -0
- package/dist/typescript/module/features/voice/recording/model/Uploader.model.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/model/VoiceRecord.model.d.ts +50 -0
- package/dist/typescript/module/features/voice/recording/model/VoiceRecord.model.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/recording/model/VoiceRecordCollection.d.ts +10 -0
- package/dist/typescript/module/features/voice/recording/model/VoiceRecordCollection.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/types.d.ts +72 -0
- package/dist/typescript/module/features/voice/types.d.ts.map +1 -0
- package/dist/typescript/module/index.d.ts +1 -0
- package/dist/typescript/module/index.d.ts.map +1 -1
- package/dist/typescript/module/shared/components/PlayButton.d.ts +18 -0
- package/dist/typescript/module/shared/components/PlayButton.d.ts.map +1 -0
- package/dist/typescript/module/shared/translation/constants.d.ts +102 -0
- package/dist/typescript/module/shared/translation/constants.d.ts.map +1 -1
- package/dist/typescript/module/shared/translation/model.d.ts +34 -0
- package/dist/typescript/module/shared/translation/model.d.ts.map +1 -1
- package/dist/typescript/module/types/common.types.d.ts +3 -0
- package/dist/typescript/module/types/common.types.d.ts.map +1 -1
- package/package.json +11 -4
- package/src/features/chatbot/components/Chat/Chat.tsx +69 -192
- package/src/features/chatbot/components/ChatControls/ChatControls.tsx +66 -44
- package/src/features/chatbot/components/ChatInput/ChatInput.tsx +1 -3
- package/src/features/chatbot/components/ChatInput/FreeText/ChatTextInput.tsx +2 -2
- package/src/features/chatbot/components/ChatInput/FreeText/SendMessageButton.tsx +1 -1
- package/src/features/chatbot/components/ChatInput/RequestHintButton.tsx +0 -1
- package/src/features/chatbot/components/ChatMessage/ChatMessage.tsx +1 -0
- package/src/features/chatbot/components/ChatMessage/MessageButtonsBlock.tsx +1 -1
- package/src/features/chatbot/components/ChatMessage/MessageLoader.tsx +35 -11
- package/src/features/chatbot/components/ChatMessage/MessageTextToSpeech.tsx +9 -51
- package/src/features/chatbot/components/ChatMessage/ReceivedMessage.tsx +17 -11
- package/src/features/chatbot/components/ChatMessage/SentMessage.tsx +1 -1
- package/src/features/chatbot/components/Chatbot.tsx +11 -21
- package/src/features/chatbot/constants.ts +4 -4
- package/src/features/chatbot/helpers.ts +0 -3
- package/src/features/chatbot/index.ts +2 -16
- package/src/features/chatbot/model/ChatBotModel.ts +8 -51
- package/src/features/chatbot/model/ChatbotApi.ts +1 -1
- package/src/features/chatbot/model/ChatsCacheModel.ts +0 -7
- package/src/features/chatbot/types/api.types.ts +17 -17
- package/src/features/chatbot/types/model.types.ts +15 -7
- package/src/features/chatbot/types/units.types.ts +0 -1
- package/src/features/gifCelebrations/helpers.ts +1 -0
- package/src/features/voice/constants.ts +15 -0
- package/src/features/voice/helpers.ts +251 -0
- package/src/features/voice/index.ts +11 -0
- package/src/features/voice/playing/components/VoiceIcon.tsx +38 -0
- package/src/features/voice/playing/components/VoiceTranscriptionsDropdown.tsx +251 -0
- package/src/features/voice/playing/components/VoiceTranscriptionsDropdownItem.tsx +127 -0
- package/src/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.ts +54 -0
- package/src/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.ts +40 -0
- package/src/features/voice/playing/model/Player.model.ts +104 -0
- package/src/features/voice/playing/model/TranscriptionsDownloaderModel.ts +80 -0
- package/src/features/voice/playing/model/VoiceFileDownloader.model.ts +42 -0
- package/src/features/voice/playing/model/VoicePlayer.model.ts +255 -0
- package/src/features/voice/playing/model/VoiceTranscriptionsCollection.ts +40 -0
- package/src/features/voice/playing/model/VoiceTranscriptionsDropdown.model.ts +11 -0
- package/src/features/voice/playing/model/index.ts +2 -0
- package/src/features/voice/recording/components/VoiceRecord.tsx +65 -0
- package/src/features/voice/recording/components/VoiceRecordButton.tsx +64 -0
- package/src/features/voice/recording/components/VoiceRecordDeleteButton.tsx +25 -0
- package/src/features/voice/recording/components/VoiceRecordDivider.tsx +17 -0
- package/src/features/voice/recording/components/VoiceRecordTimer.tsx +49 -0
- package/src/features/voice/recording/hooks/useVoiceRecorder.ts +62 -0
- package/src/features/voice/recording/hooks/useVoiceRecorderAnimation.ts +19 -0
- package/src/features/voice/recording/modal/ModalFooterButtons.tsx +54 -0
- package/src/features/voice/recording/modal/VoiceRecordDeleteModal.tsx +82 -0
- package/src/features/voice/recording/modal/VoiceRecordUndoModal.tsx +50 -0
- package/src/features/voice/recording/model/Recorder.model.ts +63 -0
- package/src/features/voice/recording/model/Uploader.model.ts +48 -0
- package/src/features/voice/recording/model/VoiceRecord.model.ts +302 -0
- package/src/features/voice/recording/model/VoiceRecordCollection.ts +26 -0
- package/src/features/voice/types.ts +84 -0
- package/src/index.ts +1 -0
- package/src/shared/components/PlayButton.tsx +84 -0
- package/src/shared/translation/localization/ca.json +17 -0
- package/src/shared/translation/localization/de.json +17 -0
- package/src/shared/translation/localization/en.json +17 -0
- package/src/shared/translation/localization/gb.json +17 -0
- package/src/shared/translation/localization/sct.json +17 -0
- package/src/shared/translation/localization/sw.json +17 -0
- package/src/types/common.types.ts +1 -0
- package/dist/commonjs/features/chatbot/TTS_HIGHLIGHTING.md +0 -120
- package/dist/commonjs/features/chatbot/components/Chat/CloseButton.js +0 -39
- package/dist/commonjs/features/chatbot/components/Chat/CloseButton.js.map +0 -1
- package/dist/commonjs/features/chatbot/components/ChatMessage/AnimatedMessage.js +0 -43
- package/dist/commonjs/features/chatbot/components/ChatMessage/AnimatedMessage.js.map +0 -1
- package/dist/module/features/chatbot/TTS_HIGHLIGHTING.md +0 -120
- package/dist/module/features/chatbot/components/Chat/CloseButton.js +0 -33
- package/dist/module/features/chatbot/components/Chat/CloseButton.js.map +0 -1
- package/dist/module/features/chatbot/components/ChatMessage/AnimatedMessage.js +0 -40
- package/dist/module/features/chatbot/components/ChatMessage/AnimatedMessage.js.map +0 -1
- package/dist/typescript/commonjs/features/chatbot/components/Chat/CloseButton.d.ts +0 -7
- package/dist/typescript/commonjs/features/chatbot/components/Chat/CloseButton.d.ts.map +0 -1
- package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/AnimatedMessage.d.ts +0 -7
- package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/AnimatedMessage.d.ts.map +0 -1
- package/dist/typescript/module/features/chatbot/components/Chat/CloseButton.d.ts +0 -7
- package/dist/typescript/module/features/chatbot/components/Chat/CloseButton.d.ts.map +0 -1
- package/dist/typescript/module/features/chatbot/components/ChatMessage/AnimatedMessage.d.ts +0 -7
- package/dist/typescript/module/features/chatbot/components/ChatMessage/AnimatedMessage.d.ts.map +0 -1
- package/src/features/chatbot/TTS_HIGHLIGHTING.md +0 -120
- package/src/features/chatbot/components/Chat/CloseButton.tsx +0 -31
- package/src/features/chatbot/components/ChatMessage/AnimatedMessage.tsx +0 -38
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
# TTS Word-by-Word Highlighting
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
Word-by-word text highlighting synchronized with text-to-speech playback in the chatbot. The feature is optional and enabled via `isWordHighlightEnabled` config flag.
|
|
6
|
-
|
|
7
|
-
## How It Works
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
11
|
-
│ 1. User clicks TTS button on a message │
|
|
12
|
-
│ ↓ │
|
|
13
|
-
│ 2. Text is converted to SSML with word marks │
|
|
14
|
-
│ "Hello world" → <speak><mark name="w_0"/>Hello │
|
|
15
|
-
│ <mark name="w_1"/>world</speak> │
|
|
16
|
-
│ ↓ │
|
|
17
|
-
│ 3. Google TTS API returns audio + timepoints │
|
|
18
|
-
│ [{ markName: "w_0", timeSeconds: 0.0 }, │
|
|
19
|
-
│ { markName: "w_1", timeSeconds: 0.5 }] │
|
|
20
|
-
│ ↓ │
|
|
21
|
-
│ 4. Audio plays, onTimeUpdate fires via RAF loop │
|
|
22
|
-
│ ↓ │
|
|
23
|
-
│ 5. Current time → find matching timepoint → word index │
|
|
24
|
-
│ ↓ │
|
|
25
|
-
│ 6. $highlightedWordIndex updates → UI re-renders highlighted │
|
|
26
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Usage
|
|
30
|
-
|
|
31
|
-
```tsx
|
|
32
|
-
// In students-web model setup
|
|
33
|
-
chatModel.bot.setUpT2S({
|
|
34
|
-
audioProvider: createT2SAudioProvider(),
|
|
35
|
-
textSanitizer: removeKatexPartFromTextToSpeech,
|
|
36
|
-
isWordHighlightEnabled: true,
|
|
37
|
-
})
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Architecture
|
|
41
|
-
|
|
42
|
-
### ChatTTSModel (ChatTTSModel.ts)
|
|
43
|
-
|
|
44
|
-
Handles TTS playback and word highlighting. Key design decisions:
|
|
45
|
-
|
|
46
|
-
- **Map-based cache** — `audioCache: Map<string, AudioCache>` stores both `audioPath` and `timepoints` per message. When highlighting is off, `timepoints` is `[]`. Cache lives for the model's lifetime (cleared when user leaves the problem).
|
|
47
|
-
- **`fetchAudio()` method** — encapsulates API call + audioContent decoding. Highlight vs non-highlight differences are ternaries (SSML vs plain text, `enableTimePointing`).
|
|
48
|
-
- **`play()` is linear** — cache lookup → fetch if miss → store → activate highlight if enabled → play audio. No branching between highlight/non-highlight paths.
|
|
49
|
-
- **Pause/resume guards** — `wordHighlightEnabled` check before toggling `setIsActive(false)`/`setIsActive(true)` on pause/resume.
|
|
50
|
-
- **`wordHighlightEnabled` (private)** — stored result of `!!isWordHighlightEnabled && !!audioProvider.onTimeUpdate`. Set once at `setConfig`.
|
|
51
|
-
- **`isWordHighlightEnabled` (public getter)** — read-only access for external consumers (e.g. `Chat.tsx`).
|
|
52
|
-
|
|
53
|
-
### AudioProvider type
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
type AudioProvider = {
|
|
57
|
-
play: (audioPath: string, onPlaybackComplete: () => void) => Promise<void>
|
|
58
|
-
pause: () => void
|
|
59
|
-
resume: () => void
|
|
60
|
-
stop: () => void
|
|
61
|
-
onTimeUpdate?: OnTimeUpdate // optional — presence enables highlight capability
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
`onTimeUpdate` is optional. It's the mechanism that syncs audio playback time with word highlights via a RAF loop. If the provider doesn't have it, highlighting won't activate even if `isWordHighlightEnabled: true`.
|
|
66
|
-
|
|
67
|
-
### ChatTTSHighlightModel (ChatTTSHighlightModel.ts)
|
|
68
|
-
|
|
69
|
-
Manages highlight state using Effector stores with declarative reset. Receives `OnTimeUpdate` callback directly (not the whole `AudioProvider`).
|
|
70
|
-
|
|
71
|
-
- **`$isActive`** — gates `$highlightedWordIndex` computation. Toggled on pause/resume without resetting timepoints.
|
|
72
|
-
- **`$highlightedWordIndex`** — derived store, returns `-1` when inactive or no match. Parses mark name via `WORD_MARK_REGEX`.
|
|
73
|
-
- **`activate(timepoints, onTimeUpdate)`** — sets timepoints, enables highlighting, registers time update callback. Only triggers store updates when the highlighted word actually changes (`lastMark` comparison).
|
|
74
|
-
- **`deactivate(onTimeUpdate)`** — stops listening, resets all state via declarative `.reset()` chain.
|
|
75
|
-
- **All stores use `.reset(this.reset)`** — single `reset` event clears `$time`, `$timepoints`, and `$isActive`.
|
|
76
|
-
|
|
77
|
-
### Helpers (helpers/ttsHighlight.ts)
|
|
78
|
-
|
|
79
|
-
- **`textToSSML(text)`** — converts plain text to SSML with `<mark>` tags for word timing.
|
|
80
|
-
- **`findCurrentMark(timepoints, time)`** — iterates backwards through timepoints to find the current mark. Efficient for linear playback.
|
|
81
|
-
|
|
82
|
-
### Constants (constants.ts)
|
|
83
|
-
|
|
84
|
-
- **`WORD_MARK_REGEX`** — `/^w_(\d+)$/` — extracts word index from mark names like `w_0`, `w_1`.
|
|
85
|
-
|
|
86
|
-
### Naming conventions
|
|
87
|
-
|
|
88
|
-
| Name | Scope | Purpose |
|
|
89
|
-
|------|-------|---------|
|
|
90
|
-
| `wordHighlight` | public instance | `ChatTTSHighlightModel` instance on `ChatTTSModel` |
|
|
91
|
-
| `wordHighlightEnabled` | private field | Whether highlighting is active (set once at config) |
|
|
92
|
-
| `isWordHighlightEnabled` | public getter | Read-only access to `wordHighlightEnabled` for external consumers |
|
|
93
|
-
| `isWordHighlightEnabled` | T2SConfig field | Config flag passed to `setUpT2S()` |
|
|
94
|
-
|
|
95
|
-
## Data Flow
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
-
AudioProvider.onTimeUpdate(callback)
|
|
99
|
-
↓
|
|
100
|
-
ChatTTSHighlightModel.activate(timepoints, onTimeUpdate)
|
|
101
|
-
↓
|
|
102
|
-
RAF loop → audio.currentTime → findCurrentMark() → only updates when mark changes
|
|
103
|
-
↓
|
|
104
|
-
$highlightedWordIndex = parse mark name "w_N" → N (or -1 if inactive/no match)
|
|
105
|
-
↓
|
|
106
|
-
Chat.tsx: model.t2s.isWordHighlightEnabled && isPlayingMessage ? highlightedWordIndex : -1
|
|
107
|
-
↓
|
|
108
|
-
ChatMessage → MessageContent → TTSHighlightRenderer({ text, highlightedIndex })
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## Key Files
|
|
112
|
-
|
|
113
|
-
| File | Purpose |
|
|
114
|
-
|------|---------|
|
|
115
|
-
| `model/ChatTTSModel.ts` | `ChatTTSModel` — TTS playback, caching, highlight orchestration |
|
|
116
|
-
| `model/ChatTTSHighlightModel.ts` | Highlight state — timepoints, current time, `$isActive`, derived word index |
|
|
117
|
-
| `helpers/ttsHighlight.ts` | `textToSSML` + `findCurrentMark` — SSML conversion and playback position lookup |
|
|
118
|
-
| `constants.ts` | `WORD_MARK_REGEX` and audio config defaults |
|
|
119
|
-
| `types/t2s.types.ts` | `AudioProvider`, `OnTimeUpdate`, `AudioStatus`, `AudioCache`, `TTSHighlightRendererProps` types |
|
|
120
|
-
| `components/Chat/Chat.tsx` | Reads `isWordHighlightEnabled` and `$highlightedWordIndex`, passes to messages |
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.CloseButton = void 0;
|
|
7
|
-
var _react = _interopRequireDefault(require("react"));
|
|
8
|
-
var _reactNative = require("react-native");
|
|
9
|
-
var _reactNativeUi = require("@magmamath/react-native-ui");
|
|
10
|
-
var _CloseIcon = require("../../../../shared/icons/CloseIcon.js");
|
|
11
|
-
var _jsxRuntime = require("react/jsx-runtime");
|
|
12
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
|
-
const CloseButton = ({
|
|
14
|
-
onPress
|
|
15
|
-
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeUi.Button, {
|
|
16
|
-
onPress: onPress,
|
|
17
|
-
style: {
|
|
18
|
-
button: styles.button
|
|
19
|
-
},
|
|
20
|
-
variant: _reactNativeUi.ButtonVariant.PRIMARY,
|
|
21
|
-
size: _reactNativeUi.ButtonSize.MEDIUM,
|
|
22
|
-
colorScheme: _reactNativeUi.ButtonColor.WHITE,
|
|
23
|
-
raiseLevel: 5,
|
|
24
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_CloseIcon.CloseIcon, {
|
|
25
|
-
width: 18,
|
|
26
|
-
height: 18
|
|
27
|
-
})
|
|
28
|
-
});
|
|
29
|
-
exports.CloseButton = CloseButton;
|
|
30
|
-
const styles = _reactNative.StyleSheet.create({
|
|
31
|
-
button: {
|
|
32
|
-
width: 38,
|
|
33
|
-
height: 38,
|
|
34
|
-
borderRadius: 36,
|
|
35
|
-
paddingHorizontal: 0,
|
|
36
|
-
borderColor: _reactNativeUi.COLORS.NEUTRAL_5
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
//# sourceMappingURL=CloseButton.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireDefault","require","_reactNative","_reactNativeUi","_CloseIcon","_jsxRuntime","e","__esModule","default","CloseButton","onPress","jsx","Button","style","button","styles","variant","ButtonVariant","PRIMARY","size","ButtonSize","MEDIUM","colorScheme","ButtonColor","WHITE","raiseLevel","children","CloseIcon","width","height","exports","StyleSheet","create","borderRadius","paddingHorizontal","borderColor","COLORS","NEUTRAL_5"],"sourceRoot":"../../../../../../src","sources":["features/chatbot/components/Chat/CloseButton.tsx"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AACA,IAAAE,cAAA,GAAAF,OAAA;AACA,IAAAG,UAAA,GAAAH,OAAA;AAA8D,IAAAI,WAAA,GAAAJ,OAAA;AAAA,SAAAD,uBAAAM,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAMvD,MAAMG,WAAW,GAAGA,CAAC;EAAEC;AAA0B,CAAC,kBACvD,IAAAL,WAAA,CAAAM,GAAA,EAACR,cAAA,CAAAS,MAAM;EACLF,OAAO,EAAEA,OAAQ;EACjBG,KAAK,EAAE;IAAEC,MAAM,EAAEC,MAAM,CAACD;EAAO,CAAE;EACjCE,OAAO,EAAEC,4BAAa,CAACC,OAAQ;EAC/BC,IAAI,EAAEC,yBAAU,CAACC,MAAO;EACxBC,WAAW,EAAEC,0BAAW,CAACC,KAAM;EAC/BC,UAAU,EAAE,CAAE;EAAAC,QAAA,eAEd,IAAArB,WAAA,CAAAM,GAAA,EAACP,UAAA,CAAAuB,SAAS;IAACC,KAAK,EAAE,EAAG;IAACC,MAAM,EAAE;EAAG,CAAE;AAAC,CAC9B,CACT;AAAAC,OAAA,CAAArB,WAAA,GAAAA,WAAA;AAED,MAAMM,MAAM,GAAGgB,uBAAU,CAACC,MAAM,CAAC;EAC/BlB,MAAM,EAAE;IACNc,KAAK,EAAE,EAAE;IACTC,MAAM,EAAE,EAAE;IACVI,YAAY,EAAE,EAAE;IAChBC,iBAAiB,EAAE,CAAC;IACpBC,WAAW,EAAEC,qBAAM,CAACC;EACtB;AACF,CAAC,CAAC","ignoreList":[]}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.AnimatedMessage = void 0;
|
|
7
|
-
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
-
var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
|
|
9
|
-
var _jsxRuntime = require("react/jsx-runtime");
|
|
10
|
-
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
11
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
12
|
-
const INITIAL_OFFSET = 25;
|
|
13
|
-
// const TIMING_CONFIG = { duration: 600, easing: Easing.out(Easing.cubic) }
|
|
14
|
-
const SPRING_CONFIG = {
|
|
15
|
-
mass: 1,
|
|
16
|
-
stiffness: 177,
|
|
17
|
-
damping: 20
|
|
18
|
-
};
|
|
19
|
-
const AnimatedMessage = ({
|
|
20
|
-
children,
|
|
21
|
-
animate = true
|
|
22
|
-
}) => {
|
|
23
|
-
const translateY = (0, _reactNativeReanimated.useSharedValue)(animate ? INITIAL_OFFSET : 0);
|
|
24
|
-
(0, _react.useEffect)(() => {
|
|
25
|
-
if (animate) {
|
|
26
|
-
// translateY.value = withTiming(0, TIMING_CONFIG)
|
|
27
|
-
translateY.value = (0, _reactNativeReanimated.withSpring)(0, SPRING_CONFIG);
|
|
28
|
-
}
|
|
29
|
-
}, []);
|
|
30
|
-
const animatedStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => ({
|
|
31
|
-
transform: [{
|
|
32
|
-
translateY: translateY.value
|
|
33
|
-
}]
|
|
34
|
-
}), [translateY]);
|
|
35
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
|
|
36
|
-
style: [animate && animatedStyle, {
|
|
37
|
-
alignItems: 'flex-end'
|
|
38
|
-
}],
|
|
39
|
-
children: children
|
|
40
|
-
});
|
|
41
|
-
};
|
|
42
|
-
exports.AnimatedMessage = AnimatedMessage;
|
|
43
|
-
//# sourceMappingURL=AnimatedMessage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNativeReanimated","_jsxRuntime","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","hasOwnProperty","call","i","set","INITIAL_OFFSET","SPRING_CONFIG","mass","stiffness","damping","AnimatedMessage","children","animate","translateY","useSharedValue","useEffect","value","withSpring","animatedStyle","useAnimatedStyle","transform","jsx","View","style","alignItems","exports"],"sourceRoot":"../../../../../../src","sources":["features/chatbot/components/ChatMessage/AnimatedMessage.tsx"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,sBAAA,GAAAF,uBAAA,CAAAC,OAAA;AAMgC,IAAAE,WAAA,GAAAF,OAAA;AAAA,SAAAG,yBAAAC,CAAA,6BAAAC,OAAA,mBAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,CAAA,WAAAA,CAAA,GAAAG,CAAA,GAAAD,CAAA,KAAAF,CAAA;AAAA,SAAAL,wBAAAK,CAAA,EAAAE,CAAA,SAAAA,CAAA,IAAAF,CAAA,IAAAA,CAAA,CAAAI,UAAA,SAAAJ,CAAA,eAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,WAAAK,OAAA,EAAAL,CAAA,QAAAG,CAAA,GAAAJ,wBAAA,CAAAG,CAAA,OAAAC,CAAA,IAAAA,CAAA,CAAAG,GAAA,CAAAN,CAAA,UAAAG,CAAA,CAAAI,GAAA,CAAAP,CAAA,OAAAQ,CAAA,KAAAC,SAAA,UAAAC,CAAA,GAAAC,MAAA,CAAAC,cAAA,IAAAD,MAAA,CAAAE,wBAAA,WAAAC,CAAA,IAAAd,CAAA,oBAAAc,CAAA,OAAAC,cAAA,CAAAC,IAAA,CAAAhB,CAAA,EAAAc,CAAA,SAAAG,CAAA,GAAAP,CAAA,GAAAC,MAAA,CAAAE,wBAAA,CAAAb,CAAA,EAAAc,CAAA,UAAAG,CAAA,KAAAA,CAAA,CAAAV,GAAA,IAAAU,CAAA,CAAAC,GAAA,IAAAP,MAAA,CAAAC,cAAA,CAAAJ,CAAA,EAAAM,CAAA,EAAAG,CAAA,IAAAT,CAAA,CAAAM,CAAA,IAAAd,CAAA,CAAAc,CAAA,YAAAN,CAAA,CAAAH,OAAA,GAAAL,CAAA,EAAAG,CAAA,IAAAA,CAAA,CAAAe,GAAA,CAAAlB,CAAA,EAAAQ,CAAA,GAAAA,CAAA;AAEhC,MAAMW,cAAc,GAAG,EAAE;AACzB;AACA,MAAMC,aAAa,GAAG;EAAEC,IAAI,EAAE,CAAC;EAAEC,SAAS,EAAE,GAAG;EAAEC,OAAO,EAAE;AAAG,CAAC;AAIvD,MAAMC,eAAe,GAAGA,CAAC;EAAEC,QAAQ;EAAEC,OAAO,GAAG;AAA2B,CAAC,KAAK;EACrF,MAAMC,UAAU,GAAG,IAAAC,qCAAc,EAACF,OAAO,GAAGP,cAAc,GAAG,CAAC,CAAC;EAE/D,IAAAU,gBAAS,EAAC,MAAM;IACd,IAAIH,OAAO,EAAE;MACX;MACAC,UAAU,CAACG,KAAK,GAAG,IAAAC,iCAAU,EAAC,CAAC,EAAEX,aAAa,CAAC;IACjD;EACF,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMY,aAAa,GAAG,IAAAC,uCAAgB,EACpC,OAAO;IACLC,SAAS,EAAE,CAAC;MAAEP,UAAU,EAAEA,UAAU,CAACG;IAAM,CAAC;EAC9C,CAAC,CAAC,EACF,CAACH,UAAU,CACb,CAAC;EAED,oBACE,IAAA7B,WAAA,CAAAqC,GAAA,EAACtC,sBAAA,CAAAQ,OAAQ,CAAC+B,IAAI;IAACC,KAAK,EAAE,CAACX,OAAO,IAAIM,aAAa,EAAE;MAAEM,UAAU,EAAE;IAAW,CAAC,CAAE;IAAAb,QAAA,EAC1EA;EAAQ,CACI,CAAC;AAEpB,CAAC;AAAAc,OAAA,CAAAf,eAAA,GAAAA,eAAA","ignoreList":[]}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
# TTS Word-by-Word Highlighting
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
Word-by-word text highlighting synchronized with text-to-speech playback in the chatbot. The feature is optional and enabled via `isWordHighlightEnabled` config flag.
|
|
6
|
-
|
|
7
|
-
## How It Works
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
11
|
-
│ 1. User clicks TTS button on a message │
|
|
12
|
-
│ ↓ │
|
|
13
|
-
│ 2. Text is converted to SSML with word marks │
|
|
14
|
-
│ "Hello world" → <speak><mark name="w_0"/>Hello │
|
|
15
|
-
│ <mark name="w_1"/>world</speak> │
|
|
16
|
-
│ ↓ │
|
|
17
|
-
│ 3. Google TTS API returns audio + timepoints │
|
|
18
|
-
│ [{ markName: "w_0", timeSeconds: 0.0 }, │
|
|
19
|
-
│ { markName: "w_1", timeSeconds: 0.5 }] │
|
|
20
|
-
│ ↓ │
|
|
21
|
-
│ 4. Audio plays, onTimeUpdate fires via RAF loop │
|
|
22
|
-
│ ↓ │
|
|
23
|
-
│ 5. Current time → find matching timepoint → word index │
|
|
24
|
-
│ ↓ │
|
|
25
|
-
│ 6. $highlightedWordIndex updates → UI re-renders highlighted │
|
|
26
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Usage
|
|
30
|
-
|
|
31
|
-
```tsx
|
|
32
|
-
// In students-web model setup
|
|
33
|
-
chatModel.bot.setUpT2S({
|
|
34
|
-
audioProvider: createT2SAudioProvider(),
|
|
35
|
-
textSanitizer: removeKatexPartFromTextToSpeech,
|
|
36
|
-
isWordHighlightEnabled: true,
|
|
37
|
-
})
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Architecture
|
|
41
|
-
|
|
42
|
-
### ChatTTSModel (ChatTTSModel.ts)
|
|
43
|
-
|
|
44
|
-
Handles TTS playback and word highlighting. Key design decisions:
|
|
45
|
-
|
|
46
|
-
- **Map-based cache** — `audioCache: Map<string, AudioCache>` stores both `audioPath` and `timepoints` per message. When highlighting is off, `timepoints` is `[]`. Cache lives for the model's lifetime (cleared when user leaves the problem).
|
|
47
|
-
- **`fetchAudio()` method** — encapsulates API call + audioContent decoding. Highlight vs non-highlight differences are ternaries (SSML vs plain text, `enableTimePointing`).
|
|
48
|
-
- **`play()` is linear** — cache lookup → fetch if miss → store → activate highlight if enabled → play audio. No branching between highlight/non-highlight paths.
|
|
49
|
-
- **Pause/resume guards** — `wordHighlightEnabled` check before toggling `setIsActive(false)`/`setIsActive(true)` on pause/resume.
|
|
50
|
-
- **`wordHighlightEnabled` (private)** — stored result of `!!isWordHighlightEnabled && !!audioProvider.onTimeUpdate`. Set once at `setConfig`.
|
|
51
|
-
- **`isWordHighlightEnabled` (public getter)** — read-only access for external consumers (e.g. `Chat.tsx`).
|
|
52
|
-
|
|
53
|
-
### AudioProvider type
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
type AudioProvider = {
|
|
57
|
-
play: (audioPath: string, onPlaybackComplete: () => void) => Promise<void>
|
|
58
|
-
pause: () => void
|
|
59
|
-
resume: () => void
|
|
60
|
-
stop: () => void
|
|
61
|
-
onTimeUpdate?: OnTimeUpdate // optional — presence enables highlight capability
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
`onTimeUpdate` is optional. It's the mechanism that syncs audio playback time with word highlights via a RAF loop. If the provider doesn't have it, highlighting won't activate even if `isWordHighlightEnabled: true`.
|
|
66
|
-
|
|
67
|
-
### ChatTTSHighlightModel (ChatTTSHighlightModel.ts)
|
|
68
|
-
|
|
69
|
-
Manages highlight state using Effector stores with declarative reset. Receives `OnTimeUpdate` callback directly (not the whole `AudioProvider`).
|
|
70
|
-
|
|
71
|
-
- **`$isActive`** — gates `$highlightedWordIndex` computation. Toggled on pause/resume without resetting timepoints.
|
|
72
|
-
- **`$highlightedWordIndex`** — derived store, returns `-1` when inactive or no match. Parses mark name via `WORD_MARK_REGEX`.
|
|
73
|
-
- **`activate(timepoints, onTimeUpdate)`** — sets timepoints, enables highlighting, registers time update callback. Only triggers store updates when the highlighted word actually changes (`lastMark` comparison).
|
|
74
|
-
- **`deactivate(onTimeUpdate)`** — stops listening, resets all state via declarative `.reset()` chain.
|
|
75
|
-
- **All stores use `.reset(this.reset)`** — single `reset` event clears `$time`, `$timepoints`, and `$isActive`.
|
|
76
|
-
|
|
77
|
-
### Helpers (helpers/ttsHighlight.ts)
|
|
78
|
-
|
|
79
|
-
- **`textToSSML(text)`** — converts plain text to SSML with `<mark>` tags for word timing.
|
|
80
|
-
- **`findCurrentMark(timepoints, time)`** — iterates backwards through timepoints to find the current mark. Efficient for linear playback.
|
|
81
|
-
|
|
82
|
-
### Constants (constants.ts)
|
|
83
|
-
|
|
84
|
-
- **`WORD_MARK_REGEX`** — `/^w_(\d+)$/` — extracts word index from mark names like `w_0`, `w_1`.
|
|
85
|
-
|
|
86
|
-
### Naming conventions
|
|
87
|
-
|
|
88
|
-
| Name | Scope | Purpose |
|
|
89
|
-
|------|-------|---------|
|
|
90
|
-
| `wordHighlight` | public instance | `ChatTTSHighlightModel` instance on `ChatTTSModel` |
|
|
91
|
-
| `wordHighlightEnabled` | private field | Whether highlighting is active (set once at config) |
|
|
92
|
-
| `isWordHighlightEnabled` | public getter | Read-only access to `wordHighlightEnabled` for external consumers |
|
|
93
|
-
| `isWordHighlightEnabled` | T2SConfig field | Config flag passed to `setUpT2S()` |
|
|
94
|
-
|
|
95
|
-
## Data Flow
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
-
AudioProvider.onTimeUpdate(callback)
|
|
99
|
-
↓
|
|
100
|
-
ChatTTSHighlightModel.activate(timepoints, onTimeUpdate)
|
|
101
|
-
↓
|
|
102
|
-
RAF loop → audio.currentTime → findCurrentMark() → only updates when mark changes
|
|
103
|
-
↓
|
|
104
|
-
$highlightedWordIndex = parse mark name "w_N" → N (or -1 if inactive/no match)
|
|
105
|
-
↓
|
|
106
|
-
Chat.tsx: model.t2s.isWordHighlightEnabled && isPlayingMessage ? highlightedWordIndex : -1
|
|
107
|
-
↓
|
|
108
|
-
ChatMessage → MessageContent → TTSHighlightRenderer({ text, highlightedIndex })
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## Key Files
|
|
112
|
-
|
|
113
|
-
| File | Purpose |
|
|
114
|
-
|------|---------|
|
|
115
|
-
| `model/ChatTTSModel.ts` | `ChatTTSModel` — TTS playback, caching, highlight orchestration |
|
|
116
|
-
| `model/ChatTTSHighlightModel.ts` | Highlight state — timepoints, current time, `$isActive`, derived word index |
|
|
117
|
-
| `helpers/ttsHighlight.ts` | `textToSSML` + `findCurrentMark` — SSML conversion and playback position lookup |
|
|
118
|
-
| `constants.ts` | `WORD_MARK_REGEX` and audio config defaults |
|
|
119
|
-
| `types/t2s.types.ts` | `AudioProvider`, `OnTimeUpdate`, `AudioStatus`, `AudioCache`, `TTSHighlightRendererProps` types |
|
|
120
|
-
| `components/Chat/Chat.tsx` | Reads `isWordHighlightEnabled` and `$highlightedWordIndex`, passes to messages |
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { StyleSheet } from 'react-native';
|
|
5
|
-
import { Button, ButtonColor, ButtonSize, ButtonVariant, COLORS } from '@magmamath/react-native-ui';
|
|
6
|
-
import { CloseIcon } from "../../../../shared/icons/CloseIcon.js";
|
|
7
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
-
export const CloseButton = ({
|
|
9
|
-
onPress
|
|
10
|
-
}) => /*#__PURE__*/_jsx(Button, {
|
|
11
|
-
onPress: onPress,
|
|
12
|
-
style: {
|
|
13
|
-
button: styles.button
|
|
14
|
-
},
|
|
15
|
-
variant: ButtonVariant.PRIMARY,
|
|
16
|
-
size: ButtonSize.MEDIUM,
|
|
17
|
-
colorScheme: ButtonColor.WHITE,
|
|
18
|
-
raiseLevel: 5,
|
|
19
|
-
children: /*#__PURE__*/_jsx(CloseIcon, {
|
|
20
|
-
width: 18,
|
|
21
|
-
height: 18
|
|
22
|
-
})
|
|
23
|
-
});
|
|
24
|
-
const styles = StyleSheet.create({
|
|
25
|
-
button: {
|
|
26
|
-
width: 38,
|
|
27
|
-
height: 38,
|
|
28
|
-
borderRadius: 36,
|
|
29
|
-
paddingHorizontal: 0,
|
|
30
|
-
borderColor: COLORS.NEUTRAL_5
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
//# sourceMappingURL=CloseButton.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["React","StyleSheet","Button","ButtonColor","ButtonSize","ButtonVariant","COLORS","CloseIcon","jsx","_jsx","CloseButton","onPress","style","button","styles","variant","PRIMARY","size","MEDIUM","colorScheme","WHITE","raiseLevel","children","width","height","create","borderRadius","paddingHorizontal","borderColor","NEUTRAL_5"],"sourceRoot":"../../../../../../src","sources":["features/chatbot/components/Chat/CloseButton.tsx"],"mappings":";;AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,UAAU,QAAQ,cAAc;AACzC,SAASC,MAAM,EAAEC,WAAW,EAAEC,UAAU,EAAEC,aAAa,EAAEC,MAAM,QAAQ,4BAA4B;AACnG,SAASC,SAAS,QAAQ,uCAAoC;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAM9D,OAAO,MAAMC,WAAW,GAAGA,CAAC;EAAEC;AAA0B,CAAC,kBACvDF,IAAA,CAACP,MAAM;EACLS,OAAO,EAAEA,OAAQ;EACjBC,KAAK,EAAE;IAAEC,MAAM,EAAEC,MAAM,CAACD;EAAO,CAAE;EACjCE,OAAO,EAAEV,aAAa,CAACW,OAAQ;EAC/BC,IAAI,EAAEb,UAAU,CAACc,MAAO;EACxBC,WAAW,EAAEhB,WAAW,CAACiB,KAAM;EAC/BC,UAAU,EAAE,CAAE;EAAAC,QAAA,eAEdb,IAAA,CAACF,SAAS;IAACgB,KAAK,EAAE,EAAG;IAACC,MAAM,EAAE;EAAG,CAAE;AAAC,CAC9B,CACT;AAED,MAAMV,MAAM,GAAGb,UAAU,CAACwB,MAAM,CAAC;EAC/BZ,MAAM,EAAE;IACNU,KAAK,EAAE,EAAE;IACTC,MAAM,EAAE,EAAE;IACVE,YAAY,EAAE,EAAE;IAChBC,iBAAiB,EAAE,CAAC;IACpBC,WAAW,EAAEtB,MAAM,CAACuB;EACtB;AACF,CAAC,CAAC","ignoreList":[]}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import React, { useEffect } from 'react';
|
|
4
|
-
import Animated, {
|
|
5
|
-
// Easing,
|
|
6
|
-
useAnimatedStyle, useSharedValue,
|
|
7
|
-
// withTiming,
|
|
8
|
-
withSpring } from 'react-native-reanimated';
|
|
9
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
|
-
const INITIAL_OFFSET = 25;
|
|
11
|
-
// const TIMING_CONFIG = { duration: 600, easing: Easing.out(Easing.cubic) }
|
|
12
|
-
const SPRING_CONFIG = {
|
|
13
|
-
mass: 1,
|
|
14
|
-
stiffness: 177,
|
|
15
|
-
damping: 20
|
|
16
|
-
};
|
|
17
|
-
export const AnimatedMessage = ({
|
|
18
|
-
children,
|
|
19
|
-
animate = true
|
|
20
|
-
}) => {
|
|
21
|
-
const translateY = useSharedValue(animate ? INITIAL_OFFSET : 0);
|
|
22
|
-
useEffect(() => {
|
|
23
|
-
if (animate) {
|
|
24
|
-
// translateY.value = withTiming(0, TIMING_CONFIG)
|
|
25
|
-
translateY.value = withSpring(0, SPRING_CONFIG);
|
|
26
|
-
}
|
|
27
|
-
}, []);
|
|
28
|
-
const animatedStyle = useAnimatedStyle(() => ({
|
|
29
|
-
transform: [{
|
|
30
|
-
translateY: translateY.value
|
|
31
|
-
}]
|
|
32
|
-
}), [translateY]);
|
|
33
|
-
return /*#__PURE__*/_jsx(Animated.View, {
|
|
34
|
-
style: [animate && animatedStyle, {
|
|
35
|
-
alignItems: 'flex-end'
|
|
36
|
-
}],
|
|
37
|
-
children: children
|
|
38
|
-
});
|
|
39
|
-
};
|
|
40
|
-
//# sourceMappingURL=AnimatedMessage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["React","useEffect","Animated","useAnimatedStyle","useSharedValue","withSpring","jsx","_jsx","INITIAL_OFFSET","SPRING_CONFIG","mass","stiffness","damping","AnimatedMessage","children","animate","translateY","value","animatedStyle","transform","View","style","alignItems"],"sourceRoot":"../../../../../../src","sources":["features/chatbot/components/ChatMessage/AnimatedMessage.tsx"],"mappings":";;AAAA,OAAOA,KAAK,IAAuBC,SAAS,QAAQ,OAAO;AAC3D,OAAOC,QAAQ;AACb;AACAC,gBAAgB,EAChBC,cAAc;AACd;AACAC,UAAU,QACL,yBAAyB;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAEhC,MAAMC,cAAc,GAAG,EAAE;AACzB;AACA,MAAMC,aAAa,GAAG;EAAEC,IAAI,EAAE,CAAC;EAAEC,SAAS,EAAE,GAAG;EAAEC,OAAO,EAAE;AAAG,CAAC;AAI9D,OAAO,MAAMC,eAAe,GAAGA,CAAC;EAAEC,QAAQ;EAAEC,OAAO,GAAG;AAA2B,CAAC,KAAK;EACrF,MAAMC,UAAU,GAAGZ,cAAc,CAACW,OAAO,GAAGP,cAAc,GAAG,CAAC,CAAC;EAE/DP,SAAS,CAAC,MAAM;IACd,IAAIc,OAAO,EAAE;MACX;MACAC,UAAU,CAACC,KAAK,GAAGZ,UAAU,CAAC,CAAC,EAAEI,aAAa,CAAC;IACjD;EACF,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMS,aAAa,GAAGf,gBAAgB,CACpC,OAAO;IACLgB,SAAS,EAAE,CAAC;MAAEH,UAAU,EAAEA,UAAU,CAACC;IAAM,CAAC;EAC9C,CAAC,CAAC,EACF,CAACD,UAAU,CACb,CAAC;EAED,oBACET,IAAA,CAACL,QAAQ,CAACkB,IAAI;IAACC,KAAK,EAAE,CAACN,OAAO,IAAIG,aAAa,EAAE;MAAEI,UAAU,EAAE;IAAW,CAAC,CAAE;IAAAR,QAAA,EAC1EA;EAAQ,CACI,CAAC;AAEpB,CAAC","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CloseButton.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/chatbot/components/Chat/CloseButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,KAAK,gBAAgB,GAAG;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,WAAW,gBAAiB,gBAAgB,sBAWxD,CAAA"}
|
package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/AnimatedMessage.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import React, { PropsWithChildren } from 'react';
|
|
2
|
-
type AnimatedMessageProps = PropsWithChildren<{
|
|
3
|
-
animate?: boolean;
|
|
4
|
-
}>;
|
|
5
|
-
export declare const AnimatedMessage: ({ children, animate }: AnimatedMessageProps) => React.JSX.Element;
|
|
6
|
-
export {};
|
|
7
|
-
//# sourceMappingURL=AnimatedMessage.d.ts.map
|
package/dist/typescript/commonjs/features/chatbot/components/ChatMessage/AnimatedMessage.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AnimatedMessage.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/chatbot/components/ChatMessage/AnimatedMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAAa,MAAM,OAAO,CAAA;AAa3D,KAAK,oBAAoB,GAAG,iBAAiB,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAAA;AAEpE,eAAO,MAAM,eAAe,0BAAkC,oBAAoB,sBAsBjF,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CloseButton.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/chatbot/components/Chat/CloseButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,KAAK,gBAAgB,GAAG;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,WAAW,gBAAiB,gBAAgB,sBAWxD,CAAA"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import React, { PropsWithChildren } from 'react';
|
|
2
|
-
type AnimatedMessageProps = PropsWithChildren<{
|
|
3
|
-
animate?: boolean;
|
|
4
|
-
}>;
|
|
5
|
-
export declare const AnimatedMessage: ({ children, animate }: AnimatedMessageProps) => React.JSX.Element;
|
|
6
|
-
export {};
|
|
7
|
-
//# sourceMappingURL=AnimatedMessage.d.ts.map
|
package/dist/typescript/module/features/chatbot/components/ChatMessage/AnimatedMessage.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AnimatedMessage.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/chatbot/components/ChatMessage/AnimatedMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAAa,MAAM,OAAO,CAAA;AAa3D,KAAK,oBAAoB,GAAG,iBAAiB,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAAA;AAEpE,eAAO,MAAM,eAAe,0BAAkC,oBAAoB,sBAsBjF,CAAA"}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
# TTS Word-by-Word Highlighting
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
Word-by-word text highlighting synchronized with text-to-speech playback in the chatbot. The feature is optional and enabled via `isWordHighlightEnabled` config flag.
|
|
6
|
-
|
|
7
|
-
## How It Works
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
11
|
-
│ 1. User clicks TTS button on a message │
|
|
12
|
-
│ ↓ │
|
|
13
|
-
│ 2. Text is converted to SSML with word marks │
|
|
14
|
-
│ "Hello world" → <speak><mark name="w_0"/>Hello │
|
|
15
|
-
│ <mark name="w_1"/>world</speak> │
|
|
16
|
-
│ ↓ │
|
|
17
|
-
│ 3. Google TTS API returns audio + timepoints │
|
|
18
|
-
│ [{ markName: "w_0", timeSeconds: 0.0 }, │
|
|
19
|
-
│ { markName: "w_1", timeSeconds: 0.5 }] │
|
|
20
|
-
│ ↓ │
|
|
21
|
-
│ 4. Audio plays, onTimeUpdate fires via RAF loop │
|
|
22
|
-
│ ↓ │
|
|
23
|
-
│ 5. Current time → find matching timepoint → word index │
|
|
24
|
-
│ ↓ │
|
|
25
|
-
│ 6. $highlightedWordIndex updates → UI re-renders highlighted │
|
|
26
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Usage
|
|
30
|
-
|
|
31
|
-
```tsx
|
|
32
|
-
// In students-web model setup
|
|
33
|
-
chatModel.bot.setUpT2S({
|
|
34
|
-
audioProvider: createT2SAudioProvider(),
|
|
35
|
-
textSanitizer: removeKatexPartFromTextToSpeech,
|
|
36
|
-
isWordHighlightEnabled: true,
|
|
37
|
-
})
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Architecture
|
|
41
|
-
|
|
42
|
-
### ChatTTSModel (ChatTTSModel.ts)
|
|
43
|
-
|
|
44
|
-
Handles TTS playback and word highlighting. Key design decisions:
|
|
45
|
-
|
|
46
|
-
- **Map-based cache** — `audioCache: Map<string, AudioCache>` stores both `audioPath` and `timepoints` per message. When highlighting is off, `timepoints` is `[]`. Cache lives for the model's lifetime (cleared when user leaves the problem).
|
|
47
|
-
- **`fetchAudio()` method** — encapsulates API call + audioContent decoding. Highlight vs non-highlight differences are ternaries (SSML vs plain text, `enableTimePointing`).
|
|
48
|
-
- **`play()` is linear** — cache lookup → fetch if miss → store → activate highlight if enabled → play audio. No branching between highlight/non-highlight paths.
|
|
49
|
-
- **Pause/resume guards** — `wordHighlightEnabled` check before toggling `setIsActive(false)`/`setIsActive(true)` on pause/resume.
|
|
50
|
-
- **`wordHighlightEnabled` (private)** — stored result of `!!isWordHighlightEnabled && !!audioProvider.onTimeUpdate`. Set once at `setConfig`.
|
|
51
|
-
- **`isWordHighlightEnabled` (public getter)** — read-only access for external consumers (e.g. `Chat.tsx`).
|
|
52
|
-
|
|
53
|
-
### AudioProvider type
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
type AudioProvider = {
|
|
57
|
-
play: (audioPath: string, onPlaybackComplete: () => void) => Promise<void>
|
|
58
|
-
pause: () => void
|
|
59
|
-
resume: () => void
|
|
60
|
-
stop: () => void
|
|
61
|
-
onTimeUpdate?: OnTimeUpdate // optional — presence enables highlight capability
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
`onTimeUpdate` is optional. It's the mechanism that syncs audio playback time with word highlights via a RAF loop. If the provider doesn't have it, highlighting won't activate even if `isWordHighlightEnabled: true`.
|
|
66
|
-
|
|
67
|
-
### ChatTTSHighlightModel (ChatTTSHighlightModel.ts)
|
|
68
|
-
|
|
69
|
-
Manages highlight state using Effector stores with declarative reset. Receives `OnTimeUpdate` callback directly (not the whole `AudioProvider`).
|
|
70
|
-
|
|
71
|
-
- **`$isActive`** — gates `$highlightedWordIndex` computation. Toggled on pause/resume without resetting timepoints.
|
|
72
|
-
- **`$highlightedWordIndex`** — derived store, returns `-1` when inactive or no match. Parses mark name via `WORD_MARK_REGEX`.
|
|
73
|
-
- **`activate(timepoints, onTimeUpdate)`** — sets timepoints, enables highlighting, registers time update callback. Only triggers store updates when the highlighted word actually changes (`lastMark` comparison).
|
|
74
|
-
- **`deactivate(onTimeUpdate)`** — stops listening, resets all state via declarative `.reset()` chain.
|
|
75
|
-
- **All stores use `.reset(this.reset)`** — single `reset` event clears `$time`, `$timepoints`, and `$isActive`.
|
|
76
|
-
|
|
77
|
-
### Helpers (helpers/ttsHighlight.ts)
|
|
78
|
-
|
|
79
|
-
- **`textToSSML(text)`** — converts plain text to SSML with `<mark>` tags for word timing.
|
|
80
|
-
- **`findCurrentMark(timepoints, time)`** — iterates backwards through timepoints to find the current mark. Efficient for linear playback.
|
|
81
|
-
|
|
82
|
-
### Constants (constants.ts)
|
|
83
|
-
|
|
84
|
-
- **`WORD_MARK_REGEX`** — `/^w_(\d+)$/` — extracts word index from mark names like `w_0`, `w_1`.
|
|
85
|
-
|
|
86
|
-
### Naming conventions
|
|
87
|
-
|
|
88
|
-
| Name | Scope | Purpose |
|
|
89
|
-
|------|-------|---------|
|
|
90
|
-
| `wordHighlight` | public instance | `ChatTTSHighlightModel` instance on `ChatTTSModel` |
|
|
91
|
-
| `wordHighlightEnabled` | private field | Whether highlighting is active (set once at config) |
|
|
92
|
-
| `isWordHighlightEnabled` | public getter | Read-only access to `wordHighlightEnabled` for external consumers |
|
|
93
|
-
| `isWordHighlightEnabled` | T2SConfig field | Config flag passed to `setUpT2S()` |
|
|
94
|
-
|
|
95
|
-
## Data Flow
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
-
AudioProvider.onTimeUpdate(callback)
|
|
99
|
-
↓
|
|
100
|
-
ChatTTSHighlightModel.activate(timepoints, onTimeUpdate)
|
|
101
|
-
↓
|
|
102
|
-
RAF loop → audio.currentTime → findCurrentMark() → only updates when mark changes
|
|
103
|
-
↓
|
|
104
|
-
$highlightedWordIndex = parse mark name "w_N" → N (or -1 if inactive/no match)
|
|
105
|
-
↓
|
|
106
|
-
Chat.tsx: model.t2s.isWordHighlightEnabled && isPlayingMessage ? highlightedWordIndex : -1
|
|
107
|
-
↓
|
|
108
|
-
ChatMessage → MessageContent → TTSHighlightRenderer({ text, highlightedIndex })
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## Key Files
|
|
112
|
-
|
|
113
|
-
| File | Purpose |
|
|
114
|
-
|------|---------|
|
|
115
|
-
| `model/ChatTTSModel.ts` | `ChatTTSModel` — TTS playback, caching, highlight orchestration |
|
|
116
|
-
| `model/ChatTTSHighlightModel.ts` | Highlight state — timepoints, current time, `$isActive`, derived word index |
|
|
117
|
-
| `helpers/ttsHighlight.ts` | `textToSSML` + `findCurrentMark` — SSML conversion and playback position lookup |
|
|
118
|
-
| `constants.ts` | `WORD_MARK_REGEX` and audio config defaults |
|
|
119
|
-
| `types/t2s.types.ts` | `AudioProvider`, `OnTimeUpdate`, `AudioStatus`, `AudioCache`, `TTSHighlightRendererProps` types |
|
|
120
|
-
| `components/Chat/Chat.tsx` | Reads `isWordHighlightEnabled` and `$highlightedWordIndex`, passes to messages |
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { StyleSheet } from 'react-native'
|
|
3
|
-
import { Button, ButtonColor, ButtonSize, ButtonVariant, COLORS } from '@magmamath/react-native-ui'
|
|
4
|
-
import { CloseIcon } from '../../../../shared/icons/CloseIcon'
|
|
5
|
-
|
|
6
|
-
type CloseButtonProps = {
|
|
7
|
-
onPress?: () => void
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const CloseButton = ({ onPress }: CloseButtonProps) => (
|
|
11
|
-
<Button
|
|
12
|
-
onPress={onPress}
|
|
13
|
-
style={{ button: styles.button }}
|
|
14
|
-
variant={ButtonVariant.PRIMARY}
|
|
15
|
-
size={ButtonSize.MEDIUM}
|
|
16
|
-
colorScheme={ButtonColor.WHITE}
|
|
17
|
-
raiseLevel={5}
|
|
18
|
-
>
|
|
19
|
-
<CloseIcon width={18} height={18} />
|
|
20
|
-
</Button>
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
const styles = StyleSheet.create({
|
|
24
|
-
button: {
|
|
25
|
-
width: 38,
|
|
26
|
-
height: 38,
|
|
27
|
-
borderRadius: 36,
|
|
28
|
-
paddingHorizontal: 0,
|
|
29
|
-
borderColor: COLORS.NEUTRAL_5,
|
|
30
|
-
},
|
|
31
|
-
})
|