SàT progress note 2020-W01

goffi 05/01/2020, 22:07 jabber-xmpp-en SàT project libre SàT progress

Hello and Happy New Year, this is the first progress note of the year.

Last weeks have seen work on OMEMO, and SàT has now a full OMEMO implementation (one2one, files with aesgcm scheme, and MUC encryption). One2one e2e OMEMO encryption was already available since 0.7, and I've talked about file encryption last time. The work on MUC has been quite straightforward, it was basically about handling the workflow differently (checking that we have a room JID and not a user JID, checking that we can retrieve real JIDs from Room, and retrieving room occupant JIDs). On Cagou, I've added the encryption button, and I've had to filter encryption algorithms available for MUC (where OTR is excluded, while it's available for one2one chat).

Once trying on Android, I've realised that OMEMO was not working as expected. After investigation I've found the issues (bad version and the Protobuf Python binding was not installed correctly), and I've proposed 2 small fixes to python-for-android's omemo and protobuff_cpp recipes, which are now merged upstream.

Once that working, I've decided to work a bit on Cagou usability. On Android, there is now a notification sound in addition to the vibration (you can activate/deactivate them in settings).

I've refactored the way platform specific behaviours are handled, and this is used, among other things, to manage URIs opening. Thanks to that, I can now handle the geo: URI scheme in a platform specific way: while by default it's opened in browser, on Android it's opening the application picking menu, so you can display the location in your map/navigation application.
That's pretty neat as you can now, using a map/navigation application + Android data sharing mechanism, send or get a location with SàT (and this may be end to end encrypted).

Continuing with Cagou UX improvements, I've added a small red "plug" icon when the user is not connected to the server. I was not sure how I can show that a user is disconnected without surcharging the interface, and I've found this solution acceptable (the icon is visible only when you're disconnected).

Now I'm working on chat room selection, i.e. how to open a chat room in Cagou.


edhelas 06/01/2020, 07:08

SàT progress note 2019-W51

goffi 20/12/2019, 18:43 jabber-xmpp-en SàT project libre SàT progress

Hello everybody,

it's time for an update on last weeks work.
As announced last time, the infinite scroll is now implemented in Cagou. It was a real usability issue to not be able to go back in history, so I'm quite happy to have it now.

Finding the right way and the right parameters to have smooth infinite scroll was not trivial: user can scroll quickly to the top, the scroll effect may still be running after use interaction (if you scroll with finger and let the screen, the scroll bar will have a inertia effect and continue to move for a little while), and you don't want that your history "jump" all of a sudden because new messages have been added.
By default, a "bump" effect is shown when you reach beginning or end of scrolling zone, which I've finally removed as it doesn't make much sense with infinite scroll.

The result is quite OK on desktop, but I have a bug on Android which make the scroll bar go to the bottom when new messages are prepended. I'll check that later.

I've also adjusted the delayed resizing for chat history (cf last note) to avoid an unpleasant flickering when a new message is sent/received.

To stay with Kivy, they have an infrastructure for community extensions called "garden", and they used to have a non standard home-made package management for that. That was really annoying for installation (Cagou is using 2 garden "flowers"), and fortunately they changed the infrastructure recently to use Python standard package manager (pip). The 2 "flowers" I'm using were not moved to the new architecture, so I did it following the online guide, with the help of Kivy team. Kivy team is really nice, helpful, and usually answering quickly; that's really important when you want to contribute.
To summarize, the 2 Kivy community extensions used by SàT are now installable like any other Python dependency, via pip/PyPI, that makes Cagou simpler to install.

The rest has been mostly about e2e encryption with OMEMO. I've updated the plugin which was not working anymore since Python 3, and updated version of python-omemo. The author of this lib, Syndace, is also really friendly and reactive, and he's on SàT room, that makes it handy to coordinate our code bases. Thanks to that we have discussed the possibility to reset trust for a device to undecided (the default state when a new device is seen), and he added the required method.

I've also fixed trust management in SàT, to handle correctly undecided and untrusted devices.

Last but not least I've implemented AES GCM encryption (the aesgcm:// scheme that you may have seen in URL with other clients), also known as OMEMO Media Sharing even if it's not directly related to OMEMO. This is not an official standard (it was proposed but rejected by XSF Council, for good reasons), but that's the only way we have at the moment to encrypt a file with OMEMO, so it's a must-have for now.

This was the occasion to use for the first time the async/await syntax in the backend. There was already a coroutine syntax in Twisted that SàT is using for years (inlineCallbacks), but the new syntax is part of Python language, is more pleasant to use, and allows some welcomed simplifications.
Thanks to the great work of Twisted team, it's super easy to mix Twisted Deferred, inlineCallbacks, and async/await code, so I can migrate the code progressively.

With that, SàT has now a complete OMEMO implementation for one2one chat. Group chat is not yet done, but I expect to do it quickly.

As usual, those features are usable from command-line with jp. You can upload a file and encrypt it with AES GCM with:

jp file upload -P --encrypt some_file.ext

(the-P is to have a progress bar)

This will give you an aesgcm:// URL

And to download from the other end:

jp file get -P "aesgcm://…"

The doc has been updated and can be seen at https://salut-a-toi.org/documentation/sat


edhelas 20/12/2019, 21:04

debacle 21/12/2019, 18:58

SàT progress note 2019-W48

goffi 28/11/2019, 21:43 jabber-xmpp-en SàT project libre SàT progress

It's time for a new progress note.

In last one I was talking about my attempt to optimize the chat history with Cagou on Android. Indeed, while scrolling through history is smooth on desktop, it's quite slow on Android (but not dramatic).

My plan was to use RecycleView, which is an optimized widget to show a big list of widgets.

But, as I've explained last time, RecycleView has troubles with widgets with dynamic height (which is the case for chat messages, height depends of content). While working on a workaround (the idea was to pre-render each widget without displaying them, and use the calculated size), I've realized that even RecycleView was not so smooth on Android, and that was complicating a lot the code.

So I took the (hard) decision to abandon this idea, it was taking too much time without perspective of good results. Sometimes it's a good thing to step back and save time for other things.

Instead, I've simplified a bit other parts of the code, and thanks to a blog post on Kivy website that I've read recently, I've used the idea of a delayed resize (the message history is complex to resize because there are many elements – messages with styling, images, avatars, nickname, timestamp, receipt flags, etc. –), meaning that when you resize the window or the messages widgets, the resize is not done immediately, but only after a short delay (replacing any previously delayed resize). This way you limit the number of size calculations, and the feeling is better.

Still there is room to improve perfs for chat history scrolling on Android, but that can wait, it's usable enough for now.

I've come across a ticket for python-for-android predicting a hard future on Android: background tasks are more and more difficult to run. I'm not sure how it will evolve and what will be the consequences for SàT, we'll see.

Still on the Kivy side, I've realized that a bug that I had on Android (issue when sliding chat widget with the Carousel) was fixed in dev version. As I have no idea when next version of Kivy will be released and I had to fix this issue immediately, I've done a backport of the dev version of Carousel in Cagou, which I'll remove as soon as the Kivy 2.0 is available.

I've moved to Python 3.8, and I've had to face a couple of troubles.

Twisted, which is a major component of the backend, is not yet Python 3.8 compatible. Fortunately, the issue and fix were easy, so I've reported the issue and proposed a fix.

It is not super pleasant to propose a fix to Twisted because you have to look into the doc (which is rather indigestible), create the ticket on their bugtracker – with a terrible UI – but with a Github account (I have one for contributions only, but I'm don't like to be forced to have it), do the fix, write a test – with a not so pleasant "Believe me, if you write your tests after you write your code, we will know. It's more obvious than you think." making you feel like a little pupil at school –, write a piece of text to generate the changelog automatically, and finally update the ticket to ask for review (then we'll follow usual change request/review until the patch get merged, rejected or abandoned).

On the bright side, the Twisted community is nice, and I have to admit that the code quality of Twisted is really good thanks to their test-driven development (and general competence of people working on it). I'm using Twisted since the beginning of SàT (without any regret so far), and I really love the stability of its API, and that I'm rarely crossing the way of a blocking bug. I just have the feeling that it could be more contributors friendly.

For the same reason as for Kivy, I've backported the patch to sat_tmp to be able to use SàT and SàT PubSub with Python 3.8.

Now I'm working on infinite scroll on Cagou. It is functional but not yet smooth.

That's all for this progress note, as usual feedbacks are welcome.

debacle 29/11/2019, 16:48

SàT progress note 2019-W44

goffi 03/11/2019, 20:24 jabber-xmpp-en SàT project libre SàT progress


once again I've skipped last week progress note, as there was not much to say and I don't think it worth writing something just to write something, so in the future I'll publish a note every week when it worth it, and may skip one or 2 weeks in case of low activity or if I'm continuing a long task.

During the last 2 weeks I've been focusing on Cagou on Android. The 0.7 version is a proof of concept and give a idea of the potential, but it's not good enough to use as a daily client; I'll try to fix this for 0.8 version.

Cagou is now windowed on Android and not fullscreen by default anymore. It was initially fullscreen to gain some space, but at the end it's not a good idea as it hides many useful informations from the user. I still plan to add a fullscreen mode in some cases (when seeing photo albums for instance).

I've added Cagou to the share menu of Android, so it can now be used to share any content, be it some text data, or an image/file. That's one of the important things which was missing, and it's pretty cool to see it when sharing something on the phone.

When possible, a preview of the data is shown (works only for text or images at the moment), and then you just have to touch the name of the contact to who the file/data to. Below is screenshot of image sharing.

screenshot of share widget first draft

The share widget is not polished yet, it's a first draft. I've tried to keep the design simple, and the option to resize the image is only shown if the image is too big, in which case it is activated by default.
It will be possible to use the same widget on desktop, I just need to do the integration with the various APIs.

I'm now working on improving the performances for chat history. So far, all the messages were put in a BoxLayout. It's working, but it keeps all widgets in memory and this is now optimized for something which may become big like a chat history. On desktop this it is fine, but on Android it is quite noticeable that scrolling the chat history is slow.

A recent Kivy widget is usable to improve that: RecycleView. This RecycleView only calculates what is necessary to show the widgets actually displayed on the screen, this is far more efficient and we can expect a good performance boost by using that. So I've started to move the history to RecycleView, but I've run into problems for which I've created Kivy issues (#6580 and #6582). I expect that it will takes some time before those tickets are handled and fixed, I'm trying to work around those problems for now.

I have some test code but it's not fine yet. Once that done, I'll implement the loading of more history when we are at the top of the chat (either with an infinite scroll or a button).

There are a couple of other improvements that I would like to do before releasing 0.8 to make Cagou good to use on Android, but let's talk about them in a future progress note.

Last but not least, jnanar, the maintainer of SàT packages on Arch Linux, has just say that the dev versions of SàT and Cagou (the new Python 3 version) are now working (but not Libervia yet), and that tests/feebacks are welcome. Thanks to him for maintaining those packages!


errormovim 16/11/2019, 16:09

SàT progress note 2019-W42

goffi 20/10/2019, 15:36 jabber-xmpp-en SàT project libre SàT progress


a short progress note this week, I've mainly been working on building the Cagou Android apk with Python 3, so I've did the last bit of Python 3 porting. The port went well, thanks to the great tools done by the python-for-android, and I could remove some Android specific hacks. More important, there was a nasty bugs with Python 2 on the open method which is gone, and some crashes disappeared (notably when changing orientation). Cagou is considerably more stable on Android.

I'm now working on usability, as there are a couple of small things missing which make the overall experience painful.

I need to add a way to go back in history in chat widgets (I'm not sure yet if I'll go with an infinite scroll or if I'll add a button for a user action), and a summary widget with last active chats would be nice. I'm also looking to add Cagou in the share menu (it would be nice to do that on desktop too). Also the back button should have better behaviour, and go up to a home widget (either the future summary widget, or the widgets selector).

The welcome screen (where we select a profile/create an account) is not user friendly yet, I'm not sure if I'll work on this this week, but it's on my short term TODO list.

So I'm working on Cagou and Android at the moment. I have also some stuff planned for Libervia, we'll see next week how it went.


edhelas 20/10/2019, 15:40

debacle 20/10/2019, 21:57


errormovim 16/11/2019, 16:09

SàT progress note 2019-W41

goffi 10/10/2019, 12:05 jabber-xmpp-en SàT project libre SàT progress

Hi everybody,

I've skipped the progress notes for a couples of weeks because I've been working on the same thing for a long time (writing documentation for jp + porting it to asyncio), it was making no sense to repeat this every week, and also because I've been seriously lacking time lastly due to events in my private life.

This week I've had absolutely no time to work on SàT, I could only update the instance running https://www.goffi.org and https://salut-a-toi.org to the dev version (i.e. on Python 3). One visible change is the performance boost when using tickets: retrieving tickets and building the page was previously taking ages, and the issue has been found and fixed.

Let's summarize some of the changes I've done while being silent on the blog:

  • jp, The CLI frontend of SàT is now fully documented. That means that all the commands (107 commands so far!) are explained with examples; you can check the rendered doc at https://salut-a-toi.org/documentation. This was the most time consuming task during the last weeks, really boring to do, but necessary. I hope it will help people to use the full potential of this tool.

  • also jp is now using asyncio, and some issues preventing to use an other bridge than D-Bus have been fixed. In other words, you can now use a bridge like pb (Twisted's Perspective Broker) instead of dbus. This has been requested by people using jp on servers where installing D-Bus was not desired, pb being natively supported by Twisted and then SàT, it's working without any extra dependencies (but D-Bus is still the default and recommanded bridge in most cases).

  • Many more or less small improvments have been done to jp and SàT during this process. Some commands options have been updated.

  • There are now 2 themes for jp, for light or dark background. You can specify the background using background option in [jp] section of sat.conf. Before that, jp was barely readable on light background. I still need to do something similar for Primitivus.

  • If not specified, jp will automatically detect the background colour of the terminal where it runs. I've discovered that it was possible to do that thanks to a ticket I've randomly found reported for vim and neovim: there is an ANSI escape code returning the RGB value of background colour on compatible terminal, this is really useful.

  • A long awaited feature: jp is now prompting for profile password if it is needed and not specified in arguments. This is better for security as the password is not visible anymore on the screen, in your shell history, or in your processes lists.

  • Thanks to TLS fixes in latest Twisted version (19.7.0), I could remove the code working around the issues. Twisted required minimal version is now 19.7.0.

  • last but not least, I've fixed an issues during launch of SàT backend, Libervia, and SàT Pubsub which could result in ReactorAlreadyInstalledError when they were all installed in the same Python environment.

That's it. With the new documentation and some usability fixes like background detection, I think jp is now very usable, and I hope people will give it a try. It's a tool particularly useful when working a lot in terminal (to send or upload a file for instance), or if you want to do scripting with XMPP. XMPP server admins could use it to, for instance, send service messages using ad-hoc command (see examples in documentation), and XMPP dev could use it to inspect PubSub services.

There are several options for next big features in SàT, I'm currently thinking about implementing video calls as I need it, but I may well also work on other tasks first (like improving file sharing).

debacle 10/10/2019, 14:03


errormovim 14/10/2019, 21:04

SàT progress note 2019-W35

goffi 30/08/2019, 10:13 jabber-xmpp-en SàT project libre SàT progress

Hi everybody,

I've skipped last week note because I could not find the time, and anyway I did the same thing as this week, so it was not really needed.

I'm currently working on porting jp (the CLI frontend) to Python's asyncio, and at the same time I'm documenting every command (I need to review them one by one, so it's a good occasion for that). It's long and really boring, but it's a good thing to do.

Let me explain why I'm doing that. SàT and its frontends are historically using D-Bus to communicate (it's an IPC, and we call it internally the bridge). SàT is 10 years old, and the Python implementation that we have used was the reference at the time : Python D-Bus. This implementation has flaws, that they recognise themselves (like trying to guess signature, see " Problems and alternatives " in the page linked). Furthermore, it's the main reason why we use GLib and its loop in SàT, which can cause trouble to install (mainly due to compilation).

Frontends and bridges are using a callbacks mechanism, which can be hard to code and maintain in some cases. Python-dbus can work with callbacks or in a blocking way, and historically we have used this feature in jp. For instance, to get backend version we have a getVersion() method, and to avoid too much callbacks hell, it was used with the bridge in a blocking way (blocking jp is not such a big deal as there is no UI to maintain or things which must run in background). This was wrong and experience shows why, you are either blocking or asynchronous, not a mix. Using D-Bus bridge in a blocking way, even if it's only in a few places, makes the code unusable with other bridges, so jp could only work with D-Bus, and today we have other ones (like Twisted Perspective Broker which is the bridge used on Android).

So in one hand we had the callback issue, and on the other hand some bridge calls using blocking mode to limit callbacks hell, and causing design issues.

The proper solution to that is to use coroutines, which is a way to write asynchronous code nearly like we write blocking code. Twisted has been offering this possibility for years thanks to the inlineCallbacks which is using Python generators in a smart way. It's really usable and indeed used in many parts of the backend: you basically have to use a decorator and yield syntax.
This could have been used in jp but this would have forced the use of Twisted (and we want jp to work with other frameworks if other bridges are used). Furthermore, inlineCallbacks are not easy to debug: in a debugger if you don't add a breakpoint just after the yield, a step over brings you in the execution workflow of the main loop.

And here come asyncio and the great async/await syntax. This syntax is doing basically the same thing as Twisted inlineCallbacks, but in a cleaner and more readable way, in locations where yield is not possible (in a loop for instance), and it is nowadays well handled by debuggers (at least pudb that I'm using). Thanks to that, it is possible to convert easily blocking parts of the code, and to simplify many things.

Doing something like repeating a method on several pages of result (when RSM is used for instance) becomes easy and pleasant. One of the main goal of asyncio was to have a common loop/framework for all asynchronous code, and Twisted made the compatibility layer so we can use Twisted and asyncio at the same time with async/await syntax.

I'm currently finishing that, for the moment I'm keeping 2 versions of the bridge (one callbacks based and one using async/await) to progressively do the conversion, but the goal is to have all frontends using the new syntax soon. It is one of the many things that has been unlocked by the port to Python 3. It's taking lot of time because of the documentation made at the same time, but it is definitely worth it.

That's all for this note, see you next week.


errormovim 07/10/2019, 22:43

SàT progress note 2019-W33

goffi 18/08/2019, 19:22 jabber-xmpp-en SàT project libre SàT progress

Hi there,

after the release I've got some vacations and I've made a break, that's why I've skipped the last few weeks progress notes, but now I'm back.

The release was a big thing, after 3 years of developments, and many new exiting stuff to show (Cagou, which is also running on Android, the advanced file sharing, photo albums, events, etc.), it is also the first "general audience" version, meaning that it's the first one which is usable for everybody, not only people with technical background. Even if there is still work to do on UX and stability, we're on the right track.

The Android version of Cagou is not stable yet, but there are several things which were not fixable easily under Python 2 (there is notably a bug on file opening with Python for Android which is not reproducible on Python 3). I hope to have feedbacks to make next version really enjoyable.

I was really happy to finally do this release, and now I can move forward and in particular do the Python 3 port.

During my holidays I've spend some time doing the first steps of the port (just a few hours here and there), and I could quite quickly get the backend and frontends running. Once back, this week, I've reviewed it and done some polishing before committing, and I'm happy to say that the development version of the backend and all the frontends now run on Python 3. Some features are still not working, but most things are here and running.

This unlock many things, and I'm very looking forward to used them : asyncio with async/await syntax, Brython, Transcrypt, and many libraries which are Python 3 only.

Thanks to better error handling, I could also already fix some issues not seen with Python 2, and we can already appreciate a performance boost (specially visible with tickets).

Once that done, I've released SàT Pubsub 0.3.0 (a release note will come soon about this), and started the developments of 0.4.0 with… Python 3 port : dev version of SàT Pubsub is now also running on Python 3. That means that all SàT ecosystem is now Python 3 only.

Beside that, I've also made 3 pull requests to see Cagou, Primitivus and jp on Flathub, but there are some modifications to do there before they can be merged.

That's all, see you next week.


errormovim 07/10/2019, 22:43

SàT progress note 2019-W28

goffi 14/07/2019, 13:21 jabber-xmpp-en SàT project libre SàT progress


remember last week when I was mentioning external things that I've put on hold? There was a Twisted ticket that I've opened months ago, I've made a pull request for that, but there was still some changes to do according to review.

Unfortunately, between my paid job, work on SàT, and real life things I haven't had the time to update it, and little after sending my last week note, I've got an email notification about the ticket being fixed (with a patch replacing mine). I was feeling a bit bad to let this for months and not finding the time to update it myself (in 8 months). Fortunately Twisted folks are nice and understand well ("No need to apologize. We're all volunteers here :)"), and it's a good thing that they managed to fix this issue.

I'm telling this because people don't always understand why things take time (why the release it taking so long? Why nobody did review my merge request?), or may be forgotten. It's just that people can be really really busy, and in free software communities, many of them work on their free time.

During this week, again, it was debugging: really useful for the project, but not so much to tell or explain. The blocker list is getting really low, and I feel fairly optimistic that release can be done next week.

There is maybe one issue I've come through that may worth a mention : while the new chat page of Libervia was working fine during my tests on localhost, it was not working at all once deployed. This is a really simple chat for now, just a proof of concept before adding advanced feature in next version. Libervia pages which come with the new web framework are currently mostly static (i.e. there is no advanced javascript to handle complex changes, this will come in next version), and the chat works by establishing a websocket with the pages, and just sending new messages to display. The web framework is supposed to make life of developer easier, and you only have to declare a dynamic = True variable to activate the websocket. In the background, Libervia create the websocket, associate the page with it, and also the request which is an object containing many useful data, including the session with the profile of the user.

While investigating, I've realised that the issue was happening only in HTTPS, so it was not visible while working on http://localhost. Happily, I'm now working mostly in HTTPS even during local development, this make the detection of this kind of issues easier. I've been using mkcert which makes the process of adding personal certificate painless, and thanks to it I can work easily in HTTPS on my own private and local domain.

This led to an issue with the request object I was storing. This Twisted object is not made to be stored this way, but I was doing it to keep the useful data it contains. Once the HTTP GET request used to retrieve the chat page is finished, the channel is closed, and it is used to test if the request is secure or not (the Twisted session is not stored in the same object or using the same cookie if the request is secured or not). As a result I was getting an empty session, like if the user was not connected, and the chat could not work. I could easily work around this issue, and I've reworked this in a cleaner way; it's working fine now.

The release is not totally ready yet, but I'm already thinking about what's coming next (beside Python 3 port), and there are several big options in my mind, it will be important to choose carefully the priorities. I'll probably focus soon on user experience (UX), as current UI (specially for Cagou), is not that intuitive and accessible for newcomers. I'll write more about this for the release note (which may replace next week progress note).

debacle 15/07/2019, 17:01


errormovim 14/10/2019, 21:06

SàT progress note 2019-W27

goffi 05/07/2019, 10:16 jabber-xmpp-en SàT project libre SàT progress


this week note will be short, first because I've mainly fixed bugs, second because I've pain in my wrist and it's not comfortable to write.

The most visible part of this week work is the addition of some installation instructions on the front page of https://salut-a-toi.org, which render like this:

capture of installation icons from https://salut-a-toi.org

(this is a screenshot, this image is not clickage, check https://salut-a-toi.org to see the real clickable version)

Thanks to the work explained in previous notes, we're getting closer to an easy installation in a few clicks. We're not exactly there yet though, as Flatpak still needs to be installed in most distributions (I think, I don't know exactly where it's installed by default), Libervia (web frontend) is not installed this way (but I'll update the Docker image at some point which is also easy to install/run), and there are maybe other tweaks to do (for instance on Android you must activate the installation from external sources). Please note than when SàT is available natively in the distribution, it's the recommended way to install it.

Also the many ways to install + different frontends/versions (and I've not put yet Libervia + packages for others platforms like Windows or Mac OS) may be confusing. Maybe a platform detection could help to highlight the most probable package in the future.

Another thing which can cause trouble with SàT specific architecture is the backend: for Flatpak I've made a wrapper to launch it automatically if it's not already, otherwise the running backend is used. It works but there is a risk of troubles when the package will be updated and the running backend version may be older than the expected one. I'll have to modify the backend to check that at some point (probably in 0.8).

An other necessary improvement for 0.8 will be the login screen: for now it's really confusing for somebody not used to XMPP (you have to create a profile with a jid and a password, then click on it, then you land to widget selector). I have several ideas on how to change that, but I'll work on it only after release and python 3 port.

That's all for this week note, as I've said in the first paragraph I've mainly done debugging which is not really interesting to explain here. I'm a bit annoyed to lack the time to do more, as I've put aside some external things that I need to finish: I have 2 XEPs to update, and a pull request for Twisted that I've opened months ago and I need to update too. I haven't had much time either to follow standard mailing list, which is a pity because some really interesting things are happening there like the long awaited full stanza encryption.

I hope to be able to fix enough bugs in the incoming week to finally release the 0.7, I'm looking forward for it, and I'm sorry that the release will happen during the summer when many people will be on holidays (well I'm happy for people being on holidays, it's just that it's not the best time to have the release being noticed).


edhelas 05/07/2019, 10:26