@@ -81,21 +81,20 @@ const ChatBotContainer = ({ flow }: { flow: Flow }) => {
81
81
// tracks count of unread messages
82
82
const [ unreadCount , setUnreadCount ] = useState < number > ( 0 ) ;
83
83
84
- // tracks view port height (for auto-resizing on mobile view)
84
+ // tracks view port height and width (for auto-resizing on mobile view)
85
85
const [ viewportHeight , setViewportHeight ] = useState < number > ( window . visualViewport ?. height as number
86
86
|| window . innerHeight ) ;
87
+ const [ viewportWidth , setViewportWidth ] = useState < number > ( window . visualViewport ?. width as number
88
+ || window . innerWidth ) ;
87
89
88
90
// tracks previous window scroll position to go back to on mobile
89
- const [ windowScrollPos , setWindowScrollPos ] = useState ( 0 ) ;
91
+ const scrollPositionRef = useRef < number > ( 0 ) ;
90
92
91
93
// adds listeners and render chat history button if enabled
92
94
useEffect ( ( ) => {
93
95
window . addEventListener ( "click" , handleFirstInteraction ) ;
94
96
window . addEventListener ( "keydown" , handleFirstInteraction ) ;
95
97
window . addEventListener ( "touchstart" , handleFirstInteraction ) ;
96
- if ( "visualViewport" in window && ! isDesktop && ! botOptions . theme ?. embedded ) {
97
- window . visualViewport ?. addEventListener ( "resize" , handleResize ) ;
98
- }
99
98
100
99
setUpNotifications ( ) ;
101
100
setTextAreaDisabled ( botOptions . chatInput ?. disabled as boolean ) ;
@@ -120,42 +119,82 @@ const ChatBotContainer = ({ flow }: { flow: Flow }) => {
120
119
window . removeEventListener ( "click" , handleFirstInteraction ) ;
121
120
window . removeEventListener ( "keydown" , handleFirstInteraction ) ;
122
121
window . removeEventListener ( "touchstart" , handleFirstInteraction ) ;
123
- if ( "visualViewport" in window && ! isDesktop && ! botOptions . theme ?. embedded ) {
124
- window . visualViewport ?. removeEventListener ( "resize" , handleResize ) ;
125
- }
126
122
} ;
127
123
} , [ ] ) ;
128
124
125
+ // used to handle virtualkeyboard api (if supported on browser)
126
+ useEffect ( ( ) => {
127
+ // if is desktop or is embedded bot, nothing to resize
128
+ if ( isDesktop || botOptions . theme ?. embedded ) {
129
+ return ;
130
+ }
131
+
132
+ if ( "virtualKeyboard" in navigator ) {
133
+ // @ts -ignore
134
+ navigator . virtualKeyboard . overlaysContent = true ;
135
+ // @ts -ignore
136
+ navigator . virtualKeyboard . addEventListener ( "geometrychange" , ( event ) => {
137
+ const { x, y, width, height } = event . target . boundingRect ;
138
+ // width does not need adjustments so only height is adjusted
139
+ if ( x == 0 && y == 0 && width == 0 && height == 0 ) {
140
+ setTimeout ( ( ) => {
141
+ setViewportHeight ( window . visualViewport ?. height as number ) ;
142
+ } , 501 ) ;
143
+ } else {
144
+ setTimeout ( ( ) => {
145
+ setViewportHeight ( window . visualViewport ?. height as number - height ) ;
146
+ } , 501 ) ;
147
+ }
148
+ } ) ;
149
+ }
150
+ } , [ ] )
151
+
129
152
// triggers check for notifications
130
153
useEffect ( ( ) => {
131
154
handleNotifications ( ) ;
132
155
} , [ messages ] ) ;
133
156
134
- // resets unread count when chat window is opened
157
+ // resets unread count on opening chat and handles scrolling/resizing window on mobile devices
135
158
useEffect ( ( ) => {
136
159
if ( botOptions . isOpen ) {
137
160
setUnreadCount ( 0 ) ;
138
- if ( ! isDesktop ) {
139
- setWindowScrollPos ( window . scrollY ) ;
140
- if ( document . documentElement . scrollWidth > document . documentElement . clientWidth ) {
141
- return ;
142
- }
161
+ setViewportHeight ( window . visualViewport ?. height as number ) ;
162
+ setViewportWidth ( window . visualViewport ?. width as number ) ;
163
+ }
143
164
144
- // only use scroll event to scroll to top if page is not scrollable horizontally
145
- // currently unable to resolve bug with chat window view on mobile when page is scrollable horizontally
146
- window . addEventListener ( "scroll" , handleScroll ) ;
165
+ if ( isDesktop ) {
166
+ return ;
167
+ }
147
168
148
- return ( ) => {
149
- if ( document . documentElement . scrollWidth > document . documentElement . clientWidth ) {
150
- return ;
151
- }
152
- window . removeEventListener ( "scroll" , handleScroll ) ;
153
- } ;
154
- }
169
+ // handles scrolling of window when chat is open (only for mobile view).
170
+ const handleMobileScrollOpened = ( ) => window . scrollTo ( { top : 0 , left : 0 , behavior : "auto" } ) ;
171
+ // handles scrolling of window when chat is closed (only for mobile view).
172
+ const handleMobileScrollClosed = ( ) => scrollPositionRef . current = window . scrollY ;
173
+ const handleResize = ( ) => {
174
+ setViewportHeight ( window . visualViewport ?. height as number ) ;
175
+ setViewportWidth ( window . visualViewport ?. width as number ) ;
176
+ }
177
+
178
+ if ( botOptions . isOpen ) {
179
+ window . removeEventListener ( 'scroll' , handleMobileScrollClosed ) ;
180
+ document . body . style . position = "fixed" ;
181
+ window . addEventListener ( "scroll" , handleMobileScrollOpened ) ;
182
+ window . visualViewport ?. addEventListener ( "resize" , handleResize ) ;
183
+
184
+ return ( ) => {
185
+ window . removeEventListener ( "scroll" , handleMobileScrollOpened ) ;
186
+ window . visualViewport ?. removeEventListener ( "resize" , handleResize ) ;
187
+ } ;
155
188
} else {
156
- if ( ! isDesktop ) {
157
- window . scrollTo ( { top : windowScrollPos , left : 0 , behavior : "auto" } ) ;
158
- }
189
+ document . body . style . position = "static" ;
190
+ window . removeEventListener ( "scroll" , handleMobileScrollOpened ) ;
191
+ window . scrollTo ( { top : scrollPositionRef . current , left : 0 , behavior : "auto" } ) ;
192
+ window . addEventListener ( 'scroll' , handleMobileScrollClosed ) ;
193
+ window . visualViewport ?. removeEventListener ( "resize" , handleResize ) ;
194
+
195
+ return ( ) => {
196
+ window . removeEventListener ( "scroll" , handleMobileScrollClosed ) ;
197
+ } ;
159
198
}
160
199
} , [ botOptions . isOpen ] ) ;
161
200
@@ -190,30 +229,6 @@ const ChatBotContainer = ({ flow }: { flow: Flow }) => {
190
229
setIsBotTyping ( false ) ;
191
230
}
192
231
193
- /**
194
- * Handles resizing of view port (only for mobile view). KIV - Refer to comments below.
195
- */
196
- const handleResize = ( ) => {
197
- // if not mobile, nothing to do
198
- if ( isDesktop || document . documentElement . scrollWidth > document . documentElement . clientWidth ) {
199
- return ;
200
- }
201
- // only resize viewport if page is not scrollable horizontally (remove this condition if fix is found)
202
- // currently unable to resolve bug with chat window view on mobile when page is scrollable horizontally
203
- setViewportHeight ( window . visualViewport ?. height as number ) ;
204
- } ;
205
-
206
- /**
207
- * Handles scrolling of window when chat is open (only for mobile view). KIV - Refer to comments below.
208
- */
209
- const handleScroll = ( ) => {
210
- // if not mobile or chat window is close, nothing to do
211
- if ( isDesktop ) {
212
- return ;
213
- }
214
- window . scrollTo ( { top : 0 , left : 0 , behavior : "auto" } ) ;
215
- }
216
-
217
232
/**
218
233
* Sets up the notifications feature (initial toggle status and sound).
219
234
*/
@@ -440,15 +455,15 @@ const ChatBotContainer = ({ flow }: { flow: Flow }) => {
440
455
* Retrieves styles for chat window.
441
456
*/
442
457
const getChatWindowStyle = ( ) => {
443
- if ( ! isDesktop ) {
458
+ if ( ! isDesktop && ! botOptions . theme ?. embedded ) {
444
459
return {
445
460
...botOptions . chatWindowStyle ,
446
461
borderRadius : '0px' ,
447
462
left : '0px' ,
448
463
right : 'auto' ,
449
464
top : '0px' ,
450
465
bottom : 'auto' ,
451
- width : '100%' ,
466
+ width : ` ${ viewportWidth } px` ,
452
467
height : `${ viewportHeight } px` ,
453
468
}
454
469
} else {
@@ -471,29 +486,15 @@ const ChatBotContainer = ({ flow }: { flow: Flow }) => {
471
486
< ChatBotTooltip />
472
487
< ChatBotButton unreadCount = { unreadCount } />
473
488
{ /* styles and prevents background from scrolling on mobile when chat window is open */ }
474
- { botOptions . isOpen && ! isDesktop &&
475
- < >
476
- < style >
477
- { `
478
- html, body {
479
- overflow: hidden;
480
- touch-action: none;
481
- }
482
- ` }
483
- </ style >
484
- < div
485
- style = { {
486
- position : "fixed" ,
487
- top : 0 ,
488
- left : 0 ,
489
- width : "100%" ,
490
- height : "100%" ,
491
- backgroundColor : "#fff" ,
492
- zIndex : 9999
493
- } }
494
- >
495
- </ div >
496
- </ >
489
+ { botOptions . isOpen && ! isDesktop && ! botOptions . theme ?. embedded &&
490
+ < style >
491
+ { `
492
+ body {
493
+ overflow: hidden;
494
+ touch-action: none;
495
+ }
496
+ ` }
497
+ </ style >
497
498
}
498
499
< div
499
500
style = { getChatWindowStyle ( ) }
0 commit comments