Downoad all images in the background and keep them in memory
As one of the first steps to offline capability we download all images and put them into the JSON stirng and into the content as data-uris for <img>-tags. This way you can go offline and keep enjoying pictures in your feeds, at least untill you restart FeedTheMonkey for now.
This commit is contained in:
parent
cf94bfe488
commit
6e450b72f1
3 changed files with 62 additions and 5 deletions
53
src/post.cpp
53
src/post.cpp
|
@ -27,7 +27,7 @@ Post::Post(QObject *parent) : QObject(parent)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Post::Post(QJsonObject post, QObject *parent) : QObject(parent)
|
Post::Post(QJsonObject post, QNetworkAccessManager *networkManager, QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
mTitle = html2text(post.value("title").toString().trimmed());
|
mTitle = html2text(post.value("title").toString().trimmed());
|
||||||
mFeedTitle = html2text(post.value("feed_title").toString().trimmed());
|
mFeedTitle = html2text(post.value("feed_title").toString().trimmed());
|
||||||
|
@ -48,6 +48,18 @@ Post::Post(QJsonObject post, QObject *parent) : QObject(parent)
|
||||||
QJsonDocument doc(post);
|
QJsonDocument doc(post);
|
||||||
QString result(doc.toJson(QJsonDocument::Indented));
|
QString result(doc.toJson(QJsonDocument::Indented));
|
||||||
mJsonString = result;
|
mJsonString = result;
|
||||||
|
|
||||||
|
mNetworkManager = networkManager;
|
||||||
|
cacheImgs();
|
||||||
|
|
||||||
|
QObject::connect(this, &Post::contentChanged, [this]() {
|
||||||
|
QJsonObject obj = QJsonDocument::fromJson(mJsonString.toUtf8()).object();
|
||||||
|
obj["content"] = QJsonValue(mContent);
|
||||||
|
QJsonDocument doc(obj);
|
||||||
|
QString result(doc.toJson(QJsonDocument::Indented));
|
||||||
|
mJsonString = result;
|
||||||
|
emit jsonStringChanged(mJsonString);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Post::~Post()
|
Post::~Post()
|
||||||
|
@ -77,3 +89,42 @@ QString Post::html2text(const QString htmlString)
|
||||||
doc.setHtml(htmlString);
|
doc.setHtml(htmlString);
|
||||||
return doc.toPlainText();
|
return doc.toPlainText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Post::cacheImgs()
|
||||||
|
{
|
||||||
|
QRegExp imgTagRegex("\\<img[^\\>]*src\\s*=\\s*\"([^\"]*)\"[^\\>]*\\>", Qt::CaseInsensitive);
|
||||||
|
imgTagRegex.setMinimal(true);
|
||||||
|
QStringList urlmatches;
|
||||||
|
int offset = 0;
|
||||||
|
while( (offset = imgTagRegex.indexIn(mContent, offset)) != -1){
|
||||||
|
offset += imgTagRegex.matchedLength();
|
||||||
|
urlmatches.append(imgTagRegex.cap(1)); // Should hold only src property
|
||||||
|
}
|
||||||
|
|
||||||
|
for(QString url : urlmatches) {
|
||||||
|
|
||||||
|
if(url.startsWith("http")) {
|
||||||
|
QNetworkRequest request(url);
|
||||||
|
QNetworkReply *reply = mNetworkManager->get(request);
|
||||||
|
|
||||||
|
connect(reply, &QNetworkReply::finished, [url, this, reply] () {
|
||||||
|
if (reply) {
|
||||||
|
if (reply->error() == QNetworkReply::NoError) {
|
||||||
|
QVariant mimeType(reply->header(QNetworkRequest::ContentTypeHeader));
|
||||||
|
QString imgString = QString("data:") + mimeType.toString() + QString(";base64,") + QString(reply->readAll().toBase64());
|
||||||
|
if(mimeType == "image/jpeg" || mimeType == "image/gif" || mimeType == "image/png")
|
||||||
|
{
|
||||||
|
mContent = mContent.replace(url, imgString);
|
||||||
|
emit contentChanged(mContent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
//do some error management
|
||||||
|
qWarning() << "HTTP error: " << httpStatus;
|
||||||
|
}
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
12
src/post.h
12
src/post.h
|
@ -24,6 +24,7 @@
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QDate>
|
#include <QDate>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
|
||||||
class Post : public QObject
|
class Post : public QObject
|
||||||
{
|
{
|
||||||
|
@ -35,16 +36,16 @@ class Post : public QObject
|
||||||
Q_PROPERTY(QString author READ author CONSTANT)
|
Q_PROPERTY(QString author READ author CONSTANT)
|
||||||
Q_PROPERTY(QUrl link READ link CONSTANT)
|
Q_PROPERTY(QUrl link READ link CONSTANT)
|
||||||
Q_PROPERTY(QDateTime date READ date CONSTANT)
|
Q_PROPERTY(QDateTime date READ date CONSTANT)
|
||||||
Q_PROPERTY(QString content READ content CONSTANT)
|
Q_PROPERTY(QString content READ content NOTIFY contentChanged)
|
||||||
Q_PROPERTY(QString excerpt READ excerpt CONSTANT)
|
Q_PROPERTY(QString excerpt READ excerpt CONSTANT)
|
||||||
Q_PROPERTY(bool starred READ starred NOTIFY starredChanged)
|
Q_PROPERTY(bool starred READ starred NOTIFY starredChanged)
|
||||||
Q_PROPERTY(bool read READ read WRITE setRead NOTIFY readChanged)
|
Q_PROPERTY(bool read READ read WRITE setRead NOTIFY readChanged)
|
||||||
Q_PROPERTY(bool dontChangeRead READ dontChangeRead WRITE setDontChangeRead NOTIFY dontChangeReadChanged)
|
Q_PROPERTY(bool dontChangeRead READ dontChangeRead WRITE setDontChangeRead NOTIFY dontChangeReadChanged)
|
||||||
Q_PROPERTY(QString jsonString READ jsonString CONSTANT)
|
Q_PROPERTY(QString jsonString READ jsonString NOTIFY jsonStringChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Post(QObject *parent = 0);
|
Post(QObject *parent = 0);
|
||||||
Post(QJsonObject post, QObject *parent = 0);
|
Post(QJsonObject post, QNetworkAccessManager *networkManager, QObject *parent = 0);
|
||||||
~Post();
|
~Post();
|
||||||
QString title() const { return mTitle; }
|
QString title() const { return mTitle; }
|
||||||
QString feedTitle() const { return mFeedTitle; }
|
QString feedTitle() const { return mFeedTitle; }
|
||||||
|
@ -63,9 +64,11 @@ public:
|
||||||
QString jsonString() const { return mJsonString; }
|
QString jsonString() const { return mJsonString; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void contentChanged(QString);
|
||||||
void starredChanged(bool);
|
void starredChanged(bool);
|
||||||
void readChanged(bool);
|
void readChanged(bool);
|
||||||
void dontChangeReadChanged(bool);
|
void dontChangeReadChanged(bool);
|
||||||
|
void jsonStringChanged(QString);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
@ -83,7 +86,10 @@ private:
|
||||||
bool mRead;
|
bool mRead;
|
||||||
bool mDontChangeRead;
|
bool mDontChangeRead;
|
||||||
QString mJsonString;
|
QString mJsonString;
|
||||||
|
|
||||||
QString html2text(const QString htmlString);
|
QString html2text(const QString htmlString);
|
||||||
|
void cacheImgs();
|
||||||
|
QNetworkAccessManager *mNetworkManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // POST_H
|
#endif // POST_H
|
||||||
|
|
|
@ -62,7 +62,7 @@ void TinyTinyRSS::reload()
|
||||||
for(int i = 0; i < posts.count(); i++)
|
for(int i = 0; i < posts.count(); i++)
|
||||||
{
|
{
|
||||||
QJsonObject postJson = posts.at(i).toObject();
|
QJsonObject postJson = posts.at(i).toObject();
|
||||||
Post *post = new Post(postJson, this);
|
Post *post = new Post(postJson, mNetworkManager, this);
|
||||||
connect(post, SIGNAL(readChanged(bool)), this, SLOT(onPostReadChanged(bool)));
|
connect(post, SIGNAL(readChanged(bool)), this, SLOT(onPostReadChanged(bool)));
|
||||||
mPosts.append(post);
|
mPosts.append(post);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue