diff --git a/src/friendlist.cpp b/src/friendlist.cpp index e278e5c6e..5198069be 100644 --- a/src/friendlist.cpp +++ b/src/friendlist.cpp @@ -87,3 +87,13 @@ QList FriendList::getAllFriends() { return friendList.values(); } + +QString FriendList::decideNickname(ToxPk peerPk, const QString origName) +{ + Friend* f = FriendList::findFriend(peerPk); + if (f != nullptr && f->hasAlias()) { + return f->getDisplayedName(); + } else { + return origName; + } +} diff --git a/src/friendlist.h b/src/friendlist.h index 63c5e5565..e83de1f7b 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -28,6 +28,7 @@ template class QHash; class Friend; class QByteArray; +class QString; class ToxPk; class FriendList @@ -39,6 +40,7 @@ public: static QList getAllFriends(); static void removeFriend(uint32_t friendId, bool fake = false); static void clear(); + static QString decideNickname(ToxPk peerPk, const QString origName); private: static QHash friendList; diff --git a/src/model/friend.cpp b/src/model/friend.cpp index 1c0b43fc4..13481b158 100644 --- a/src/model/friend.cpp +++ b/src/model/friend.cpp @@ -84,6 +84,14 @@ void Friend::setAlias(const QString& alias) if (oldDisplayed != newDisplayed) { emit displayedNameChanged(newDisplayed); } + + for (Group* g : GroupList::getAllGroups()) { + if (userAlias.isEmpty()) { + g->updateUsername(friendPk, userName); + continue; + } + g->updateUsername(friendPk, userAlias); + } } void Friend::setStatusMessage(const QString& message) diff --git a/src/model/group.cpp b/src/model/group.cpp index e03bd33da..3803fa0f7 100644 --- a/src/model/group.cpp +++ b/src/model/group.cpp @@ -46,12 +46,7 @@ void Group::updatePeer(int peerId, QString name) { ToxPk peerKey = Core::getInstance()->getGroupPeerPk(groupId, peerId); toxpks[peerKey] = name; - - Friend* f = FriendList::findFriend(peerKey); - if (f != nullptr) { - // use the displayed name from the friends list - toxpks[peerKey] = f->getDisplayedName(); - } + qDebug() << "name change: " + name; emit userListChanged(groupId, toxpks); } @@ -124,6 +119,12 @@ void Group::regeneratePeerList() emit userListChanged(groupId, toxpks); } +void Group::updateUsername(ToxPk pk, const QString newName) +{ + toxpks[pk] = newName; + emit userListChanged(groupId, toxpks); +} + bool Group::isAvGroupchat() const { return avGroupchat; diff --git a/src/model/group.h b/src/model/group.h index a30180940..22469ca95 100644 --- a/src/model/group.h +++ b/src/model/group.h @@ -47,6 +47,7 @@ public: bool getMentionedFlag() const; void updatePeer(int peerId, QString newName); + void updateUsername(ToxPk pk, const QString newName); void setName(const QString& newTitle) override; void setTitle(const QString& author, const QString& newTitle); QString getName() const; diff --git a/src/nexus.cpp b/src/nexus.cpp index 611189bf5..a94cf3249 100644 --- a/src/nexus.cpp +++ b/src/nexus.cpp @@ -213,6 +213,7 @@ void Nexus::showMainGUI() connect(core, &Core::friendTypingChanged, widget, &Widget::onFriendTypingChanged); connect(core, &Core::messageSentResult, widget, &Widget::onMessageSendResult); connect(core, &Core::groupSentFailed, widget, &Widget::onGroupSendFailed); + connect(core, &Core::usernameSet, widget, &Widget::refreshPeerListsLocal); connect(widget, &Widget::statusSet, core, &Core::setStatus); connect(widget, &Widget::friendRequested, core, &Core::requestFriendship); diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp index 2b521c581..6b2e0ce88 100644 --- a/src/widget/form/groupchatform.cpp +++ b/src/widget/form/groupchatform.cpp @@ -176,6 +176,7 @@ void GroupChatForm::onUserListChanged() { updateUserCount(); updateUserNames(); + sendJoinLeaveMessages(); // Enable or disable call button const int peersCount = group->getPeersCount(); @@ -261,7 +262,7 @@ void GroupChatForm::updateUserNames() * and then sort them by their text and add them to the layout in that order */ const auto selfPk = Core::getInstance()->getSelfPublicKey(); for (const auto& peerPk : peers.keys()) { - const QString fullName = peers.value(peerPk); + const QString fullName = FriendList::decideNickname(peerPk, peers.value(peerPk)); const QString editedName = editName(fullName).append(QLatin1String(", ")); QLabel* const label = new QLabel(editedName); if (editedName != fullName) { @@ -307,6 +308,57 @@ void GroupChatForm::updateUserNames() } } +void GroupChatForm::sendJoinLeaveMessages() +{ + const auto peers = group->getPeerList(); + + // no need to do anything without any peers + if (peers.isEmpty()) { + return; + } + + // generate user list from the current group if it's empty + if (groupLast.isEmpty()) { + groupLast = group->getPeerList(); + return; + } + + // user joins + for (const auto& peerPk : peers.keys()) { + if (!firstTime.value(peerPk, false)) { + if (!groupLast.contains(peerPk)) { + addSystemInfoMessage(tr("A new user has connected to the group"), ChatMessage::INFO, QDateTime::currentDateTime()); + } + firstTime[peerPk] = true; + continue; + } + const QString name = FriendList::decideNickname(peerPk, peers.value(peerPk)); + if (!groupLast.contains(peerPk)) { + groupLast.insert(peerPk, name); + addSystemInfoMessage(tr("%1 has joined the group").arg(name), ChatMessage::INFO, QDateTime::currentDateTime()); + } else { + Friend *f = FriendList::findFriend(peerPk); + if (groupLast[peerPk] != name + && peers.value(peerPk) == name + && peerPk != Core::getInstance()->getSelfPublicKey() // ignore myself + && !(f != nullptr && f->hasAlias()) // ignore friends with aliases + ) { + addSystemInfoMessage(tr("%1 is now known as %2").arg(groupLast[peerPk], name), ChatMessage::INFO, QDateTime::currentDateTime()); + groupLast[peerPk] = name; + } + } + } + // user leaves + for (const auto& peerPk : groupLast.keys()) { + const QString name = FriendList::decideNickname(peerPk, groupLast.value(peerPk)); + if (!peers.contains(peerPk)) { + groupLast.remove(peerPk); + firstTime.remove(peerPk); + addSystemInfoMessage(tr("%1 has left the group").arg(name), ChatMessage::INFO, QDateTime::currentDateTime()); + } + } +} + void GroupChatForm::peerAudioPlaying(ToxPk peerPk) { peerLabels[peerPk]->setProperty("playingAudio", LABEL_PEER_PLAYING_AUDIO); diff --git a/src/widget/form/groupchatform.h b/src/widget/form/groupchatform.h index 63c1c6e3b..0257306ff 100644 --- a/src/widget/form/groupchatform.h +++ b/src/widget/form/groupchatform.h @@ -67,11 +67,14 @@ private: void retranslateUi(); void updateUserCount(); void updateUserNames(); + void sendJoinLeaveMessages(); private: Group* group; QMap peerLabels; QMap peerAudioTimers; + QMap groupLast; + QMap firstTime; FlowLayout* namesListLayout; QLabel* nusersLabel; TabCompleter* tabber; diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index b0f35f2d9..3de9b2674 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -1745,7 +1745,7 @@ void Widget::onGroupMessageReceived(int groupnumber, int peernumber, const QStri return; } - const auto mention = message.contains(nameMention) || message.contains(sanitizedNameMention); + const auto mention = !core->getUsername().isEmpty() && (message.contains(nameMention) || message.contains(sanitizedNameMention)); const auto targeted = !isSelf && mention; const auto groupId = g->getId(); const auto date = QDateTime::currentDateTime(); @@ -2506,3 +2506,10 @@ void Widget::focusChatInput() } } } + +void Widget::refreshPeerListsLocal(const QString &username) +{ + for (Group* g : GroupList::getAllGroups()) { + g->updateUsername(Core::getInstance()->getSelfPublicKey(), username); + } +} diff --git a/src/widget/widget.h b/src/widget/widget.h index 06d5877bc..2daa4525b 100644 --- a/src/widget/widget.h +++ b/src/widget/widget.h @@ -182,6 +182,7 @@ public slots: void onFriendDialogShown(const Friend* f); void onGroupDialogShown(Group* g); void toggleFullscreen(); + void refreshPeerListsLocal(const QString &username); signals: void friendRequestAccepted(const ToxPk& friendPk);