Fixes #53 last read message indicator
This commit is contained in:
@@ -145,7 +145,8 @@ void MessageLayout::actuallyLayout(int width, MessageElement::Flags flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Painting
|
// Painting
|
||||||
void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection &selection)
|
void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection &selection,
|
||||||
|
bool isLastReadMessage, bool isWindowFocused)
|
||||||
{
|
{
|
||||||
QPixmap *pixmap = this->buffer.get();
|
QPixmap *pixmap = this->buffer.get();
|
||||||
singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance();
|
singletons::ThemeManager &themeManager = singletons::ThemeManager::getInstance();
|
||||||
@@ -180,6 +181,16 @@ void MessageLayout::paint(QPainter &painter, int y, int messageIndex, Selection
|
|||||||
// draw gif emotes
|
// draw gif emotes
|
||||||
this->container.paintAnimatedElements(painter, y);
|
this->container.paintAnimatedElements(painter, y);
|
||||||
|
|
||||||
|
// draw last read message line
|
||||||
|
if (isLastReadMessage) {
|
||||||
|
QColor color = isWindowFocused ? themeManager.tabs.selected.backgrounds.regular.color()
|
||||||
|
: themeManager.tabs.selected.backgrounds.unfocused.color();
|
||||||
|
|
||||||
|
QBrush brush = QBrush(color, Qt::VerPattern);
|
||||||
|
|
||||||
|
painter.fillRect(0, y + this->container.getHeight() - 1, this->container.width, 1, brush);
|
||||||
|
}
|
||||||
|
|
||||||
this->bufferValid = true;
|
this->bufferValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ public:
|
|||||||
bool layout(int width, float scale, MessageElement::Flags flags);
|
bool layout(int width, float scale, MessageElement::Flags flags);
|
||||||
|
|
||||||
// Painting
|
// Painting
|
||||||
void paint(QPainter &painter, int y, int messageIndex, Selection &selection);
|
void paint(QPainter &painter, int y, int messageIndex, Selection &selection,
|
||||||
|
bool isLastReadMessage, bool isWindowFocused);
|
||||||
void invalidateBuffer();
|
void invalidateBuffer();
|
||||||
void deleteBuffer();
|
void deleteBuffer();
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,9 @@ ChannelView::ChannelView(BaseWidget *parent)
|
|||||||
auto e = new QResizeEvent(this->size(), this->size());
|
auto e = new QResizeEvent(this->size(), this->size());
|
||||||
this->resizeEvent(e);
|
this->resizeEvent(e);
|
||||||
delete e;
|
delete e;
|
||||||
|
|
||||||
|
singletons::SettingManager::getInstance().showLastMessageIndicator.connect(
|
||||||
|
[this](auto, auto) { this->update(); }, this->managedConnections);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelView::~ChannelView()
|
ChannelView::~ChannelView()
|
||||||
@@ -410,6 +413,17 @@ void ChannelView::pause(int msecTimeout)
|
|||||||
this->pauseTimeout.start(msecTimeout);
|
this->pauseTimeout.start(msecTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChannelView::updateLastReadMessage()
|
||||||
|
{
|
||||||
|
auto _snapshot = this->getMessagesSnapshot();
|
||||||
|
|
||||||
|
if (_snapshot.getLength() > 0) {
|
||||||
|
this->lastReadMessage = _snapshot[_snapshot.getLength() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
this->update();
|
||||||
|
}
|
||||||
|
|
||||||
void ChannelView::resizeEvent(QResizeEvent *)
|
void ChannelView::resizeEvent(QResizeEvent *)
|
||||||
{
|
{
|
||||||
this->scrollBar.resize(this->scrollBar.width(), height());
|
this->scrollBar.resize(this->scrollBar.width(), height());
|
||||||
@@ -477,11 +491,17 @@ void ChannelView::drawMessages(QPainter &painter)
|
|||||||
(fmod(this->scrollBar.getCurrentValue(), 1)));
|
(fmod(this->scrollBar.getCurrentValue(), 1)));
|
||||||
|
|
||||||
messages::MessageLayout *end = nullptr;
|
messages::MessageLayout *end = nullptr;
|
||||||
|
bool windowFocused = this->window() == QApplication::activeWindow();
|
||||||
|
|
||||||
for (size_t i = start; i < messagesSnapshot.getLength(); ++i) {
|
for (size_t i = start; i < messagesSnapshot.getLength(); ++i) {
|
||||||
messages::MessageLayout *layout = messagesSnapshot[i].get();
|
messages::MessageLayout *layout = messagesSnapshot[i].get();
|
||||||
|
|
||||||
layout->paint(painter, y, i, this->selection);
|
bool isLastMessage = false;
|
||||||
|
if (singletons::SettingManager::getInstance().showLastMessageIndicator) {
|
||||||
|
isLastMessage = this->lastReadMessage.get() == layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout->paint(painter, y, i, this->selection, isLastMessage, windowFocused);
|
||||||
|
|
||||||
y += layout->getHeight();
|
y += layout->getHeight();
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ public:
|
|||||||
void setEnableScrollingToBottom(bool);
|
void setEnableScrollingToBottom(bool);
|
||||||
bool getEnableScrollingToBottom() const;
|
bool getEnableScrollingToBottom() const;
|
||||||
void pause(int msecTimeout);
|
void pause(int msecTimeout);
|
||||||
|
void updateLastReadMessage();
|
||||||
|
|
||||||
void setChannel(SharedChannel channel);
|
void setChannel(SharedChannel channel);
|
||||||
messages::LimitedQueueSnapshot<messages::MessageLayoutPtr> getMessagesSnapshot();
|
messages::LimitedQueueSnapshot<messages::MessageLayoutPtr> getMessagesSnapshot();
|
||||||
@@ -72,6 +73,7 @@ private:
|
|||||||
bool messageWasAdded = false;
|
bool messageWasAdded = false;
|
||||||
bool paused = false;
|
bool paused = false;
|
||||||
QTimer pauseTimeout;
|
QTimer pauseTimeout;
|
||||||
|
messages::MessageLayoutPtr lastReadMessage;
|
||||||
|
|
||||||
messages::LimitedQueueSnapshot<messages::MessageLayoutPtr> snapshot;
|
messages::LimitedQueueSnapshot<messages::MessageLayoutPtr> snapshot;
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#define WINDOW_TOPMOST "Window always on top (requires restart)"
|
#define WINDOW_TOPMOST "Window always on top (requires restart)"
|
||||||
#define INPUT_EMPTY "Hide input box when empty"
|
#define INPUT_EMPTY "Hide input box when empty"
|
||||||
#define LAST_MSG "Show last read message indicator"
|
#define LAST_MSG "Show last read message indicator (marks the spot where you left the window)"
|
||||||
#define PAUSE_HOVERING "When hovering"
|
#define PAUSE_HOVERING "When hovering"
|
||||||
|
|
||||||
#define STREAMLINK_QUALITY "Choose", "Source", "High", "Medium", "Low", "Audio only"
|
#define STREAMLINK_QUALITY "Choose", "Source", "High", "Medium", "Low", "Audio only"
|
||||||
|
|||||||
@@ -252,6 +252,11 @@ void Split::updateGifEmotes()
|
|||||||
this->view.queueUpdate();
|
this->view.queueUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Split::updateLastReadMessage()
|
||||||
|
{
|
||||||
|
this->view.updateLastReadMessage();
|
||||||
|
}
|
||||||
|
|
||||||
void Split::giveFocus(Qt::FocusReason reason)
|
void Split::giveFocus(Qt::FocusReason reason)
|
||||||
{
|
{
|
||||||
this->input.textInput.setFocus(reason);
|
this->input.textInput.setFocus(reason);
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ public:
|
|||||||
bool hasFocus() const;
|
bool hasFocus() const;
|
||||||
void layoutMessages();
|
void layoutMessages();
|
||||||
void updateGifEmotes();
|
void updateGifEmotes();
|
||||||
|
void updateLastReadMessage();
|
||||||
|
|
||||||
void drag();
|
void drag();
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ void SplitContainer::addToLayout(Split *widget, std::pair<int, int> position)
|
|||||||
this->refreshCurrentFocusCoordinates();
|
this->refreshCurrentFocusCoordinates();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<Split *> &SplitContainer::getChatWidgets() const
|
const std::vector<Split *> &SplitContainer::getSplits() const
|
||||||
{
|
{
|
||||||
return this->splits;
|
return this->splits;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public:
|
|||||||
std::pair<int, int> removeFromLayout(Split *widget);
|
std::pair<int, int> removeFromLayout(Split *widget);
|
||||||
void addToLayout(Split *widget, std::pair<int, int> position = std::pair<int, int>(-1, -1));
|
void addToLayout(Split *widget, std::pair<int, int> position = std::pair<int, int>(-1, -1));
|
||||||
|
|
||||||
const std::vector<Split *> &getChatWidgets() const;
|
const std::vector<Split *> &getSplits() const;
|
||||||
NotebookTab *getTab() const;
|
NotebookTab *getTab() const;
|
||||||
|
|
||||||
void addChat(bool openChannelNameDialog = false, std::string chatUUID = std::string());
|
void addChat(bool openChannelNameDialog = false, std::string chatUUID = std::string());
|
||||||
|
|||||||
+22
-1
@@ -107,7 +107,7 @@ void Window::repaintVisibleChatWidgets(Channel *channel)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<Split *> &widgets = page->getChatWidgets();
|
const std::vector<Split *> &widgets = page->getSplits();
|
||||||
|
|
||||||
for (auto it = widgets.begin(); it != widgets.end(); ++it) {
|
for (auto it = widgets.begin(); it != widgets.end(); ++it) {
|
||||||
Split *widget = *it;
|
Split *widget = *it;
|
||||||
@@ -140,6 +140,27 @@ void Window::closeEvent(QCloseEvent *)
|
|||||||
this->closed();
|
this->closed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Window::event(QEvent *e)
|
||||||
|
{
|
||||||
|
switch (e->type()) {
|
||||||
|
case QEvent::WindowActivate:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEvent::WindowDeactivate: {
|
||||||
|
auto page = this->notebook.getSelectedPage();
|
||||||
|
|
||||||
|
if (page != nullptr) {
|
||||||
|
std::vector<Split *> splits = page->getSplits();
|
||||||
|
|
||||||
|
for (Split *split : splits) {
|
||||||
|
split->updateLastReadMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
};
|
||||||
|
return BaseWindow::event(e);
|
||||||
|
}
|
||||||
|
|
||||||
void Window::loadGeometry()
|
void Window::loadGeometry()
|
||||||
{
|
{
|
||||||
bool doSetGeometry = false;
|
bool doSetGeometry = false;
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void closeEvent(QCloseEvent *event) override;
|
virtual void closeEvent(QCloseEvent *event) override;
|
||||||
|
virtual bool event(QEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
singletons::ThemeManager &themeManager;
|
singletons::ThemeManager &themeManager;
|
||||||
|
|||||||
Reference in New Issue
Block a user