+
diff --git a/public/script.js b/public/script.js
index 15a6f41fd..964927eb4 100644
--- a/public/script.js
+++ b/public/script.js
@@ -116,6 +116,8 @@ import {
countOccurrences,
isOdd,
isElementInViewport,
+ sortMoments,
+ timestampToMoment,
} from "./scripts/utils.js";
import { extension_settings, loadExtensionSettings, runGenerationInterceptors } from "./scripts/extensions.js";
@@ -1503,7 +1505,7 @@ class StreamingProcessor {
return;
}
- $(`#chat .mes[mesid="${messageId}"] .mes_stop`).css({ 'display': '' });
+ $(`#chat .mes[mesid="${messageId}"] .mes_stop`).css({ 'display': 'block' });
$(`#chat .mes[mesid="${messageId}"] .mes_buttons`).css({ 'display': 'none' });
}
@@ -1513,7 +1515,7 @@ class StreamingProcessor {
}
$(`#chat .mes[mesid="${messageId}"] .mes_stop`).css({ 'display': 'none' });
- $(`#chat .mes[mesid="${messageId}"] .mes_buttons`).css({ 'display': '' });
+ $(`#chat .mes[mesid="${messageId}"] .mes_buttons`).css({ 'display': 'block' });
}
onStartStreaming(text) {
@@ -4040,6 +4042,9 @@ export async function displayPastChats() {
const displayName = selected_group ? group?.name : characters[this_chid].name;
const avatarImg = selected_group ? group?.avatar_url : getThumbnailUrl('avatar', characters[this_chid]['avatar']);
+ // Sort by last message date descending
+ data.sort((a, b) => sortMoments(timestampToMoment(a.last_mes), timestampToMoment(b.last_mes)));
+
$("#load_select_chat_div").css("display", "none");
$("#ChatHistoryCharName").text(displayName);
for (const key in data) {
@@ -4053,6 +4058,7 @@ export async function displayPastChats() {
const chat_items = data[key]["chat_items"];
const file_size = data[key]["file_size"];
const fileName = data[key]['file_name'];
+ const timestamp = timestampToMoment(data[key]['last_mes']).format('LL LT');
const template = $('#past_chat_template .select_chat_block_wrapper').clone();
template.find('.select_chat_block').attr('file_name', fileName);
template.find('.avatar img').attr('src', avatarImg);
@@ -4061,6 +4067,7 @@ export async function displayPastChats() {
template.find('.chat_messages_num').text(" (" + chat_items + " messages)");
template.find('.select_chat_block_mes').text(mes);
template.find('.PastChat_cross').attr('file_name', fileName);
+ template.find('.chat_messages_date').text(timestamp);
if (selected_group) {
template.find('.avatar img').replaceWith(getGroupAvatar(group));
diff --git a/public/scripts/group-chats.js b/public/scripts/group-chats.js
index 90f189f1f..3876c7965 100644
--- a/public/scripts/group-chats.js
+++ b/public/scripts/group-chats.js
@@ -1206,9 +1206,11 @@ export async function getGroupPastChats(groupId) {
let this_chat_file_size = (JSON.stringify(messages).length / 1024).toFixed(2) + "kb";
let chat_items = messages.length;
const lastMessage = messages.length ? messages[messages.length - 1].mes : '[The chat is empty]';
+ const lastMessageDate = messages.length ? (messages[messages.length - 1].send_date || Date.now()) : Date.now();
chats.push({
'file_name': chatId,
'mes': lastMessage,
+ 'last_mes': lastMessageDate,
'file_size': this_chat_file_size,
'chat_items': chat_items,
});
@@ -1303,7 +1305,7 @@ export async function importGroupChat(formData) {
if (data.res) {
const chatId = data.res;
const group = groups.find(x => x.id == selected_group);
-
+
if (group) {
group.chats.push(chatId);
await editGroup(selected_group, true, true);
@@ -1369,4 +1371,4 @@ jQuery(() => {
const value = $(this).prop("checked");
is_group_automode_enabled = value;
});
-});
\ No newline at end of file
+});
diff --git a/public/scripts/utils.js b/public/scripts/utils.js
index 61f0d1321..d9b921ccc 100644
--- a/public/scripts/utils.js
+++ b/public/scripts/utils.js
@@ -259,6 +259,31 @@ export function isOdd(number) {
return number % 2 !== 0;
}
+export function timestampToMoment(timestamp) {
+ // Unix time (legacy TAI)
+ if (typeof timestamp === 'number') {
+ return moment(timestamp);
+ }
+
+ // ST "humanized" format pattern
+ const pattern = /(\d{4})-(\d{1,2})-(\d{1,2}) @(\d{1,2})h (\d{1,2})m (\d{1,2})s (\d{1,3})ms/;
+ const replacement = (match, year, month, day, hour, minute, second, millisecond) => {
+ return `${year.padStart(4, "0")}-${month.padStart(2, "0")}-${day.padStart(2, "0")}T${hour.padStart(2, "0")}:${minute.padStart(2, "0")}:${second.padStart(2, "0")}.${millisecond.padStart(3, "0")}Z`;
+ };
+ const isoTimestamp = timestamp.replace(pattern, replacement);
+ return moment(isoTimestamp);
+}
+
+export function sortMoments(a, b) {
+ if (a.isBefore(b)) {
+ return 1;
+ } else if (a.isAfter(b)) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
/** Split string to parts no more than length in size */
export function splitRecursive(input, length, delimitiers = ['\n\n', '\n', ' ', '']) {
const delim = delimitiers[0] ?? '';
diff --git a/server.js b/server.js
index 2a40f7e60..96b3147a0 100644
--- a/server.js
+++ b/server.js
@@ -1454,7 +1454,6 @@ app.post("/getallchatsofcharacter", jsonParser, function (request, response) {
}
// filter for JSON files
- console.log('looking for JSONL files');
const jsonFiles = files.filter(file => path.extname(file) === '.jsonl');
// sort the files by name
@@ -1496,6 +1495,7 @@ app.post("/getallchatsofcharacter", jsonParser, function (request, response) {
chatData[i]['file_size'] = fileSizeInKB;
chatData[i]['chat_items'] = itemCounter - 1;
chatData[i]['mes'] = jsonData['mes'] || '[The chat is empty]';
+ chatData[i]['last_mes'] = jsonData['send_date'] || Date.now();
}
}
if (ii === 0) {