ViewBinding Instead of DataBinding and Image Quality Optimised in favour of Less Cache and App Load.

This commit is contained in:
Shabinder 2020-11-10 17:30:03 +05:30
parent b3b2e6ed51
commit b39c581458
22 changed files with 172 additions and 129 deletions

View File

@ -38,10 +38,7 @@ import com.github.javiersantos.appupdater.enums.UpdateFrom
import com.shabinder.spotiflyer.databinding.MainActivityBinding
import com.shabinder.spotiflyer.networking.SpotifyService
import com.shabinder.spotiflyer.networking.SpotifyServiceTokenRequest
import com.shabinder.spotiflyer.utils.NetworkInterceptor
import com.shabinder.spotiflyer.utils.createDirectories
import com.shabinder.spotiflyer.utils.isOnline
import com.shabinder.spotiflyer.utils.startService
import com.shabinder.spotiflyer.utils.*
import com.squareup.moshi.Moshi
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
@ -160,6 +157,7 @@ class MainActivity : AppCompatActivity(){
Log.i("Spotify Authentication","Started")
val token = spotifyServiceTokenRequest.getToken()
token.value?.let {
showMessage("Success: Spotify Token Acquired",isSuccess = true)
implementSpotifyService(it.access_token)
}
Log.i("Spotify Token", token.value.toString())

View File

@ -79,7 +79,7 @@ object DownloadHelper {
showMessage("Download Started, Now You can leave the App!")
}
startService(mainActivity,downloadList)
},5000)
},3000)
}
}else{
val searchQuery = "${it.title} - ${it.artists.joinToString(",")}"

View File

@ -35,12 +35,12 @@ import kotlinx.coroutines.launch
class DownloadRecordAdapter: ListAdapter<DownloadRecord,DownloadRecordAdapter.ViewHolder>(DownloadRecordDiffCallback()) {
private val adapterScope = CoroutineScope(Dispatchers.Default)
//Remember To change when Submitting a Different List / Or Use New Submit List Fun
//Remember To change when Submitting a Different List / Or Use New Submit List Function
var source:Source = Source.Spotify
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding =DownloadRecordItemBinding.inflate(layoutInflater)
val binding = DownloadRecordItemBinding.inflate(layoutInflater)
return ViewHolder(binding)
}
@ -53,11 +53,17 @@ class DownloadRecordAdapter: ListAdapter<DownloadRecord,DownloadRecordAdapter.Vi
holder.binding.totalItems.text = "Tracks: ${item.totalFiles}"
holder.binding.type.text = item.type
holder.binding.btnAction.setOnClickListener {
if (item.link.contains("spotify",true)){
it.findNavController().navigate(DownloadRecordFragmentDirections.actionDownloadRecordToSpotifyFragment((item.link)))
}else if(item.link.contains("youtube.com",true) || item.link.contains("youtu.be",true) ){
it.findNavController().navigate(DownloadRecordFragmentDirections.actionDownloadRecordToYoutubeFragment(item.link))
}
when {
item.link.contains("spotify",true) -> {
it.findNavController().navigate(DownloadRecordFragmentDirections.actionDownloadRecordToSpotifyFragment((item.link)))
}
item.link.contains("youtube.com",true) || item.link.contains("youtu.be",true) -> {
it.findNavController().navigate(DownloadRecordFragmentDirections.actionDownloadRecordToYoutubeFragment(item.link))
}
item.link.contains("gaana",true) -> {
it.findNavController().navigate(DownloadRecordFragmentDirections.actionDownloadRecordToGaanaFragment((item.link)))
}
}
}
}
class ViewHolder(val binding: DownloadRecordItemBinding) : RecyclerView.ViewHolder(binding.root)

View File

@ -57,7 +57,8 @@ class DownloadRecordFragment : Fragment() {
}
when(binding.tabLayout.selectedTabPosition){
0-> adapter.submitList(downloadRecordViewModel.spotifyList,Source.Spotify)
1-> adapter.submitList(downloadRecordViewModel.ytList,Source.YouTube)
1-> adapter.submitList(downloadRecordViewModel.gaanaList,Source.Gaana)
2-> adapter.submitList(downloadRecordViewModel.ytList,Source.YouTube)
}
}
})
@ -67,7 +68,8 @@ class DownloadRecordFragment : Fragment() {
override fun onTabSelected(tab: TabLayout.Tab?) {
when(tab?.position){
0-> adapter.submitList(downloadRecordViewModel.spotifyList,Source.Spotify)
1-> adapter.submitList(downloadRecordViewModel.ytList,Source.YouTube)
1-> adapter.submitList(downloadRecordViewModel.gaanaList,Source.Gaana)
2-> adapter.submitList(downloadRecordViewModel.ytList,Source.YouTube)
}
}
override fun onTabReselected(tab: TabLayout.Tab?) {}

View File

@ -41,6 +41,7 @@ class DownloadRecordViewModel @ViewModelInject constructor(val databaseDAO: Data
init {
getDownloadRecordList()
}
private fun getDownloadRecordList() {
uiScope.launch {
downloadRecordList.postValue(databaseDAO.getRecord().toMutableList())

View File

@ -40,6 +40,7 @@ class GaanaViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO)
override var folderType:String = ""
override var subFolder:String = ""
var gaanaInterface : GaanaInterface? = null
val gaanaPlaceholderImageUrl = "https://a10.gaanacdn.com/images/social/gaana_social.jpg"
fun gaanaSearch(type:String,link:String){
when(type){
@ -109,6 +110,7 @@ class GaanaViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO)
trackList.value = it.tracks.toTrackDetailsList()
title.value = link
//coverUrl.value = "TODO"
coverUrl.value = gaanaPlaceholderImageUrl
withContext(Dispatchers.IO){
databaseDAO.insert(DownloadRecord(
type = "Playlist",

View File

@ -17,9 +17,6 @@
package com.shabinder.spotiflyer.ui.mainfragment
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.text.SpannableStringBuilder
import android.view.LayoutInflater
@ -32,10 +29,7 @@ import com.shabinder.spotiflyer.MainActivity
import com.shabinder.spotiflyer.R
import com.shabinder.spotiflyer.SharedViewModel
import com.shabinder.spotiflyer.databinding.MainFragmentBinding
import com.shabinder.spotiflyer.utils.Provider
import com.shabinder.spotiflyer.utils.isOnline
import com.shabinder.spotiflyer.utils.showMessage
import com.shabinder.spotiflyer.utils.showNoConnectionAlert
import com.shabinder.spotiflyer.utils.*
import com.shreyaspatil.easyupipayment.EasyUpiPayment
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
@ -122,82 +116,22 @@ class MainFragment : Fragment() {
private fun initializeAll() {
mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java)
openYTButton()
openSpotifyButton()
openGithubButton()
openInstaButton()
openLinkedInButton()
historyButton()
binding.usage.text = usageText()
binding.btnDonate.setOnClickListener {
easyUpiPayment.startPayment()
binding.apply {
btnGaana.openPlatformOnClick("com.gaana","http://gaana.com")
btnSpotify.openPlatformOnClick("com.spotify.music","http://open.spotify.com")
btnYoutube.openPlatformOnClick("com.google.android.youtube","http://m.youtube.com")
btnGithub.openPlatformOnClick("http://github.com/Shabinder/SpotiFlyer")
btnInsta.openPlatformOnClick("http://www.instagram.com/mr.shabinder")
btnHistory.setOnClickListener {
findNavController().navigate(MainFragmentDirections.actionMainFragmentToDownloadRecord())
}
usage.text = usageText()
btnDonate.setOnClickListener {
easyUpiPayment.startPayment()
}
}
}
/**
* Implementing buttons
**/
private fun historyButton() {
binding.btnHistory.setOnClickListener {
findNavController().navigate(MainFragmentDirections.actionMainFragmentToDownloadRecord())
}
}
private fun openSpotifyButton() {
val manager: PackageManager = requireActivity().packageManager
try {
val i = manager.getLaunchIntentForPackage("com.spotify.music")
?: throw PackageManager.NameNotFoundException()
i.addCategory(Intent.CATEGORY_LAUNCHER)
binding.btnSpotify.setOnClickListener { startActivity(i) }
} catch (e: PackageManager.NameNotFoundException) {
val uri: Uri =
Uri.parse("http://open.spotify.com")
val intent = Intent(Intent.ACTION_VIEW, uri)
binding.btnSpotify.setOnClickListener {
startActivity(intent)
}
}
}
private fun openYTButton() {
val manager: PackageManager = requireActivity().packageManager
try {
val i = manager.getLaunchIntentForPackage("com.google.android.youtube")
?: throw PackageManager.NameNotFoundException()
i.addCategory(Intent.CATEGORY_LAUNCHER)
binding.btnYoutube.setOnClickListener { startActivity(i) }
} catch (e: PackageManager.NameNotFoundException) {
val uri: Uri =
Uri.parse("http://m.youtube.com")
val intent = Intent(Intent.ACTION_VIEW, uri)
binding.btnYoutube.setOnClickListener {
startActivity(intent)
}
}
}
private fun openGithubButton() {
val uri: Uri =
Uri.parse("http://github.com/Shabinder/SpotiFlyer")
val intent = Intent(Intent.ACTION_VIEW, uri)
binding.btnGithubSpotify.setOnClickListener {
startActivity(intent)
}
}
private fun openLinkedInButton() {
val uri: Uri =
Uri.parse("https://in.linkedin.com/in/shabinder")
val intent = Intent(Intent.ACTION_VIEW, uri)
binding.btnLinkedin.setOnClickListener {
startActivity(intent)
}
}
private fun openInstaButton() {
val uri: Uri =
Uri.parse("http://www.instagram.com/mr.shabinder")
val intent = Intent(Intent.ACTION_VIEW, uri)
binding.developerInstaSpotify.setOnClickListener {
startActivity(intent)
}
}
private fun usageText(): SpannableStringBuilder {
return SpannableStringBuilder()
.append(getText(R.string.d_one)).append("\n")

View File

@ -26,7 +26,6 @@ import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.SimpleItemAnimator
import com.shabinder.spotiflyer.MainActivity
import com.shabinder.spotiflyer.downloadHelper.DownloadHelper
import com.shabinder.spotiflyer.models.DownloadStatus
import com.shabinder.spotiflyer.models.spotify.Source
@ -63,8 +62,9 @@ class SpotifyFragment : TrackListFragment<SpotifyViewModel,SpotifyFragmentArgs>(
Log.i("Spotify Fragment", "$type : $link")
if(sharedViewModel.spotifyService.value == null){//Authentication pending!!
(activity as MainActivity).authenticateSpotify()
if(isOnline()) mainActivity.authenticateSpotify()
}
when{
@ -89,7 +89,7 @@ class SpotifyFragment : TrackListFragment<SpotifyViewModel,SpotifyFragmentArgs>(
binding.downloadingFab.visibility = View.VISIBLE
rotateAnim(binding.downloadingFab)
for (track in this.viewModel.trackList.value!!){
for (track in this.viewModel.trackList.value ?: listOf()){
if(track.downloaded != DownloadStatus.Downloaded){
track.downloaded = DownloadStatus.Downloading
adapter.notifyItemChanged(this.viewModel.trackList.value!!.indexOf(track))

View File

@ -52,7 +52,7 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
}
trackList.value = listOf(it).toTrackDetailsList()
title.value = it.name
coverUrl.value = it.album!!.images?.get(0)!!.url!!
coverUrl.value = it.album!!.images?.elementAtOrNull(1)?.url ?: it.album!!.images?.elementAtOrNull(0)?.url
withContext(Dispatchers.IO){
databaseDAO.insert(DownloadRecord(
type = "Track",
@ -77,11 +77,11 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
if(File(finalOutputDir(it.name!!,folderType,subFolder)).exists()){//Download Already Present!!
it.downloaded = DownloadStatus.Downloaded
}
it.album = Album(images = listOf(Image(url = albumObject.images?.get(0)?.url)))
it.album = Album(images = listOf(Image(url = albumObject.images?.elementAtOrNull(1)?.url ?: albumObject.images?.elementAtOrNull(0)?.url )))
}
trackList.value = albumObject?.tracks?.items?.toTrackDetailsList()
title.value = albumObject?.name
coverUrl.value = albumObject?.images?.get(0)?.url
coverUrl.value = albumObject?.images?.elementAtOrNull(1)?.url ?: albumObject?.images?.elementAtOrNull(0)?.url
withContext(Dispatchers.IO){
databaseDAO.insert(DownloadRecord(
type = "Album",
@ -124,7 +124,7 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
Log.i("Total Tracks Fetched",tempTrackList.size.toString())
trackList.value = tempTrackList.toTrackDetailsList()
title.value = playlistObject?.name
coverUrl.value = playlistObject?.images?.get(0)?.url.toString()
coverUrl.value = playlistObject?.images?.elementAtOrNull(1)?.url ?: playlistObject?.images?.firstOrNull()?.url.toString()
withContext(Dispatchers.IO){
databaseDAO.insert(DownloadRecord(
type = "Playlist",
@ -153,14 +153,14 @@ class SpotifyViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
durationSec = (it.duration_ms/1000).toInt(),
albumArt = File(
Environment.getExternalStorageDirectory(),
Provider.defaultDir +".Images/" + (it.album?.images?.get(0)?.url.toString()).substringAfterLast('/') + ".jpeg"),
Provider.defaultDir +".Images/" + (it.album?.images?.elementAtOrNull(1)?.url ?: it.album?.images?.firstOrNull()?.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()
albumArtURL = it.album?.images?.elementAtOrNull(1)?.url ?: it.album?.images?.firstOrNull()?.url.toString()
)
}.toMutableList()

View File

@ -27,11 +27,8 @@ import com.shabinder.spotiflyer.database.DownloadRecord
import com.shabinder.spotiflyer.models.DownloadStatus
import com.shabinder.spotiflyer.models.TrackDetails
import com.shabinder.spotiflyer.models.spotify.Source
import com.shabinder.spotiflyer.utils.*
import com.shabinder.spotiflyer.utils.Provider.defaultDir
import com.shabinder.spotiflyer.utils.TrackListViewModel
import com.shabinder.spotiflyer.utils.finalOutputDir
import com.shabinder.spotiflyer.utils.removeIllegalChars
import com.shabinder.spotiflyer.utils.showMessage
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -48,6 +45,7 @@ class YoutubeViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
override var subFolder = ""
fun getYTPlaylist(searchId:String, ytDownloader:YoutubeDownloader){
if(!isOnline())return
try{
uiScope.launch(Dispatchers.IO) {
Log.i("YT Playlist",searchId)
@ -105,6 +103,7 @@ class YoutubeViewModel @ViewModelInject constructor(val databaseDAO: DatabaseDAO
@SuppressLint("DefaultLocale")
fun getYTTrack(searchId:String, ytDownloader:YoutubeDownloader) {
if(!isOnline())return
try{
uiScope.launch(Dispatchers.IO) {
Log.i("YT Video",searchId)

View File

@ -0,0 +1,45 @@
/*
* 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.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.view.View
import com.shabinder.spotiflyer.utils.Provider.mainActivity
fun View.openPlatformOnClick(packageName:String, websiteAddress:String){
val manager: PackageManager = mainActivity.packageManager
try {
val i = manager.getLaunchIntentForPackage(packageName)
?: throw PackageManager.NameNotFoundException()
i.addCategory(Intent.CATEGORY_LAUNCHER)
this.setOnClickListener { mainActivity.startActivity(i) }
} catch (e: PackageManager.NameNotFoundException) {
val uri: Uri =
Uri.parse(websiteAddress)
val intent = Intent(Intent.ACTION_VIEW, uri)
this.setOnClickListener { mainActivity.startActivity(intent) }
}
}
fun View.openPlatformOnClick(websiteAddress:String){
val uri: Uri =
Uri.parse(websiteAddress)
val intent = Intent(Intent.ACTION_VIEW, uri)
this.setOnClickListener { mainActivity.startActivity(intent) }
}

View File

@ -36,6 +36,7 @@ import com.shabinder.spotiflyer.models.DownloadStatus
import com.shabinder.spotiflyer.models.TrackDetails
import com.shabinder.spotiflyer.models.spotify.Source
import com.shabinder.spotiflyer.recyclerView.TrackListAdapter
import com.shabinder.spotiflyer.utils.Provider.mainActivity
abstract class TrackListFragment<VM : TrackListViewModel , args: NavArgs> : Fragment() {
@ -50,6 +51,10 @@ abstract class TrackListFragment<VM : TrackListViewModel , args: NavArgs> : Frag
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if(!isOnline()){
showNoConnectionAlert()
mainActivity.onBackPressed()
}
sharedViewModel = ViewModelProvider(this.requireActivity()).get(SharedViewModel::class.java)
}
@ -72,7 +77,7 @@ abstract class TrackListFragment<VM : TrackListViewModel , args: NavArgs> : Frag
**/
private fun initializeLiveDataObservers() {
viewModel.trackList.observe(viewLifecycleOwner, {
if (it.isNotEmpty()){
if (!it.isNullOrEmpty()){
Log.i("GaanaFragment","TrackList Updated")
adapter.submitList(it, source)
checkIfAllDownloaded()
@ -80,7 +85,7 @@ abstract class TrackListFragment<VM : TrackListViewModel , args: NavArgs> : Frag
})
viewModel.coverUrl.observe(viewLifecycleOwner, {
if(it!="Loading") bindImage(binding.coverImage,it, source)
it?.let{bindImage(binding.coverImage,it, source)}
})
viewModel.title.observe(viewLifecycleOwner, {

View File

@ -35,7 +35,7 @@ abstract class TrackListViewModel:ViewModel() {
private val loading = "Loading!"
open var title = MutableLiveData<String>().apply { value = loading }
open var coverUrl = MutableLiveData<String>().apply { value = loading }
open var coverUrl = MutableLiveData<String>()
override fun onCleared() {
super.onCleared()

View File

@ -96,7 +96,7 @@ fun isOnline(): Boolean {
return result
}
fun showMessage(message: String, long: Boolean = false){
fun showMessage(message: String, long: Boolean = false,isSuccess:Boolean = false , isError:Boolean = false){
CoroutineScope(Dispatchers.Main).launch{
Snackbar.make(
mainActivity.snackBarAnchor,
@ -106,6 +106,11 @@ fun showMessage(message: String, long: Boolean = false){
setAction("Ok") {
dismiss()
}
setActionTextColor(ContextCompat.getColor(mainActivity,R.color.black))
when{
isSuccess -> setBackgroundTint(ContextCompat.getColor(mainActivity,R.color.successGreen))
isError -> setBackgroundTint(ContextCompat.getColor(mainActivity,R.color.errorRed))
}
}.show()
}
}

View File

@ -304,7 +304,7 @@ class ForegroundService : Service(){
}
}
speed = 0
updateNotification()
// updateNotification()
}
override fun onDeleted(download: Download) {
@ -343,7 +343,7 @@ class ForegroundService : Service(){
val track = requestMap[download.request]
Log.i(tag,"${track?.title} ETA: ${etaInMilliSeconds/1000} sec")
speed = (downloadedBytesPerSecond/1000)
updateNotification()
// updateNotification()
}
}
@ -448,7 +448,7 @@ class ForegroundService : Service(){
.setSubText("Total: $total Completed:$converted")
.setNotificationSilent()
.setStyle(NotificationCompat.InboxStyle()
.setBigContentTitle("Speed: $speed KB/s")
// .setBigContentTitle("Speed: $speed KB/s")
.addLine(messageList[0])
.addLine(messageList[1])
.addLine(messageList[2])
@ -540,7 +540,7 @@ class ForegroundService : Service(){
.setNotificationSilent()
.setSubText("Total: $total Completed:$converted")
.setStyle(NotificationCompat.InboxStyle()
.setBigContentTitle("Speed: $speed KB/s")
// .setBigContentTitle("Speed: $speed KB/s")
.addLine(messageList[0])
.addLine(messageList[1])
.addLine(messageList[2])

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,27 @@
<!--
~ Copyright (C) 2020 Shabinder Singh
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="83dp"
android:height="45dp"
android:viewportWidth="83"
android:viewportHeight="33">
<path
android:fillColor="#F42C30"
android:fillType="evenOdd"
android:pathData="M58.7,19.8c0.2,-1 0.3,-2 0.5,-2.9c0.6,-3.2 1.1,-6.4 1.7,-9.6c0.2,-0.9 -0.4,-1.6 -1.4,-1.6c-0.6,0 -1.2,0 -1.9,0c-1.3,0 -2.1,0.8 -2.4,2c-0.7,3.9 -1.4,7.9 -2.1,11.8c0,0.1 -0.2,0.3 -0.3,0.3c-1.8,0 -3.5,0 -5.3,-0.2c-1.1,-0.1 -2.1,-0.6 -2.7,-1.6c0,0 -0.1,-0.1 -0.1,-0.2c-0.2,0.3 -0.5,0.5 -0.7,0.7c-0.8,0.8 -1.7,1.3 -2.9,1.2c-0.8,-0.1 -1.7,0 -2.5,-0.1c-1.4,-0.3 -2.6,-1 -3.3,-2.4c-0.1,0.5 -0.2,1 -0.3,1.4c-0.2,1.2 -0.2,1.1 -1.4,1.1c-0.9,0 -1.7,-0.2 -2.4,-0.6c-0.6,-0.3 -1,-0.8 -1.6,-1.3c-0.2,0.2 -0.4,0.4 -0.6,0.7c-0.8,0.8 -1.7,1.2 -2.9,1.2c-1.1,0 -2.2,0 -3.3,-0.4c-1.9,-0.7 -3,-2.4 -2.6,-4.4c0.4,-2.6 0.8,-5.3 1.4,-7.9c0.6,-2.6 2.2,-4.4 5,-5c0.4,-0.1 0.8,-0.1 1.2,-0.1c2.3,0 4.6,0 6.9,0c0.1,0 0.2,0 0.4,0c-0.2,1.3 -0.5,2.5 -0.7,3.8c-0.5,2.9 -1,5.7 -1.5,8.6c0,0.3 0.1,0.6 0.2,0.8c0.3,0.6 1.4,1 2.1,0.9c0.3,-3 0.9,-6 1.5,-9c0.6,-2.6 2.2,-4.5 5,-5c0.4,-0.1 0.8,-0.1 1.2,-0.1c2.3,0 4.6,0 6.9,0c0.1,0 0.2,0 0.4,0c-0.1,0.8 -0.3,1.5 -0.4,2.3c-0.6,3.4 -1.2,6.8 -1.9,10.2c-0.1,0.5 0.1,0.9 0.5,1.2c0.2,0.1 0.3,0.2 0.5,0.3c0.4,0.1 0.8,0.3 1.1,0.2c0.5,-0.1 0.3,-0.6 0.4,-1c0.7,-3.8 1.4,-7.7 2.1,-11.5c0.1,-0.5 0.2,-1.1 0.3,-1.6c0.1,0 0.3,0 0.4,0c2.3,0 4.5,0 6.8,0c0.9,0 1.7,0.2 2.5,0.6c1.4,0.7 2.1,1.7 2.1,3.2c0,1.3 -0.3,2.5 -0.5,3.7c-0.5,3.1 -1.1,6.3 -1.7,9.4c0,0.2 0,0.4 -0.1,0.5c0,0.1 -0.2,0.2 -0.2,0.2C61,19.8 59.9,19.8 58.7,19.8L58.7,19.8zM30.8,5.7c-0.1,0 -0.2,0 -0.2,0c-1.1,0 -2.3,0 -3.4,0c-1.1,0 -2,0.7 -2.2,1.8c-0.4,2.3 -0.9,4.7 -1.3,7c-0.2,1.2 0.4,1.9 1.7,1.9c0.5,0 1,0 1.5,0c1.4,0 2.2,-0.7 2.4,-2c0.4,-2.1 0.8,-4.1 1.1,-6.2C30.5,7.3 30.7,6.5 30.8,5.7L30.8,5.7zM46,5.7c-0.1,0 -0.2,0 -0.2,0c-1.2,0 -2.3,0 -3.4,0c-1.2,0 -2,0.7 -2.2,1.8c-0.4,2.3 -0.9,4.7 -1.3,7c-0.2,1.1 0.3,1.7 1.4,1.8c0.6,0.1 1.2,0 1.8,0c1.3,0 2.2,-0.7 2.4,-2l1.1,-5.7C45.6,7.7 45.8,6.7 46,5.7zM14.6,19.8c-0.3,0 -0.6,0 -0.8,0c-1.3,0 -2.5,0 -3.8,-0.1c-1.9,-0.2 -3.2,-1.4 -3.6,-3c-0.2,-0.9 -0.1,-1.7 0.1,-2.6c0.4,-2.3 0.8,-4.6 1.3,-6.9c0.5,-2.8 2.7,-4.8 5.6,-5c1.7,-0.1 3.4,-0.1 5.1,-0.1c0.9,0 1.8,0 2.8,0c-0.1,0.7 -0.2,1.4 -0.3,2c-0.7,3.7 -1.3,7.3 -2,11c-0.4,2.3 -0.8,4.6 -1.3,6.9c-0.6,3.1 -3.1,4.6 -5.5,4.9C11.6,27 11,27 10.4,27c-2.1,0 -4.2,0 -6.3,0c0,0 -0.1,0 -0.1,0c0,-0.1 0,-0.1 0,-0.2c0.6,-1 1.2,-2.1 1.8,-3.1c0.1,-0.1 0.4,-0.2 0.6,-0.2c1.8,0 3.7,0 5.5,0c1.4,0 2.1,-0.6 2.4,-1.9C14.4,21 14.5,20.5 14.6,19.8L14.6,19.8zM13.2,16.3L13.2,16.3c0.5,0.1 0.9,0 1.4,0.1c0.5,0 0.6,-0.1 0.7,-0.6c0.5,-2.8 1,-5.6 1.5,-8.4c0.2,-1.1 -0.4,-1.7 -1.5,-1.8c-0.6,0 -1.2,0 -1.8,0c-1.2,0 -2,0.7 -2.3,1.9c-0.2,1.3 -0.5,2.6 -0.7,3.8c-0.2,1.2 -0.4,2.3 -0.6,3.5c-0.1,0.8 0.4,1.4 1.2,1.5C11.9,16.4 12.6,16.3 13.2,16.3zM78.9,2.1c-0.3,1.8 -0.6,3.5 -0.9,5.2c-0.4,2.4 -0.9,4.8 -1.3,7.1c-0.2,1 0.2,1.6 1.2,1.9c0.1,0 0.3,0.3 0.2,0.4c-0.2,1 -0.4,2 -0.5,3.1c-1.6,-0.1 -3,-0.6 -4,-1.9c-0.3,0.3 -0.5,0.5 -0.7,0.8c-0.8,0.8 -1.7,1.2 -2.9,1.2c-1,-0.1 -2,0 -3,-0.3c-2.2,-0.7 -3.3,-2.4 -3,-4.7c0.4,-2.6 0.8,-5.2 1.4,-7.8c0.6,-2.4 2,-4.2 4.6,-4.8c0.5,-0.1 1.1,-0.2 1.6,-0.2c2.4,0 4.7,0 7.1,0C78.7,2.1 78.8,2.1 78.9,2.1L78.9,2.1zM74.7,5.7c-0.2,0 -0.3,0 -0.4,0c-1.1,0 -2.2,0 -3.3,0c-1.1,0 -2,0.7 -2.2,1.8c-0.5,2.4 -0.9,4.8 -1.3,7.3c-0.2,0.9 0.3,1.5 1.3,1.7c0.6,0.1 1.2,0.1 1.9,0.1c1.4,0 2.2,-0.7 2.5,-2.1c0.4,-2.3 0.8,-4.5 1.2,-6.7C74.5,6.9 74.6,6.3 74.7,5.7z"/>
</vector>

View File

@ -26,7 +26,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
style="@style/Widget.AppCompat.EditText.Gradient"
style="@style/Widget.AppCompat.TextView.Gradient"
android:drawablePadding="5dp"
android:fontFamily="@font/raleway_semibold"
android:text=" Download History "
@ -56,6 +56,11 @@
android:icon="@drawable/ic_spotify_logo"
android:text="Spotify" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:icon="@drawable/gaana"
android:text="Gaana" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"

View File

@ -20,7 +20,6 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mainActivity"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View

View File

@ -31,7 +31,7 @@
<EditText
android:id="@+id/linkSearch"
style="@style/Widget.AppCompat.EditText.Gradient"
style="@style/Widget.AppCompat.TextView.Gradient"
android:layout_height="46dp"
android:layout_marginTop="24dp"
android:ems="10"
@ -113,7 +113,7 @@
android:layout_marginEnd="2dp"
android:contentDescription="Open Spotify App Button"
android:src="@drawable/ic_spotify_logo"
app:layout_constraintEnd_toStartOf="@+id/btn_youtube"
app:layout_constraintEnd_toStartOf="@+id/btn_Gaana"
android:padding="6dp"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="@+id/appSubTitle"
@ -122,11 +122,22 @@
<ImageButton
android:id="@+id/btn_youtube"
style="@style/Widget.AppCompat.ImageButton.platformIcon"
android:contentDescription="Open Youtube App Button"
android:src="@drawable/ic_youtube"
app:layout_constraintBottom_toBottomOf="@+id/btn_spotify"
android:contentDescription="Open Youtube App Button"
app:layout_constraintStart_toEndOf="@+id/btn_spotify"
app:layout_constraintEnd_toEndOf="@+id/appSubTitle"
app:layout_constraintStart_toEndOf="@+id/btn_Gaana"
app:layout_constraintTop_toTopOf="@+id/btn_spotify"/>
<ImageButton
android:id="@+id/btn_Gaana"
style="@style/Widget.AppCompat.ImageButton.platformIcon"
android:contentDescription="Open Gaana App Button"
android:padding="6dp"
android:src="@drawable/gaana"
app:layout_constraintBottom_toBottomOf="@+id/btn_spotify"
app:layout_constraintEnd_toStartOf="@+id/btn_youtube"
app:layout_constraintStart_toEndOf="@+id/btn_spotify"
app:layout_constraintTop_toTopOf="@+id/btn_spotify" />
<TextView
@ -139,10 +150,10 @@
android:textAlignment="center"
android:textColor="#D0838383"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="@+id/developer_insta_spotify"
app:layout_constraintBottom_toBottomOf="@+id/btn_Insta"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/btn_linkedin"
app:layout_constraintTop_toTopOf="@+id/btn_github_spotify" />
app:layout_constraintTop_toTopOf="@+id/btn_github" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_donate"
@ -177,7 +188,7 @@
<ImageButton
android:id="@+id/btn_github_spotify"
android:id="@+id/btn_github"
style="@style/Widget.AppCompat.ImageButton.platformIcon"
android:src="@drawable/ic_github"
app:layout_constraintBottom_toTopOf="@+id/btn_linkedin"
@ -190,13 +201,13 @@
android:id="@+id/btn_linkedin"
style="@style/Widget.AppCompat.ImageButton.platformIcon"
android:src="@drawable/ic_linkedin"
app:layout_constraintBottom_toTopOf="@+id/developer_insta_spotify"
app:layout_constraintBottom_toTopOf="@+id/btn_Insta"
app:layout_constraintStart_toStartOf="parent"
android:contentDescription="Open LinkedIN App Button"
app:layout_constraintTop_toBottomOf="@+id/btn_github_spotify"/>
app:layout_constraintTop_toBottomOf="@+id/btn_github"/>
<ImageButton
android:id="@+id/developer_insta_spotify"
android:id="@+id/btn_Insta"
style="@style/Widget.AppCompat.ImageButton.platformIcon"
android:src="@drawable/ic_instagram"
app:layout_constraintBottom_toTopOf="@+id/btn_donate"

View File

@ -25,7 +25,7 @@
<color name="grey">#99FFFFFF</color>
<color name="black">#000000</color>
<color name="dark">#121212</color>
<color name="successGreen">#4BB543</color>
<color name="successGreen">#59C351</color>
<color name="errorRed">#FF9494</color>
</resources>

View File

@ -25,6 +25,8 @@
<item name="colorError">#FF5E5E</item>
<item name="colorOnError">@color/black</item>
<item name="colorSurface">@color/dark</item>
<item name="statusBarScrim">@color/black</item>
<item name="android:statusBarColor">@color/black</item>
<item name="colorOnSurface">@color/white</item>
<item name="colorPrimary">#FC5C7D</item>
<item name="colorOnPrimary">@color/white</item>
@ -62,11 +64,13 @@
<item name="android:scaleType">fitCenter</item>
<item name="android:layout_margin">8dp</item>
</style>
<style name="Widget.AppCompat.EditText.Gradient" parent="Widget.AppCompat.EditText">
<style name="Widget.AppCompat.TextView.Gradient">
<item name="android:background">@drawable/text_background_accented</item>
<item name="android:textAlignment">center</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:inputType">text</item>
<item name="android:gravity">center</item>
<item name="android:layout_gravity">center</item>
<item name="android:padding">8dp</item>
<item name="android:textSize">18sp</item>
<item name="android:textColor">@color/white</item>