mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-11-25 02:14:32 +01:00
Unifying All Things For Better Maintenance and Less Trouble.
This commit is contained in:
parent
cac306e9e8
commit
180a284a54
@ -25,7 +25,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
|
||||||
class SharedViewModel : ViewModel() {
|
class SharedViewModel : ViewModel() {
|
||||||
var intentString = MutableLiveData<String>().apply { value = "" }
|
var intentString = MutableLiveData<String>()
|
||||||
var spotifyService = MutableLiveData<SpotifyService>()
|
var spotifyService = MutableLiveData<SpotifyService>()
|
||||||
|
|
||||||
private var viewModelJob = Job()
|
private var viewModelJob = Job()
|
||||||
|
@ -33,8 +33,8 @@ import com.shabinder.spotiflyer.models.TrackDetails
|
|||||||
import com.shabinder.spotiflyer.networking.YoutubeMusicApi
|
import com.shabinder.spotiflyer.networking.YoutubeMusicApi
|
||||||
import com.shabinder.spotiflyer.networking.makeJsonBody
|
import com.shabinder.spotiflyer.networking.makeJsonBody
|
||||||
import com.shabinder.spotiflyer.utils.*
|
import com.shabinder.spotiflyer.utils.*
|
||||||
import com.shabinder.spotiflyer.utils.Provider.activity
|
|
||||||
import com.shabinder.spotiflyer.utils.Provider.defaultDir
|
import com.shabinder.spotiflyer.utils.Provider.defaultDir
|
||||||
|
import com.shabinder.spotiflyer.utils.Provider.mainActivity
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@ -76,9 +76,9 @@ object DownloadHelper {
|
|||||||
//Delay is Added ,if a request is in processing it may finish
|
//Delay is Added ,if a request is in processing it may finish
|
||||||
Log.i("Spotify Helper","Download Request Sent")
|
Log.i("Spotify Helper","Download Request Sent")
|
||||||
sharedViewModel?.uiScope?.launch (Dispatchers.Main){
|
sharedViewModel?.uiScope?.launch (Dispatchers.Main){
|
||||||
Toast.makeText(activity,"Download Started, Now You can leave the App!", Toast.LENGTH_SHORT).show()
|
Toast.makeText(mainActivity,"Download Started, Now You can leave the App!", Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
startService(activity,downloadList)
|
startService(mainActivity,downloadList)
|
||||||
},5000)
|
},5000)
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@ -121,9 +121,9 @@ object DownloadHelper {
|
|||||||
//Delay is Added ,if a request is in processing it may finish
|
//Delay is Added ,if a request is in processing it may finish
|
||||||
Log.i("Spotify Helper","Download Request Sent")
|
Log.i("Spotify Helper","Download Request Sent")
|
||||||
sharedViewModel?.uiScope?.launch (Dispatchers.Main){
|
sharedViewModel?.uiScope?.launch (Dispatchers.Main){
|
||||||
Toast.makeText(activity,"Download Started, Now You can leave the App!", Toast.LENGTH_SHORT).show()
|
Toast.makeText(mainActivity,"Download Started, Now You can leave the App!", Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
startService(activity,downloadList)
|
startService(mainActivity,downloadList)
|
||||||
},5000)
|
},5000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,8 @@ import android.util.Log
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.shabinder.spotiflyer.models.DownloadObject
|
import com.shabinder.spotiflyer.models.DownloadObject
|
||||||
import com.shabinder.spotiflyer.models.TrackDetails
|
import com.shabinder.spotiflyer.models.TrackDetails
|
||||||
import com.shabinder.spotiflyer.utils.Provider.activity
|
|
||||||
import com.shabinder.spotiflyer.utils.Provider.defaultDir
|
import com.shabinder.spotiflyer.utils.Provider.defaultDir
|
||||||
|
import com.shabinder.spotiflyer.utils.Provider.mainActivity
|
||||||
import com.shabinder.spotiflyer.utils.isOnline
|
import com.shabinder.spotiflyer.utils.isOnline
|
||||||
import com.shabinder.spotiflyer.utils.removeIllegalChars
|
import com.shabinder.spotiflyer.utils.removeIllegalChars
|
||||||
import com.shabinder.spotiflyer.utils.showNoConnectionAlert
|
import com.shabinder.spotiflyer.utils.showNoConnectionAlert
|
||||||
@ -63,8 +63,8 @@ object YTDownloadHelper {
|
|||||||
}
|
}
|
||||||
Log.i("YT Downloader Helper","Download Request Sent")
|
Log.i("YT Downloader Helper","Download Request Sent")
|
||||||
withContext(Dispatchers.Main){
|
withContext(Dispatchers.Main){
|
||||||
Toast.makeText(activity,"Download Started, Now You can leave the App!", Toast.LENGTH_SHORT).show()
|
Toast.makeText(mainActivity,"Download Started, Now You can leave the App!", Toast.LENGTH_SHORT).show()
|
||||||
startService(activity,downloadList)
|
startService(mainActivity,downloadList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -40,6 +40,7 @@ data class TrackDetails(
|
|||||||
var lyrics:String?=null,
|
var lyrics:String?=null,
|
||||||
var trackUrl:String?=null,
|
var trackUrl:String?=null,
|
||||||
var albumArt: File,
|
var albumArt: File,
|
||||||
|
var albumArtURL: String,
|
||||||
var source: Source,
|
var source: Source,
|
||||||
var downloaded: DownloadStatus = DownloadStatus.NotDownloaded
|
var downloaded: DownloadStatus = DownloadStatus.NotDownloaded
|
||||||
):Parcelable
|
):Parcelable
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
package com.shabinder.spotiflyer.models.gaana
|
package com.shabinder.spotiflyer.models.gaana
|
||||||
|
|
||||||
data class GaanaAlbum (
|
data class GaanaAlbum (
|
||||||
val tracks : List<Tracks>,
|
val tracks : List<GaanaTrack>,
|
||||||
val count : Int,
|
val count : Int,
|
||||||
val custom_artworks : CustomArtworks,
|
val custom_artworks : CustomArtworks,
|
||||||
val release_year : Int,
|
val release_year : Int,
|
||||||
|
@ -19,5 +19,5 @@ package com.shabinder.spotiflyer.models.gaana
|
|||||||
|
|
||||||
data class GaanaArtistTracks(
|
data class GaanaArtistTracks(
|
||||||
val count : Int,
|
val count : Int,
|
||||||
val tracks : List<Tracks>
|
val tracks : List<GaanaTrack>
|
||||||
)
|
)
|
@ -18,11 +18,11 @@
|
|||||||
package com.shabinder.spotiflyer.models.gaana
|
package com.shabinder.spotiflyer.models.gaana
|
||||||
|
|
||||||
data class GaanaPlaylist (
|
data class GaanaPlaylist (
|
||||||
val tags : String,
|
val tags : String,
|
||||||
val fromCache : Int,
|
val fromCache : Int,
|
||||||
val modified_on : String,
|
val modified_on : String,
|
||||||
val count : Int,
|
val count : Int,
|
||||||
val created_on : String,
|
val created_on : String,
|
||||||
val favorite_count : Int,
|
val favorite_count : Int,
|
||||||
val tracks : List<Tracks>,
|
val tracks : List<GaanaTrack>,
|
||||||
)
|
)
|
@ -18,5 +18,5 @@
|
|||||||
package com.shabinder.spotiflyer.models.gaana
|
package com.shabinder.spotiflyer.models.gaana
|
||||||
|
|
||||||
data class GaanaSong(
|
data class GaanaSong(
|
||||||
val tracks : List<Tracks>
|
val tracks : List<GaanaTrack>
|
||||||
)
|
)
|
@ -17,9 +17,10 @@
|
|||||||
|
|
||||||
package com.shabinder.spotiflyer.models.gaana
|
package com.shabinder.spotiflyer.models.gaana
|
||||||
|
|
||||||
|
import com.shabinder.spotiflyer.models.DownloadStatus
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
|
|
||||||
data class Tracks (
|
data class GaanaTrack (
|
||||||
val tags : List<Tags>,
|
val tags : List<Tags>,
|
||||||
val seokey : String,
|
val seokey : String,
|
||||||
val albumseokey : String,
|
val albumseokey : String,
|
||||||
@ -35,4 +36,5 @@ data class Tracks (
|
|||||||
val release_date : String,
|
val release_date : String,
|
||||||
val play_ct : String,
|
val play_ct : String,
|
||||||
val secondary_language : String,
|
val secondary_language : String,
|
||||||
|
var downloaded: DownloadStatus? = DownloadStatus.NotDownloaded
|
||||||
)
|
)
|
@ -40,6 +40,6 @@ data class Track(
|
|||||||
var album: Album? = null,
|
var album: Album? = null,
|
||||||
var external_ids: Map<String?, String?>? = null,
|
var external_ids: Map<String?, String?>? = null,
|
||||||
var popularity: Int? = null,
|
var popularity: Int? = null,
|
||||||
var downloaded: DownloadStatus? = DownloadStatus.NotDownloaded
|
var downloaded: DownloadStatus = DownloadStatus.NotDownloaded
|
||||||
):Parcelable
|
):Parcelable
|
||||||
|
|
||||||
|
@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.shabinder.spotiflyer.recyclerView
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.os.Environment
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.shabinder.spotiflyer.R
|
|
||||||
import com.shabinder.spotiflyer.databinding.TrackListItemBinding
|
|
||||||
import com.shabinder.spotiflyer.downloadHelper.DownloadHelper.downloadAllTracks
|
|
||||||
import com.shabinder.spotiflyer.models.DownloadStatus
|
|
||||||
import com.shabinder.spotiflyer.models.TrackDetails
|
|
||||||
import com.shabinder.spotiflyer.models.spotify.Source
|
|
||||||
import com.shabinder.spotiflyer.models.spotify.Track
|
|
||||||
import com.shabinder.spotiflyer.ui.spotify.SpotifyViewModel
|
|
||||||
import com.shabinder.spotiflyer.utils.*
|
|
||||||
import com.shabinder.spotiflyer.utils.Provider.activity
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class SpotifyTrackListAdapter(private val spotifyViewModel : SpotifyViewModel): ListAdapter<Track,SpotifyTrackListAdapter.ViewHolder>(SpotifyTrackDiffCallback()) {
|
|
||||||
|
|
||||||
var isAlbum:Boolean = false
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
|
||||||
val layoutInflater = LayoutInflater.from(parent.context)
|
|
||||||
val binding = TrackListItemBinding.inflate(layoutInflater,parent,false)
|
|
||||||
return ViewHolder(binding)
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
|
||||||
val item = getItem(position)
|
|
||||||
if(itemCount ==1 || isAlbum){
|
|
||||||
holder.binding.imageUrl.visibility = View.GONE}else{
|
|
||||||
spotifyViewModel.uiScope.launch {
|
|
||||||
//Placeholder Set
|
|
||||||
bindImage(holder.binding.imageUrl, item.album?.images?.get(0)?.url, Source.Spotify)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
holder.binding.trackName.text = "${if(item.name!!.length > 17){"${item.name!!.subSequence(0,16)}..."}else{item.name}}"
|
|
||||||
holder.binding.artist.text = "${item.artists?.get(0)?.name?:""}..."
|
|
||||||
holder.binding.duration.text = "${item.duration_ms/1000/60} minutes, ${(item.duration_ms/1000)%60} sec"
|
|
||||||
when (item.downloaded) {
|
|
||||||
DownloadStatus.Downloaded -> {
|
|
||||||
holder.binding.btnDownload.setImageResource(R.drawable.ic_tick)
|
|
||||||
holder.binding.btnDownload.clearAnimation()
|
|
||||||
}
|
|
||||||
DownloadStatus.Downloading -> {
|
|
||||||
holder.binding.btnDownload.setImageResource(R.drawable.ic_refresh)
|
|
||||||
rotateAnim(holder.binding.btnDownload)
|
|
||||||
}
|
|
||||||
DownloadStatus.NotDownloaded -> {
|
|
||||||
holder.binding.btnDownload.setImageResource(R.drawable.ic_arrow)
|
|
||||||
holder.binding.btnDownload.clearAnimation()
|
|
||||||
holder.binding.btnDownload.setOnClickListener{
|
|
||||||
if(!isOnline()){
|
|
||||||
showNoConnectionAlert()
|
|
||||||
return@setOnClickListener
|
|
||||||
}
|
|
||||||
Toast.makeText(activity,"Processing!",Toast.LENGTH_SHORT).show()
|
|
||||||
holder.binding.btnDownload.setImageResource(R.drawable.ic_refresh)
|
|
||||||
rotateAnim(it)
|
|
||||||
item.downloaded = DownloadStatus.Downloading
|
|
||||||
spotifyViewModel.uiScope.launch {
|
|
||||||
val itemList = mutableListOf<TrackDetails>()
|
|
||||||
itemList.add(item.let { track ->
|
|
||||||
val artistsList = mutableListOf<String>()
|
|
||||||
track.artists?.forEach { artist -> artistsList.add(artist!!.name!!) }
|
|
||||||
TrackDetails(
|
|
||||||
title = track.name.toString(),
|
|
||||||
artists = artistsList,
|
|
||||||
durationSec = (track.duration_ms/1000).toInt(),
|
|
||||||
albumArt = File(
|
|
||||||
Environment.getExternalStorageDirectory(),
|
|
||||||
Provider.defaultDir +".Images/" + (track.album?.images?.get(0)?.url.toString()).substringAfterLast('/') + ".jpeg"),
|
|
||||||
albumName = track.album?.name,
|
|
||||||
year = track.album?.release_date,
|
|
||||||
comment = "Genres:${track.album?.genres?.joinToString()}",
|
|
||||||
trackUrl = track.href,
|
|
||||||
source = Source.Spotify
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
downloadAllTracks(spotifyViewModel.folderType,spotifyViewModel.subFolder,itemList)
|
|
||||||
}
|
|
||||||
notifyItemChanged(position)//start showing anim!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class ViewHolder(val binding: TrackListItemBinding) : RecyclerView.ViewHolder(binding.root)
|
|
||||||
}
|
|
||||||
|
|
||||||
class SpotifyTrackDiffCallback: DiffUtil.ItemCallback<Track>(){
|
|
||||||
override fun areItemsTheSame(oldItem: Track, newItem: Track): Boolean {
|
|
||||||
return oldItem.name == newItem.name
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun areContentsTheSame(oldItem: Track, newItem: Track): Boolean {
|
|
||||||
return oldItem == newItem //Downloaded Check
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,39 +22,35 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.shabinder.spotiflyer.R
|
import com.shabinder.spotiflyer.R
|
||||||
import com.shabinder.spotiflyer.databinding.TrackListItemBinding
|
import com.shabinder.spotiflyer.databinding.TrackListItemBinding
|
||||||
|
import com.shabinder.spotiflyer.downloadHelper.DownloadHelper
|
||||||
import com.shabinder.spotiflyer.downloadHelper.YTDownloadHelper
|
import com.shabinder.spotiflyer.downloadHelper.YTDownloadHelper
|
||||||
import com.shabinder.spotiflyer.models.DownloadStatus
|
import com.shabinder.spotiflyer.models.DownloadStatus
|
||||||
import com.shabinder.spotiflyer.models.TrackDetails
|
import com.shabinder.spotiflyer.models.TrackDetails
|
||||||
import com.shabinder.spotiflyer.models.spotify.Source
|
import com.shabinder.spotiflyer.models.spotify.Source
|
||||||
import com.shabinder.spotiflyer.ui.youtube.YoutubeViewModel
|
|
||||||
import com.shabinder.spotiflyer.utils.*
|
import com.shabinder.spotiflyer.utils.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class YoutubeTrackListAdapter(private val youtubeViewModel :YoutubeViewModel): ListAdapter<TrackDetails,SpotifyTrackListAdapter.ViewHolder>(YouTubeTrackDiffCallback()) {
|
class TrackListAdapter(private val viewModel :BaseViewModel): ListAdapter<TrackDetails, TrackListAdapter.ViewHolder>(TrackDiffCallback()) {
|
||||||
|
|
||||||
|
var source:Source =Source.Spotify
|
||||||
|
|
||||||
override fun onCreateViewHolder(
|
override fun onCreateViewHolder(
|
||||||
parent: ViewGroup,
|
parent: ViewGroup,
|
||||||
viewType: Int
|
viewType: Int
|
||||||
): SpotifyTrackListAdapter.ViewHolder {
|
): ViewHolder {
|
||||||
val layoutInflater = LayoutInflater.from(parent.context)
|
val layoutInflater = LayoutInflater.from(parent.context)
|
||||||
val binding = TrackListItemBinding.inflate(layoutInflater,parent,false)
|
val binding = TrackListItemBinding.inflate(layoutInflater,parent,false)
|
||||||
// val view = layoutInflater.inflate(R.layout.track_list_item,parent,false)
|
return ViewHolder(binding)
|
||||||
return SpotifyTrackListAdapter.ViewHolder(binding)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: SpotifyTrackListAdapter.ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val item = getItem(position)
|
val item = getItem(position)
|
||||||
if(itemCount == 1){
|
if(itemCount == 1){ holder.binding.imageUrl.visibility = View.GONE}else{
|
||||||
holder.binding.imageUrl.visibility = View.GONE}else{
|
viewModel.uiScope.launch {
|
||||||
youtubeViewModel.uiScope.launch {
|
bindImage(holder.binding.imageUrl,item.albumArtURL, source)
|
||||||
bindImage(holder.binding.imageUrl,
|
|
||||||
"https://i.ytimg.com/vi/${item.albumArt.absolutePath.substringAfterLast("/")
|
|
||||||
.substringBeforeLast(".")}/hqdefault.jpg"
|
|
||||||
,
|
|
||||||
Source.YouTube
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,14 +75,25 @@ class YoutubeTrackListAdapter(private val youtubeViewModel :YoutubeViewModel): L
|
|||||||
holder.binding.btnDownload.setImageResource(R.drawable.ic_refresh)
|
holder.binding.btnDownload.setImageResource(R.drawable.ic_refresh)
|
||||||
rotateAnim(it)
|
rotateAnim(it)
|
||||||
item.downloaded = DownloadStatus.Downloading
|
item.downloaded = DownloadStatus.Downloading
|
||||||
youtubeViewModel.uiScope.launch {
|
when(source){
|
||||||
val itemList = mutableListOf<TrackDetails>()
|
Source.Spotify -> {
|
||||||
itemList.add(item)
|
viewModel.uiScope.launch {
|
||||||
YTDownloadHelper.downloadYTTracks(
|
DownloadHelper.downloadAllTracks(
|
||||||
youtubeViewModel.folderType,
|
viewModel.folderType,
|
||||||
youtubeViewModel.subFolder,
|
viewModel.subFolder,
|
||||||
itemList
|
listOf(item)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Source.YouTube -> {
|
||||||
|
viewModel.uiScope.launch {
|
||||||
|
YTDownloadHelper.downloadYTTracks(
|
||||||
|
viewModel.folderType,
|
||||||
|
viewModel.subFolder,
|
||||||
|
listOf(item)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
notifyItemChanged(position)//start showing anim!
|
notifyItemChanged(position)//start showing anim!
|
||||||
}
|
}
|
||||||
@ -97,8 +104,15 @@ class YoutubeTrackListAdapter(private val youtubeViewModel :YoutubeViewModel): L
|
|||||||
holder.binding.artist.text = "${item.artists.get(0)}..."
|
holder.binding.artist.text = "${item.artists.get(0)}..."
|
||||||
holder.binding.duration.text = "${item.durationSec/60} minutes, ${item.durationSec%60} sec"
|
holder.binding.duration.text = "${item.durationSec/60} minutes, ${item.durationSec%60} sec"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ViewHolder(val binding: TrackListItemBinding) : RecyclerView.ViewHolder(binding.root)
|
||||||
|
|
||||||
|
fun submitList(list: MutableList<TrackDetails>?, source: Source) {
|
||||||
|
super.submitList(list)
|
||||||
|
this.source = source
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class YouTubeTrackDiffCallback: DiffUtil.ItemCallback<TrackDetails>(){
|
class TrackDiffCallback: DiffUtil.ItemCallback<TrackDetails>(){
|
||||||
override fun areItemsTheSame(oldItem: TrackDetails, newItem: TrackDetails): Boolean {
|
override fun areItemsTheSame(oldItem: TrackDetails, newItem: TrackDetails): Boolean {
|
||||||
return oldItem.title == newItem.title
|
return oldItem.title == newItem.title
|
||||||
}
|
}
|
@ -20,6 +20,7 @@ package com.shabinder.spotiflyer.ui.gaana
|
|||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -29,8 +30,14 @@ import androidx.lifecycle.ViewModelProvider
|
|||||||
import com.shabinder.spotiflyer.R
|
import com.shabinder.spotiflyer.R
|
||||||
import com.shabinder.spotiflyer.SharedViewModel
|
import com.shabinder.spotiflyer.SharedViewModel
|
||||||
import com.shabinder.spotiflyer.databinding.TrackListFragmentBinding
|
import com.shabinder.spotiflyer.databinding.TrackListFragmentBinding
|
||||||
|
import com.shabinder.spotiflyer.downloadHelper.DownloadHelper
|
||||||
|
import com.shabinder.spotiflyer.models.DownloadStatus
|
||||||
import com.shabinder.spotiflyer.networking.GaanaInterface
|
import com.shabinder.spotiflyer.networking.GaanaInterface
|
||||||
import com.shabinder.spotiflyer.networking.YoutubeMusicApi
|
import com.shabinder.spotiflyer.networking.YoutubeMusicApi
|
||||||
|
import com.shabinder.spotiflyer.recyclerView.TrackListAdapter
|
||||||
|
import com.shabinder.spotiflyer.utils.*
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class GaanaFragment : Fragment() {
|
class GaanaFragment : Fragment() {
|
||||||
@ -39,6 +46,7 @@ class GaanaFragment : Fragment() {
|
|||||||
private lateinit var sharedViewModel: SharedViewModel
|
private lateinit var sharedViewModel: SharedViewModel
|
||||||
@Inject lateinit var youtubeMusicApi: YoutubeMusicApi
|
@Inject lateinit var youtubeMusicApi: YoutubeMusicApi
|
||||||
private lateinit var viewModel: GaanaViewModel
|
private lateinit var viewModel: GaanaViewModel
|
||||||
|
private lateinit var adapter: TrackListAdapter
|
||||||
@Inject lateinit var gaanaInterface: GaanaInterface
|
@Inject lateinit var gaanaInterface: GaanaInterface
|
||||||
private var intentFilter: IntentFilter? = null
|
private var intentFilter: IntentFilter? = null
|
||||||
private var updateUIReceiver: BroadcastReceiver? = null
|
private var updateUIReceiver: BroadcastReceiver? = null
|
||||||
@ -49,6 +57,63 @@ class GaanaFragment : Fragment() {
|
|||||||
): View? {
|
): View? {
|
||||||
binding = DataBindingUtil.inflate(inflater,R.layout.track_list_fragment, container, false)
|
binding = DataBindingUtil.inflate(inflater,R.layout.track_list_fragment, container, false)
|
||||||
viewModel = ViewModelProvider(this).get(GaanaViewModel::class.java)
|
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
|
||||||
|
val link = gaanaLink.substringAfterLast('/', "error")
|
||||||
|
val type = gaanaLink.substringBeforeLast('/', "error").substringAfterLast('/')
|
||||||
|
|
||||||
|
Log.i("Gaana Fragment", "$type : $link")
|
||||||
|
|
||||||
|
when{
|
||||||
|
type == "Error" || link == "Error" -> {
|
||||||
|
showMessage("Please Check Your Link!")
|
||||||
|
Provider.mainActivity.onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
viewModel.gaanaSearch(type,link)
|
||||||
|
|
||||||
|
binding.btnDownloadAll.setOnClickListener {
|
||||||
|
if(!isOnline()){
|
||||||
|
showNoConnectionAlert()
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
binding.btnDownloadAll.visibility = View.GONE
|
||||||
|
binding.downloadingFab.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
rotateAnim(binding.downloadingFab)
|
||||||
|
for (track in viewModel.trackList.value!!){
|
||||||
|
if(track.downloaded != DownloadStatus.Downloaded){
|
||||||
|
track.downloaded = DownloadStatus.Downloading
|
||||||
|
adapter.notifyItemChanged(viewModel.trackList.value!!.indexOf(track))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showMessage("Processing!")
|
||||||
|
sharedViewModel.uiScope.launch(Dispatchers.Default){
|
||||||
|
val urlList = arrayListOf<String>()
|
||||||
|
viewModel.trackList.value?.forEach { urlList.add(it.albumArtURL) }
|
||||||
|
//Appending Source
|
||||||
|
urlList.add("spotify")
|
||||||
|
loadAllImages(
|
||||||
|
requireActivity(),
|
||||||
|
urlList
|
||||||
|
)
|
||||||
|
}
|
||||||
|
viewModel.uiScope.launch {
|
||||||
|
val finalList = viewModel.trackList.value
|
||||||
|
if(finalList.isNullOrEmpty())showMessage("Not Downloading Any Song")
|
||||||
|
DownloadHelper.downloadAllTracks(
|
||||||
|
viewModel.folderType,
|
||||||
|
viewModel.subFolder,
|
||||||
|
finalList ?: listOf(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,7 +18,18 @@
|
|||||||
package com.shabinder.spotiflyer.ui.gaana
|
package com.shabinder.spotiflyer.ui.gaana
|
||||||
|
|
||||||
import androidx.hilt.lifecycle.ViewModelInject
|
import androidx.hilt.lifecycle.ViewModelInject
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import com.shabinder.spotiflyer.database.DatabaseDAO
|
import com.shabinder.spotiflyer.database.DatabaseDAO
|
||||||
|
import com.shabinder.spotiflyer.networking.GaanaInterface
|
||||||
|
import com.shabinder.spotiflyer.utils.BaseViewModel
|
||||||
|
|
||||||
class GaanaViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO) : ViewModel()
|
class GaanaViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO) : BaseViewModel(){
|
||||||
|
|
||||||
|
override var folderType:String = ""
|
||||||
|
override var subFolder:String = ""
|
||||||
|
var gaanaInterface : GaanaInterface? = null
|
||||||
|
|
||||||
|
fun gaanaSearch(type:String,link:String){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -65,19 +65,60 @@ class MainFragment : Fragment() {
|
|||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
val link = binding.linkSearch.text.toString()
|
val link = binding.linkSearch.text.toString()
|
||||||
if (link.contains("spotify",true)){
|
when{
|
||||||
if(sharedViewModel.spotifyService.value == null){//Authentication pending!!
|
//SPOTIFY
|
||||||
(activity as MainActivity).authenticateSpotify()
|
link.contains("spotify",true) -> {
|
||||||
|
if(sharedViewModel.spotifyService.value == null){//Authentication pending!!
|
||||||
|
(activity as MainActivity).authenticateSpotify()
|
||||||
|
}
|
||||||
|
findNavController().navigate(MainFragmentDirections.actionMainFragmentToSpotifyFragment(link))
|
||||||
}
|
}
|
||||||
findNavController().navigate(MainFragmentDirections.actionMainFragmentToSpotifyFragment(link))
|
|
||||||
}else if(link.contains("youtube.com",true) || link.contains("youtu.be",true) ){
|
//YOUTUBE
|
||||||
findNavController().navigate(MainFragmentDirections.actionMainFragmentToYoutubeFragment(link))
|
link.contains("youtube.com",true) || link.contains("youtu.be",true) -> {
|
||||||
}else showMessage("Link is Not Valid",true)
|
findNavController().navigate(MainFragmentDirections.actionMainFragmentToYoutubeFragment(link))
|
||||||
|
}
|
||||||
|
|
||||||
|
//GAANA
|
||||||
|
link.contains("gaana",true) -> {
|
||||||
|
findNavController().navigate(MainFragmentDirections.actionMainFragmentToGaanaFragment(link))
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> showMessage("Link is Not Valid",true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
handleIntent()
|
handleIntent()
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle Intent If there is any!
|
||||||
|
**/
|
||||||
|
private fun handleIntent() {
|
||||||
|
sharedViewModel.intentString.observe(viewLifecycleOwner,{ it?.let {
|
||||||
|
sharedViewModel.uiScope.launch(Dispatchers.IO) {
|
||||||
|
//Wait for any Authentication to Finish ,
|
||||||
|
// this Wait prevents from multiple Authentication Requests
|
||||||
|
Thread.sleep(1000)
|
||||||
|
if(sharedViewModel.spotifyService.value == null){
|
||||||
|
//Not Authenticated Yet
|
||||||
|
Provider.mainActivity.authenticateSpotify()
|
||||||
|
while (sharedViewModel.spotifyService.value == null) {
|
||||||
|
//Waiting for Authentication to Finish
|
||||||
|
Thread.sleep(1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main){
|
||||||
|
binding.linkSearch.setText(sharedViewModel.intentString.value)
|
||||||
|
binding.btnSearch.performClick()
|
||||||
|
//Intent Consumed
|
||||||
|
sharedViewModel.intentString.value = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private fun initializeAll() {
|
private fun initializeAll() {
|
||||||
mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
|
mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
|
||||||
@ -94,44 +135,14 @@ class MainFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementing buttons
|
||||||
|
**/
|
||||||
private fun historyButton() {
|
private fun historyButton() {
|
||||||
binding.btnHistory.setOnClickListener {
|
binding.btnHistory.setOnClickListener {
|
||||||
findNavController().navigate(MainFragmentDirections.actionMainFragmentToDownloadRecord())
|
findNavController().navigate(MainFragmentDirections.actionMainFragmentToDownloadRecord())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle Intent If there is any!
|
|
||||||
**/
|
|
||||||
private fun handleIntent() {
|
|
||||||
sharedViewModel.intentString.observe(viewLifecycleOwner,{
|
|
||||||
if(it != ""){
|
|
||||||
sharedViewModel.uiScope.launch(Dispatchers.IO) {
|
|
||||||
//Wait for any Authentication to Finish ,
|
|
||||||
// this Wait prevents from multiple Authentication Requests
|
|
||||||
Thread.sleep(1000)
|
|
||||||
if(sharedViewModel.spotifyService.value == null){
|
|
||||||
//Not Authenticated Yet
|
|
||||||
Provider.activity.authenticateSpotify()
|
|
||||||
while (sharedViewModel.spotifyService.value == null) {
|
|
||||||
//Waiting for Authentication to Finish
|
|
||||||
Thread.sleep(1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main){
|
|
||||||
binding.linkSearch.setText(sharedViewModel.intentString.value)
|
|
||||||
binding.btnSearch.performClick()
|
|
||||||
sharedViewModel.intentString.value = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementing buttons
|
|
||||||
**/
|
|
||||||
private fun openSpotifyButton() {
|
private fun openSpotifyButton() {
|
||||||
val manager: PackageManager = requireActivity().packageManager
|
val manager: PackageManager = requireActivity().packageManager
|
||||||
try {
|
try {
|
||||||
|
@ -23,7 +23,6 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -41,13 +40,12 @@ import com.shabinder.spotiflyer.models.DownloadStatus
|
|||||||
import com.shabinder.spotiflyer.models.TrackDetails
|
import com.shabinder.spotiflyer.models.TrackDetails
|
||||||
import com.shabinder.spotiflyer.models.spotify.Source
|
import com.shabinder.spotiflyer.models.spotify.Source
|
||||||
import com.shabinder.spotiflyer.networking.YoutubeMusicApi
|
import com.shabinder.spotiflyer.networking.YoutubeMusicApi
|
||||||
import com.shabinder.spotiflyer.recyclerView.SpotifyTrackListAdapter
|
import com.shabinder.spotiflyer.recyclerView.TrackListAdapter
|
||||||
import com.shabinder.spotiflyer.utils.*
|
import com.shabinder.spotiflyer.utils.*
|
||||||
import com.shabinder.spotiflyer.utils.Provider.defaultDir
|
import com.shabinder.spotiflyer.utils.Provider.mainActivity
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@ -58,7 +56,7 @@ class SpotifyFragment : Fragment() {
|
|||||||
private lateinit var sharedViewModel: SharedViewModel
|
private lateinit var sharedViewModel: SharedViewModel
|
||||||
@Inject lateinit var youtubeMusicApi: YoutubeMusicApi
|
@Inject lateinit var youtubeMusicApi: YoutubeMusicApi
|
||||||
private lateinit var viewModel: SpotifyViewModel
|
private lateinit var viewModel: SpotifyViewModel
|
||||||
private lateinit var adapter:SpotifyTrackListAdapter
|
private lateinit var adapter:TrackListAdapter
|
||||||
private var intentFilter:IntentFilter? = null
|
private var intentFilter:IntentFilter? = null
|
||||||
private var updateUIReceiver: BroadcastReceiver? = null
|
private var updateUIReceiver: BroadcastReceiver? = null
|
||||||
|
|
||||||
@ -73,81 +71,70 @@ class SpotifyFragment : Fragment() {
|
|||||||
initializeLiveDataObservers()
|
initializeLiveDataObservers()
|
||||||
initializeBroadcast()
|
initializeBroadcast()
|
||||||
|
|
||||||
val args = SpotifyFragmentArgs.fromBundle(requireArguments())
|
val spotifyLink = SpotifyFragmentArgs.fromBundle(requireArguments()).link.substringAfter("open.spotify.com/")
|
||||||
val spotifyLink = args.link
|
|
||||||
|
|
||||||
val link = spotifyLink.substringAfterLast('/', "Error").substringBefore('?')
|
val link = spotifyLink.substringAfterLast('/', "Error").substringBefore('?')
|
||||||
val type = spotifyLink.substringBeforeLast('/', "Error").substringAfterLast('/')
|
val type = spotifyLink.substringBeforeLast('/', "Error").substringAfterLast('/')
|
||||||
|
|
||||||
Log.i("Fragment", "$type : $link")
|
Log.i("Spotify Fragment", "$type : $link")
|
||||||
|
|
||||||
if(sharedViewModel.spotifyService.value == null){//Authentication pending!!
|
if(sharedViewModel.spotifyService.value == null){//Authentication pending!!
|
||||||
(activity as MainActivity).authenticateSpotify()
|
(activity as MainActivity).authenticateSpotify()
|
||||||
}
|
}
|
||||||
if (type == "Error" || link == "Error") {//Incorrect Link
|
|
||||||
showMessage("Please Check Your Link!")
|
when{
|
||||||
}else if(spotifyLink.contains("open.spotify",true)){//Link Validation!!
|
type == "Error" || link == "Error" -> {
|
||||||
if(type == "episode" || type == "show"){//TODO Implementation
|
showMessage("Please Check Your Link!")
|
||||||
showMessage("Implementing Soon, Stay Tuned!")
|
mainActivity.onBackPressed()
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
viewModel.spotifySearch(type,link)
|
|
||||||
if(type=="album")adapter.isAlbum = true
|
|
||||||
|
|
||||||
binding.btnDownloadAll.setOnClickListener {
|
else -> {
|
||||||
if(!isOnline()){
|
if(type == "episode" || type == "show"){//TODO Implementation
|
||||||
showNoConnectionAlert()
|
showMessage("Implementing Soon, Stay Tuned!")
|
||||||
return@setOnClickListener
|
}
|
||||||
}
|
else{
|
||||||
binding.btnDownloadAll.visibility = View.GONE
|
viewModel.spotifySearch(type,link)
|
||||||
binding.downloadingFab.visibility = View.VISIBLE
|
|
||||||
|
|
||||||
rotateAnim(binding.downloadingFab)
|
binding.btnDownloadAll.setOnClickListener {
|
||||||
for (track in viewModel.trackList.value!!){
|
if(!isOnline()){
|
||||||
if(track.downloaded != DownloadStatus.Downloaded){
|
showNoConnectionAlert()
|
||||||
track.downloaded = DownloadStatus.Downloading
|
return@setOnClickListener
|
||||||
adapter.notifyItemChanged(viewModel.trackList.value!!.indexOf(track))
|
|
||||||
}
|
}
|
||||||
}
|
binding.btnDownloadAll.visibility = View.GONE
|
||||||
showMessage("Processing!")
|
binding.downloadingFab.visibility = View.VISIBLE
|
||||||
sharedViewModel.uiScope.launch(Dispatchers.Default){
|
|
||||||
val urlList = arrayListOf<String>()
|
rotateAnim(binding.downloadingFab)
|
||||||
viewModel.trackList.value?.forEach { urlList.add(it.album?.images?.get(0)?.url.toString()) }
|
for (track in viewModel.trackList.value!!){
|
||||||
//Appending Source
|
if(track.downloaded != DownloadStatus.Downloaded){
|
||||||
urlList.add("spotify")
|
track.downloaded = DownloadStatus.Downloading
|
||||||
loadAllImages(
|
adapter.notifyItemChanged(viewModel.trackList.value!!.indexOf(track))
|
||||||
requireActivity(),
|
}
|
||||||
urlList
|
}
|
||||||
)
|
showMessage("Processing!")
|
||||||
}
|
sharedViewModel.uiScope.launch(Dispatchers.Default){
|
||||||
viewModel.uiScope.launch {
|
val urlList = arrayListOf<String>()
|
||||||
val finalList = viewModel.trackList.value?.map{
|
viewModel.trackList.value?.forEach { urlList.add(it.albumArtURL) }
|
||||||
val artistsList = mutableListOf<String>()
|
//Appending Source
|
||||||
it.artists?.forEach { artist -> artistsList.add(artist!!.name!!) }
|
urlList.add("spotify")
|
||||||
TrackDetails(
|
loadAllImages(
|
||||||
title = it.name.toString(),
|
requireActivity(),
|
||||||
artists = artistsList,
|
urlList
|
||||||
durationSec = (it.duration_ms/1000).toInt(),
|
)
|
||||||
albumArt = File(
|
}
|
||||||
Environment.getExternalStorageDirectory(),
|
viewModel.uiScope.launch {
|
||||||
defaultDir +".Images/" + (it.album?.images?.get(0)?.url.toString()).substringAfterLast('/') + ".jpeg"),
|
val finalList = viewModel.trackList.value
|
||||||
albumName = it.album?.name,
|
if(finalList.isNullOrEmpty())showMessage("Not Downloading Any Song")
|
||||||
year = it.album?.release_date,
|
DownloadHelper.downloadAllTracks(
|
||||||
comment = "Genres:${it.album?.genres?.joinToString()}",
|
viewModel.folderType,
|
||||||
trackUrl = it.href,
|
viewModel.subFolder,
|
||||||
source = Source.Spotify
|
finalList ?: listOf(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if(finalList.isNullOrEmpty())showMessage("Not Downloading Any Song")
|
|
||||||
DownloadHelper.downloadAllTracks(
|
|
||||||
viewModel.folderType,
|
|
||||||
viewModel.subFolder,
|
|
||||||
finalList ?: listOf(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +147,7 @@ class SpotifyFragment : Fragment() {
|
|||||||
sharedViewModel.spotifyService.observe(viewLifecycleOwner, {
|
sharedViewModel.spotifyService.observe(viewLifecycleOwner, {
|
||||||
viewModel.spotifyService = it
|
viewModel.spotifyService = it
|
||||||
})
|
})
|
||||||
adapter = SpotifyTrackListAdapter(viewModel)
|
adapter = TrackListAdapter(viewModel)
|
||||||
DownloadHelper.youtubeMusicApi = youtubeMusicApi
|
DownloadHelper.youtubeMusicApi = youtubeMusicApi
|
||||||
DownloadHelper.sharedViewModel = sharedViewModel
|
DownloadHelper.sharedViewModel = sharedViewModel
|
||||||
DownloadHelper.statusBar = binding.statusBar
|
DownloadHelper.statusBar = binding.statusBar
|
||||||
@ -211,7 +198,7 @@ class SpotifyFragment : Fragment() {
|
|||||||
if (intent != null){
|
if (intent != null){
|
||||||
val trackDetails = intent.getParcelableExtra<TrackDetails?>("track")
|
val trackDetails = intent.getParcelableExtra<TrackDetails?>("track")
|
||||||
trackDetails?.let {
|
trackDetails?.let {
|
||||||
val position: Int = viewModel.trackList.value?.map { it.name }?.indexOf(trackDetails.title) ?: -1
|
val position: Int = viewModel.trackList.value?.map { it.title }?.indexOf(trackDetails.title) ?: -1
|
||||||
Log.i("Track","Download Completed Intent :$position")
|
Log.i("Track","Download Completed Intent :$position")
|
||||||
if(position != -1) {
|
if(position != -1) {
|
||||||
val track = viewModel.trackList.value?.get(position)
|
val track = viewModel.trackList.value?.get(position)
|
||||||
|
@ -17,34 +17,30 @@
|
|||||||
|
|
||||||
package com.shabinder.spotiflyer.ui.spotify
|
package com.shabinder.spotiflyer.ui.spotify
|
||||||
|
|
||||||
|
import android.os.Environment
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.hilt.lifecycle.ViewModelInject
|
import androidx.hilt.lifecycle.ViewModelInject
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import com.shabinder.spotiflyer.database.DatabaseDAO
|
import com.shabinder.spotiflyer.database.DatabaseDAO
|
||||||
import com.shabinder.spotiflyer.database.DownloadRecord
|
import com.shabinder.spotiflyer.database.DownloadRecord
|
||||||
import com.shabinder.spotiflyer.models.DownloadStatus
|
import com.shabinder.spotiflyer.models.DownloadStatus
|
||||||
|
import com.shabinder.spotiflyer.models.TrackDetails
|
||||||
import com.shabinder.spotiflyer.models.spotify.*
|
import com.shabinder.spotiflyer.models.spotify.*
|
||||||
import com.shabinder.spotiflyer.networking.SpotifyService
|
import com.shabinder.spotiflyer.networking.SpotifyService
|
||||||
|
import com.shabinder.spotiflyer.utils.BaseViewModel
|
||||||
|
import com.shabinder.spotiflyer.utils.Provider
|
||||||
import com.shabinder.spotiflyer.utils.finalOutputDir
|
import com.shabinder.spotiflyer.utils.finalOutputDir
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO) :
|
class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO) : BaseViewModel(){
|
||||||
ViewModel(){
|
|
||||||
|
override var folderType:String = ""
|
||||||
|
override var subFolder:String = ""
|
||||||
|
|
||||||
var folderType:String = ""
|
|
||||||
var subFolder:String = ""
|
|
||||||
var trackList = MutableLiveData<MutableList<Track>>()
|
|
||||||
private val loading = "Loading"
|
|
||||||
var title = MutableLiveData<String>().apply { value = loading }
|
|
||||||
var coverUrl = MutableLiveData<String>().apply { value = loading }
|
|
||||||
var spotifyService : SpotifyService? = null
|
var spotifyService : SpotifyService? = null
|
||||||
|
|
||||||
private var viewModelJob = Job()
|
|
||||||
val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
|
|
||||||
|
|
||||||
|
|
||||||
fun spotifySearch(type:String,link: String){
|
fun spotifySearch(type:String,link: String){
|
||||||
when (type) {
|
when (type) {
|
||||||
"track" -> {
|
"track" -> {
|
||||||
@ -56,7 +52,7 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
|
|||||||
trackObject.downloaded = DownloadStatus.Downloaded
|
trackObject.downloaded = DownloadStatus.Downloaded
|
||||||
}
|
}
|
||||||
tempTrackList.add(trackObject)
|
tempTrackList.add(trackObject)
|
||||||
trackList.value = tempTrackList
|
trackList.value = tempTrackList.toTrackDetailsList()
|
||||||
title.value = trackObject.name
|
title.value = trackObject.name
|
||||||
coverUrl.value = trackObject.album!!.images?.get(0)!!.url!!
|
coverUrl.value = trackObject.album!!.images?.get(0)!!.url!!
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
@ -86,7 +82,7 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
|
|||||||
it.album = Album(images = listOf(Image(url = albumObject.images?.get(0)?.url)))
|
it.album = Album(images = listOf(Image(url = albumObject.images?.get(0)?.url)))
|
||||||
tempTrackList.add(it)
|
tempTrackList.add(it)
|
||||||
}
|
}
|
||||||
trackList.value = tempTrackList
|
trackList.value = tempTrackList.toTrackDetailsList()
|
||||||
title.value = albumObject?.name
|
title.value = albumObject?.name
|
||||||
coverUrl.value = albumObject?.images?.get(0)?.url
|
coverUrl.value = albumObject?.images?.get(0)?.url
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
@ -129,7 +125,7 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
|
|||||||
moreTracksAvailable = !moreTracks?.next.isNullOrBlank()
|
moreTracksAvailable = !moreTracks?.next.isNullOrBlank()
|
||||||
}
|
}
|
||||||
Log.i("Total Tracks Fetched",tempTrackList.size.toString())
|
Log.i("Total Tracks Fetched",tempTrackList.size.toString())
|
||||||
trackList.value = tempTrackList
|
trackList.value = tempTrackList.toTrackDetailsList()
|
||||||
title.value = playlistObject?.name
|
title.value = playlistObject?.name
|
||||||
coverUrl.value = playlistObject?.images?.get(0)?.url.toString()
|
coverUrl.value = playlistObject?.images?.get(0)?.url.toString()
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
@ -152,6 +148,26 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun List<Track>.toTrackDetailsList() = this.map {
|
||||||
|
val artistsList = mutableListOf<String>()
|
||||||
|
it.artists?.forEach { artist -> artistsList.add(artist!!.name!!) }
|
||||||
|
TrackDetails(
|
||||||
|
title = it.name.toString(),
|
||||||
|
artists = artistsList,
|
||||||
|
durationSec = (it.duration_ms/1000).toInt(),
|
||||||
|
albumArt = File(
|
||||||
|
Environment.getExternalStorageDirectory(),
|
||||||
|
Provider.defaultDir +".Images/" + (it.album?.images?.get(0)?.url.toString()).substringAfterLast('/') + ".jpeg"),
|
||||||
|
albumName = it.album?.name,
|
||||||
|
year = it.album?.release_date,
|
||||||
|
comment = "Genres:${it.album?.genres?.joinToString()}",
|
||||||
|
trackUrl = it.href,
|
||||||
|
downloaded = it.downloaded,
|
||||||
|
source = Source.Spotify,
|
||||||
|
albumArtURL = it.album?.images?.get(0)?.url.toString()
|
||||||
|
)
|
||||||
|
}.toMutableList()
|
||||||
|
|
||||||
private suspend fun getTrackDetails(trackLink:String): Track?{
|
private suspend fun getTrackDetails(trackLink:String): Track?{
|
||||||
Log.i("Requesting","https://api.spotify.com/v1/tracks/$trackLink")
|
Log.i("Requesting","https://api.spotify.com/v1/tracks/$trackLink")
|
||||||
return spotifyService?.getTrack(trackLink)?.value
|
return spotifyService?.getTrack(trackLink)?.value
|
||||||
@ -168,10 +184,4 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
|
|||||||
Log.i("Requesting","https://api.spotify.com/v1/playlists/$link/tracks?offset=$offset&limit=$limit")
|
Log.i("Requesting","https://api.spotify.com/v1/playlists/$link/tracks?offset=$offset&limit=$limit")
|
||||||
return spotifyService?.getPlaylistTracks(link, offset, limit)?.value
|
return spotifyService?.getPlaylistTracks(link, offset, limit)?.value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCleared() {
|
|
||||||
super.onCleared()
|
|
||||||
viewModelJob.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -37,7 +37,7 @@ import com.shabinder.spotiflyer.downloadHelper.YTDownloadHelper
|
|||||||
import com.shabinder.spotiflyer.models.DownloadStatus
|
import com.shabinder.spotiflyer.models.DownloadStatus
|
||||||
import com.shabinder.spotiflyer.models.TrackDetails
|
import com.shabinder.spotiflyer.models.TrackDetails
|
||||||
import com.shabinder.spotiflyer.models.spotify.Source
|
import com.shabinder.spotiflyer.models.spotify.Source
|
||||||
import com.shabinder.spotiflyer.recyclerView.YoutubeTrackListAdapter
|
import com.shabinder.spotiflyer.recyclerView.TrackListAdapter
|
||||||
import com.shabinder.spotiflyer.utils.*
|
import com.shabinder.spotiflyer.utils.*
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -51,7 +51,7 @@ class YoutubeFragment : Fragment() {
|
|||||||
private lateinit var viewModel: YoutubeViewModel
|
private lateinit var viewModel: YoutubeViewModel
|
||||||
private lateinit var sharedViewModel: SharedViewModel
|
private lateinit var sharedViewModel: SharedViewModel
|
||||||
@Inject lateinit var ytDownloader: YoutubeDownloader
|
@Inject lateinit var ytDownloader: YoutubeDownloader
|
||||||
private lateinit var adapter : YoutubeTrackListAdapter
|
private lateinit var adapter : TrackListAdapter
|
||||||
private var intentFilter: IntentFilter? = null
|
private var intentFilter: IntentFilter? = null
|
||||||
private var updateUIReceiver: BroadcastReceiver? = null
|
private var updateUIReceiver: BroadcastReceiver? = null
|
||||||
private val sampleDomain2 = "youtu.be"
|
private val sampleDomain2 = "youtu.be"
|
||||||
@ -64,7 +64,7 @@ class YoutubeFragment : Fragment() {
|
|||||||
binding = DataBindingUtil.inflate(inflater,R.layout.track_list_fragment,container,false)
|
binding = DataBindingUtil.inflate(inflater,R.layout.track_list_fragment,container,false)
|
||||||
viewModel = ViewModelProvider(this).get(YoutubeViewModel::class.java)
|
viewModel = ViewModelProvider(this).get(YoutubeViewModel::class.java)
|
||||||
sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java)
|
sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java)
|
||||||
adapter = YoutubeTrackListAdapter(viewModel)
|
adapter = TrackListAdapter(viewModel)
|
||||||
binding.trackList.adapter = adapter
|
binding.trackList.adapter = adapter
|
||||||
|
|
||||||
initializeLiveDataObservers()
|
initializeLiveDataObservers()
|
||||||
@ -108,16 +108,16 @@ class YoutubeFragment : Fragment() {
|
|||||||
|
|
||||||
rotateAnim(binding.downloadingFab)
|
rotateAnim(binding.downloadingFab)
|
||||||
|
|
||||||
for (track in viewModel.ytTrackList.value?: listOf()){
|
for (track in viewModel.trackList.value?: listOf()){
|
||||||
if(track.downloaded != DownloadStatus.Downloaded){
|
if(track.downloaded != DownloadStatus.Downloaded){
|
||||||
track.downloaded = DownloadStatus.Downloading
|
track.downloaded = DownloadStatus.Downloading
|
||||||
adapter.notifyItemChanged(viewModel.ytTrackList.value!!.indexOf(track))
|
adapter.notifyItemChanged(viewModel.trackList.value!!.indexOf(track))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
showMessage("Processing!")
|
showMessage("Processing!")
|
||||||
sharedViewModel.uiScope.launch(Dispatchers.Default){
|
sharedViewModel.uiScope.launch(Dispatchers.Default){
|
||||||
val urlList = arrayListOf<String>()
|
val urlList = arrayListOf<String>()
|
||||||
viewModel.ytTrackList.value?.forEach { urlList.add("https://i.ytimg.com/vi/${it.albumArt.absolutePath.substringAfterLast("/")
|
viewModel.trackList.value?.forEach { urlList.add("https://i.ytimg.com/vi/${it.albumArt.absolutePath.substringAfterLast("/")
|
||||||
.substringBeforeLast(".")}/hqdefault.jpg")}
|
.substringBeforeLast(".")}/hqdefault.jpg")}
|
||||||
//Appending Source
|
//Appending Source
|
||||||
urlList.add("youtube")
|
urlList.add("youtube")
|
||||||
@ -130,7 +130,7 @@ class YoutubeFragment : Fragment() {
|
|||||||
YTDownloadHelper.downloadYTTracks(
|
YTDownloadHelper.downloadYTTracks(
|
||||||
type = viewModel.folderType,
|
type = viewModel.folderType,
|
||||||
subFolder = viewModel.subFolder,
|
subFolder = viewModel.subFolder,
|
||||||
tracks = viewModel.ytTrackList.value ?: listOf()
|
tracks = viewModel.trackList.value ?: listOf()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,13 +150,13 @@ class YoutubeFragment : Fragment() {
|
|||||||
if (intent != null){
|
if (intent != null){
|
||||||
val trackDetails = intent.getParcelableExtra<TrackDetails?>("track")
|
val trackDetails = intent.getParcelableExtra<TrackDetails?>("track")
|
||||||
trackDetails?.let {
|
trackDetails?.let {
|
||||||
val position: Int = viewModel.ytTrackList.value?.map { it.title }?.indexOf(trackDetails.title) ?: -1
|
val position: Int = viewModel.trackList.value?.map { it.title }?.indexOf(trackDetails.title) ?: -1
|
||||||
Log.i("Track","Download Completed Intent :$position")
|
Log.i("Track","Download Completed Intent :$position")
|
||||||
if(position != -1) {
|
if(position != -1) {
|
||||||
val track = viewModel.ytTrackList.value?.get(position)
|
val track = viewModel.trackList.value?.get(position)
|
||||||
track?.let{
|
track?.let{
|
||||||
it.downloaded = DownloadStatus.Downloaded
|
it.downloaded = DownloadStatus.Downloaded
|
||||||
viewModel.ytTrackList.value?.set(position, it)
|
viewModel.trackList.value?.set(position, it)
|
||||||
adapter.notifyItemChanged(position)
|
adapter.notifyItemChanged(position)
|
||||||
checkIfAllDownloaded()
|
checkIfAllDownloaded()
|
||||||
}
|
}
|
||||||
@ -174,7 +174,7 @@ class YoutubeFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkIfAllDownloaded() {
|
private fun checkIfAllDownloaded() {
|
||||||
if(!viewModel.ytTrackList.value!!.any { it.downloaded != DownloadStatus.Downloaded }){
|
if(!viewModel.trackList.value!!.any { it.downloaded != DownloadStatus.Downloaded }){
|
||||||
//All Tracks Downloaded
|
//All Tracks Downloaded
|
||||||
binding.btnDownloadAll.visibility = View.GONE
|
binding.btnDownloadAll.visibility = View.GONE
|
||||||
binding.downloadingFab.apply{
|
binding.downloadingFab.apply{
|
||||||
@ -195,7 +195,7 @@ class YoutubeFragment : Fragment() {
|
|||||||
/**
|
/**
|
||||||
* TrackList Binding Observer!
|
* TrackList Binding Observer!
|
||||||
**/
|
**/
|
||||||
viewModel.ytTrackList.observe(viewLifecycleOwner, {
|
viewModel.trackList.observe(viewLifecycleOwner, {
|
||||||
adapter.submitList(it)
|
adapter.submitList(it)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -21,38 +21,31 @@ import android.annotation.SuppressLint
|
|||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.hilt.lifecycle.ViewModelInject
|
import androidx.hilt.lifecycle.ViewModelInject
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import com.github.kiulian.downloader.YoutubeDownloader
|
import com.github.kiulian.downloader.YoutubeDownloader
|
||||||
import com.shabinder.spotiflyer.database.DatabaseDAO
|
import com.shabinder.spotiflyer.database.DatabaseDAO
|
||||||
import com.shabinder.spotiflyer.database.DownloadRecord
|
import com.shabinder.spotiflyer.database.DownloadRecord
|
||||||
import com.shabinder.spotiflyer.models.DownloadStatus
|
import com.shabinder.spotiflyer.models.DownloadStatus
|
||||||
import com.shabinder.spotiflyer.models.TrackDetails
|
import com.shabinder.spotiflyer.models.TrackDetails
|
||||||
import com.shabinder.spotiflyer.models.spotify.Source
|
import com.shabinder.spotiflyer.models.spotify.Source
|
||||||
|
import com.shabinder.spotiflyer.utils.BaseViewModel
|
||||||
import com.shabinder.spotiflyer.utils.Provider.defaultDir
|
import com.shabinder.spotiflyer.utils.Provider.defaultDir
|
||||||
import com.shabinder.spotiflyer.utils.finalOutputDir
|
import com.shabinder.spotiflyer.utils.finalOutputDir
|
||||||
import com.shabinder.spotiflyer.utils.removeIllegalChars
|
import com.shabinder.spotiflyer.utils.removeIllegalChars
|
||||||
import com.shabinder.spotiflyer.utils.showMessage
|
import com.shabinder.spotiflyer.utils.showMessage
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class YoutubeViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO) : ViewModel(){
|
class YoutubeViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO) : BaseViewModel(){
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* YT Album Art Schema
|
* YT Album Art Schema
|
||||||
* HI-RES Url: https://i.ytimg.com/vi/$searchId/maxresdefault.jpg"
|
* HI-RES Url: https://i.ytimg.com/vi/$searchId/maxresdefault.jpg"
|
||||||
* Normal Url: https://i.ytimg.com/vi/$searchId/hqdefault.jpg"
|
* Normal Url: https://i.ytimg.com/vi/$searchId/hqdefault.jpg"
|
||||||
* */
|
* */
|
||||||
|
|
||||||
val ytTrackList = MutableLiveData<MutableList<TrackDetails>>()
|
override var folderType = "YT_Downloads"
|
||||||
private val loading = "Loading"
|
override var subFolder = ""
|
||||||
var title = MutableLiveData<String>().apply { value = "\"Loading!\"" }
|
|
||||||
var coverUrl = MutableLiveData<String>().apply { value = loading }
|
|
||||||
val folderType = "YT_Downloads"
|
|
||||||
var subFolder = ""
|
|
||||||
private var viewModelJob = Job()
|
|
||||||
val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
|
|
||||||
|
|
||||||
|
|
||||||
fun getYTPlaylist(searchId:String, ytDownloader:YoutubeDownloader){
|
fun getYTPlaylist(searchId:String, ytDownloader:YoutubeDownloader){
|
||||||
try{
|
try{
|
||||||
@ -67,7 +60,7 @@ class YoutubeViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
|
|||||||
title.postValue(
|
title.postValue(
|
||||||
if(name.length > 17){"${name.subSequence(0,16)}..."}else{name}
|
if(name.length > 17){"${name.subSequence(0,16)}..."}else{name}
|
||||||
)
|
)
|
||||||
ytTrackList.postValue(videos.map {
|
this@YoutubeViewModel.trackList.postValue(videos.map {
|
||||||
TrackDetails(
|
TrackDetails(
|
||||||
title = it.title(),
|
title = it.title(),
|
||||||
artists = listOf(it.author().toString()),
|
artists = listOf(it.author().toString()),
|
||||||
@ -77,13 +70,13 @@ class YoutubeViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
|
|||||||
defaultDir + ".Images/" + it.videoId() + ".jpeg"
|
defaultDir + ".Images/" + it.videoId() + ".jpeg"
|
||||||
),
|
),
|
||||||
source = Source.YouTube,
|
source = Source.YouTube,
|
||||||
|
albumArtURL = "https://i.ytimg.com/vi/${it.videoId()}/hqdefault.jpg",
|
||||||
downloaded = if (File(
|
downloaded = if (File(
|
||||||
finalOutputDir(
|
finalOutputDir(
|
||||||
itemName = it.title(),
|
itemName = it.title(),
|
||||||
type = folderType,
|
type = folderType,
|
||||||
subFolder = subFolder
|
subFolder = subFolder
|
||||||
)
|
)).exists()
|
||||||
).exists()
|
|
||||||
)
|
)
|
||||||
DownloadStatus.Downloaded
|
DownloadStatus.Downloaded
|
||||||
else {
|
else {
|
||||||
@ -120,17 +113,18 @@ class YoutubeViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
|
|||||||
val detail = video?.details()
|
val detail = video?.details()
|
||||||
val name = detail?.title()?.replace(detail.author()!!.toUpperCase(),"",true) ?: detail?.title() ?: ""
|
val name = detail?.title()?.replace(detail.author()!!.toUpperCase(),"",true) ?: detail?.title() ?: ""
|
||||||
Log.i("YT View Model",detail.toString())
|
Log.i("YT View Model",detail.toString())
|
||||||
ytTrackList.postValue(
|
this@YoutubeViewModel.trackList.postValue(
|
||||||
listOf(
|
listOf(
|
||||||
TrackDetails(
|
TrackDetails(
|
||||||
title = name,
|
title = name,
|
||||||
artists = listOf(detail?.author().toString()),
|
artists = listOf(detail?.author().toString()),
|
||||||
durationSec = detail?.lengthSeconds()?:0,
|
durationSec = detail?.lengthSeconds()?:0,
|
||||||
albumArt = File(
|
albumArt = File(
|
||||||
Environment.getExternalStorageDirectory(),
|
Environment.getExternalStorageDirectory(),
|
||||||
defaultDir +".Images/" + searchId + ".jpeg"
|
"$defaultDir.Images/$searchId.jpeg"
|
||||||
),
|
),
|
||||||
source = Source.YouTube
|
source = Source.YouTube,
|
||||||
|
albumArtURL = "https://i.ytimg.com/vi/$searchId/hqdefault.jpg"
|
||||||
)
|
)
|
||||||
).toMutableList()
|
).toMutableList()
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.shabinder.spotiflyer.utils
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import com.shabinder.spotiflyer.models.TrackDetails
|
||||||
|
import kotlinx.coroutines.CompletableJob
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
|
||||||
|
abstract class BaseViewModel:ViewModel() {
|
||||||
|
abstract var folderType:String
|
||||||
|
abstract var subFolder:String
|
||||||
|
open val trackList = MutableLiveData<MutableList<TrackDetails>>()
|
||||||
|
private val viewModelJob:CompletableJob = Job()
|
||||||
|
open val uiScope = CoroutineScope(Dispatchers.Default + viewModelJob)
|
||||||
|
|
||||||
|
private val loading = "Loading!"
|
||||||
|
open var title = MutableLiveData<String>().apply { value = loading }
|
||||||
|
open var coverUrl = MutableLiveData<String>().apply { value = loading }
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
super.onCleared()
|
||||||
|
viewModelJob.cancel()
|
||||||
|
}
|
||||||
|
}
|
@ -49,7 +49,7 @@ import javax.inject.Singleton
|
|||||||
@Module
|
@Module
|
||||||
object Provider {
|
object Provider {
|
||||||
|
|
||||||
val activity: MainActivity = MainActivity.getInstance()
|
val mainActivity: MainActivity = MainActivity.getInstance()
|
||||||
val defaultDir = Environment.DIRECTORY_MUSIC + File.separator + "SpotiFlyer" + File.separator
|
val defaultDir = Environment.DIRECTORY_MUSIC + File.separator + "SpotiFlyer" + File.separator
|
||||||
|
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ object Provider {
|
|||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideUpi():EasyUpiPayment {
|
fun provideUpi():EasyUpiPayment {
|
||||||
return EasyUpiPayment.Builder(activity)
|
return EasyUpiPayment.Builder(mainActivity)
|
||||||
.setPayeeVpa("technoshab@paytm")
|
.setPayeeVpa("technoshab@paytm")
|
||||||
.setPayeeName("Shabinder Singh")
|
.setPayeeName("Shabinder Singh")
|
||||||
.setTransactionId("UNIQUE_TRANSACTION_ID")
|
.setTransactionId("UNIQUE_TRANSACTION_ID")
|
||||||
|
@ -41,13 +41,12 @@ import com.google.android.material.snackbar.Snackbar
|
|||||||
import com.shabinder.spotiflyer.R
|
import com.shabinder.spotiflyer.R
|
||||||
import com.shabinder.spotiflyer.models.DownloadObject
|
import com.shabinder.spotiflyer.models.DownloadObject
|
||||||
import com.shabinder.spotiflyer.models.spotify.Source
|
import com.shabinder.spotiflyer.models.spotify.Source
|
||||||
import com.shabinder.spotiflyer.utils.Provider.activity
|
|
||||||
import com.shabinder.spotiflyer.utils.Provider.defaultDir
|
import com.shabinder.spotiflyer.utils.Provider.defaultDir
|
||||||
|
import com.shabinder.spotiflyer.utils.Provider.mainActivity
|
||||||
import com.shabinder.spotiflyer.worker.ForegroundService
|
import com.shabinder.spotiflyer.worker.ForegroundService
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
@ -77,7 +76,7 @@ fun finalOutputDir(itemName:String? = null,type:String, subFolder:String?=null,e
|
|||||||
fun isOnline(): Boolean {
|
fun isOnline(): Boolean {
|
||||||
var result = false
|
var result = false
|
||||||
val connectivityManager =
|
val connectivityManager =
|
||||||
activity.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
|
mainActivity.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
|
||||||
connectivityManager?.let {
|
connectivityManager?.let {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
it.getNetworkCapabilities(connectivityManager.activeNetwork)?.apply {
|
it.getNetworkCapabilities(connectivityManager.activeNetwork)?.apply {
|
||||||
@ -90,7 +89,7 @@ fun isOnline(): Boolean {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val netInfo =
|
val netInfo =
|
||||||
(activity.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo
|
(mainActivity.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo
|
||||||
result = netInfo != null && netInfo.isConnected
|
result = netInfo != null && netInfo.isConnected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,12 +99,12 @@ fun isOnline(): Boolean {
|
|||||||
fun showMessage(message: String, long: Boolean = false){
|
fun showMessage(message: String, long: Boolean = false){
|
||||||
CoroutineScope(Dispatchers.Main).launch{
|
CoroutineScope(Dispatchers.Main).launch{
|
||||||
Snackbar.make(
|
Snackbar.make(
|
||||||
activity.snackBarAnchor,
|
mainActivity.snackBarAnchor,
|
||||||
message,
|
message,
|
||||||
if (long) Snackbar.LENGTH_LONG else Snackbar.LENGTH_SHORT
|
if (long) Snackbar.LENGTH_LONG else Snackbar.LENGTH_SHORT
|
||||||
).also { snackbar ->
|
).apply {
|
||||||
snackbar.setAction("Ok") {
|
setAction("Ok") {
|
||||||
snackbar.dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
@ -126,7 +125,7 @@ fun rotateAnim(view: View){
|
|||||||
|
|
||||||
fun showNoConnectionAlert(){
|
fun showNoConnectionAlert(){
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
activity.apply {
|
mainActivity.apply {
|
||||||
MaterialAlertDialogBuilder(this, R.style.AlertDialogTheme)
|
MaterialAlertDialogBuilder(this, R.style.AlertDialogTheme)
|
||||||
.setTitle(resources.getString(R.string.title))
|
.setTitle(resources.getString(R.string.title))
|
||||||
.setMessage(resources.getString(R.string.supporting_text))
|
.setMessage(resources.getString(R.string.supporting_text))
|
||||||
@ -187,13 +186,10 @@ fun bindImage(imgView: ImageView, imgUrl: String?,source: Source?) {
|
|||||||
}
|
}
|
||||||
// the File to save , append increasing numeric counter to prevent files from getting overwritten.
|
// the File to save , append increasing numeric counter to prevent files from getting overwritten.
|
||||||
resource?.copyTo(file)
|
resource?.copyTo(file)
|
||||||
withContext(Dispatchers.Main){
|
Glide.with(imgView)
|
||||||
Glide.with(imgView)
|
.load(file)
|
||||||
.load(file)
|
.placeholder(R.drawable.ic_song_placeholder)
|
||||||
.placeholder(R.drawable.ic_song_placeholder)
|
.into(imgView)
|
||||||
.into(imgView)
|
|
||||||
// Log.i("Glide","imageSaved")
|
|
||||||
}
|
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
@ -22,15 +22,6 @@
|
|||||||
android:id="@+id/navigation"
|
android:id="@+id/navigation"
|
||||||
app:startDestination="@id/mainFragment">
|
app:startDestination="@id/mainFragment">
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/spotifyFragment"
|
|
||||||
android:name="com.shabinder.spotiflyer.ui.spotify.SpotifyFragment"
|
|
||||||
android:label="main_fragment"
|
|
||||||
tools:layout="@layout/track_list_fragment" >
|
|
||||||
<argument
|
|
||||||
android:name="link"
|
|
||||||
app:argType="string" />
|
|
||||||
</fragment>
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/mainFragment"
|
android:id="@+id/mainFragment"
|
||||||
android:name="com.shabinder.spotiflyer.ui.mainfragment.MainFragment"
|
android:name="com.shabinder.spotiflyer.ui.mainfragment.MainFragment"
|
||||||
@ -51,16 +42,11 @@
|
|||||||
app:destination="@id/downloadRecord"
|
app:destination="@id/downloadRecord"
|
||||||
app:enterAnim="@android:anim/slide_in_left"
|
app:enterAnim="@android:anim/slide_in_left"
|
||||||
app:exitAnim="@android:anim/slide_out_right" />
|
app:exitAnim="@android:anim/slide_out_right" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_mainFragment_to_gaanaFragment"
|
||||||
|
app:destination="@id/gaanaFragment" />
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
|
||||||
android:id="@+id/youtubeFragment"
|
|
||||||
android:name="com.shabinder.spotiflyer.ui.youtube.YoutubeFragment"
|
|
||||||
android:label="YoutubeFragment"
|
|
||||||
tools:layout="@layout/track_list_fragment">
|
|
||||||
<argument
|
|
||||||
android:name="link"
|
|
||||||
app:argType="string" />
|
|
||||||
</fragment>
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/downloadRecord"
|
android:id="@+id/downloadRecord"
|
||||||
android:name="com.shabinder.spotiflyer.ui.downloadrecord.DownloadRecordFragment"
|
android:name="com.shabinder.spotiflyer.ui.downloadrecord.DownloadRecordFragment"
|
||||||
@ -76,5 +62,35 @@
|
|||||||
app:destination="@id/youtubeFragment"
|
app:destination="@id/youtubeFragment"
|
||||||
app:enterAnim="@android:anim/slide_in_left"
|
app:enterAnim="@android:anim/slide_in_left"
|
||||||
app:exitAnim="@android:anim/slide_out_right"/>
|
app:exitAnim="@android:anim/slide_out_right"/>
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_downloadRecord_to_gaanaFragment"
|
||||||
|
app:destination="@id/gaanaFragment" />
|
||||||
|
</fragment>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/spotifyFragment"
|
||||||
|
android:name="com.shabinder.spotiflyer.ui.spotify.SpotifyFragment"
|
||||||
|
android:label="main_fragment"
|
||||||
|
tools:layout="@layout/track_list_fragment" >
|
||||||
|
<argument
|
||||||
|
android:name="link"
|
||||||
|
app:argType="string" />
|
||||||
|
</fragment>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/youtubeFragment"
|
||||||
|
android:name="com.shabinder.spotiflyer.ui.youtube.YoutubeFragment"
|
||||||
|
android:label="YoutubeFragment"
|
||||||
|
tools:layout="@layout/track_list_fragment">
|
||||||
|
<argument
|
||||||
|
android:name="link"
|
||||||
|
app:argType="string" />
|
||||||
|
</fragment>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/gaanaFragment"
|
||||||
|
android:name="com.shabinder.spotiflyer.ui.gaana.GaanaFragment"
|
||||||
|
android:label="GaanaFragment"
|
||||||
|
tools:layout="@layout/track_list_fragment">
|
||||||
|
<argument
|
||||||
|
android:name="link"
|
||||||
|
app:argType="string" />
|
||||||
</fragment>
|
</fragment>
|
||||||
</navigation>
|
</navigation>
|
Loading…
Reference in New Issue
Block a user