diff --git a/css/main.css b/css/main.css index 47506c5e..b06d809d 100644 --- a/css/main.css +++ b/css/main.css @@ -648,3 +648,19 @@ div.svelte-362y77>*, div.svelte-362y77>.form>* { .options { z-index: 100 !important; } + +/* ---------------------------------------------- + Big profile picture for characters +---------------------------------------------- */ +.bigProfilePicture { + position: fixed; + bottom: 0; + left: 0; + width: calc((100vw - 880px - 120px) /2); +} + +@media screen and (width <= 1300px) { + .bigProfilePicture { + display: none; + } +} diff --git a/js/main.js b/js/main.js index 17d1d354..2e0c765b 100644 --- a/js/main.js +++ b/js/main.js @@ -312,6 +312,10 @@ document.addEventListener("click", function (event) { if (!isMouseOverButtonOrMenu() && menu.style.display === "flex") { hideMenu(); } + + if (event.target.classList.contains("pfp_character")) { + toggleBigPicture(); + } }); //------------------------------------------------ @@ -335,3 +339,38 @@ document.getElementById("show-controls").parentNode.style.bottom = "0px"; // Focus on the chat input //------------------------------------------------ document.querySelector("#chat-input textarea").focus(); + +//------------------------------------------------ +// Show enlarged character picture when the profile +// picture is clicked on +//------------------------------------------------ +let bigPictureVisible = false; + +function addBigPicture() { + var imgElement = document.createElement("img"); + var timestamp = new Date().getTime(); + imgElement.src = "/file/cache/pfp_character.png?time=" + timestamp; + imgElement.classList.add("bigProfilePicture"); + + var imgElementParent = document.getElementById("chat").parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode; + imgElementParent.appendChild(imgElement); +} + +function deleteBigPicture() { + var bigProfilePictures = document.querySelectorAll('.bigProfilePicture'); + bigProfilePictures.forEach(function (element) { + element.parentNode.removeChild(element); + }); +} + +function toggleBigPicture() { + if(bigPictureVisible) { + deleteBigPicture(); + bigPictureVisible = false; + } else { + addBigPicture(); + bigPictureVisible = true; + } +} + +showBigPicture(); diff --git a/js/update_big_picture.js b/js/update_big_picture.js new file mode 100644 index 00000000..1984215a --- /dev/null +++ b/js/update_big_picture.js @@ -0,0 +1,7 @@ +function updateBigPicture() { + var existingElement = document.querySelector('.bigProfilePicture'); + if (existingElement) { + var timestamp = new Date().getTime(); + existingElement.src = "/file/cache/pfp_character.png?time=" + timestamp; + } +} diff --git a/modules/chat.py b/modules/chat.py index dda16749..436e3e43 100644 --- a/modules/chat.py +++ b/modules/chat.py @@ -544,9 +544,13 @@ def generate_pfp_cache(character): for path in [Path(f"characters/{character}.{extension}") for extension in ['png', 'jpg', 'jpeg']]: if path.exists(): - img = make_thumbnail(Image.open(path)) - img.save(Path('cache/pfp_character.png'), format='PNG') - return img + original_img = Image.open(path) + original_img.save(Path('cache/pfp_character.png'), format='PNG') + + thumb = make_thumbnail(original_img) + thumb.save(Path('cache/pfp_character_thumb.png'), format='PNG') + + return thumb return None @@ -575,8 +579,9 @@ def load_character(character, name1, name2, instruct=False): file_contents = open(filepath, 'r', encoding='utf-8').read() data = json.loads(file_contents) if extension == "json" else yaml.safe_load(file_contents) - if Path("cache/pfp_character.png").exists() and not instruct: - Path("cache/pfp_character.png").unlink() + for path in [Path("cache/pfp_character.png"), Path("cache/pfp_character_thumb.png")]: + if path.exists() and not instruct: + path.unlink() picture = generate_pfp_cache(character) diff --git a/modules/html_generator.py b/modules/html_generator.py index 26e47848..2a6509b3 100644 --- a/modules/html_generator.py +++ b/modules/html_generator.py @@ -225,7 +225,7 @@ def generate_cai_chat_html(history, name1, name2, style, reset_cache=False): output = f'
' # We use ?name2 and ?time.time() to force the browser to reset caches - img_bot = f'' if Path("cache/pfp_character.png").exists() else '' + img_bot = f'' if Path("cache/pfp_character_thumb.png").exists() else '' img_me = f'' if Path("cache/pfp_me.png").exists() else '' for i, _row in enumerate(history): diff --git a/modules/ui.py b/modules/ui.py index 383bc66f..9e2d6b6a 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -20,6 +20,8 @@ with open(Path(__file__).resolve().parent / '../js/switch_tabs.js', 'r') as f: switch_tabs_js = f.read() with open(Path(__file__).resolve().parent / '../js/show_controls.js', 'r') as f: show_controls_js = f.read() +with open(Path(__file__).resolve().parent / '../js/update_big_picture.js', 'r') as f: + update_big_picture_js = f.read() refresh_symbol = '🔄' delete_symbol = '🗑️' diff --git a/modules/ui_chat.py b/modules/ui_chat.py index b3cff3d6..40c8d71c 100644 --- a/modules/ui_chat.py +++ b/modules/ui_chat.py @@ -275,7 +275,8 @@ def create_event_handlers(): ui.gather_interface_values, gradio(shared.input_elements), gradio('interface_state')).then( chat.load_latest_history, gradio('interface_state'), gradio('history')).then( chat.redraw_html, gradio(reload_arr), gradio('display')).then( - lambda x: gr.update(choices=(histories := chat.find_all_histories(x)), value=histories[0]), gradio('interface_state'), gradio('unique_id')) + lambda x: gr.update(choices=(histories := chat.find_all_histories(x)), value=histories[0]), gradio('interface_state'), gradio('unique_id')).then( + lambda: None, None, None, _js=f'() => {{{ui.update_big_picture_js}; updateBigPicture()}}') shared.gradio['mode'].change( lambda x: gr.update(visible=x != 'instruct'), gradio('mode'), gradio('chat_style'), show_progress=False).then(