Tidal track not available for streaming

I kept finding songs on Tidal I had added to my tracks list but were marked as “not available for streaming” but if you went to the artist page the song stil existsed.

For some reason Tidal’s backend seems to generate a lot of new track IDs when they update or need to make some change to a track. Really frusterating.

To fix this I wrote a script to find exact song title matches of songs from the same artist and swap them. Its been working really well for me and you can find it here on github.

React Context Provider Optimization

React createContext is a powerful way to to use react to communicate between components but there are a lot of easy mistakes to be made that will slow down your app. From memoizing everything to separating component with hooks and components with UI.

Yet even if you follow all of those patterns you can still find your app rendering components that could be expensive to render.

This is because providers trigger renders any time they render. It does not matter if a hook or parent triggers them to render or if it passes in a memoized value. If a provider renders it will trigger anything subscribed to it with useContext.

Consider this provider:

  const [activeModal, setActiveModal] = useState<string>('none');
  const show = useCallback((activeModal: string) => setActiveModal(activeModal), []);
  const value = useMemo(() => ({ activeModal, show }), [activeModal, show]);
  return (
  <ModalContext.Provider value={value}>
    {props.children}
  </ModalContext.Provider>
  );

Above the provider has two values. One to know what the current activeModal is. The other, show, will let components around the appo set a new activeModal.

Because the both values share one prodiver ALL components who access the show function will render when ANY component calls show().

When I learned that dozens of components were getting rendered simply because they wanted the option of possibly calling show() I was a little shocked. Fixing this is not immediately obvious. Memoization can not save you and this might make you start to look at react state libraries. But there is a solution that is architectural.

  const [activeModal, setActiveModal] = useState<string>('none');
  const show = useCallback((activeModal: string) => setActiveModal(activeModal), []);
  return (
  <ModalActionContext.Provider value={show}>
    <ModalContext.Provider value={activeModal}>
      {props.children}
    </ModalContext.Provider>
  </ModalActionContext.Provider>
  );

With values that change separated from function that do not change now any component can access the show() function and never have it trigger a re-render.

You can play with this below. The red components on the left only use one provider and calling show() or hide() causes all red components to render every time. On the right the green components are broken in two providers and calling show() or hide() only renders the components that need to know the activeModal. It doesn’t even trigger a render on the component with the button!

Play with this code on codesandbox.io

Separating the values and functions is a great start and can save many renders around the application. Depending on the data you can think of more ways to separate data. If some values update every time and others only sometime then it might make sense to break those in to separate providers as well.

Most Followed Mastodon Accounts

I’ve launched a new bot / website. Mastodon Most Followed tracks the top 10,000 mastodon accounts. At the moment to make the list you only need over 500 followers to make the list. The list is compiled though monitoring the federated timeline of mastodon.social as well as any mention accounts.

image

Tidal Music Metadata Csv Export

I never trust these music services to remember what music I love. Tidal doesn’t have an easy way to export this. I just want a CSV file to keep so Tidal doesn’t own the music I have found.

So here is a small repo you can clone to run against your Tidal and pull your favorites out.

# You need to install tidalapi using pip install tidalapi (more can be found here https://github.com/tamland/python-tidal)
# had to be fixed with https://github.com/tamland/python-tidal/pull/130

import csv
import sys
import pprint

import tidalapi

session = tidalapi.Session()
session.login_oauth_simple()
favorites = tidalapi.Favorites(session, session.user.id)

#
# Get Tracks
#
open('../tracks.csv', 'w').close()
f = open("../tracks.csv", "a")

f.write('track,album,artist\n')

getMore = True
limit = 1000
offset = 0

while getMore == True:

    tracks = favorites.tracks(limit, offset);
    offset += limit;
    if len(tracks) == 0:
        getMore = False

    for track in tracks:
        f.write(','.join([track.name, track.album.name, track.artist.name]) + '\n')


#
# Get Artists
#
open('../artists.csv', 'w').close()
f = open("../artists.csv", "a")

f.write('artist\n')

getMore = True
limit = 1000
offset = 0

while getMore == True:

    artists = favorites.artists(limit, offset);
    offset += limit;
    if len(artists) == 0:
        getMore = False

    for artist in artists:
        f.write(artist.name + '\n')


#
# Get Album
#
open('../albums.csv', 'w').close()
f = open("../albums.csv", "a")

f.write('album,artist\n')

getMore = True
limit = 1000
offset = 0

while getMore == True:

    albums = favorites.albums(limit, offset);
    offset += limit;
    if len(albums) == 0:
        getMore = False

    for album in albums:
        f.write(','.join([album.name, album.artist.name]) + '\n')

Mechanical Keyboards

Had a fun time getting in to mechanical keyboards for real this time. In the past I got a low profile keychron with Gateron blues and a air75 Nuphy with browns.

The low profile keychrone had flat keys and I couldn’t feel which key my fingers were on and I also didn’t like the blue switch but I didn’t know it at the time.

The Nuphy was much better but I need more room around the sift and arrow keys for me to type well. Also I didn’t like the brown switch though I didn’t know it at the time.

Keychron Q2 QMK - 65% with knob and Gateron G Pro Red

One I got this keyboard I realized why I had problems with the others. I really need that gap for the arrow keys and the linear reds made typing feel good to me.

image

Ajazz AK816 from Epomaker - 75% with gold knob and Gateron Pro 2.0 Silver linears

Once I hit on how much I love the Keychron and why I felt much better with this purchase. I know I like they layout. I was excited to try the silvers which are just like the reds but with a shorter travel distance. I really love a linear with a short travel distance.

Ajazz AK816 from Epomaker

Now that I know what I like I can go back to the original keychron and get better keys and switches and the Nuphy and get linear switches for that as well. It took some money but I’ve set myself up well to always be happy with the keyboard I have.