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);
}
});