Skip to content

Commit

Permalink
Display message being replied to above input box (#4350)
Browse files Browse the repository at this point in the history
Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
  • Loading branch information
dnsge and pajlada authored Jul 14, 2024
1 parent 9788d0f commit 6b73bb5
Show file tree
Hide file tree
Showing 7 changed files with 353 additions and 58 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- Minor: Improve appearance of reply button. (#5491)
- Minor: Introduce HTTP API for plugins. (#5383, #5492, #5494)
- Minor: Support more Firefox variants for incognito link opening. (#5503)
- Minor: Replying to a message will now display the message being replied to. (#4350)
- Minor: Links can now have prefixes and suffixes such as parentheses. (#5486)
- Bugfix: Fixed tab move animation occasionally failing to start after closing a tab. (#5426)
- Bugfix: If a network request errors with 200 OK, Qt's error code is now reported instead of the HTTP status. (#5378)
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,8 @@ set(SOURCE_FILES
widgets/helper/IconDelegate.hpp
widgets/helper/InvisibleSizeGrip.cpp
widgets/helper/InvisibleSizeGrip.hpp
widgets/helper/MessageView.cpp
widgets/helper/MessageView.hpp
widgets/helper/NotebookButton.cpp
widgets/helper/NotebookButton.hpp
widgets/helper/NotebookTab.cpp
Expand Down
2 changes: 1 addition & 1 deletion src/messages/MessageElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ SingleLineTextElement::SingleLineTextElement(const QString &text,
void SingleLineTextElement::addToContainer(MessageLayoutContainer &container,
MessageElementFlags flags)
{
auto *app = getApp();
auto *app = getIApp();

if (flags.hasAny(this->getFlags()))
{
Expand Down
134 changes: 134 additions & 0 deletions src/widgets/helper/MessageView.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#include "widgets/helper/MessageView.hpp"

#include "Application.hpp"
#include "messages/layouts/MessageLayout.hpp"
#include "messages/MessageElement.hpp"
#include "messages/Selection.hpp"
#include "providers/colors/ColorProvider.hpp"
#include "singletons/Theme.hpp"
#include "singletons/WindowManager.hpp"

#include <QApplication>
#include <QPainter>

namespace {

using namespace chatterino;

const Selection EMPTY_SELECTION;

const MessageElementFlags MESSAGE_FLAGS{
MessageElementFlag::Text,
MessageElementFlag::EmojiAll,
MessageElementFlag::EmoteText,
};

} // namespace

namespace chatterino {

MessageView::MessageView() = default;
MessageView::~MessageView() = default;

void MessageView::createMessageLayout()
{
if (this->message_ == nullptr)
{
this->messageLayout_.reset();
return;
}

this->messageLayout_ = std::make_unique<MessageLayout>(this->message_);
}

void MessageView::setMessage(const MessagePtr &message)
{
if (!message)
{
return;
}

auto singleLineMessage = std::make_shared<Message>();
singleLineMessage->elements.emplace_back(
std::make_unique<SingleLineTextElement>(
message->messageText, MESSAGE_FLAGS, MessageColor::Type::System,
FontStyle::ChatMediumSmall));
this->message_ = std::move(singleLineMessage);
this->createMessageLayout();
this->layoutMessage();
}

void MessageView::clearMessage()
{
this->setMessage(nullptr);
}

void MessageView::setWidth(int width)
{
if (this->width_ != width)
{
this->width_ = width;
this->layoutMessage();
}
}

void MessageView::paintEvent(QPaintEvent * /*event*/)
{
QPainter painter(this);

auto ctx = MessagePaintContext{
.painter = painter,
.selection = EMPTY_SELECTION,
.colorProvider = ColorProvider::instance(),
.messageColors = this->messageColors_,
.preferences = this->messagePreferences_,

.canvasWidth = this->width_,
.isWindowFocused = this->window() == QApplication::activeWindow(),
.isMentions = false,

.y = 0,
.messageIndex = 0,
.isLastReadMessage = false,
};

this->messageLayout_->paint(ctx);
}

void MessageView::themeChangedEvent()
{
this->messageColors_.applyTheme(getTheme());
this->messageColors_.regular = getTheme()->splits.input.background;
if (this->messageLayout_)
{
this->messageLayout_->invalidateBuffer();
}
}

void MessageView::scaleChangedEvent(float newScale)
{
(void)newScale;

this->layoutMessage();
}

void MessageView::layoutMessage()
{
if (this->messageLayout_ == nullptr)
{
return;
}

bool updateRequired = this->messageLayout_->layout(
this->width_, this->scale(),
this->scale() * static_cast<float>(this->devicePixelRatio()),
MESSAGE_FLAGS, false);

if (updateRequired)
{
this->setFixedSize(this->width_, this->messageLayout_->getHeight());
this->update();
}
}

} // namespace chatterino
50 changes: 50 additions & 0 deletions src/widgets/helper/MessageView.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include "messages/layouts/MessageLayoutContext.hpp"
#include "messages/Message.hpp"
#include "widgets/BaseWidget.hpp"

#include <QWidget>

namespace chatterino {

class MessageLayout;

/// MessageView is a fixed-width widget that displays a single message.
/// For the message to be rendered, you must call setWidth.
class MessageView : public BaseWidget
{
Q_OBJECT

public:
MessageView();
~MessageView() override;
MessageView(const MessageView &) = delete;
MessageView(MessageView &&) = delete;
MessageView &operator=(const MessageView &) = delete;
MessageView &operator=(MessageView &&) = delete;

void setMessage(const MessagePtr &message);
void clearMessage();

void setWidth(int width);

protected:
void paintEvent(QPaintEvent *event) override;
void themeChangedEvent() override;
void scaleChangedEvent(float newScale) override;

private:
void createMessageLayout();
void layoutMessage();

MessagePtr message_;
std::unique_ptr<MessageLayout> messageLayout_;

MessageColors messageColors_;
MessagePreferences messagePreferences_;

int width_{};
};

} // namespace chatterino
Loading

0 comments on commit 6b73bb5

Please sign in to comment.