sessions improved, v0.7.0

This commit is contained in:
serversdwn
2025-12-21 15:50:52 -05:00
parent 01d4811717
commit b4613ac30c
7 changed files with 424 additions and 41 deletions

View File

@@ -81,6 +81,14 @@
</label>
</div>
</div>
<div class="settings-section" style="margin-top: 24px;">
<h4>Session Management</h4>
<p class="settings-desc">Manage your saved chat sessions:</p>
<div id="sessionList" class="session-list">
<p style="color: var(--text-fade); font-size: 0.85rem;">Loading sessions...</p>
</div>
</div>
</div>
<div class="modal-footer">
<button id="saveSettingsBtn" class="primary-btn">Save</button>
@@ -99,21 +107,28 @@
let history = [];
let currentSession = localStorage.getItem("currentSession") || null;
let sessions = JSON.parse(localStorage.getItem("sessions") || "[]");
let sessions = []; // Now loaded from server
function saveSessions() {
localStorage.setItem("sessions", JSON.stringify(sessions));
localStorage.setItem("currentSession", currentSession);
async function loadSessionsFromServer() {
try {
const resp = await fetch(`${RELAY_BASE}/sessions`);
const serverSessions = await resp.json();
sessions = serverSessions;
return sessions;
} catch (e) {
console.error("Failed to load sessions from server:", e);
return [];
}
}
function renderSessions() {
async function renderSessions() {
const select = document.getElementById("sessions");
select.innerHTML = "";
sessions.forEach(s => {
const opt = document.createElement("option");
opt.value = s.id;
opt.textContent = s.name;
opt.textContent = s.name || s.id;
if (s.id === currentSession) opt.selected = true;
select.appendChild(opt);
});
@@ -121,7 +136,21 @@
function getSessionName(id) {
const s = sessions.find(s => s.id === id);
return s ? s.name : id;
return s ? (s.name || s.id) : id;
}
async function saveSessionMetadata(sessionId, name) {
try {
await fetch(`${RELAY_BASE}/sessions/${sessionId}/metadata`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name })
});
return true;
} catch (e) {
console.error("Failed to save session metadata:", e);
return false;
}
}
async function loadSession(id) {
@@ -258,55 +287,75 @@
localStorage.setItem("theme", isDark ? "dark" : "light");
});
// Sessions
// Populate dropdown initially
renderSessions();
// Ensure we have at least one session
if (!currentSession) {
const id = generateSessionId();
const name = "default";
sessions.push({ id, name });
currentSession = id;
saveSessions();
renderSessions();
}
// Sessions - Load from server
(async () => {
await loadSessionsFromServer();
await renderSessions();
// Load current session history (if it exists on Relay)
loadSession(currentSession);
// Ensure we have at least one session
if (sessions.length === 0) {
const id = generateSessionId();
const name = "default";
currentSession = id;
history = [];
await saveSession(); // Create empty session on server
await saveSessionMetadata(id, name);
await loadSessionsFromServer();
await renderSessions();
localStorage.setItem("currentSession", currentSession);
} else {
// If no current session or current session doesn't exist, use first one
if (!currentSession || !sessions.find(s => s.id === currentSession)) {
currentSession = sessions[0].id;
localStorage.setItem("currentSession", currentSession);
}
}
// Load current session history
if (currentSession) {
await loadSession(currentSession);
}
})();
// Switch session
document.getElementById("sessions").addEventListener("change", async e => {
currentSession = e.target.value;
history = [];
saveSessions();
localStorage.setItem("currentSession", currentSession);
addMessage("system", `Switched to session: ${getSessionName(currentSession)}`);
await loadSession(currentSession); // ✅ load the chat history from Relay
await loadSession(currentSession);
});
// Create new session
document.getElementById("newSessionBtn").addEventListener("click", () => {
document.getElementById("newSessionBtn").addEventListener("click", async () => {
const name = prompt("Enter new session name:");
if (!name) return;
const id = generateSessionId();
sessions.push({ id, name });
currentSession = id;
history = [];
saveSessions();
renderSessions();
localStorage.setItem("currentSession", currentSession);
// Create session on server
await saveSession();
await saveSessionMetadata(id, name);
await loadSessionsFromServer();
await renderSessions();
addMessage("system", `Created session: ${name}`);
});
// Rename session
document.getElementById("renameSessionBtn").addEventListener("click", () => {
document.getElementById("renameSessionBtn").addEventListener("click", async () => {
const session = sessions.find(s => s.id === currentSession);
if (!session) return;
const newName = prompt("Rename session:", session.name);
const newName = prompt("Rename session:", session.name || currentSession);
if (!newName) return;
session.name = newName;
saveSessions();
renderSessions();
// Update metadata on server
await saveSessionMetadata(currentSession, newName);
await loadSessionsFromServer();
await renderSessions();
addMessage("system", `Session renamed to: ${newName}`);
});
@@ -335,9 +384,90 @@
document.querySelector(`input[name="backend"][value="${savedBackend}"]`).checked = true;
}
// Show modal
// Session management functions
async function loadSessionList() {
try {
// Reload from server to get latest
await loadSessionsFromServer();
const sessionListEl = document.getElementById("sessionList");
if (sessions.length === 0) {
sessionListEl.innerHTML = '<p style="color: var(--text-fade); font-size: 0.85rem;">No saved sessions found</p>';
return;
}
sessionListEl.innerHTML = "";
sessions.forEach(sess => {
const sessionItem = document.createElement("div");
sessionItem.className = "session-item";
const sessionInfo = document.createElement("div");
sessionInfo.className = "session-info";
const sessionName = sess.name || sess.id;
const lastModified = new Date(sess.lastModified).toLocaleString();
sessionInfo.innerHTML = `
<strong>${sessionName}</strong>
<small>${sess.messageCount} messages • ${lastModified}</small>
`;
const deleteBtn = document.createElement("button");
deleteBtn.className = "session-delete-btn";
deleteBtn.textContent = "🗑️";
deleteBtn.title = "Delete session";
deleteBtn.onclick = async () => {
if (!confirm(`Delete session "${sessionName}"?`)) return;
try {
await fetch(`${RELAY_BASE}/sessions/${sess.id}`, { method: "DELETE" });
// Reload sessions from server
await loadSessionsFromServer();
// If we deleted the current session, switch to another or create new
if (currentSession === sess.id) {
if (sessions.length > 0) {
currentSession = sessions[0].id;
localStorage.setItem("currentSession", currentSession);
history = [];
await loadSession(currentSession);
} else {
const id = generateSessionId();
const name = "default";
currentSession = id;
localStorage.setItem("currentSession", currentSession);
history = [];
await saveSession();
await saveSessionMetadata(id, name);
await loadSessionsFromServer();
}
}
// Refresh both the dropdown and the settings list
await renderSessions();
await loadSessionList();
addMessage("system", `Deleted session: ${sessionName}`);
} catch (e) {
alert("Failed to delete session: " + e.message);
}
};
sessionItem.appendChild(sessionInfo);
sessionItem.appendChild(deleteBtn);
sessionListEl.appendChild(sessionItem);
});
} catch (e) {
const sessionListEl = document.getElementById("sessionList");
sessionListEl.innerHTML = '<p style="color: #ff3333; font-size: 0.85rem;">Failed to load sessions</p>';
}
}
// Show modal and load session list
settingsBtn.addEventListener("click", () => {
settingsModal.classList.add("show");
loadSessionList(); // Refresh session list when opening settings
});
// Hide modal functions