11<template >
2- <div class =" chat-wrapper" :class =" { 'dark-mode': store.darkMode, 'fit-to-parent': store.fitToParent, 'stick-input-prompt': store.stickInputPrompt, 'split-screen': store.splitScreenIframe}" @click =" store.menuOpened = false" >
3- <div class =" right-content" >
4- <div class =" conversation-content" ref =" conversationContent" :class =" {'dark-mode': store.darkMode, 'fit-to-parent-conversation-content': store.fitToParent}" >
5- <div class =" stacks" :class =" {'merge-to-prev': getFirstLayerMergeToPrev(message)}" v-for =" (message, index) in store.messages" >
2+ <div class =" chat-wrapper"
3+ :class =" { 'dark-mode': store.darkMode, 'fit-to-parent': store.fitToParent, 'stick-input-prompt': store.stickInputPrompt, 'split-screen': store.splitScreenIframe}"
4+ @click =" store.menuOpened = false" >
5+ <div class =" right-content" :style =" rightContentStyle" >
6+ <div class =" conversation-content" ref =" conversationContent"
7+ :class =" {'dark-mode': store.darkMode, 'fit-to-parent-conversation-content': store.fitToParent}" >
8+ <div class =" stacks" :class =" {'merge-to-prev': getFirstLayerMergeToPrev(message)}"
9+ v-for =" (message, index) in store.messages" >
610 <ChatMsgManager
711 v-if =" isRenderableStackType(message)"
812 :message =" message"
2327 </div >
2428 <ChatPrompt @send =" (msg) => sendMessage(msg)" />
2529 </div >
26- <div v-if =" store.splitScreenIframe" class =" split-screen-iframe-container" >
30+
31+ <div v-if =" store.splitScreenIframe"
32+ class =" resizable-divider"
33+ @mousedown =" startResize"
34+ :class =" {'dark-mode': store.darkMode}" >
35+ </div >
36+
37+ <div v-if =" store.splitScreenIframe" class =" split-screen-iframe-container" :style =" iframeContainerStyle" >
2738 <iframe
2839 class =" split-screen-iframe"
2940 :src =" store.splitScreenIframe"
3445</template >
3546
3647<script setup>
37- import {ref , watch , nextTick , onMounted } from " vue" ;
48+ import {ref , watch , nextTick , onMounted , computed , onUnmounted } from " vue" ;
3849import {useGlobalStore } from " ~/store" ;
3950import LoaderMsg from " ~/components/chat/LoaderMsg.vue" ;
4051import ChatMsgManager from " ~/components/chat/msgs/ChatMsgManager.vue" ;
4152import ChatPrompt from " ~/components/chat/ChatPrompt.vue" ;
42- import { createTextMessage , createMessage } from " ~/utils" ;
53+ import {createTextMessage , createMessage } from " ~/utils" ;
4354
4455const store = useGlobalStore ();
4556
@@ -50,6 +61,31 @@ let notRenderableStackTypes = ["gtm_tag", "close_conversation", undefined]
5061notRenderableStackTypes = notRenderableStackTypes .concat (store .notRenderableStackTypes )
5162let ws = undefined
5263
64+ // --- Resizing functionality ---
65+ const rightContentWidth = ref ( ' 100%' );
66+ const iframeContainerWidth = ref (' 0' );
67+ const isResizing = ref (false );
68+ const startX = ref (0 );
69+ const startRightWidth = ref (0 );
70+ // Computed styles
71+ const rightContentStyle = computed (() => ({
72+ width: rightContentWidth .value
73+ }));
74+
75+ const iframeContainerStyle = computed (() => ({
76+ width: iframeContainerWidth .value ,
77+ pointerEvents: isResizing .value ? ' none' : ' auto'
78+ }));
79+
80+ watch (() => store .splitScreenIframe , () => {
81+ if (store .splitScreenIframe ) {
82+ rightContentWidth .value = ' 50%' ;
83+ iframeContainerWidth .value = ' 50%' ;
84+ } else {
85+ rightContentWidth .value = ' 100%' ;
86+ iframeContainerWidth .value = ' 0' ;
87+ }
88+ })
5389watch (() => store .scrollToBottom , scrollConversationDown)
5490watch (() => store .selectedPlConversationId , createConnection)
5591watch (() => store .feedbackSent , animateFeedbackSent)
@@ -66,9 +102,11 @@ onMounted(async () => {
66102function isLastOfType (index ) {
67103 return index === store .messages .length - 1 || store .messages [index + 1 ].sender .type !== store .messages [index].sender .type
68104}
105+
69106function getFirstLayerMergeToPrev (message ) {
70107 return message? .stack [0 ]? .payload .merge_to_prev ;
71108}
109+
72110function scrollConversationDown () {
73111 nextTick (() => {
74112 conversationContent .value .scroll ({top: conversationContent .value .scrollHeight , behavior: " smooth" })
@@ -85,12 +123,13 @@ function animateFeedbackSent() {
85123 feedbackSentDisabled .value = true
86124 }, 1500 )
87125}
126+
88127function isRenderableStackType (message ) {
89128 return ! notRenderableStackTypes .includes (message .stack [0 ]? .type )
90129}
91130
92131function createConnection () {
93- if (store .previewMode )
132+ if (store .previewMode )
94133 return
95134
96135 if (ws)
@@ -141,7 +180,7 @@ function createConnection() {
141180
142181 sendToGTM (msg)
143182 store .addMessage (msg);
144- if (store .messages .length === 1 )
183+ if (store .messages .length === 1 )
145184 await store .gatherConversations ()
146185 };
147186 ws .onopen = async function () {
@@ -166,7 +205,7 @@ function createConnection() {
166205
167206
168207async function initializeConversation () {
169- if (store .previewMode )
208+ if (store .previewMode )
170209 return
171210
172211 if (store .initialSelectedPlConversationId ) {
@@ -194,7 +233,7 @@ function sendMessage(message) {
194233}
195234
196235function sendMessagesToBeSent () {
197- if (! store .canSendMsg ) {
236+ if (! store .canSendMsg ) {
198237 setTimeout (() => sendMessagesToBeSent (), 1000 )
199238 return
200239 }
@@ -221,9 +260,52 @@ function sendToGTM(msg) {
221260 console .warn (" GTM tag received but no dataLayer found" )
222261 }
223262}
263+
224264document .addEventListener (" request-text-message-send" , (ev ) => sendMessage (createTextMessage (" human" , ev .detail )))
225265document .addEventListener (" request-message-send" , (ev ) => sendMessage (createMessage (" human" , ev .detail )))
226266
267+ // --- Resizing functionality ---
268+ // Resize methods
269+ function startResize (e ) {
270+ isResizing .value = true ;
271+ startX .value = e .clientX ;
272+ startRightWidth .value = parseInt (rightContentWidth .value );
273+
274+ // Add event listeners
275+ document .addEventListener (' mousemove' , resize);
276+ document .addEventListener (' mouseup' , stopResize);
277+
278+ // Prevent text selection during resize
279+ // e.preventDefault();
280+ }
281+
282+ function resize (e ) {
283+ if (! isResizing .value ) return ;
284+
285+ const chatWrapper = document .querySelector (' .chat-wrapper' );
286+ const totalWidth = chatWrapper .offsetWidth ;
287+
288+ // Calculate the new width based on mouse movement
289+ const dx = e .clientX - startX .value ;
290+ const newRightWidth = Math .max (20 , Math .min (80 , (startRightWidth .value + dx / totalWidth * 100 )));
291+
292+ // Update the widths
293+ rightContentWidth .value = ` ${ newRightWidth} %` ;
294+ iframeContainerWidth .value = ` ${ 100 - newRightWidth} %` ;
295+ }
296+
297+ function stopResize () {
298+ isResizing .value = false ;
299+ document .removeEventListener (' mousemove' , resize);
300+ document .removeEventListener (' mouseup' , stopResize);
301+ }
302+
303+ // Clean up event listeners when component is unmounted
304+ onUnmounted (() => {
305+ document .removeEventListener (' mousemove' , resize);
306+ document .removeEventListener (' mouseup' , stopResize);
307+ });
308+
227309< / script>
228310< style scoped lang= " scss" >
229311.chat - wrapper {
@@ -235,31 +317,52 @@ document.addEventListener("request-message-send", (ev) => sendMessage(createMess
235317 display: flex;
236318 flex- direction: column;
237319 background- color: $chatfaq- color- chat- background- light;
320+
238321 & .split - screen {
239322 flex- direction: row;
240323 overflow: hidden ! important;
241324 }
325+
242326 .right - content {
243327 display: flex;
244328 flex- direction: column;
245329 justify- content: space- between;
246330 height: 100 % ;
247- width: 100 % ;
331+ // width: 100%;
332+ // transition: width 0.05s ease;
248333
249334 }
335+
336+
337+ .resizable - divider {
338+ width: 8px ;
339+ opacity: 0 ;
340+ height: 100 % ;
341+ background- color: #f0f0f0;
342+ cursor: col- resize;
343+ display: flex;
344+ align- items: center;
345+ justify- content: center;
346+ z- index: 10 ;
347+ }
348+
250349 .split - screen - iframe- container {
251350 height: 100 % ;
252- width: 100 % ;
351+ // width: 100%;
253352 box- shadow: 0px 2px 18px 0px #0000001A ;
353+ // transition: width 0.05s ease;
254354 }
355+
255356 .split - screen - iframe {
256357 height: 100 % ;
257358 width: 100 % ;
258359 border: 0 ;
259360 }
361+
260362 & .dark - mode {
261363 background- color: $chatfaq- color- chat- background- dark;
262364 }
365+
263366 & .fit - to- parent {
264367 border: unset ! important;
265368 border- radius: inherit ! important;
@@ -316,6 +419,7 @@ document.addEventListener("request-message-send", (ev) => sendMessage(createMess
316419 & .dark - mode {
317420 @include scroll- style ($chatfaq- color- scrollBar- dark);
318421 }
422+
319423 & .fit - to- parent- conversation- content {
320424 min- height: inherit;
321425 }
0 commit comments