diff --git a/public/index.html b/public/index.html index 3833b8760..8fbef0fb5 100644 --- a/public/index.html +++ b/public/index.html @@ -989,48 +989,48 @@
-
- +
+ - + - -

API key

-
Get it here: Register
- Enter 0000000000 to use anonymous mode. -
-
- View my Kudos -
-
- - -
-
For privacy reasons, your API key will be hidden after you reload the page.
-

- Model -
-
+ +

API key

+
Get it here: Register
+ Enter 0000000000 to use anonymous mode. +
+ -

- Hold Control / Command key to select multiple models. - -
+
+ + +
+
For privacy reasons, your API key will be hidden after you reload the page.
+

+ Model +
+
+
+

+ Hold Control / Command key to select multiple models. + +
Not connected
@@ -1931,6 +1931,7 @@ + @@ -2221,7 +2222,7 @@

Context Template Editor

-

+

@@ -2657,4 +2658,4 @@ - + \ No newline at end of file diff --git a/public/script.js b/public/script.js index 87263296f..1f7b489e1 100644 --- a/public/script.js +++ b/public/script.js @@ -4258,30 +4258,38 @@ function select_rm_info(type, charId, previousCharId = null) { toastr.error(`Invalid process (no 'type')`); return; } + if (type !== 'group_create') { + var displayName = String(charId).replace('.png', ''); + } + if (type === 'char_delete') { - toastr.warning(`Character Deleted: ${charId}`); + toastr.warning(`Character Deleted: ${displayName}`); } if (type === 'char_create') { - toastr.success(`Character Created: ${charId}`); + toastr.success(`Character Created: ${displayName}`); } if (type === 'group_create') { toastr.success(`Group Created`); } - if (type === 'char_import') { - toastr.success(`Character Imported: ${charId}`); + if (type === 'group_delete') { + toastr.warning(`Group Deleted`); } + if (type === 'char_import') { + toastr.success(`Character Imported: ${displayName}`); + } + + getCharacters(); selectRightMenuWithAnimation('rm_characters_block'); if (type === 'char_import' || type === 'char_create') { - //$(`#rm_characters_block [title="${charId + '.png'}"]`).scrollIntoView({ behavior: "smooth", block: "end" }); - const element = $(`#rm_characters_block [title="${charId + '.png'}"]`).get(0); + const element = $(`#rm_characters_block [title="${charId}"]`).get(0); element.scrollIntoView({ behavior: 'smooth', block: 'end' }); - $(`#rm_characters_block [title="${charId + '.png'}"]`).parent().addClass('flash animated'); + $(`#rm_characters_block [title="${charId}"]`).parent().addClass('flash animated'); setTimeout(function () { - $(`#rm_characters_block [title="${charId + '.png'}"]`).parent().removeClass('flash animated'); + $(`#rm_characters_block [title="${charId}"]`).parent().removeClass('flash animated'); }, 5000); } @@ -4319,7 +4327,8 @@ export function select_selected_character(chid) { $("#rm_button_back").css("display", "none"); //$("#character_import_button").css("display", "none"); $("#create_button").attr("value", "Save"); // what is the use case for this? - $("#create_button_label").css("display", "none"); + $("#dupe_button").show(); + //$("#create_button_label").css("display", "none"); // Don't update the navbar name if we're peeking the group member defs if (!selected_group) { @@ -4376,8 +4385,7 @@ function select_rm_create() { $("#export_button").css("display", "none"); $("#create_button_label").css("display", ""); $("#create_button").attr("value", "Create"); - //RossAscends: commented this out as part of the auto-loading token counter - //$('#result_info').html(' '); + $("#dupe_button").hide(); //create text poles $("#rm_button_back").css("display", ""); @@ -4511,7 +4519,7 @@ function read_bg_load(input) { url: "/downloadbackground", data: formData, beforeSend: function () { - //$('#create_button').attr('value','Creating...'); + }, cache: false, contentType: false, @@ -5412,7 +5420,6 @@ $(document).ready(function () { url: "/deletecharacter", beforeSend: function () { select_rm_info("char_delete", characters[this_chid].name); - //$('#create_button').attr('value','Deleting...'); }, data: msg, cache: false, @@ -5593,7 +5600,7 @@ $(document).ready(function () { $("#rm_info_block").transition({ opacity: 0, duration: 0 }); var $prev_img = $("#avatar_div_div").clone(); $("#rm_info_avatar").append($prev_img); - select_rm_info(`char_create`, save_name, oldSelectedChar); + select_rm_info(`char_create`, html, oldSelectedChar); $("#rm_info_block").transition({ opacity: 1.0, duration: 2000 }); crop_data = undefined; @@ -5617,7 +5624,7 @@ $(document).ready(function () { url: url, data: formData, beforeSend: function () { - //$("#create_button").attr("disabled", true); + $("#create_button").attr("disabled", true); $("#create_button").attr("value", "Save"); }, cache: false, @@ -6548,6 +6555,20 @@ $(document).ready(function () { select_rm_characters(); }); + $("#dupe_button").click(async function () { + + const body = { avatar_url: characters[this_chid].avatar }; + const response = await fetch('/dupecharacter', { + method: 'POST', + headers: getRequestHeaders(), + body: JSON.stringify(body), + }); + if (response.ok) { + toastr.success("Character Duplicated"); + getCharacters(); + } + }); + $(document).on("click", ".select_chat_block, .bookmark_link, .mes_bookmark", async function () { let file_name = $(this).hasClass('mes_bookmark') ? $(this).closest('.mes').attr('bookmark_link') diff --git a/public/scripts/group-chats.js b/public/scripts/group-chats.js index 8bb80735b..db471c403 100644 --- a/public/scripts/group-chats.js +++ b/public/scripts/group-chats.js @@ -762,7 +762,7 @@ async function deleteGroup(id) { $("#rm_info_avatar").html(""); $("#rm_info_block").transition({ opacity: 0, duration: 0 }); - select_rm_info("Group deleted!"); + select_rm_info("group_delete", id); $("#rm_info_block").transition({ opacity: 1.0, duration: 2000 }); $("#rm_button_selected_ch").children("h2").text(''); diff --git a/server.js b/server.js index 05c6500a7..09d5486d6 100644 --- a/server.js +++ b/server.js @@ -1545,6 +1545,39 @@ app.post("/importcharacter", urlencodedParser, async function (request, response } }); +app.post("/dupecharacter", jsonParser, async function (request, response) { + try { + if (!request.body.avatar_url) { + console.log("avatar URL not found in request body"); + console.log(request.body); + return response.sendStatus(400); + } + let filename = path.join(directories.characters, sanitize(request.body.avatar_url)); + if (!fs.existsSync(filename)) { + console.log('file for dupe not found'); + console.log(filename); + return response.sendStatus(404); + } + let suffix = 1; + let newFilename = filename; + while (fs.existsSync(newFilename)) { + let suffixStr = "_" + suffix; + let ext = path.extname(filename); + newFilename = filename.slice(0, -ext.length) + suffixStr + ext; + suffix++; + } + fs.copyFile(filename, newFilename, (err) => { + if (err) throw err; + console.log(`${filename} was copied to ${newFilename}`); + response.sendStatus(200); + }); + } + catch (error) { + console.error(error); + return response.send({ error: true }); + } +}); + app.post("/exportcharacter", jsonParser, async function (request, response) { if (!request.body.format || !request.body.avatar_url) { return response.sendStatus(400);