-
-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce Table of Content Without Intense JS Invasion #1237
base: main
Are you sure you want to change the base?
Conversation
Bug report - when the TOC is not empty the attempt to open the TOC sidebar results in the latter growing wider and wider indefinitely. |
@veloman-yunkan I can't seem to replicate this. Is this happening on any zim? |
fe978e1
to
331855e
Compare
It happens on ray_charles.zim for sure |
Screencast.from.11-07-2024.08.22.37.PM.webm |
@veloman-yunkan Would like to confirm if you are on Qt6? I have tested Qt5 and Qt6, where Qt6 seems to be the version that this bug happens |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is the initial feedback from a quick and very superficial review
QWebEngineScript getScript(QString filename, | ||
QWebEngineScript::InjectionPoint point = QWebEngineScript::DocumentReady) | ||
{ | ||
QWebEngineScript script; | ||
script.setInjectionPoint(point); | ||
script.setWorldId(QWebEngineScript::UserWorld); | ||
|
||
QFile scriptFile(filename); | ||
scriptFile.open(QIODevice::ReadOnly); | ||
script.setSourceCode(scriptFile.readAll()); | ||
return script; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hide in unnamed namespace
src/webview.cpp
Outdated
connect(tabbar, &TabBar::currentTitleChanged, this, | ||
[=](){ | ||
const auto tableObject = m_tableOfContent.object(); | ||
const auto currentUrl = url().url(QUrl::RemoveFragment); | ||
const auto tableValid = tableObject["url"].toString() == currentUrl; | ||
|
||
/* When table invalid, then we are loading and the emit will be | ||
handled by KiwixWebChannelObject::tableOfContentChanged. | ||
*/ | ||
if (tabbar->currentWebView() == this && tableValid) | ||
emit tableOfContentChanged(m_tableOfContent); | ||
}); | ||
connect(kiwixChannelObj, &KiwixWebChannelObject::tableOfContentChanged, this, | ||
[=](const QString& tableJson){ | ||
m_tableOfContent = QJsonDocument::fromJson(tableJson.toUtf8()); | ||
if (tabbar->currentWebView() == this) | ||
emit tableOfContentChanged(m_tableOfContent); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better use named slots instead of anonymous lambdas
function recurseChild(elem, recurseData) | ||
{ | ||
if (elem !== "undefined") | ||
{ | ||
if(elem.nodeName.match(/^H\d+$/) && elem.textContent) | ||
{ | ||
var headerText = elem.textContent.trim(); | ||
var prevLevel = recurseData.level; | ||
var level = elem.nodeName.substr(1); | ||
var anchor = "kiwix-toc-" + recurseData.count; | ||
var anchorLink = window.location.href.replace(location.hash,"") + '#' + anchor; | ||
recurseData.count += 1; | ||
|
||
var anchorElem = document.createElement("a"); | ||
anchorElem.id = anchor; | ||
|
||
/* Wrap header content with something we can reference. */ | ||
elem.insertAdjacentElement("afterbegin", anchorElem); | ||
|
||
if (level < prevLevel) | ||
{ | ||
/* Complete current element and the parent element.*/ | ||
recurseData.toc += ']}]}, '; | ||
} | ||
else if (level == prevLevel) | ||
{ | ||
/* Complete current element*/ | ||
recurseData.toc += ']}, '; | ||
} | ||
|
||
recurseData.level = parseInt(level); | ||
recurseData.levelSet.add(parseInt(level)); | ||
recurseData.toc += '{"text" : "' + headerText.replace(/"/g, '\\"') + '", "anchor": "' + anchorLink + '", ' + '"child" : ['; | ||
} | ||
|
||
var c = elem.children; | ||
for (var i = 0; i < c.length; i++) | ||
recurseChild(c[i], recurseData); | ||
} | ||
} | ||
|
||
function tocJSON() | ||
{ | ||
/* level used to track current header level. | ||
toc used to store constructed list. | ||
count used to uniquely identify each list item in toc. | ||
levelSet used to retrieve the levels disregarding header level value. | ||
*/ | ||
var recurseData = { level: 0, toc: '{ "url" : "' + window.location.href.replace(location.hash,"") + '", "table" : [', count: 0, levelSet: new Set}; | ||
recurseChild(document.body, recurseData); | ||
|
||
var levelArray = Array.from(recurseData.levelSet).sort(); | ||
levelArray.sort(function(a, b){return a - b}); | ||
var level = levelArray.indexOf(recurseData.level) + 1; | ||
|
||
/* End un-closed lists */ | ||
if (level) | ||
recurseData.toc += (new Array(level + 1)).join(']}'); | ||
recurseData.toc += ']}'; | ||
return recurseData.toc; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that instead of constructing the final JSON string it is better to construct a recursive JS object and then call JSON.stringify()
on it.
var prevLevel = recurseData.level; | ||
var level = elem.nodeName.substr(1); | ||
var anchor = "kiwix-toc-" + recurseData.count; | ||
var anchorLink = window.location.href.replace(location.hash,"") + '#' + anchor; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that it doesn't make sense to include the full URL with every link. The URL of the page can be provided only once at the root level of the returned JSON object while each TOC entry will include only the anchor.
resources/js/tableofcontent.js
Outdated
kiwixObj.navigationRequested.connect(function(anchor) { | ||
var anchorIndex = anchor.lastIndexOf('#'); | ||
var anchorPageUrl = anchor.substr(0, anchorIndex); | ||
if (window.location.href.replace(location.hash,"") === anchorPageUrl) | ||
window.location.href = anchor; | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is about the full commit - can you elaborate on the scenario that is problematic if the navigation is implemented in C++? Is your solution fully devoid of similar problems or they are just made less embarrassing for the UX?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I thought I replaced this commit already... I previously forgot the setUrl method and was using this method. Another victim from rebasing.
No, I am a qtsaur. I don't use the most recent version. |
Is this assessment based on your understanding of the implementation or a result of some measurement? |
@veloman-yunkan It is more like my own understanding and observation from other Stackoverflowers:
|
331855e
to
388441f
Compare
@veloman-yunkan Should be fixed now. Somehow under the same settings, QListWidget in ReadingListBar doesn't have this problem. This might be due to either styling or underlying widget differences. |
Setup for TOC Javascript/CSS Injection
Add channel to communicate between web page and Qt
Re-enabled ToggleTOCAction to display the bar.
Only one should be in checked state.
Signal emits the collected header JSON. Parsing delegated to JS due to better DOM manipulations.
Recursively load the header JSON.
Upon signaling, use JS to navigate, as helps avoid wrong url setting given the asynchronism.
Elided item text is expanded here.
388441f
to
6d4aca1
Compare
Alternative to #1201. FIx #42
Changes:
Benefits:
Loses: