Building an iPod: Part 1 — Angular User Interface

Krisztian Seres
3 min readMar 26, 2021

Wonder how it feels to use an iPod with Apple Music or even Spotify? Let me show it to you in this series. I’ll try my best to recreate the classic iPod experience.

I remember getting my first iPod in 2006. It was an iPod Nano with 1 GB of storage. Its user interface with the click wheel blew me away.
In 2014 Apple discontinued the iPod Classic, the same time they released their streaming platform, ever since Apple Music has no support for any of the non-iOS iPods.

I used Angular framework and I started with the most important component of the interface: the click wheel.

The iPod click wheel is the navigation component of several iPod models. It uses a combination of touch technology and traditional buttons, involving the technology of capacitive sensing, which senses the capacitance of the user’s fingers. The wheel allows the user to find music, videos, photos and play games on the device.

I believe this interface can be seamlessly integrated into touch screens. The music player I’m building does not allow touch interactions on its screen. I want it to be classic.

I built an Angular component around Anthony Terrien’s knob implementation. This repository is an implementation of a knob user interface element with rich customization options. I used the infinite configuration that allows me to scroll up and down capturing decrease and increase events.

I identified every event that can occur on a click wheel. Then, I routed these events to a publisher service. Every Angular component that is subscribed to the specific event gets notified through the publisher. After a little bit of styling it looks like this:

The click wheel built with HTML5 and CSS.

In this project, I used the Publisher-Subscriber pattern for event handling. Every triggered event is routed to a publisher. Any component that is interested in a specific event can subscribe itself to get notified. These events can be a set of click wheel events or events from the specific streaming platform, such as: authorization events, change of playback state, track finished, playlist update.

Next up, we have the menu, which essentially is a set of multi-lists. Suppose we have a library of a thousand songs; I don’t want to render each song into an HTML element with an *ngFor because that kills the scroll performance. Instead, I only render the visible 9 rows (the iPod’s menu consists of 9 rows and a header).

In case we hit the enter on the click wheel we’ll slide the currently displayed menu list and render its nested child-menu. Only the currently displayed menu page is subscribed to scroll events. When we return to the previous page its selected element is not affected by scrolling; this works because when we hit enter on the click wheel, the current menu-page requests the Publisher to unsubscribe itself from the scroll subscriber list.

Let’s see how the interface looks with a dummy set of nested lists:

Upon entering the ‘Songs’ category by clicking the middle button we render the submenu of a 1000 songs. This is not a performance hit however, since we only render 9 HTML element and only the labels are getting updated on each scroll event.

With a working scroll wheel and a functional menu, the interface is ready for our first streaming service integration: Spotify. More on that story later.

You can try the beta version here: webPod

--

--

Krisztian Seres

Co-Founder of Enlight Digital Studios. Software Engineer.