Dev Week 15

This week I worked on the podcast player's autoplay!

Previously, when you'd be listening to an episode, you'd get near the end and hit the next key to listen to the next episode.. and the next episode would start loading, but it wouldn't play. This would require you to now manually hit the play button, which especially on small devices, can be difficult (think: trying to start the next episode on your mobile device while driving..). Also, the playback speed wouldn't persist, so you'd have to click another tiny radio button to restore your playback speed. Now, whether or not the player would automatically switch to the next episode when you got to the very end of an episode without pushing the next button, I don't know. It was supposed to, but I didn't test it thoroughly because I always hit "next" manually.

Now, it automatically refreshes the playback speed and starts playing the episode! Single-click to progress!

I thought I had seen a page on MDN (Mozilla Developer Network) about the audio tag event lifecycle, but I couldn't find it after what I felt was too much time spent. Instead, I added some logging scaffolding to watch every audio element event as it occurred. This code automatically overrides console.log to add all log messages to a div element to the page instead of only to the console, enabling the viewing of logging even on mobile!

const originalLog = console.log;

const logToScreen = (...args: any[]) => {
  originalLog.apply(console, args);

  // Create debug element if it doesn't exist
  let debugDiv = document.getElementById('debug-log');
  if (!debugDiv) {
    debugDiv = document.createElement('div');
    debugDiv.id = 'debug-log';
    debugDiv.style.cssText = 'position: fixed; bottom: 0; left: 0; right: 0; background: rgba(0,0,0,0.8); color: white; padding: 10px; max-height: 200px; overflow-y: auto; font-family: monospace; font-size: 12px;';
    document.body.appendChild(debugDiv);
  }

  // Add new log entry
  const entry = document.createElement('div');
  entry.textContent = `${new Date().toISOString().split('T')[1].split('.')[0]} ${args.join(' ')}`;
  debugDiv.appendChild(entry);

  // Keep only last 5 entries
  while (debugDiv.childNodes.length > 100) {
    debugDiv.removeChild(debugDiv.firstChild);
  }
};

// console.log = logToScreen;

All you need to do is comment out the last line to enable it, and ensure your code has some console.log calls.

This allowed me to realize what I really needed to do: record speed and play state whenever they change; when metadataloaded is finished, trigger a play; when play is triggered, restore the values. There's some extra boolean logic to make sure it only restores at the correct times, but that's the basic gist of it.

This also reminds me that I'd also like to style the UI so the playback speed radio boxes look like nice big clickable buttons, increase the size of the forward/backward/previous/next buttons to overall make it more mobile-friendly.

As if that's not enough, I also want to show the date of the episode on the page, but that requires a backend change and I've been super focused on what I can do only by changing frontend code. It gives me a greater appreciation for communication and teamwork, because if you only know how to do frontend or only backend, and depend on someone else for vital functionality, if they don't do it then it simply doesn't get done and you're stuck! That's certainly a nice thing about knowing backend and frontend.

I've always been more of a backend gal, but I think I'm finally getting the hang of React, reasonably, especially with using lots of custom hooks to keep functionality nice and self-contained. The code needs another refactor after working on the autoplay, but it's worlds apart from the raw HTML/JavaScript I wrote on my dashboard/weather app back in 2017. Unfortunately that code was a bit too tied-in with my "personal stuff" and I never published it on Github. Thinking back, that "personal stuff" may be entirely irrelevant and non-sensitive today, so hopefully I'll get a burst of motivation someday to go find it, clean it up, and publish it.

Back on "As if that's not enough", I have a lot of functionality I want to implement, and I'm trying to avoid making a huge list and overwhelming myself, instead focusing on the most important usability functionality right now. The past two weeks I got playback to be really smooth, being able to play the audio as soon as you hit the page instead of waiting several seconds, and the ability to switch to playing the next episode at the same speed with a single click. I think these are massive usability improvements. I'm wanting to implement the improvement I mentioned on last week's post about the server loading segments from file in increasing sized groups, instead of one segment from the filesystem per request while running an additional backend job to load the entire file. While the algorithm is unclear, the idea is not.

As I was working on these two features, it's really making me itch to start making automated browser testing using Selenium. I've been exposed to Selenium but I actually got to use it very briefly for work at least once or twice, and it's not terribly scary. My time spent manually sliding and scrolling and skipping and clicking, all would have been a lot faster (or at least less tedious on my part) if I had an automated testing suite. There's so much I want to do!!!

In case anyone is wondering why the image of the console logs shows the "Adding event listeners to videoRef number 1" and another message each twice, it's because in non-production mode, React useEffect runs twice in a row each time to help developers catch bugs, because useEffect is supposed to be idempotent, i.e. running it twice in a row should behave exactly the same as if it had run once. See the docs if you're interested.

I've made it up to SN episode 146. Steve mentioned Black Viper (https://www.blackviper.com/), who has an "In Loving Memory" page, which I'm considering making one of my own. Additionally, I need to rename Dev Week to Tech Week.

In my home lab stuff, I struggled with Element/Synapse/Matrix a little bit. I needed to manually reset permissions on my Element client (which had gone from something like rwxr-xr-x to ------ [?!]), change the configs to stop automatically logging my dang clients out, fix router DNS settings (there was an old record that was wrong and overriding the correct record), and fixing up the Nginx server to redirect the .well-known paths for server discovery. Phew! All that just to post the image above of the logs in the playlist app, but now my entire system is much nicer, with additional comments in all the config files I touched, setting up a highway that I can drive on the next time I have to deal with something (no, I'm not using Ansible or Terraform, which I'd love to use if I didn't already have so much stuff set up without them; maybe the next time I migrate servers, or maybe I'll experiment with a raspberry pi.. if I weren't so busy building a podcast app). I'm getting much better at commenting and leaving myself breadcrumbs to get back faster.

I interact with a lot of different FOSS technologies and I'm wondering about including them in my blog posts more, hence Element/Synapse/Matrix, Nginx, Ansible, (Terraform isn't FOSS), and Raspberry Pi. I don't even know if I've mentioned anywhere on my site: I use Gentoo Linux with Xfce4 as my windowing manager. I love looking at Github repos and installing various FOSS software, setting up lots of Docker containers with different apps. I have around 27 apps installed as Docker Stacks/Compose, and I'd like to mention at least 1-2 each week.

Thanks for joining us for this week's Dev Tech Week!

Posted in Dev

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.