With the changing of the package used for getting the metadata of tracks, I wonder if we could reduce the time it takes for saving. The idea I've came up with was to do a "sparse save" of the tracks, saving only the minimum amount of data needed for a Track as getting the list of tracks on your device is pretty fast. We then get & save the metadata of the track in the background. Although it did cut down the time by a decent chunk, it led to the laggy UI issue seen in the past when we tried saving artwork in the background, but worse.
Since this logic will only happen when the app discovers new tracks, I decided it would be fine to have this process take a while as it's a "setup process" in a sense. With the new strategy, we implemented an idea of "batching", in which, we decided to integrate with the original logic. This actually fixes an issue with the original logic, in which, it was an all-or-nothing strategy in which we save all the tracks in one go. If the app crashed during this process, essentially, the user will never get in the app as the app might crash in the same place in successive runs.
Compared to other apps, we're much slower in the set-up process. This is probably due to basically going through an abstraction layer (as we're not writing our app in the native language such as Kotlin). In addition, we're a bit limited in the libraries we can use (a different music app got all the metadata of the tracks on my device basically immediately - they were using the taglib C++ library).
To improved the experience while on the loading screen, I've added some progress indicator to help the user understand that the app is actually doing something. In addition, we also added a modal after we get pass the loading screen to tell the user how we save artwork for the tracks as some were thinking the app was broken due to the track artwork not being visible.
Some other things changed/fixed:
Ignore some errors that could be reported to Sentry.
Fixed ESLint config for Drizzle plugin as it was treating .delete() on sets as a Drizzle query.
Renamed FileNode table variable to fileNodes from fileNode (for consistency).
Fixed createAlbum() "upsert" logic.
Fixed clearAllQueries() as we used the wrong query key since it was changed when we used _queryKeys.ts for the "Settings" feature.
Add documentation on how we save tracks.
[!IMPORTANT]
It seems that the generation of the file tree for the "Folder" feature is becoming a bottleneck, so I'm probably going to fix that next.
How
With users with large amount of media, there's a chance where the app might crash as we overloaded the app with promises (when we do a Promise.all() with more than 500 promises, we get the following warning: WARN Excessive number of pending callbacks). To counter-act this, we implemented batching (ie: passing fewer promises into Promise.all(), but getting through all of them via a for-loop).
Test Plan
Mainly, we're making sure that we don't emit the WARN Excessive number of pending callbacks, display informative information about the current saving status on the loading screen, and render the explanation modal when we open the app for the first time
Checklist
[x] Documentation is up to date to reflect these changes (ie: CHANGELOG.md & README.md).
[ ] Add new dependencies into THIRD_PARTY.md.
[x] This diff will work correctly for pnpm android:prod.
Why
With the changing of the package used for getting the metadata of tracks, I wonder if we could reduce the time it takes for saving. The idea I've came up with was to do a "sparse save" of the tracks, saving only the minimum amount of data needed for a
Track
as getting the list of tracks on your device is pretty fast. We then get & save the metadata of the track in the background. Although it did cut down the time by a decent chunk, it led to the laggy UI issue seen in the past when we tried saving artwork in the background, but worse.Since this logic will only happen when the app discovers new tracks, I decided it would be fine to have this process take a while as it's a "setup process" in a sense. With the new strategy, we implemented an idea of "batching", in which, we decided to integrate with the original logic. This actually fixes an issue with the original logic, in which, it was an all-or-nothing strategy in which we save all the tracks in one go. If the app crashed during this process, essentially, the user will never get in the app as the app might crash in the same place in successive runs.
taglib
C++ library).To improved the experience while on the loading screen, I've added some progress indicator to help the user understand that the app is actually doing something. In addition, we also added a modal after we get pass the loading screen to tell the user how we save artwork for the tracks as some were thinking the app was broken due to the track artwork not being visible.
Some other things changed/fixed:
.delete()
on sets as a Drizzle query.FileNode
table variable tofileNodes
fromfileNode
(for consistency).createAlbum()
"upsert" logic.clearAllQueries()
as we used the wrong query key since it was changed when we used_queryKeys.ts
for the "Settings" feature.How
With users with large amount of media, there's a chance where the app might crash as we overloaded the app with promises (when we do a
Promise.all()
with more than 500 promises, we get the following warning:WARN Excessive number of pending callbacks
). To counter-act this, we implemented batching (ie: passing fewer promises intoPromise.all()
, but getting through all of them via a for-loop).Test Plan
Mainly, we're making sure that we don't emit the
WARN Excessive number of pending callbacks
, display informative information about the current saving status on the loading screen, and render the explanation modal when we open the app for the first timeChecklist
CHANGELOG.md
&README.md
).THIRD_PARTY.md
.pnpm android:prod
.