feat: Sessions an Projekt/Workspace binden [appimage]
Some checks failed
Build AppImage / build (push) Failing after 3m54s
Some checks failed
Build AppImage / build (push) Failing after 3m54s
Sessions werden jetzt nach aktivem Projekt gefiltert (working_dir). Beim Projektwechsel sieht man nur noch die Sessions die zu diesem Projekt gehören. Backend: load_sessions_filtered() mit optionalem WHERE working_dir-Filter. Ohne Projekt: alle Sessions (abwärtskompatibel). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ebbb65a1a9
commit
c2db56f392
3 changed files with 39 additions and 12 deletions
|
|
@ -519,13 +519,12 @@ impl Database {
|
||||||
|
|
||||||
/// Lädt alle Sessions (neueste zuerst)
|
/// Lädt alle Sessions (neueste zuerst)
|
||||||
pub fn load_sessions(&self, limit: usize) -> SqlResult<Vec<Session>> {
|
pub fn load_sessions(&self, limit: usize) -> SqlResult<Vec<Session>> {
|
||||||
let mut stmt = self.conn.prepare(
|
self.load_sessions_filtered(limit, None)
|
||||||
"SELECT id, claude_session_id, title, working_dir, message_count,
|
}
|
||||||
token_input, token_output, cost_usd, status, created_at, updated_at, last_message
|
|
||||||
FROM sessions ORDER BY updated_at DESC LIMIT ?1"
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let sessions = stmt.query_map(params![limit as i64], |row| {
|
/// Sessions laden, optional gefiltert nach working_dir (Projekt-Bindung)
|
||||||
|
pub fn load_sessions_filtered(&self, limit: usize, working_dir: Option<&str>) -> SqlResult<Vec<Session>> {
|
||||||
|
let row_mapper = |row: &rusqlite::Row| -> rusqlite::Result<Session> {
|
||||||
Ok(Session {
|
Ok(Session {
|
||||||
id: row.get(0)?,
|
id: row.get(0)?,
|
||||||
claude_session_id: row.get(1)?,
|
claude_session_id: row.get(1)?,
|
||||||
|
|
@ -540,7 +539,23 @@ impl Database {
|
||||||
updated_at: row.get(10)?,
|
updated_at: row.get(10)?,
|
||||||
last_message: row.get(11)?,
|
last_message: row.get(11)?,
|
||||||
})
|
})
|
||||||
})?.collect::<SqlResult<Vec<_>>>()?;
|
};
|
||||||
|
|
||||||
|
let sessions = if let Some(dir) = working_dir {
|
||||||
|
let mut stmt = self.conn.prepare(
|
||||||
|
"SELECT id, claude_session_id, title, working_dir, message_count,
|
||||||
|
token_input, token_output, cost_usd, status, created_at, updated_at, last_message
|
||||||
|
FROM sessions WHERE working_dir = ?1 ORDER BY updated_at DESC LIMIT ?2"
|
||||||
|
)?;
|
||||||
|
stmt.query_map(params![dir, limit as i64], row_mapper)?.collect::<SqlResult<Vec<_>>>()?
|
||||||
|
} else {
|
||||||
|
let mut stmt = self.conn.prepare(
|
||||||
|
"SELECT id, claude_session_id, title, working_dir, message_count,
|
||||||
|
token_input, token_output, cost_usd, status, created_at, updated_at, last_message
|
||||||
|
FROM sessions ORDER BY updated_at DESC LIMIT ?1"
|
||||||
|
)?;
|
||||||
|
stmt.query_map(params![limit as i64], row_mapper)?.collect::<SqlResult<Vec<_>>>()?
|
||||||
|
};
|
||||||
|
|
||||||
Ok(sessions)
|
Ok(sessions)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,16 +53,17 @@ pub async fn update_session(
|
||||||
db.update_session(&session).map_err(|e| e.to_string())
|
db.update_session(&session).map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Alle Sessions laden
|
/// Alle Sessions laden (optional gefiltert nach working_dir)
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn list_sessions(
|
pub async fn list_sessions(
|
||||||
app: AppHandle,
|
app: AppHandle,
|
||||||
limit: Option<usize>,
|
limit: Option<usize>,
|
||||||
|
working_dir: Option<String>,
|
||||||
) -> Result<Vec<Session>, String> {
|
) -> Result<Vec<Session>, String> {
|
||||||
let limit = limit.unwrap_or(50);
|
let limit = limit.unwrap_or(50);
|
||||||
let state = app.state::<Arc<Mutex<db::Database>>>();
|
let state = app.state::<Arc<Mutex<db::Database>>>();
|
||||||
let db = state.lock().unwrap();
|
let db = state.lock().unwrap();
|
||||||
db.load_sessions(limit).map_err(|e| e.to_string())
|
db.load_sessions_filtered(limit, working_dir.as_deref()).map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Session nach ID laden
|
/// Session nach ID laden
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
activeProject = project;
|
activeProject = project;
|
||||||
showProjectList = false;
|
showProjectList = false;
|
||||||
console.log(`📂 Projekt gewechselt: ${project.name} → ${project.working_dir}`);
|
console.log(`📂 Projekt gewechselt: ${project.name} → ${project.working_dir}`);
|
||||||
// Sessions neu laden (gefiltert nach Projekt wäre Zukunftsmusik)
|
// Sessions gefiltert nach Projekt-Verzeichnis laden
|
||||||
await loadSessions();
|
await loadSessions();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Fehler beim Projektwechsel:', err);
|
console.error('Fehler beim Projektwechsel:', err);
|
||||||
|
|
@ -131,9 +131,20 @@
|
||||||
|
|
||||||
async function loadSessions() {
|
async function loadSessions() {
|
||||||
try {
|
try {
|
||||||
sessions = await invoke('list_sessions', { limit: 50 });
|
// Sessions nach aktivem Projekt filtern (working_dir)
|
||||||
|
const workingDir = activeProject?.working_dir ?? undefined;
|
||||||
|
sessions = await invoke('list_sessions', { limit: 50, workingDir: workingDir });
|
||||||
const active: Session | null = await invoke('get_active_session');
|
const active: Session | null = await invoke('get_active_session');
|
||||||
activeSessionId = active?.id || null;
|
|
||||||
|
// Prüfen ob aktive Session zum aktuellen Projekt gehört
|
||||||
|
if (active && (!workingDir || active.working_dir === workingDir)) {
|
||||||
|
activeSessionId = active.id;
|
||||||
|
} else if (sessions.length > 0) {
|
||||||
|
// Erste Session des Projekts aktivieren
|
||||||
|
activeSessionId = sessions[0].id;
|
||||||
|
} else {
|
||||||
|
activeSessionId = null;
|
||||||
|
}
|
||||||
$currentSessionId = activeSessionId;
|
$currentSessionId = activeSessionId;
|
||||||
|
|
||||||
// Wenn aktive Session existiert, Nachrichten laden
|
// Wenn aktive Session existiert, Nachrichten laden
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue