Sessions: Sidebar, Session-Wechsel, Archivieren-Button, alles session-bezogen

This commit is contained in:
Meleki committed 2026-02-26 18:37:24 +01:00
1 parent 8ddee38032
commit 25f07caf83
15 files changed
+442 -78

No files matched your search

+76 -22
View File
@@ -31,9 +31,18 @@ public class DatabaseService
Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
conn.Execute(@"
CREATE TABLE IF NOT EXISTS sessions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL UNIQUE,
name TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS archives (
id INTEGER PRIMARY KEY AUTOINCREMENT,
archive_id TEXT NOT NULL UNIQUE,
session_id TEXT NOT NULL,
name TEXT,
chain_count INTEGER NOT NULL DEFAULT 0,
message_count INTEGER NOT NULL DEFAULT 0,
@@ -75,24 +84,76 @@ public class DatabaseService
");
}
// ── Sessions ──
public async Task<SessionRecord> CreateSession(string name = null)
{
using var conn = CreateConnection();
var now = DateTime.UtcNow.ToString("o");
var session = new SessionRecord
{
SessionId = Guid.NewGuid().ToString("N"),
Name = name,
CreatedAt = now,
UpdatedAt = now
};
await conn.ExecuteAsync(@"
INSERT INTO sessions (session_id, name, created_at, updated_at)
VALUES (@SessionId, @Name, @CreatedAt, @UpdatedAt)
", session);
return session;
}
public async Task<IEnumerable<SessionRecord>> GetSessions()
{
using var conn = CreateConnection();
return await conn.QueryAsync<SessionRecord>(
"SELECT * FROM sessions ORDER BY updated_at DESC");
}
public async Task<SessionRecord> GetSession(string sessionId)
{
using var conn = CreateConnection();
return await conn.QuerySingleOrDefaultAsync<SessionRecord>(
"SELECT * FROM sessions WHERE session_id = @sessionId", new { sessionId });
}
public async Task UpdateSessionTimestamp(string sessionId)
{
using var conn = CreateConnection();
await conn.ExecuteAsync(
"UPDATE sessions SET updated_at = @now WHERE session_id = @sessionId",
new { sessionId, now = DateTime.UtcNow.ToString("o") });
}
public async Task UpdateSessionName(string sessionId, string name)
{
using var conn = CreateConnection();
await conn.ExecuteAsync(
"UPDATE sessions SET name = @name, updated_at = @now WHERE session_id = @sessionId",
new { sessionId, name, now = DateTime.UtcNow.ToString("o") });
}
// ── Archives ──
public async Task<ArchiveRecord> CreateArchive(string name = null)
public async Task<ArchiveRecord> CreateArchive(string sessionId, string name = null)
{
using var conn = CreateConnection();
// Zähle aktive Chains und Messages
var chainCount = await conn.ExecuteScalarAsync<int>(
"SELECT COUNT(*) FROM chains WHERE archive_id IS NULL");
"SELECT COUNT(*) FROM chains WHERE archive_id IS NULL AND session_id = @sessionId",
new { sessionId });
if (chainCount == 0) return null;
var messageCount = await conn.ExecuteScalarAsync<int>(@"
SELECT COUNT(*) FROM messages
WHERE chain_id IN (SELECT chain_id FROM chains WHERE archive_id IS NULL)");
WHERE chain_id IN (SELECT chain_id FROM chains WHERE archive_id IS NULL AND session_id = @sessionId)",
new { sessionId });
var archive = new ArchiveRecord
{
ArchiveId = Guid.NewGuid().ToString("N"),
SessionId = sessionId,
Name = name,
ChainCount = chainCount,
MessageCount = messageCount,
@@ -100,23 +161,23 @@ public class DatabaseService
};
await conn.ExecuteAsync(@"
INSERT INTO archives (archive_id, name, chain_count, message_count, created_at)
VALUES (@ArchiveId, @Name, @ChainCount, @MessageCount, @CreatedAt)
INSERT INTO archives (archive_id, session_id, name, chain_count, message_count, created_at)
VALUES (@ArchiveId, @SessionId, @Name, @ChainCount, @MessageCount, @CreatedAt)
", archive);
// Alle aktiven Chains diesem Archiv zuweisen
await conn.ExecuteAsync(
"UPDATE chains SET archive_id = @archiveId WHERE archive_id IS NULL",
new { archiveId = archive.ArchiveId });
"UPDATE chains SET archive_id = @archiveId WHERE archive_id IS NULL AND session_id = @sessionId",
new { archiveId = archive.ArchiveId, sessionId });
return archive;
}
public async Task<IEnumerable<ArchiveRecord>> GetArchives(int limit = 20)
public async Task<IEnumerable<ArchiveRecord>> GetArchives(string sessionId)
{
using var conn = CreateConnection();
return await conn.QueryAsync<ArchiveRecord>(
"SELECT * FROM archives ORDER BY id DESC LIMIT @limit", new { limit });
"SELECT * FROM archives WHERE session_id = @sessionId ORDER BY id DESC",
new { sessionId });
}
public async Task<IEnumerable<ChainRecord>> GetArchiveChains(string archiveId)
@@ -161,14 +222,7 @@ public class DatabaseService
);
}
public async Task<IEnumerable<ChainRecord>> GetActiveChains()
{
using var conn = CreateConnection();
return await conn.QueryAsync<ChainRecord>(
"SELECT * FROM chains WHERE archive_id IS NULL ORDER BY id DESC");
}
public async Task<IEnumerable<ChainRecord>> GetSessionChains(string sessionId)
public async Task<IEnumerable<ChainRecord>> GetActiveChains(string sessionId)
{
using var conn = CreateConnection();
return await conn.QueryAsync<ChainRecord>(
@@ -197,14 +251,14 @@ public class DatabaseService
);
}
public async Task<IEnumerable<MessageRecord>> GetActiveMessagesAfterId(long afterId, int limit = 200)
public async Task<IEnumerable<MessageRecord>> GetActiveMessagesAfterId(string sessionId, long afterId, int limit = 200)
{
using var conn = CreateConnection();
return await conn.QueryAsync<MessageRecord>(@"
SELECT m.* FROM messages m
JOIN chains c ON m.chain_id = c.chain_id
WHERE m.id > @afterId AND c.archive_id IS NULL
WHERE m.id > @afterId AND c.archive_id IS NULL AND c.session_id = @sessionId
ORDER BY m.id LIMIT @limit",
new { afterId, limit });
new { sessionId, afterId, limit });
}
}