better chat list view + anchor to bottom. sqlite db for chats + LIFO-ordered
This commit is contained in:
@@ -1,14 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "messagemodel.hpp"
|
||||
#include "message.hpp"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QtQml>
|
||||
|
||||
namespace ZShell {
|
||||
namespace ZShell::llm {
|
||||
|
||||
class LlmClient;
|
||||
|
||||
class ChatSession : public QObject {
|
||||
Q_OBJECT
|
||||
@@ -16,13 +18,14 @@ class ChatSession : public QObject {
|
||||
QML_UNCREATABLE("Chat sessions are managed by Chat.chats")
|
||||
|
||||
Q_PROPERTY(QString id READ id CONSTANT)
|
||||
Q_PROPERTY(QString title READ title NOTIFY titleChanged)
|
||||
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
|
||||
Q_PROPERTY(QString icon READ icon NOTIFY iconChanged)
|
||||
Q_PROPERTY(QDateTime createdAt READ createdAt CONSTANT)
|
||||
Q_PROPERTY(QDateTime updatedAt READ updatedAt NOTIFY updatedAtChanged)
|
||||
Q_PROPERTY(bool pinned READ pinned NOTIFY pinnedChanged)
|
||||
Q_PROPERTY(int messageCount READ messageCount NOTIFY messageCountChanged)
|
||||
Q_PROPERTY(QList<ChatMessage*> messages READ messages NOTIFY messagesChanged)
|
||||
Q_PROPERTY(
|
||||
ZShell::llm::ChatMessageModel* messagesModel READ messagesModel CONSTANT)
|
||||
|
||||
public:
|
||||
explicit ChatSession(const QString& id, QObject* parent = nullptr);
|
||||
@@ -40,10 +43,14 @@ class ChatSession : public QObject {
|
||||
[[nodiscard]] qint64 updatedAtMs() const { return m_updatedAt; }
|
||||
[[nodiscard]] bool pinned() const { return m_pinned; }
|
||||
[[nodiscard]] int messageCount() const { return m_messageCount; }
|
||||
[[nodiscard]] QList<ChatMessage*> messages() {
|
||||
ensureLoaded();
|
||||
return m_messages;
|
||||
}
|
||||
// Loads the messages from the store on first access.
|
||||
[[nodiscard]] ChatMessageModel* messagesModel();
|
||||
void ensureLoaded();
|
||||
[[nodiscard]] bool isLoaded() const { return m_loaded; }
|
||||
|
||||
[[nodiscard]] LlmClient* client() const;
|
||||
[[nodiscard]] int lastTokenCount() const { return m_lastTokenCount; }
|
||||
void setLastTokenCount(int value);
|
||||
|
||||
void setTitle(const QString& value);
|
||||
void setIcon(const QString& value);
|
||||
@@ -56,23 +63,29 @@ class ChatSession : public QObject {
|
||||
qint64 updatedAt,
|
||||
int messageCount);
|
||||
|
||||
void ensureLoaded();
|
||||
[[nodiscard]] bool isLoaded() const { return m_loaded; }
|
||||
// Replaces the model's rows with `messages` (most recent first).
|
||||
void adoptMessages(QList<ChatMessage*> messages);
|
||||
ChatMessage* appendMessage(
|
||||
ChatMessage::Role role, const QString& content, qint64 timestamp);
|
||||
void persist();
|
||||
void removeMessage(ChatMessage* message);
|
||||
void clearMessages();
|
||||
|
||||
Q_INVOKABLE void sendMessage(const QString& text);
|
||||
Q_INVOKABLE void retry(ZShell::llm::ChatMessage* target);
|
||||
Q_INVOKABLE void continueFrom(ZShell::llm::ChatMessage* message);
|
||||
Q_INVOKABLE void clear();
|
||||
|
||||
Q_SIGNALS:
|
||||
void titleChanged();
|
||||
void iconChanged();
|
||||
void updatedAtChanged();
|
||||
void pinnedChanged();
|
||||
void messageCountChanged();
|
||||
void messagesChanged();
|
||||
|
||||
private:
|
||||
void onModelRowsChanged();
|
||||
ChatMessage* appendNewest(
|
||||
ChatMessage::Role role, const QString& content, qint64 timestamp);
|
||||
void startGeneration(ChatMessage* target);
|
||||
void setCount(int value);
|
||||
|
||||
QString m_id;
|
||||
@@ -82,8 +95,9 @@ class ChatSession : public QObject {
|
||||
qint64 m_updatedAt = 0;
|
||||
bool m_pinned = false;
|
||||
int m_messageCount = 0;
|
||||
QList<ChatMessage*> m_messages;
|
||||
ChatMessageModel* m_model = nullptr;
|
||||
bool m_loaded = false;
|
||||
int m_lastTokenCount = 0;
|
||||
};
|
||||
|
||||
} // namespace ZShell
|
||||
} // namespace ZShell::llm
|
||||
|
||||
Reference in New Issue
Block a user