Mercurial > minori
changeset 365:f81bed4e04ac
*: megacommit that probably breaks things
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Wed, 02 Oct 2024 23:06:43 -0400 |
parents | 99c961c91809 |
children | 886f66775f31 |
files | dep/animone/src/fd/proc.cc dep/animone/src/fd/xnu.cc include/gui/widgets/anime_button.h include/gui/widgets/graph.h include/gui/widgets/text.h src/core/strings.cc src/gui/dialog/licenses.cc src/gui/pages/seasons.cc src/gui/widgets/anime_button.cc src/gui/widgets/text.cc src/services/anilist.cc |
diffstat | 11 files changed, 271 insertions(+), 183 deletions(-) [+] |
line wrap: on
line diff
--- a/dep/animone/src/fd/proc.cc Tue Jul 16 21:15:59 2024 -0400 +++ b/dep/animone/src/fd/proc.cc Wed Oct 02 23:06:43 2024 -0400 @@ -21,7 +21,34 @@ namespace animone::internal::proc { -static bool IsRegularFile(std::string link) { +struct Fdinfo { + bool Parse(std::istream& istr); + std::unordered_map<std::string, std::string> data; +}; + +bool Fdinfo::Parse(std::istream& istr) { + /* shift to the start of the stream */ + istr.seekg(0); + + for (std::string line; std::getline(istr, line); ) { + if (line.empty()) /* huh? */ + continue; + + std::size_t colon = line.find(':'); + if (colon == std::string::npos) + return false; + + std::string key = line.substr(0, colon); + std::string value = line.substr(colon + 1); + util::TrimLeft(value, " "); + + data[key] = value; + } + + return true; +} + +static bool IsRegularFile(const std::string& link) { struct stat sb; if (stat(link.c_str(), &sb) == -1) return false; @@ -37,15 +64,22 @@ if (!file) return false; - int flags = 0; - for (std::string line; std::getline(file, line);) - if (line.find("flags:", 0) == 0) - flags = util::StringToInt(line.substr(line.find_last_not_of("0123456789") + 1)); + Fdinfo fdinfo; + if (!fdinfo.Parse(file)) + return false; + + if (fdinfo.data.find("flags") == fdinfo.data.end()) + return false; /* check if the file was opened in a write mode */ - int accflags = flags & O_ACCMODE; - if (accflags == O_WRONLY || accflags == O_RDWR) - return false; + try { + const long long accflags = std::stoll(fdinfo.data["flags"]) & O_ACCMODE; + + if (accflags == O_WRONLY || accflags == O_RDWR) + return false; + } catch (const std::exception& ex) { + return false; /* huh ? */ + } return true; }
--- a/dep/animone/src/fd/xnu.cc Tue Jul 16 21:15:59 2024 -0400 +++ b/dep/animone/src/fd/xnu.cc Wed Oct 02 23:06:43 2024 -0400 @@ -35,21 +35,28 @@ namespace animone::internal::xnu { bool EnumerateOpenProcesses(process_proc_t process_proc) { - size_t pids_size = 256; - std::unique_ptr<pid_t[]> pids; + /* pre-allocate 256 pids */ + std::vector<pid_t> pids(256); + int returned_size_bytes = 0; + + for (;;) { + returned_size_bytes = proc_listpids(PROC_ALL_PIDS, 0, pids.data(), pids.size() * sizeof(pid_t)); + if (returned_size_bytes <= 0) /* probably an error ? */ + return false; - int returned_size = 0; - do { - pids.reset(new pid_t[pids_size *= 2]); - returned_size = proc_listpids(PROC_ALL_PIDS, 0, pids.get(), pids_size * sizeof(pid_t)); - if (returned_size == -1) - return false; - } while ((pids_size * sizeof(size_t)) < returned_size); + /* break out of the loop if we have everything */ + if ((pids.size() * sizeof(pid_t)) > returned_size_bytes) + break; + + pids.resize(pids.size() * 2); + } - for (int i = 0; i < pids_size; i++) { + pids.resize(returned_size_bytes); + + for (const auto& pid : pids) { std::string result; - GetProcessName(pids[i], result); - if (!process_proc({.platform = ExecutablePlatform::Xnu, .pid = pids[i], .comm = result})) + GetProcessName(pid, result); + if (!process_proc({.platform = ExecutablePlatform::Xnu, .pid = pid, .comm = result})) return false; } @@ -61,36 +68,41 @@ return false; for (const auto& pid : pids) { - const int bufsz = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); - if (bufsz < 0) - return false; + /* most processes probably don't even have that many files opened! */ + std::vector<struct proc_fdinfo> fds(4); + int returned_size_bytes = 0; + + for (;;) { + returned_size_bytes = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds.data(), fds.size()); + if (returned_size_bytes <= 0) /* probably an error ? */ + return false; - const size_t info_len = bufsz / sizeof(struct proc_fdinfo); - if (info_len < 1) - return false; + /* break out of the loop if we have everything */ + if ((fds.size() * sizeof(struct proc_fdinfo)) > returned_size_bytes) + break; - std::unique_ptr<struct proc_fdinfo[]> info(new struct proc_fdinfo[info_len]); - if (!info) - return false; + fds.resize(fds.size() * 2); + } - proc_pidinfo(pid, PROC_PIDLISTFDS, 0, info.get(), bufsz); + fds.resize(returned_size_bytes / sizeof(struct proc_fdinfo)); - for (size_t i = 0; i < info_len; i++) { - if (info[i].proc_fdtype == PROX_FDTYPE_VNODE) { - struct vnode_fdinfowithpath vnodeInfo; + for (const auto& fd : fds) { + if (fd.proc_fdtype != PROX_FDTYPE_VNODE) + continue; + + struct vnode_fdinfowithpath vnodeInfo; - int sz = proc_pidfdinfo(pid, info[i].proc_fd, PROC_PIDFDVNODEPATHINFO, &vnodeInfo, - PROC_PIDFDVNODEPATHINFO_SIZE); - if (sz != PROC_PIDFDVNODEPATHINFO_SIZE) - return false; + int sz = proc_pidfdinfo(pid, fd.proc_fd, PROC_PIDFDVNODEPATHINFO, &vnodeInfo, + PROC_PIDFDVNODEPATHINFO_SIZE); + if (sz != PROC_PIDFDVNODEPATHINFO_SIZE) + return false; - /* why would a media player open a file in write mode? */ - if (vnodeInfo.pfi.fi_openflags & FWRITE) - continue; + /* why would a media player open a file in write mode? */ + if (vnodeInfo.pfi.fi_openflags & FWRITE) + continue; - if (!open_file_proc({pid, vnodeInfo.pvip.vip_path})) - return false; - } + if (!open_file_proc({pid, vnodeInfo.pvip.vip_path})) + return false; } } @@ -100,7 +112,7 @@ static bool GetProcessNameFromProcPidPath(pid_t pid, std::string& result) { result.assign(PROC_PIDPATHINFO_MAXSIZE, '\0'); - int ret = proc_pidpath(pid, result.data(), result.size() * sizeof(char)); + int ret = proc_pidpath(pid, result.data(), result.size()); if (ret <= 0) return false; @@ -116,7 +128,7 @@ static bool GetProcessNameFromProcName(pid_t pid, std::string& result) { result.assign(2 * MAXCOMLEN, '\0'); - int size = proc_name(pid, &result.front(), result.length()); + int size = proc_name(pid, result.data(), result.length()); /* if size is MAXCOMLEN or 2 * MAXCOMLEN, assume * this method won't work and our result is truncated */
--- a/include/gui/widgets/anime_button.h Tue Jul 16 21:15:59 2024 -0400 +++ b/include/gui/widgets/anime_button.h Wed Oct 02 23:06:43 2024 -0400 @@ -13,7 +13,7 @@ class Anime; } -class AnimeButton : public QFrame { +class AnimeButton final : public QFrame { Q_OBJECT public: @@ -21,6 +21,9 @@ AnimeButton(const Anime::Anime& anime, QWidget* parent = nullptr); void SetAnime(const Anime::Anime& anime); + bool hasHeightForWidth() const override; + int heightForWidth(int w) const override; + protected: Poster _poster; QLabel _title;
--- a/include/gui/widgets/graph.h Tue Jul 16 21:15:59 2024 -0400 +++ b/include/gui/widgets/graph.h Wed Oct 02 23:06:43 2024 -0400 @@ -103,6 +103,8 @@ /* only draw this if we actually have any data */ if (total) { + const int rect_width = (static_cast<double>(value) / total) * (width - offset - HORIZ_SPACING - value_width); + painter.save(); QPen pen(painter.pen()); @@ -110,12 +112,11 @@ painter.setPen(pen); QPainterPath path; - path.addRect(x + offset, y, - (static_cast<double>(value) / total) * (width - offset - HORIZ_SPACING - value_width), each_height); + path.addRect(x + offset, y, rect_width, each_height); painter.fillPath(path, Qt::darkGreen); painter.drawPath(path); - offset += (static_cast<double>(value) / total) * (width - offset - HORIZ_SPACING - value_width); + offset += rect_width; painter.restore(); }
--- a/include/gui/widgets/text.h Tue Jul 16 21:15:59 2024 -0400 +++ b/include/gui/widgets/text.h Wed Oct 02 23:06:43 2024 -0400 @@ -30,6 +30,21 @@ QPointer<QFrame> separator_; }; +class Label final : public QLabel { + Q_OBJECT + +public: + Label(QWidget *parent = nullptr); + Label(const QString &string, QWidget *parent = nullptr); + void SetElidingMode(bool elide); + +protected: + void paintEvent(QPaintEvent *event) override; + +private: + bool elide_; +}; + /* This is a nice clean wrapper around Label suitable for our needs. */ class Paragraph : public QWidget { Q_OBJECT @@ -65,7 +80,7 @@ QPointer<QWidget> contents_; QPointer<QGridLayout> contents_layout_; - std::vector<std::pair<QSharedPointer<QLabel>, QSharedPointer<QLabel>>> data_; + std::vector<std::pair<QSharedPointer<Label>, QSharedPointer<Label>>> data_; }; /* this is just a generic QLabel with a specific font and foreground role,
--- a/src/core/strings.cc Tue Jul 16 21:15:59 2024 -0400 +++ b/src/core/strings.cc Wed Oct 02 23:06:43 2024 -0400 @@ -82,9 +82,9 @@ /* this also performs case folding, so our string is lowercase after this */ void NormalizeUnicode(std::string& string) { static constexpr utf8proc_option_t options = static_cast<utf8proc_option_t>( - UTF8PROC_COMPAT | UTF8PROC_COMPOSE | UTF8PROC_STABLE | - UTF8PROC_IGNORE | UTF8PROC_STRIPCC | UTF8PROC_STRIPMARK | - UTF8PROC_LUMP | UTF8PROC_CASEFOLD | UTF8PROC_NLF2LS + UTF8PROC_COMPAT | UTF8PROC_COMPOSE | UTF8PROC_STABLE | + UTF8PROC_IGNORE | UTF8PROC_STRIPCC | UTF8PROC_STRIPMARK | + UTF8PROC_LUMP | UTF8PROC_CASEFOLD | UTF8PROC_NLF2LS ); /* ack */ @@ -97,11 +97,12 @@ options ); - if (size) - string = std::string(reinterpret_cast<const char*>(buf), size); + if (buf) { + if (size) + string.assign(reinterpret_cast<const char*>(buf), size); - if (buf) - free(buf); + std::free(buf); + } } void NormalizeAnimeTitle(std::string& string) { @@ -190,14 +191,20 @@ return def; } +template<typename T> +constexpr T ipow(T num, unsigned int pow) { + return (pow >= sizeof(unsigned int)*8) ? 0 : + pow == 0 ? 1 : num * ipow(num, pow-1); +} + /* util funcs */ uint64_t HumanReadableSizeToBytes(const std::string& str) { static const std::unordered_map<std::string, uint64_t> bytes_map = { - {"KB", 1000ull}, - {"MB", 1000000ull}, - {"GB", 1000000000ull}, - {"TB", 1000000000000ull}, - {"PB", 1000000000000000ull}, + {"KB", 1e3}, + {"MB", 1e6}, + {"GB", 1e9}, + {"TB", 1e12}, + {"PB", 1e15}, {"KiB", 1ull << 10}, {"MiB", 1ull << 20}, {"GiB", 1ull << 30},
--- a/src/gui/dialog/licenses.cc Tue Jul 16 21:15:59 2024 -0400 +++ b/src/gui/dialog/licenses.cc Wed Oct 02 23:06:43 2024 -0400 @@ -24,14 +24,49 @@ # include "sys/win32/dark_theme.h" #endif -static QWidget *create_license_widget(QWidget *parent, const std::string& license) { +static QWidget *create_license_widget(QWidget *parent, const QString& license) { QTextBrowser* paragraph = new QTextBrowser(parent); paragraph->setFrameShape(QFrame::NoFrame); - paragraph->setPlainText(Strings::ToQString(license)); + paragraph->setPlainText(license); paragraph->setFont(QFont("monospace")); return paragraph; } +static void create_basic_license(QTabWidget *tab_widget, const QString& filename, const QString& title) { + QFile f(filename); + if (!f.exists()) + return; + + f.open(QFile::ReadOnly | QFile::Text); + tab_widget->addTab(create_license_widget(tab_widget, f.readAll()), title); +} + +static void create_dual_license(QTabWidget *tab_widget, const QString& filename1, const QString& title1, const QString& filename2, const QString& title2) { + QString l1, l2; + { + QFile f1(filename1), f2(filename2); + if (!f1.exists() || !f2.exists()) + return; + + f1.open(QFile::ReadOnly | QFile::Text); + f2.open(QFile::ReadOnly | QFile::Text); + + l1 = f1.readAll(); + l2 = f2.readAll(); + } + + QWidget *dual = new QWidget(tab_widget); + QVBoxLayout *dual_layout = new QVBoxLayout(dual); + + QLabel *dual_notice = new QLabel(QCoreApplication::tr("%1 was originally forked from %2, where any changes divergent from %2 are now under a different license. Both the licenses for %1 and %2 are provided below, respectfully:").arg(title1, title2), dual); + dual_notice->setWordWrap(true); + dual_layout->addWidget(dual_notice); + dual_layout->addWidget(create_license_widget(dual, l1)); + dual_layout->addWidget(create_license_widget(dual, l2)); + + tab_widget->addTab(dual, title1); +} + LicensesWindow::LicensesWindow(QWidget* parent) : QDialog(parent) { resize(641, 500); setWindowTitle(tr("About Minori")); @@ -46,101 +81,17 @@ layout->addWidget(tab_widget); - do { - QFile f(":/licenses/LICENSE.minori"); - if (!f.exists()) - break; - - f.open(QFile::ReadOnly | QFile::Text); - tab_widget->addTab(create_license_widget(this, Strings::ToUtf8String(f.readAll())), tr("Minori")); - } while (0); - - do { - QFile f(":/licenses/LICENSE.MIT.animone"); - QFile b(":/licenses/LICENSE.BSD.animone"); - if (!f.exists() || !b.exists()) - break; - - f.open(QFile::ReadOnly | QFile::Text); - b.open(QFile::ReadOnly | QFile::Text); - - std::string mit = Strings::ToUtf8String(f.readAll()); - std::string bsd = Strings::ToUtf8String(b.readAll()); + create_basic_license(tab_widget, ":/licenses/LICENSE.minori", tr("Minori")); - QWidget *dual = new QWidget(this); - QVBoxLayout *dual_layout = new QVBoxLayout(dual); - - QLabel *dual_notice = new QLabel(tr("Animone was originally forked from Anisthesia, where any changes divergent from Anisthesia are now under a different license. Both the licenses for Animone and Anisthesia are provided below, respectfully:"), dual); - dual_notice->setWordWrap(true); - dual_layout->addWidget(dual_notice); - dual_layout->addWidget(create_license_widget(dual, bsd)); - dual_layout->addWidget(create_license_widget(dual, mit)); - - tab_widget->addTab(dual, tr("Animone")); - } while (0); - - do { - QFile f(":/licenses/LICENSE.anitomy"); - if (!f.exists()) - break; - - f.open(QFile::ReadOnly | QFile::Text); - tab_widget->addTab(create_license_widget(this, Strings::ToUtf8String(f.readAll())), tr("Anitomy")); - } while (0); - - do { - QFile f(":/licenses/LICENSE.fmt"); - if (!f.exists()) - break; + create_dual_license(tab_widget, ":/licenses/LICENSE.MIT.animone", tr("Animone"), ":/licenses/LICENSE.BSD.animone", tr("Anisthesia")); - f.open(QFile::ReadOnly | QFile::Text); - tab_widget->addTab(create_license_widget(this, Strings::ToUtf8String(f.readAll())), tr("fmt")); - } while (0); - - do { - QFile f(":/licenses/LICENSE.nlohmann"); - if (!f.exists()) - break; - - f.open(QFile::ReadOnly | QFile::Text); - tab_widget->addTab(create_license_widget(this, Strings::ToUtf8String(f.readAll())), tr("JSON for Modern C++")); - } while (0); - - do { - QFile f(":/licenses/LICENSE.pugixml"); - if (!f.exists()) - break; - - f.open(QFile::ReadOnly | QFile::Text); - tab_widget->addTab(create_license_widget(this, Strings::ToUtf8String(f.readAll())), tr("pugixml")); - } while (0); - - do { - QFile f(":/licenses/LICENSE.semver"); - if (!f.exists()) - break; - - f.open(QFile::ReadOnly | QFile::Text); - tab_widget->addTab(create_license_widget(this, Strings::ToUtf8String(f.readAll())), tr("semver")); - } while (0); - - do { - QFile f(":/licenses/LICENSE.toml11"); - if (!f.exists()) - break; - - f.open(QFile::ReadOnly | QFile::Text); - tab_widget->addTab(create_license_widget(this, Strings::ToUtf8String(f.readAll())), tr("toml11")); - } while (0); - - do { - QFile f(":/licenses/LICENSE.utf8proc"); - if (!f.exists()) - break; - - f.open(QFile::ReadOnly | QFile::Text); - tab_widget->addTab(create_license_widget(this, Strings::ToUtf8String(f.readAll())), tr("utf8proc")); - } while (0); + create_basic_license(tab_widget, ":/licenses/LICENSE.anitomy", tr("Anitomy")); + create_basic_license(tab_widget, ":/licenses/LICENSE.fmt", tr("fmt")); + create_basic_license(tab_widget, ":/licenses/LICENSE.nlohmann", tr("JSON for Modern C++")); + create_basic_license(tab_widget, ":/licenses/LICENSE.pugixml", tr("pugixml")); + create_basic_license(tab_widget, ":/licenses/LICENSE.semver", tr("semver")); + create_basic_license(tab_widget, ":/licenses/LICENSE.toml11", tr("toml11")); + create_basic_license(tab_widget, ":/licenses/LICENSE.utf8proc", tr("utf8proc")); } void LicensesWindow::showEvent(QShowEvent* event) {
--- a/src/gui/pages/seasons.cc Tue Jul 16 21:15:59 2024 -0400 +++ b/src/gui/pages/seasons.cc Wed Oct 02 23:06:43 2024 -0400 @@ -67,7 +67,7 @@ QListWidgetItem* item = new QListWidgetItem; AnimeButton* button = new AnimeButton(this); button->SetAnime(Anime::db.items[id]); - item->setSizeHint(button->sizeHint()); + item->setSizeHint(QSize(500, 200)); buttons->addItem(item); buttons->setItemWidget(item, button); } @@ -232,6 +232,7 @@ buttons->setContentsMargins(4, 4, 4, 4); buttons->setSpacing(2); buttons->setResizeMode(QListView::Adjust); + buttons->setUniformItemSizes(true); full_layout->addWidget(buttons); }
--- a/src/gui/widgets/anime_button.cc Tue Jul 16 21:15:59 2024 -0400 +++ b/src/gui/widgets/anime_button.cc Wed Oct 02 23:06:43 2024 -0400 @@ -35,8 +35,7 @@ QHBoxLayout* ly = new QHBoxLayout(this); _poster.SetClickable(false); - _poster.setFixedSize(120, 170); - ly->addWidget(&_poster, 0, Qt::AlignTop); + ly->addWidget(&_poster, 1, Qt::AlignTop); const std::vector<std::pair<std::string, std::string>> imap = { {Strings::Translate("Aired:"), ""}, @@ -51,7 +50,6 @@ { QWidget* misc_section = new QWidget(this); - misc_section->setFixedSize(354, 180); QVBoxLayout* misc_layout = new QVBoxLayout(misc_section); misc_layout->setContentsMargins(0, 0, 0, 0); @@ -79,13 +77,12 @@ dummy_layout->setSpacing(0); dummy_layout->setContentsMargins(0, 0, 0, 0); - _synopsis.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); _synopsis.SetSelectable(false); dummy_layout->addWidget(&_synopsis); misc_layout->addWidget(dummy); } - ly->addWidget(misc_section, 0, Qt::AlignTop); + ly->addWidget(misc_section, 3, Qt::AlignTop); } } @@ -112,3 +109,11 @@ _synopsis.SetText(anime.GetSynopsis()); } + +bool AnimeButton::hasHeightForWidth() const { + return true; +} + +int AnimeButton::heightForWidth(int w) const { + return static_cast<int>(static_cast<double>(w) / 2.5); +}
--- a/src/gui/widgets/text.cc Tue Jul 16 21:15:59 2024 -0400 +++ b/src/gui/widgets/text.cc Wed Oct 02 23:06:43 2024 -0400 @@ -9,6 +9,7 @@ #include <QVBoxLayout> #include <QScrollArea> #include <QDebug> +#include <QPainter> namespace TextWidgets { @@ -16,8 +17,8 @@ Header::Header(QWidget* parent) : QWidget(parent) - , title_(new QLabel(this)) - , separator_(new QFrame(this)) { + , title_(new QLabel) + , separator_(new QFrame) { QVBoxLayout* layout = new QVBoxLayout(this); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); @@ -44,6 +45,69 @@ updateGeometry(); } +Label::Label(QWidget *parent) : QLabel(parent) {} +Label::Label(const QString &string, QWidget *parent) : QLabel(string, parent) {} + +void Label::SetElidingMode(bool elide) { + elide_ = elide; + update(); +} + +void Label::paintEvent(QPaintEvent *event) { + if (elide_) { + /* bruh */ + if (wordWrap()) { + QFrame::paintEvent(event); + + const QString content = text(); + + QPainter painter(this); + QFontMetrics fontMetrics = painter.fontMetrics(); + + bool didElide = false; + int lineSpacing = fontMetrics.lineSpacing(); + int y = 0; + + QTextLayout textLayout(content, painter.font()); + textLayout.beginLayout(); + for (;;) { + QTextLine line = textLayout.createLine(); + + if (!line.isValid()) + break; + + line.setLineWidth(width()); + int nextLineY = y + lineSpacing; + + if (height() >= nextLineY + lineSpacing) { + line.draw(&painter, QPoint(0, y)); + y = nextLineY; + } else { + QString lastLine = content.mid(line.textStart()); + QString elidedLastLine = fontMetrics.elidedText(lastLine, Qt::ElideRight, width()); + painter.drawText(QPoint(0, y + fontMetrics.ascent()), elidedLastLine); + line = textLayout.createLine(); + didElide = line.isValid(); + break; + } + } + textLayout.endLayout(); + } else { + QString backup_text = QLabel::text(); + + QFontMetrics metric(fontMetrics()); + QString elided_text = metric.elidedText(backup_text, Qt::ElideRight, width()); + + QLabel::setText(elided_text); + QLabel::paintEvent(event); + QLabel::setText(backup_text); + } + } else { + /* QLabel can handle everything... */ + QLabel::paintEvent(event); + } +} + /* ---------------------------------------------------------------------------------- */ /* "Paragraph" widgets, as in widgets meant to hold a bunch of text. */ @@ -111,8 +175,8 @@ data_.reserve(data.size()); for (std::size_t i = 0; i < data.size(); i++) { - QSharedPointer<QLabel> first(new QLabel); - QSharedPointer<QLabel> second(new QLabel); + QSharedPointer<Label> first(new Label); + QSharedPointer<Label> second(new Label); first->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); @@ -121,7 +185,7 @@ data_.push_back({first, second}); - contents_layout_->addWidget(first.data(), i, 0); + contents_layout_->addWidget(first.data(), i, 0); contents_layout_->addWidget(second.data(), i, 1); } } @@ -131,7 +195,12 @@ for (auto& [label, data] : data_) label->setStyleSheet(style_sheet); - // TODO ElidedData + if (style & LabelledParagraph::ElidedData) { + for (auto& [label, data] : data_) { + data->setWordWrap(false); + data->SetElidingMode(true); + } + } } } // namespace TextWidgets
--- a/src/services/anilist.cc Tue Jul 16 21:15:59 2024 -0400 +++ b/src/services/anilist.cc Wed Oct 02 23:06:43 2024 -0400 @@ -70,25 +70,15 @@ /* FIXME: why is this here */ -static bool AccountIsValid() { - const auto& auth = session.config.auth.anilist; - return (auth.user_id && !auth.auth_token.empty()); -} - static std::optional<nlohmann::json> SendJSONRequest(const nlohmann::json& data) { - if (!AccountIsValid()) { - session.SetStatusBar(Strings::Translate("AniList: Account isn't valid! (unauthorized?)")); - return std::nullopt; - } - - const auto& auth = session.config.auth.anilist; - - const std::vector<std::string> headers = { - "Authorization: Bearer " + auth.auth_token, + std::vector<std::string> headers = { "Accept: application/json", "Content-Type: application/json", }; + if (!session.config.auth.anilist.auth_token.empty()) + headers.push_back("Authorization: Bearer " + session.config.auth.anilist.auth_token); + const std::string response = Strings::ToUtf8String(HTTP::Request("https://graphql.anilist.co", headers, data.dump(), HTTP::Type::Post)); if (response.empty()) { session.SetStatusBar(Strings::Translate("AniList: JSON request returned an empty result!"));