Improves caching api related to urls, implements fragment handling, fixes #237

This commit is contained in:
Felix "xq" Queißner 2021-11-20 15:02:03 +01:00
parent 9744a24ffb
commit 9dd660d66e
5 changed files with 61 additions and 38 deletions

View File

@ -586,6 +586,15 @@ void BrowserTab::on_requestComplete(const QByteArray &ref_data, const MimeType &
renderPage(data, mime);
if(this->navigate_to_fragment)
{
// Implement navigation semantics:
QString fragment = this->current_location.fragment();
if(not fragment.isEmpty()) {
this->scrollToAnchor(fragment);
}
}
this->updatePageTitle();
this->updateUrlBarStyle();
@ -1585,6 +1594,18 @@ bool BrowserTab::startRequest(const QUrl &url, ProtocolHandler::RequestOptions o
QString urlstr = url.toString(QUrl::FullyEncoded);
{
QUrl old_url_cleaned = this->current_location;
QUrl new_url_cleaned = url;
old_url_cleaned.setFragment("");
new_url_cleaned.setFragment("");
// Only jump to (potential) fragment when we either change the base url
// or reload the current page with a new fragment.
this->navigate_to_fragment = ((old_url_cleaned != new_url_cleaned) or (this->current_location.fragment() != url.fragment()));
}
this->is_internal_location = (url.scheme() == "about" || url.scheme() == "file");
this->current_location = url;
this->setUrlBarText(urlstr);
@ -1596,8 +1617,7 @@ bool BrowserTab::startRequest(const QUrl &url, ProtocolHandler::RequestOptions o
return this->current_handler->startRequest(url.adjusted(QUrl::RemoveFragment), options);
};
if ((flags & RequestFlags::DontReadFromCache) ||
this->current_identity.isValid())
if ((flags & RequestFlags::DontReadFromCache) || this->current_identity.isValid())
{
return req();
}
@ -1610,10 +1630,10 @@ bool BrowserTab::startRequest(const QUrl &url, ProtocolHandler::RequestOptions o
this->was_read_from_cache = true;
this->on_requestComplete(pg->body, pg->mime);
// Move scrollbar to cached position
if ((flags & RequestFlags::NavigatedBackOrForward) &&
pg->scroll_pos != -1)
// Move scrollbar to cached position, but only if url or the fragment has changed
if ((flags & RequestFlags::NavigatedBackOrForward) && pg->scroll_pos != -1) {
this->ui->text_browser->verticalScrollBar()->setValue(pg->scroll_pos);
}
return true;
}

View File

@ -257,6 +257,9 @@ public:
RequestState request_state;
DocumentStyle current_style;
//! If set, `on_requestComplete` will navigate to the fragment of the url.
bool navigate_to_fragment = false;
};
#endif // BROWSERTAB_HPP

View File

@ -4,6 +4,11 @@
#include <QDebug>
QString CacheHandler::cleanUrl(QUrl const & url)
{
return url.toString(QUrl::FullyEncoded | QUrl::RemoveFragment);
}
void CacheHandler::push(const QUrl &url, const QByteArray &body, const MimeType &mime)
{
// Skip if this item is above the cached item size threshold
@ -20,48 +25,40 @@ void CacheHandler::push(const QUrl &url, const QByteArray &body, const MimeType
this->popOldest();
}
QString urlstr = url.toString(QUrl::FullyEncoded | QUrl::RemoveFragment);
QString urlstr = cleanUrl(url);
if (this->page_cache.find(urlstr) != this->page_cache.end())
auto it = this->page_cache.find(urlstr);
if (it != this->page_cache.end())
{
qDebug() << "cache: updating page";
auto pg = this->page_cache[urlstr];
qDebug() << "cache: updating page" << urlstr;
auto pg = it->second;
pg->body = body;
pg->mime = mime;
pg->time_cached = QDateTime::currentDateTime();
return;
}
this->page_cache[urlstr] = std::make_shared<CachedPage>(
url, body, mime, QDateTime::currentDateTime());
qDebug() << "cache: pushing url " << url;
return;
else
{
this->page_cache.emplace(urlstr, std::make_shared<CachedPage>(url, body, mime, QDateTime::currentDateTime()));
qDebug() << "cache: pushing url " << urlstr;
}
}
std::shared_ptr<CachedPage> CacheHandler::find(const QString &url)
std::shared_ptr<CachedPage> CacheHandler::find(const QUrl &url)
{
if (this->page_cache.find(url) != this->page_cache.end())
QString urltext = cleanUrl(url);
auto it = this->page_cache.find(urltext);
if(it != this->page_cache.end())
{
return this->page_cache[url];
return it->second;
}
return nullptr;
}
std::shared_ptr<CachedPage> CacheHandler::find(const QUrl &url)
{
return this->find(url.toString(QUrl::FullyEncoded | QUrl::RemoveFragment));
}
bool CacheHandler::contains(const QString &url)
{
return this->page_cache.find(url) != this->page_cache.end();
}
bool CacheHandler::contains(const QUrl &url)
{
return this->contains(url.toString(QUrl::FullyEncoded | QUrl::RemoveFragment));
return this->page_cache.find(cleanUrl(url)) != this->page_cache.end();
}
int CacheHandler::size()

View File

@ -45,7 +45,9 @@ struct CachedPage
CachedPage(const QUrl &url, const QByteArray &body,
const MimeType &mime, const QDateTime &cached)
: url(url), body(body), mime(mime), scroll_pos(-1), time_cached(cached)
{}
{
this->url.setFragment("");
}
};
// Maybe unordered_map isn't the best type for this?
@ -67,12 +69,10 @@ public:
CacheMap const& getPages() const;
private:
std::shared_ptr<CachedPage> find(QString const &url);
bool contains(QString const & url);
void popOldest();
static QString cleanUrl(QUrl const & str);
private:
// In-memory cache storage.
CacheMap page_cache;

View File

@ -109,6 +109,10 @@ static void renderRecursive(RenderState & state, GumboNode const & node, int nes
bool process_header = false;
QString header_text;
// Fetch the original `id` attribute if any
char const * const header_id = getAttribute(element, "id");
QString const anchor = (header_id != nullptr) ? QString(header_id) : QString("header-%1").arg(state.header_count);
switch(element.tag) {
// Stripped tags
@ -173,7 +177,7 @@ static void renderRecursive(RenderState & state, GumboNode const & node, int nes
process_header = true;
state.header_text = &header_text;
}
stream += "<" + QString::fromUtf8(gumbo_normalized_tagname(element.tag)) + QString(" id=\"header-%1\">").arg(state.header_count);
stream += "<" + QString::fromUtf8(gumbo_normalized_tagname(element.tag)) + " id=\"" + anchor + "\">";
break;
default:
@ -192,7 +196,6 @@ static void renderRecursive(RenderState & state, GumboNode const & node, int nes
QRegularExpression regex { "\\s+", QRegularExpression::DotMatchesEverythingOption };
QString const header = header_text.replace(regex, " ");
QString const anchor = QString("header-%1").arg(state.header_count);
switch(element.tag) {
case GUMBO_TAG_H1: