1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

fix(history): display broken messages UI with error icon

Allows users to still see their broken messages in the chatlog, but in a way
that's clear that they haven't been delivered and won't be sent.
This commit is contained in:
Anthony Bilinski 2019-10-07 20:43:10 -07:00
parent 527c7d2d3c
commit 1a726b54cd
No known key found for this signature in database
GPG Key ID: 2AA8E0DA1B31FB3C
9 changed files with 165 additions and 25 deletions

View File

@ -290,6 +290,8 @@ set(${PROJECT_NAME}_SOURCES
src/chatlog/content/text.h src/chatlog/content/text.h
src/chatlog/content/timestamp.cpp src/chatlog/content/timestamp.cpp
src/chatlog/content/timestamp.h src/chatlog/content/timestamp.h
src/chatlog/content/broken.cpp
src/chatlog/content/broken.h
src/chatlog/customtextdocument.cpp src/chatlog/customtextdocument.cpp
src/chatlog/customtextdocument.h src/chatlog/customtextdocument.h
src/chatlog/documentcache.cpp src/chatlog/documentcache.cpp

View File

@ -26,6 +26,7 @@
#include "content/spinner.h" #include "content/spinner.h"
#include "content/text.h" #include "content/text.h"
#include "content/timestamp.h" #include "content/timestamp.h"
#include "content/broken.h"
#include "src/widget/style.h" #include "src/widget/style.h"
#include <QDebug> #include <QDebug>
@ -33,6 +34,7 @@
#include "src/persistence/settings.h" #include "src/persistence/settings.h"
#include "src/persistence/smileypack.h" #include "src/persistence/smileypack.h"
#include "src/persistence/history.h"
#define NAME_COL_WIDTH 90.0 #define NAME_COL_WIDTH 90.0
#define TIME_COL_WIDTH 90.0 #define TIME_COL_WIDTH 90.0
@ -43,7 +45,8 @@ ChatMessage::ChatMessage()
} }
ChatMessage::Ptr ChatMessage::createChatMessage(const QString& sender, const QString& rawMessage, ChatMessage::Ptr ChatMessage::createChatMessage(const QString& sender, const QString& rawMessage,
MessageType type, bool isMe, const QDateTime& date, bool colorizeName) MessageType type, bool isMe, MessageState state,
const QDateTime& date, bool colorizeName)
{ {
ChatMessage::Ptr msg = ChatMessage::Ptr(new ChatMessage); ChatMessage::Ptr msg = ChatMessage::Ptr(new ChatMessage);
@ -105,12 +108,21 @@ ChatMessage::Ptr ChatMessage::createChatMessage(const QString& sender, const QSt
? QString("%1 %2").arg(sender, rawMessage) ? QString("%1 %2").arg(sender, rawMessage)
: rawMessage), : rawMessage),
ColumnFormat(1.0, ColumnFormat::VariableSize)); ColumnFormat(1.0, ColumnFormat::VariableSize));
switch (state) {
case MessageState::complete:
msg->addColumn(new Timestamp(date, Settings::getInstance().getTimestampFormat(), baseFont),
ColumnFormat(TIME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
break;
case MessageState::pending:
msg->addColumn(new Spinner(Style::getImagePath("chatArea/spinner.svg"), QSize(16, 16), 360.0 / 1.6), msg->addColumn(new Spinner(Style::getImagePath("chatArea/spinner.svg"), QSize(16, 16), 360.0 / 1.6),
ColumnFormat(TIME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right)); ColumnFormat(TIME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
break;
if (!date.isNull()) case MessageState::broken:
msg->markAsDelivered(date); msg->addColumn(new Broken(Style::getImagePath("chatArea/error.svg"), QSize(16, 16)),
ColumnFormat(TIME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right));
break;
}
return msg; return msg;
} }

View File

@ -22,6 +22,8 @@
#include "chatline.h" #include "chatline.h"
#include "src/core/toxfile.h" #include "src/core/toxfile.h"
#include "src/persistence/history.h"
#include <QDateTime> #include <QDateTime>
class QGraphicsScene; class QGraphicsScene;
@ -48,8 +50,8 @@ public:
ChatMessage(); ChatMessage();
static ChatMessage::Ptr createChatMessage(const QString& sender, const QString& rawMessage, static ChatMessage::Ptr createChatMessage(const QString& sender, const QString& rawMessage,
MessageType type, bool isMe, MessageType type, bool isMe, MessageState state,
const QDateTime& date = QDateTime(), bool colorizeName = false); const QDateTime& date, bool colorizeName = false);
static ChatMessage::Ptr createChatInfoMessage(const QString& rawMessage, SystemMessageType type, static ChatMessage::Ptr createChatInfoMessage(const QString& rawMessage, SystemMessageType type,
const QDateTime& date); const QDateTime& date);
static ChatMessage::Ptr createFileTransferMessage(const QString& sender, ToxFile file, static ChatMessage::Ptr createFileTransferMessage(const QString& sender, ToxFile file,

View File

@ -0,0 +1,61 @@
/*
Copyright © 2019 by The qTox Project Contributors
This file is part of qTox, a Qt-based graphical interface for Tox.
qTox is libre software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
qTox is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with qTox. If not, see <http://www.gnu.org/licenses/>.
*/
#include "broken.h"
#include "src/chatlog/pixmapcache.h"
#include <QPainter>
class QStyleOptionGraphicsItem;
Broken::Broken(const QString& img, QSize size)
: pmap{PixmapCache::getInstance().get(img, size)}
, size{size}
{
}
QRectF Broken::boundingRect() const
{
return QRectF(QPointF(-size.width() / 2.0, -size.height() / 2.0), size);
}
void Broken::paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
QWidget* widget)
{
painter->setRenderHint(QPainter::SmoothPixmapTransform);
painter->drawPixmap(0, 0, pmap);
Q_UNUSED(option)
Q_UNUSED(widget)
}
void Broken::setWidth(qreal width)
{
Q_UNUSED(width);
}
void Broken::visibilityChanged(bool visible)
{
Q_UNUSED(visible);
}
qreal Broken::getAscent() const
{
return 0.0;
}

View File

@ -0,0 +1,45 @@
/*
Copyright © 2019 by The qTox Project Contributors
This file is part of qTox, a Qt-based graphical interface for Tox.
qTox is libre software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
qTox is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with qTox. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BROKEN_H
#define BROKEN_H
#include "../chatlinecontent.h"
#include <QObject>
#include <QPixmap>
class Broken : public ChatLineContent
{
Q_OBJECT
public:
Broken(const QString& img, QSize size);
QRectF boundingRect() const override;
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
QWidget* widget) override;
void setWidth(qreal width) override;
void visibilityChanged(bool visible) override;
qreal getAscent() const override;
private:
QSize size;
QPixmap pmap;
};
#endif // BROKEN_H

View File

@ -394,19 +394,23 @@ void ChatHistory::loadHistoryIntoSessionChatLog(ChatLogIdx start) const
std::find_if(dispatchedMessageRowIdMap.begin(), dispatchedMessageRowIdMap.end(), std::find_if(dispatchedMessageRowIdMap.begin(), dispatchedMessageRowIdMap.end(),
[&](RowId dispatchedId) { return dispatchedId == message.id; }); [&](RowId dispatchedId) { return dispatchedId == message.id; });
MessageState messageState; assert((message.state != MessageState::pending && dispatchedMessageIt == dispatchedMessageRowIdMap.end()) ||
if (dispatchedMessageIt == dispatchedMessageRowIdMap.end()) { (message.state == MessageState::pending && dispatchedMessageIt != dispatchedMessageRowIdMap.end()));
messageState = MessageState::complete;
} else { auto chatLogMessage = ChatLogMessage{message.state, processedMessage};
messageState = MessageState::pending; switch (message.state) {
} case MessageState::complete:
auto chatLogMessage = ChatLogMessage{messageState, processedMessage};
if (messageState == MessageState::complete) {
sessionChatLog.insertCompleteMessageAtIdx(currentIdx, sender, message.dispName, sessionChatLog.insertCompleteMessageAtIdx(currentIdx, sender, message.dispName,
chatLogMessage); chatLogMessage);
} else { break;
case MessageState::pending:
sessionChatLog.insertIncompleteMessageAtIdx(currentIdx, sender, message.dispName, sessionChatLog.insertIncompleteMessageAtIdx(currentIdx, sender, message.dispName,
chatLogMessage, dispatchedMessageIt.key()); chatLogMessage, dispatchedMessageIt.key());
break;
case MessageState::broken:
sessionChatLog.insertBrokenMessageAtIdx(currentIdx, sender, message.dispName,
chatLogMessage);
break;
} }
break; break;
} }

View File

@ -324,6 +324,20 @@ void SessionChatLog::insertIncompleteMessageAtIdx(ChatLogIdx idx, const ToxPk& s
outgoingMessages.insert(dispatchId, idx); outgoingMessages.insert(dispatchId, idx);
} }
void SessionChatLog::insertBrokenMessageAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName,
const ChatLogMessage& message)
{
auto item = ChatLogItem(sender, message);
if (!senderName.isEmpty()) {
item.setDisplayName(senderName);
}
assert(message.state == MessageState::broken);
items.emplace(idx, std::move(item));
}
void SessionChatLog::insertFileAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName, const ChatLogFile& file) void SessionChatLog::insertFileAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName, const ChatLogFile& file)
{ {
auto item = ChatLogItem(sender, file); auto item = ChatLogItem(sender, file);

View File

@ -51,6 +51,8 @@ public:
const ChatLogMessage& message); const ChatLogMessage& message);
void insertIncompleteMessageAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName, void insertIncompleteMessageAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName,
const ChatLogMessage& message, DispatchedMessageId dispatchId); const ChatLogMessage& message, DispatchedMessageId dispatchId);
void insertBrokenMessageAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName,
const ChatLogMessage& message);
void insertFileAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName, const ChatLogFile& file); void insertFileAtIdx(ChatLogIdx idx, const ToxPk& sender, const QString& senderName, const ChatLogFile& file);
public slots: public slots:

View File

@ -178,11 +178,9 @@ ChatMessage::Ptr createMessage(const QString& displayName, bool isSelf, bool col
messageType = ChatMessage::MessageType::ALERT; messageType = ChatMessage::MessageType::ALERT;
} }
// Spinner is displayed by passing in an empty date const auto timestamp = chatLogMessage.message.timestamp;
auto timestamp = chatLogMessage.state == MessageState::complete ? chatLogMessage.message.timestamp : QDateTime();
return ChatMessage::createChatMessage(displayName, chatLogMessage.message.content, messageType, return ChatMessage::createChatMessage(displayName, chatLogMessage.message.content, messageType,
isSelf, timestamp, colorizeNames); isSelf, chatLogMessage.state, timestamp, colorizeNames);
} }
void renderMessage(const QString& displayName, bool isSelf, bool colorizeNames, void renderMessage(const QString& displayName, bool isSelf, bool colorizeNames,