diff --git a/.gitignore b/.gitignore index ec1e67404..e71f3fc00 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ config.conf public/settings.json /thumbnails whitelist.txt +.vscode diff --git a/public/index.html b/public/index.html index 929940cfd..4b0ab9790 100644 --- a/public/index.html +++ b/public/index.html @@ -1415,13 +1415,25 @@

-
- Description - - ? - +
+
+ Favorite + + ? + +
+
+ +
+
-
+
+ Description + + ? + + +
@@ -1458,6 +1470,10 @@
+
+ +
@@ -1532,6 +1550,7 @@ +
diff --git a/public/notes/15.html b/public/notes/15.html new file mode 100644 index 000000000..5db0f97ad --- /dev/null +++ b/public/notes/15.html @@ -0,0 +1,21 @@ + + + TavernAI - Note - Favorite Character + + + + + + + + +
+
+

Favorite Character

+

+ Mark character as favorite to quickly filter on the side menu bar by pressing on the star button. +

+
+
+ + diff --git a/public/script.js b/public/script.js index 73ad32b3d..277453e37 100644 --- a/public/script.js +++ b/public/script.js @@ -203,6 +203,8 @@ let dialogueResolve = null; let chat_metadata = {}; let streamingProcessor = null; +let fav_ch_checked = false; +window.filterByFav = false; const durationSaveEdit = 200; const saveSettingsDebounced = debounce(() => saveSettings(), durationSaveEdit); @@ -329,6 +331,7 @@ var menu_type = ""; //what is selected in the menu var selected_button = ""; //which button pressed //create pole save var create_save_name = ""; +var create_fav_chara = ""; var create_save_description = ""; var create_save_personality = ""; var create_save_first_message = ""; @@ -634,8 +637,6 @@ function updateSoftPromptsList(soft_prompts) { } function printCharacters() { - //console.log('printCharacters() entered'); - $("#rm_print_characters_block").empty(); //console.log('printCharacters() -- sees '+characters.length+' characters.'); characters.forEach(function (item, i, arr) { @@ -647,7 +648,8 @@ function printCharacters() { `
-
${item.name}
+
${item.name} ${item.fav == "true" ? '' : ''}
+
` ); //console.log('printcharacters() -- printing -- ChID '+i+' ('+item.name+')'); @@ -1316,7 +1318,7 @@ class StreamingProcessor { } async function Generate(type, automatic_trigger, force_name2) { - console.log('Generate entered'); + //console.log('Generate entered'); setGenerationProgress(0); tokens_already_generated = 0; const isImpersonate = type == "impersonate"; @@ -3164,6 +3166,9 @@ function select_selected_character(chid) { if (characters[chid].avatar != "none") { this_avatar = getThumbnailUrl('avatar', characters[chid].avatar); } + + $("#fav_checkbox").prop("checked", characters[chid].fav == "true"); + $("#avatar_load_preview").attr("src", this_avatar); $("#name_div").css("display", "none"); @@ -3760,6 +3765,25 @@ $(document).ready(function () { } }); + $("#filter_by_fav").click(function() { + filterByFav = !filterByFav; + + const selector = ['#rm_print_characters_block .character_select', '#rm_print_characters_block .group_select'].join(','); + if(filterByFav){ + $(selector).each(function () { + if($(this).children(".ch_fav").length !== 0){ + $(this).children(".ch_fav").val().toLowerCase().includes(true) + ? $(this).show() + : $(this).hide(); + } + }); + $("#filter_by_fav").addClass("fav_on"); + }else{ + $(selector).show(); + $("#filter_by_fav").removeClass("fav_on"); + } + }); + $("#send_but").click(function () { if (is_send_press == false) { is_send_press = true; @@ -3802,6 +3826,7 @@ $(document).ready(function () { selected_button = "character_edit"; select_selected_character(this_chid); } + $("#character_search_bar").val("").trigger("input"); }); $(document).on("click", ".character_select", function () { @@ -3829,7 +3854,6 @@ $(document).ready(function () { selected_button = "character_edit"; select_selected_character(this_chid); } - $("#character_search_bar").val("").trigger("input"); }); @@ -4096,6 +4120,7 @@ $(document).ready(function () { $("#rm_info_avatar").html(""); let save_name = create_save_name; var formData = new FormData($("#form_create").get(0)); + formData.set('fav', fav_ch_checked); if ($("#form_create").attr("actiontype") == "createcharacter") { if ($("#character_name_pole").val().length > 0) { //if the character name text area isn't empty (only posible when creating a new character) @@ -4262,11 +4287,18 @@ $(document).ready(function () { create_save_scenario = $("#scenario_pole").val(); create_save_mes_example = $("#mes_example_textarea").val(); create_save_first_message = $("#firstmessage_textarea").val(); + create_fav_chara = $("#fav_checkbox").val(); } else { saveCharacterDebounced(); } }); + $("#fav_checkbox").change(function(){ + fav_ch_checked = $(this).prop("checked"); + if (menu_type != "create") { + saveCharacterDebounced(); + } + }); $("#talkativeness_slider").on("input", function () { if (menu_type == "create") { diff --git a/public/scripts/group-chats.js b/public/scripts/group-chats.js index 12752d1e5..bf53c4491 100644 --- a/public/scripts/group-chats.js +++ b/public/scripts/group-chats.js @@ -214,7 +214,9 @@ function printGroups() { const template = $("#group_list_template .group_select").clone(); template.data("id", group.id); template.attr("grid", group.id); - template.find(".ch_name").text(group.name); + template.find(".ch_name").html(group.name); + group.fav ? template.find(".group_fav_icon").show() : template.find(".group_fav_icon").hide(); + template.find(".ch_fav").val(group.fav); $("#rm_print_characters_block").prepend(template); updateGroupAvatar(group); } @@ -695,7 +697,6 @@ async function reorderGroupMember(chat_id, groupMember, direction) { function select_group_chats(chat_id, skipAnimation) { const group = chat_id && groups.find((x) => x.id == chat_id); const groupName = group?.name ?? ""; - $("#rm_group_chat_name").val(groupName); $("#rm_group_chat_name").off(); $("#rm_group_chat_name").on("input", async function () { @@ -753,6 +754,7 @@ function select_group_chats(chat_id, skipAnimation) { const groupHasMembers = !!$("#rm_group_members").children().length; $("#rm_group_submit").prop("disabled", !groupHasMembers); $("#rm_group_allow_self_responses").prop("checked", group && group.allow_self_responses); + $("#rm_group_fav").prop("checked", group && group.fav); // bottom buttons if (chat_id) { @@ -774,6 +776,15 @@ function select_group_chats(chat_id, skipAnimation) { callPopup("

Delete the group?

", "del_group"); }); + $("#rm_group_fav").off(); + $("#rm_group_fav").on("input", async function(){ + if (group) { + const value = $(this).prop("checked"); + group.fav = value; + await editGroup(chat_id); + } + }); + $("#rm_group_allow_self_responses").off(); $("#rm_group_allow_self_responses").on("input", async function () { if (group) { @@ -829,6 +840,9 @@ $(document).ready(() => { updateChatMetadata({}, true); chat.length = 0; await getGroupChat(id); + //to avoid the filter being lit up yellow and left at true while the list of character and group reseted. + $("#filter_by_fav").removeClass("fav_on"); + filterByFav = false; } select_group_chats(id); @@ -852,6 +866,7 @@ $(document).ready(() => { $("#rm_group_submit").click(async function () { let name = $("#rm_group_chat_name").val(); let allow_self_responses = !!$("#rm_group_allow_self_responses").prop("checked"); + let fav = $("#rm_group_fav").prop("checked"); let activation_strategy = $('input[name="rm_group_activation_strategy"]:checked').val() ?? group_activation_strategy.NATURAL; const members = $("#rm_group_members .group_member") .map((_, x) => $(x).data("id")) @@ -877,6 +892,7 @@ $(document).ready(() => { allow_self_responses: allow_self_responses, activation_strategy: activation_strategy, chat_metadata: {}, + fav: fav, }), }); diff --git a/public/style.css b/public/style.css index f312124b6..c132061bc 100644 --- a/public/style.css +++ b/public/style.css @@ -909,6 +909,9 @@ select option:not(:checked) { cursor: not-allowed; } +.fav_on { + color: #ffff00 !important; +} #api_url_text, #textgenerationwebui_api_url_text { @@ -1138,6 +1141,17 @@ input[type=search]:focus::-webkit-search-cancel-button { margin-bottom: 4px; } +#fav_chara_wrap{ + display: flex; + margin: 5px 0px; +} + +#fav_chara { + border: none; + font-size: var(--mainFontSize); + display: flex; +} + #description_div { position: relative; } @@ -2484,12 +2498,15 @@ h5 { } .group_select .ch_name { - flex-grow: 1; max-width: calc(100% - 100px); overflow: hidden; text-overflow: ellipsis; } +.group_select .group_fav_icon{ + margin-left: 5px; +} + #typing_indicator_template { display: none !important; } diff --git a/server.js b/server.js index 410385c63..c1c0404d6 100644 --- a/server.js +++ b/server.js @@ -681,7 +681,7 @@ function checkServer() { //***************** Main functions function charaFormatData(data) { - var char = { "name": data.ch_name, "description": data.description, "personality": data.personality, "first_mes": data.first_mes, "avatar": 'none', "chat": data.ch_name + ' - ' + humanizedISO8601DateTime(), "mes_example": data.mes_example, "scenario": data.scenario, "create_date": humanizedISO8601DateTime(), "talkativeness": data.talkativeness }; + var char = { "name": data.ch_name, "description": data.description, "personality": data.personality, "first_mes": data.first_mes, "avatar": 'none', "chat": data.ch_name + ' - ' + humanizedISO8601DateTime(), "mes_example": data.mes_example, "scenario": data.scenario, "create_date": humanizedISO8601DateTime(), "talkativeness": data.talkativeness, "fav": data.fav}; return char; } app.post("/createcharacter", urlencodedParser, function (request, response) { @@ -735,10 +735,8 @@ app.post("/editcharacter", urlencodedParser, async function (request, response) var char = charaFormatData(request.body);//{"name": request.body.ch_name, "description": request.body.description, "personality": request.body.personality, "first_mes": request.body.first_mes, "avatar": request.body.avatar_url, "chat": request.body.chat, "last_mes": request.body.last_mes, "mes_example": ''}; char.chat = request.body.chat; char.create_date = request.body.create_date; - char = JSON.stringify(char); let target_img = (request.body.avatar_url).replace('.png', ''); - try { if (!filedata) { @@ -1761,6 +1759,7 @@ app.post('/creategroup', jsonParser, (request, response) => { allow_self_responses: !!request.body.allow_self_responses, activation_strategy: request.body.activation_strategy ?? 0, chat_metadata: request.body.chat_metadata ?? {}, + fav: request.body.fav, }; const pathToFile = path.join(directories.groups, `${id}.json`); const fileData = JSON.stringify(chatMetadata); @@ -1777,7 +1776,6 @@ app.post('/editgroup', jsonParser, (request, response) => { if (!request.body || !request.body.id) { return response.sendStatus(400); } - const id = request.body.id; const pathToFile = path.join(directories.groups, `${id}.json`); const fileData = JSON.stringify(request.body);