feat: show acks on particles

This commit is contained in:
talksik
2026-02-06 15:06:11 -08:00
parent fefba20571
commit 01529e8d14
3 changed files with 56 additions and 0 deletions
+32
View File
@@ -115,11 +115,29 @@ MainWindow::MainWindow(QWidget *parent)
connect(m_authManager, &AuthManager::signedOut, m_authDialog, &AuthDialog::reset);
connect(m_authManager, &AuthManager::signedOut, m_authDialog, &AuthDialog::show);
connect(m_authManager, &AuthManager::signedIn, this, [this]() {
m_store->setCurrentUserEmail(m_authManager->sessionData()->email);
m_store->loadStartupData();
});
connect(m_store, &Store::startupDataLoaded, this, [this]() {
ui->topLevelParticlesView->expandAll();
});
connect(m_store, &Store::particleUpdated, this, [this](const QString &, const QString &particleId) {
if (particleId == m_selectedParticleId)
{
const Particle *particle = m_store->particleById(particleId);
if (particle && !particle->ackedByEmails.empty())
{
QStringList acked;
for (const auto &email : particle->ackedByEmails)
acked.append(email);
ui->label_3->setText("Acked by: " + acked.join(", "));
}
else
{
ui->label_3->setText("");
}
}
});
// DocumentSend toolbar button opens text input dialog
connect(ui->toolButton_3, &QToolButton::clicked, this, &MainWindow::showTextInputDialog);
@@ -329,6 +347,7 @@ void MainWindow::onParticleSelectionChanged(const QItemSelection &selected, cons
{
ui->label->setText("");
ui->label_2->setText("");
ui->label_3->setText("");
m_selectedParticleId.clear();
m_selectedParticleRow = -1;
updateStatusBar();
@@ -352,6 +371,19 @@ void MainWindow::onParticleSelectionChanged(const QItemSelection &selected, cons
ui->label->setText("");
}
// Show ack info
if (!particle->ackedByEmails.empty())
{
QStringList acked;
for (const auto &email : particle->ackedByEmails)
acked.append(email);
ui->label_3->setText("Acked by: " + acked.join(", "));
}
else
{
ui->label_3->setText("");
}
// Mark seen on selection
if (!particle->seen)
{
+21
View File
@@ -791,8 +791,29 @@ Operation *Store::markParticlesSeen(const QStringList &particleIds)
return new Operation(reply, this);
}
void Store::setCurrentUserEmail(const QString &email) { m_currentUserEmail = email; }
Operation *Store::ackParticle(const QString &particleId)
{
// Optimistic local update
for (auto it = m_particles.begin(); it != m_particles.end(); ++it)
{
for (int i = 0; i < it.value().size(); ++i)
{
if (it.value()[i].id == particleId)
{
auto &emails = it.value()[i].ackedByEmails;
if (!m_currentUserEmail.isEmpty() &&
std::find(emails.begin(), emails.end(), m_currentUserEmail) == emails.end())
{
emails.push_back(m_currentUserEmail);
emit particleUpdated(it.key(), particleId);
}
break;
}
}
}
QNetworkReply *reply = NetworkManager::instance().post(
QString("/particles/%1/ack").arg(particleId), QJsonDocument());
return new Operation(reply, this);
+3
View File
@@ -85,6 +85,8 @@ public:
Operation *markParticlesSeen(const QStringList &particleIds);
Operation *ackParticle(const QString &particleId);
void setCurrentUserEmail(const QString &email);
signals:
// ── Data-change signals ──
@@ -106,6 +108,7 @@ private:
QMap<QString, QList<Particle>> m_particles; // streamId -> particles
QMap<QString, int> m_networkIndex; // networkId -> index in m_networks
QMap<QString, QString> m_streamToNetwork; // streamId -> networkId
QString m_currentUserEmail;
// ── JSON parsing ──