From 14a266e3551c1359a39f896972c333d5efd5dba2 Mon Sep 17 00:00:00 2001 From: somebody Date: Sun, 28 Aug 2022 21:28:07 -0500 Subject: [PATCH 1/2] File upload wip --- static/koboldai.css | 21 ++++++++ static/koboldai.js | 106 +++++++++++++++++++++++++++++++++++++++ templates/index_new.html | 4 ++ 3 files changed, 131 insertions(+) diff --git a/static/koboldai.css b/static/koboldai.css index fe784ae9..a8d78532 100644 --- a/static/koboldai.css +++ b/static/koboldai.css @@ -1638,6 +1638,27 @@ body { .context-an {background-color: var(--context_colors_authors_notes);} .context-action {background-color: var(--context_colors_game_text);} +/* File Drag Indicator */ +#file-upload-notice { + display: flex; + justify-content: center; + align-items: center; + + position: absolute; + left: 0px; + top: 0px; + + background-color: rgba(0, 0, 0, 0.5); + z-index: 20; + + width: 100vw; + height: 100vh; +} + +#file-upload-notice > span { + font-size: 50vh; + opacity: 0.7; +} /*---------------------------------- Global ------------------------------------------------*/ .hidden { display: none; diff --git a/static/koboldai.js b/static/koboldai.js index f974bc6d..b1ca307e 100644 --- a/static/koboldai.js +++ b/static/koboldai.js @@ -2847,6 +2847,75 @@ function detect_key_up(e) { } } +function loadNAILorebook(data) { + let lorebookVersion = data.lorebookVersion; + console.log(`Loading NAI lorebook version ${lorebookVersion}`); + + // TODO: Make folder + let folder = "root"; + + let uid = -1; + for (item of document.getElementsByClassName('world_info_card')) { + if (parseInt(item.getAttribute("uid")) <= uid) { + uid = parseInt(item.getAttribute("uid")) - 1; + } + } + + for (const entry of data.entries) { + console.log(entry); + // contextConfig: Object { suffix: "\n", tokenBudget: 2048, reservedTokens: 0, … } + // displayName: "Aboleth" + // enabled: true + // forceActivation: false + // keys: Array [ "Aboleth" ] + // lastUpdatedAt: 1624443329051 + // searchRange: 1000 + // text + data = { + "uid": uid, + "title": entry.displayName, + "key": entry.keys, + "keysecondary": [], + "folder": folder, + "constant": entry.forceActivation, + "content": "",//entry.text, + "manual_text": entry.text, + "comment": "", + "token_length": 0, + "selective": false, + "wpp": {"name": "", "type": "", "format": "W++", "attributes": {}}, + "use_wpp": false, + }; + uid--; + card = world_info_entry(data); + card.scrollIntoView(false); + console.log(card); + } + +} + +async function processDroppedFile(file) { + let extension = /.*\.(.*)/.exec(file.name)[1]; + console.log("file is", file) + + switch (extension) { + case "png": + // TODO: Support NovelAI's image lorebook cards. The format for those + // is base64-encoded JSON under a TXT key called "naidata". + console.warn("TODO: NAI LORECARDS"); + return; + case "json": + // KoboldAI story (probably, parse to be sure.); + console.warn("TODO: KOBOLD STORY"); + break; + case "lorebook": + // NovelAI lorebook, JSON encoded. + let data = JSON.parse(await file.text()); + loadNAILorebook(data); + break; + } +} + $(document).ready(function(){ create_theming_elements(); document.onkeydown = detect_key_down; @@ -2915,4 +2984,41 @@ $(document).ready(function(){ $(".token_breakdown").click(function() { document.getElementById("context-viewer-container").classList.remove("hidden"); }); + + document.body.addEventListener("drop", function(e) { + e.preventDefault(); + $("#file-upload-notice")[0].classList.add("hidden"); + + // items api + if (e.dataTransfer.items) { + for (const item of e.dataTransfer.items) { + if (item.kind !== "file") continue; + let file = item.getAsFile(); + processDroppedFile(file); + } + } else { + for (const file of e.dataTransfer.files) { + processDroppedFile(file); + } + } + }); + + let lastTarget = null; + + document.body.addEventListener("dragover", function(e) { + e.preventDefault(); + }); + + document.body.addEventListener("dragenter", function(e) { + lastTarget = e.target; + console.log("start"); + $("#file-upload-notice")[0].classList.remove("hidden"); + }); + + document.body.addEventListener("dragleave", function(e) { + if (!(e.target === document || e.target === lastTarget)) return; + + console.log("end") + $("#file-upload-notice")[0].classList.add("hidden"); + }); }); diff --git a/templates/index_new.html b/templates/index_new.html index f21e54f8..a13b4920 100644 --- a/templates/index_new.html +++ b/templates/index_new.html @@ -139,5 +139,9 @@
+ + \ No newline at end of file From 1cf131a6ccd99c2182fb613d61e616d1e8e1143c Mon Sep 17 00:00:00 2001 From: somebody Date: Mon, 29 Aug 2022 17:49:31 -0500 Subject: [PATCH 2/2] Improve drag thingey --- aiserver.py | 24 ++++++++++++++++++ koboldai_settings.py | 1 + static/koboldai.css | 2 +- static/koboldai.js | 60 +++++++++++++++++++++++++++----------------- 4 files changed, 63 insertions(+), 24 deletions(-) diff --git a/aiserver.py b/aiserver.py index 53a7024a..91c25ab0 100644 --- a/aiserver.py +++ b/aiserver.py @@ -7337,6 +7337,30 @@ def UI_2_upload_world_info_folder(data): json_data = json.loads(data['data']) koboldai_vars.worldinfo_v2.load_json(json_data, folder=data['folder']) +@socketio.on('import_world_info') +def UI_2_import_world_info(data): + wi_data = data["data"] + uids = {} + + for folder_name, children in wi_data["folders"].items(): + koboldai_vars.worldinfo_v2.add_folder(folder_name) + for child in children: + # Child is index + if child not in uids: + entry_data = wi_data["entries"][str(child)] + uids[child] = koboldai_vars.worldinfo_v2.add_item( + title=entry_data["title"], + key=entry_data["key"], + keysecondary=entry_data["keysecondary"], + folder=folder_name, + constant=entry_data["constant"], + manual_text=entry_data["manual_text"], + comment=entry_data["comment"], + use_wpp=entry_data["use_wpp"], + wpp=entry_data["wpp"], + ) + koboldai_vars.worldinfo_v2.add_item_to_folder(uids[child], folder_name) + #==================================================================# # Event triggered when user edits phrase biases diff --git a/koboldai_settings.py b/koboldai_settings.py index 43073bff..aa02bfaa 100644 --- a/koboldai_settings.py +++ b/koboldai_settings.py @@ -1258,6 +1258,7 @@ class KoboldWorldInfo(object): self.socketio.emit("world_info_folder", {x: self.world_info_folder[x] for x in self.world_info_folder}, broadcast=True, room="UI_2") self.socketio.emit("world_info_entry", self.world_info[uid], broadcast=True, room="UI_2") ignore = self.koboldai_vars.calc_ai_text() + return uid def edit_item(self, uid, title, key, keysecondary, folder, constant, manual_text, comment, use_wpp=False, before=None, wpp={'name': "", 'type': "", 'format': "W++", 'attributes': {}}): old_folder = self.world_info[uid]['folder'] diff --git a/static/koboldai.css b/static/koboldai.css index 536f9b9b..85dcfd95 100644 --- a/static/koboldai.css +++ b/static/koboldai.css @@ -1695,7 +1695,7 @@ body { top: 0px; background-color: rgba(0, 0, 0, 0.5); - z-index: 20; + z-index: 99999999; width: 100vw; height: 100vh; diff --git a/static/koboldai.js b/static/koboldai.js index 500faf52..c78c888a 100644 --- a/static/koboldai.js +++ b/static/koboldai.js @@ -2918,22 +2918,13 @@ function detect_key_up(e) { } } -function loadNAILorebook(data) { +function loadNAILorebook(data, filename) { let lorebookVersion = data.lorebookVersion; + let wi_data = {folders: {[filename]: []}, entries: {}}; console.log(`Loading NAI lorebook version ${lorebookVersion}`); - // TODO: Make folder - let folder = "root"; - - let uid = -1; - for (item of document.getElementsByClassName('world_info_card')) { - if (parseInt(item.getAttribute("uid")) <= uid) { - uid = parseInt(item.getAttribute("uid")) - 1; - } - } - + let i = 0; for (const entry of data.entries) { - console.log(entry); // contextConfig: Object { suffix: "\n", tokenBudget: 2048, reservedTokens: 0, … } // displayName: "Aboleth" // enabled: true @@ -2942,14 +2933,15 @@ function loadNAILorebook(data) { // lastUpdatedAt: 1624443329051 // searchRange: 1000 // text - data = { + + wi_data.entries[i.toString()] = { "uid": uid, "title": entry.displayName, "key": entry.keys, "keysecondary": [], "folder": folder, "constant": entry.forceActivation, - "content": "",//entry.text, + "content": "", "manual_text": entry.text, "comment": "", "token_length": 0, @@ -2957,17 +2949,32 @@ function loadNAILorebook(data) { "wpp": {"name": "", "type": "", "format": "W++", "attributes": {}}, "use_wpp": false, }; - uid--; - card = world_info_entry(data); - card.scrollIntoView(false); - console.log(card); - } + wi_data.folders[filename].push(i); + i++; + } + socket.emit("import_world_info", {data: wi_data}); +} + +async function loadKoboldData(data, filename) { + if (data.gamestarted !== undefined) { + // Story + socket.emit("upload_file", {"filename": filename, "data": JSON.stringify(data)}); + socket.emit("load_story_list", ""); + } else if (data.folders !== undefined && data.entries !== undefined) { + // World Info Folder + socket.emit("import_world_info", {data: data}); + } else { + // Bad data + console.error("Bad data!"); + return; + } } async function processDroppedFile(file) { let extension = /.*\.(.*)/.exec(file.name)[1]; console.log("file is", file) + let data; switch (extension) { case "png": @@ -2976,14 +2983,21 @@ async function processDroppedFile(file) { console.warn("TODO: NAI LORECARDS"); return; case "json": - // KoboldAI story (probably, parse to be sure.); - console.warn("TODO: KOBOLD STORY"); + // KoboldAI file + data = JSON.parse(await file.text()); + loadKoboldData(data, file.name); break; case "lorebook": // NovelAI lorebook, JSON encoded. - let data = JSON.parse(await file.text()); - loadNAILorebook(data); + data = JSON.parse(await file.text()); + loadNAILorebook(data, file.name); break; + case "css": + console.warn("TODO: THEME"); + break; + case "lua": + console.warn("TODO: USERSCRIPT"); + break } }