Files
gemini-banlancer/frontend/js/pages/chat/SessionManager.js

179 lines
5.5 KiB
JavaScript

// Filename: frontend/js/pages/chat/SessionManager.js
import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js';
const LOCAL_STORAGE_KEY = 'gemini_chat_state';
/**
* Manages the state and persistence of chat sessions.
* This class handles loading from/saving to localStorage,
* and all operations like creating, switching, and deleting sessions.
*/
export class SessionManager {
constructor() {
this.state = null;
}
/**
* Initializes the manager by loading state from localStorage or creating a default state.
*/
init() {
this._loadState();
}
// --- Public API for state access ---
getSessions() {
return this.state.sessions;
}
getCurrentSessionId() {
return this.state.currentSessionId;
}
getCurrentSession() {
return this.state.sessions.find(s => s.id === this.state.currentSessionId);
}
// --- Public API for state mutation ---
/**
* Creates a new, empty session and sets it as the current one.
*/
createSession() {
const newSessionId = nanoid();
const newSession = {
id: newSessionId,
name: '新会话',
systemPrompt: '',
messages: [],
modelConfig: { model: 'gemini-2.0-flash-lite' },
params: { temperature: 0.7 }
};
this.state.sessions.unshift(newSession);
this.state.currentSessionId = newSessionId;
this._saveState();
}
/**
* Switches the current session to the one with the given ID.
* @param {string} sessionId The ID of the session to switch to.
*/
switchSession(sessionId) {
if (this.state.currentSessionId === sessionId) return;
this.state.currentSessionId = sessionId;
this._saveState();
}
/**
* Deletes a session by its ID.
* @param {string} sessionId The ID of the session to delete.
*/
deleteSession(sessionId) {
this.state.sessions = this.state.sessions.filter(s => s.id !== sessionId);
if (this.state.currentSessionId === sessionId) {
this.state.currentSessionId = this.state.sessions[0]?.id || null;
if (!this.state.currentSessionId) {
this._createInitialState(); // Create a new one if all are deleted
}
}
this._saveState();
}
/**
* [NEW] Clears all messages from the currently active session.
*/
clearCurrentSession() {
const currentSession = this.getCurrentSession();
if (currentSession) {
currentSession.messages = [];
this._saveState();
}
}
/**
* Adds a message to the current session and updates the session name if it's the first message.
* @param {object} message The message object to add.
* @returns {object} The session that was updated.
*/
addMessage(message) {
const currentSession = this.getCurrentSession();
if (currentSession) {
if (currentSession.messages.length === 0 && message.role === 'user') {
currentSession.name = message.content.substring(0, 30);
}
currentSession.messages.push(message);
this._saveState();
return currentSession;
}
return null;
}
deleteMessage(messageId) {
const currentSession = this.getCurrentSession();
if (currentSession) {
const messageIndex = currentSession.messages.findIndex(m => m.id === messageId);
if (messageIndex > -1) {
currentSession.messages.splice(messageIndex, 1);
this._saveState();
console.log(`Message ${messageId} deleted.`);
}
}
}
truncateMessagesAfter(messageId) {
const currentSession = this.getCurrentSession();
if (currentSession) {
const messageIndex = currentSession.messages.findIndex(m => m.id === messageId);
// Ensure the message exists and it's not already the last one
if (messageIndex > -1 && messageIndex < currentSession.messages.length - 1) {
currentSession.messages.splice(messageIndex + 1);
this._saveState();
console.log(`Truncated messages after ${messageId}.`);
}
}
}
// --- Private persistence methods ---
_saveState() {
try {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(this.state));
} catch (error) {
console.error("Failed to save session state:", error);
}
}
_loadState() {
try {
const stateString = localStorage.getItem(LOCAL_STORAGE_KEY);
if (stateString) {
this.state = JSON.parse(stateString);
} else {
this._createInitialState();
}
} catch (error) {
console.error("Failed to load session state, creating initial state:", error);
this._createInitialState();
}
}
_createInitialState() {
const initialSessionId = nanoid();
this.state = {
sessions: [{
id: initialSessionId,
name: '新会话',
systemPrompt: '',
messages: [],
modelConfig: { model: 'gemini-2.0-flash-lite' },
params: { temperature: 0.7 }
}],
currentSessionId: initialSessionId,
settings: {}
};
this._saveState();
}
}