-
Started with a search engine (FlexSearch) to store tracks, and serialized JS lists for albums & artists.
Altough very performant (50s to index the whole music library), the memory footprint is heavy (700Mo) since
FlexSearch is loading entire indices in memory
-
Moved to sqlite3 denormalized tables (drawback: no streaming supported)
-
Dropped the idea to query tracks of a given albums/artists/genre/playlist by using SQL queries.
Sqlite has a very poor json support, compared to Postgres. There is only one way to query json field: json_extract
.
It is possible to create indexes on expressions, and this makes retrieving tracks of a given album very efficient:
create index track_album on tracks (trim(lower(json_extract(tags, '$.album'))))
select id, tags from tracks where trim(lower(json_extract(tags, '$.album'))) = lower('Le grand bleu')
However, it doesn't work on artists or genres, because they are modeled with arrays, and operator used do not leverage any index:
select id, tags from tracks where instr(lower(json_extract(tags, '$.artists')), 'eric serra')
select id, tags from tracks where json_extract(tags, '$.artists') like '%eric serra%'
-
chokidar is the best of breed watch tool, but has this annoying linux-only big when moving folders outside of the watched paths
Watchman is a C program that'll be hard to bundle.
node-watch does not send file event when removing/renaming folders
watchr API seems overly complex
watch-pack is using chokidar and the next version isn't ready
-
wiring jest, storybook, svelte and tailwind was really painfull. Too many configuration files now :(
To make storyshots working, I had to downgrade Jest because of an annoying bug (reference).
-
I considered Sapper for its nice conventional router, but given all the unsued feature (service workers, SSR) I chose a simpler router.
It is based on hash handling, as electron urls are using file:// protocol which makes it difficult to use with history-based routers.
-
Initially, albums & artists id where hash of their names. It was very convenient to keep a list of artist's albums just by storing album names in artist's linked
array. UI would infer ids by applying the same hash.
However, it is common to see albums with same name from different artists (like "Greatest hits").
To mitigate this issue, I had to make album's id out of album name and album artist (when defined). This ruined the hash convention, and I had to replace all "links" by proper references (id + name). Now UI does not infer ids anymore.
-
For system notifications, document.hidden and visibilityChange are too weak because they only notice when the app is minimized/restored
-
System notification was tricky: HTML5 Notification API doesn't support actions, except from service workers.
Using service workers was overkill, and didn't work in the end.
Electron's native notificaiton does not support actions either.
Using node-notifier was a viable possibility, but doesn't support actions in a portable fashion (notify-send on linux doesn't support it).
Finally back to HTML5 notification API, without actions :(
-
The discovery of mediaSession's metadata and handler was completely random. It's only supported by Chrome (hopefully for me!), and can be seen on Deezer, Spotify or Youtube Music. However, it does not display artworks.
-
IntersectionObserver does not call the intersection entry when the position inside viewport is changing but the intersection doesn't.
As a result, dropdown in the sheet will enter viewport during sheet animation, causing troubles positioning the menu
-
AC/DC was displayed as 2 different artists ('AC' and 'DC'). This is an issue with ID3 tags: version 2.3 uses /
as a separators for artists.
Overitting mp3 tags with 2.4 solved the issue
-
Snap packaging was hairy to figure out. It is clearly the best option on Linux, as it has great desktop integration (which AppImage lacks) and a renowed app store. However, getting the MediaMetadata to work with snap confinement took two days of try-and-fail research. The full journey is available in this PR on electron-builnder. Besides, the way snapd is creating different folders for each new version forced me to move artist albums outside of electron's data folders: snapd ensure that files are copied from old to new version, but can not update the media full paths store inside SQLite DB.
-
MacOS builder was constantly failing with the same error: 7zip couldn't find any file to compress in the final archive. It turns out it is because the production name as an accent (Mélodie), and the mac flavor of 7zip can not handle it...
-
Chokidar has a "limitation" and triggers for each renamed or moved file an 'unlink' and an 'add' event. The implication on Mélodie were high: moved/renamed files would disappear from playlists. Ty bypass the issue, Mélodie stores file inodes and buffer chokidar events: when a file is removed, Mélodie will wait 250ms more, and if another file is added with the same inode during that time, will consider it as a rename/move.
-
The mono-repo endeavour. My goal was to split code in various reusable packages: a UI and core that would not depend on Electron, and could be used in both Web and Desktop context, and two apps: an Electron-based desktop application and the Github-page site. As developer I would expect the ability to hoist as many modules
- runing jest with pnpm does not work at all.
- lerna is a pain when it comes to hoisting deps.
- svelte-jester and preprocess absolutely don't work with yarn@2
- yarn@1 works fine but brings very little commands (just a little more than npm@7)
- npm@7 < 7.24 must install peer deps in legacy mode and does not offer any sugar for multi-package commands. All deps must be manually added to package.json, because install command MUST be run at root level
Electron-builder does not like monorepo either: author, description and other metadata must be copied from root package.json to apps/desktop/package.json. The Electron version must be fixed because node_modules are hoisted. The package.json name MUST be
melodie
:(
Caveats: always run npm i --legacy-peer-deps
AT ROOT level. Running npm or npx command inside packages would re-create node_modules
Ensuring the same version in all packages and dependencies similarities must be done manually
-
svelte-spa-router, and its dependency on regexparam, has been bother me for a very long time. When ran with jest, svelte-spa-router files must be transpiled by Svelte compiler, but they import regexparam as esm, and this lib doesn't expose such binding. One must replace the import with require, and this must only be done during test, because rollup will handle it properly.
When receiving errors from svelte-jester, don't forget to clean jest cache with --cleanCache CLI option.
-
since v22.11.1, electron-builder fails to build the app on Github worker. Fixing the version to 22.10.5 for the time being.
-
Tailwind is veeeeeeeeeeeery slow to compile. Svelte preprocessor can not handle it fast, making vite pretty slow when starting atelier (only the first load). More information here. Moving to Windi CSS speed the build time from 65 to 28 seconds!
-
The Audio
element failed to play any music when coupled with AudioContext
:
- Bluetooth must be enabled prior to starting the app (simply reload the app once enabled)
AudioContext
will build, but will not process any data.
Being running or suspended (as per Google's policy) does not matter: rebuilding the context or building it on user interaction does not solve the issue as long as bluetooth is enabled