Skip to content
/ Rac1.js Public

React.js app to play Rac1 radio station podcasts

License

Notifications You must be signed in to change notification settings

emibcn/Rac1.js

Repository files navigation

Node.js CI Build Status coverage DeepSource

Web APP to listen to Rac1 radio station podcasts. Uses React as JS frontend library and GitHub pages to publish it at Rac1 podcast player at Github Pages. There, you will find this repo's gh-pages branch contents, which are the results of executing yarn build on this project's GitHub workflow/Actions using this project's source application (See more in the Install section).

The podcasts lister is a pure JS lib, which only depends on abortcontroller-polyfill to help GoogleBot execute modern JS, so you can easily re-use it for other JS projects.

Motivation

I made this app for 3 reasons:

  • I needed a better way to listen to those podcasts (because the official app is not useful to me) and I wanted it to be easily compatible with all my devices.
  • Learn modern JavaScript (and some other modern stuff): I've been using JavaScript (mostly with JQuery) since a long time ago. Doing an app on my free time is a good way to me to learn a new language or refreshing it.
  • This is an open and free (open, gratis and libre) app. It can serve as:
    • Learning material (as I did). You may want to learn some of the libs and APIs used here.
    • Share and re-use. You may want to use it as a starting point for your own app, or you may want to add parts of the code to your own app. Please, follow GPLv3.
    • This source code and the working APP also serve as presentational card for my '20s frontend abilities. If you want to hire me, send me a PM.

Inspired by my command line Python app Rac1.py, which was not enough for my Android phone ;P

See also

Dependencies

Features

  • Always with a coherently time ordered list of available podcasts
  • Auto play next podcast when currently played one finishes (as a normal playlist)
  • Ability to update podcasts list
  • Autoupdate podcasts list when trying to play next podcast after last one, and play the next one (if there is any) after the update finishes
  • Show currently playing program metadata: Name, author, schedule, image
  • keyPress event handling, via a non-visible <input> element which focus itself everytime onBlur is detected. You can use some of the mplayer default key bindings:
    • LEFT: seek backwards 10s
    • UP: seek backwards 1m
    • PAGE UP: seek backwards 10m
    • RIGHT: seek forward 10s
    • DOWN: seek forward 1m
    • PAGE DOWN: seek forward 10m
    • SHIFT+UP/DOWN or *//: Adjust volume
    • SPACE/P: (Un)Pause
    • M: (Un)Mute
    • ENTER: Jump to next podcast
    • SHIFT + ENTER: Jump to previous podcast
    • R: Update the list of podcasts
  • Good UI controls for use with mobile devices (big buttons, disabled key bindings).
  • Use MediaSession to show podcast data and more controls on mobile (and some desktops) notifications and lock screens.
  • Almost WCAG accessible.
  • Very fast:
    • Use <meta rel="preconnect"> to pre-initiate external HTTPS connections early
    • Use <meta rel="prefetch"> to begin early download of external very slow server
    • Use ServiceWorker (SW) to predownload and maintain the assets in cache
    • Included manifest and SW to allow adding the app icon to mobile desktop with splash screen
    • Very fast backend HTML parser
    • Use React.PureComponent where possible
  • Asynchronuosly fetch podcast list and pages list HTML page, parse it with RegExp and download remaining pages
  • Asynchronuosly fetch podcasts JSON data
  • Asynchronuosly fetch live podcast data (in HTML) and parse it

TODO

  • Improve UX: layout, styles, info shown, responsible, controls, ¿bootstrap4?
  • Use Streams API to control audio downloading and playing (and editing?)
  • Add a section to allow easily play podcasts filtered by program
  • Filters via localStorage, to easily jump unwanted podcasts
  • Save volume to localStorage and use in all players.
  • Better internal state handling for player status: currentPosition, play...
  • Consider using Redux
  • There is some issue with memory: 300MB+ for each extra date visited (leak, fragmentation or just JS?). Try to debug and fix it.
  • Add tests

Install

You can already use the app on it's public location. But you would like to run a local copy of it, or start the development local server to start developing some changes. Whatever is your case, you need to download the code and its dependencies, build it and serve it somehow. Here, I use git to download the code, docker and docker-compose to contain all the boilerplate out of my system and ensuring a consistent CI/CD, npm and yarn to manage the JS dependencies (and building and testing), the create-react-app (CRA) development server and NGinx for serving the static/built version.

Download

git clone https://github.com/emibcn/Rac1.js.git
cd Rac1.js

Development container

Using the provided docker-compose.yml file, it is possible to build and execute a live environment which can host the application in development mode using WebpackDevServer configured by Create React App (CRA), what helps a lot while actively modifying the files. It is also possible to serve the static version of the app using vanilla NGinx locally.

Of course, you can opt-out and install NodeJS, NPM and yarn by yourself. Also, you can eject CRA.

Install Docker

It depends on which system you use. Go to Docker documentation to get help adapted to your use case.

Install DockerCompose

Go to Docker Compose and follow instructions, depending on your use case.

Build + Run

This will build the containers images, download system and NodeJS dependencies and launch NodeJS development server at port 3000 and NGinx static server at port 4000:

docker-compose up -d

Build

This will build the containers images:

docker-compose build

Run

Background

docker-compose up -d

Foreground (following WebpackDevServer logs)

docker-compose up

(If you stop this with CTRL+C, container will stop too)

Logs (with follow)

Once the container is started, you can view WebpackDevServer logs executing:

docker-compose logs -f

(You can stop this with CTRL+C)

Stop

docker-compose down

Application

By default, the container installs all NPM dependencies using yarn dependency manager. If you use the provided docker-compose.yml, the app directory will be mounted inside the container. This automatically helps maintaining the cache of the installed npm modules and auto refreshing the browser when any file is modified or module added/removed/updated.

Once the container has been started, you can enter inside it to execute commands needing NodeJS. For example:

me@mypc:~/Rac1.js$ docker-compose exec rac1 bash
node@8cf780c7b2bb:~/app$ yarn add react-dom-router
[...]
node@8cf780c7b2bb:~/app$ exit
me@mypc:~/Rac1.js$

Or, in one line:

me@mypc:~/Rac1.js$ docker-compose exec rac1 yarn add react-dom-router
[...]
me@mypc:~/Rac1.js$

If you need root permisions:

me@mypc:~/Rac1.js$ docker-compose exec -u root rac1 bash
root@8cf780c7b2bb:~/app$ apt-get update; apt-get install git; apt-get clean

Or:

docker-compose exec -u root rac1 bash -c 'apt-get update; apt-get install git; apt-get clean'

Build static app

In order to publish the app, it's needed to build it. This will do some modern JS magic (Babel, WebPack, ...) and create a static version of the app, which can be served as static assets. To do so, it's needed to execute yarn build on the app's dir:

me@mypc:~/Rac1.js$ docker-compose exec rac1 yarn build
yarn run v1.9.4
$ react-scripts build && yarn sw-epilog && yarn pubgh
Creating an optimized production build...
[...]
Done in 58.15s.
me@mypc:~/Rac1.js$

Access the app

Open your browser and point it to the development version at http://127.0.0.1:3000 or the static version at http://127.0.0.1:4000/Rac1.js/, or visit the public version at https://emibcn.github.io/Rac1.js/ .