sillytavern 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. package/.dockerignore +4 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +35 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  4. package/.github/workflows/npm-publish.yml +32 -0
  5. package/Dockerfile +49 -0
  6. package/Start.bat +3 -0
  7. package/colab/GPU.ipynb +339 -0
  8. package/colab/extras_server.py +40 -0
  9. package/colab/globals.py +2 -0
  10. package/colab/models.py +77 -0
  11. package/docker/docker-compose.yml +12 -0
  12. package/docker/docker-entrypoint.sh +28 -0
  13. package/faq.md +208 -0
  14. package/package.json +49 -0
  15. package/poe-client.js +638 -0
  16. package/poe-test.js +21 -0
  17. package/poe_graphql/AddHumanMessageMutation.graphql +52 -0
  18. package/poe_graphql/AddMessageBreakMutation.graphql +17 -0
  19. package/poe_graphql/AutoSubscriptionMutation.graphql +7 -0
  20. package/poe_graphql/BioFragment.graphql +8 -0
  21. package/poe_graphql/ChatAddedSubscription.graphql +5 -0
  22. package/poe_graphql/ChatFragment.graphql +6 -0
  23. package/poe_graphql/ChatListPaginationQuery.graphql +316 -0
  24. package/poe_graphql/ChatPaginationQuery.graphql +26 -0
  25. package/poe_graphql/ChatViewQuery.graphql +8 -0
  26. package/poe_graphql/DeleteHumanMessagesMutation.graphql +7 -0
  27. package/poe_graphql/DeleteMessageMutation.graphql +7 -0
  28. package/poe_graphql/HandleFragment.graphql +8 -0
  29. package/poe_graphql/LoginWithVerificationCodeMutation.graphql +13 -0
  30. package/poe_graphql/MessageAddedSubscription.graphql +115 -0
  31. package/poe_graphql/MessageDeletedSubscription.graphql +8 -0
  32. package/poe_graphql/MessageFragment.graphql +13 -0
  33. package/poe_graphql/MessageRemoveVoteMutation.graphql +7 -0
  34. package/poe_graphql/MessageSetVoteMutation.graphql +7 -0
  35. package/poe_graphql/SendVerificationCodeForLoginMutation.graphql +12 -0
  36. package/poe_graphql/ShareMessagesMutation.graphql +9 -0
  37. package/poe_graphql/SignupWithVerificationCodeMutation.graphql +13 -0
  38. package/poe_graphql/StaleChatUpdateMutation.graphql +7 -0
  39. package/poe_graphql/SubscriptionsMutation.graphql +9 -0
  40. package/poe_graphql/SummarizePlainPostQuery.graphql +3 -0
  41. package/poe_graphql/SummarizeQuotePostQuery.graphql +3 -0
  42. package/poe_graphql/SummarizeSharePostQuery.graphql +3 -0
  43. package/poe_graphql/UserSnippetFragment.graphql +14 -0
  44. package/poe_graphql/ViewerInfoQuery.graphql +21 -0
  45. package/poe_graphql/ViewerMessageLimitUpdatedSubscription.graphql +81 -0
  46. package/poe_graphql/ViewerStateFragment.graphql +30 -0
  47. package/poe_graphql/ViewerStateUpdatedSubscription.graphql +63 -0
  48. package/public/KoboldAI Settings/Ace of Spades 13B.settings +22 -0
  49. package/public/KoboldAI Settings/Adventurer-NeoX-20B-Erebus.settings +54 -0
  50. package/public/KoboldAI Settings/Basic Coherence 13B.settings +22 -0
  51. package/public/KoboldAI Settings/Best Guess 6B.settings +22 -0
  52. package/public/KoboldAI Settings/Calibrated-Pygmalion-6b.settings +47 -0
  53. package/public/KoboldAI Settings/Classic-Pygmalion-2.7b.settings +46 -0
  54. package/public/KoboldAI Settings/Classic-Pygmalion-6b.settings +47 -0
  55. package/public/KoboldAI Settings/Coherent Creativity 6B.settings +22 -0
  56. package/public/KoboldAI Settings/Default-TavernAI.settings +22 -0
  57. package/public/KoboldAI Settings/DragonSlayer-Pygmalion-6b.settings +47 -0
  58. package/public/KoboldAI Settings/GPU-Pygmalion-6b.settings +47 -0
  59. package/public/KoboldAI Settings/Genesis 13B.settings +22 -0
  60. package/public/KoboldAI Settings/Godlike.settings +22 -0
  61. package/public/KoboldAI Settings/Good Winds.settings +22 -0
  62. package/public/KoboldAI Settings/Lancer-OPT-2.7B-Erebus.settings +54 -0
  63. package/public/KoboldAI Settings/Liminal Drift.settings +22 -0
  64. package/public/KoboldAI Settings/Low Rider 13B.settings +22 -0
  65. package/public/KoboldAI Settings/Luna Moth 6B.settings +22 -0
  66. package/public/KoboldAI Settings/Mayday.settings +22 -0
  67. package/public/KoboldAI Settings/Ouroboros.settings +22 -0
  68. package/public/KoboldAI Settings/Pleasing Results 6B.settings +22 -0
  69. package/public/KoboldAI Settings/Pro Writer 13B.settings +22 -0
  70. package/public/KoboldAI Settings/RA - Pygmalion-1.3b.settings +46 -0
  71. package/public/KoboldAI Settings/Storywriter 6B.settings +22 -0
  72. package/public/NovelAI Settings/Classic-Euterpe.settings +14 -0
  73. package/public/NovelAI Settings/Classic-Krake.settings +14 -0
  74. package/public/OpenAI Settings/Default.settings +15 -0
  75. package/public/TextGen Settings/Beam Search.settings +15 -0
  76. package/public/TextGen Settings/Contrastive Search.settings +15 -0
  77. package/public/TextGen Settings/Default.settings +15 -0
  78. package/public/TextGen Settings/Deterministic.settings +15 -0
  79. package/public/TextGen Settings/Kobold (Godlike).settings +15 -0
  80. package/public/TextGen Settings/Kobold (Liminal Drift).settings +15 -0
  81. package/public/TextGen Settings/Naive.settings +15 -0
  82. package/public/TextGen Settings/NovelAI (Best Guess).settings +15 -0
  83. package/public/TextGen Settings/NovelAI (Decadence).settings +15 -0
  84. package/public/TextGen Settings/NovelAI (Genesis).settings +15 -0
  85. package/public/TextGen Settings/NovelAI (Lycaenidae).settings +15 -0
  86. package/public/TextGen Settings/NovelAI (Ouroboros).settings +15 -0
  87. package/public/TextGen Settings/NovelAI (Pleasing Results).settings +15 -0
  88. package/public/TextGen Settings/NovelAI (Sphinx Moth).settings +15 -0
  89. package/public/TextGen Settings/NovelAI (Storywriter).settings +15 -0
  90. package/public/TextGen Settings/Pygmalion.settings +15 -0
  91. package/public/css/fontawesome.css +8488 -0
  92. package/public/css/notes.css +46 -0
  93. package/public/css/solid.css +24 -0
  94. package/public/favicon.ico +0 -0
  95. package/public/img/No-Image-Placeholder.svg +309 -0
  96. package/public/img/addbg3.png +0 -0
  97. package/public/img/ai4.png +0 -0
  98. package/public/img/apple-icon-114x114.png +0 -0
  99. package/public/img/apple-icon-144x144.png +0 -0
  100. package/public/img/apple-icon-57x57.png +0 -0
  101. package/public/img/apple-icon-72x72.png +0 -0
  102. package/public/img/book2.png +0 -0
  103. package/public/img/default-expressions/admiration.png +0 -0
  104. package/public/img/default-expressions/amusement.png +0 -0
  105. package/public/img/default-expressions/anger.png +0 -0
  106. package/public/img/default-expressions/annoyance.png +0 -0
  107. package/public/img/default-expressions/approval.png +0 -0
  108. package/public/img/default-expressions/caring.png +0 -0
  109. package/public/img/default-expressions/confusion.png +0 -0
  110. package/public/img/default-expressions/curiosity.png +0 -0
  111. package/public/img/default-expressions/desire.png +0 -0
  112. package/public/img/default-expressions/desire1.png +0 -0
  113. package/public/img/default-expressions/desire2.png +0 -0
  114. package/public/img/default-expressions/disappointment.png +0 -0
  115. package/public/img/default-expressions/disapproval.png +0 -0
  116. package/public/img/default-expressions/disgust.png +0 -0
  117. package/public/img/default-expressions/embarrassment.png +0 -0
  118. package/public/img/default-expressions/excitement.png +0 -0
  119. package/public/img/default-expressions/fear.png +0 -0
  120. package/public/img/default-expressions/gratitude.png +0 -0
  121. package/public/img/default-expressions/grief.png +0 -0
  122. package/public/img/default-expressions/joy.png +0 -0
  123. package/public/img/default-expressions/love.png +0 -0
  124. package/public/img/default-expressions/nervousness.png +0 -0
  125. package/public/img/default-expressions/neutral.png +0 -0
  126. package/public/img/default-expressions/optimism.png +0 -0
  127. package/public/img/default-expressions/pride.png +0 -0
  128. package/public/img/default-expressions/realization.png +0 -0
  129. package/public/img/default-expressions/relief.png +0 -0
  130. package/public/img/default-expressions/remorse.png +0 -0
  131. package/public/img/default-expressions/sadness.png +0 -0
  132. package/public/img/default-expressions/surprise.png +0 -0
  133. package/public/img/five.png +0 -0
  134. package/public/img/times-circle.svg +1 -0
  135. package/public/img/you.png +0 -0
  136. package/public/index.html +1899 -0
  137. package/public/notes/1.html +44 -0
  138. package/public/notes/1.png +0 -0
  139. package/public/notes/10.html +20 -0
  140. package/public/notes/11.html +33 -0
  141. package/public/notes/12.html +27 -0
  142. package/public/notes/13.html +29 -0
  143. package/public/notes/13_1.html +24 -0
  144. package/public/notes/13_2.html +25 -0
  145. package/public/notes/13_3.html +89 -0
  146. package/public/notes/14.html +30 -0
  147. package/public/notes/2.html +37 -0
  148. package/public/notes/2.png +0 -0
  149. package/public/notes/3.html +37 -0
  150. package/public/notes/4.html +105 -0
  151. package/public/notes/6.html +33 -0
  152. package/public/notes/7.html +40 -0
  153. package/public/notes/8.html +19 -0
  154. package/public/notes/9.html +46 -0
  155. package/public/notes/advanced_formatting.html +91 -0
  156. package/public/notes/group_reply_strategy.html +63 -0
  157. package/public/notes/message_sound.html +33 -0
  158. package/public/notes/multigen.html +36 -0
  159. package/public/notes/oai_api_key.html +37 -0
  160. package/public/notes/textgen_streaming.html +29 -0
  161. package/public/notes/token-limits.html +68 -0
  162. package/public/script.js +5131 -0
  163. package/public/scripts/RossAscends-mods.js +750 -0
  164. package/public/scripts/bookmarks.js +130 -0
  165. package/public/scripts/extensions/backgrounds/index.js +129 -0
  166. package/public/scripts/extensions/backgrounds/manifest.json +11 -0
  167. package/public/scripts/extensions/backgrounds/style.css +45 -0
  168. package/public/scripts/extensions/caption/index.js +117 -0
  169. package/public/scripts/extensions/caption/manifest.json +13 -0
  170. package/public/scripts/extensions/caption/style.css +23 -0
  171. package/public/scripts/extensions/dice/droll.js +108 -0
  172. package/public/scripts/extensions/dice/index.js +96 -0
  173. package/public/scripts/extensions/dice/manifest.json +11 -0
  174. package/public/scripts/extensions/dice/style.css +26 -0
  175. package/public/scripts/extensions/expressions/index.js +387 -0
  176. package/public/scripts/extensions/expressions/manifest.json +13 -0
  177. package/public/scripts/extensions/expressions/style.css +115 -0
  178. package/public/scripts/extensions/floating-prompt/index.js +151 -0
  179. package/public/scripts/extensions/floating-prompt/manifest.json +11 -0
  180. package/public/scripts/extensions/floating-prompt/style.css +19 -0
  181. package/public/scripts/extensions/memory/index.js +358 -0
  182. package/public/scripts/extensions/memory/manifest.json +13 -0
  183. package/public/scripts/extensions/memory/style.css +34 -0
  184. package/public/scripts/extensions.js +288 -0
  185. package/public/scripts/f-localStorage.js +27 -0
  186. package/public/scripts/gpt-2-3-tokenizer/README.md +28 -0
  187. package/public/scripts/gpt-2-3-tokenizer/encoder.js +1 -0
  188. package/public/scripts/gpt-2-3-tokenizer/mod.js +169 -0
  189. package/public/scripts/gpt-2-3-tokenizer/vocab.bpe.js +1 -0
  190. package/public/scripts/gpt-3-tokenizer/array-keyed-map.js +210 -0
  191. package/public/scripts/gpt-3-tokenizer/gpt3-tokenizer.js +271 -0
  192. package/public/scripts/gpt-3-tokenizer/gpt3-tokenizer.js.map +1 -0
  193. package/public/scripts/group-chats.js +899 -0
  194. package/public/scripts/horde.js +214 -0
  195. package/public/scripts/jquery-3.5.1.min.js +2 -0
  196. package/public/scripts/jquery-cookie-1.4.1.min.js +2 -0
  197. package/public/scripts/jquery.transit.min.js +1 -0
  198. package/public/scripts/kai-settings.js +179 -0
  199. package/public/scripts/nai-settings.js +108 -0
  200. package/public/scripts/openai.js +973 -0
  201. package/public/scripts/poe.js +360 -0
  202. package/public/scripts/popper.js +2008 -0
  203. package/public/scripts/popper.js.map +1 -0
  204. package/public/scripts/power-user.js +571 -0
  205. package/public/scripts/purify.min.js +3 -0
  206. package/public/scripts/purify.min.js.map +1 -0
  207. package/public/scripts/showdown.min.js +3 -0
  208. package/public/scripts/showdown.min.js.map +1 -0
  209. package/public/scripts/swiped-events.js +165 -0
  210. package/public/scripts/textgen-settings.js +194 -0
  211. package/public/scripts/toolcool-color-picker.js +87 -0
  212. package/public/scripts/utils.js +109 -0
  213. package/public/scripts/world-info.js +661 -0
  214. package/public/sounds/message.mp3 +0 -0
  215. package/public/style.css +3633 -0
  216. package/public/webfonts/NotoSans/NotoSans-Black.woff +0 -0
  217. package/public/webfonts/NotoSans/NotoSans-Black.woff2 +0 -0
  218. package/public/webfonts/NotoSans/NotoSans-BlackItalic.woff +0 -0
  219. package/public/webfonts/NotoSans/NotoSans-BlackItalic.woff2 +0 -0
  220. package/public/webfonts/NotoSans/NotoSans-Bold.woff +0 -0
  221. package/public/webfonts/NotoSans/NotoSans-Bold.woff2 +0 -0
  222. package/public/webfonts/NotoSans/NotoSans-BoldItalic.woff +0 -0
  223. package/public/webfonts/NotoSans/NotoSans-BoldItalic.woff2 +0 -0
  224. package/public/webfonts/NotoSans/NotoSans-ExtraBold.woff +0 -0
  225. package/public/webfonts/NotoSans/NotoSans-ExtraBold.woff2 +0 -0
  226. package/public/webfonts/NotoSans/NotoSans-ExtraBoldItalic.woff +0 -0
  227. package/public/webfonts/NotoSans/NotoSans-ExtraBoldItalic.woff2 +0 -0
  228. package/public/webfonts/NotoSans/NotoSans-ExtraLight.woff +0 -0
  229. package/public/webfonts/NotoSans/NotoSans-ExtraLight.woff2 +0 -0
  230. package/public/webfonts/NotoSans/NotoSans-ExtraLightItalic.woff +0 -0
  231. package/public/webfonts/NotoSans/NotoSans-ExtraLightItalic.woff2 +0 -0
  232. package/public/webfonts/NotoSans/NotoSans-Italic.woff +0 -0
  233. package/public/webfonts/NotoSans/NotoSans-Italic.woff2 +0 -0
  234. package/public/webfonts/NotoSans/NotoSans-Light.woff +0 -0
  235. package/public/webfonts/NotoSans/NotoSans-Light.woff2 +0 -0
  236. package/public/webfonts/NotoSans/NotoSans-LightItalic.woff +0 -0
  237. package/public/webfonts/NotoSans/NotoSans-LightItalic.woff2 +0 -0
  238. package/public/webfonts/NotoSans/NotoSans-Medium.woff +0 -0
  239. package/public/webfonts/NotoSans/NotoSans-Medium.woff2 +0 -0
  240. package/public/webfonts/NotoSans/NotoSans-MediumItalic.woff +0 -0
  241. package/public/webfonts/NotoSans/NotoSans-MediumItalic.woff2 +0 -0
  242. package/public/webfonts/NotoSans/NotoSans-Regular.woff +0 -0
  243. package/public/webfonts/NotoSans/NotoSans-Regular.woff2 +0 -0
  244. package/public/webfonts/NotoSans/NotoSans-SemiBold.woff +0 -0
  245. package/public/webfonts/NotoSans/NotoSans-SemiBold.woff2 +0 -0
  246. package/public/webfonts/NotoSans/NotoSans-SemiBoldItalic.woff +0 -0
  247. package/public/webfonts/NotoSans/NotoSans-SemiBoldItalic.woff2 +0 -0
  248. package/public/webfonts/NotoSans/NotoSans-Thin.woff +0 -0
  249. package/public/webfonts/NotoSans/NotoSans-Thin.woff2 +0 -0
  250. package/public/webfonts/NotoSans/NotoSans-ThinItalic.woff +0 -0
  251. package/public/webfonts/NotoSans/NotoSans-ThinItalic.woff2 +0 -0
  252. package/public/webfonts/NotoSans/stylesheet.css +162 -0
  253. package/public/webfonts/fa-solid-900.ttf +0 -0
  254. package/public/webfonts/fa-solid-900.woff2 +0 -0
  255. package/readme.md +187 -0
  256. package/server.js +2593 -0
  257. package/start.sh +24 -0
  258. package/tools/charaverter/main.mjs +110 -0
  259. package/tools/charaverter/package.json +10 -0
@@ -0,0 +1,750 @@
1
+ esversion: 6
2
+
3
+ import {
4
+ Generate,
5
+ this_chid,
6
+ characters,
7
+ online_status,
8
+ main_api,
9
+ api_server,
10
+ nai_settings,
11
+ api_server_textgenerationwebui,
12
+ is_send_press,
13
+ getTokenCount,
14
+ max_context,
15
+
16
+ } from "../script.js";
17
+
18
+ import {
19
+ power_user,
20
+ } from "./power-user.js";
21
+
22
+ import { LoadLocal, SaveLocal, ClearLocal, CheckLocal, LoadLocalBool } from "./f-localStorage.js";
23
+ import { selected_group, is_group_generating } from "./group-chats.js";
24
+ import { oai_settings } from "./openai.js";
25
+ import { poe_settings } from "./poe.js";
26
+
27
+ var NavToggle = document.getElementById("nav-toggle");
28
+ var RPanelPin = document.getElementById("rm_button_panel_pin");
29
+ var LPanelPin = document.getElementById("lm_button_panel_pin");
30
+ var SelectedCharacterTab = document.getElementById("rm_button_selected_ch");
31
+ var RightNavPanel = document.getElementById("right-nav-panel");
32
+ var LeftNavPanel = document.getElementById("left-nav-panel")
33
+ var AdvancedCharDefsPopup = document.getElementById("character_popup");
34
+ var ConfirmationPopup = document.getElementById("dialogue_popup");
35
+ var AutoConnectCheckbox = document.getElementById("auto-connect-checkbox");
36
+ var AutoLoadChatCheckbox = document.getElementById("auto-load-chat-checkbox");
37
+ var SelectedNavTab = ("#" + LoadLocal('SelectedNavTab'));
38
+
39
+ var create_save_name;
40
+ var create_save_description;
41
+ var create_save_personality;
42
+ var create_save_first_message;
43
+ var create_save_scenario;
44
+ var create_save_mes_example;
45
+ var count_tokens;
46
+ var perm_tokens;
47
+
48
+ var connection_made = false;
49
+ var retry_delay = 100;
50
+ var RA_AC_retries = 1;
51
+
52
+ const observerConfig = { childList: true, subtree: true };
53
+
54
+ const observer = new MutationObserver(function (mutations) {
55
+ mutations.forEach(function (mutation) {
56
+ if (mutation.target.id === "online_status_text2" ||
57
+ mutation.target.id === "online_status_text3" ||
58
+ mutation.target.classList.contains("online_status_text4")) {
59
+ RA_checkOnlineStatus();
60
+ } else if (mutation.target.parentNode === SelectedCharacterTab) {
61
+ setTimeout(RA_CountCharTokens, 200);
62
+ }
63
+
64
+ });
65
+ });
66
+
67
+ observer.observe(document.documentElement, observerConfig);
68
+
69
+ /**
70
+ * Wait for an element before resolving a promise
71
+ * @param {String} querySelector - Selector of element to wait for
72
+ * @param {Integer} timeout - Milliseconds to wait before timing out, or 0 for no timeout
73
+ */
74
+ function waitForElement(querySelector, timeout) {
75
+ return new Promise((resolve, reject) => {
76
+ var timer = false;
77
+ if (document.querySelectorAll(querySelector).length) return resolve();
78
+ const observer = new MutationObserver(() => {
79
+ if (document.querySelectorAll(querySelector).length) {
80
+ observer.disconnect();
81
+ if (timer !== false) clearTimeout(timer);
82
+ return resolve();
83
+ }
84
+ });
85
+ observer.observe(document.body, {
86
+ childList: true,
87
+ subtree: true
88
+ });
89
+ if (timeout) timer = setTimeout(() => {
90
+ observer.disconnect();
91
+ reject();
92
+ }, timeout);
93
+ });
94
+ }
95
+
96
+ waitForElement("#expression-image", 10000).then(function () {
97
+
98
+ dragElement(document.getElementById("expression-holder"));
99
+ }).catch(() => {
100
+ console.log("expression holder not loaded yet");
101
+ });
102
+
103
+
104
+ //RossAscends: Added function to format dates used in files and chat timestamps to a humanized format.
105
+ //Mostly I wanted this to be for file names, but couldn't figure out exactly where the filename save code was as everything seemed to be connected.
106
+ //Does not break old characters/chats, as the code just uses whatever timestamp exists in the chat.
107
+ //New chats made with characters will use this new formatting.
108
+ export function humanizedDateTime() {
109
+ let baseDate = new Date(Date.now());
110
+ let humanYear = baseDate.getFullYear();
111
+ let humanMonth = baseDate.getMonth() + 1;
112
+ let humanDate = baseDate.getDate();
113
+ let humanHour = (baseDate.getHours() < 10 ? "0" : "") + baseDate.getHours();
114
+ let humanMinute =
115
+ (baseDate.getMinutes() < 10 ? "0" : "") + baseDate.getMinutes();
116
+ let humanSecond =
117
+ (baseDate.getSeconds() < 10 ? "0" : "") + baseDate.getSeconds();
118
+ let humanMillisecond =
119
+ (baseDate.getMilliseconds() < 10 ? "0" : "") + baseDate.getMilliseconds();
120
+ let HumanizedDateTime =
121
+ humanYear + "-" + humanMonth + "-" + humanDate + " @" + humanHour + "h " + humanMinute + "m " + humanSecond + "s " + humanMillisecond + "ms";
122
+ return HumanizedDateTime;
123
+ }
124
+
125
+
126
+ // triggers:
127
+ $("#rm_button_create").on("click", function () { //when "+New Character" is clicked
128
+ $(SelectedCharacterTab).children("h2").html(''); // empty nav's 3rd panel tab
129
+
130
+ //empty temp vars to store new char data for counting
131
+ create_save_name = "";
132
+ create_save_description = "";
133
+ create_save_personality = "";
134
+ create_save_first_message = "";
135
+ create_save_scenario = "";
136
+ create_save_mes_example = "";
137
+ $("#result_info").html('Type to start counting tokens!');
138
+ });
139
+ $("#rm_ch_create_block").on("input", function () { RA_CountCharTokens(); }); //when any input is made to the create/edit character form textareas
140
+ $("#character_popup").on("input", function () { RA_CountCharTokens(); }); //when any input is made to the advanced editing popup textareas
141
+ //function:
142
+ function RA_CountCharTokens() {
143
+ $("#result_info").html("");
144
+ //console.log('RA_TC -- starting with this_chid = ' + this_chid);
145
+ if (document.getElementById('name_div').style.display == "block") { //if new char
146
+
147
+ $("#form_create").on("input", function () { //fill temp vars with form_create values
148
+ create_save_name = $("#character_name_pole").val();
149
+ create_save_description = $("#description_textarea").val();
150
+ create_save_first_message = $("#firstmessage_textarea").val();
151
+ });
152
+ $("#character_popup").on("input", function () { //fill temp vars with advanced popup values
153
+ create_save_personality = $("#personality_textarea").val();
154
+ create_save_scenario = $("#scenario_pole").val();
155
+ create_save_mes_example = $("#mes_example_textarea").val();
156
+
157
+ });
158
+
159
+ //count total tokens, including those that will be removed from context once chat history is long
160
+ count_tokens = getTokenCount(JSON.stringify(
161
+ create_save_name +
162
+ create_save_description +
163
+ create_save_personality +
164
+ create_save_scenario +
165
+ create_save_first_message +
166
+ create_save_mes_example
167
+ ));
168
+
169
+ //count permanent tokens that will never get flushed out of context
170
+ perm_tokens = getTokenCount(JSON.stringify(
171
+ create_save_name +
172
+ create_save_description +
173
+ create_save_personality +
174
+ create_save_scenario
175
+ ));
176
+
177
+ } else {
178
+ if (this_chid !== undefined && this_chid !== "invalid-safety-id") { // if we are counting a valid pre-saved char
179
+
180
+ //same as above, all tokens including temporary ones
181
+ count_tokens = getTokenCount(
182
+ JSON.stringify(
183
+ characters[this_chid].description +
184
+ characters[this_chid].personality +
185
+ characters[this_chid].scenario +
186
+ characters[this_chid].first_mes +
187
+ characters[this_chid].mes_example
188
+ ));
189
+
190
+ //permanent tokens count
191
+ perm_tokens = getTokenCount(
192
+ JSON.stringify(
193
+ characters[this_chid].name +
194
+ characters[this_chid].description +
195
+ characters[this_chid].personality +
196
+ characters[this_chid].scenario +
197
+ (power_user.pin_examples ? characters[this_chid].mes_example : '') // add examples to permanent if they are pinned
198
+ ));
199
+ } else { console.log("RA_TC -- no valid char found, closing."); } // if neither, probably safety char or some error in loading
200
+ }
201
+ // display the counted tokens
202
+ if (count_tokens < 1024 && perm_tokens < 1024) {
203
+ $("#result_info").html(count_tokens + " Tokens (" + perm_tokens + " Permanent Tokens)"); //display normal if both counts are under 1024
204
+ } else {
205
+ $("#result_info").html(`
206
+ <span class="neutral_warning">${count_tokens}</span>&nbsp;Tokens (<span class="neutral_warning">${perm_tokens}</span><span>&nbsp;Permanent Tokens)
207
+ <br>
208
+ <div id="chartokenwarning" class="menu_button whitespacenowrap"><a href="/notes/token-limits.html" target="_blank">Learn More About Token 'Limits'</a></div>`);
209
+ } //warn if either are over 1024
210
+ }
211
+ //Auto Load Last Charcter -- (fires when active_character is defined and auto_load_chat is true)
212
+ async function RA_autoloadchat() {
213
+ if (document.getElementById('CharID0') !== null) {
214
+ //console.log('char list loaded! clicking activeChar');
215
+ var CharToAutoLoad = document.getElementById('CharID' + LoadLocal('ActiveChar'));
216
+ //console.log(CharToAutoLoad);
217
+ let autoLoadGroup = document.querySelector(`.group_select[grid="${LoadLocal('ActiveGroup')}"]`);
218
+ //console.log(autoLoadGroup);
219
+ if (CharToAutoLoad != null) {
220
+
221
+
222
+ // console.log('--ALC - clicking character');
223
+ CharToAutoLoad.click();
224
+ CharToAutoLoad.click();
225
+
226
+ }
227
+ else if (autoLoadGroup != null) {
228
+ //console.log('--ALC - clicking group');
229
+ autoLoadGroup.click();
230
+ autoLoadGroup.click();
231
+ }
232
+ else {
233
+ console.log(CharToAutoLoad + ' ActiveChar local var - not found: ' + LoadLocal('ActiveChar'));
234
+ }
235
+ RestoreNavTab();
236
+ } else {
237
+ //console.log('no char list yet..');
238
+ setTimeout(RA_autoloadchat, 100); // if the charcter list hadn't been loaded yet, try again.
239
+ }
240
+ }
241
+ //only triggers when AutoLoadChat is enabled, consider adding this as an independent feature later.
242
+ function RestoreNavTab() {
243
+ if ($('#rm_button_selected_ch').children("h2").text() !== '') { //check for a change in the character edit tab name
244
+ //console.log('detected ALC char finished loaded, proceeding to restore tab.');
245
+ $(SelectedNavTab).click(); //click to restore saved tab when name has changed (signalling char load is done)
246
+ } else {
247
+ setTimeout(RestoreNavTab, 100); //if not changed yet, check again after 100ms
248
+ }
249
+ }
250
+ //changes input bar and send button display depending on connection status
251
+ function RA_checkOnlineStatus() {
252
+ if (online_status == "no_connection") {
253
+ $("#send_textarea").attr("placeholder", "Not connected to API!"); //Input bar placeholder tells users they are not connected
254
+ $("#send_form").addClass('no-connection'); //entire input form area is red when not connected
255
+ $("#send_but").css("display", "none"); //send button is hidden when not connected;
256
+ $("#API-status-top").removeClass("fa-plug");
257
+ $("#API-status-top").addClass("fa-plug-circle-exclamation redOverlayGlow");
258
+ connection_made = false;
259
+ } else {
260
+ if (online_status !== undefined && online_status !== "no_connection") {
261
+ $("#send_textarea").attr("placeholder", "Type a message..."); //on connect, placeholder tells user to type message
262
+ $('#send_form').removeClass("no-connection");
263
+ $("#API-status-top").removeClass("fa-plug-circle-exclamation redOverlayGlow");
264
+ $("#API-status-top").addClass("fa-plug");
265
+ connection_made = true;
266
+ retry_delay = 100;
267
+ RA_AC_retries = 1;
268
+
269
+ if (!is_send_press && !(selected_group && is_group_generating)) {
270
+ $("#send_but").css("display", "flex"); //on connect, send button shows
271
+ }
272
+ }
273
+ }
274
+ }
275
+ //Auto-connect to API (when set to kobold, API URL exists, and auto_connect is true)
276
+
277
+ function RA_autoconnect(PrevApi) {
278
+ if (online_status === undefined) {
279
+ setTimeout(RA_autoconnect, 100);
280
+ return;
281
+ }
282
+ if (online_status === "no_connection" && LoadLocalBool('AutoConnectEnabled')) {
283
+ switch (main_api) {
284
+ case 'kobold':
285
+ if (api_server && isUrlOrAPIKey(api_server)) {
286
+ $("#api_button").click();
287
+
288
+ }
289
+ break;
290
+ case 'novel':
291
+ if (nai_settings.api_key_novel) {
292
+ $("#api_button_novel").click();
293
+
294
+ }
295
+ break;
296
+ case 'textgenerationwebui':
297
+ if (api_server_textgenerationwebui && isUrlOrAPIKey(api_server_textgenerationwebui)) {
298
+ $("#api_button_textgenerationwebui").click();
299
+ }
300
+ break;
301
+ case 'openai':
302
+ if (oai_settings.api_key_openai) {
303
+ $("#api_button_openai").click();
304
+ }
305
+ break;
306
+ case 'poe':
307
+ if (poe_settings.token) {
308
+ $("#poe_connect").click();
309
+ }
310
+ break;
311
+ }
312
+
313
+ if (!connection_made) {
314
+
315
+ RA_AC_retries++;
316
+ retry_delay = Math.min(retry_delay * 2, 30000); // double retry delay up to to 30 secs
317
+ //console.log('connection attempts: ' + RA_AC_retries + ' delay: ' + (retry_delay / 1000) + 's');
318
+ setTimeout(RA_autoconnect, retry_delay);
319
+ }
320
+ }
321
+ }
322
+
323
+ function isUrlOrAPIKey(string) {
324
+ try {
325
+ new URL(string);
326
+ return true;
327
+ } catch (_) {
328
+ // return pattern.test(string);
329
+ }
330
+ }
331
+
332
+ function OpenNavPanels() {
333
+ //auto-open R nav if locked and previously open
334
+ if (LoadLocalBool("NavLockOn") == true && LoadLocalBool("NavOpened") == true) {
335
+ console.log("RA -- clicking right nav to open");
336
+ $("#rightNavDrawerIcon").click();
337
+ } else {
338
+ /* console.log('didnt see reason to open right nav on load: R-nav locked? ' +
339
+ LoadLocalBool("NavLockOn")
340
+ + ' R-nav was open before? ' +
341
+ LoadLocalBool("NavOpened" == true)); */
342
+ }
343
+
344
+ //auto-open L nav if locked and previously open
345
+
346
+ if (LoadLocalBool("LNavLockOn") == true && LoadLocalBool("LNavOpened") == true) {
347
+ console.log("RA -- clicking left nav to open");
348
+ $("#leftNavDrawerIcon").click();
349
+ } else {
350
+ /* console.log('didnt see reason to open left nav on load: L-Nav Locked? ' +
351
+ LoadLocalBool("LNavLockOn")
352
+ + ' L-nav was open before? ' +
353
+ LoadLocalBool("LNavOpened" == true)); */
354
+ }
355
+ }
356
+
357
+
358
+ // Make the DIV element draggable:
359
+ dragElement(document.getElementById("sheld"));
360
+ dragElement(document.getElementById("left-nav-panel"));
361
+ dragElement(document.getElementById("right-nav-panel"));
362
+
363
+
364
+
365
+ function dragElement(elmnt) {
366
+ var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
367
+ if (document.getElementById(elmnt.id + "header")) { //ex: id="sheldheader"
368
+ // if present, the header is where you move the DIV from, but this overrides everything else:
369
+ document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
370
+ } else {
371
+ // otherwise, move the DIV from anywhere inside the DIV, b:
372
+ elmnt.onmousedown = dragMouseDown;
373
+ }
374
+
375
+ function dragMouseDown(e) {
376
+ e = e || window.event;
377
+ e.preventDefault();
378
+ // get the mouse cursor position at startup:
379
+ pos3 = e.clientX; //mouse X at click
380
+ pos4 = e.clientY; //mouse Y at click
381
+ document.onmouseup = closeDragElement;
382
+ // call a function whenever the cursor moves:
383
+ document.onmousemove = elementDrag;
384
+ }
385
+
386
+ function elementDrag(e) {
387
+ //disable scrollbars when dragging to prevent jitter
388
+ $("body").css("overflow", "hidden");
389
+
390
+
391
+ //get window size
392
+ let winWidth = window.innerWidth;
393
+ let winHeight = window.innerHeight;
394
+
395
+ //get necessary data for calculating element footprint
396
+ let draggableHeight = parseInt(getComputedStyle(elmnt).getPropertyValue('height').slice(0, -2));
397
+ let draggableWidth = parseInt(getComputedStyle(elmnt).getPropertyValue('width').slice(0, -2));
398
+ let draggableTop = parseInt(getComputedStyle(elmnt).getPropertyValue('top').slice(0, -2));
399
+ let draggableLeft = parseInt(getComputedStyle(elmnt).getPropertyValue('left').slice(0, -2));
400
+ let sheldWidth = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--sheldWidth').slice(0, -2));
401
+ let topBarFirstX = (winWidth - sheldWidth) / 2;
402
+ let topBarLastX = topBarFirstX + sheldWidth;
403
+
404
+ //set the lowest and most-right pixel the element touches
405
+ let maxX = (draggableWidth + draggableLeft);
406
+ let maxY = (draggableHeight + draggableTop);
407
+
408
+ // calculate the new cursor position:
409
+ e = e || window.event;
410
+ e.preventDefault();
411
+
412
+ pos1 = pos3 - e.clientX; //X change amt
413
+ pos2 = pos4 - e.clientY; //Y change amt
414
+ pos3 = e.clientX; //new mouse X
415
+ pos4 = e.clientY; //new mouse Y
416
+
417
+
418
+
419
+ //fix over/underflows:
420
+
421
+ setTimeout(function () {
422
+ if (elmnt.offsetTop < 40) {
423
+ /* console.log('6'); */
424
+ if (maxX > topBarFirstX && maxX < topBarLastX) {
425
+ /* console.log('maxX inside topBar!'); */
426
+ elmnt.style.top = "42px";
427
+ }
428
+ if (elmnt.offsetLeft < topBarLastX && elmnt.offsetLeft > topBarFirstX) {
429
+ /* console.log('offsetLeft inside TopBar!'); */
430
+ elmnt.style.top = "42px";
431
+ }
432
+ }
433
+
434
+ if (elmnt.offsetTop - pos2 <= 0) {
435
+ /* console.log('1'); */
436
+ //prevent going out of window top + 42px barrier for TopBar (can hide grabber)
437
+ elmnt.style.top = "0px";
438
+ }
439
+
440
+ if (elmnt.offsetLeft - pos1 <= 0) {
441
+ /* console.log('2'); */
442
+ //prevent moving out of window left
443
+ elmnt.style.left = "0px";
444
+ }
445
+
446
+ if (maxX >= winWidth) {
447
+ /* console.log('3'); */
448
+ //bounce off right
449
+ elmnt.style.left = elmnt.offsetLeft - 10 + "px";
450
+ }
451
+
452
+ if (maxY >= winHeight) {
453
+ /* console.log('4'); */
454
+ //bounce off bottom
455
+ elmnt.style.top = elmnt.offsetTop - 10 + "px";
456
+ if (elmnt.offsetTop - pos2 <= 40) {
457
+ /* console.log('5'); */
458
+ //prevent going out of window top + 42px barrier for TopBar (can hide grabber)
459
+ /* console.log('caught Y bounce to <40Y top'); */
460
+ elmnt.style.top = "20px";
461
+ }
462
+ }
463
+ // if no problems, set element's new position
464
+ /* console.log('7'); */
465
+
466
+ elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
467
+ elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
468
+ $(elmnt).css("bottom", "unset");
469
+ $(elmnt).css("right", "unset");
470
+
471
+ /* console.log(`
472
+ offsetLeft: ${elmnt.offsetLeft}, offsetTop: ${elmnt.offsetTop}
473
+ winWidth: ${winWidth}, winHeight: ${winHeight}
474
+ sheldWidth: ${sheldWidth}
475
+ X: ${elmnt.style.left}
476
+ Y: ${elmnt.style.top}
477
+ MaxX: ${maxX}, MaxY: ${maxY}
478
+ Topbar 1st X: ${((winWidth - sheldWidth) / 2)}
479
+ TopBar lastX: ${((winWidth - sheldWidth) / 2) + sheldWidth}
480
+ `); */
481
+
482
+
483
+
484
+ }, 50)
485
+
486
+ /* console.log("left/top: " + (elmnt.offsetLeft - pos1) + "/" + (elmnt.offsetTop - pos2) +
487
+ ", win: " + winWidth + "/" + winHeight +
488
+ ", max X / Y: " + maxX + " / " + maxY); */
489
+
490
+ }
491
+
492
+ function closeDragElement() {
493
+ // stop moving when mouse button is released:
494
+ document.onmouseup = null;
495
+ document.onmousemove = null;
496
+ //revert scrolling to normal after drag to allow recovery of vastly misplaced elements
497
+ $("body").css("overflow", "auto");
498
+
499
+ }
500
+ }
501
+
502
+ // ---------------------------------------------------
503
+
504
+ $("document").ready(function () {
505
+
506
+ // initial status check
507
+ setTimeout(RA_checkOnlineStatus, 100);
508
+
509
+ // read the state of AutoConnect and AutoLoadChat.
510
+ $(AutoConnectCheckbox).prop("checked", LoadLocalBool("AutoConnectEnabled"));
511
+ $(AutoLoadChatCheckbox).prop("checked", LoadLocalBool("AutoLoadChatEnabled"));
512
+
513
+ if (LoadLocalBool('AutoLoadChatEnabled') == true) { RA_autoloadchat(); }
514
+ //Autoconnect on page load if enabled, or when api type is changed
515
+ if (LoadLocalBool("AutoConnectEnabled") == true) { RA_autoconnect(); }
516
+ $("#main_api").change(function () {
517
+ var PrevAPI = main_api;
518
+ setTimeout(() => RA_autoconnect(PrevAPI), 100);
519
+ });
520
+ $("#api_button").click(function () { setTimeout(RA_checkOnlineStatus, 100); });
521
+
522
+ //toggle pin class when lock toggle clicked
523
+ $(RPanelPin).on("click", function () {
524
+ SaveLocal("NavLockOn", $(RPanelPin).prop("checked"));
525
+ if ($(RPanelPin).prop("checked") == true) {
526
+ console.log('adding pin class to right nav');
527
+ $(RightNavPanel).addClass('pinnedOpen');
528
+ } else {
529
+ console.log('removing pin class from right nav');
530
+ $(RightNavPanel).removeClass('pinnedOpen');
531
+
532
+ if ($(RightNavPanel).hasClass('openDrawer') && $('.openDrawer').length > 1) {
533
+ $(RightNavPanel).slideToggle(200, "swing");
534
+ $(rightNavDrawerIcon).toggleClass('openIcon closedIcon');
535
+ $(RightNavPanel).toggleClass('openDrawer closedDrawer');
536
+ }
537
+ }
538
+ });
539
+ $(LPanelPin).on("click", function () {
540
+ SaveLocal("LNavLockOn", $(LPanelPin).prop("checked"));
541
+ if ($(LPanelPin).prop("checked") == true) {
542
+ console.log('adding pin class to Left nav');
543
+ $(LeftNavPanel).addClass('pinnedOpen');
544
+ } else {
545
+ console.log('removing pin class from Left nav');
546
+ $(LeftNavPanel).removeClass('pinnedOpen');
547
+
548
+ if ($(LeftNavPanel).hasClass('openDrawer') && $('.openDrawer').length > 1) {
549
+ $(LeftNavPanel).slideToggle(200, "swing");
550
+ $(leftNavDrawerIcon).toggleClass('openIcon closedIcon');
551
+ $(LeftNavPanel).toggleClass('openDrawer closedDrawer');
552
+ }
553
+ }
554
+ });
555
+
556
+ // read the state of right Nav Lock and apply to rightnav classlist
557
+ $(RPanelPin).prop('checked', LoadLocalBool("NavLockOn"));
558
+ if (LoadLocalBool("NavLockOn") == true) {
559
+ //console.log('setting pin class via local var');
560
+ $(RightNavPanel).addClass('pinnedOpen');
561
+ }
562
+ if ($(RPanelPin).prop('checked' == true)) {
563
+ console.log('setting pin class via checkbox state');
564
+ $(RightNavPanel).addClass('pinnedOpen');
565
+ }
566
+ // read the state of left Nav Lock and apply to leftnav classlist
567
+ $(LPanelPin).prop('checked', LoadLocalBool("LNavLockOn"));
568
+ if (LoadLocalBool("LNavLockOn") == true) {
569
+ //console.log('setting pin class via local var');
570
+ $(LeftNavPanel).addClass('pinnedOpen');
571
+ }
572
+ if ($(LPanelPin).prop('checked' == true)) {
573
+ console.log('setting pin class via checkbox state');
574
+ $(LeftNavPanel).addClass('pinnedOpen');
575
+ }
576
+
577
+ //save state of Right nav being open or closed
578
+ $("#rightNavDrawerIcon").on("click", function () {
579
+ if (!$("#rightNavDrawerIcon").hasClass('openIcon')) {
580
+ SaveLocal('NavOpened', 'true');
581
+ } else { SaveLocal('NavOpened', 'false'); }
582
+ });
583
+
584
+ //save state of Left nav being open or closed
585
+ $("#leftNavDrawerIcon").on("click", function () {
586
+ if (!$("#leftNavDrawerIcon").hasClass('openIcon')) {
587
+ SaveLocal('LNavOpened', 'true');
588
+ } else { SaveLocal('LNavOpened', 'false'); }
589
+ });
590
+
591
+ var chatbarInFocus = false;
592
+ $('#send_textarea').focus(function () {
593
+ chatbarInFocus = true;
594
+ });
595
+
596
+ $('#send_textarea').blur(function () {
597
+ chatbarInFocus = false;
598
+ });
599
+
600
+
601
+
602
+
603
+ setTimeout(() => {
604
+ OpenNavPanels();
605
+ }, 300);
606
+
607
+ //save AutoConnect and AutoLoadChat prefs
608
+ $(AutoConnectCheckbox).on("change", function () { SaveLocal("AutoConnectEnabled", $(AutoConnectCheckbox).prop("checked")); });
609
+ $(AutoLoadChatCheckbox).on("change", function () { SaveLocal("AutoLoadChatEnabled", $(AutoLoadChatCheckbox).prop("checked")); });
610
+
611
+ $(SelectedCharacterTab).click(function () { SaveLocal('SelectedNavTab', 'rm_button_selected_ch'); });
612
+ $("#rm_button_characters").click(function () { //if char list is clicked, in addition to saving it...
613
+ SaveLocal('SelectedNavTab', 'rm_button_characters');
614
+ characters.sort(Intl.Collator().compare); // we sort the list
615
+ });
616
+
617
+ // when a char is selected from the list, save them as the auto-load character for next page load
618
+ $(document).on("click", ".character_select", function () {
619
+ SaveLocal('ActiveChar', $(this).attr('chid'));
620
+ SaveLocal('ActiveGroup', null);
621
+ });
622
+
623
+ $(document).on("click", ".group_select", function () {
624
+ SaveLocal('ActiveChar', null);
625
+ SaveLocal('ActiveGroup', $(this).data('id'));
626
+ });
627
+
628
+ //this makes the chat input text area resize vertically to match the text size (limited by CSS at 50% window height)
629
+ $('#send_textarea').on('input', function () {
630
+ this.style.height = '40px';
631
+ this.style.height = (this.scrollHeight) + 'px';
632
+ });
633
+
634
+ //Regenerate if user swipes on the last mesage in chat
635
+
636
+ document.addEventListener('swiped-left', function (e) {
637
+ var SwipeButR = $('.swipe_right:last');
638
+ var SwipeTargetMesClassParent = e.target.closest('.last_mes');
639
+ if (SwipeTargetMesClassParent !== null) {
640
+ if (SwipeButR.css('display') === 'flex') {
641
+ SwipeButR.click();
642
+ }
643
+ }
644
+ });
645
+ document.addEventListener('swiped-right', function (e) {
646
+ var SwipeButL = $('.swipe_left:last');
647
+ var SwipeTargetMesClassParent = e.target.closest('.last_mes');
648
+ if (SwipeTargetMesClassParent !== null) {
649
+ if (SwipeButL.css('display') === 'flex') {
650
+ SwipeButL.click();
651
+ }
652
+ }
653
+ });
654
+
655
+
656
+ function isInputElementInFocus() {
657
+ //return $(document.activeElement).is(":input");
658
+ var focused = $(':focus');
659
+ if (focused.is('input') || focused.is('textarea')) {
660
+ if (focused.attr('id') === 'send_textarea') {
661
+ return false;
662
+ }
663
+ return true;
664
+ }
665
+ return false;
666
+ }
667
+
668
+
669
+
670
+
671
+
672
+ //Additional hotkeys CTRL+ENTER and CTRL+UPARROW
673
+ document.addEventListener("keydown", (event) => {
674
+ if (event.ctrlKey && event.key == "Enter") {
675
+ // Ctrl+Enter for Regeneration Last Response
676
+ if (is_send_press == false) {
677
+ $('#option_regenerate').click();
678
+ $('#options').hide();
679
+ }
680
+ }
681
+
682
+ if (event.ctrlKey && event.key == "ArrowLeft") { //for debug, show all local stored vars
683
+ CheckLocal();
684
+ }
685
+ /*
686
+ if (event.ctrlKey && event.key == "ArrowRight") { //for debug, empty local storage state
687
+ ClearLocal();
688
+ }
689
+ */
690
+ if (event.key == "ArrowLeft") { //swipes left
691
+ if (
692
+ $(".swipe_left:last").css('display') === 'flex' &&
693
+ $("#send_textarea").val() === '' &&
694
+ $("#character_popup").css("display") === "none" &&
695
+ $("#shadow_select_chat_popup").css("display") === "none" &&
696
+ !isInputElementInFocus()
697
+ ) {
698
+ $('.swipe_left:last').click();
699
+ }
700
+ }
701
+ if (event.key == "ArrowRight") { //swipes right
702
+ if (
703
+ $(".swipe_right:last").css('display') === 'flex' &&
704
+ $("#send_textarea").val() === '' &&
705
+ $("#character_popup").css("display") === "none" &&
706
+ $("#shadow_select_chat_popup").css("display") === "none" &&
707
+ !isInputElementInFocus()
708
+ ) {
709
+ $('.swipe_right:last').click();
710
+ }
711
+ }
712
+
713
+
714
+ if (event.ctrlKey && event.key == "ArrowUp") { //edits last USER message if chatbar is empty and focused
715
+ console.log('got ctrl+uparrow input');
716
+ if (
717
+ $("#send_textarea").val() === '' &&
718
+ chatbarInFocus === true &&
719
+ $(".swipe_right:last").css('display') === 'flex' &&
720
+ $("#character_popup").css("display") === "none" &&
721
+ $("#shadow_select_chat_popup").css("display") === "none"
722
+ ) {
723
+ const isUserMesList = document.querySelectorAll('div[is_user="true"]');
724
+ const lastIsUserMes = isUserMesList[isUserMesList.length - 1];
725
+ const editMes = lastIsUserMes.querySelector('.mes_block .mes_edit');
726
+ if (editMes !== null) {
727
+ $(editMes).click();
728
+ }
729
+ }
730
+ }
731
+
732
+ if (event.key == "ArrowUp") { //edits last message if chatbar is empty and focused
733
+ console.log('got uparrow input');
734
+ if (
735
+ $("#send_textarea").val() === '' &&
736
+ chatbarInFocus === true &&
737
+ $(".swipe_right:last").css('display') === 'flex' &&
738
+ $("#character_popup").css("display") === "none" &&
739
+ $("#shadow_select_chat_popup").css("display") === "none"
740
+ ) {
741
+ const lastMes = document.querySelector('.last_mes');
742
+ const editMes = lastMes.querySelector('.mes_block .mes_edit');
743
+ if (editMes !== null) {
744
+ $(editMes).click();
745
+ }
746
+ }
747
+ }
748
+
749
+ });
750
+ });