chatgui: local nicknames per channel member — edit via MemberPropsDialog, override display everywhere
This commit is contained in:
1 parent
373a2e4687
commit
85bdc00aaf
9 files changed
+87
-16
No files matched your search
@@ -214,7 +214,7 @@ int DbManager::getChannelMemberCount(const QString& chId) const {
|
|||||||
QList<ChannelMember> DbManager::getChannelMembers(const QString& chId, int offset, int limit) const {
|
QList<ChannelMember> DbManager::getChannelMembers(const QString& chId, int offset, int limit) const {
|
||||||
QList<ChannelMember> list;
|
QList<ChannelMember> list;
|
||||||
QString sql = QStringLiteral(
|
QString sql = QStringLiteral(
|
||||||
"SELECT p.node_id, COALESCE(n.online,0), COALESCE(n.name,'')"
|
"SELECT p.node_id, COALESCE(n.online,0), COALESCE(n.name,''), COALESCE(p.local_nick,'')"
|
||||||
" FROM \"%1\" p LEFT JOIN nodes n ON p.node_id=n.node_id"
|
" FROM \"%1\" p LEFT JOIN nodes n ON p.node_id=n.node_id"
|
||||||
" ORDER BY n.online DESC, p.node_id ASC LIMIT ? OFFSET ?"
|
" ORDER BY n.online DESC, p.node_id ASC LIMIT ? OFFSET ?"
|
||||||
).arg(peersTableName(chId));
|
).arg(peersTableName(chId));
|
||||||
@@ -227,12 +227,27 @@ QList<ChannelMember> DbManager::getChannelMembers(const QString& chId, int offse
|
|||||||
m.nodeId = (quint64)sqlite3_column_int64(stmt, 0);
|
m.nodeId = (quint64)sqlite3_column_int64(stmt, 0);
|
||||||
m.online = sqlite3_column_int(stmt, 1) != 0;
|
m.online = sqlite3_column_int(stmt, 1) != 0;
|
||||||
m.name = colText(stmt, 2);
|
m.name = colText(stmt, 2);
|
||||||
|
m.localNick = colText(stmt, 3);
|
||||||
list.append(m);
|
list.append(m);
|
||||||
}
|
}
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMap<quint64, QString> DbManager::getLocalNicknames(const QString& chId) const {
|
||||||
|
QMap<quint64, QString> m;
|
||||||
|
if (!m_db) return m;
|
||||||
|
QString sql = QStringLiteral(
|
||||||
|
"SELECT node_id, local_nick FROM \"%1\" WHERE local_nick IS NOT NULL AND local_nick != ''"
|
||||||
|
).arg(peersTableName(chId));
|
||||||
|
sqlite3_stmt* stmt = prepareOrNull(sql.toUtf8().constData());
|
||||||
|
if (!stmt) return m;
|
||||||
|
while (sqlite3_step(stmt) == SQLITE_ROW)
|
||||||
|
m.insert((quint64)sqlite3_column_int64(stmt, 0), colText(stmt, 1));
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
void DbManager::cleanOrphanedPeers(const QString& chId) const {
|
void DbManager::cleanOrphanedPeers(const QString& chId) const {
|
||||||
if (!m_db) return;
|
if (!m_db) return;
|
||||||
QString sql = QStringLiteral(
|
QString sql = QStringLiteral(
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ struct ChannelMember {
|
|||||||
quint64 nodeId = 0;
|
quint64 nodeId = 0;
|
||||||
bool online = false;
|
bool online = false;
|
||||||
QString name; // from nodes.name, empty if not set
|
QString name; // from nodes.name, empty if not set
|
||||||
|
QString localNick; // from peers.local_nick override, empty if not set
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NodeAddr {
|
struct NodeAddr {
|
||||||
@@ -96,6 +97,7 @@ public:
|
|||||||
QList<ChannelMember> getChannelMembers(const QString& chId, int offset, int limit) const;
|
QList<ChannelMember> getChannelMembers(const QString& chId, int offset, int limit) const;
|
||||||
void cleanOrphanedPeers(const QString& chId) const;
|
void cleanOrphanedPeers(const QString& chId) const;
|
||||||
QString getDisplayName(quint64 nodeId) const;
|
QString getDisplayName(quint64 nodeId) const;
|
||||||
|
QMap<quint64, QString> getLocalNicknames(const QString& chId) const;
|
||||||
|
|
||||||
/* ── Узлы ── */
|
/* ── Узлы ── */
|
||||||
QByteArray loadNodeInfo(quint64 nodeId) const;
|
QByteArray loadNodeInfo(quint64 nodeId) const;
|
||||||
|
|||||||
@@ -130,6 +130,21 @@ void AccountList::showMemberDetail(quint64 nodeId) {
|
|||||||
if (m_detailName.isEmpty())
|
if (m_detailName.isEmpty())
|
||||||
m_detailName = QString("0x%1").arg(nodeId, 8, 16, QChar('0')).right(4).toUpper();
|
m_detailName = QString("0x%1").arg(nodeId, 8, 16, QChar('0')).right(4).toUpper();
|
||||||
|
|
||||||
|
/* prefer local nickname */
|
||||||
|
QString tbl = m_db->peersTableName(m_channelId);
|
||||||
|
sqlite3_stmt* nickSt = nullptr;
|
||||||
|
QByteArray nickSql = QString(
|
||||||
|
"SELECT local_nick FROM \"%1\" WHERE node_id=?"
|
||||||
|
).arg(tbl).toUtf8();
|
||||||
|
if (sqlite3_prepare_v2(d, nickSql.constData(), -1, &nickSt, nullptr) == SQLITE_OK) {
|
||||||
|
sqlite3_bind_int64(nickSt, 1, (sqlite3_int64)nodeId);
|
||||||
|
if (sqlite3_step(nickSt) == SQLITE_ROW) {
|
||||||
|
QString n = DbManager::colText(nickSt, 0);
|
||||||
|
if (!n.isEmpty()) m_detailName = n;
|
||||||
|
}
|
||||||
|
sqlite3_finalize(nickSt);
|
||||||
|
}
|
||||||
|
|
||||||
sqlite3_stmt* na = nullptr;
|
sqlite3_stmt* na = nullptr;
|
||||||
sqlite3_prepare_v2(d,
|
sqlite3_prepare_v2(d,
|
||||||
"SELECT family, protocol, address, port FROM node_addresses WHERE node_id=? ORDER BY family, port",
|
"SELECT family, protocol, address, port FROM node_addresses WHERE node_id=? ORDER BY family, port",
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ QVariant MemberListModel::data(const QModelIndex& index, int role) const {
|
|||||||
|
|
||||||
auto it = m_cache.find(index.row());
|
auto it = m_cache.find(index.row());
|
||||||
if (it != m_cache.end()) {
|
if (it != m_cache.end()) {
|
||||||
if (role == Qt::DisplayRole) return it->name;
|
if (role == Qt::DisplayRole) return it->localNick.isEmpty() ? it->name : it->localNick;
|
||||||
if (role == Qt::DecorationRole) return QVariant::fromValue(QIcon(it->avatar));
|
if (role == Qt::DecorationRole) return QVariant::fromValue(QIcon(it->avatar));
|
||||||
if (role == Qt::UserRole + 1) {
|
if (role == Qt::UserRole + 1) {
|
||||||
QString sub;
|
QString sub;
|
||||||
@@ -93,6 +93,7 @@ void MemberListModel::loadBatch(int from, int count) {
|
|||||||
item.online = members[i].online;
|
item.online = members[i].online;
|
||||||
QString shortId = QString("%1").arg(members[i].nodeId, 8, 16, QChar('0')).right(4).toUpper();
|
QString shortId = QString("%1").arg(members[i].nodeId, 8, 16, QChar('0')).right(4).toUpper();
|
||||||
item.name = members[i].name.isEmpty() ? shortId : members[i].name;
|
item.name = members[i].name.isEmpty() ? shortId : members[i].name;
|
||||||
|
item.localNick = members[i].localNick;
|
||||||
QColor c = members[i].online ? QColor("#4CAF50") : QColor("#9E9E9E");
|
QColor c = members[i].online ? QColor("#4CAF50") : QColor("#9E9E9E");
|
||||||
item.avatar = makeAvatar(c, item.name[0]);
|
item.avatar = makeAvatar(c, item.name[0]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ struct MemberListItem {
|
|||||||
bool online = false;
|
bool online = false;
|
||||||
QPixmap avatar;
|
QPixmap avatar;
|
||||||
QString name;
|
QString name;
|
||||||
|
QString localNick;
|
||||||
int rtt = -1; // ms (min из node_addresses, -1 если нет)
|
int rtt = -1; // ms (min из node_addresses, -1 если нет)
|
||||||
int natType = -1; // addr_type: 0=NET, 1=DIR, 2=EIM, 3=STR
|
int natType = -1; // addr_type: 0=NET, 1=DIR, 2=EIM, 3=STR
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ MemberPropsDialog::MemberPropsDialog(DbManager* db, const QString& channelId,
|
|||||||
setMinimumWidth(340);
|
setMinimumWidth(340);
|
||||||
setModal(true);
|
setModal(true);
|
||||||
|
|
||||||
// читаем ed25519_privkey канала
|
|
||||||
auto chs = m_db->getChannels();
|
auto chs = m_db->getChannels();
|
||||||
for (const auto& ch : chs) {
|
for (const auto& ch : chs) {
|
||||||
if (ch.channelId == channelId) {
|
if (ch.channelId == channelId) {
|
||||||
@@ -30,13 +29,14 @@ MemberPropsDialog::MemberPropsDialog(DbManager* db, const QString& channelId,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool haveKey = (m_edPrivkey.size() == 32);
|
bool haveKey = (m_edPrivkey.size() == 32);
|
||||||
|
bool isOwn = (m_nodeId == m_db->myNodeId());
|
||||||
|
|
||||||
// читаем текущий adm_tags
|
|
||||||
bool isAdmin = false, isSuper = false;
|
bool isAdmin = false, isSuper = false;
|
||||||
|
QString curNick;
|
||||||
if (m_db->m_db) {
|
if (m_db->m_db) {
|
||||||
QString tbl = m_db->peersTableName(channelId);
|
QString tbl = m_db->peersTableName(channelId);
|
||||||
QByteArray sql = QString(
|
QByteArray sql = QString(
|
||||||
"SELECT adm_tags FROM \"%1\" WHERE node_id=?"
|
"SELECT adm_tags, local_nick FROM \"%1\" WHERE node_id=?"
|
||||||
).arg(tbl).toUtf8();
|
).arg(tbl).toUtf8();
|
||||||
sqlite3_stmt* st = nullptr;
|
sqlite3_stmt* st = nullptr;
|
||||||
if (sqlite3_prepare_v2(m_db->m_db, sql.constData(), -1, &st, nullptr) == SQLITE_OK) {
|
if (sqlite3_prepare_v2(m_db->m_db, sql.constData(), -1, &st, nullptr) == SQLITE_OK) {
|
||||||
@@ -47,10 +47,10 @@ MemberPropsDialog::MemberPropsDialog(DbManager* db, const QString& channelId,
|
|||||||
if (strstr(tags, "admin=yes")) isAdmin = true;
|
if (strstr(tags, "admin=yes")) isAdmin = true;
|
||||||
if (strstr(tags, "supernode=yes")) isSuper = true;
|
if (strstr(tags, "supernode=yes")) isSuper = true;
|
||||||
}
|
}
|
||||||
|
curNick = DbManager::colText(st, 1);
|
||||||
}
|
}
|
||||||
sqlite3_finalize(st);
|
sqlite3_finalize(st);
|
||||||
}
|
}
|
||||||
// страховка: добавить колонки если нет
|
|
||||||
QByteArray alt = QString(
|
QByteArray alt = QString(
|
||||||
"ALTER TABLE \"%1\" ADD COLUMN adm_tags TEXT"
|
"ALTER TABLE \"%1\" ADD COLUMN adm_tags TEXT"
|
||||||
).arg(tbl).toUtf8();
|
).arg(tbl).toUtf8();
|
||||||
@@ -59,6 +59,10 @@ MemberPropsDialog::MemberPropsDialog(DbManager* db, const QString& channelId,
|
|||||||
"ALTER TABLE \"%1\" ADD COLUMN adm_tags_sig BLOB"
|
"ALTER TABLE \"%1\" ADD COLUMN adm_tags_sig BLOB"
|
||||||
).arg(tbl).toUtf8();
|
).arg(tbl).toUtf8();
|
||||||
sqlite3_exec(m_db->m_db, alt.constData(), nullptr, nullptr, nullptr);
|
sqlite3_exec(m_db->m_db, alt.constData(), nullptr, nullptr, nullptr);
|
||||||
|
alt = QString(
|
||||||
|
"ALTER TABLE \"%1\" ADD COLUMN local_nick TEXT"
|
||||||
|
).arg(tbl).toUtf8();
|
||||||
|
sqlite3_exec(m_db->m_db, alt.constData(), nullptr, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* layout = new QVBoxLayout(this);
|
auto* layout = new QVBoxLayout(this);
|
||||||
@@ -72,6 +76,12 @@ MemberPropsDialog::MemberPropsDialog(DbManager* db, const QString& channelId,
|
|||||||
title->setStyleSheet("font-weight: bold; font-size: 13px;");
|
title->setStyleSheet("font-weight: bold; font-size: 13px;");
|
||||||
layout->addWidget(title);
|
layout->addWidget(title);
|
||||||
|
|
||||||
|
m_nickEdit = new QLineEdit(this);
|
||||||
|
m_nickEdit->setPlaceholderText("Local nickname...");
|
||||||
|
m_nickEdit->setText(curNick);
|
||||||
|
m_nickEdit->setEnabled(!isOwn);
|
||||||
|
layout->addWidget(m_nickEdit);
|
||||||
|
|
||||||
m_adminCb = new QCheckBox("Admin", this);
|
m_adminCb = new QCheckBox("Admin", this);
|
||||||
m_adminCb->setChecked(isAdmin);
|
m_adminCb->setChecked(isAdmin);
|
||||||
m_adminCb->setEnabled(haveKey);
|
m_adminCb->setEnabled(haveKey);
|
||||||
@@ -83,7 +93,7 @@ MemberPropsDialog::MemberPropsDialog(DbManager* db, const QString& channelId,
|
|||||||
layout->addWidget(m_superCb);
|
layout->addWidget(m_superCb);
|
||||||
|
|
||||||
if (!haveKey) {
|
if (!haveKey) {
|
||||||
auto* hint = new QLabel("(requires channel private key)", this);
|
auto* hint = new QLabel("(Admin/Super require channel private key)", this);
|
||||||
hint->setStyleSheet("color: gray; font-size: 11px;");
|
hint->setStyleSheet("color: gray; font-size: 11px;");
|
||||||
layout->addWidget(hint);
|
layout->addWidget(hint);
|
||||||
}
|
}
|
||||||
@@ -105,7 +115,6 @@ MemberPropsDialog::MemberPropsDialog(DbManager* db, const QString& channelId,
|
|||||||
auto* saveBtn = new QPushButton("Save", this);
|
auto* saveBtn = new QPushButton("Save", this);
|
||||||
saveBtn->setFixedWidth(90);
|
saveBtn->setFixedWidth(90);
|
||||||
saveBtn->setDefault(true);
|
saveBtn->setDefault(true);
|
||||||
saveBtn->setEnabled(haveKey);
|
|
||||||
saveBtn->setStyleSheet(
|
saveBtn->setStyleSheet(
|
||||||
"QPushButton { border: none; border-radius: 4px;"
|
"QPushButton { border: none; border-radius: 4px;"
|
||||||
" padding: 6px 16px; font-size: 13px; font-weight: bold;"
|
" padding: 6px 16px; font-size: 13px; font-weight: bold;"
|
||||||
@@ -119,9 +128,26 @@ MemberPropsDialog::MemberPropsDialog(DbManager* db, const QString& channelId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MemberPropsDialog::onSave() {
|
void MemberPropsDialog::onSave() {
|
||||||
if (m_edPrivkey.size() != 32 || !m_db->m_db) return;
|
if (!m_db->m_db) return;
|
||||||
|
QString tbl = m_db->peersTableName(m_channelId);
|
||||||
|
|
||||||
|
/* local_nick — always save (unsigned, local only) */
|
||||||
|
QString nick = m_nickEdit->text().trimmed();
|
||||||
|
QByteArray nickSql = QString(
|
||||||
|
"UPDATE \"%1\" SET local_nick=? WHERE node_id=?"
|
||||||
|
).arg(tbl).toUtf8();
|
||||||
|
sqlite3_stmt* ns = nullptr;
|
||||||
|
if (sqlite3_prepare_v2(m_db->m_db, nickSql.constData(), -1, &ns, nullptr) == SQLITE_OK) {
|
||||||
|
sqlite3_bind_text(ns, 1, nick.isEmpty() ? nullptr : nick.toUtf8().constData(),
|
||||||
|
-1, nick.isEmpty() ? SQLITE_STATIC : SQLITE_TRANSIENT);
|
||||||
|
sqlite3_bind_int64(ns, 2, (sqlite3_int64)m_nodeId);
|
||||||
|
sqlite3_step(ns);
|
||||||
|
sqlite3_finalize(ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* signed fields — only if key available */
|
||||||
|
if (m_edPrivkey.size() != 32) { accept(); return; }
|
||||||
|
|
||||||
// собираем adm_tags
|
|
||||||
QString tags;
|
QString tags;
|
||||||
if (m_adminCb->isChecked()) tags += "admin=yes";
|
if (m_adminCb->isChecked()) tags += "admin=yes";
|
||||||
if (m_superCb->isChecked()) {
|
if (m_superCb->isChecked()) {
|
||||||
@@ -129,7 +155,6 @@ void MemberPropsDialog::onSave() {
|
|||||||
tags += "supernode=yes";
|
tags += "supernode=yes";
|
||||||
}
|
}
|
||||||
|
|
||||||
// подписываем: tags || node_id(8 LE)
|
|
||||||
QByteArray msg = tags.toUtf8();
|
QByteArray msg = tags.toUtf8();
|
||||||
uint64_t le = htole64(m_nodeId);
|
uint64_t le = htole64(m_nodeId);
|
||||||
msg.append((const char*)&le, 8);
|
msg.append((const char*)&le, 8);
|
||||||
@@ -148,8 +173,6 @@ void MemberPropsDialog::onSave() {
|
|||||||
EVP_PKEY_free(pkey);
|
EVP_PKEY_free(pkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
// пишем в БД
|
|
||||||
QString tbl = m_db->peersTableName(m_channelId);
|
|
||||||
QByteArray sql = QString(
|
QByteArray sql = QString(
|
||||||
"UPDATE \"%1\" SET adm_tags=?, adm_tags_sig=?, node_type=? WHERE node_id=?"
|
"UPDATE \"%1\" SET adm_tags=?, adm_tags_sig=?, node_type=? WHERE node_id=?"
|
||||||
).arg(tbl).toUtf8();
|
).arg(tbl).toUtf8();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
|
#include <QLineEdit>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
class DbManager;
|
class DbManager;
|
||||||
@@ -22,6 +23,7 @@ private:
|
|||||||
quint64 m_nodeId;
|
quint64 m_nodeId;
|
||||||
QByteArray m_edPrivkey;
|
QByteArray m_edPrivkey;
|
||||||
|
|
||||||
|
QLineEdit* m_nickEdit;
|
||||||
QCheckBox* m_adminCb;
|
QCheckBox* m_adminCb;
|
||||||
QCheckBox* m_superCb;
|
QCheckBox* m_superCb;
|
||||||
};
|
};
|
||||||
@@ -207,11 +207,13 @@ void MessageList::loadChannel(const QString& channelId) {
|
|||||||
m_readDebounce->stop();
|
m_readDebounce->stop();
|
||||||
if (!m_db || !m_db->isOpen()) return;
|
if (!m_db || !m_db->isOpen()) return;
|
||||||
|
|
||||||
|
m_localNicks = m_db->getLocalNicknames(channelId);
|
||||||
|
|
||||||
auto msgs = m_db->getMessages(channelId, 100);
|
auto msgs = m_db->getMessages(channelId, 100);
|
||||||
|
|
||||||
for (const auto& m : msgs) {
|
for (const auto& m : msgs) {
|
||||||
AccountRow acc = m_db->getAccount(m.authorNodeId);
|
AccountRow acc = m_db->getAccount(m.authorNodeId);
|
||||||
QString author = m_db->getDisplayName(m.authorNodeId);
|
QString author = authorName(m.authorNodeId);
|
||||||
QString letter = acc.avatarLetter.isEmpty() ? author.mid(0, 1) : acc.avatarLetter;
|
QString letter = acc.avatarLetter.isEmpty() ? author.mid(0, 1) : acc.avatarLetter;
|
||||||
QColor color(acc.avatarColor);
|
QColor color(acc.avatarColor);
|
||||||
|
|
||||||
@@ -271,12 +273,14 @@ void MessageList::refresh() {
|
|||||||
auto newMsgs = m_db->getMessagesSince(m_currentChannelId, maxId);
|
auto newMsgs = m_db->getMessagesSince(m_currentChannelId, maxId);
|
||||||
if (newMsgs.isEmpty()) return;
|
if (newMsgs.isEmpty()) return;
|
||||||
|
|
||||||
|
m_localNicks = m_db->getLocalNicknames(m_currentChannelId);
|
||||||
|
|
||||||
QScrollBar* sb = m_view->verticalScrollBar();
|
QScrollBar* sb = m_view->verticalScrollBar();
|
||||||
bool wasAtBottom = sb && (sb->value() >= sb->maximum());
|
bool wasAtBottom = sb && (sb->value() >= sb->maximum());
|
||||||
|
|
||||||
for (const auto& m : newMsgs) {
|
for (const auto& m : newMsgs) {
|
||||||
AccountRow acc = m_db->getAccount(m.authorNodeId);
|
AccountRow acc = m_db->getAccount(m.authorNodeId);
|
||||||
QString author = m_db->getDisplayName(m.authorNodeId);
|
QString author = authorName(m.authorNodeId);
|
||||||
QString letter = acc.avatarLetter.isEmpty() ? author.mid(0, 1) : acc.avatarLetter;
|
QString letter = acc.avatarLetter.isEmpty() ? author.mid(0, 1) : acc.avatarLetter;
|
||||||
QColor color(acc.avatarColor);
|
QColor color(acc.avatarColor);
|
||||||
if (!m_avatarCache.contains(m.authorNodeId))
|
if (!m_avatarCache.contains(m.authorNodeId))
|
||||||
@@ -302,7 +306,7 @@ void MessageList::addMessage(const QString& channelId, quint64 authorNodeId,
|
|||||||
if (channelId != m_currentChannelId) return;
|
if (channelId != m_currentChannelId) return;
|
||||||
|
|
||||||
AccountRow acc = m_db ? m_db->getAccount(authorNodeId) : AccountRow();
|
AccountRow acc = m_db ? m_db->getAccount(authorNodeId) : AccountRow();
|
||||||
QString author = m_db ? m_db->getDisplayName(authorNodeId) : QString("node_%1").arg(authorNodeId);
|
QString author = m_db ? authorName(authorNodeId) : QString("node_%1").arg(authorNodeId);
|
||||||
QString letter = acc.avatarLetter.isEmpty() ? author.mid(0, 1) : acc.avatarLetter;
|
QString letter = acc.avatarLetter.isEmpty() ? author.mid(0, 1) : acc.avatarLetter;
|
||||||
QColor color(acc.avatarColor);
|
QColor color(acc.avatarColor);
|
||||||
auto avatar = makeAvatar(color, letter);
|
auto avatar = makeAvatar(color, letter);
|
||||||
@@ -356,6 +360,12 @@ void MessageList::saveChannelState() {
|
|||||||
if (lastPosMsgId > 0) saveKey("_last_pos", lastPosMsgId);
|
if (lastPosMsgId > 0) saveKey("_last_pos", lastPosMsgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString MessageList::authorName(quint64 nodeId) const {
|
||||||
|
auto it = m_localNicks.find(nodeId);
|
||||||
|
if (it != m_localNicks.end() && !it->isEmpty()) return *it;
|
||||||
|
return m_db->getDisplayName(nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
void MessageList::restoreScrollPosition(const QString& channelId) {
|
void MessageList::restoreScrollPosition(const QString& channelId) {
|
||||||
if (!m_db || m_model->rowCount() == 0) {
|
if (!m_db || m_model->rowCount() == 0) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ private:
|
|||||||
QTimer* m_readDebounce;
|
QTimer* m_readDebounce;
|
||||||
qint64 m_savedTopMsgId = 0;
|
qint64 m_savedTopMsgId = 0;
|
||||||
bool m_wasAtBottom = false;
|
bool m_wasAtBottom = false;
|
||||||
|
QMap<quint64, QString> m_localNicks;
|
||||||
|
|
||||||
|
QString authorName(quint64 nodeId) const;
|
||||||
void restoreScrollPosition(const QString& channelId);
|
void restoreScrollPosition(const QString& channelId);
|
||||||
void updateReadPosition();
|
void updateReadPosition();
|
||||||
};
|
};
|
||||||
Reference in new issue
Block a user