@memori.ai/memori-react 7.5.1 → 7.6.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 +51 -0
- package/README.md +10 -2
- package/dist/components/Avatar/Avatar.d.ts +2 -0
- package/dist/components/Avatar/Avatar.js +11 -6
- package/dist/components/Avatar/Avatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +20 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +107 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controls.d.ts +26 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controls.js +59 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/controls.js.map +1 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.d.ts +30 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js +148 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js.map +1 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +15 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +77 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/loader.d.ts +5 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/loader.js +12 -0
- package/dist/components/Avatar/AvatarView/AvatarComponent/components/loader.js.map +1 -0
- package/dist/components/Avatar/AvatarView/components/avatar.d.ts +9 -0
- package/dist/components/Avatar/AvatarView/components/avatar.js +39 -0
- package/dist/components/Avatar/AvatarView/components/avatar.js.map +1 -0
- package/dist/components/Avatar/AvatarView/components/fullbodyAvatar.d.ts +2 -1
- package/dist/components/Avatar/AvatarView/components/fullbodyAvatar.js +8 -9
- package/dist/components/Avatar/AvatarView/components/fullbodyAvatar.js.map +1 -1
- package/dist/components/Avatar/AvatarView/index.d.ts +6 -1
- package/dist/components/Avatar/AvatarView/index.js +14 -84
- package/dist/components/Avatar/AvatarView/index.js.map +1 -1
- package/dist/components/Avatar/AvatarView/utils/useEyeBlink.d.ts +16 -2
- package/dist/components/Avatar/AvatarView/utils/useEyeBlink.js +62 -38
- package/dist/components/Avatar/AvatarView/utils/useEyeBlink.js.map +1 -1
- package/dist/components/Avatar/AvatarView/utils/useMouthAnimation.d.ts +16 -0
- package/dist/components/Avatar/AvatarView/utils/useMouthAnimation.js +59 -0
- package/dist/components/Avatar/AvatarView/utils/useMouthAnimation.js.map +1 -0
- package/dist/components/Avatar/AvatarView/utils/useMouthSpeaking.js +1 -1
- package/dist/components/Avatar/AvatarView/utils/useMouthSpeaking.js.map +1 -1
- package/dist/components/Avatar/AvatarView/utils/useSmile.js +1 -1
- package/dist/components/Avatar/AvatarView/utils/useSmile.js.map +1 -1
- package/dist/components/Avatar/AvatarView/utils/useViseme.d.ts +18 -0
- package/dist/components/Avatar/AvatarView/utils/useViseme.js +141 -0
- package/dist/components/Avatar/AvatarView/utils/useViseme.js.map +1 -0
- package/dist/components/Avatar/AvatarView/utils/visemeContext.d.ts +24 -0
- package/dist/components/Avatar/AvatarView/utils/visemeContext.js +157 -0
- package/dist/components/Avatar/AvatarView/utils/visemeContext.js.map +1 -0
- package/dist/components/ChatBubble/ChatBubble.js +2 -3
- package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
- package/dist/components/CompletionProviderStatus/CompletionProviderStatus.d.ts +1 -1
- package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js +24 -3
- package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.d.ts +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.js +25 -3
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/components/MemoriWidget/enhanceSSML/enhanceSSML.d.ts +4 -0
- package/dist/components/MemoriWidget/enhanceSSML/enhanceSSML.js +157 -0
- package/dist/components/MemoriWidget/enhanceSSML/enhanceSSML.js.map +1 -0
- package/dist/components/StartPanel/StartPanel.js +1 -1
- package/dist/components/StartPanel/StartPanel.js.map +1 -1
- package/dist/components/layouts/HiddenChat.d.ts +4 -0
- package/dist/components/layouts/HiddenChat.js +50 -0
- package/dist/components/layouts/HiddenChat.js.map +1 -0
- package/dist/components/layouts/ZoomedFullBody.d.ts +4 -0
- package/dist/components/layouts/ZoomedFullBody.js +8 -0
- package/dist/components/layouts/ZoomedFullBody.js.map +1 -0
- package/dist/components/layouts/ZoomedHalfBody.d.ts +4 -0
- package/dist/components/layouts/ZoomedHalfBody.js +8 -0
- package/dist/components/layouts/ZoomedHalfBody.js.map +1 -0
- package/dist/components/layouts/hidden-chat.css +184 -0
- package/dist/components/layouts/zoomed-half-body.css +3 -0
- package/dist/context/visemeContext.d.ts +27 -0
- package/dist/context/visemeContext.js +221 -0
- package/dist/context/visemeContext.js.map +1 -0
- package/dist/helpers/utils.d.ts +7 -0
- package/dist/helpers/utils.js +51 -1
- package/dist/helpers/utils.js.map +1 -1
- package/dist/index.js +20 -16
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -0
- package/esm/components/Avatar/Avatar.d.ts +2 -0
- package/esm/components/Avatar/Avatar.js +11 -6
- package/esm/components/Avatar/Avatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.d.ts +20 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js +102 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/avatarComponent.js.map +1 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controls.d.ts +26 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controls.js +56 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/controls.js.map +1 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.d.ts +30 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js +145 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.js.map +1 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.d.ts +15 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js +73 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.js.map +1 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/loader.d.ts +5 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/loader.js +9 -0
- package/esm/components/Avatar/AvatarView/AvatarComponent/components/loader.js.map +1 -0
- package/esm/components/Avatar/AvatarView/components/avatar.d.ts +9 -0
- package/esm/components/Avatar/AvatarView/components/avatar.js +35 -0
- package/esm/components/Avatar/AvatarView/components/avatar.js.map +1 -0
- package/esm/components/Avatar/AvatarView/components/fullbodyAvatar.d.ts +2 -1
- package/esm/components/Avatar/AvatarView/components/fullbodyAvatar.js +8 -9
- package/esm/components/Avatar/AvatarView/components/fullbodyAvatar.js.map +1 -1
- package/esm/components/Avatar/AvatarView/index.d.ts +6 -1
- package/esm/components/Avatar/AvatarView/index.js +15 -85
- package/esm/components/Avatar/AvatarView/index.js.map +1 -1
- package/esm/components/Avatar/AvatarView/utils/useEyeBlink.d.ts +16 -2
- package/esm/components/Avatar/AvatarView/utils/useEyeBlink.js +61 -38
- package/esm/components/Avatar/AvatarView/utils/useEyeBlink.js.map +1 -1
- package/esm/components/Avatar/AvatarView/utils/useMouthAnimation.d.ts +16 -0
- package/esm/components/Avatar/AvatarView/utils/useMouthAnimation.js +55 -0
- package/esm/components/Avatar/AvatarView/utils/useMouthAnimation.js.map +1 -0
- package/esm/components/Avatar/AvatarView/utils/useMouthSpeaking.js +1 -1
- package/esm/components/Avatar/AvatarView/utils/useMouthSpeaking.js.map +1 -1
- package/esm/components/Avatar/AvatarView/utils/useSmile.js +1 -1
- package/esm/components/Avatar/AvatarView/utils/useSmile.js.map +1 -1
- package/esm/components/Avatar/AvatarView/utils/useViseme.d.ts +18 -0
- package/esm/components/Avatar/AvatarView/utils/useViseme.js +137 -0
- package/esm/components/Avatar/AvatarView/utils/useViseme.js.map +1 -0
- package/esm/components/Avatar/AvatarView/utils/visemeContext.d.ts +24 -0
- package/esm/components/Avatar/AvatarView/utils/visemeContext.js +152 -0
- package/esm/components/Avatar/AvatarView/utils/visemeContext.js.map +1 -0
- package/esm/components/ChatBubble/ChatBubble.js +2 -3
- package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
- package/esm/components/CompletionProviderStatus/CompletionProviderStatus.d.ts +1 -1
- package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js +24 -3
- package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.d.ts +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.js +26 -4
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/components/MemoriWidget/enhanceSSML/enhanceSSML.d.ts +4 -0
- package/esm/components/MemoriWidget/enhanceSSML/enhanceSSML.js +152 -0
- package/esm/components/MemoriWidget/enhanceSSML/enhanceSSML.js.map +1 -0
- package/esm/components/StartPanel/StartPanel.js +1 -1
- package/esm/components/StartPanel/StartPanel.js.map +1 -1
- package/esm/components/layouts/HiddenChat.d.ts +4 -0
- package/esm/components/layouts/HiddenChat.js +47 -0
- package/esm/components/layouts/HiddenChat.js.map +1 -0
- package/esm/components/layouts/ZoomedFullBody.d.ts +4 -0
- package/esm/components/layouts/ZoomedFullBody.js +5 -0
- package/esm/components/layouts/ZoomedFullBody.js.map +1 -0
- package/esm/components/layouts/ZoomedHalfBody.d.ts +4 -0
- package/esm/components/layouts/ZoomedHalfBody.js +5 -0
- package/esm/components/layouts/ZoomedHalfBody.js.map +1 -0
- package/esm/components/layouts/hidden-chat.css +184 -0
- package/esm/components/layouts/zoomed-half-body.css +3 -0
- package/esm/context/visemeContext.d.ts +27 -0
- package/esm/context/visemeContext.js +216 -0
- package/esm/context/visemeContext.js.map +1 -0
- package/esm/helpers/utils.d.ts +7 -0
- package/esm/helpers/utils.js +45 -0
- package/esm/helpers/utils.js.map +1 -1
- package/esm/index.js +20 -16
- package/esm/index.js.map +1 -1
- package/esm/styles.css +1 -0
- package/package.json +2 -2
- package/src/components/Avatar/Avatar.test.tsx +28 -20
- package/src/components/Avatar/Avatar.tsx +19 -5
- package/src/components/Avatar/AvatarView/AvatarComponent/avatarComponent.tsx +222 -0
- package/src/components/Avatar/AvatarView/{components → AvatarComponent/components}/controls.tsx +16 -10
- package/src/components/Avatar/AvatarView/AvatarComponent/components/fullbodyAvatar.tsx +234 -0
- package/src/components/Avatar/AvatarView/AvatarComponent/components/halfbodyAvatar.tsx +123 -0
- package/src/components/Avatar/AvatarView/{components → AvatarComponent/components}/loader.tsx +1 -1
- package/src/components/Avatar/AvatarView/AvatarView.stories.tsx +47 -8
- package/src/components/Avatar/AvatarView/index.tsx +35 -167
- package/src/components/Avatar/AvatarView/utils/useEyeBlink.ts +89 -48
- package/src/components/Avatar/AvatarView/utils/useMouthAnimation.ts +93 -0
- package/src/components/Avatar/AvatarView/utils/useSmile.ts +1 -1
- package/src/components/ChatBubble/ChatBubble.tsx +3 -4
- package/src/components/CompletionProviderStatus/CompletionProviderStatus.tsx +33 -3
- package/src/components/CompletionProviderStatus/__snapshots__/CompletionProviderStatus.test.tsx.snap +18 -0
- package/src/components/MemoriWidget/MemoriWidget.tsx +60 -5
- package/src/components/StartPanel/StartPanel.tsx +1 -1
- package/src/components/layouts/Chat.test.tsx +7 -5
- package/src/components/layouts/FullPage.test.tsx +11 -8
- package/src/components/layouts/HiddenChat.test.tsx +37 -0
- package/src/components/layouts/HiddenChat.tsx +107 -0
- package/src/components/layouts/Totem.test.tsx +6 -4
- package/src/components/layouts/WebsiteAssistant.test.tsx +7 -5
- package/src/components/layouts/ZoomedFullBody.test.tsx +37 -0
- package/src/components/layouts/ZoomedFullBody.tsx +55 -0
- package/src/components/layouts/__snapshots__/HiddenChat.test.tsx.snap +210 -0
- package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +444 -0
- package/src/components/layouts/hidden-chat.css +184 -0
- package/src/components/layouts/layouts.stories.tsx +135 -19
- package/src/context/visemeContext.tsx +328 -0
- package/src/helpers/utils.ts +73 -0
- package/src/index.stories.tsx +40 -17
- package/src/index.tsx +82 -78
- package/src/styles.css +1 -0
- package/dist/components/AttachmentMediaModal/AttachmentMediaModal.d.ts +0 -14
- package/dist/components/AttachmentMediaModal/AttachmentMediaModal.js +0 -66
- package/dist/components/AttachmentMediaModal/AttachmentMediaModal.js.map +0 -1
- package/dist/components/ImageUpload/ImageUpload.css +0 -168
- package/dist/components/ImageUpload/ImageUpload.d.ts +0 -28
- package/dist/components/ImageUpload/ImageUpload.js +0 -163
- package/dist/components/ImageUpload/ImageUpload.js.map +0 -1
- package/dist/components/layouts/Default.d.ts +0 -17
- package/dist/components/layouts/Default.js +0 -8
- package/dist/components/layouts/Default.js.map +0 -1
- package/dist/components/ui/Message.d.ts +0 -17
- package/dist/components/ui/Message.js +0 -13
- package/dist/components/ui/Message.js.map +0 -1
- package/esm/components/AttachmentMediaModal/AttachmentMediaModal.d.ts +0 -14
- package/esm/components/AttachmentMediaModal/AttachmentMediaModal.js +0 -63
- package/esm/components/AttachmentMediaModal/AttachmentMediaModal.js.map +0 -1
- package/esm/components/ImageUpload/ImageUpload.css +0 -168
- package/esm/components/ImageUpload/ImageUpload.d.ts +0 -28
- package/esm/components/ImageUpload/ImageUpload.js +0 -160
- package/esm/components/ImageUpload/ImageUpload.js.map +0 -1
- package/esm/components/layouts/Default.d.ts +0 -17
- package/esm/components/layouts/Default.js +0 -5
- package/esm/components/layouts/Default.js.map +0 -1
- package/esm/components/ui/Message.d.ts +0 -17
- package/esm/components/ui/Message.js +0 -10
- package/esm/components/ui/Message.js.map +0 -1
- package/src/components/Avatar/AvatarView/components/fullbodyAvatar.tsx +0 -120
- package/src/components/Avatar/AvatarView/components/halfbodyAvatar.tsx +0 -69
- package/src/components/Avatar/AvatarView/utils/useMouthSpeaking.ts +0 -87
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
.memori-sidebar-container {
|
|
2
|
+
position: fixed;
|
|
3
|
+
z-index: 1000;
|
|
4
|
+
top: 0;
|
|
5
|
+
right: 0;
|
|
6
|
+
height: 100%;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.memori-sidebar-toggle {
|
|
10
|
+
display: none;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.memori-sidebar-toggle-label {
|
|
14
|
+
position: absolute;
|
|
15
|
+
top: 50%;
|
|
16
|
+
right: 0;
|
|
17
|
+
display: flex;
|
|
18
|
+
width: auto;
|
|
19
|
+
height: 80px;
|
|
20
|
+
align-items: center;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
padding: 10px 5px;
|
|
23
|
+
background-color: var(--memori-primary);
|
|
24
|
+
color: white;
|
|
25
|
+
cursor: pointer;
|
|
26
|
+
font-size: 18px;
|
|
27
|
+
font-weight: bold;
|
|
28
|
+
text-orientation: mixed;
|
|
29
|
+
transform: translateY(-50%);
|
|
30
|
+
transition: all 0.3s ease-in-out;
|
|
31
|
+
writing-mode: vertical-rl;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.memori-open-label {
|
|
35
|
+
border-radius: 5px 0 0 5px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.memori-close-label {
|
|
39
|
+
right: 350px;
|
|
40
|
+
border-radius: 0 5px 5px 0;
|
|
41
|
+
opacity: 0;
|
|
42
|
+
pointer-events: none;
|
|
43
|
+
transform: rotate(180deg);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.memori-sidebar {
|
|
47
|
+
position: fixed;
|
|
48
|
+
z-index: 1000;
|
|
49
|
+
top: 0;
|
|
50
|
+
right: -350px;
|
|
51
|
+
width: 350px;
|
|
52
|
+
height: 100%;
|
|
53
|
+
background-color: white;
|
|
54
|
+
box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1);
|
|
55
|
+
transition: right 0.3s ease-in-out;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.memori-sidebar-content h2 {
|
|
59
|
+
margin-bottom: 20px;
|
|
60
|
+
color: var(--memori-primary);
|
|
61
|
+
font-size: 24px;
|
|
62
|
+
font-weight: bold;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.memori-sidebar-content ul {
|
|
66
|
+
padding: 0;
|
|
67
|
+
list-style-type: none;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.memori-sidebar-content li {
|
|
71
|
+
margin-bottom: 10px;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.memori-sidebar-content a {
|
|
75
|
+
display: flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
color: #4b5563;
|
|
78
|
+
text-decoration: none;
|
|
79
|
+
transition: color 0.2s ease-in-out;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.memori-sidebar-content a:hover {
|
|
83
|
+
color: var(--memori-primary);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.memori-sidebar-content svg {
|
|
87
|
+
width: 20px;
|
|
88
|
+
height: 20px;
|
|
89
|
+
margin-right: 10px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.memori-sidebar-toggle:checked ~ .memori-sidebar-container .memori-sidebar {
|
|
93
|
+
right: 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.memori-sidebar-toggle:checked ~ .memori-sidebar-container .memori-open-label {
|
|
97
|
+
opacity: 0;
|
|
98
|
+
pointer-events: none;
|
|
99
|
+
transform: translateY(-50%) translateX(350px);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.memori-loading {
|
|
103
|
+
display: flex;
|
|
104
|
+
height: 100%;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: center;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
.memori-sidebar-content {
|
|
111
|
+
position: absolute;
|
|
112
|
+
top: -10px;
|
|
113
|
+
width: 100%;
|
|
114
|
+
padding: 20px;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.memori-sidebar-toggle:checked ~ .memori-sidebar-container .memori-close-label {
|
|
118
|
+
opacity: 1;
|
|
119
|
+
pointer-events: auto;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.memori-hidden-chat-layout--controls {
|
|
123
|
+
display: flex;
|
|
124
|
+
height: 90%;
|
|
125
|
+
padding: 10px;
|
|
126
|
+
margin-top: 50px;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.memori-hidden-chat-layout-header--layout {
|
|
130
|
+
display: flex;
|
|
131
|
+
width: 100%;
|
|
132
|
+
align-items: center;
|
|
133
|
+
justify-content: flex-end;
|
|
134
|
+
padding: 10px;
|
|
135
|
+
margin: 0;
|
|
136
|
+
background-color: white;
|
|
137
|
+
color: white;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.memori-hidden-chat-layout-header--layout > button, .memori-hidden-chat-layout-header--layout > div > button {
|
|
141
|
+
display: flex;
|
|
142
|
+
width: 38px;
|
|
143
|
+
height: 38px;
|
|
144
|
+
align-items: center;
|
|
145
|
+
justify-content: center;
|
|
146
|
+
border-radius: 50%;
|
|
147
|
+
aspect-ratio: 1;
|
|
148
|
+
background-color: var(--memori-primary);
|
|
149
|
+
cursor: pointer;
|
|
150
|
+
transition: background-color 0.3s ease-in-out;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.memori-button--icon > svg {
|
|
154
|
+
margin: 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.memori-icon,.memori-icon-close {
|
|
158
|
+
width: 25px;
|
|
159
|
+
height: 25px;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.memori-icon-close{
|
|
163
|
+
fill: white;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@media (max-width: 768px) {
|
|
168
|
+
.memori-sidebar-container {
|
|
169
|
+
display: none;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.memori-sidebar {
|
|
173
|
+
right: -100%;
|
|
174
|
+
width: 100%;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.memori-sidebar-toggle:checked ~ .memori-sidebar-container .memori-open-label {
|
|
178
|
+
transform: translateY(-50%) translateX(100%);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.memori-close-label {
|
|
182
|
+
right: 100%;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -4,6 +4,7 @@ import { memori, tenant, integration } from '../../mocks/data';
|
|
|
4
4
|
import Memori, { LayoutProps, Props } from '../MemoriWidget/MemoriWidget';
|
|
5
5
|
import I18nWrapper from '../../I18nWrapper';
|
|
6
6
|
import Spin from '../ui/Spin';
|
|
7
|
+
import { VisemeProvider } from '../../context/visemeContext';
|
|
7
8
|
|
|
8
9
|
const meta: Meta = {
|
|
9
10
|
title: 'General/Layouts',
|
|
@@ -62,7 +63,9 @@ export const CustomLayout: React.FC<LayoutProps> = ({
|
|
|
62
63
|
|
|
63
64
|
const Template: Story<Props> = args => (
|
|
64
65
|
<I18nWrapper>
|
|
65
|
-
<
|
|
66
|
+
<VisemeProvider>
|
|
67
|
+
<Memori {...args} />
|
|
68
|
+
</VisemeProvider>
|
|
66
69
|
</I18nWrapper>
|
|
67
70
|
);
|
|
68
71
|
// By passing using the Args format for exported stories, you can control the props for a component for reuse in a test
|
|
@@ -197,8 +200,20 @@ ChatOnly.args = {
|
|
|
197
200
|
layout: 'CHAT',
|
|
198
201
|
};
|
|
199
202
|
|
|
200
|
-
|
|
201
|
-
|
|
203
|
+
|
|
204
|
+
export const Custom = Template.bind({});
|
|
205
|
+
Custom.args = {
|
|
206
|
+
uiLang: 'it',
|
|
207
|
+
showShare: true,
|
|
208
|
+
showSettings: true,
|
|
209
|
+
memori,
|
|
210
|
+
tenant,
|
|
211
|
+
layout: 'FULLPAGE',
|
|
212
|
+
customLayout: CustomLayout,
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
export const WebsiteAssistant = Template.bind({});
|
|
216
|
+
WebsiteAssistant.args = {
|
|
202
217
|
uiLang: 'it',
|
|
203
218
|
showShare: true,
|
|
204
219
|
showSettings: true,
|
|
@@ -303,25 +318,16 @@ Totem.args = {
|
|
|
303
318
|
}),
|
|
304
319
|
},
|
|
305
320
|
tenant,
|
|
306
|
-
layout: '
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
export const Custom = Template.bind({});
|
|
310
|
-
Custom.args = {
|
|
311
|
-
uiLang: 'it',
|
|
312
|
-
showShare: true,
|
|
313
|
-
showSettings: true,
|
|
314
|
-
memori,
|
|
315
|
-
tenant,
|
|
316
|
-
layout: 'FULLPAGE',
|
|
317
|
-
customLayout: CustomLayout,
|
|
321
|
+
layout: 'WEBSITE_ASSISTANT',
|
|
318
322
|
};
|
|
319
323
|
|
|
320
|
-
export const
|
|
321
|
-
|
|
324
|
+
export const HiddenChat = Template.bind({});
|
|
325
|
+
HiddenChat.args = {
|
|
322
326
|
uiLang: 'it',
|
|
323
327
|
showShare: true,
|
|
324
328
|
showSettings: true,
|
|
329
|
+
// memori,
|
|
330
|
+
// tenant,
|
|
325
331
|
memori: {
|
|
326
332
|
memoriID: '6573844d-a7cd-47ef-9e78-840d82020c21',
|
|
327
333
|
name: 'Nicola',
|
|
@@ -422,6 +428,116 @@ WebsiteAssistant.args = {
|
|
|
422
428
|
new Date(Date.now()).getTime(),
|
|
423
429
|
}),
|
|
424
430
|
},
|
|
425
|
-
|
|
426
|
-
|
|
431
|
+
layout: 'HIDDEN_CHAT',
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
export const ZoomedFullBody = Template.bind({});
|
|
436
|
+
ZoomedFullBody.args = {
|
|
437
|
+
uiLang: 'it',
|
|
438
|
+
showShare: true,
|
|
439
|
+
showSettings: true,
|
|
440
|
+
showAudio: true,
|
|
441
|
+
enableAudio: true,
|
|
442
|
+
memori: {
|
|
443
|
+
memoriID: '6573844d-a7cd-47ef-9e78-840d82020c21',
|
|
444
|
+
name: 'Nicola',
|
|
445
|
+
password: null,
|
|
446
|
+
recoveryTokens: null,
|
|
447
|
+
newPassword: null,
|
|
448
|
+
ownerUserID: null,
|
|
449
|
+
ownerUserName: 'nzambello',
|
|
450
|
+
ownerTenantName: 'aisuru.com',
|
|
451
|
+
memoriConfigurationID: 'fd10bb42-98d9-4c08-8e02-2b08bd4e4975',
|
|
452
|
+
description:
|
|
453
|
+
'Sono Nicola Zambello, sviluppatore e attivista per un web etico e sostenibile',
|
|
454
|
+
completionDescription: null,
|
|
455
|
+
engineMemoriID: '9b0a2913-d3d8-4e98-a49d-6e1c99479e1b',
|
|
456
|
+
isOwner: false,
|
|
457
|
+
isGiver: false,
|
|
458
|
+
isReceiver: false,
|
|
459
|
+
giverTag: null,
|
|
460
|
+
giverPIN: null,
|
|
461
|
+
privacyType: 'PUBLIC',
|
|
462
|
+
enableAudio: true,
|
|
463
|
+
secretToken: null,
|
|
464
|
+
minimumNumberOfRecoveryTokens: null,
|
|
465
|
+
totalNumberOfRecoveryTokens: null,
|
|
466
|
+
sentInvitations: [],
|
|
467
|
+
receivedInvitations: [],
|
|
468
|
+
integrations: [
|
|
469
|
+
{
|
|
470
|
+
integrationID: '62de8c99-0ac2-4cbe-bd95-a39ad7dc6b32',
|
|
471
|
+
memoriID: '6573844d-a7cd-47ef-9e78-840d82020c21',
|
|
472
|
+
type: 'LANDING_EXPERIENCE',
|
|
473
|
+
state: 'NEW',
|
|
474
|
+
deviceEmails: null,
|
|
475
|
+
invocationText: null,
|
|
476
|
+
jobID: null,
|
|
477
|
+
customData:
|
|
478
|
+
'{"textColor":"#000000","buttonBgColor":"#007eb6","buttonTextColor":"#ffffff","globalBackground":"https://assets.memori.ai/api/v2/asset/cade3b9c-0437-4342-b2bd-8db9c2a3a20e.png","blurBackground":true,"innerBgColor":"light","multilanguage":true,"avatar":"readyplayerme","avatarURL":"https://assets.memori.ai/api/v2/asset/893c41df-7619-436d-9e86-fe1d406fc933.glb#1681736752156","name":"Pagina pubblica","contextVars":"ANIMALE:CANE","personTag":"☠️","personPIN":"666666","personName":"Pirata","showShare":true,"avatarFullBodyURL":"https://models.readyplayer.me/63b55751f17e295642bf07a2.glb"}',
|
|
479
|
+
resources: [],
|
|
480
|
+
publish: true,
|
|
481
|
+
creationTimestamp: '2022-06-13T14:44:52.833573Z',
|
|
482
|
+
lastChangeTimestamp: '2022-06-13T14:44:52.833573Z',
|
|
483
|
+
},
|
|
484
|
+
],
|
|
485
|
+
avatarURL:
|
|
486
|
+
'https://assets.memori.ai/api/v2/asset/3049582f-db5f-452c-913d-e4340d4afd0a.png',
|
|
487
|
+
coverURL:
|
|
488
|
+
'https://assets.memori.ai/api/v2/asset/e9bb9f6d-8f34-45ab-af9e-6d630d9a51a8.png',
|
|
489
|
+
avatar3DURL:
|
|
490
|
+
'https://assets.memori.ai/api/v2/asset/3932bf70-e953-4e8a-b63a-f316544c283e.glb',
|
|
491
|
+
avatarOriginal3DURL:
|
|
492
|
+
'https://assets.memori.ai/api/v2/asset/3932bf70-e953-4e8a-b63a-f316544c283e.glb',
|
|
493
|
+
needsPosition: false,
|
|
494
|
+
voiceType: 'FEMALE',
|
|
495
|
+
culture: 'it-IT',
|
|
496
|
+
categories: [
|
|
497
|
+
'biografico',
|
|
498
|
+
'tecnologia',
|
|
499
|
+
'web',
|
|
500
|
+
'open-source',
|
|
501
|
+
'green',
|
|
502
|
+
'privacy',
|
|
503
|
+
],
|
|
504
|
+
exposed: true,
|
|
505
|
+
disableR2R3Loop: null,
|
|
506
|
+
disableR4Loop: null,
|
|
507
|
+
disableR5Loop: null,
|
|
508
|
+
enableCompletions: true,
|
|
509
|
+
completionModel: null,
|
|
510
|
+
chainingMemoriID: null,
|
|
511
|
+
chainingBaseURL: null,
|
|
512
|
+
chainingPassword: null,
|
|
513
|
+
contentQualityIndex: 210.8,
|
|
514
|
+
contentQualityIndexTimestamp: '2023-04-17T00:01:32.194744Z',
|
|
515
|
+
publishedInTheMetaverse: true,
|
|
516
|
+
metaverseEnvironment: 'apartment',
|
|
517
|
+
blockedUntil: null,
|
|
518
|
+
creationTimestamp: '2022-06-13T14:21:55.793034Z',
|
|
519
|
+
lastChangeTimestamp: '2023-04-15T08:15:36.403546Z',
|
|
520
|
+
},
|
|
521
|
+
integration: {
|
|
522
|
+
integrationID: '62de8c99-0ac2-4cbe-bd95-a39ad7dc6b32',
|
|
523
|
+
memoriID: '6573844d-a7cd-47ef-9e78-840d82020c21',
|
|
524
|
+
type: 'LANDING_EXPERIENCE',
|
|
525
|
+
state: 'NEW',
|
|
526
|
+
deviceEmails: null,
|
|
527
|
+
invocationText: null,
|
|
528
|
+
jobID: null,
|
|
529
|
+
publish: true,
|
|
530
|
+
creationTimestamp: '2022-06-13T14:44:52.833573Z',
|
|
531
|
+
lastChangeTimestamp: '2022-06-13T14:44:52.833573Z',
|
|
532
|
+
customData: JSON.stringify({
|
|
533
|
+
...JSON.parse(
|
|
534
|
+
'{"textColor":"#000000","buttonBgColor":"#007eb6","buttonTextColor":"#ffffff","globalBackground":"https://assets.memori.ai/api/v2/asset/cade3b9c-0437-4342-b2bd-8db9c2a3a20e.png","blurBackground":true,"innerBgColor":"light","multilanguage":true,"avatar":"readyplayerme","avatarURL":"https://assets.memori.ai/api/v2/asset/893c41df-7619-436d-9e86-fe1d406fc933.glb#1681736752156","name":"Pagina pubblica","contextVars":"ANIMALE:CANE","personTag":"☠️","personPIN":"666666","personName":"Pirata","showShare":true,"avatarFullBodyURL":"https://models.readyplayer.me/63b55751f17e295642bf07a2.glb"}'
|
|
535
|
+
),
|
|
536
|
+
avatar: 'readyplayerme-full',
|
|
537
|
+
avatarURL:
|
|
538
|
+
'https://assets.memori.ai/api/v2/asset/3932bf70-e953-4e8a-b63a-f316544c283e.glb'+
|
|
539
|
+
new Date(Date.now()).getTime(),
|
|
540
|
+
}),
|
|
541
|
+
},
|
|
542
|
+
layout: 'ZOOMED_FULL_BODY',
|
|
427
543
|
};
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
useContext,
|
|
4
|
+
useState,
|
|
5
|
+
useCallback,
|
|
6
|
+
useRef,
|
|
7
|
+
useEffect,
|
|
8
|
+
} from 'react';
|
|
9
|
+
import { SkinnedMesh } from 'three';
|
|
10
|
+
|
|
11
|
+
type AzureViseme = { visemeId: number; audioOffset: number };
|
|
12
|
+
|
|
13
|
+
type ProcessedViseme = {
|
|
14
|
+
name: string;
|
|
15
|
+
duration: number;
|
|
16
|
+
weight: number;
|
|
17
|
+
startTime: number;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
interface VisemeContextType {
|
|
21
|
+
setMeshRef: (mesh: SkinnedMesh | null) => void;
|
|
22
|
+
addVisemeToQueue: (viseme: AzureViseme) => void;
|
|
23
|
+
processVisemeQueue: () => ProcessedViseme[];
|
|
24
|
+
clearVisemes: () => void;
|
|
25
|
+
isMeshSet: boolean;
|
|
26
|
+
setEmotion: (emotion: string) => void;
|
|
27
|
+
emotion: string;
|
|
28
|
+
getAzureStyleForEmotion: (emotion: string) => string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const VisemeContext = createContext<VisemeContextType | undefined>(undefined);
|
|
32
|
+
|
|
33
|
+
const VISEME_SMOOTHING = 0.5;
|
|
34
|
+
const DEFAULT_VISEME_DURATION = 0.1;
|
|
35
|
+
const MINIMUM_ELAPSED_TIME = 0.01;
|
|
36
|
+
const VISEME_SPEED_FACTOR = 1.0;
|
|
37
|
+
const AUDIO_PLAYBACK_RATE = 1.0;
|
|
38
|
+
const VISEME_BASE_SPEED = 1.0;
|
|
39
|
+
|
|
40
|
+
const VISEME_MAP: { [key: number]: string } = {
|
|
41
|
+
0: 'viseme_sil', // silence
|
|
42
|
+
1: 'viseme_PP', // p, b, m
|
|
43
|
+
2: 'viseme_FF', // f, v
|
|
44
|
+
3: 'viseme_TH', // th, dh
|
|
45
|
+
4: 'viseme_DD', // t, d, n, l
|
|
46
|
+
5: 'viseme_kk', // k, g, ng
|
|
47
|
+
6: 'viseme_CH', // tS, dZ, S, Z
|
|
48
|
+
7: 'viseme_SS', // s, z
|
|
49
|
+
8: 'viseme_nn', // Not explicitly defined in Azure mapping, keeping for compatibility
|
|
50
|
+
9: 'viseme_RR', // r
|
|
51
|
+
10: 'viseme_aa', // A:
|
|
52
|
+
11: 'viseme_E', // e
|
|
53
|
+
12: 'viseme_I', // I
|
|
54
|
+
13: 'viseme_O', // O
|
|
55
|
+
14: 'viseme_U', // u
|
|
56
|
+
// Mapping the rest based on closest matches or keeping them as in the original mapping
|
|
57
|
+
15: 'viseme_kk', // g, k (same as 5)
|
|
58
|
+
16: 'viseme_CH', // ch, j, sh, zh (same as 6)
|
|
59
|
+
17: 'viseme_SS', // s, z (same as 7)
|
|
60
|
+
18: 'viseme_TH', // th, dh (same as 3)
|
|
61
|
+
19: 'viseme_RR', // r (same as 9)
|
|
62
|
+
20: 'viseme_kk', // w (closest match, could be debated)
|
|
63
|
+
21: 'viseme_PP', // y (closest match, could be debated)
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const VisemeProvider: React.FC<{ children: React.ReactNode }> = ({
|
|
67
|
+
children,
|
|
68
|
+
}) => {
|
|
69
|
+
const [isMeshSet, setIsMeshSet] = useState(false);
|
|
70
|
+
const [emotion, setEmotion] = useState('Neutral');
|
|
71
|
+
const isAnimatingRef = useRef(false);
|
|
72
|
+
const currentVisemesRef = useRef<ProcessedViseme[]>([]);
|
|
73
|
+
const visemeQueueRef = useRef<AzureViseme[]>([]);
|
|
74
|
+
const animationFrameRef = useRef<number | null>(null);
|
|
75
|
+
const startTimeRef = useRef<number | null>(null);
|
|
76
|
+
const currentVisemeWeightRef = useRef<{ [key: string]: number }>({});
|
|
77
|
+
const meshRef = useRef<SkinnedMesh | null>(null);
|
|
78
|
+
|
|
79
|
+
const lerp = (start: number, end: number, alpha: number): number => {
|
|
80
|
+
return start * (1 - alpha) + end * alpha;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const easeInOutCubic = (x: number): number => {
|
|
84
|
+
return x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const setMeshRef = useCallback(
|
|
88
|
+
(mesh: SkinnedMesh | null) => {
|
|
89
|
+
if (mesh && mesh.morphTargetDictionary && mesh.morphTargetInfluences) {
|
|
90
|
+
meshRef.current = mesh;
|
|
91
|
+
setIsMeshSet(true);
|
|
92
|
+
// console.log('Mesh set successfully:', mesh);
|
|
93
|
+
} else {
|
|
94
|
+
console.error('Invalid mesh provided:', mesh);
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
[meshRef]
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const addVisemeToQueue = useCallback((viseme: AzureViseme) => {
|
|
101
|
+
visemeQueueRef.current.push(viseme);
|
|
102
|
+
// console.log('Viseme added to queue:', viseme);
|
|
103
|
+
}, []);
|
|
104
|
+
|
|
105
|
+
const getCurrentViseme = useCallback((elapsedTime: number) => {
|
|
106
|
+
if (elapsedTime < MINIMUM_ELAPSED_TIME) return null;
|
|
107
|
+
|
|
108
|
+
return currentVisemesRef.current.find((viseme, index) => {
|
|
109
|
+
const nextViseme = currentVisemesRef.current[index + 1];
|
|
110
|
+
return (
|
|
111
|
+
elapsedTime >= viseme.startTime &&
|
|
112
|
+
(!nextViseme || elapsedTime < nextViseme.startTime)
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
}, []);
|
|
116
|
+
|
|
117
|
+
const getDynamicSpeedFactor = (visemeDuration: number): number => {
|
|
118
|
+
const baseDuration = 0.1; // Average expected viseme duration
|
|
119
|
+
return (
|
|
120
|
+
VISEME_BASE_SPEED * (baseDuration / visemeDuration) * AUDIO_PLAYBACK_RATE
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const applyViseme = useCallback(
|
|
125
|
+
(viseme: ProcessedViseme, elapsedTime: number) => {
|
|
126
|
+
if (!meshRef.current) {
|
|
127
|
+
console.error('Mesh not set');
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const visemeProgress = Math.min(
|
|
132
|
+
(elapsedTime - viseme.startTime) / viseme.duration,
|
|
133
|
+
1
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const dynamicSpeedFactor = getDynamicSpeedFactor(viseme.duration);
|
|
137
|
+
const adjustedProgress = visemeProgress * dynamicSpeedFactor;
|
|
138
|
+
|
|
139
|
+
// Use a cubic easing function for smoother transitions
|
|
140
|
+
const easedProgress = easeInOutCubic(adjustedProgress);
|
|
141
|
+
const targetWeight = Math.sin(easedProgress * Math.PI) * viseme.weight;
|
|
142
|
+
|
|
143
|
+
currentVisemeWeightRef.current[viseme.name] = lerp(
|
|
144
|
+
currentVisemeWeightRef.current[viseme.name] || 0,
|
|
145
|
+
targetWeight,
|
|
146
|
+
VISEME_SMOOTHING
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
const visemeIndex = meshRef.current.morphTargetDictionary?.[viseme.name];
|
|
150
|
+
if (
|
|
151
|
+
typeof visemeIndex === 'number' &&
|
|
152
|
+
meshRef.current.morphTargetInfluences
|
|
153
|
+
) {
|
|
154
|
+
meshRef.current.morphTargetInfluences[visemeIndex] =
|
|
155
|
+
currentVisemeWeightRef.current[viseme.name];
|
|
156
|
+
// console.log(`Applied viseme: ${viseme.name}, weight: ${currentVisemeWeightRef.current[viseme.name]}`);
|
|
157
|
+
} else {
|
|
158
|
+
console.error(
|
|
159
|
+
`Viseme not found in morph target dictionary: ${viseme.name}`
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
[]
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const animate = useCallback(
|
|
167
|
+
(time: number) => {
|
|
168
|
+
if (startTimeRef.current === null) {
|
|
169
|
+
startTimeRef.current = time;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const elapsedTime =
|
|
173
|
+
((time - startTimeRef.current) / 1000) * VISEME_SPEED_FACTOR;
|
|
174
|
+
|
|
175
|
+
const currentViseme = getCurrentViseme(elapsedTime);
|
|
176
|
+
|
|
177
|
+
if (currentViseme) {
|
|
178
|
+
applyViseme(currentViseme, elapsedTime);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (
|
|
182
|
+
currentVisemesRef.current.length > 0 &&
|
|
183
|
+
elapsedTime <
|
|
184
|
+
currentVisemesRef.current[currentVisemesRef.current.length - 1]
|
|
185
|
+
.startTime +
|
|
186
|
+
currentVisemesRef.current[currentVisemesRef.current.length - 1]
|
|
187
|
+
.duration
|
|
188
|
+
) {
|
|
189
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
190
|
+
} else {
|
|
191
|
+
clearVisemes();
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
[getCurrentViseme, applyViseme]
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
const processVisemeQueue = useCallback(() => {
|
|
198
|
+
const azureVisemes = [...visemeQueueRef.current];
|
|
199
|
+
visemeQueueRef.current = [];
|
|
200
|
+
|
|
201
|
+
if (azureVisemes.length === 0) {
|
|
202
|
+
// console.log('No visemes to process');
|
|
203
|
+
return [];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const processedVisemes: ProcessedViseme[] = azureVisemes.map(
|
|
207
|
+
(currentViseme, i) => {
|
|
208
|
+
const nextViseme = azureVisemes[i + 1];
|
|
209
|
+
const duration = nextViseme
|
|
210
|
+
? (nextViseme.audioOffset - currentViseme.audioOffset) / 10000000
|
|
211
|
+
: DEFAULT_VISEME_DURATION;
|
|
212
|
+
|
|
213
|
+
const processedViseme = {
|
|
214
|
+
name: VISEME_MAP[currentViseme.visemeId] || 'viseme_sil',
|
|
215
|
+
duration,
|
|
216
|
+
weight: 1,
|
|
217
|
+
startTime: currentViseme.audioOffset / 10000000,
|
|
218
|
+
};
|
|
219
|
+
//console.log('Processed viseme:', processedViseme);
|
|
220
|
+
return processedViseme;
|
|
221
|
+
}
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
currentVisemesRef.current = processedVisemes;
|
|
225
|
+
|
|
226
|
+
// Start animation immediately if not already animating
|
|
227
|
+
if (!isAnimatingRef.current) {
|
|
228
|
+
isAnimatingRef.current = true;
|
|
229
|
+
startTimeRef.current = performance.now();
|
|
230
|
+
// console.log('Starting animation');
|
|
231
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
232
|
+
} else {
|
|
233
|
+
// If already animating, adjust the start time for the new visemes
|
|
234
|
+
if (startTimeRef.current !== null) {
|
|
235
|
+
const currentTime = performance.now();
|
|
236
|
+
const elapsedTime =
|
|
237
|
+
((currentTime - startTimeRef.current) / 1000) * VISEME_SPEED_FACTOR;
|
|
238
|
+
startTimeRef.current =
|
|
239
|
+
currentTime - (elapsedTime / VISEME_SPEED_FACTOR) * 1000;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return processedVisemes;
|
|
244
|
+
}, [isMeshSet, animate]);
|
|
245
|
+
|
|
246
|
+
const clearVisemes = useCallback(() => {
|
|
247
|
+
currentVisemesRef.current = [];
|
|
248
|
+
visemeQueueRef.current = [];
|
|
249
|
+
|
|
250
|
+
if (animationFrameRef.current !== null) {
|
|
251
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
252
|
+
animationFrameRef.current = null;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (
|
|
256
|
+
meshRef.current?.morphTargetDictionary &&
|
|
257
|
+
meshRef.current?.morphTargetInfluences
|
|
258
|
+
) {
|
|
259
|
+
Object.values(meshRef.current.morphTargetDictionary).forEach(index => {
|
|
260
|
+
if (typeof index === 'number') {
|
|
261
|
+
meshRef.current!.morphTargetInfluences![index] = 0;
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
currentVisemeWeightRef.current = {};
|
|
267
|
+
startTimeRef.current = null;
|
|
268
|
+
isAnimatingRef.current = false;
|
|
269
|
+
// console.log('Visemes cleared');
|
|
270
|
+
}, []);
|
|
271
|
+
|
|
272
|
+
// Your existing emotion map
|
|
273
|
+
const emotionMap: Record<string, Record<string, number>> = {
|
|
274
|
+
Gioia: { Gioria: 1 },
|
|
275
|
+
Rabbia: { Rabbia: 1 },
|
|
276
|
+
Sorpresa: { Sorpresa: 1 },
|
|
277
|
+
Tristezza: { Tristezza: 1 },
|
|
278
|
+
Timore: { Timore: 1 },
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
// Mapping from your emotions to Azure styles
|
|
282
|
+
const emotionToAzureStyleMap: Record<string, string> = {
|
|
283
|
+
Gioia: 'cheerful',
|
|
284
|
+
Rabbia: 'angry',
|
|
285
|
+
Sorpresa: 'excited',
|
|
286
|
+
Tristezza: 'sad',
|
|
287
|
+
Timore: 'terrified',
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// Function to get Azure style from emotion
|
|
291
|
+
function getAzureStyleForEmotion(emotion: string): string {
|
|
292
|
+
return emotionToAzureStyleMap[emotion] || 'neutral';
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
useEffect(() => {
|
|
297
|
+
return () => {
|
|
298
|
+
if (animationFrameRef.current !== null) {
|
|
299
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
}, []);
|
|
303
|
+
|
|
304
|
+
const contextValue: VisemeContextType = {
|
|
305
|
+
setMeshRef,
|
|
306
|
+
addVisemeToQueue,
|
|
307
|
+
processVisemeQueue,
|
|
308
|
+
clearVisemes,
|
|
309
|
+
isMeshSet,
|
|
310
|
+
setEmotion,
|
|
311
|
+
emotion,
|
|
312
|
+
getAzureStyleForEmotion,
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
return (
|
|
316
|
+
<VisemeContext.Provider value={contextValue}>
|
|
317
|
+
{children}
|
|
318
|
+
</VisemeContext.Provider>
|
|
319
|
+
);
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
export const useViseme = (): VisemeContextType => {
|
|
323
|
+
const context = useContext(VisemeContext);
|
|
324
|
+
if (context === undefined) {
|
|
325
|
+
throw new Error('useViseme must be used within a VisemeProvider');
|
|
326
|
+
}
|
|
327
|
+
return context;
|
|
328
|
+
};
|