diff --git a/public/index.html b/public/index.html index bad942b81..63f755d2f 100644 --- a/public/index.html +++ b/public/index.html @@ -1346,6 +1346,16 @@ Auto-scroll Chat +
+

+ Send on Enter +

+ +
diff --git a/public/scripts/RossAscends-mods.js b/public/scripts/RossAscends-mods.js index 56a94b892..a635ca450 100644 --- a/public/scripts/RossAscends-mods.js +++ b/public/scripts/RossAscends-mods.js @@ -17,6 +17,7 @@ import { import { power_user, + send_on_enter_options, } from "./power-user.js"; import { LoadLocal, SaveLocal, ClearLocal, CheckLocal, LoadLocalBool } from "./f-localStorage.js"; @@ -24,9 +25,6 @@ import { selected_group, is_group_generating } from "./group-chats.js"; import { oai_settings } from "./openai.js"; import { poe_settings } from "./poe.js"; -const deviceInfo = await getDeviceInfo(); -console.log("Device type: " + deviceInfo.device.type); - var NavToggle = document.getElementById("nav-toggle"); var RPanelPin = document.getElementById("rm_button_panel_pin"); var LPanelPin = document.getElementById("lm_button_panel_pin"); @@ -52,10 +50,6 @@ var connection_made = false; var retry_delay = 100; var RA_AC_retries = 1; -let isVirtualKB = false; -let lastKeyDownTime = 0; -let lastKeyUpTime = 0; - const observerConfig = { childList: true, subtree: true }; const observer = new MutationObserver(function (mutations) { @@ -107,8 +101,35 @@ waitForElement("#expression-image", 10000).then(function () { console.log("expression holder not loaded yet"); }); +// Device detection +const deviceInfo = await getDeviceInfo(); + async function getDeviceInfo() { - return await (await fetch('/deviceinfo')).json(); + try { + const deviceInfo = await (await fetch('/deviceinfo')).json(); + console.log("Device type: " + deviceInfo?.device?.type); + return deviceInfo; + } + catch { + console.log("Couldn't load device info. Defaulting to desktop"); + return { device: { type: 'desktop' } }; + } +} + +function isMobile() { + const mobileTypes = ['smartphone', 'tablet', 'phablet', 'feature phone', 'portable media player']; + return mobileTypes.includes(deviceInfo?.device?.type); +} + +function shouldSendOnEnter() { + switch (power_user.send_on_enter) { + case send_on_enter_options.DISABLED: + return false; + case send_on_enter_options.AUTO: + return !isMobile(); + case send_on_enter_options.ENABLED: + return true; + } } //RossAscends: Added function to format dates used in files and chat timestamps to a humanized format. @@ -681,33 +702,17 @@ $("document").ready(function () { return false; } - document.addEventListener("keydown", () => { - lastKeyDownTime = new Date().getTime(); - }) - - document.addEventListener('keyup', (event) => { - lastKeyUpTime = new Date().getTime(); - isVirtualKeyboard(event); - }) - - - function isVirtualKeyboard(event) { - var keyTiming = lastKeyUpTime - lastKeyDownTime; // array to store times - if (keyTiming <= 40) { - console.log(`detected VKB (${keyTiming}ms)`); - return; - } - if (keyTiming > 40) { - console.log(`detected PhysKB (${keyTiming}ms)`); - processHotkeys(event); - } - } + $(document).on('keydown', function (event) { + processHotkeys(event); + }); //Additional hotkeys CTRL+ENTER and CTRL+UPARROW function processHotkeys(event) { + const sendOnEnter = shouldSendOnEnter(); + //Enter to send when send_textarea in focus if ($(':focus').attr('id') === 'send_textarea') { - if (!event.shiftKey && !event.ctrlKey && event.key == "Enter" && is_send_press == false) { + if (!event.shiftKey && !event.ctrlKey && event.key == "Enter" && is_send_press == false && sendOnEnter) { event.preventDefault(); Generate(); } @@ -748,7 +753,6 @@ $("document").ready(function () { } } - if (event.ctrlKey && event.key == "ArrowUp") { //edits last USER message if chatbar is empty and focused console.log('got ctrl+uparrow input'); if ( @@ -783,7 +787,5 @@ $("document").ready(function () { } } } - } }); - diff --git a/public/scripts/power-user.js b/public/scripts/power-user.js index a75305cc4..6b38968a7 100644 --- a/public/scripts/power-user.js +++ b/public/scripts/power-user.js @@ -16,6 +16,7 @@ export { power_user, pygmalion_options, tokenizers, + send_on_enter_options, }; const avatar_styles = { @@ -46,6 +47,12 @@ const tokenizers = { LLAMA: 3, } +const send_on_enter_options = { + DISABLED: -1, + AUTO: 0, + ENABLED: 1, +} + let power_user = { tokenizer: tokenizers.CLASSIC, collapse_newlines: false, @@ -89,6 +96,7 @@ let power_user = { auto_scroll_chat_to_bottom: true, auto_fix_generated_markdown: true, + send_on_enter: send_on_enter_options.AUTO, }; let themes = []; @@ -145,7 +153,8 @@ function fixMarkdown(text) { // "^example *text *\n" -> "^example *text*\n" // "^* example * text\n" -> "^*example* text\n" // take note that the side you move the asterisk depends on where its pairing is - // i.e. both of the following strings have the same broken asterisk ' * ', but you move the first to the left and the second to the right, to match the non-broken asterisk "^example * text*\n" "^*example * text\n" + // i.e. both of the following strings have the same broken asterisk ' * ', + // but you move the first to the left and the second to the right, to match the non-broken asterisk "^example * text*\n" "^*example * text\n" // and you HAVE to handle the cases where multiple pairs of asterisks exist in the same line // i.e. "^example * text* * harder problem *\n" -> "^example *text* *harder problem*\n" @@ -340,6 +349,7 @@ function loadPowerUserSettings(settings, data) { $('#auto_scroll_chat_to_bottom').prop("checked", power_user.auto_scroll_chat_to_bottom); $(`#tokenizer option[value="${power_user.tokenizer}"]`).attr('selected', true); $(`#pygmalion_formatting option[value=${power_user.pygmalion_formatting}]`).attr("selected", true); + $(`#send_on_enter option[value=${power_user.send_on_enter}]`).attr("selected", true); $("#collapse-newlines-checkbox").prop("checked", power_user.collapse_newlines); $("#pin-examples-checkbox").prop("checked", power_user.pin_examples); $("#disable-description-formatting-checkbox").prop("checked", power_user.disable_description_formatting); @@ -415,6 +425,79 @@ function sortCharactersList(selector = '.character_select') { } } +async function saveTheme() { + const name = await callPopup('Enter a theme preset name:', 'input'); + + if (!name) { + return; + } + + const theme = { + name, + blur_strength: power_user.blur_strength, + main_text_color: power_user.main_text_color, + italics_text_color: power_user.italics_text_color, + quote_text_color: power_user.quote_text_color, + fastui_bg_color: power_user.fastui_bg_color, + blur_tint_color: power_user.blur_tint_color, + shadow_color: power_user.shadow_color, + shadow_width: power_user.shadow_width, + }; + + const response = await fetch('/savetheme', { + method: 'POST', headers: { + 'X-CSRF-Token': token, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(theme) + }); + + if (response.ok) { + const themeIndex = themes.findIndex(x => x.name == name); + + if (themeIndex == -1) { + themes.push(theme); + const option = document.createElement('option'); + option.selected = true; + option.value = name; + option.innerText = name; + $('#themes').append(option); + } + else { + themes[themeIndex] = theme; + $(`#themes option[value="${name}"]`).attr('selected', true); + } + + power_user.theme = name; + saveSettingsDebounced(); + } +} + +function resetMovablePanels() { + document.getElementById("sheld").style.top = ''; + document.getElementById("sheld").style.left = ''; + document.getElementById("sheld").style.height = ''; + document.getElementById("sheld").style.width = ''; + + document.getElementById("left-nav-panel").style.top = ''; + document.getElementById("left-nav-panel").style.left = ''; + document.getElementById("left-nav-panel").style.height = ''; + document.getElementById("left-nav-panel").style.width = ''; + + document.getElementById("right-nav-panel").style.top = ''; + document.getElementById("right-nav-panel").style.left = ''; + document.getElementById("right-nav-panel").style.right = ''; + document.getElementById("right-nav-panel").style.height = ''; + document.getElementById("right-nav-panel").style.width = ''; + + document.getElementById("expression-holder").style.top = ''; + document.getElementById("expression-holder").style.left = ''; + document.getElementById("expression-holder").style.right = ''; + document.getElementById("expression-holder").style.bottom = ''; + document.getElementById("expression-holder").style.height = ''; + document.getElementById("expression-holder").style.width = ''; +} + $(document).ready(() => { // Settings that go to settings.json $("#collapse-newlines-checkbox").change(function () { @@ -498,32 +581,7 @@ $(document).ready(() => { noShadows(); }); - $("#movingUIreset").on('click', function () { - - document.getElementById("sheld").style.top = ''; - document.getElementById("sheld").style.left = ''; - document.getElementById("sheld").style.height = ''; - document.getElementById("sheld").style.width = ''; - - document.getElementById("left-nav-panel").style.top = ''; - document.getElementById("left-nav-panel").style.left = ''; - document.getElementById("left-nav-panel").style.height = ''; - document.getElementById("left-nav-panel").style.width = ''; - - document.getElementById("right-nav-panel").style.top = ''; - document.getElementById("right-nav-panel").style.left = ''; - document.getElementById("right-nav-panel").style.right = ''; - document.getElementById("right-nav-panel").style.height = ''; - document.getElementById("right-nav-panel").style.width = ''; - - document.getElementById("expression-holder").style.top = ''; - document.getElementById("expression-holder").style.left = ''; - document.getElementById("expression-holder").style.right = ''; - document.getElementById("expression-holder").style.bottom = ''; - document.getElementById("expression-holder").style.height = ''; - document.getElementById("expression-holder").style.width = ''; - - }) + $("#movingUIreset").on('click', resetMovablePanels); $(`input[name="avatar_style"]`).on('input', function (e) { power_user.avatar_style = Number(e.target.value); @@ -608,53 +666,7 @@ $(document).ready(() => { saveSettingsDebounced(); }); - $("#ui-preset-save-button").on('click', async function () { - const name = await callPopup('Enter a theme preset name:', 'input'); - - if (!name) { - return; - } - - const theme = { - name, - blur_strength: power_user.blur_strength, - main_text_color: power_user.main_text_color, - italics_text_color: power_user.italics_text_color, - quote_text_color: power_user.quote_text_color, - fastui_bg_color: power_user.fastui_bg_color, - blur_tint_color: power_user.blur_tint_color, - shadow_color: power_user.shadow_color, - shadow_width: power_user.shadow_width, - }; - - const response = await fetch('/savetheme', { - method: 'POST', headers: { - 'X-CSRF-Token': token, - 'Content-Type': 'application/json', - }, - body: JSON.stringify(theme) - }); - - if (response.ok) { - const themeIndex = themes.findIndex(x => x.name == name); - - if (themeIndex == -1) { - themes.push(theme); - const option = document.createElement('option'); - option.selected = true; - option.value = name; - option.innerText = name; - $('#themes').append(option); - } - else { - themes[themeIndex] = theme; - $(`#themes option[value="${name}"]`).attr('selected', true); - } - - power_user.theme = name; - saveSettingsDebounced(); - } - }); + $("#ui-preset-save-button").on('click', saveTheme); $("#play_message_sound").on('input', function () { power_user.play_message_sound = !!$(this).prop('checked'); @@ -709,6 +721,12 @@ $(document).ready(() => { $("#character_popup").trigger('input'); }); + $("#send_on_enter").on('change', function () { + const value = $(this).find(':selected').val(); + power_user.send_on_enter = Number(value); + saveSettingsDebounced(); + }); + $(window).on('focus', function () { browser_has_focus = true; }); diff --git a/server.js b/server.js index fe5af95ee..8b8c24964 100644 --- a/server.js +++ b/server.js @@ -1848,7 +1848,8 @@ app.post('/status_poe', jsonParser, async (request, response) => { return response.send({ 'bot_names': botNames }); } - catch { + catch (err) { + console.error(err); return response.sendStatus(401); } }); @@ -1869,7 +1870,8 @@ app.post('/purge_poe', jsonParser, async (request, response) => { return response.send({ "ok": true }); } - catch { + catch (err) { + console.error(err); return response.sendStatus(500); } });