The most simplest way to build it as a complete package is by running this script:
mkdir ~/game-collection
cd ~/game-collection
git clone https://github.com/andrehtissot/electron-game-collection.git
git clone https://github.com/andrehtissot/electron-game-collection-server.git
cd electron-game-collection
npm install
npm run build-release
And within ~/game-collection/out
, you shall find the directory with the binary ready.
Having more than a couple of computer games can get difficult to manage, specially when the collection is divided between many different stores.
There are many launchers out there, usually not multi-platform, helpful to manage installed or locally stored, but none focused on the online collection.
As the goal was ease the control of a big collection and having a computer was a giving, the interface was designed primarily for desktops.
As the app would focus on the online collection, there would be no problem on requiring it to be implemented multi-platform.
If any platform-specific feature would be considered, it would be available as an option. Ideally as a "plugin".
As a first draft of the interface, using Pencil, the three main screens were designed.
As the icon would be presented in many different sizes, a "public domain" (WTFPL) SVG icon was chosen, simple but clear. Later its color were changed. Original link
As of this point, the screen was mocked, an icon was chosen, and the requirements were loading from the web and being multi-platform. But what to use?
As today nothing is more reliable to continue to be supported than HTML, the easiest way to start, even if just to prototype, is a web page. To not start from zero, at the time, the Angular community was growing and the framework looked solid.
The simplicity intended and issues with performance, inspired me to look for alternatives.
Brought the performance I expected and presented nicely for the desktop look and feel.
Unfortunately the time cost of implementation, inspired me to look into its js-like variant, QML.
Easy to develop, easy componentize. Thread support unfortunately still on C++, but quite nice to work with.
But the hacks to overcome the configuration limitations of its graphical components started getting messy.
It is quite funny how little multi-platform desktop technologies have evolved in the last decade.
But, as chromium is everywhere, it's also shippable as a desktop app, with a mix of browser and node.
As this weird times we live in, that betting for web technologies works even for desktop development, the current state of frameworks and libraries where investigated again, and, to avoid the overhead, keep the simplicity and make use of the professional skills I already apply, ReactJS was chosen.
The debug tools offered by Redux made me chose it in the beginning. But as Context API got more attention, its simplicity and lesser boilerplate code convinced me.
The same simplicity made me convert, gradually, to stateless components and hooks.
Having the app as a SPA had the benefits of allowing me to test it against the newest chrome versions, giving a better performance and better debug tools.
But file access, for downloading a large number of files, would not be available within the browser. Plus having to work around Cross Origin Request issues made a clear case for a separation of a "frontend" and a "backend".
Which, when bundle into the electron package, would start a window as a browser and run the backend scripts with its embedded node, not requiring the user to install anything special, just running the standalone app.
For this project, only the chromium run-time mattered and the components were redone as many times as necessary until the performance expected was met. For that reason, instead of investing on traditional automated tests, it was chosen to have a strict set of typescript rules to avoid writing code prone to errors instead of trying to catch them.
The app, while not complete, does some in regards to communicate with the main store today, Steam.
And its edit settings, workarounded by exporting and importing CSVs.
This screen presents, in a grid, all the games in the database, with the overview image, if available, or the game title.
On the left top of the screen you can select one of the properties and if is sorted asc or desc.
The tile size is resizable and they respond to window width, avoiding wasting space.
The image bellow has it's tiles here pixelated to avoid copyright issues, as the game tiles images presented are not part of the software, hence not covered by its MIT license.
This screen presents in a table all the values of the enabled properties.
The properties presented can be enabled/disabled by clicking on the settings menu on the right top of the screen.
Clicking on the column header, the table is sorted by that property. If it is already sorted asc by the property, it will sort desc. Otherwise it'll sort asc.
For big texts, links or images, a simple modal is displayed.
In this screen, you can trigger the plugin-driven data enhancing per game or for all.
In this screen, you can import/export data as CSV files, enable/disable plugins and configure them.
The user's data is saved in the IndexedDB, which its storing made use Dexie for its convenience alone.
usePersistedState
was created as useState
hook, which automatically retrieves and stores the state.
As by design, this app had an open-ended feature list, having it all inside the main app would eventually get messy, and for most users, not necessary to be loaded.
As the plugins should interact with the interface, to change it, and to use the benefits of ReactJS, from the plugins, it could be given Components to be rendered.
The plugins would also be triggerable in the backend, to execute heavier tasks of manage files.
Some heavy tasks to manipulate data, like converting from and to CSVs to internal IndexedDB, where given to webworkers.
Standardized communication:
[operation: string, params: any[]] => [status: "SUCCESS" | "ERROR", payload: any]
"Abortable promises" for an easy async/await AND connections control.
Currently, the future of this project depends on the success of projects like GoG Galaxy 2.0.
In the case of lack of:
- Support for smaller stores like Humble Bundle, Origin, Twitch;
- Support for Linux;
- Modability; Or
- Uninteresting UI.
On app start, to avoid issues with the frontend-backend communication, the server ports should be chosen from available ones. As it now conflict with other app instances and may conflict with other apps.
In the mockups you can the block that should open below one, for overview screen, or more, for library screen. This component is yet implemented, and should be highly extendable with plugins.
It was implemented in older iterations, but removed due to component restructuring, and should be easily ported to this new version.
As of now, all the columns share equally the screen width, but were design to be more flexible than this, and with a little work, it would be manually resizable.
Currently only British English is supported.
Unfortunately, due to awful performance from toLocaleDateString
, a temporary Date to String formatter is used, but it should be configurable.
It is designed to be extendable, and more stores and or optional features would be supported.