diff --git a/css/main.css b/css/main.css index 8628f6bb..77ba3cbb 100644 --- a/css/main.css +++ b/css/main.css @@ -323,12 +323,6 @@ div.svelte-362y77>*, div.svelte-362y77>.form>* { height: calc(100dvh - 200px); } -#show-controls { - position: absolute; - background-color: transparent; - left: calc(100% - 180px); -} - .chat > .messages { display: flex; flex-direction: column; @@ -412,3 +406,64 @@ div.svelte-362y77>*, div.svelte-362y77>.form>* { max-width: unset; } } + +#show-controls { + position: absolute; + background-color: transparent; + left: calc(100% - 180px); +} + +#typing-container { + display: none; + position: absolute; + background-color: transparent; + left: -2px; + padding: var(--block-padding); +} + +.typing { + position: relative; +} + +.visible-dots #typing-container { + display: block; +} + +.typing span { + content: ''; + animation: blink 1.5s infinite; + animation-fill-mode: both; + height: 10px; + width: 10px; + background: #3b5998;; + position: absolute; + left:0; + top:0; + border-radius: 50%; +} + +.typing .dot1 { + animation-delay: .2s; + margin-left: calc(10px * 1.5); +} + +.typing .dot2 { + animation-delay: .4s; + margin-left: calc(10px * 3); +} + +@keyframes blink { + 0% { + opacity: .1; + } + 20% { + opacity: 1; + } + 100% { + opacity: .1; + } +} + +#chat-tab .generating { + display: none !important; +} diff --git a/js/main.js b/js/main.js index 81e6a991..6267871c 100644 --- a/js/main.js +++ b/js/main.js @@ -58,6 +58,14 @@ document.addEventListener("keydown", function(event) { }); +//------------------------------------------------ +// Position the chat typing dots +//------------------------------------------------ +typing = document.getElementById('typing-container'); +typingParent = typing.parentNode; +typingSibling = typing.previousElementSibling; +typingSibling.insertBefore(typing, typingSibling.childNodes[2]); + //------------------------------------------------ // Chat scrolling //------------------------------------------------ @@ -81,6 +89,14 @@ const observer = new MutationObserver(function(mutations) { if(!isScrolled) { targetElement.scrollTop = targetElement.scrollHeight; } + + const firstChild = targetElement.children[0]; + if (firstChild.classList.contains('generating')) { + typing.parentNode.classList.add('visible-dots'); + } else { + typing.parentNode.classList.remove('visible-dots'); + } + }); }); diff --git a/modules/ui_chat.py b/modules/ui_chat.py index f85fe611..e3f5820d 100644 --- a/modules/ui_chat.py +++ b/modules/ui_chat.py @@ -24,6 +24,7 @@ def create_ui(): shared.gradio['display'] = gr.HTML(value=chat_html_wrapper({'internal': [], 'visible': []}, shared.settings['name1'], shared.settings['name2'], 'chat', 'cai-chat')) shared.gradio['textbox'] = gr.Textbox(label='', placeholder='Send a message', elem_id='chat-input') shared.gradio['show_controls'] = gr.Checkbox(value=shared.settings['show_controls'], label='Show controls (Ctrl+S)', elem_id='show-controls') + shared.gradio['typing-dots'] = gr.HTML(value='