diff --git a/app/build.gradle b/app/build.gradle
index 11df113f..2f73bc55 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,7 +1,10 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
+ id 'kotlin-parcelize'
id 'kotlin-kapt'
+ id 'dagger.hilt.android.plugin'
+ id 'kotlinx-serialization'
}
kapt {
@@ -98,6 +101,15 @@ dependencies {
implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-ktx:$room_version"
+ //Hilt
+ kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
+ implementation "com.google.dagger:hilt-android:$hilt_version"
+ kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'
+ implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'
+
+ //FFmpeg
+ implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
+
//Okhttp
implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version"
@@ -106,11 +118,15 @@ dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
//Json
+ implementation 'com.beust:klaxon:5.4'
implementation 'com.squareup.moshi:moshi:1.11.0'
implementation 'com.squareup.moshi:moshi-kotlin:1.11.0'
implementation "com.squareup.retrofit2:converter-moshi:2.9.0"
implementation "com.squareup.retrofit2:converter-scalars:2.9.0"
- implementation 'com.beust:klaxon:5.4'
+ implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1"
+
+ //Glide-Image Loading
+ implementation "dev.chrisbanes.accompanist:accompanist-glide:0.4.1"
//Coil-Image Loading
implementation "dev.chrisbanes.accompanist:accompanist-coil:$coil_version"
diff --git a/app/libs/mobile-ffmpeg.aar b/app/libs/mobile-ffmpeg.aar
new file mode 100644
index 00000000..ba7575f6
Binary files /dev/null and b/app/libs/mobile-ffmpeg.aar differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 20a151a7..a1ffe0ce 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -23,6 +23,7 @@
.
+ */
+
+package com.shabinder.spotiflyer
+
+import android.app.Application
+import dagger.hilt.android.HiltAndroidApp
+
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+@HiltAndroidApp
+class App:Application(){
+ companion object{
+ const val clientId:String = "694d8bf4f6ec420fa66ea7fb4c68f89d"
+ const val clientSecret:String = "02ca2d4021a7452dae2328b47a6e8fe8"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/MainActivity.kt b/app/src/main/java/com/shabinder/spotiflyer/MainActivity.kt
index 002147df..5bd2575d 100644
--- a/app/src/main/java/com/shabinder/spotiflyer/MainActivity.kt
+++ b/app/src/main/java/com/shabinder/spotiflyer/MainActivity.kt
@@ -16,18 +16,28 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.setContent
import androidx.compose.ui.res.vectorResource
import androidx.core.view.WindowCompat
-import com.shabinder.spotiflyer.home.Home
+import androidx.lifecycle.ViewModelProvider
import com.shabinder.spotiflyer.navigation.ComposeNavigation
+import com.shabinder.spotiflyer.networking.SpotifyService
import com.shabinder.spotiflyer.ui.ComposeLearnTheme
import com.shabinder.spotiflyer.ui.appNameStyle
import com.shabinder.spotiflyer.utils.requestStoragePermission
+import dagger.hilt.android.AndroidEntryPoint
import dev.chrisbanes.accompanist.insets.ProvideWindowInsets
import dev.chrisbanes.accompanist.insets.statusBarsHeight
+import javax.inject.Inject
+/*
+* This is App's God Activity
+* */
+@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
+
+ private var spotifyService : SpotifyService? = null
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
-
+ sharedViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
// This app draws behind the system bars, so we want to handle fitting system windows
WindowCompat.setDecorFitsSystemWindows(window, false)
@@ -56,7 +66,9 @@ class MainActivity : AppCompatActivity() {
companion object{
private lateinit var instance: MainActivity
+ private lateinit var sharedViewModel: SharedViewModel
fun getInstance():MainActivity = this.instance
+ fun getSharedViewModel():SharedViewModel = this.sharedViewModel
}
init {
@@ -100,6 +112,20 @@ fun AppBar(
@Composable
fun DefaultPreview() {
ComposeLearnTheme {
+ ProvideWindowInsets {
+ Column {
+ val appBarColor = MaterialTheme.colors.surface.copy(alpha = 0.87f)
+ // Draw a scrim over the status bar which matches the app bar
+ Spacer(Modifier.background(appBarColor).fillMaxWidth().statusBarsHeight())
+
+ AppBar(
+ backgroundColor = appBarColor,
+ modifier = Modifier.fillMaxWidth()
+ )
+
+ ComposeNavigation()
+ }
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/SharedViewModel.kt b/app/src/main/java/com/shabinder/spotiflyer/SharedViewModel.kt
new file mode 100644
index 00000000..9c5711e7
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/SharedViewModel.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.shabinder.spotiflyer.networking.SpotifyService
+
+class SharedViewModel : ViewModel() {
+ var intentString = MutableLiveData()
+ var spotifyService = MutableLiveData()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/database/DatabaseDAO.kt b/app/src/main/java/com/shabinder/spotiflyer/database/DatabaseDAO.kt
new file mode 100644
index 00000000..f323cf01
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/database/DatabaseDAO.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.database
+
+import androidx.room.*
+
+@Dao
+interface DatabaseDAO {
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ suspend fun insert(record: DownloadRecord)
+
+ @Update
+ suspend fun update(record: DownloadRecord)
+
+ @Query("SELECT * from download_record_table ORDER BY id DESC")
+ suspend fun getRecord():List
+
+ @Query("DELETE FROM download_record_table")
+ suspend fun deleteAll()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/database/DownloadRecord.kt b/app/src/main/java/com/shabinder/spotiflyer/database/DownloadRecord.kt
new file mode 100644
index 00000000..0a734771
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/database/DownloadRecord.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.database
+
+import android.os.Parcelable
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.Index
+import androidx.room.PrimaryKey
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+@Entity(
+ tableName = "download_record_table",
+ indices = [Index(value = ["link"], unique = true)]
+)
+data class DownloadRecord(
+
+ @PrimaryKey(autoGenerate = true)
+ var id:Int = 0,
+
+ @ColumnInfo(name = "type")
+ var type:String,
+
+ @ColumnInfo(name = "name")
+ var name:String,
+
+ @ColumnInfo(name = "link")
+ var link:String,
+
+ @ColumnInfo(name = "coverUrl")
+ var coverUrl:String,
+
+ @ColumnInfo(name = "totalFiles")
+ var totalFiles:Int = 1,
+):Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/database/DownloadRecordDatabase.kt b/app/src/main/java/com/shabinder/spotiflyer/database/DownloadRecordDatabase.kt
new file mode 100644
index 00000000..98d84a09
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/database/DownloadRecordDatabase.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.database
+
+import android.content.Context
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
+
+@Database(entities = [DownloadRecord::class], version = 2, exportSchema = false)
+abstract class DownloadRecordDatabase:RoomDatabase() {
+
+ abstract val databaseDAO: DatabaseDAO
+
+ companion object {
+ @Volatile
+ private var INSTANCE: DownloadRecordDatabase? = null
+
+ fun getInstance(context: Context): DownloadRecordDatabase {
+ synchronized(this) {
+ var instance = INSTANCE
+ if (instance == null) {
+ instance = Room.databaseBuilder(
+ context.applicationContext,
+ DownloadRecordDatabase::class.java,
+ "download_record_database")
+ .fallbackToDestructiveMigration()
+ .build()
+
+ INSTANCE = instance
+ }
+
+ return instance
+ }
+
+ }
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/downloadHelper/YoutubeProvider.kt b/app/src/main/java/com/shabinder/spotiflyer/downloadHelper/YoutubeProvider.kt
new file mode 100644
index 00000000..444d11df
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/downloadHelper/YoutubeProvider.kt
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.downloadHelper
+
+import android.annotation.SuppressLint
+import com.beust.klaxon.JsonArray
+import com.beust.klaxon.JsonObject
+import com.beust.klaxon.Parser
+import com.shabinder.spotiflyer.models.YoutubeTrack
+import me.xdrop.fuzzywuzzy.FuzzySearch
+import kotlin.math.absoluteValue
+
+/*
+* Thanks To https://github.com/spotDL/spotify-downloader
+* */
+fun getYTTracks(response: String):List{
+ val youtubeTracks = mutableListOf()
+
+ val stringBuilder: StringBuilder = StringBuilder(response)
+ val responseObj: JsonObject = Parser.default().parse(stringBuilder) as JsonObject
+ val contentBlocks = responseObj.obj("contents")?.obj("sectionListRenderer")?.array("contents")
+ val resultBlocks = mutableListOf>()
+ if (contentBlocks != null) {
+ for (cBlock in contentBlocks){
+ /**
+ *Ignore user-suggestion
+ *The 'itemSectionRenderer' field is for user notices (stuff like - 'showing
+ *results for xyz, search for abc instead') we have no use for them, the for
+ *loop below if throw a keyError if we don't ignore them
+ */
+ if(cBlock.containsKey("itemSectionRenderer")){
+ continue
+ }
+
+ for(contents in cBlock.obj("musicShelfRenderer")?.array("contents") ?: listOf()){
+ /**
+ * apparently content Blocks without an 'overlay' field don't have linkBlocks
+ * I have no clue what they are and why there even exist
+ *
+ if(!contents.containsKey("overlay")){
+ println(contents)
+ continue
+ TODO check and correct
+ }*/
+
+ val result = contents.obj("musicResponsiveListItemRenderer")
+ ?.array("flexColumns")
+
+ //Add the linkBlock
+ val linkBlock = contents.obj("musicResponsiveListItemRenderer")
+ ?.obj("overlay")
+ ?.obj("musicItemThumbnailOverlayRenderer")
+ ?.obj("content")
+ ?.obj("musicPlayButtonRenderer")
+ ?.obj("playNavigationEndpoint")
+
+ // detailsBlock is always a list, so we just append the linkBlock to it
+ // instead of carrying along all the other junk from "musicResponsiveListItemRenderer"
+ linkBlock?.let { result?.add(it) }
+ result?.let { resultBlocks.add(it) }
+ }
+ }
+
+ /* We only need results that are Songs or Videos, so we filter out the rest, since
+ ! Songs and Videos are supplied with different details, extracting all details from
+ ! both is just carrying on redundant data, so we also have to selectively extract
+ ! relevant details. What you need to know to understand how we do that here:
+ !
+ ! Songs details are ALWAYS in the following order:
+ ! 0 - Name
+ ! 1 - Type (Song)
+ ! 2 - com.shabinder.spotiflyer.models.gaana.Artist
+ ! 3 - Album
+ ! 4 - Duration (mm:ss)
+ !
+ ! Video details are ALWAYS in the following order:
+ ! 0 - Name
+ ! 1 - Type (Video)
+ ! 2 - Channel
+ ! 3 - Viewers
+ ! 4 - Duration (hh:mm:ss)
+ !
+ ! We blindly gather all the details we get our hands on, then
+ ! cherrypick the details we need based on their index numbers,
+ ! we do so only if their Type is 'Song' or 'Video
+ */
+
+ for(result in resultBlocks){
+
+ // Blindly gather available details
+ val availableDetails = mutableListOf()
+
+ /*
+ Filter Out dummies here itself
+ ! 'musicResponsiveListItemFlexColumnRenderer' should have more that one
+ ! sub-block, if not its a dummy, why does the YTM response contain dummies?
+ ! I have no clue. We skip these.
+
+ ! Remember that we appended the linkBlock to result, treating that like the
+ ! other constituents of a result block will lead to errors, hence the 'in
+ ! result[:-1] ,i.e., skip last element in array '
+ */
+ for(detail in result.subList(0,result.size-1)){
+ if(detail.obj("musicResponsiveListItemFlexColumnRenderer")?.size!! < 2) continue
+
+ // if not a dummy, collect All Variables
+ detail.obj("musicResponsiveListItemFlexColumnRenderer")
+ ?.obj("text")
+ ?.array("runs")?.get(0)?.get("text")?.let {
+ availableDetails.add(
+ it.toString()
+ )
+ }
+ }
+ //log("Text Api",availableDetails.toString())
+ /*
+ ! Filter Out non-Song/Video results and incomplete results here itself
+ ! From what we know about detail order, note that [1] - indicate result type
+ */
+ if ( availableDetails.size == 5 && availableDetails[1] in listOf("Song","Video") ){
+
+ // skip if result is in hours instead of minutes (no song is that long)
+ if(availableDetails[4].split(':').size != 2) continue //Has Been Giving Issues
+
+ /*
+ ! grab Video ID
+ ! this is nested as [playlistEndpoint/watchEndpoint][videoId/playlistId/...]
+ ! so hardcoding the dict keys for data look up is an ardours process, since
+ ! the sub-block pattern is fixed even though the key isn't, we just
+ ! reference the dict keys by index
+ */
+
+ val videoId:String = result.last().obj("watchEndpoint")?.get("videoId") as String
+ val ytTrack = YoutubeTrack(
+ name = availableDetails[0],
+ type = availableDetails[1],
+ artist = availableDetails[2],
+ duration = availableDetails[4],
+ videoId = videoId
+ )
+ youtubeTracks.add(ytTrack)
+ }
+ }
+ }
+
+ return youtubeTracks
+}
+
+@SuppressLint("DefaultLocale")
+fun sortByBestMatch(ytTracks:List,
+ trackName:String,
+ trackArtists:List,
+ trackDurationSec:Int,
+ ):Map{
+ /*
+ * "linksWithMatchValue" is map with Youtube VideoID and its rating/match with 100 as Max Value
+ **/
+ val linksWithMatchValue = mutableMapOf()
+
+ for (result in ytTracks){
+
+ // LoweCasing Name to match Properly
+ // most song results on youtube go by $artist - $songName or artist1/artist2
+ var hasCommonWord = false
+
+ val resultName = result.name?.toLowerCase()?.replace("-"," ")?.replace("/"," ") ?: ""
+ val trackNameWords = trackName.toLowerCase().split(" ")
+
+ for (nameWord in trackNameWords){
+ if (nameWord.isNotBlank() && FuzzySearch.partialRatio(nameWord,resultName) > 85) hasCommonWord = true
+ }
+
+ // Skip this Result if No Word is Common in Name
+ if (!hasCommonWord) {
+ //log("YT Api Removing", result.toString())
+ continue
+ }
+
+
+ // Find artist match
+ // Will Be Using Fuzzy Search Because YT Spelling might be mucked up
+ // match = (no of artist names in result) / (no. of artist names on spotify) * 100
+ var artistMatchNumber = 0
+
+ if(result.type == "Song"){
+ for (artist in trackArtists){
+ if(FuzzySearch.ratio(artist.toLowerCase(),result.artist?.toLowerCase()) > 85)
+ artistMatchNumber++
+ }
+ }else{//i.e. is a Video
+ for (artist in trackArtists) {
+ if(FuzzySearch.partialRatio(artist.toLowerCase(),result.name?.toLowerCase()) > 85)
+ artistMatchNumber++
+ }
+ }
+
+ if(artistMatchNumber == 0) {
+ //log("YT Api Removing", result.toString())
+ continue
+ }
+
+ val artistMatch = (artistMatchNumber / trackArtists.size ) * 100
+
+ // Duration Match
+ /*! time match = 100 - (delta(duration)**2 / original duration * 100)
+ ! difference in song duration (delta) is usually of the magnitude of a few
+ ! seconds, we need to amplify the delta if it is to have any meaningful impact
+ ! wen we calculate the avg match value*/
+ val difference = result.duration?.split(":")?.get(0)?.toInt()?.times(60)
+ ?.plus(result.duration?.split(":")?.get(1)?.toInt()?:0)
+ ?.minus(trackDurationSec)?.absoluteValue ?: 0
+ val nonMatchValue :Float= ((difference*difference).toFloat()/trackDurationSec.toFloat())
+ val durationMatch = 100 - (nonMatchValue*100)
+
+ val avgMatch = (artistMatch + durationMatch)/2
+ linksWithMatchValue[result.videoId.toString()] = avgMatch.toInt()
+ }
+ //log("YT Api Result", "$trackName - $linksWithMatchValue")
+ return linksWithMatchValue.toList().sortedByDescending { it.second }.toMap()
+}
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/DownloadObject.kt b/app/src/main/java/com/shabinder/spotiflyer/models/DownloadObject.kt
new file mode 100644
index 00000000..14001ee9
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/DownloadObject.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models
+
+import android.os.Parcelable
+import com.shabinder.spotiflyer.models.spotify.Source
+import kotlinx.parcelize.Parcelize
+import java.io.File
+
+@Parcelize
+data class TrackDetails(
+ var title:String,
+ var artists:List,
+ var durationSec:Int,
+ var albumName:String?=null,
+ var year:String?=null,
+ var comment:String?=null,
+ var lyrics:String?=null,
+ var trackUrl:String?=null,
+ var albumArt: File,
+ var albumArtURL: String,
+ var source: Source,
+ var downloaded: DownloadStatus = DownloadStatus.NotDownloaded,
+ var progress: Int = 0,
+ var outputFile: String,
+ var videoID:String? = null
+):Parcelable
+
+enum class DownloadStatus{
+ Downloaded,
+ Downloading,
+ Queued,
+ NotDownloaded,
+ Converting,
+ Failed
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/Optional.kt b/app/src/main/java/com/shabinder/spotiflyer/models/Optional.kt
new file mode 100644
index 00000000..2257df5d
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/Optional.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class Optional(val value: T?)
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/YoutubeTrack.kt b/app/src/main/java/com/shabinder/spotiflyer/models/YoutubeTrack.kt
new file mode 100644
index 00000000..d82ab05c
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/YoutubeTrack.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class YoutubeTrack(
+ var name: String? = null,
+ var type: String? = null, // Song / Video
+ var artist: String? = null,
+ var duration:String? = null,
+ var videoId: String? = null
+):Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/gaana/Artist.kt b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/Artist.kt
new file mode 100644
index 00000000..49c27d04
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/Artist.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.gaana
+
+import com.squareup.moshi.Json
+
+data class Artist (
+ val popularity : Int,
+ val seokey : String,
+ val name : String,
+ @Json(name = "artwork_175x175")var artworkLink :String?
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/gaana/CustomArtworks.kt b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/CustomArtworks.kt
new file mode 100644
index 00000000..f73b5510
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/CustomArtworks.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.gaana
+
+import com.squareup.moshi.Json
+
+data class CustomArtworks (
+ @Json(name = "40x40") val size_40p : String,
+ @Json(name = "80x80") val size_80p : String,
+ @Json(name = "110x110")val size_110p : String,
+ @Json(name = "175x175")val size_175p : String,
+ @Json(name = "480x480")val size_480p : String,
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaAlbum.kt b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaAlbum.kt
new file mode 100644
index 00000000..354e9e4d
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaAlbum.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.gaana
+
+data class GaanaAlbum (
+ val tracks : List,
+ val count : Int,
+ val custom_artworks : CustomArtworks,
+ val release_year : Int,
+ val favorite_count : Int,
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaArtistDetails.kt b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaArtistDetails.kt
new file mode 100644
index 00000000..17d57ac3
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaArtistDetails.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.gaana
+
+data class GaanaArtistDetails(
+ val artist : List,
+ val count : Int,
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaArtistTracks.kt b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaArtistTracks.kt
new file mode 100644
index 00000000..2f31fb01
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaArtistTracks.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.gaana
+
+data class GaanaArtistTracks(
+ val count : Int,
+ val tracks : List
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaPlaylist.kt b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaPlaylist.kt
new file mode 100644
index 00000000..b64ca02e
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaPlaylist.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.gaana
+
+data class GaanaPlaylist (
+ val modified_on : String,
+ val count : Int,
+ val created_on : String,
+ val favorite_count : Int,
+ val tracks : List,
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaSong.kt b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaSong.kt
new file mode 100644
index 00000000..8acbff96
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaSong.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.gaana
+
+data class GaanaSong(
+ val tracks : List
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaTrack.kt b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaTrack.kt
new file mode 100644
index 00000000..f4a0b94d
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/GaanaTrack.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.gaana
+
+import com.shabinder.spotiflyer.models.DownloadStatus
+import com.squareup.moshi.Json
+
+data class GaanaTrack (
+ val tags : List?,
+ val seokey : String,
+ val albumseokey : String?,
+ val track_title : String,
+ val album_title : String?,
+ val language : String?,
+ val duration: Int,
+ @Json(name = "artwork_large") val artworkLink : String,
+ val artist : List,
+ @Json(name = "gener") val genre : List?,
+ val lyrics_url : String?,
+ val youtube_id : String?,
+ val total_favourite_count : Int?,
+ val release_date : String?,
+ val play_ct : String?,
+ val secondary_language : String?,
+ var downloaded: DownloadStatus? = DownloadStatus.NotDownloaded
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/gaana/Genre.kt b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/Genre.kt
new file mode 100644
index 00000000..0f4fcd21
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/Genre.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.gaana
+
+data class Genre (
+ val genre_id : Int,
+ val name : String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/gaana/Tags.kt b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/Tags.kt
new file mode 100644
index 00000000..c348a321
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/gaana/Tags.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.gaana
+
+data class Tags (
+ val tag_id : Int,
+ val tag_name : String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Album.kt b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Album.kt
new file mode 100644
index 00000000..b8eec7b9
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Album.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.spotify
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class Album(
+ var album_type: String? = null,
+ var artists: List? = null,
+ var available_markets: List? = null,
+ var copyrights: List? = null,
+ var external_ids: Map? = null,
+ var external_urls: Map? = null,
+ var genres: List? = null,
+ var href: String? = null,
+ var id: String? = null,
+ var images: List? = null,
+ var label :String? = null,
+ var name: String? = null,
+ var popularity: Int? = null,
+ var release_date: String? = null,
+ var release_date_precision: String? = null,
+ var tracks: PagingObjectTrack? = null,
+ var type: String? = null,
+ var uri: String? = null):Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Artist.kt b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Artist.kt
new file mode 100644
index 00000000..6b7d2050
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Artist.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.spotify
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class Artist(
+ var external_urls: Map? = null,
+ var href: String? = null,
+ var id: String? = null,
+ var name: String? = null,
+ var type: String? = null,
+ var uri: String? = null):Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Copyright.kt b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Copyright.kt
new file mode 100644
index 00000000..ace8f1cc
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Copyright.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.spotify
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class Copyright(
+ var text: String? = null,
+ var type: String? = null):Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Episodes.kt b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Episodes.kt
new file mode 100644
index 00000000..cb502c13
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Episodes.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.spotify
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class Episodes(
+ var audio_preview_url:String?,
+ var description:String?,
+ var duration_ms:Int?,
+ var explicit:Boolean?,
+ var external_urls:Map?,
+ var href:String?,
+ var id:String?,
+ var images:List?,
+ var is_externally_hosted:Boolean?,
+ var is_playable:Boolean?,
+ var language:String?,
+ var languages:List?,
+ var name:String?,
+ var release_date:String?,
+ var release_date_precision:String?,
+ var type:String?,
+ var uri:String
+): Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Followers.kt b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Followers.kt
new file mode 100644
index 00000000..8a3ad1a0
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Followers.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.spotify
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class Followers(
+ var href: String? = null,
+ var total: Int? = null):Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Image.kt b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Image.kt
new file mode 100644
index 00000000..f2b1e355
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/Image.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.spotify
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class Image(
+ var width: Int? = null,
+ var height: Int? = null,
+ var url: String? = null):Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/spotify/LinkedTrack.kt b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/LinkedTrack.kt
new file mode 100644
index 00000000..ce1745d3
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/LinkedTrack.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.spotify
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class LinkedTrack(
+ var external_urls: Map? = null,
+ var href: String? = null,
+ var id: String? = null,
+ var type: String? = null,
+ var uri: String? = null): Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/spotify/PagingObjectPlaylistTrack.kt b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/PagingObjectPlaylistTrack.kt
new file mode 100644
index 00000000..55c7b000
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/PagingObjectPlaylistTrack.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.spotify
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class PagingObjectPlaylistTrack(
+ var href: String? = null,
+ var items: List? = null,
+ var limit: Int = 0,
+ var next: String? = null,
+ var offset: Int = 0,
+ var previous: String? = null,
+ var total: Int = 0): Parcelable
\ No newline at end of file
diff --git a/app/src/main/java/com/shabinder/spotiflyer/models/spotify/PagingObjectTrack.kt b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/PagingObjectTrack.kt
new file mode 100644
index 00000000..617c9ead
--- /dev/null
+++ b/app/src/main/java/com/shabinder/spotiflyer/models/spotify/PagingObjectTrack.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 Shabinder Singh
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.shabinder.spotiflyer.models.spotify
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class PagingObjectTrack(
+ var href: String? = null,
+ var items: List