diff --git a/public/script.js b/public/script.js
index 66a2798af..193d1c14e 100644
--- a/public/script.js
+++ b/public/script.js
@@ -102,6 +102,7 @@ export {
online_status,
main_api,
api_server,
+ system_messages,
nai_settings,
token,
name1,
@@ -163,6 +164,8 @@ const system_message_types = {
GROUP: "group",
EMPTY: "empty",
GENERIC: "generic",
+ BOOKMARK_CREATED: "bookmark_created",
+ BOOKMARK_BACK: "bookmark_back",
};
const system_messages = {
@@ -223,6 +226,22 @@ const system_messages = {
is_name: true,
mes: "Generic system message. User `text` parameter to override the contents",
},
+ bookmark_created: {
+ name: systemUserName,
+ force_avatar: system_avatar,
+ is_user: false,
+ is_system: true,
+ is_name: true,
+ mes: `Bookmark created! Click here to open the bookmark chat:
{0}`,
+ },
+ bookmark_back: {
+ name: systemUserName,
+ force_avatar: system_avatar,
+ is_user: false,
+ is_system: true,
+ is_name: true,
+ mes: `Click here to return to the original chat:
{0}`,
+ },
};
const talkativeness_default = 0.5;
@@ -711,9 +730,9 @@ function messageFormating(mes, ch_name, isSystem, forceAvatar) {
return mes;
}
-function getMessageFromTemplate(mesId, characterName, isUser, avatarImg, bias) {
+function getMessageFromTemplate(mesId, characterName, isUser, avatarImg, bias, isSystem) {
const mes = $('#message_template .mes').clone();
- mes.attr({ 'mesid': mesId, 'ch_name': characterName, 'is_user': isUser });
+ mes.attr({ 'mesid': mesId, 'ch_name': characterName, 'is_user': isUser, 'is_system': !!isSystem });
mes.find('.avatar img').attr('src', avatarImg);
mes.find('.ch_name .name_text').text(characterName);
mes.find('.mes_bias').html(bias);
@@ -767,7 +786,7 @@ function addOneMessage(mes, type = "normal") {
);
const bias = messageFormating(mes.extra?.bias ?? "");
- var HTMLForEachMes = getMessageFromTemplate(count_view_mes, characterName, mes.is_user, avatarImg, bias);
+ var HTMLForEachMes = getMessageFromTemplate(count_view_mes, characterName, mes.is_user, avatarImg, bias, isSystem);
if (type !== 'swipe') {
$("#chat").append(HTMLForEachMes);
@@ -1686,7 +1705,8 @@ function resultCheckStatusNovel() {
$("#api_button_novel").css("display", "inline-block");
}
-async function saveChat() {
+async function saveChat(chat_name) {
+ let file_name = chat_name ?? characters[this_chid].chat;
chat.forEach(function (item, i) {
if (item["is_group"]) {
alert('Trying to save group chat with regular saveChat function. Aborting to prevent corruption.');
@@ -1714,7 +1734,7 @@ async function saveChat() {
url: "/savechat",
data: JSON.stringify({
ch_name: characters[this_chid].name,
- file_name: characters[this_chid].chat,
+ file_name: file_name,
chat: save_chat,
avatar_url: characters[this_chid].avatar,
}),
@@ -3318,6 +3338,9 @@ $(document).ready(function () {
processData: false,
success: function (html) {
$(".mes").each(function () {
+ if ($(this).attr("is_system") == 'true') {
+ return;
+ }
if ($(this).attr("ch_name") != name1) {
$(this)
.children(".avatar")
@@ -4035,7 +4058,7 @@ $(document).ready(function () {
selectRightMenuWithAnimation('rm_extensions_block');
});
- $(document).on("click", ".select_chat_block", function () {
+ $(document).on("click", ".select_chat_block, .bookmark_link", function () {
let file_name = $(this).attr("file_name").replace(".jsonl", "");
//console.log(characters[this_chid]['chat']);
characters[this_chid]["chat"] = file_name;
diff --git a/public/scripts/bookmarks.js b/public/scripts/bookmarks.js
new file mode 100644
index 000000000..9ea56c585
--- /dev/null
+++ b/public/scripts/bookmarks.js
@@ -0,0 +1,61 @@
+import {
+ characters,
+ saveChat,
+ sendSystemMessage,
+ deleteLastMessage,
+ token,
+ system_messages,
+ system_message_types,
+ this_chid,
+} from "../script.js";
+import { selected_group } from "./group-chats.js";
+
+import {
+ stringFormat,
+} from "./utils.js";
+
+async function getExistingChatNames() {
+ const response = await fetch("/getallchatsofcharacter", {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ "X-CSRF-Token": token,
+ },
+ body: JSON.stringify({ avatar_url: characters[this_chid].avatar})
+ });
+
+ if (response.ok) {
+ const data = await response.json();
+ return Object.values(data).map(x => x.file_name.replace('.jsonl', ''));
+ }
+}
+
+async function getBookmarkName() {
+ const chatNames = await getExistingChatNames();
+ let newChat = Date.now();
+
+ for (let i = 0; i < 1000; i++) {
+ newChat = `Bookmark - ${i}`;
+ if (!chatNames.includes(newChat)) {
+ break;
+ }
+ }
+ return newChat;
+}
+
+$(document).ready(function () {
+ $('#option_new_bookmark').on('click', async function () {
+ if (selected_group) {
+ alert('Unsupported for groups');
+ throw new Error('not yet implemented');
+ }
+
+ let newChat = await getBookmarkName();
+
+ saveChat(newChat);
+ let mainMessage = stringFormat(system_messages[system_message_types.BOOKMARK_CREATED].mes, newChat);
+ sendSystemMessage(system_message_types.BOOKMARK_CREATED, mainMessage);
+ saveChat();
+ });
+});
+
diff --git a/public/scripts/utils.js b/public/scripts/utils.js
index 321d1e12d..63c53ac80 100644
--- a/public/scripts/utils.js
+++ b/public/scripts/utils.js
@@ -8,6 +8,8 @@ export {
debounce,
delay,
isSubsetOf,
+ incrementString,
+ stringFormat,
};
/// UTILS
@@ -86,3 +88,22 @@ function debounce(func, timeout = 300) {
const delay = (ms) => new Promise((res) => setTimeout(res, ms));
const isSubsetOf = (a, b) => (Array.isArray(a) && Array.isArray(b)) ? b.every(val => a.includes(val)) : false;
+
+function incrementString(str) {
+ // Find the trailing number or it will match the empty string
+ const count = str.match(/\d*$/);
+
+ // Take the substring up until where the integer was matched
+ // Concatenate it to the matched count incremented by 1
+ return str.substr(0, count.index) + (++count[0]);
+};
+
+function stringFormat(format) {
+ const args = Array.prototype.slice.call(arguments, 1);
+ return format.replace(/{(\d+)}/g, function (match, number) {
+ return typeof args[number] != 'undefined'
+ ? args[number]
+ : match
+ ;
+ });
+};
\ No newline at end of file
diff --git a/public/style.css b/public/style.css
index c1fe4fea2..bc3a16b9b 100644
--- a/public/style.css
+++ b/public/style.css
@@ -1970,7 +1970,8 @@ input[type="range"]{
position: absolute;
width: 100%;
height: 100vh;
- z-index: 2059;
+ z-index: 3001;
+ top: 0;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}