Fragment Code Clean , and Unification

This commit is contained in:
Shabinder 2020-11-09 23:53:22 +05:30
parent 92e699075c
commit f869725953
9 changed files with 208 additions and 312 deletions

View File

@ -69,12 +69,12 @@ class MainActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
binding = DataBindingUtil.setContentView(this, R.layout.main_activity) binding = DataBindingUtil.setContentView(this, R.layout.main_activity)
sharedViewModel = ViewModelProvider(this).get(SharedViewModel::class.java) sharedViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
navController = findNavController(R.id.navHostFragment) navController = findNavController(R.id.navHostFragment)
snackBarAnchor = binding.snackBarPosition snackBarAnchor = binding.snackBarPosition
//Enabling Dark Mode //Enabling Dark Mode
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
authenticateSpotify() authenticateSpotify()

View File

@ -76,7 +76,7 @@ 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(mainActivity,"Download Started, Now You can leave the App!", Toast.LENGTH_SHORT).show() showMessage("Download Started, Now You can leave the App!")
} }
startService(mainActivity,downloadList) startService(mainActivity,downloadList)
},5000) },5000)

View File

@ -17,55 +17,38 @@
package com.shabinder.spotiflyer.ui.gaana package com.shabinder.spotiflyer.ui.gaana
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle import android.os.Bundle
import android.util.Log 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
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.SimpleItemAnimator import androidx.recyclerview.widget.SimpleItemAnimator
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.downloadHelper.DownloadHelper import com.shabinder.spotiflyer.downloadHelper.DownloadHelper
import com.shabinder.spotiflyer.models.DownloadStatus 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.Source
import com.shabinder.spotiflyer.networking.GaanaInterface
import com.shabinder.spotiflyer.networking.YoutubeMusicApi
import com.shabinder.spotiflyer.recyclerView.TrackListAdapter import com.shabinder.spotiflyer.recyclerView.TrackListAdapter
import com.shabinder.spotiflyer.utils.* import com.shabinder.spotiflyer.utils.*
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject
@AndroidEntryPoint class GaanaFragment : BaseFragment() {
class GaanaFragment : Fragment() {
override lateinit var baseViewModel: BaseViewModel
override lateinit var adapter: TrackListAdapter
override var source: Source = Source.Gaana
private val viewModel:GaanaViewModel
get() = baseViewModel as GaanaViewModel
private lateinit var binding: TrackListFragmentBinding
private lateinit var sharedViewModel: SharedViewModel
@Inject lateinit var youtubeMusicApi: YoutubeMusicApi
private lateinit var viewModel: GaanaViewModel
private lateinit var adapter: TrackListAdapter
@Inject lateinit var gaanaInterface: GaanaInterface
private var intentFilter: IntentFilter? = null
private var updateUIReceiver: BroadcastReceiver? = null
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
binding = DataBindingUtil.inflate(inflater,R.layout.track_list_fragment, container, false) super.onCreateView(inflater, container, savedInstanceState)
initializeAll() initializeAll()
initializeLiveDataObservers()
initializeBroadcast()
val gaanaLink = GaanaFragmentArgs.fromBundle(requireArguments()).link.substringAfter("gaana.com/") val gaanaLink = GaanaFragmentArgs.fromBundle(requireArguments()).link.substringAfter("gaana.com/")
//Link Schema: https://gaana.com/type/link //Link Schema: https://gaana.com/type/link
@ -92,16 +75,16 @@ class GaanaFragment : Fragment() {
binding.downloadingFab.visibility = View.VISIBLE binding.downloadingFab.visibility = View.VISIBLE
rotateAnim(binding.downloadingFab) rotateAnim(binding.downloadingFab)
for (track in viewModel.trackList.value!!){ for (track in baseViewModel.trackList.value!!){
if(track.downloaded != DownloadStatus.Downloaded){ if(track.downloaded != DownloadStatus.Downloaded){
track.downloaded = DownloadStatus.Downloading track.downloaded = DownloadStatus.Downloading
adapter.notifyItemChanged(viewModel.trackList.value!!.indexOf(track)) adapter.notifyItemChanged(baseViewModel.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.trackList.value?.forEach { urlList.add(it.albumArtURL) } baseViewModel.trackList.value?.forEach { urlList.add(it.albumArtURL) }
//Appending Source //Appending Source
urlList.add("gaana") urlList.add("gaana")
loadAllImages( loadAllImages(
@ -109,19 +92,18 @@ class GaanaFragment : Fragment() {
urlList urlList
) )
} }
viewModel.uiScope.launch { baseViewModel.uiScope.launch {
val finalList = viewModel.trackList.value val finalList = baseViewModel.trackList.value
if(finalList.isNullOrEmpty())showMessage("Not Downloading Any Song") if(finalList.isNullOrEmpty())showMessage("Not Downloading Any Song")
DownloadHelper.downloadAllTracks( DownloadHelper.downloadAllTracks(
viewModel.folderType, baseViewModel.folderType,
viewModel.subFolder, baseViewModel.subFolder,
finalList ?: listOf(), finalList ?: listOf(),
) )
} }
} }
} }
} }
return binding.root return binding.root
} }
@ -130,7 +112,7 @@ class GaanaFragment : Fragment() {
**/ **/
private fun initializeAll() { private fun initializeAll() {
sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java) sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java)
viewModel = ViewModelProvider(this).get(GaanaViewModel::class.java) baseViewModel = ViewModelProvider(this).get(GaanaViewModel::class.java)
viewModel.gaanaInterface = gaanaInterface viewModel.gaanaInterface = gaanaInterface
adapter = TrackListAdapter(viewModel) adapter = TrackListAdapter(viewModel)
DownloadHelper.youtubeMusicApi = youtubeMusicApi DownloadHelper.youtubeMusicApi = youtubeMusicApi
@ -140,73 +122,5 @@ class GaanaFragment : Fragment() {
(binding.trackList.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false (binding.trackList.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
} }
/**
*Live Data Observers
**/
private fun initializeLiveDataObservers() {
viewModel.trackList.observe(viewLifecycleOwner, {
if (it.isNotEmpty()){
Log.i("GaanaFragment","TrackList Updated")
adapter.submitList(it,Source.Gaana)
checkIfAllDownloaded()
}
})
viewModel.coverUrl.observe(viewLifecycleOwner, {
if(it!="Loading") bindImage(binding.coverImage,it, Source.Gaana)
})
viewModel.title.observe(viewLifecycleOwner, {
binding.titleView.text = it
})
}
private fun checkIfAllDownloaded() {
if(!viewModel.trackList.value!!.any { it.downloaded != DownloadStatus.Downloaded }){
//All Tracks Downloaded
binding.btnDownloadAll.visibility = View.GONE
binding.downloadingFab.apply{
setImageResource(R.drawable.ic_tick)
visibility = View.VISIBLE
clearAnimation()
}
}
}
private fun initializeBroadcast() {
intentFilter = IntentFilter()
intentFilter?.addAction("track_download_completed")
updateUIReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
//UI update here
if (intent != null){
val trackDetails = intent.getParcelableExtra<TrackDetails?>("track")
trackDetails?.let {
val position: Int = viewModel.trackList.value?.map { it.title }?.indexOf(trackDetails.title) ?: -1
Log.i("Track","Download Completed Intent :$position")
if(position != -1) {
val track = viewModel.trackList.value?.get(position)
track?.let{
it.downloaded = DownloadStatus.Downloaded
viewModel.trackList.value?.set(position, it)
adapter.notifyItemChanged(position)
checkIfAllDownloaded()
}
}
}
}
}
}
requireActivity().registerReceiver(updateUIReceiver, intentFilter)
}
override fun onResume() {
super.onResume()
initializeBroadcast()
}
override fun onPause() {
super.onPause()
requireActivity().unregisterReceiver(updateUIReceiver)
}
} }

View File

@ -18,47 +18,31 @@
package com.shabinder.spotiflyer.ui.spotify package com.shabinder.spotiflyer.ui.spotify
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle import android.os.Bundle
import android.util.Log 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
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.SimpleItemAnimator import androidx.recyclerview.widget.SimpleItemAnimator
import com.shabinder.spotiflyer.MainActivity import com.shabinder.spotiflyer.MainActivity
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.downloadHelper.DownloadHelper
import com.shabinder.spotiflyer.models.DownloadStatus 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.Source
import com.shabinder.spotiflyer.networking.YoutubeMusicApi
import com.shabinder.spotiflyer.recyclerView.TrackListAdapter import com.shabinder.spotiflyer.recyclerView.TrackListAdapter
import com.shabinder.spotiflyer.utils.* import com.shabinder.spotiflyer.utils.*
import com.shabinder.spotiflyer.utils.Provider.mainActivity import com.shabinder.spotiflyer.utils.Provider.mainActivity
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
class SpotifyFragment : BaseFragment() {
@AndroidEntryPoint override lateinit var baseViewModel: BaseViewModel
class SpotifyFragment : Fragment() { override lateinit var adapter: TrackListAdapter
private lateinit var binding:TrackListFragmentBinding override var source: Source = Source.Spotify
private lateinit var sharedViewModel: SharedViewModel private val viewModel: SpotifyViewModel
@Inject lateinit var youtubeMusicApi: YoutubeMusicApi get() = baseViewModel as SpotifyViewModel
private lateinit var viewModel: SpotifyViewModel
private lateinit var adapter:TrackListAdapter
private var intentFilter:IntentFilter? = null
private var updateUIReceiver: BroadcastReceiver? = null
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
@ -66,10 +50,8 @@ class SpotifyFragment : Fragment() {
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
binding = DataBindingUtil.inflate(inflater,R.layout.track_list_fragment,container,false) super.onCreateView(inflater, container, savedInstanceState)
initializeAll() initializeAll()
initializeLiveDataObservers()
initializeBroadcast()
val spotifyLink = SpotifyFragmentArgs.fromBundle(requireArguments()).link.substringAfter("open.spotify.com/") val spotifyLink = SpotifyFragmentArgs.fromBundle(requireArguments()).link.substringAfter("open.spotify.com/")
@ -142,87 +124,15 @@ class SpotifyFragment : Fragment() {
* Basic Initialization * Basic Initialization
**/ **/
private fun initializeAll() { private fun initializeAll() {
sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java) baseViewModel = ViewModelProvider(this).get(SpotifyViewModel::class.java)
viewModel = ViewModelProvider(this).get(SpotifyViewModel::class.java) adapter = TrackListAdapter(viewModel)
sharedViewModel.spotifyService.observe(viewLifecycleOwner, { sharedViewModel.spotifyService.observe(viewLifecycleOwner, {
viewModel.spotifyService = it viewModel.spotifyService = it
}) })
adapter = TrackListAdapter(viewModel)
DownloadHelper.youtubeMusicApi = youtubeMusicApi DownloadHelper.youtubeMusicApi = youtubeMusicApi
DownloadHelper.sharedViewModel = sharedViewModel DownloadHelper.sharedViewModel = sharedViewModel
DownloadHelper.statusBar = binding.statusBar DownloadHelper.statusBar = binding.statusBar
binding.trackList.adapter = adapter binding.trackList.adapter = adapter
(binding.trackList.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false (binding.trackList.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
} }
/**
*Live Data Observers
**/
private fun initializeLiveDataObservers() {
viewModel.trackList.observe(viewLifecycleOwner, {
if (it.isNotEmpty()){
Log.i("SpotifyFragment","TrackList Updated")
adapter.submitList(it,Source.Spotify)
checkIfAllDownloaded()
}
})
viewModel.coverUrl.observe(viewLifecycleOwner, {
if(it!="Loading") bindImage(binding.coverImage,it, Source.Spotify)
})
viewModel.title.observe(viewLifecycleOwner, {
binding.titleView.text = it
})
}
private fun checkIfAllDownloaded() {
if(!viewModel.trackList.value!!.any { it.downloaded != DownloadStatus.Downloaded }){
//All Tracks Downloaded
binding.btnDownloadAll.visibility = View.GONE
binding.downloadingFab.apply{
setImageResource(R.drawable.ic_tick)
visibility = View.VISIBLE
clearAnimation()
}
}
}
private fun initializeBroadcast() {
intentFilter = IntentFilter()
intentFilter?.addAction("track_download_completed")
updateUIReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
//UI update here
if (intent != null){
val trackDetails = intent.getParcelableExtra<TrackDetails?>("track")
trackDetails?.let {
val position: Int = viewModel.trackList.value?.map { it.title }?.indexOf(trackDetails.title) ?: -1
Log.i("Track","Download Completed Intent :$position")
if(position != -1) {
val track = viewModel.trackList.value?.get(position)
track?.let{
it.downloaded = DownloadStatus.Downloaded
viewModel.trackList.value?.set(position, it)
adapter.notifyItemChanged(position)
checkIfAllDownloaded()
}
}
}
}
}
}
requireActivity().registerReceiver(updateUIReceiver, intentFilter)
}
override fun onResume() {
super.onResume()
initializeBroadcast()
}
override fun onPause() {
super.onPause()
requireActivity().unregisterReceiver(updateUIReceiver)
}
} }

View File

@ -17,43 +17,26 @@
package com.shabinder.spotiflyer.ui.youtube package com.shabinder.spotiflyer.ui.youtube
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
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
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import com.github.kiulian.downloader.YoutubeDownloader
import com.shabinder.spotiflyer.R
import com.shabinder.spotiflyer.SharedViewModel
import com.shabinder.spotiflyer.databinding.TrackListFragmentBinding
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.spotify.Source import com.shabinder.spotiflyer.models.spotify.Source
import com.shabinder.spotiflyer.recyclerView.TrackListAdapter import com.shabinder.spotiflyer.recyclerView.TrackListAdapter
import com.shabinder.spotiflyer.utils.* import com.shabinder.spotiflyer.utils.*
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject
@AndroidEntryPoint class YoutubeFragment : BaseFragment() {
class YoutubeFragment : Fragment() {
private lateinit var binding: TrackListFragmentBinding override lateinit var baseViewModel: BaseViewModel
private lateinit var viewModel: YoutubeViewModel override lateinit var adapter : TrackListAdapter
private lateinit var sharedViewModel: SharedViewModel override var source: Source = Source.YouTube
@Inject lateinit var ytDownloader: YoutubeDownloader private val viewModel: YoutubeViewModel
private lateinit var adapter : TrackListAdapter get() = baseViewModel as YoutubeViewModel
private var intentFilter: IntentFilter? = null
private var updateUIReceiver: BroadcastReceiver? = null
private val sampleDomain2 = "youtu.be" private val sampleDomain2 = "youtu.be"
private val sampleDomain1 = "youtube.com" private val sampleDomain1 = "youtube.com"
@ -61,15 +44,11 @@ class YoutubeFragment : Fragment() {
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
binding = DataBindingUtil.inflate(inflater,R.layout.track_list_fragment,container,false) super.onCreateView(inflater, container, savedInstanceState)
viewModel = ViewModelProvider(this).get(YoutubeViewModel::class.java) baseViewModel = ViewModelProvider(this).get(YoutubeViewModel::class.java)
sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java)
adapter = TrackListAdapter(viewModel) adapter = TrackListAdapter(viewModel)
binding.trackList.adapter = adapter binding.trackList.adapter = adapter
initializeLiveDataObservers()
initializeBroadcast()
val args = YoutubeFragmentArgs.fromBundle(requireArguments()) val args = YoutubeFragmentArgs.fromBundle(requireArguments())
val link = args.link val link = args.link
youtubeSearch(link) youtubeSearch(link)
@ -135,76 +114,4 @@ class YoutubeFragment : Fragment() {
} }
} }
} }
override fun onResume() {
super.onResume()
initializeBroadcast()
}
private fun initializeBroadcast() {
intentFilter = IntentFilter()
intentFilter?.addAction("track_download_completed")
updateUIReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
//UI update here
if (intent != null){
val trackDetails = intent.getParcelableExtra<TrackDetails?>("track")
trackDetails?.let {
val position: Int = viewModel.trackList.value?.map { it.title }?.indexOf(trackDetails.title) ?: -1
Log.i("Track","Download Completed Intent :$position")
if(position != -1) {
val track = viewModel.trackList.value?.get(position)
track?.let{
it.downloaded = DownloadStatus.Downloaded
viewModel.trackList.value?.set(position, it)
adapter.notifyItemChanged(position)
checkIfAllDownloaded()
}
}
}
}
}
}
requireActivity().registerReceiver(updateUIReceiver, intentFilter)
}
override fun onPause() {
super.onPause()
requireActivity().unregisterReceiver(updateUIReceiver)
}
private fun checkIfAllDownloaded() {
if(!viewModel.trackList.value!!.any { it.downloaded != DownloadStatus.Downloaded }){
//All Tracks Downloaded
binding.btnDownloadAll.visibility = View.GONE
binding.downloadingFab.apply{
setImageResource(R.drawable.ic_tick)
visibility = View.VISIBLE
clearAnimation()
}
}
}
private fun initializeLiveDataObservers() {
/**
* CoverUrl Binding Observer!
**/
viewModel.coverUrl.observe(viewLifecycleOwner, {
if(it!="Loading") bindImage(binding.coverImage,it, Source.YouTube)
})
/**
* TrackList Binding Observer!
**/
viewModel.trackList.observe(viewLifecycleOwner, {
adapter.submitList(it,Source.YouTube)
})
/**
* Title Binding Observer!
**/
viewModel.title.observe(viewLifecycleOwner, {
binding.titleView.text = it
})
}
} }

View File

@ -0,0 +1,148 @@
/*
* 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 android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.github.kiulian.downloader.YoutubeDownloader
import com.shabinder.spotiflyer.R
import com.shabinder.spotiflyer.SharedViewModel
import com.shabinder.spotiflyer.databinding.TrackListFragmentBinding
import com.shabinder.spotiflyer.models.DownloadStatus
import com.shabinder.spotiflyer.models.TrackDetails
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 dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
abstract class BaseFragment : Fragment() {
@Inject open lateinit var youtubeMusicApi: YoutubeMusicApi
@Inject open lateinit var ytDownloader: YoutubeDownloader
@Inject open lateinit var gaanaInterface: GaanaInterface
open lateinit var sharedViewModel: SharedViewModel
open lateinit var binding: TrackListFragmentBinding
abstract var baseViewModel: BaseViewModel
abstract var adapter: TrackListAdapter
abstract var source: Source
private var intentFilter: IntentFilter? = null
private var updateUIReceiver: BroadcastReceiver? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater,R.layout.track_list_fragment, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initializeLiveDataObservers()
}
/**
*Live Data Observers
**/
open fun initializeLiveDataObservers() {
baseViewModel.trackList.observe(viewLifecycleOwner, {
if (it.isNotEmpty()){
Log.i("GaanaFragment","TrackList Updated")
adapter.submitList(it, source)
checkIfAllDownloaded()
}
})
baseViewModel.coverUrl.observe(viewLifecycleOwner, {
if(it!="Loading") bindImage(binding.coverImage,it, source)
})
baseViewModel.title.observe(viewLifecycleOwner, {
binding.titleView.text = it
})
}
open fun initializeBroadcast() {
intentFilter = IntentFilter()
intentFilter?.addAction("track_download_completed")
updateUIReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
//UI update here
if (intent != null){
val trackDetails = intent.getParcelableExtra<TrackDetails?>("track")
trackDetails?.let {
val position: Int = baseViewModel.trackList.value?.map { it.title }?.indexOf(trackDetails.title) ?: -1
Log.i("Track","Download Completed Intent :$position")
if(position != -1) {
val track = baseViewModel.trackList.value?.get(position)
track?.let{
it.downloaded = DownloadStatus.Downloaded
baseViewModel.trackList.value?.set(position, it)
adapter.notifyItemChanged(position)
checkIfAllDownloaded()
}
}
}
}
}
}
requireActivity().registerReceiver(updateUIReceiver, intentFilter)
}
override fun onResume() {
super.onResume()
initializeBroadcast()
}
override fun onPause() {
super.onPause()
requireActivity().unregisterReceiver(updateUIReceiver)
}
open fun checkIfAllDownloaded() {
if(!baseViewModel.trackList.value!!.any { it.downloaded != DownloadStatus.Downloaded }){
//All Tracks Downloaded
binding.btnDownloadAll.visibility = View.GONE
binding.downloadingFab.apply{
setImageResource(R.drawable.ic_tick)
visibility = View.VISIBLE
clearAnimation()
}
}
}
}

View File

@ -29,6 +29,7 @@ abstract class BaseViewModel:ViewModel() {
abstract var folderType:String abstract var folderType:String
abstract var subFolder:String abstract var subFolder:String
open val trackList = MutableLiveData<MutableList<TrackDetails>>() open val trackList = MutableLiveData<MutableList<TrackDetails>>()
private val viewModelJob:CompletableJob = Job() private val viewModelJob:CompletableJob = Job()
open val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob) open val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)

View File

@ -281,3 +281,19 @@ fun createDirectories() {
fun getEmojiByUnicode(unicode: Int): String? { fun getEmojiByUnicode(unicode: Int): String? {
return String(Character.toChars(unicode)) return String(Character.toChars(unicode))
} }
/*
internal val nullOnEmptyConverterFactory = object : Converter.Factory() {
fun converterFactory() = this
override fun responseBodyConverter(
type: Type,
annotations: Array<out Annotation>,
retrofit: Retrofit
) = object : Converter<ResponseBody, Any?> {
val nextResponseBodyConverter =
retrofit.nextResponseBodyConverter<Any?>(converterFactory(), type, annotations)
override fun convert(value: ResponseBody) =
if (value.contentLength() != 0L) nextResponseBodyConverter.convert(value) else null
}
}*/

View File

@ -20,7 +20,7 @@ buildscript {
ext{ ext{
kotlin_version = "1.4.10" kotlin_version = "1.4.10"
navigationVersion = '2.3.0' navigationVersion = '2.3.0'
ext.hilt_version = '2.28-alpha' ext.hilt_version = '2.29.1-alpha'
} }
repositories { repositories {
google() google()