GithubHelp home page GithubHelp logo

jsmith / relar Goto Github PK

View Code? Open in Web Editor NEW
13.0 2.0 0.0 25.71 MB

The Relar cloud music player repository.

Home Page: https://relar.app

License: Mozilla Public License 2.0

JavaScript 2.95% TypeScript 87.39% CSS 0.54% HTML 0.22% Shell 0.61% Ruby 0.68% Java 2.98% Swift 4.45% Objective-C 0.17%
music react tailwind cloud firebase snowpack tailwindcss musicplayer capacitor hybrid-app

relar's People

Contributors

jsmith avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

relar's Issues

Google Analytics References

I want to know where people have come from when they visit the site. To do this, I should use some kind of reference identifier for all sites that I post the app on and send that information to Google Analytics.

Playlists

Problem

This is a no brainer feature! As a user, I want to be able to create playlists to store collections of songs.

Implementation

There are three solutions that I see:

  • Store a collection of IDs for each playlist. Pro is that there isn't a size limit but con that you have to perform lots of reads (2 for each song).
  • Store a collection of songs (so duplicate data) in a playlist. Pros are that there are no size limits, only one query needs to be performed per song, and sorting is super easy! Cons are that maintaining up-to-date data is harder. This may be the solution we employ eventually.
  • Store a single document (max size 1 MB) that contains a list of document IDs. Cons is that we need to perform a query based on IDs (ie. get songs based on a list of UIDs). Not sure how efficient this is yet but it does make querying the playlist much simpler. Since the song ID is 16 bytes, we can store 1024 * 1024 / 16 <= 65536 songs (we need to store the created date and the name of the playlist as well). Another con of this solution is that there is a risk of overwriting data. This will need to be investigated before implementation starts.

Scope

We will not be adding the ability to sort playlists based on any attributes. By default, they will be sorted by the time they were added. Google Play does allow you to sort; however, Spotify does not.

Locally Stored Songs

Problem

Loading songs every time may turn out to be an expensive opration ($0.06 / 100,000 reads).

Solution

Create some kind of system that syncs changes to each device (CRDTs??).

Queue

Problem

As a user, I want to be able to create a queue of songs (albums, artists, entire libraries, custom). Additionally, for each song, I want to see where that song came from.

Solution

A queue will basically be a list of songs with a source.

interface SongQueue {
  /** The current index into the queue */
  current: number;
  songs: SongQueueItem[];
}

interface SongQueueItem {
  source: "album" | "custom" | "artist" | "library" | "playlist";
  sourceId: string | undefined; // defined if source === "album" or source === "artist" or source === "playlist"
  song: DocumentSnapshot<Song>;
}

A user will be able reorder the queue without losing the source information (the current value will need to be updated when this happens). Furthermore, a user should be able to create a playlist from this queue.

Scope

Nothing here yet.

Google Analytics

Problem

As the owner, I want to be able to understand how people are using the app.

Solution

Google Analytics is a great tool that integrates well with firebase. Use this documentation along with tutorials and such to add analytics to the web and mobile apps.

Scope

We should be tracking lots of things. For example:

  • How many people use feature "x"
  • How many times do people load songs and how many songs do they own?
  • How many times do people upload songs and how many songs do they upload at a time?
  • How many times do people open the app
  • How long do users spend on each tab

This information will be critical to optimize usage before the release.

Sentry

Problem

As the owner, I want to be able to quickly respond to user errors.

Solution

Sentry! Sentry is already integrated into the app but we should ensure that everything is correct configured and that we are capturing all errors.

Scope

This doesn't need to be too in depth. This tutorial looks like a good starting point to ensure everything is correctly integrated.

Icon & Branding

Problem

As a user, I want consistent branding.

Solution

Create a logo, ensure name is good, create favicon and other icon.

Enable Subscriptions

Problem

As a user, I want to be able to subscribe to increase the services I receive.

Solution

We need to integrate stripe into our app (especially firestore) to enable users to subscribe to our app.

Scope

If it's not too hard to set up, we should offer the subscription cost in different currencies. We also need to ensure we collect tax correctly. Also, we need to ensure we are complying with all legal requirements. Are there any issues with hosting the app in the USA but serving Canada/Europe? Should we restrict who can use this app?

Artist Tab & Artist Page

Problem

As a user, I want to be able to organize my songs my artist.

Solution

Artists are actually super simple, they just contain a name! This makes them super easy to identify and look up. We'll store a collection of artists (where the unique ID is the name of the artist) with just a single attribute (the artist name).

Scope

We are not storing artwork for artists. This might be a nice feature though! Also, you will not be able to edit the name of an artist.

Feedback & Contact Information

Problem

As a user, I want to be able to contact someone for support or to leave feedback.

Solution

We should add a contact form that users can use for support issues and feedback. This could be present in the account dropdown and automatically be linked to their account. We could also add a support page that could be accessed from the footer for users who don't have accounts.

Scope

We will not be doing anything fancy for feedback yet. Eventually, we might be able to use some kind of service to manage feedback and provide support.

Public Update/Changelog

Problem

As a user, I want to follow updates to the app.

Solution

Have a public relar.app/updates page which pulls data from a collection of updates with change logs, dates and versions.

Inspiration

Firestore Watcher

Problem

We need a way to sync data across the app. React is pretty good at this but there are particular instances where this is not sufficient. In addition to React state management (ie. useState, useContext), we are using react-query to manage queries, mutations and frontend caching. This need stemmed from this user story:

As a user, I want to be able to like a song in the song table and have that automatically show up in other parts of the app (ie. the player).

Vue would particularly be a better fit to this task given their dependency tracking but of course... we are using React. This synchronization feature will appear in other locations in the app too. For example, a user may change a song's metadata and expect that change to appear in other locations in the app, even if the old value had previously been cached.

The hardest part about this problem is the magnitude of data we could be dealing with (on the scale of tens of thousands). We could engineer a simpler solution using onSnapshot but I think it would be a good idea to create a solution now.

Solution

This solution will attach onto the .doc methods and .collection methods to return DocumentReference objects that have their update, set, and delete methods wrapped. By wrapping these methods, we can be alerted when mutations occur. Once these mutations succeed, we will kick off a get on the reference object to grab the latest data. This data will need to be stored for the lifetime of the app as other elements with stale data may attach at which point we should return the most up-to-date locally stored data. The second step to this solution is creating a hook that can be used to watch for updates. Then, for example, the Player elements along with the SongTableRow elements will be able to use this hook to receive the most up-to-date version of the object.

export interface SongTableRowProps {
  /**
   * The song. `undefined` means it is loading.
   */
  song: firebase.firestore.QueryDocumentSnapshot<Song> | undefined;
}

export const SongTableRow = ({ song: original }: SongTableRowProps) => {
  ...
  const song = useFirebaseUpdater(original);
  ...
}

This should be a fairly efficient solution. Unlike onSnapshot, we are not listening for remote updates. Using hooks, we can easily dispose of listeners when components are unmounted.

Scope

This solution is for local changes only. This solution treats whats in the cache as the source of truth, not whats in the remote database. If a user mutates data on another device, they can just refresh the page. If we wanted local and remote changes, we could use the onSnapshot method for document references. We will be supporting deletions (delete), updates (update), and sets (set).

References

Offline Support

Problem

As a user, I want to be able to use the app while offline. All my songs/albums/artists/playlists should be available. Additionally, I want to be able to download specific songs/albums/artists/playlists and automatically download new songs.

Solution

To start, we should use firebase's offline support. This should work without have many changes to the codebase. To implement offline support, we can use capacitors filesystem and storage APIs to store JSON data (saying which files are downloaded) the associated files.

Scope

  • We need to implement something that periodically cleans out deleted songs.
  • We should also implement simple LRU cache. We'll need to add a setting to clear out this cache.

Player

Problem

As a user, I need be able to play music from the app.

Solution

Build a player page that can be minimized/maximized while playing. This page should follow the tradition design of players (see SoundCloud, Google Play, Spotify, etc).

CORS

We should add CORS for relar.app, staging.relar.app and localhost:3000!

Songs Page

Problem

As a user, I want to see all of my songs on mobile.

Solution

Create a songs list using the recycle view. Also build a nice navigation that allows you quickly jump to different sections of the songs by letter.

Accessible Forms

Problem

As a user, I want to ensure forms are accessible

Solution

  • Ensure required fields are marked required
  • Ensure password integration works
  • Ensure is used and

Mobile

We need a mobile app!

Optimize Search

Problem

As a user, I want to be able to find the website by searching online.

Solution

Go through the optimization documentation from Google to optimize search. I'm really not sure how all of this actually works.

Queue

Problem

As a user, I want to view the queue on mobile.

Solution

The easiest and coolest solution is to replicate the views from Apple Music.

Customize Email Templates

Problem

Emails will be sent to users when signing up, creating their account, confirming their email, resetting their password, etc. These need to be customized!

Solution

Customize the emails!

Scope

We will be doing nothing fancy :) Just simple text.

Subscriptions

Problem

As a user, I want to be able to upgrade my account to improve my services.

Solution

Use stripe to implement subscription system. Firebase has a great tutorial. Be sure to integrate firebase analytics to be able to distinguish users by subscription level.

Scope

  • The scope will definitely have to be limited! Create one or two subscription levels and limit the currencies to USD or USD and CAD.

Custom Email Action Handlers

Problem

As a user, I want to go to a page that I am familiar with to change my password/email.

Solution

Implement custom email action handlers. See the tutorial here.

Infinite Scroll Song Table

Problem

Users will be able to upload lots of songs. Because of this, we don't want to load everything at once. Although infinite scroll is a hassle, I think it's worth the effort.

Solution

We will use firebase in addition to the infinite scroll of react-query to implement this feature. No infinite scroll table has been chosen yet but note that we will have an accurate count of the number of songs in the database which is useful for correctly size the scrollbar.

This solution will take advantage of the work from #2 to ensure the data in the table is the most up-to-date data and changes are automatically propagated.

Scope

Depending on the complexity, sorting by title, artist, album, play count, like may or may not be supported.

Album Tab & Album Page

Problem

We need to be able to store albums and have them linked to songs. One of the main questions we need to answer is, how do we uniquely identify an album? In the real world, this is done by an album name and an artist. This could lead to conflicts in practice but these situations can be ignored and left up to the user to deal with.

Solution

Uniquely identify an album by an album name and album artist. Album artists are purely for organizations purposes and are apart of the ID3 spec. See here for more information. In practice, this could lead to annoyances. If a user uploads a song with an album name but no album artist, an album artist but no album or an album name with an artist (no album artist), then we want to handle these situations as well. Here is a summary of the situations that may arise:

  1. No album name: Show "No Album Name" to the user and leave the album name empty or undefined in the db.
  2. No album artist name or artist: Just show "No Artist" to the user similar to above.
  3. No album artist: Use the artist instead of the album artist to create the album. The album artist should always take priority though.

Querying

The above points are detailed enough to provide solutions for everything but they're good enough for now. One more problem is figuring out how we are going to query songs that belong to an album. One possibility is generating unique IDs for each album and then storing that in the db but a much nice solution is deriving the ID from the album name and album artist. This makes it super easy to lookup an album given an album name, artist name, and album artist name.

Syncing Data

If the data of an album is changed, that information should be changed within all of the songs as well.

Scope

Nothing important to put here!

Dynamic Titles

Problem

As a user, I want artist/album/playlist page titles to show the name of these items.

Solution

Use a hook system to set and unset the page title.

Undo

Problem

Users are going to do things they don't mean to do!

Solution

Either we make the user confirm actions or provide very basic undo functionality (or both). For certain operations (ie. changing email address), a confirmation works best; however, for things like removing a song from a playlist, undo might be the most user friendly option. Here is a non complete list:

  • Adding a song to a playlist.
  • Removing a song to a playlist.
  • Editing song data.
  • Deleting a song

Scope

  • No redo after an undo
  • No undo stack
  • Undos shouldn't worry about other undos messing with their state

Shuffle

Problem

As a user, I want to be able to shuffle playlists, artists, albums and my entire song library.

Solution

Shuffle will take the item being shuffled (ie. simple randomization) and then insert everything into the queue. This will be fairly easy for playlists, artists and albums but the entire song library poses a problem if we don't plan to load everything into memory at once. Because of this, I plan to change how we implement the frontend to actually load all songs during the loading process of the app. This will make the implementation of the shuffle much easier, along with other problems.

Scope

We will not be any kind of smart shuffle features. See the accepted answer of this SO post for more details but here is the gist of why this would make things harder:

• Users don't want to hear the same song multiple times in a row.
• Users don't want to the same artist/album played consecutively or too close together.
• Users want to hear 1-2 songs from every artist/genre in their collection before repeats occur.
• Random sequences that match established patterns are viewed as not random and disliked. This would be things like playing track 2 from albums A, B, C then playing track 3 from those albums, or playing track 1 from A, track 2 from B, track 3 from C. This would also be if songs followed a rock, country, rap, pop cycle or songs played in alphabetical order.
• Over playing less liked artists or under playing favorite artists creates dissatisfaction.
• Subsets of songs shouldn't be played in the same order as previous iterations. similarly the last X songs shouldn't be in the first X songs in the next iteration.

Firebase Rule Review

Problem

As a user, I want my data to be secure and not become messed up.

Solution

Ensure firebase rules are as strict as possible.

Scope

Add type checks and attribute checks for all create and update permissions.

Editing Song Data

Problem

As a user, I want to be edit song metadata and then have those changes affect artists/albums.

One of the hardest parts about maintaining a song database per user (as appose to a streaming service like Spotify) is that the source of truth for all data is songs. For example, when a user uploads a new song with an album that doesn't exist yet, we need to create that album in the database so that it can be queried. Furthermore, if a user edits a song to change the album, we need to delete the old album if it's now empty and create a new album if that new album doesn't exist. The same things go for artists as well!

Solution

For this complex operation, we can create a cloud function using express. Obviously, this function will allow the user to edit the:

  1. title
  2. year
  3. genre
  4. album name
  5. artist name
  6. album artist name

But if the album, artist, or album artist change, we may or may not need to delete/create albums/artist.

Scope

  • We will not support querying by genre for the beta release. Therefore, we do not need to maintain a list of genres.
  • We will also not be supporting other metadata such as track #, total tracks, explicit, etc.
  • We will also not support editing artwork yet.

Search

Problem

Users need to be able to search through their own libraries for songs, albums, and artists.

Solution

Algolia and Elasticsearch seem like two great options. Since the solution we choose needs to work with data on the scale of 20,000 songs / user, this immediately eliminates Algolia which charges $1 / month / 1,000 documents. The officially managed elasticsearch service from elasticsearch seems like a promising option. We'll need to run the numbers to be sure that this solution will work for the scale of data we will be using (ie. hopefully much less than $1 / month / user).

Scope

  • To start, we can just index songs maybe?

Library Backup

Problem

As a user, I want to be able to perform backups of my library to ensure my mp3 collection is always safe.

Solution

Provide a desktop tool that allows users to backup their library one song at a time.

Settings

Problem

As a user, I want to be able to control the app.

Solution

Create Settings page that allows users to sign out, directs them to the web app to control their account. Also, have streaming/downloading settings (related to #58) that allows users to configure "cache during playback", "clear cache", "stream via wifi only", "download via wifi only". Eventually, we can have stream/download quality settings as well.

Scope

  • We will not have account controls (account deletion, change password, change email) in the app

IMG_2557
IMG_2558
IMG_2559

Albums/Playlists Mobile

Problem

As a user, I want to see my albums/playlists.

Solution

Build an albums/playlists page and an album/playlist/generated page. Similar to the web, this should show meta information and the list of songs.

Performance Monitoring

Problem

As the owner, I want to be able to see how my app is performing.

Solution

Use firebase performance monitoring.

Keyboard Shortcuts

Problem

As a user, I want to be able to use keyboard shortcuts to navigate to different tabs and to perform different actions.

Examples

  • "/" to navigate to the search tab.
  • "Space" to play/pause song

Solution

This should be pretty easy! We can just register a list of global keyboard shortcuts using something like react-hotkeys-hooks. We should also create a nice modal that has all of the shortcuts.

Screen Shot 2020-08-03 at 8 58 31 AM

The Soundcloud shortcut modal.

Scope

There will be no overly complex shortcuts that only apply if certain areas of the app are focused (like VS Code does).

Auto Generated Playlists

Problem

As a user, I want to see my recently added songs and my recently liked songs.

Solution

We can easily query using firestore queries.

Scope

We'll limit the # of recently added songs to 1000.

Accessibility Review

Problem

As a user who uses screen readers, I want to be able to use the app.

Solution

We should review best practices and research how Spotify implements accessibility.

Scope

This does not need to be perfect by any means. Eventually, I might be able to bring in someone more knowledgable to evaluate the app once the low hanging fruit are taken care of.

Resources

Duration

Problem

We need to store the duration of the track for UI purposes. For example, this will be useful to quickly calculate the duration of a playlist and to display a duration in the song table.

Solution

Use this package to get the duration while uploading a song. Modify the SongType accordingly to make the duration property required.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.