changeset 378:5912dafc6e28 default tip

anime: add poster cache :)
author Paper <paper@tflc.us>
date Wed, 05 Nov 2025 12:50:35 -0500
parents 1b0b8e746d83
children
files include/core/anime_db.h include/core/filesystem.h include/gui/widgets/poster.h include/services/services.h src/core/anime_db.cc src/core/filesystem.cc src/gui/widgets/poster.cc
diffstat 7 files changed, 99 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/include/core/anime_db.h	Fri Jul 25 12:40:25 2025 -0400
+++ b/include/core/anime_db.h	Wed Nov 05 12:50:35 2025 -0500
@@ -5,6 +5,7 @@
 #include "json/json_fwd.hpp"
 #include <string>
 #include <unordered_map>
+#include <QImage>
 
 namespace Anime {
 
@@ -36,6 +37,8 @@
 	void RemoveAllUserData();
 
 	std::vector<int> GetAllAnimeForSeason(Season season);
+
+	QImage GetAnimePoster(int id);
 };
 
 extern Database db;
--- a/include/core/filesystem.h	Fri Jul 25 12:40:25 2025 -0400
+++ b/include/core/filesystem.h	Wed Nov 05 12:50:35 2025 -0500
@@ -10,6 +10,7 @@
 std::filesystem::path GetConfigPath(); // (dotpath)/config.json
 std::filesystem::path GetAnimeDBPath();  // (dotpath)/anime/db.json
 std::filesystem::path GetTorrentsPath(); // (dotpath)/torrents/...
+std::filesystem::path GetAnimePostersPath(); // (dotpath)/anime/posters/
 
 } // namespace Filesystem
 
--- a/include/gui/widgets/poster.h	Fri Jul 25 12:40:25 2025 -0400
+++ b/include/gui/widgets/poster.h	Wed Nov 05 12:50:35 2025 -0500
@@ -10,6 +10,22 @@
 class Anime;
 }
 
+class GetPosterThread final : public QThread {
+	/* :') */
+	Q_OBJECT
+public:
+	GetPosterThread(QObject *parent);
+	void SetId(int id);
+	virtual void run() override;
+
+	/* Or PvP boss */
+signals:
+	void Finished(const QImage &img);
+
+private:
+	int id_ = 0;
+};
+
 class Poster final : public QFrame {
 	Q_OBJECT
 
@@ -26,7 +42,7 @@
 protected:
 	void showEvent(QShowEvent*) override;
 	void resizeEvent(QResizeEvent*) override;
-	void ImageDownloadFinished(const QByteArray& arr);
+	void ImageDownloadFinished(const QImage& img);
 	void RenderToLabel();
 	void DownloadPoster();
 
@@ -35,12 +51,12 @@
 
 private:
 	/* stored as a pointer to prevent blocking */
-	HTTP::RequestThread* get_thread_;
+	GetPosterThread* get_thread_;
 
 	QImage img_;
 	QString service_url_;
-	std::string poster_url_;
 	ClickableLabel label_;
+	int id_;
 
 	bool clickable_ = true;
 	bool need_refresh_ = false;
--- a/include/services/services.h	Fri Jul 25 12:40:25 2025 -0400
+++ b/include/services/services.h	Wed Nov 05 12:50:35 2025 -0500
@@ -7,6 +7,8 @@
 #include <string>
 #include <vector>
 
+// TODO this stuff should be asynchronous
+
 namespace Services {
 
 void Synchronize();
--- a/src/core/anime_db.cc	Fri Jul 25 12:40:25 2025 -0400
+++ b/src/core/anime_db.cc	Wed Nov 05 12:50:35 2025 -0500
@@ -4,6 +4,7 @@
 #include "core/json.h"
 #include "core/session.h"
 #include "core/strings.h"
+#include "core/http.h"
 
 #include "gui/translate/anilist.h"
 #include "gui/translate/anime.h"
@@ -379,6 +380,45 @@
 	return res;
 }
 
+QImage Database::GetAnimePoster(int id)
+{
+	/* Creates an anime poster and then saves it to disk */
+	QImage res;
+	QString posterfile;
+
+	std::filesystem::path posterpath = Filesystem::GetAnimePostersPath();
+
+	posterpath = posterpath / ((Strings::ToUtf8String(id) + ".png"));
+
+	Filesystem::CreateDirectories(posterpath);
+
+	/* Load from disk if available */
+	posterfile = Strings::ToQString(posterpath.string());
+
+	if (res.load(posterfile))
+		return res;
+
+	/* TODO check if the anime even exists.. */
+
+	Anime &anime = db.items[id];
+
+	QByteArray arr = HTTP::Request(anime.GetPosterUrl());
+
+	/* If it's not valid, return dummy QImage */
+	if (arr.isNull() || !res.loadFromData(arr))
+		return QImage();
+
+	qDebug() << posterfile;
+
+	/* Save the result to disk
+	 * TODO might be more efficient to save with original format,
+	 * and save filename as well */
+	if (!res.save(posterfile, "png"))
+		qDebug() << "oops\n";
+
+	return res;
+}
+
 Database db;
 
 } // namespace Anime
--- a/src/core/filesystem.cc	Fri Jul 25 12:40:25 2025 -0400
+++ b/src/core/filesystem.cc	Wed Nov 05 12:50:35 2025 -0500
@@ -51,4 +51,9 @@
 	return GetDotPath() / "torrents";
 }
 
+std::filesystem::path GetAnimePostersPath()
+{
+	return GetDotPath() / "anime" / "posters";
+}
+
 } // namespace Filesystem
--- a/src/gui/widgets/poster.cc	Fri Jul 25 12:40:25 2025 -0400
+++ b/src/gui/widgets/poster.cc	Wed Nov 05 12:50:35 2025 -0500
@@ -18,6 +18,24 @@
 
 #include <iostream>
 
+GetPosterThread::GetPosterThread(QObject *parent) : QThread(parent)
+{
+}
+
+void GetPosterThread::SetId(int id)
+{
+	id_ = id;
+}
+
+void GetPosterThread::run()
+{
+	/* this sucks cuz we can't really STOP the thread easily
+	 * without making it fully finish */
+	QImage img = Anime::db.GetAnimePoster(id_);
+
+	emit Finished(img);
+}
+
 Poster::Poster(QWidget *parent) : QFrame(parent)
 {
 	QHBoxLayout *layout = new QHBoxLayout(this);
@@ -31,8 +49,8 @@
 	label_.setAlignment(Qt::AlignCenter);
 	layout->addWidget(&label_);
 
-	get_thread_ = new HTTP::RequestThread(HTTP::Type::Get);
-	connect(get_thread_, &HTTP::RequestThread::ReceivedData, this, &Poster::ImageDownloadFinished);
+	get_thread_ = new GetPosterThread(nullptr);
+	connect(get_thread_, &GetPosterThread::Finished, this, &Poster::ImageDownloadFinished);
 }
 
 Poster::Poster(const Anime::Anime &anime, QWidget *parent) : Poster(parent)
@@ -48,11 +66,10 @@
 
 void Poster::DownloadPoster()
 {
-	if (get_thread_->isRunning())
-		get_thread_->Stop();
+	/* ;-; */
 	get_thread_->wait();
 
-	get_thread_->SetUrl(poster_url_);
+	get_thread_->SetId(id_);
 	get_thread_->start();
 }
 
@@ -60,11 +77,13 @@
 {
 	label_.clear();
 
-	poster_url_ = anime.GetPosterUrl();
-	if (isVisible())
+	id_ = anime.GetId();
+
+	if (isVisible()) {
 		DownloadPoster();
-	else
+	} else {
 		need_refresh_ = true;
+	}
 
 	std::optional<std::string> url = anime.GetServiceUrl(session.config.service);
 	if (url)
@@ -98,9 +117,9 @@
 	}
 }
 
-void Poster::ImageDownloadFinished(const QByteArray &arr)
+void Poster::ImageDownloadFinished(const QImage &img)
 {
-	img_.loadFromData(arr);
+	img_ = img;
 	RenderToLabel();
 }