Rewrite of Falkon plugin Readability to QML
This rewrite was a challenge as well as a good test subject for Falkon QMl API. I had to work around few pitfalls to make it work.
Click on button always opens popup
Desired or not the popup will always open. I used it to write there sone informative message, but it is unsued so far. In the future it an be used a bit more to dislay the debug message or a feedback from the script if the conversion fails.
The popup has to be there since without it the button would be without an icon, which is sad.
Communication between webpage JavaScript and the QML
This one is also a fannu one since there are multiple ways how I think this can be done. The communication is needed depending oo how and when the settings are modified and saved.
1. The Global settings can only be edited in preferences
This approach is interesting since it allows to set some defaults in plugin preferences which will be used all the time and any changes in configuration done on the webpage after activating Readability plugin is only for that single use and will be thrown away after the tab is closed or the Readability mode is exited.
2. Provide a “SAVE” button after clicking on the toolbal icon
After clicking on the toolbar button I could run a script to determine if Readability is running on the page and if it is I could try to fetch the current configuration and store it. If not detected the Readability will be executed as normal. Now at the time of writing I am not sure if the settings should be stored after clicking on the toolbar button or on the “Save configuration” button which would popup.
3. Change global configuration after each change on the page
This is the method I chose. It seems very intuitive and simple to use for the user (only from my limited understanding) since the change is interactive and user sees how Readability is configured at the moment. The downside is that QML API does not allow me to simply send these data the way how it was done before on C++ or Python version. In these older versions of this plugin the Readability script is executed in “Application world” which allows it access to the externalJjObject and this way can send data to the plugin code. The QML does not allow this at the moment, and the javascript executed is always in different js world (forgot the name, sorry). This is why I thought of using some obscure methods like I described before. The only way to make the communication running (allowing the JS on webpage to access the Falkon.external object created by QML) is to run the whole thing as UserScript which is executed probably on every single webpage. This is a huge waste, but it is a first working version in QML and sure, it can be improved.
As it can be seen, none of these options are great, but I decided to “ship” something instead of wasting years until it is “perfect”
Javascript code is weird
If yuu are JavaScript developer (a good one) you will notice that my skills in this language are very limited and I have no idea sometimes what I am doing since browsers these days are way too complex monsters.
Ensure that only current page is converted
Welcome to the train of action and reaction. Since I decided to use the
userscript way to inject the script to the page I have to ensure that
only the currently visible page will be converted and not all of them.
The older versions simply ran the JS code on a current window and
current tab which QML cannot do with desired JsWorld. So, I went with
userscript and some Qt signals. This approach causes it to send a signal
to every sinle instance of the userscrip in the browser and I am unable
(or I do not know) how to limit it in the QML code. Thus in the
JavaScript I added a simple condition which I found on the web (from web
documentation, this w3c thing, should be legit) called
document.hidden
. This should be FALSE if the tab is active. I only
tested it with one browser window and it did the job, I have no idea how
it works with multiple windows.
Loading assets in QML
According to my knowledge QML does not have a file read interface or any file manipulation things, this should all be handled in some additional C++ code. QML should be just a nice face and all heavy lifting is done in C++. And here we go, the old versions loaded the required assets (scripts, style and images) on the fly and put the final JS together after by itself. This solution is a crude one and wastes a lot of CU power in a long run, but is nice for a development.
The sad part is that Falkon QML API only supports loading text files and not images. This is a bit sad but also not a thing to worry about since the images can be converted to base64 format and added to style while the plugin is being packages. That is exactly what I have done this time. I still left the final gue operation for JS in QML code (it joins the scripts and styles together into one). This should also be done in the packagin process together with minifying the scripts to save a bit extra on user side.
Conclusion
Now that I think about it, I used Readabilty QML rewrite as a good excuse to learn a bit more about the current state of Falkon QMl API and how to work around it in my own way. Playing with mysteiour QML thing together with monster browser and little Makefile for packaging was fun. Later I might write another chapters of my Falkon QML tutorials since I learnt a lot these past few months.
PS: Yeah, it all sounds chaotic.
Enjoy, or scold me.
The extension can be found at Falkon store and code at my Gitea.