diff --git a/include/headline.h b/include/headline.h index fe4f474..4b8d37d 100644 --- a/include/headline.h +++ b/include/headline.h @@ -22,6 +22,8 @@ struct Headline { QList news; QList pinned; + + QList topics; }; class LauncherCore; diff --git a/include/launcherwindow.h b/include/launcherwindow.h index 6c473e9..712fab9 100644 --- a/include/launcherwindow.h +++ b/include/launcherwindow.h @@ -4,8 +4,10 @@ #include #include #include +#include #include "launchercore.h" +#include "headline.h" class LauncherWindow : public QMainWindow { Q_OBJECT @@ -23,8 +25,13 @@ public slots: private: LauncherCore& core; + Headline headline; + bool currentlyReloadingControls = false; + QLabel* bannerImageView; + QTreeWidget* newsListView; + QComboBox* profileSelect; QLineEdit* usernameEdit, *passwordEdit; QLineEdit* otpEdit; diff --git a/src/headline.cpp b/src/headline.cpp index 48d60ed..24d7104 100644 --- a/src/headline.cpp +++ b/src/headline.cpp @@ -38,7 +38,7 @@ void getHeadline(LauncherCore& core, std::function return_func) const auto parseNews = [](QJsonObject object) -> News { News news; - news.date = QDateTime::fromString(object["date"].toString()); + news.date = QDateTime::fromString(object["date"].toString(), Qt::DateFormat::ISODate); news.id = object["id"].toString(); news.tag = object["tag"].toString(); news.title = object["title"].toString(); @@ -60,11 +60,16 @@ void getHeadline(LauncherCore& core, std::function return_func) headline.news.push_back(news); } - for(auto pinnedObject : document.object()["news"].toArray()) { + for(auto pinnedObject : document.object()["pinned"].toArray()) { auto pinned = parseNews(pinnedObject.toObject()); headline.pinned.push_back(pinned); } + for(auto pinnedObject : document.object()["topics"].toArray()) { + auto pinned = parseNews(pinnedObject.toObject()); + headline.topics.push_back(pinned); + } + return_func(headline); }); } \ No newline at end of file diff --git a/src/launcherwindow.cpp b/src/launcherwindow.cpp index f5b9551..ce600ac 100644 --- a/src/launcherwindow.cpp +++ b/src/launcherwindow.cpp @@ -5,12 +5,16 @@ #include #include #include +#include +#include +#include #include "settingswindow.h" #include "squareboot.h" #include "squarelauncher.h" #include "sapphirelauncher.h" #include "assetupdater.h" +#include "headline.h" LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindow(parent), core(core) { setWindowTitle("Astra"); @@ -86,44 +90,62 @@ LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindo QApplication::aboutQt(); }); - auto layout = new QFormLayout(); + auto layout = new QGridLayout(); + + bannerImageView = new QLabel(); + layout->addWidget(bannerImageView, 0, 0); + + newsListView = new QTreeWidget(); + newsListView->setColumnCount(2); + newsListView->setHeaderLabels({"Title", "Date"}); + newsListView->header()->setStretchLastSection(true); + newsListView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + connect(newsListView, &QTreeWidget::itemClicked, [](QTreeWidgetItem* item, int column) { + auto url = item->data(0, Qt::UserRole).toUrl(); + qInfo() << "clicked" << url; + QDesktopServices::openUrl(url); + }); + layout->addWidget(newsListView, 1, 0); + + auto loginLayout = new QFormLayout(); + layout->addLayout(loginLayout, 0, 1, 1, 1); profileSelect = new QComboBox(); connect(profileSelect, static_cast(&QComboBox::currentIndexChanged), [=](int index) { reloadControls(); }); - layout->addRow("Profile", profileSelect); + loginLayout->addRow("Profile", profileSelect); usernameEdit = new QLineEdit(); - layout->addRow("Username", usernameEdit); + loginLayout->addRow("Username", usernameEdit); rememberUsernameBox = new QCheckBox(); connect(rememberUsernameBox, &QCheckBox::stateChanged, [=](int) { currentProfile().rememberUsername = rememberUsernameBox->isChecked(); this->core.saveSettings(); }); - layout->addRow("Remember Username?", rememberUsernameBox); + loginLayout->addRow("Remember Username?", rememberUsernameBox); passwordEdit = new QLineEdit(); passwordEdit->setEchoMode(QLineEdit::EchoMode::Password); - layout->addRow("Password", passwordEdit); + loginLayout->addRow("Password", passwordEdit); rememberPasswordBox = new QCheckBox(); connect(rememberPasswordBox, &QCheckBox::stateChanged, [=](int) { currentProfile().rememberPassword = rememberPasswordBox->isChecked(); this->core.saveSettings(); }); - layout->addRow("Remember Password?", rememberPasswordBox); + loginLayout->addRow("Remember Password?", rememberPasswordBox); otpEdit = new QLineEdit(); - layout->addRow("One-Time Password", otpEdit); + loginLayout->addRow("One-Time Password", otpEdit); loginButton = new QPushButton("Login"); - layout->addRow(loginButton); + loginLayout->addRow(loginButton); registerButton = new QPushButton("Register"); - layout->addRow(registerButton); + loginLayout->addRow(registerButton); auto emptyWidget = new QWidget(); emptyWidget->setLayout(layout); @@ -179,6 +201,11 @@ LauncherWindow::LauncherWindow(LauncherCore& core, QWidget* parent) : QMainWindo }); reloadControls(); + + getHeadline(core, [this](Headline headline) { + this->headline = headline; + reloadControls(); + }); } ProfileSettings LauncherWindow::currentProfile() const { @@ -195,6 +222,52 @@ void LauncherWindow::reloadControls() { currentlyReloadingControls = true; + if(!headline.banner.empty()) { + auto request = QNetworkRequest(headline.banner[0].bannerImage); + core.buildRequest(request); + + auto reply = core.mgr->get(request); + connect(reply, &QNetworkReply::finished, [=] { + QPixmap pixmap; + pixmap.loadFromData(reply->readAll()); + bannerImageView->setPixmap(pixmap); + }); + + QTreeWidgetItem* newsItem = new QTreeWidgetItem((QTreeWidgetItem*)nullptr, QStringList("News")); + for(auto news : headline.news) { + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0, news.title); + item->setText(1, QLocale().toString(news.date, QLocale::ShortFormat)); + item->setData(0, Qt::UserRole, news.url); + + newsItem->addChild(item); + } + + QTreeWidgetItem* pinnedItem = new QTreeWidgetItem((QTreeWidgetItem*)nullptr, QStringList("Pinned")); + for(auto pinned : headline.pinned) { + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0, pinned.title); + item->setText(1, QLocale().toString(pinned.date, QLocale::ShortFormat)); + item->setData(0, Qt::UserRole, pinned.url); + + pinnedItem->addChild(item); + } + + QTreeWidgetItem* topicsItem = new QTreeWidgetItem((QTreeWidgetItem*)nullptr, QStringList("Topics")); + for(auto news : headline.topics) { + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setText(0, news.title); + item->setText(1, QLocale().toString(news.date, QLocale::ShortFormat)); + item->setData(0, Qt::UserRole, news.url); + + qInfo() << news.url; + + topicsItem->addChild(item); + } + + newsListView->insertTopLevelItems(0, QList({newsItem, pinnedItem, topicsItem})); + } + const int oldIndex = profileSelect->currentIndex(); profileSelect->clear();