Dependencies Handling at Lower Level.

This commit is contained in:
Shabinder 2020-11-12 00:03:47 +05:30
parent c58f73be1d
commit 04b6f13b22
14 changed files with 171 additions and 179 deletions

View File

@ -36,6 +36,7 @@ import androidx.navigation.findNavController
import com.github.javiersantos.appupdater.AppUpdater
import com.github.javiersantos.appupdater.enums.UpdateFrom
import com.shabinder.spotiflyer.databinding.MainActivityBinding
import com.shabinder.spotiflyer.downloadHelper.DownloadHelper
import com.shabinder.spotiflyer.networking.SpotifyService
import com.shabinder.spotiflyer.networking.SpotifyServiceTokenRequest
import com.shabinder.spotiflyer.utils.*
@ -57,9 +58,9 @@ import javax.inject.Inject
class MainActivity : AppCompatActivity(){
private var spotifyService : SpotifyService? = null
private lateinit var binding: MainActivityBinding
lateinit var snackBarAnchor: View
private lateinit var sharedViewModel: SharedViewModel
private lateinit var navController: NavController
lateinit var snackBarAnchor: View
lateinit var navController: NavController
@Inject lateinit var moshi: Moshi
@Inject lateinit var spotifyServiceTokenRequest: SpotifyServiceTokenRequest
@ -72,6 +73,7 @@ class MainActivity : AppCompatActivity(){
sharedViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
navController = findNavController(R.id.navHostFragment)
snackBarAnchor = binding.snackBarPosition
DownloadHelper.youtubeMusicApi = sharedViewModel.youtubeMusicApi
authenticateSpotify()
@ -80,7 +82,6 @@ class MainActivity : AppCompatActivity(){
checkIfLatestVersion()
createDirectories()
Log.i("Connection Status", isOnline().toString())
//starting Notification and Downloader Service!
startService(this)

View File

@ -17,14 +17,18 @@
package com.shabinder.spotiflyer
import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.shabinder.spotiflyer.networking.SpotifyService
import com.shabinder.spotiflyer.networking.YoutubeMusicApi
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
class SharedViewModel : ViewModel() {
class SharedViewModel @ViewModelInject constructor(
val youtubeMusicApi: YoutubeMusicApi
) : ViewModel() {
var intentString = MutableLiveData<String>()
var spotifyService = MutableLiveData<SpotifyService>()

View File

@ -17,6 +17,7 @@
package com.shabinder.spotiflyer.recyclerView
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -46,6 +47,7 @@ class TrackListAdapter(private val viewModel :TrackListViewModel): ListAdapter<T
return ViewHolder(binding)
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = getItem(position)
if(itemCount == 1){ holder.binding.imageUrl.visibility = View.GONE}else{
@ -100,8 +102,8 @@ class TrackListAdapter(private val viewModel :TrackListViewModel): ListAdapter<T
}
}
holder.binding.trackName.text = "${if(item.title.length > 17){"${item.title.subSequence(0,16)}..."}else{item.title}}"
holder.binding.artist.text = "${item.artists.get(0)}..."
holder.binding.trackName.text = if(item.title.length > 20){"${item.title.subSequence(0,18)}..."}else{item.title}
holder.binding.artist.text = "${item.artists.firstOrNull()}..."
holder.binding.duration.text = "${item.durationSec/60} minutes, ${item.durationSec%60} sec"
}

View File

@ -24,25 +24,18 @@ import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.SimpleItemAnimator
import com.shabinder.spotiflyer.SharedViewModel
import com.shabinder.spotiflyer.downloadHelper.DownloadHelper
import com.shabinder.spotiflyer.models.DownloadStatus
import com.shabinder.spotiflyer.models.spotify.Source
import com.shabinder.spotiflyer.networking.GaanaInterface
import com.shabinder.spotiflyer.networking.YoutubeMusicApi
import com.shabinder.spotiflyer.recyclerView.TrackListAdapter
import com.shabinder.spotiflyer.utils.*
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject
@AndroidEntryPoint
class GaanaFragment : TrackListFragment<GaanaViewModel,GaanaFragmentArgs>() {
@Inject lateinit var youtubeMusicApi: YoutubeMusicApi
@Inject lateinit var gaanaInterface: GaanaInterface
override lateinit var viewModel: GaanaViewModel
override lateinit var adapter: TrackListAdapter
override var source: Source = Source.Gaana
@ -53,8 +46,8 @@ class GaanaFragment : TrackListFragment<GaanaViewModel,GaanaFragmentArgs>() {
savedInstanceState: Bundle?
): View? {
super.onCreateView(inflater, container, savedInstanceState)
initializeAll()
viewModel = ViewModelProvider(this).get(GaanaViewModel::class.java)
adapter = TrackListAdapter(viewModel)
val gaanaLink = GaanaFragmentArgs.fromBundle(requireArguments()).link.substringAfter("gaana.com/")
//Link Schema: https://gaana.com/type/link
@ -112,21 +105,4 @@ class GaanaFragment : TrackListFragment<GaanaViewModel,GaanaFragmentArgs>() {
}
return binding.root
}
/**
* Basic Initialization
**/
private fun initializeAll() {
sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java)
viewModel = ViewModelProvider(this).get(GaanaViewModel::class.java)
viewModel.gaanaInterface = gaanaInterface
adapter = TrackListAdapter(viewModel)
DownloadHelper.youtubeMusicApi = youtubeMusicApi
DownloadHelper.sharedViewModel = sharedViewModel
DownloadHelper.statusBar = binding.statusBar
binding.trackList.adapter = adapter
(binding.trackList.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
}
}

View File

@ -18,13 +18,12 @@
package com.shabinder.spotiflyer.ui.gaana
import android.os.Environment
import android.util.Log
import androidx.hilt.lifecycle.ViewModelInject
import com.shabinder.spotiflyer.database.DatabaseDAO
import com.shabinder.spotiflyer.database.DownloadRecord
import com.shabinder.spotiflyer.models.DownloadStatus
import com.shabinder.spotiflyer.models.TrackDetails
import com.shabinder.spotiflyer.models.gaana.*
import com.shabinder.spotiflyer.models.gaana.GaanaTrack
import com.shabinder.spotiflyer.models.spotify.Source
import com.shabinder.spotiflyer.networking.GaanaInterface
import com.shabinder.spotiflyer.utils.Provider
@ -35,18 +34,20 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
class GaanaViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO) : TrackListViewModel(){
class GaanaViewModel @ViewModelInject constructor(
val databaseDAO: DatabaseDAO,
val gaanaInterface : GaanaInterface
) : TrackListViewModel(){
override var folderType:String = ""
override var subFolder:String = ""
var gaanaInterface : GaanaInterface? = null
val gaanaPlaceholderImageUrl = "https://a10.gaanacdn.com/images/social/gaana_social.jpg"
private val gaanaPlaceholderImageUrl = "https://a10.gaanacdn.com/images/social/gaana_social.jpg"
fun gaanaSearch(type:String,link:String){
when(type){
"song" -> {
uiScope.launch {
getGaanaSong(link)?.tracks?.firstOrNull()?.also {
gaanaInterface.getGaanaSong(seokey = link).value?.tracks?.firstOrNull()?.also {
folderType = "Tracks"
if(File(finalOutputDir(it.track_title,folderType,subFolder)).exists()){//Download Already Present!!
it.downloaded = DownloadStatus.Downloaded
@ -72,7 +73,7 @@ class GaanaViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO)
}
"album" -> {
uiScope.launch {
getGaanaAlbum(link)?.also {
gaanaInterface.getGaanaAlbum(seokey = link).value?.also {
folderType = "Albums"
subFolder = link
it.tracks.forEach { track ->
@ -99,7 +100,7 @@ class GaanaViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO)
}
"playlist" -> {
uiScope.launch {
getGaanaPlaylist(link)?.also {
gaanaInterface.getGaanaPlaylist(seokey = link).value?.also {
folderType = "Playlists"
subFolder = link
it.tracks.forEach {track ->
@ -129,11 +130,11 @@ class GaanaViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO)
uiScope.launch {
folderType = "Artist"
subFolder = link
val artistDetails = getGaanaArtistDetails(link)?.artist?.firstOrNull()?.also {
val artistDetails = gaanaInterface.getGaanaArtistDetails(seokey = link).value?.artist?.firstOrNull()?.also {
title.value = it.name
coverUrl.value = it.artworkLink
}
getGaanaArtistTracks(link)?.also {
gaanaInterface.getGaanaArtistTracks(seokey = link).value?.also {
it.tracks.forEach {track ->
if(File(finalOutputDir(track.track_title,folderType,subFolder)).exists()){//Download Already Present!!
track.downloaded = DownloadStatus.Downloaded
@ -175,25 +176,4 @@ class GaanaViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO)
albumArtURL = it.artworkLink
)
}.toMutableList()
private suspend fun getGaanaSong(songLink:String): GaanaSong?{
Log.i("Requesting","https://gaana.com/song/$songLink")
return gaanaInterface?.getGaanaSong(seokey = songLink)?.value
}
private suspend fun getGaanaAlbum(albumLink:String): GaanaAlbum?{
Log.i("Requesting","https://gaana.com/album/$albumLink")
return gaanaInterface?.getGaanaAlbum(seokey = albumLink)?.value
}
private suspend fun getGaanaPlaylist(link:String): GaanaPlaylist?{
Log.i("Requesting","https://gaana.com/playlist/$link")
return gaanaInterface?.getGaanaPlaylist(seokey = link)?.value
}
private suspend fun getGaanaArtistDetails(link:String): GaanaArtistDetails?{
Log.i("Requesting","https://gaana.com/artist/$link")
return gaanaInterface?.getGaanaArtistDetails(seokey = link)?.value
}
private suspend fun getGaanaArtistTracks(link:String,limit:Int = 50): GaanaArtistTracks?{
Log.i("Requesting","Tracks of: https://gaana.com/artist/$link")
return gaanaInterface?.getGaanaArtistTracks(seokey = link,limit = limit)?.value
}
}

View File

@ -25,23 +25,19 @@ import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.SimpleItemAnimator
import com.shabinder.spotiflyer.downloadHelper.DownloadHelper
import com.shabinder.spotiflyer.models.DownloadStatus
import com.shabinder.spotiflyer.models.spotify.Source
import com.shabinder.spotiflyer.networking.YoutubeMusicApi
import com.shabinder.spotiflyer.recyclerView.TrackListAdapter
import com.shabinder.spotiflyer.utils.*
import com.shabinder.spotiflyer.utils.Provider.mainActivity
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject
@AndroidEntryPoint
class SpotifyFragment : TrackListFragment<SpotifyViewModel,SpotifyFragmentArgs>() {
@Inject lateinit var youtubeMusicApi: YoutubeMusicApi
override lateinit var viewModel: SpotifyViewModel
override lateinit var adapter: TrackListAdapter
override var source: Source = Source.Spotify
@ -132,10 +128,5 @@ class SpotifyFragment : TrackListFragment<SpotifyViewModel,SpotifyFragmentArgs>(
sharedViewModel.spotifyService.observe(viewLifecycleOwner, {
this.viewModel.spotifyService = it
})
DownloadHelper.youtubeMusicApi = youtubeMusicApi
DownloadHelper.sharedViewModel = sharedViewModel
DownloadHelper.statusBar = binding.statusBar
binding.trackList.adapter = adapter
(binding.trackList.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
}
}

View File

@ -24,7 +24,10 @@ import com.shabinder.spotiflyer.database.DatabaseDAO
import com.shabinder.spotiflyer.database.DownloadRecord
import com.shabinder.spotiflyer.models.DownloadStatus
import com.shabinder.spotiflyer.models.TrackDetails
import com.shabinder.spotiflyer.models.spotify.*
import com.shabinder.spotiflyer.models.spotify.Album
import com.shabinder.spotiflyer.models.spotify.Image
import com.shabinder.spotiflyer.models.spotify.Source
import com.shabinder.spotiflyer.models.spotify.Track
import com.shabinder.spotiflyer.networking.SpotifyService
import com.shabinder.spotiflyer.utils.Provider
import com.shabinder.spotiflyer.utils.TrackListViewModel
@ -34,7 +37,9 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO) : TrackListViewModel(){
class SpotifyViewModel @ViewModelInject constructor(
val databaseDAO: DatabaseDAO,
) : TrackListViewModel(){
override var folderType:String = ""
override var subFolder:String = ""
@ -42,105 +47,148 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
var spotifyService : SpotifyService? = null
fun spotifySearch(type:String,link: String){
when (type) {
"track" -> {
uiScope.launch {
getTrackDetails(link)?.also {
uiScope.launch {
when (type) {
"track" -> {
spotifyService?.getTrack(link)?.value?.also {
folderType = "Tracks"
if(File(finalOutputDir(it.name,folderType,subFolder)).exists()){//Download Already Present!!
if (File(
finalOutputDir(
it.name,
folderType,
subFolder
)
).exists()
) {//Download Already Present!!
it.downloaded = DownloadStatus.Downloaded
}
trackList.value = listOf(it).toTrackDetailsList()
title.value = it.name
coverUrl.value = it.album!!.images?.elementAtOrNull(1)?.url ?: it.album!!.images?.elementAtOrNull(0)?.url
withContext(Dispatchers.IO){
databaseDAO.insert(DownloadRecord(
type = "Track",
name = title.value!!,
link = "https://open.spotify.com/$type/$link",
coverUrl = coverUrl.value!!,
totalFiles = 1,
downloaded = it.downloaded == DownloadStatus.Downloaded,
directory = finalOutputDir(it.name,folderType,subFolder)
))
coverUrl.value = it.album!!.images?.elementAtOrNull(1)?.url
?: it.album!!.images?.elementAtOrNull(0)?.url
withContext(Dispatchers.IO) {
databaseDAO.insert(
DownloadRecord(
type = "Track",
name = title.value!!,
link = "https://open.spotify.com/$type/$link",
coverUrl = coverUrl.value!!,
totalFiles = 1,
downloaded = it.downloaded == DownloadStatus.Downloaded,
directory = finalOutputDir(it.name, folderType, subFolder)
)
)
}
}
}
}
"album" -> {
uiScope.launch {
val albumObject = getAlbumDetails(link)
"album" -> {
val albumObject = spotifyService?.getAlbum(link)?.value
folderType = "Albums"
subFolder = albumObject?.name.toString()
albumObject?.tracks?.items?.forEach {
if(File(finalOutputDir(it.name!!,folderType,subFolder)).exists()){//Download Already Present!!
if (File(
finalOutputDir(
it.name!!,
folderType,
subFolder
)
).exists()
) {//Download Already Present!!
it.downloaded = DownloadStatus.Downloaded
}
it.album = Album(images = listOf(Image(url = albumObject.images?.elementAtOrNull(1)?.url ?: albumObject.images?.elementAtOrNull(0)?.url )))
it.album = Album(
images = listOf(
Image(
url = albumObject.images?.elementAtOrNull(1)?.url
?: albumObject.images?.elementAtOrNull(0)?.url
)
)
)
}
trackList.value = albumObject?.tracks?.items?.toTrackDetailsList()
title.value = albumObject?.name
coverUrl.value = albumObject?.images?.elementAtOrNull(1)?.url ?: albumObject?.images?.elementAtOrNull(0)?.url
withContext(Dispatchers.IO){
databaseDAO.insert(DownloadRecord(
type = "Album",
name = title.value!!,
link = "https://open.spotify.com/$type/$link",
coverUrl = coverUrl.value.toString(),
totalFiles = trackList.value?.size ?: 0,
downloaded = File(finalOutputDir(type = folderType,subFolder = subFolder)).listFiles()?.size == trackList.value?.size,
directory = finalOutputDir(type = folderType,subFolder = subFolder)
))
coverUrl.value = albumObject?.images?.elementAtOrNull(1)?.url
?: albumObject?.images?.elementAtOrNull(0)?.url
withContext(Dispatchers.IO) {
databaseDAO.insert(
DownloadRecord(
type = "Album",
name = title.value!!,
link = "https://open.spotify.com/$type/$link",
coverUrl = coverUrl.value.toString(),
totalFiles = trackList.value?.size ?: 0,
downloaded = File(
finalOutputDir(
type = folderType,
subFolder = subFolder
)
).listFiles()?.size == trackList.value?.size,
directory = finalOutputDir(type = folderType, subFolder = subFolder)
)
)
}
}
}
"playlist" -> {
uiScope.launch {
val playlistObject = getPlaylistDetails(link)
"playlist" -> {
val playlistObject = spotifyService?.getPlaylist(link)?.value
folderType = "Playlists"
subFolder = playlistObject?.name.toString()
val tempTrackList = mutableListOf<Track>()
Log.i("Tracks Fetched",playlistObject?.tracks?.items?.size.toString())
Log.i("Tracks Fetched", playlistObject?.tracks?.items?.size.toString())
playlistObject?.tracks?.items?.forEach {
it.track?.let {
it1 -> if(File(finalOutputDir(it1.name!!,folderType,subFolder)).exists()){//Download Already Present!!
it1.downloaded = DownloadStatus.Downloaded
}
it.track?.let { it1 ->
if (File(
finalOutputDir(
it1.name!!,
folderType,
subFolder
)
).exists()
) {//Download Already Present!!
it1.downloaded = DownloadStatus.Downloaded
}
tempTrackList.add(it1)
}
}
var moreTracksAvailable = !playlistObject?.tracks?.next.isNullOrBlank()
while(moreTracksAvailable){
while (moreTracksAvailable) {
//Check For More Tracks If available
val moreTracks = getPlaylistTrackDetails(link,offset = tempTrackList.size)
moreTracks?.items?.forEach{
val moreTracks = spotifyService?.getPlaylistTracks(link, offset = tempTrackList.size)?.value
moreTracks?.items?.forEach {
it.track?.let { it1 -> tempTrackList.add(it1) }
}
moreTracksAvailable = !moreTracks?.next.isNullOrBlank()
}
Log.i("Total Tracks Fetched",tempTrackList.size.toString())
Log.i("Total Tracks Fetched", tempTrackList.size.toString())
trackList.value = tempTrackList.toTrackDetailsList()
title.value = playlistObject?.name
coverUrl.value = playlistObject?.images?.elementAtOrNull(1)?.url ?: playlistObject?.images?.firstOrNull()?.url.toString()
withContext(Dispatchers.IO){
databaseDAO.insert(DownloadRecord(
type = "Playlist",
name = title.value.toString(),
link = "https://open.spotify.com/$type/$link",
coverUrl = coverUrl.value.toString(),
totalFiles = tempTrackList.size,
downloaded = File(finalOutputDir(type = folderType,subFolder = subFolder)).listFiles()?.size == tempTrackList.size,
directory = finalOutputDir(type = folderType,subFolder = subFolder)
))
coverUrl.value = playlistObject?.images?.elementAtOrNull(1)?.url
?: playlistObject?.images?.firstOrNull()?.url.toString()
withContext(Dispatchers.IO) {
databaseDAO.insert(
DownloadRecord(
type = "Playlist",
name = title.value.toString(),
link = "https://open.spotify.com/$type/$link",
coverUrl = coverUrl.value.toString(),
totalFiles = tempTrackList.size,
downloaded = File(
finalOutputDir(
type = folderType,
subFolder = subFolder
)
).listFiles()?.size == tempTrackList.size,
directory = finalOutputDir(type = folderType, subFolder = subFolder)
)
)
}
}
}
"episode" -> {//TODO
}
"show" -> {//TODO
"episode" -> {//TODO
}
"show" -> {//TODO
}
}
}
}
@ -163,21 +211,4 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
albumArtURL = it.album?.images?.elementAtOrNull(1)?.url ?: it.album?.images?.firstOrNull()?.url.toString()
)
}.toMutableList()
private suspend fun getTrackDetails(trackLink:String): Track?{
Log.i("Requesting","https://api.spotify.com/v1/tracks/$trackLink")
return spotifyService?.getTrack(trackLink)?.value
}
private suspend fun getAlbumDetails(albumLink:String): Album?{
Log.i("Requesting","https://api.spotify.com/v1/albums/$albumLink")
return spotifyService?.getAlbum(albumLink)?.value
}
private suspend fun getPlaylistDetails(link:String): Playlist?{
Log.i("Requesting","https://api.spotify.com/v1/playlists/$link")
return spotifyService?.getPlaylist(link)?.value
}
private suspend fun getPlaylistTrackDetails(link:String,offset:Int = 0,limit:Int = 100): PagingObjectPlaylistTrack?{
Log.i("Requesting","https://api.spotify.com/v1/playlists/$link/tracks?offset=$offset&limit=$limit")
return spotifyService?.getPlaylistTracks(link, offset, limit)?.value
}
}

View File

@ -23,7 +23,6 @@ import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.navArgs
import com.github.kiulian.downloader.YoutubeDownloader
import com.shabinder.spotiflyer.downloadHelper.YTDownloadHelper
import com.shabinder.spotiflyer.models.DownloadStatus
import com.shabinder.spotiflyer.models.spotify.Source
@ -32,7 +31,6 @@ import com.shabinder.spotiflyer.utils.*
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject
private const val sampleDomain2 = "youtu.be"
private const val sampleDomain1 = "youtube.com"
@ -40,7 +38,6 @@ private const val sampleDomain1 = "youtube.com"
@AndroidEntryPoint
class YoutubeFragment : TrackListFragment<YoutubeViewModel,YoutubeFragmentArgs>() {
@Inject lateinit var ytDownloader: YoutubeDownloader
override lateinit var viewModel: YoutubeViewModel
override lateinit var adapter : TrackListAdapter
override var source: Source = Source.YouTube
@ -53,7 +50,6 @@ class YoutubeFragment : TrackListFragment<YoutubeViewModel,YoutubeFragmentArgs>(
super.onCreateView(inflater, container, savedInstanceState)
this.viewModel = ViewModelProvider(this).get(YoutubeViewModel::class.java)
adapter = TrackListAdapter(this.viewModel)
binding.trackList.adapter = adapter
val args = YoutubeFragmentArgs.fromBundle(requireArguments())
val link = args.link
@ -66,7 +62,7 @@ class YoutubeFragment : TrackListFragment<YoutubeViewModel,YoutubeFragmentArgs>(
if(link.contains("playlist",true) || link.contains("list",true)){
// Given Link is of a Playlist
val playlistId = link.substringAfter("?list=").substringAfter("&list=").substringBefore("&")
this.viewModel.getYTPlaylist(playlistId,ytDownloader)
this.viewModel.getYTPlaylist(playlistId)
}else{//Given Link is of a Video
var searchId = "error"
if(link.contains(sampleDomain1,true) ){
@ -76,7 +72,7 @@ class YoutubeFragment : TrackListFragment<YoutubeViewModel,YoutubeFragmentArgs>(
searchId = link.substringAfterLast("/","error")
}
if(searchId != "error") {
this.viewModel.getYTTrack(searchId,ytDownloader)
this.viewModel.getYTTrack(searchId)
}else{showMessage("Your Youtube Link is not of a Video!!")}
}

View File

@ -34,7 +34,10 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
class YoutubeViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO) : TrackListViewModel(){
class YoutubeViewModel @ViewModelInject constructor(
val databaseDAO: DatabaseDAO,
val ytDownloader: YoutubeDownloader
) : TrackListViewModel(){
/*
* YT Album Art Schema
* HI-RES Url: https://i.ytimg.com/vi/$searchId/maxresdefault.jpg"
@ -44,7 +47,7 @@ class YoutubeViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
override var folderType = "YT_Downloads"
override var subFolder = ""
fun getYTPlaylist(searchId:String, ytDownloader:YoutubeDownloader){
fun getYTPlaylist(searchId:String){
if(!isOnline())return
try{
uiScope.launch(Dispatchers.IO) {
@ -102,7 +105,7 @@ class YoutubeViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
}
@SuppressLint("DefaultLocale")
fun getYTTrack(searchId:String, ytDownloader:YoutubeDownloader) {
fun getYTTrack(searchId:String) {
if(!isOnline())return
try{
uiScope.launch(Dispatchers.IO) {

View File

@ -17,9 +17,9 @@
package com.shabinder.spotiflyer.utils
import android.util.Log
import okhttp3.Interceptor
import okhttp3.Protocol
import okhttp3.RequestBody
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
@ -27,13 +27,14 @@ const val NoInternetErrorCode = 222
class NetworkInterceptor: Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
Log.i("Network Requesting",chain.request().url.toString())
return if (!isOnline()){
//No Internet Connection
showNoConnectionAlert()
//Lets Stop the Incoming Request
Response.Builder()
.code(NoInternetErrorCode) // code(200.300) = successful else = unsuccessful
.body("{}".toResponseBody(null)) // Whatever body
.body("{}".toResponseBody(null)) // Empty Object
.protocol(Protocol.HTTP_2)
.message("No Internet Connection")
.request(chain.request())
@ -52,15 +53,7 @@ class NetworkInterceptor: Interceptor {
.message(response.message)
.request(chain.request())
.build()
// chain.proceed(chain.request())
}
}
/*
* Converts REQUEST's Body to String
* */
private fun RequestBody?.bodyToString(): String {
if (this == null) return ""
val buffer = okio.Buffer()
writeTo(buffer)
return buffer.readUtf8()
}
}

View File

@ -49,6 +49,11 @@ import javax.inject.Singleton
@Module
object Provider {
/*
* mainActivity Instance to use whereEver Needed , as Its God Activity.
* (i.e, Active Through out App' Lifecycle )
* */
val mainActivity: MainActivity = MainActivity.getInstance()
val defaultDir = Environment.DIRECTORY_MUSIC + File.separator + "SpotiFlyer" + File.separator

View File

@ -29,9 +29,11 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.NavArgs
import androidx.recyclerview.widget.SimpleItemAnimator
import com.shabinder.spotiflyer.R
import com.shabinder.spotiflyer.SharedViewModel
import com.shabinder.spotiflyer.databinding.TrackListFragmentBinding
import com.shabinder.spotiflyer.downloadHelper.DownloadHelper
import com.shabinder.spotiflyer.models.DownloadStatus
import com.shabinder.spotiflyer.models.TrackDetails
import com.shabinder.spotiflyer.models.spotify.Source
@ -53,7 +55,7 @@ abstract class TrackListFragment<VM : TrackListViewModel , args: NavArgs> : Frag
super.onCreate(savedInstanceState)
if(!isOnline()){
showNoConnectionAlert()
mainActivity.onBackPressed()
mainActivity.navController.popBackStack()
}
sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java)
}
@ -64,11 +66,20 @@ abstract class TrackListFragment<VM : TrackListViewModel , args: NavArgs> : Frag
savedInstanceState: Bundle?
): View? {
binding = TrackListFragmentBinding.inflate(inflater,container,false)
initializeAll()
return binding.root
}
private fun initializeAll() {
DownloadHelper.youtubeMusicApi = sharedViewModel.youtubeMusicApi
DownloadHelper.sharedViewModel = sharedViewModel
DownloadHelper.statusBar = binding.statusBar
(binding.trackList.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.trackList.adapter = adapter
initializeLiveDataObservers()
}
@ -130,7 +141,6 @@ abstract class TrackListFragment<VM : TrackListViewModel , args: NavArgs> : Frag
super.onPause()
requireActivity().unregisterReceiver(updateUIReceiver)
}
private fun checkIfAllDownloaded() {
if(!viewModel.trackList.value!!.any { it.downloaded != DownloadStatus.Downloaded }){
//All Tracks Downloaded
@ -142,5 +152,5 @@ abstract class TrackListFragment<VM : TrackListViewModel , args: NavArgs> : Frag
}
}
}
open fun applicationContext(): Context = requireActivity().applicationContext
}

View File

@ -116,19 +116,19 @@
app:layout_constraintBottom_toTopOf="@+id/cover_image"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/title_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginBottom="22dp"
android:layout_marginBottom="24dp"
android:background="#00000000"
android:fontFamily="@font/raleway_semibold"
android:gravity="end"
android:text='"Loading..."'
android:textAlignment="viewEnd"
android:textColor="#9AB3FF"
android:textSize="28sp"
android:textSize="26sp"
android:textStyle="bold"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"

View File

@ -48,7 +48,7 @@
android:textAllCaps="false"
android:textAppearance="@style/TextAppearance.AppTheme.Headline4"
android:textColor="#9AB3FF"
android:textSize="20sp"
android:textSize="18sp"
app:layout_constraintEnd_toStartOf="@+id/btn_download"
app:layout_constraintStart_toStartOf="@+id/artist"
app:layout_constraintTop_toTopOf="parent" />