Music App, where users can create a personal account to explore/discover tracks, artist and albums top on the area and world wide, at the same time search for tracks listen to their previews, look for artist and albums, and being able to create and edit their own personalized playlist with their selected tracks.
To kick off this session, we want to list out the things a user can do within our app, and tag them as “must-have” (required) or “nice-to-have” (optional)
Required Must-have Stories For NotraMuse, we identified the following “must-have” features which a user needs to be able to perform for the app to work:
After Sprint 1 most use cases are made in parts and just need to be joined to have the completed user story
Optional Nice-to-have Stories
Tab Navigation (Tab to Screen)
Flow Navigation (Screen to Screen)
Property | Type | Description |
---|---|---|
objectId | String | unique id for the user post (default field) |
username | String | Username of the user |
image | String | Password of the user |
Property | Type | Description |
---|---|---|
objectId | String | unique id for the user post (default field) |
creator | Pointer to user | Name of the playlist creator |
name | String | Name of the playlist |
playlist_img | File | Cover image of the playlist |
songIds | Array pointers to songs | An array of ids of songs that are in the playlist |
Property | Type | Description |
---|---|---|
objectId | String | unique id for the user's playlist (default field) |
name | String | Name of the song |
cover_image | file | cover image of the song |
album_name | String | Name of the album this song belongs to |
release | DateTime | date the song was released (default field) |
track_no | Number | track number |
Property | Type | Description |
---|---|---|
objectId | String | unique id for the user's album (default field) |
creator | Pointer to user | Name of the playlist creator |
albumID | Pointer to album | Name of the album |
album_img | File | Cover image of the album |
Property | Type | Description |
---|---|---|
objectId | String | unique id for the user post (default field) |
name | String | Name of the album |
cover_image | file | cover image of the album |
artist | string | name of the artist |
tracks | JSON Object | Contains all the tracks in the album |
List of network requests by screen:
Login/Sign Up Screen
let username = userField.text!
let password = passwordField.text!
PFUser.logInWithUsername(inBackground: username, password: password) {(user, error) in
if user != nil{
self.performSegue(withIdentifier: "loginSegue", sender: nil)
} else {
print("Error: \(String(describing: error))")
}
let user = PFUser()
user.username = userField.text
user.password = passwordField.text
user.signUpInBackground{ (success ,error) in
if success{
self.performSegue(withIdentifier: "loginSegue", sender: nil)
let query = PFQuery(className:"User")
query.whereKey("Username", equalTo:"SampleUser")
query.findObjectsInBackground { (objects: [PFObject]?, error: Error?) in
if let error = error {
// Log details of the failure
print(error.localizedDescription)
} else if let objects = objects {
// The find succeeded.
print("Successfully retrieved user information.")
// Do something with the found objects
user = objects
}
}
Search Screen
(Create/POST) Create a new track object on user playlist
let track = PFObject(className: "Playlist")
track["user"] = PFUser.current()!
track["title"] = track_title!
track["artist"] = artist!
let imageData = uploadImage.image!.pngData()
let file = PFFileObject(name: "image.png", data: imageData!)
track["artist_pic"] = file
track["album"] = album!
track.saveInBackground{ (success, error) in
usleep(3000)
if success {
print("saved!")
} else {
print("Error!")
}
}
let query = PFQuery(className:"Playlist")
query.whereKey("user", equalTo: currentUser)
query.order(byDescending: "updatedAt")
query.findObjectsInBackground { (tracks: [PFObject]?, error: Error?) in
if let error = error {
print(error.localizedDescription)
} else if let tracks = tracks {
print("Successfully retrieved user's playlist.")
}
}
Base URL - https://www.last.fm/api
HTTP Verb | Endpoint | Description |
---|---|---|
GET |
/tag.getTopTags | get the top global tags like rock, electronic, hip-hop |
GET |
/tag.gettopartists&tag= | get all the top artists from a passed tag |
GET |
/tag.gettoptracks&tag= | get all the top tracks from a passed tag |
GET |
/tag.gettopalbums&tag= | get all the top albums from a passed tag |
GET |
/geo.gettoptracks&country= | get all the top tracks from the passed country |
GET |
/geo.gettopartists&country= | get all the top artist from the passed country |
Base URL - https://api.deezer.com
HTTP Verb | Endpoint | Description |
---|---|---|
GET |
/artist/artist_id | Receive artist info by id |
GET |
/artist/artist_id/albums | Get all info on all of artist's albums |
GET |
/album/album_id | Get info on a specific album by id |
GET |
/album/album_id/tracks | Get info on that specific albums tracks |
GET |
/track/track_id | Get info about that specific track by id |
GET |
/search?q=word | Search query for anything that contains given word |
GET |
/chart | Get top artist,tracks, albums, playlist, and podcast |
Wrap Up screens:
Move to player VC when possible:
User can add tracks to their playlist:
User can see their profile information:
User can play previews of tracks saved on playlist:
Fixtures:
*Note audio can't be heard due to being a gif but music is played when view controller is displayed
User can play a song:
User can see info of a song from their playlist:
Playlist and LogOut:
user Sign Up:
Keep Restart:
Fixtures Extra Workflow of User:
Worked on API Incorporation Fixtures:
Album Screen UI:
Playlist Screen FrontEnd Layout:
Show all the code created:
Workflow of Playlist:
Workflow of Tracks:
Workflow of Album:
Workflow of User:
Create classes for different items returned by API:
Search Screen Layout:
Login Screen UI:
Home Screen UI with horizontal scrolling per category:
Configure Parse Server:
Setting up functionality to be used with View Controllers and Parse Server:
Initialize code project and Music API:
Show Track Info and Artist Info:
Leonardo Osorio Nelson Mendez Nelly Delgado Carter Sellgren