/*
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
*
* This program is free 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QApplication>
#include <QFileInfo>
#include <QTimer>
#include "Cache.h"
#include "ChatPage.h"
#include "Config.h"
#include "FloatingButton.h"
#include "UserSettingsPage.h"
#include "Utils.h"
#include "timeline/TimelineView.h"
#include "timeline/widgets/AudioItem.h"
#include "timeline/widgets/FileItem.h"
#include "timeline/widgets/ImageItem.h"
#include "timeline/widgets/VideoItem.h"
using TimelineEvent = mtx::events::collections::TimelineEvents;
DateSeparator::DateSeparator(QDateTime datetime, QWidget *parent)
: QWidget{parent}
{
auto now = QDateTime::currentDateTime();
auto days = now.daysTo(datetime);
font_.setWeight(60);
font_.setPixelSize(conf::timeline::fonts::dateSeparator);
QString fmt;
if (now.date().year() != datetime.date().year())
fmt = QString("ddd d MMMM yy");
else
fmt = QString("ddd d MMMM");
if (days == 0)
msg_ = tr("Today");
else if (std::abs(days) == 1)
msg_ = tr("Yesterday");
else
msg_ = datetime.toString(fmt);
QFontMetrics fm{font_};
width_ = fm.width(msg_) + HPadding * 2;
height_ = fm.ascent() + 2 * VPadding;
}
void
DateSeparator::paintEvent(QPaintEvent *)
{
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
p.setFont(font_);
// Center the box horizontally & vertically.
auto textRegion = QRectF(width() / 2 - width_ / 2, HMargin, width_, height_);
QPainterPath ppath;
ppath.addRoundedRect(textRegion, height_ / 2, height_ / 2);
p.setPen(Qt::NoPen);
p.fillPath(ppath, boxColor());
p.drawPath(ppath);
p.setPen(QPen(textColor()));
p.drawText(textRegion, Qt::AlignCenter, msg_);
}
TimelineView::TimelineView(const mtx::responses::Timeline &timeline,
QSharedPointer<MatrixClient> client,
const QString &room_id,
QWidget *parent)
: QWidget(parent)
, room_id_{room_id}
, client_{client}
{
init();
addEvents(timeline);
}
TimelineView::TimelineView(QSharedPointer<MatrixClient> client,
const QString &room_id,
QWidget *parent)
: QWidget(parent)
, room_id_{room_id}
, client_{client}
{
init();
client_->messages(room_id_, "");
}
void
TimelineView::sliderRangeChanged(int min, int max)
{
Q_UNUSED(min);
if (!scroll_area_->verticalScrollBar()->isVisible()) {
scroll_area_->verticalScrollBar()->setValue(max);
return;
}
// If the scrollbar is close to the bottom and a new message
// is added we move the scrollbar.
if (max - scroll_area_->verticalScrollBar()->value() < SCROLL_BAR_GAP) {
scroll_area_->verticalScrollBar()->setValue(max);
return;
}
int currentHeight = scroll_widget_->size().height();
int diff = currentHeight - oldHeight_;
int newPosition = oldPosition_ + diff;
// Keep the scroll bar to the bottom if it hasn't been activated yet.
if (oldPosition_ == 0 && !scroll_area_->verticalScrollBar()->isVisible())
newPosition = max;
if (lastMessageDirection_ == TimelineDirection::Top)
scroll_area_->verticalScrollBar()->setValue(newPosition);
}
void
TimelineView::fetchHistory()
{
if (!isScrollbarActivated() && !isTimelineFinished) {
if (!isVisible())
return;
isPaginationInProgress_ = true;
client_->messages(room_id_, prev_batch_token_);
paginationTimer_->start(5000);
return;
}
paginationTimer_->stop();
}
void
TimelineView::scrollDown()
{
int current = scroll_area_->verticalScrollBar()->value();
i