Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
ba92455
feat(groups): added NGC group support prototype
Monsterovich Aug 6, 2026
c656f08
feat(friends): invite friend to group
Monsterovich Aug 6, 2026
e339a51
refactor(model): use toxcore group size macros
Monsterovich Aug 6, 2026
48dbce4
fix(groups): respect topic lock for setting topic
Monsterovich Aug 6, 2026
5dbacf3
fix(groups): query initial founder control states
Monsterovich Aug 6, 2026
daacc7c
fix(groups): inviting friend to group
Monsterovich Aug 6, 2026
65d481c
fix(groups): remove kicked peer locally
Monsterovich Aug 6, 2026
9fa0651
fix(groups): update local state after founder set
Monsterovich Aug 6, 2026
9dec394
fix(groups): refresh peer roles on self join and reconnect
Monsterovich Aug 6, 2026
28f93b6
fix(groups): added workaround for connecting to NGC
Monsterovich Aug 6, 2026
79f55f9
fix(groups): strip HTML markup from context menu title
Monsterovich Aug 6, 2026
11a53bd
feat(groups): fetch and cache group topic
Monsterovich Aug 7, 2026
1cc9674
fix(groups): clean up group forms before ChatManager destruction
Monsterovich Aug 7, 2026
adae758
fix(groups): persist groups in tox save
Monsterovich Aug 7, 2026
5953af9
feat(groups): highlight group button and dim icon when selected
Monsterovich Aug 7, 2026
3b37a2d
feat(groups): translate group button labels
Monsterovich Aug 7, 2026
92b8f0d
feat(groups): translate group peer context menu
Monsterovich Aug 7, 2026
a69aa9b
fix(groups): mark getSavedGroups as override
Monsterovich Aug 7, 2026
8900b54
fix(groups): silence unused parameter warnings
Monsterovich Aug 7, 2026
be1872b
fix(groups): guard against double accept of the same group invite
Monsterovich Aug 7, 2026
e196573
fix(groups): create reconnect timers on the core thread
Monsterovich Aug 7, 2026
1f77b9b
fix(groups): remove group UI before model on join failure
Monsterovich Aug 7, 2026
63f290d
fix(groups): remove group from groupIdToNumber before erasing entry
Monsterovich Aug 7, 2026
27021e4
fix(widget): free groupInviteForm when main window is destroyed
Monsterovich Aug 7, 2026
f6db753
fix(groupform): free topic context menu after it hides
Monsterovich Aug 7, 2026
317d3ca
style(groupform): wrap single-line if bodies in braces
Monsterovich Aug 7, 2026
b24c903
fix(chatmanager): store group name/topic under persistent id
Monsterovich Aug 7, 2026
373d579
fix(widget): guard group invite handling against unknown sender
Monsterovich Aug 7, 2026
d4a5788
refactor(core): log group join/leave events at debug level
Monsterovich Aug 7, 2026
79a1e54
fix(widget): defer group removal on middle click
Monsterovich Aug 7, 2026
e72639a
fix(groupinvite): suppress duplicate invites by friend and data
Monsterovich Aug 7, 2026
19f765f
fix(widget): show failed group message sends
Monsterovich Aug 7, 2026
c09772e
fix(settings): save group data on mutation
Monsterovich Aug 7, 2026
92db347
fix(friendlist): filter out group entries
Monsterovich Aug 7, 2026
ea743b3
feat(widget): add group filter
Monsterovich Aug 7, 2026
6fffb35
fix(widget): swap conference and group filter logic
Monsterovich Aug 7, 2026
87d12c9
fix(groups): keep user-set group alias across reconnects
Monsterovich Aug 7, 2026
18c8d02
fix(groupform): don't HTML-escape peer names shown as plain text
Monsterovich Aug 7, 2026
eedf57b
fix(groups): fully cleanup groups that fail to join
Monsterovich Aug 7, 2026
22a4972
feat(groups): use toxcore name when alias is empty
Monsterovich Aug 7, 2026
ad6e253
feat(groups): add per-group nickname support
Monsterovich Aug 7, 2026
e7bd851
feat(groups): add per-group status support
Monsterovich Aug 7, 2026
4ab2176
feat(groups): add status icons to group status menu
Monsterovich Aug 7, 2026
7806441
feat(ru): add Russian translations for group features
Monsterovich Aug 7, 2026
e0270b6
fix(groups): use default nickname when group nickname is cleared
Monsterovich Aug 7, 2026
295f272
fix(groups): check group creation before inviting friend
Monsterovich Aug 7, 2026
a7e2ffb
fix(settings): remove group nickname when leaving group
Monsterovich Aug 7, 2026
034df08
fix(widget): use same icon for group button disabled state
Monsterovich Aug 7, 2026
e896ff2
fix(groups): remove stale peer role on exit
Monsterovich Aug 7, 2026
3f84b8b
fix(groups): prevent unintended actions when context menu is dismissed
Monsterovich Aug 7, 2026
e34f17a
fix(groups): clear peer list on self disconnect
Monsterovich Aug 7, 2026
5891c22
feat(groups): add private message support
Monsterovich Aug 8, 2026
0bb6591
feat(groups): show recipient name in private message badge
Monsterovich Aug 8, 2026
30c6c5e
feat(groups): cancel private message mode with Escape key
Monsterovich Aug 8, 2026
9f53562
fix(groups): restore recipient name from group list on history load
Monsterovich Aug 8, 2026
f93c464
fix(groups): store recipient name in database for persistence
Monsterovich Aug 8, 2026
b1578e6
fix(groups): restore recipient name from group list on history load
Monsterovich Aug 8, 2026
32fafda
refactor(groups): use QByteArray instead of std::vector for buffer al…
Monsterovich Aug 9, 2026
ba4f20a
fix(groups): preserve action type in private messages
Monsterovich Aug 9, 2026
8de71c6
refactor(groups): replace dynamic_cast with qobject_cast
Monsterovich Aug 9, 2026
17c9ac4
fix(groups): don't remove saved group on transient join failure
Monsterovich Aug 9, 2026
dcda61b
style(groups): add braces to single-line if statements
Monsterovich Aug 9, 2026
cced5a4
fix(groups): prevent crash on message received after group left
Monsterovich Aug 9, 2026
57c918a
fix(groups): recipient name for incoming private messages
Monsterovich Aug 10, 2026
107a9b1
fix(groups): prevent silent message loss when private recipient is gone
Monsterovich Aug 11, 2026
854cb46
feat(groups): added message box for empty fields
Monsterovich Aug 14, 2026
2e651a8
fix(groupinviteform): prevent error popups on cancel
Monsterovich Aug 14, 2026
737ddee
feat(ru): add missing Russian translations for group features
Monsterovich Aug 15, 2026
0ad8168
fix(groups): prevent crash on group events after group left
Monsterovich Aug 15, 2026
d76706e
fix(groups): include sender username in group chat notifications
Monsterovich Aug 18, 2026
31eee4c
fix(test): update dbschema test for schema version 12
Monsterovich Aug 21, 2026
9cdf741
fix(tidy): resolve clang-tidy warnings
Monsterovich Aug 21, 2026
943f685
Merge branch 'master' into feat-ngc
Monsterovich Aug 21, 2026
bbef3ab
fix(groups): use group peer key instead of profile tox id for self
Monsterovich Aug 24, 2026
6654ab3
Merge branch 'master' into feat-ngc
Monsterovich Sep 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ set(${BINARY_NAME}_SOURCES
src/friendlist.h
src/conferencelist.cpp
src/conferencelist.h
src/grouplist.cpp
src/grouplist.h
src/ipc.cpp
src/ipc.h
src/nexus.cpp
Expand Down Expand Up @@ -309,6 +311,10 @@ set(${BINARY_NAME}_SOURCES
src/core/icoreconferencemessagesender.h
src/core/icoreconferencequery.cpp
src/core/icoreconferencequery.h
src/core/icoregroupmessagesender.cpp
src/core/icoregroupmessagesender.h
src/core/icoregroupquery.cpp
src/core/icoregroupquery.h
src/core/icoreidhandler.cpp
src/core/icoreidhandler.h
src/core/idebugsettings.cpp
Expand All @@ -324,6 +330,8 @@ set(${BINARY_NAME}_SOURCES
src/core/toxid.h
src/core/conferenceid.cpp
src/core/conferenceid.h
src/core/groupid.cpp
src/core/groupid.h
src/core/toxlogger.cpp
src/core/toxlogger.h
src/core/toxoptions.cpp
Expand All @@ -348,6 +356,8 @@ set(${BINARY_NAME}_SOURCES
src/model/chatroom/friendchatroom.h
src/model/chatroom/conferenceroom.cpp
src/model/chatroom/conferenceroom.h
src/model/chatroom/grouproom.cpp
src/model/chatroom/grouproom.h
src/model/chat.cpp
src/model/chat.h
src/model/debug/debuglogmodel.cpp
Expand All @@ -374,6 +384,12 @@ set(${BINARY_NAME}_SOURCES
src/model/conferencemessagedispatcher.h
src/model/conference.cpp
src/model/conference.h
src/model/group.cpp
src/model/group.h
src/model/groupinvite.cpp
src/model/groupinvite.h
src/model/groupmessagedispatcher.cpp
src/model/groupmessagedispatcher.h
src/model/ibootstraplistgenerator.cpp
src/model/ibootstraplistgenerator.h
src/model/ichatlog.h
Expand Down Expand Up @@ -537,6 +553,12 @@ set(${BINARY_NAME}_SOURCES
src/widget/form/conferenceinviteform.h
src/widget/form/conferenceinvitewidget.cpp
src/widget/form/conferenceinvitewidget.h
src/widget/form/groupform.cpp
src/widget/form/groupform.h
src/widget/form/groupinviteform.cpp
src/widget/form/groupinviteform.h
src/widget/form/groupinvitewidget.cpp
src/widget/form/groupinvitewidget.h
src/widget/form/loadhistorydialog.cpp
src/widget/form/loadhistorydialog.h
src/widget/form/profileform.cpp
Expand Down Expand Up @@ -581,6 +603,8 @@ set(${BINARY_NAME}_SOURCES
src/widget/genericchatroomwidget.h
src/widget/conferencewidget.cpp
src/widget/conferencewidget.h
src/widget/groupwidget.cpp
src/widget/groupwidget.h
src/widget/loginscreen.cpp
src/widget/loginscreen.h
src/widget/maskablepixmapwidget.cpp
Expand Down
20 changes: 20 additions & 0 deletions img/group.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions img/group_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions res.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
<file>img/contact_dark.svg</file>
<file>img/contact.svg</file>
<file>img/debug.svg</file>
<file>img/group_dark.svg</file>
<file>img/group.svg</file>
<file>img/icons/qtox.svg</file>
<file>img/login_logo.svg</file>
<file>img/others/logout-icon.svg</file>
Expand Down
14 changes: 13 additions & 1 deletion src/chatlog/chatmessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ ChatMessage::Ptr ChatMessage::createChatMessage(const QString& sender, const QSt
MessageType type, bool isMe, MessageState state,
const QDateTime& date, DocumentCache& documentCache,
SmileyPack& smileyPack, Settings& settings,
Style& style, bool colorizeName)
Style& style, bool colorizeName, bool isPrivate,
const QString& recipientName)
{
ChatMessage::Ptr msg = std::make_shared<ChatMessage>(documentCache, settings, style);

Expand Down Expand Up @@ -71,6 +72,17 @@ ChatMessage::Ptr ChatMessage::createChatMessage(const QString& sender, const QSt
text = TextFormatter::applyMarkdown(text, styleType == Settings::StyleType::WITH_CHARS);
}

if (isPrivate) {
QString badgeText = QObject::tr("private", "Label for private group messages");
if (!recipientName.isEmpty()) {
badgeText += QStringLiteral(" → %1").arg(recipientName.toHtmlEscaped());
}
const QString badge = QStringLiteral(
"<span class=\"private-badge\">%1</span>&nbsp;")
.arg(badgeText);
text = badge + text;
}


switch (type) {
case NORMAL:
Expand Down
4 changes: 3 additions & 1 deletion src/chatlog/chatmessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ class ChatMessage : public ChatLine
MessageType type, bool isMe, MessageState state,
const QDateTime& date, DocumentCache& documentCache,
SmileyPack& smileyPack, Settings& settings,
Style& style, bool colorizeName = false);
Style& style, bool colorizeName = false,
bool isPrivate = false,
const QString& recipientName = QString());
static ChatMessage::Ptr createChatInfoMessage(const QString& rawMessage, SystemMessageType type,
const QDateTime& date, DocumentCache& documentCache,
Settings& settings, Style& style);
Expand Down
7 changes: 5 additions & 2 deletions src/chatlog/chatwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,13 @@ ChatMessage::Ptr createMessage(const QString& displayName, bool isSelf, bool col
messageType = ChatMessage::MessageType::ALERT;
}

const bool isPrivate = !chatLogMessage.message.recipient.isEmpty();
const QString recipientName = isSelf ? chatLogMessage.message.recipientName : QString();
const auto timestamp = chatLogMessage.message.timestamp;
return ChatMessage::createChatMessage(displayName, chatLogMessage.message.content, messageType,
isSelf, chatLogMessage.state, timestamp, documentCache,
smileyPack, settings, style, colorizeNames);
smileyPack, settings, style, colorizeNames, isPrivate,
recipientName);
}

void renderMessageRaw(const QString& displayName, bool isSelf, bool colorizeNames,
Expand Down Expand Up @@ -1075,7 +1078,7 @@ void ChatWidget::onWorkerTimeout()
return;
}

if (static_cast<size_t>(workerLastIndex) >= chatLineStorage->size()) {
if (workerLastIndex >= chatLineStorage->size()) {
break;
}

Expand Down
10 changes: 5 additions & 5 deletions src/core/conferenceid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ ConferenceId::ConferenceId()
/**
* @brief Constructs a ConferenceId from bytes.
* @param rawId The bytes to construct the ConferenceId from. The length must be exactly
* ConferenceId::size, else the ConferenceId will be empty.
* TOX_CONFERENCE_ID_SIZE, else the ConferenceId will be empty.
*/
ConferenceId::ConferenceId(const QByteArray& rawId)
: ChatId([rawId]() {
assert(rawId.length() == size);
assert(rawId.length() == TOX_CONFERENCE_ID_SIZE);
return rawId;
}())
{
Expand All @@ -39,10 +39,10 @@ ConferenceId::ConferenceId(const QByteArray& rawId)
/**
* @brief Constructs a ConferenceId from bytes.
* @param rawId The bytes to construct the ConferenceId from, will read exactly
* ConferenceId::size from the specified buffer.
* TOX_CONFERENCE_ID_SIZE from the specified buffer.
*/
ConferenceId::ConferenceId(const uint8_t* rawId)
: ChatId(QByteArray(reinterpret_cast<const char*>(rawId), size))
: ChatId(QByteArray(reinterpret_cast<const char*>(rawId), TOX_CONFERENCE_ID_SIZE))
{
}

Expand All @@ -52,7 +52,7 @@ ConferenceId::ConferenceId(const uint8_t* rawId)
*/
int ConferenceId::getSize() const
{
return size;
return TOX_CONFERENCE_ID_SIZE;
}

std::unique_ptr<ChatId> ConferenceId::clone() const
Expand Down
2 changes: 1 addition & 1 deletion src/core/conferenceid.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
#include <QByteArray>

#include <cstdint>
#include <tox/tox.h>

class ConferenceId : public ChatId
{
public:
static constexpr int size = 32;
ConferenceId();
explicit ConferenceId(const QByteArray& rawId);
explicit ConferenceId(const uint8_t* rawId);
Expand Down
Loading
Loading