Commit 292ac49b authored by kaniini's avatar kaniini

add thread viewer

parent 7a0ce8b7
......@@ -424,6 +424,68 @@ void Account::fetchTimeline(QString &original_name, QString &from_id)
});
}
void Account::fetchThread(QString post_id, std::function<void (QList<std::shared_ptr<Post>>)> final_cb)
{
auto status_url = apiUrl (QString ("/api/v1/statuses/%1").arg (post_id));
auto context_url = apiUrl (QString ("/api/v1/statuses/%1/context").arg (post_id));
QList<std::shared_ptr<Post>> *thread = new QList<std::shared_ptr<Post>>;
auto on_fetch_context = [=] (QNetworkReply *reply) {
auto data = reply->readAll ();
auto doc = QJsonDocument::fromJson (data);
auto obj = doc.object ();
if (! doc.isObject ())
return;
auto ancestors = obj["ancestors"].toArray ();
for (auto anc : ancestors)
{
if (! anc.isObject ())
continue;
auto anc_obj = anc.toObject ();
auto p = std::make_shared<Post> (this, anc_obj);
thread->push_front (p);
}
auto descendents = obj["descendants"].toArray ();
for (auto desc : descendents)
{
if (! desc.isObject ())
continue;
auto desc_obj = desc.toObject ();
auto p = std::make_shared<Post> (this, desc_obj);
thread->push_back (p);
}
QList<std::shared_ptr<Post>> final_thread = QList<std::shared_ptr<Post>> (*thread);
delete thread;
final_cb (final_thread);
};
auto on_fetch_status = [=] (QNetworkReply *reply) {
auto data = reply->readAll ();
auto doc = QJsonDocument::fromJson (data);
auto obj = doc.object ();
if (! doc.isObject ())
return;
auto p = std::make_shared<Post>(this, obj);
thread->push_front(p);
get (context_url, true, on_fetch_context);
};
get (status_url, true, on_fetch_status);
}
void Account::postStatus(std::shared_ptr<Post> p)
{
......
......@@ -108,6 +108,9 @@ public:
void upload(std::shared_ptr<Post> p, QFile *file, QString filename);
void updateAttachment(Attachment *a);
// thread fetching
void fetchThread(QString post_id, std::function<void(QList<std::shared_ptr<Post>>)> final_cb);
// streaming
QUrl streamingUrl(QString stream);
QWebSocket *streamingSocket(QString stream);
......
......@@ -36,7 +36,8 @@ SOURCES += \
ui/onboardingwidget.cc \
ui/timelineselectorwidget.cc \
ui/timelinewidget.cc \
ui/notificationimpl.cc
ui/notificationimpl.cc \
ui/threadwindow.cc
HEADERS += \
core/account.h \
......@@ -52,7 +53,8 @@ HEADERS += \
ui/onboardingwidget.h \
ui/timelineselectorwidget.h \
ui/timelinewidget.h \
ui/notificationimpl.h
ui/notificationimpl.h \
ui/threadwindow.h
FORMS +=
......
#include "threadwindow.h"
ThreadWindow::ThreadWindow()
ThreadModel::ThreadModel(Michabo::AccountManager *manager, QString timeline_name, QObject *parent)
: TimelineModel(manager, timeline_name, parent)
{
fillTimeline ();
}
void ThreadModel::fillTimeline(QString)
{
qDebug() << "Fetch thread" << m_timeline_name;
m_account->fetchThread(m_timeline_name, [=] (QList<std::shared_ptr<Michabo::Post>> posts) {
qDebug() << "Got" << posts.size () << "posts";
m_timeline = posts;
for (auto p : m_timeline)
p->fetchAttachmentPreviews ();
beginInsertRows (QModelIndex (), 0, m_timeline.size ());
endInsertRows ();
});
}
bool ThreadModel::canFetchMore(const QModelIndex &) const
{
return false;
}
ThreadWindow::ThreadWindow(Michabo::AccountManager *manager, QString thread_id, QWidget *parent)
: QWidget(parent),
m_manager(manager),
m_id(thread_id)
{
setWindowTitle (QString (tr("Thread %1").arg (m_id)));
resize (300, 600);
m_model = new ThreadModel (m_manager, m_id, this);
m_timeline_widget = new TimelineWidget (m_manager, m_id, m_model, this);
m_vbox_layout = new QVBoxLayout (this);
m_vbox_layout->addWidget (m_timeline_widget);
}
......@@ -2,11 +2,32 @@
#define THREADWINDOW_H
#include <QWidget>
#include <QVBoxLayout>
class ThreadWindow
#include "timelinewidget.h"
class ThreadModel : public TimelineModel
{
public:
ThreadModel(Michabo::AccountManager *manager, QString id, QObject *parent = nullptr);
void fillTimeline(QString from_id = "");
bool canFetchMore(const QModelIndex &parent) const;
};
class ThreadWindow : public QWidget
{
Q_OBJECT
public:
ThreadWindow();
ThreadWindow(Michabo::AccountManager *manager, QString thread_id, QWidget *parent = nullptr);
private:
Michabo::AccountManager *m_manager;
QString m_id;
ThreadModel *m_model;
TimelineWidget *m_timeline_widget;
QVBoxLayout *m_vbox_layout;
};
#endif // THREADWINDOW_H
\ No newline at end of file
#endif // THREADWINDOW_H
......@@ -8,6 +8,7 @@
#include "timelinewidget.h"
#include "composeform.h"
#include "threadwindow.h"
// control the size of avatars
#define AVATAR_ICON_SIZE 48
......@@ -510,20 +511,26 @@ QSize HTMLDelegate::sizeHint(const QStyleOptionViewItem & option_, const QModelI
bool HTMLDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
if (event->type() != QEvent::MouseButtonRelease && event->type() != QEvent::MouseMove)
return false;
QMouseEvent *mouse_event = static_cast<QMouseEvent *> (event);
auto parentView = qobject_cast<QTreeView *> (parent ());
auto rect = parentView->visualRect (index);
auto pos = mouse_event->pos () - QPoint (rect.x (), rect.y ());
// check if we are in a hitbox for a link
auto anchor = m_doc.documentLayout ()->anchorAt (pos);
// get our model
auto timeline_model = static_cast<TimelineModel *>(model);
if (event->type() == QEvent::MouseButtonDblClick)
{
timeline_model->showThreadWindow(index);
return true;
}
if (event->type() != QEvent::MouseButtonRelease && event->type() != QEvent::MouseMove)
return false;
// check if we are in a hitbox for a link
auto anchor = m_doc.documentLayout ()->anchorAt (pos);
if (anchor.isEmpty ())
{
// we are not in a hitbox for a link
......@@ -657,6 +664,9 @@ TimelineModel::TimelineModel(Michabo::AccountManager *manager, QString timeline_
m_manager(manager),
m_account(m_manager->selectedAccount())
{
if (timeline_name != "home" && timeline_name != "public" && timeline_name != "federated")
return;
QObject::connect(m_manager, &Michabo::AccountManager::accountSelected, [=] (Michabo::Account *account) {
m_account = account;
......@@ -898,6 +908,15 @@ void TimelineModel::actionExpand(const QModelIndex &index)
emit dataChanged(index, index);
}
void TimelineModel::showThreadWindow(const QModelIndex &index)
{
int row = index.row ();
auto p = m_timeline[row];
auto win = new ThreadWindow(m_manager, p->m_post_id);
win->show();
}
void TimelineModel::handleMouseOver(const QModelIndex &index)
{
emit dataChanged(index, index);
......
......@@ -60,7 +60,7 @@ public:
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
void fillTimeline(QString from_id = "");
virtual void fillTimeline(QString from_id = "");
void actionReply(const QModelIndex &index);
void actionFavorite(const QModelIndex &index);
......@@ -69,6 +69,7 @@ public:
void actionVis(const QModelIndex &index);
void actionExpand(const QModelIndex &index);
void handleMouseOver(const QModelIndex &index);
void showThreadWindow(const QModelIndex &index);
void disallowUpdates() { m_last_fetch = time(nullptr) + 3; }
......@@ -82,7 +83,6 @@ protected:
void fetchMore(const QModelIndex &parent);
bool canFetchMore(const QModelIndex &parent) const;
private:
QString m_timeline_name;
Michabo::AccountManager *m_manager;
Michabo::Account *m_account;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment