fixed selections moving when new messages come in while selecting

This commit is contained in:
fourtf 2018-05-17 12:16:13 +02:00
parent 8ee0f85a2b
commit d24e1f8314
7 changed files with 112 additions and 32 deletions

View file

@ -42,6 +42,11 @@ struct SelectionItem {
{
return this->messageIndex == b.messageIndex && this->charIndex == b.charIndex;
}
bool operator!=(const SelectionItem &b) const
{
return this->operator==(b);
}
};
struct Selection {

View file

@ -45,7 +45,8 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection
this->refreshLiveStatus(); //
});
this->managedConnect(app->accounts->Twitch.currentUserChanged, [this]() { this->setMod(false); });
this->managedConnect(app->accounts->Twitch.currentUserChanged,
[this]() { this->setMod(false); });
auto refreshPubSubState = [=]() {
if (!this->hasModRights()) {
@ -102,6 +103,10 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection
this->chattersListTimer = new QTimer;
QObject::connect(this->chattersListTimer, &QTimer::timeout, doRefreshChatters);
this->chattersListTimer->start(5 * 60 * 1000);
for (int i = 0; i < 1000; i++) {
this->addMessage(messages::Message::createSystemMessage("asdf"));
}
}
TwitchChannel::~TwitchChannel()

View file

@ -28,6 +28,8 @@
#include <memory>
#define LAYOUT_WIDTH (this->width() - (this->scrollBar.isVisible() ? 16 : 4) * this->getScale())
#define SELECTION_RESUME_SCROLLING_MSG_THRESHOLD 3
#define CHAT_HOVER_PAUSE_DURATION 300
using namespace chatterino::messages;
using namespace chatterino::providers::twitch;
@ -42,9 +44,6 @@ ChannelView::ChannelView(BaseWidget *parent)
{
auto app = getApp();
#ifndef Q_OS_MAC
// this->setAttribute(Qt::WA_OpaquePaintEvent);
#endif
this->setMouseTracking(true);
this->managedConnections.emplace_back(app->settings->wordFlagsChanged.connect([=] {
@ -56,7 +55,8 @@ ChannelView::ChannelView(BaseWidget *parent)
// Whenever the scrollbar value has been changed, re-render the ChatWidgetView
this->actuallyLayoutMessages(true);
this->goToBottom->setVisible(this->enableScrollingToBottom && this->scrollBar.isVisible() &&
!this->scrollBar.isAtBottom());
!this->scrollBar.isAtBottom() &&
!this->scrollToBottomAfterTemporaryPause);
this->queueUpdate();
});
@ -97,12 +97,21 @@ ChannelView::ChannelView(BaseWidget *parent)
// });
this->pauseTimeout.setSingleShot(true);
QObject::connect(&this->pauseTimeout, &QTimer::timeout, [this] {
this->pausedTemporarily = false;
if (!this->isPaused() && this->scrollToBottomAfterTemporaryPause) {
this->scrollBar.scrollToBottom();
}
this->scrollToBottomAfterTemporaryPause = false;
});
// auto e = new QResizeEvent(this->size(), this->size());
// this->resizeEvent(e);
// delete e;
this->scrollBar.resize(this->scrollBar.width(), this->height() + 1);
// this->scrollBar.resize(this->scrollBar.width(), this->height() + 1);
app->settings->showLastMessageIndicator.connect(
[this](auto, auto) {
@ -120,6 +129,11 @@ ChannelView::ChannelView(BaseWidget *parent)
this->layoutQueued = false;
}
});
QTimer::singleShot(1, this, [this] {
this->scrollBar.setGeometry(this->width() - this->scrollBar.width(), 0,
this->scrollBar.width(), this->height());
});
}
ChannelView::~ChannelView()
@ -336,10 +350,11 @@ const boost::optional<messages::MessageElement::Flags> &ChannelView::getOverride
messages::LimitedQueueSnapshot<MessageLayoutPtr> ChannelView::getMessagesSnapshot()
{
if (!this->paused) {
// if (!this->isPaused()) {
this->snapshot = this->messages.getSnapshot();
}
// }
// return this->snapshot;
return this->snapshot;
}
@ -363,14 +378,18 @@ void ChannelView::setChannel(ChannelPtr newChannel)
}
this->lastMessageHasAlternateBackground = !this->lastMessageHasAlternateBackground;
if (this->isPaused()) {
this->messagesAddedSinceSelectionPause++;
}
if (this->messages.pushBack(MessageLayoutPtr(messageRef), deleted)) {
if (!this->paused) {
// if (!this->isPaused()) {
if (this->scrollBar.isAtBottom()) {
this->scrollBar.scrollToBottom();
} else {
this->scrollBar.offset(-1);
}
}
// }
}
if (!(message->flags & Message::DoNotTriggerNotification)) {
@ -395,7 +414,7 @@ void ChannelView::setChannel(ChannelPtr newChannel)
messageRefs.at(i) = MessageLayoutPtr(new MessageLayout(messages.at(i)));
}
if (!this->paused) {
if (!this->isPaused()) {
if (this->messages.pushFront(messageRefs).size() > 0) {
if (this->scrollBar.isAtBottom()) {
this->scrollBar.scrollToBottom();
@ -474,7 +493,15 @@ void ChannelView::detachChannel()
void ChannelView::pause(int msecTimeout)
{
this->paused = true;
if (!this->pauseTimeout.isActive()) {
this->scrollToBottomAfterTemporaryPause = this->scrollBar.isAtBottom();
}
this->beginPause();
// this->scrollBar.setDesiredValue(this->scrollBar.getDesiredValue() - 0.01);
this->pausedTemporarily = true;
this->pauseTimeout.start(msecTimeout);
}
@ -492,8 +519,8 @@ void ChannelView::updateLastReadMessage()
void ChannelView::resizeEvent(QResizeEvent *)
{
this->scrollBar.resize(this->scrollBar.width(), this->height());
this->scrollBar.move(this->width() - this->scrollBar.width(), 0);
this->scrollBar.setGeometry(this->width() - this->scrollBar.width(), 0, this->scrollBar.width(),
this->height());
this->goToBottom->setGeometry(0, this->height() - 32, this->width(), 32);
@ -507,6 +534,15 @@ void ChannelView::resizeEvent(QResizeEvent *)
void ChannelView::setSelection(const SelectionItem &start, const SelectionItem &end)
{
// selections
if (!this->selecting && start != end) {
this->messagesAddedSinceSelectionPause =
(this->scrollToBottomAfterTemporaryPause || this->scrollBar.isAtBottom()) ? 0 : 100;
this->beginPause();
this->selecting = true;
this->pausedBySelection = true;
}
this->selection = Selection(start, end);
this->selectionChanged.invoke();
@ -536,6 +572,23 @@ messages::MessageElement::Flags ChannelView::getFlags() const
return flags;
}
bool ChannelView::isPaused()
{
return this->pausedTemporarily || this->pausedBySelection;
}
void ChannelView::beginPause()
{
if (this->scrollBar.isAtBottom()) {
this->scrollBar.setDesiredValue(this->scrollBar.getDesiredValue() - 0.001);
this->layoutMessages();
}
}
void ChannelView::endPause()
{
}
void ChannelView::paintEvent(QPaintEvent * /*event*/)
{
// BENCH(timer);
@ -691,7 +744,7 @@ void ChannelView::enterEvent(QEvent *)
void ChannelView::leaveEvent(QEvent *)
{
this->paused = false;
this->pausedTemporarily = false;
}
void ChannelView::mouseMoveEvent(QMouseEvent *event)
@ -706,7 +759,7 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event)
auto app = getApp();
if (app->settings->pauseChatHover.getValue()) {
this->pause(300);
this->pause(CHAT_HOVER_PAUSE_DURATION);
}
auto tooltipWidget = TooltipWidget::getInstance();
@ -722,8 +775,8 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event)
}
// is selecting
if (this->selecting) {
this->pause(500);
if (this->isMouseDown) {
this->pause(300);
int index = layout->getSelectionIndex(relativePos);
this->setSelection(this->selection.start, SelectionItem(messageIndex, index));
@ -804,7 +857,6 @@ void ChannelView::mousePressEvent(QMouseEvent *event)
SelectionItem selectionItem(lastMessageIndex, lastCharacterIndex);
this->setSelection(selectionItem, selectionItem);
this->selecting = true;
return;
}
@ -818,7 +870,6 @@ void ChannelView::mousePressEvent(QMouseEvent *event)
auto selectionItem = SelectionItem(messageIndex, index);
this->setSelection(selectionItem, selectionItem);
this->selecting = true;
this->repaint();
}
@ -841,11 +892,23 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event)
auto app = getApp();
if (this->selecting) {
this->paused = false;
if (this->messagesAddedSinceSelectionPause <= SELECTION_RESUME_SCROLLING_MSG_THRESHOLD) {
// don't scroll
this->scrollBar.scrollToBottom(false);
// this->scrollBar.setDesiredValue(this->scrollBar.getDesiredValue() -
// this->messagesAddedSinceSelectionPause);
}
this->scrollToBottomAfterTemporaryPause = false;
this->pausedBySelection = false;
this->selecting = false;
this->pauseTimeout.stop();
this->pausedTemporarily = false;
this->layoutMessages();
}
this->isMouseDown = false;
this->selecting = false;
float distance = util::distanceBetweenPoints(this->lastPressPosition, event->screenPos());

View file

@ -86,7 +86,10 @@ private:
bool updateQueued = false;
bool messageWasAdded = false;
bool lastMessageHasAlternateBackground = false;
bool paused = false;
bool pausedTemporarily = false;
bool pausedBySelection = false;
bool scrollToBottomAfterTemporaryPause = false;
int messagesAddedSinceSelectionPause = 0;
QTimer pauseTimeout;
boost::optional<messages::MessageElement::Flags> overrideFlags;
messages::MessageLayoutPtr lastReadMessage;
@ -99,6 +102,10 @@ private:
void drawMessages(QPainter &painter);
void setSelection(const messages::SelectionItem &start, const messages::SelectionItem &end);
messages::MessageElement::Flags getFlags() const;
bool isPaused();
void beginPause();
void endPause();
ChannelPtr channel;

View file

@ -253,7 +253,7 @@ void SplitHeader::mouseReleaseEvent(QMouseEvent *event)
TooltipWidget *widget = new TooltipWidget();
widget->setText("Double click or press <ctrl+r> to change the channel.\nClick and "
widget->setText("Double click or press <Ctrl+R> to change the channel.\nClick and "
"drag to move the split.");
widget->setAttribute(Qt::WA_DeleteOnClose);
widget->move(pos);

View file

@ -86,7 +86,7 @@ SplitOverlay::SplitOverlay(Split *parent)
void SplitOverlay::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.fillRect(this->rect(), QColor(0, 0, 0, 90));
painter.fillRect(this->rect(), QColor(0, 0, 0, 150));
QRect rect;
switch (this->hoveredElement) {

View file

@ -109,14 +109,14 @@ void Scrollbar::setDesiredValue(qreal value, bool animated)
// }
this->currentValueAnimation.setEndValue(value);
this->smoothScrollingOffset = 0;
this->atBottom = ((this->getMaximum() - this->getLargeChange()) - value) <= 0.01;
this->atBottom = ((this->getMaximum() - this->getLargeChange()) - value) <= 0.0001;
this->currentValueAnimation.start();
} else {
if (this->currentValueAnimation.state() != QPropertyAnimation::Running) {
this->smoothScrollingOffset = 0;
this->desiredValue = value;
this->currentValueAnimation.stop();
this->atBottom = ((this->getMaximum() - this->getLargeChange()) - value) <= 0.01;
this->atBottom = ((this->getMaximum() - this->getLargeChange()) - value) <= 0.0001;
setCurrentValue(value);
}
}