Donation and other Actions Implemented

This commit is contained in:
shabinder 2021-01-02 19:23:10 +05:30
parent d91313370a
commit e056344d28
9 changed files with 122 additions and 34 deletions

View File

@ -5,6 +5,8 @@ plugins {
id 'kotlin-kapt' id 'kotlin-kapt'
id 'dagger.hilt.android.plugin' id 'dagger.hilt.android.plugin'
id 'kotlinx-serialization' id 'kotlinx-serialization'
id 'com.google.gms.google-services'
id 'com.google.firebase.crashlytics'
} }
kapt { kapt {
@ -127,9 +129,6 @@ dependencies {
implementation "com.squareup.retrofit2:converter-scalars:2.9.0" implementation "com.squareup.retrofit2:converter-scalars:2.9.0"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1" implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1"
//Glide-Image Loading
implementation "dev.chrisbanes.accompanist:accompanist-glide:0.4.1"
//Coil-Image Loading //Coil-Image Loading
implementation "dev.chrisbanes.accompanist:accompanist-coil:$coil_version" implementation "dev.chrisbanes.accompanist:accompanist-coil:$coil_version"
implementation "dev.chrisbanes.accompanist:accompanist-insets:$coil_version" implementation "dev.chrisbanes.accompanist:accompanist-insets:$coil_version"
@ -140,9 +139,16 @@ dependencies {
//Extras //Extras
implementation 'me.xdrop:fuzzywuzzy:1.3.1' implementation 'me.xdrop:fuzzywuzzy:1.3.1'
implementation 'com.mpatric:mp3agic:0.9.1' implementation 'com.mpatric:mp3agic:0.9.1'
implementation 'com.razorpay:checkout:1.6.4'
implementation "com.github.amitbd1508:AppUpdater:4.1.0"
implementation "androidx.tonyodev.fetch2:xfetch2:3.1.5" implementation "androidx.tonyodev.fetch2:xfetch2:3.1.5"
implementation 'com.github.sealedtx:java-youtube-downloader:2.4.4' implementation 'com.github.sealedtx:java-youtube-downloader:2.4.4'
//Crashlytics & Analytics
implementation platform('com.google.firebase:firebase-bom:26.2.0')
implementation 'com.google.firebase:firebase-crashlytics-ktx'
implementation 'com.google.firebase:firebase-analytics-ktx'
//Test //Test
testImplementation 'junit:junit:4.13.1' testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.ext:junit:1.1.2'

View File

@ -29,6 +29,11 @@ import androidx.lifecycle.ViewModelProvider
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.example.jetcaster.util.verticalGradientScrim import com.example.jetcaster.util.verticalGradientScrim
import com.github.javiersantos.appupdater.AppUpdater
import com.github.javiersantos.appupdater.enums.Display
import com.github.javiersantos.appupdater.enums.UpdateFrom
import com.razorpay.Checkout
import com.razorpay.PaymentResultListener
import com.shabinder.spotiflyer.models.DownloadStatus import com.shabinder.spotiflyer.models.DownloadStatus
import com.shabinder.spotiflyer.navigation.ComposeNavigation import com.shabinder.spotiflyer.navigation.ComposeNavigation
import com.shabinder.spotiflyer.navigation.navigateToTrackList import com.shabinder.spotiflyer.navigation.navigateToTrackList
@ -43,14 +48,13 @@ import dagger.hilt.android.AndroidEntryPoint
import dev.chrisbanes.accompanist.insets.ProvideWindowInsets import dev.chrisbanes.accompanist.insets.ProvideWindowInsets
import dev.chrisbanes.accompanist.insets.statusBarsHeight import dev.chrisbanes.accompanist.insets.statusBarsHeight
import kotlinx.coroutines.* import kotlinx.coroutines.*
import okhttp3.Dispatcher
import javax.inject.Inject import javax.inject.Inject
/* /*
* This is App's God Activity * This is App's God Activity
* */ * */
@AndroidEntryPoint @AndroidEntryPoint
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity(), PaymentResultListener {
private lateinit var navController: NavHostController private lateinit var navController: NavHostController
private lateinit var updateUIReceiver: BroadcastReceiver private lateinit var updateUIReceiver: BroadcastReceiver
@ -98,13 +102,25 @@ class MainActivity : AppCompatActivity() {
} }
private fun initialize() { private fun initialize() {
Checkout.preload(applicationContext)
requestStoragePermission() requestStoragePermission()
disableDozeMode() disableDozeMode()
//checkIfLatestVersion() checkIfLatestVersion()
createDirectories() createDirectories()
handleIntentFromExternalActivity() handleIntentFromExternalActivity()
} }
private fun checkIfLatestVersion() {
AppUpdater(this,0).run {
setDisplay(Display.NOTIFICATION)
showAppUpdated(true)//true:Show App is Updated Dialog
setUpdateFrom(UpdateFrom.XML)
setUpdateXML("https://raw.githubusercontent.com/Shabinder/SpotiFlyer/master/app/src/main/res/xml/app_update.xml")
setCancelable(false)
start()
}
}
override fun onNewIntent(intent: Intent?) { override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent) super.onNewIntent(intent)
handleIntentFromExternalActivity(intent) handleIntentFromExternalActivity(intent)
@ -208,7 +224,6 @@ class MainActivity : AppCompatActivity() {
val string = it.replace("\n".toRegex(), " ") val string = it.replace("\n".toRegex(), " ")
val link = filterLinkRegex.find(string)?.value.toString() val link = filterLinkRegex.find(string)?.value.toString()
log("Intent Link",link) log("Intent Link",link)
sharedViewModel.updateLink(link)
navController.navigateToTrackList(link) navController.navigateToTrackList(link)
} }
} }
@ -227,6 +242,24 @@ class MainActivity : AppCompatActivity() {
init { init {
instance = this instance = this
} }
override fun onPaymentError(errorCode: Int, response: String?) {
try{
showDialog("Payment Failed", "$response")
}catch (e: Exception){
log("Razorpay Payment","Exception in onPaymentSuccess $response")
}
}
override fun onPaymentSuccess(razorpayPaymentId: String?) {
try{
showDialog("Payment Successful", "ThankYou!")
}catch (e: Exception){
showDialog("Razorpay Payment, Error Occurred.")
log("Razorpay Payment","Exception in onPaymentSuccess, ${e.message}")
}
}
} }
@Composable @Composable

View File

@ -36,7 +36,7 @@ data class TrackDetails(
var albumArtURL: String, var albumArtURL: String,
var source: Source, var source: Source,
var downloaded: DownloadStatus = DownloadStatus.NotDownloaded, var downloaded: DownloadStatus = DownloadStatus.NotDownloaded,
var progress: Int = 0, var progress: Int = 2,//2 for visual progress bar hint
var outputFile: String, var outputFile: String,
var videoID:String? = null var videoID:String? = null
):Parcelable ):Parcelable

View File

@ -8,6 +8,7 @@ import androidx.navigation.compose.*
import androidx.navigation.compose.popUpTo import androidx.navigation.compose.popUpTo
import com.shabinder.spotiflyer.ui.home.Home import com.shabinder.spotiflyer.ui.home.Home
import com.shabinder.spotiflyer.ui.tracklist.TrackList import com.shabinder.spotiflyer.ui.tracklist.TrackList
import com.shabinder.spotiflyer.utils.sharedViewModel
@Composable @Composable
fun ComposeNavigation(navController: NavHostController) { fun ComposeNavigation(navController: NavHostController) {
@ -36,6 +37,7 @@ fun ComposeNavigation(navController: NavHostController) {
} }
fun NavController.navigateToTrackList(link:String, singleInstance: Boolean = true, inclusive:Boolean = false) { fun NavController.navigateToTrackList(link:String, singleInstance: Boolean = true, inclusive:Boolean = false) {
sharedViewModel.updateLink(link)
navigate("track_list/$link") { navigate("track_list/$link") {
launchSingleTop = singleInstance launchSingleTop = singleInstance
popUpTo(route = "home") { popUpTo(route = "home") {

View File

@ -1,5 +1,6 @@
package com.shabinder.spotiflyer.ui.home package com.shabinder.spotiflyer.ui.home
import android.content.Intent
import androidx.compose.foundation.* import androidx.compose.foundation.*
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
@ -30,15 +31,19 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.navigation.NavController import androidx.navigation.NavController
import com.razorpay.Checkout
import com.shabinder.spotiflyer.R import com.shabinder.spotiflyer.R
import com.shabinder.spotiflyer.database.DownloadRecord import com.shabinder.spotiflyer.database.DownloadRecord
import com.shabinder.spotiflyer.navigation.navigateToTrackList import com.shabinder.spotiflyer.navigation.navigateToTrackList
import com.shabinder.spotiflyer.ui.SpotiFlyerTypography import com.shabinder.spotiflyer.ui.SpotiFlyerTypography
import com.shabinder.spotiflyer.ui.colorAccent import com.shabinder.spotiflyer.ui.colorAccent
import com.shabinder.spotiflyer.ui.colorPrimary import com.shabinder.spotiflyer.ui.colorPrimary
import com.shabinder.spotiflyer.utils.mainActivity
import com.shabinder.spotiflyer.utils.openPlatform import com.shabinder.spotiflyer.utils.openPlatform
import com.shabinder.spotiflyer.utils.sharedViewModel import com.shabinder.spotiflyer.utils.sharedViewModel
import dev.chrisbanes.accompanist.glide.GlideImage import com.shabinder.spotiflyer.utils.showDialog
import dev.chrisbanes.accompanist.coil.CoilImage
import org.json.JSONObject
@Composable @Composable
fun Home(navController: NavController, modifier: Modifier = Modifier) { fun Home(navController: NavController, modifier: Modifier = Modifier) {
@ -137,7 +142,11 @@ fun AboutColumn(modifier: Modifier = Modifier) {
) )
} }
} }
Row(modifier = modifier.fillMaxWidth().padding(vertical = 6.dp),verticalAlignment = Alignment.CenterVertically) { Row(
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
.clickable(onClick = { openPlatform("http://github.com/Shabinder/SpotiFlyer") }),
verticalAlignment = Alignment.CenterVertically
) {
Icon(Icons.Rounded.Flag.copy(defaultHeight = 32.dp,defaultWidth = 32.dp)) Icon(Icons.Rounded.Flag.copy(defaultHeight = 32.dp,defaultWidth = 32.dp))
Spacer(modifier = Modifier.padding(start = 16.dp)) Spacer(modifier = Modifier.padding(start = 16.dp))
Column { Column {
@ -151,7 +160,11 @@ fun AboutColumn(modifier: Modifier = Modifier) {
) )
} }
} }
Row(modifier = modifier.fillMaxWidth().padding(vertical = 6.dp),verticalAlignment = Alignment.CenterVertically) { Row(
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
.clickable(onClick = { startPayment() }),
verticalAlignment = Alignment.CenterVertically
) {
Icon(Icons.Rounded.CardGiftcard.copy(defaultHeight = 32.dp,defaultWidth = 32.dp)) Icon(Icons.Rounded.CardGiftcard.copy(defaultHeight = 32.dp,defaultWidth = 32.dp))
Spacer(modifier = Modifier.padding(start = 16.dp)) Spacer(modifier = Modifier.padding(start = 16.dp))
Column { Column {
@ -165,7 +178,20 @@ fun AboutColumn(modifier: Modifier = Modifier) {
) )
} }
} }
Row(modifier = modifier.fillMaxWidth().padding(vertical = 6.dp),verticalAlignment = Alignment.CenterVertically) { Row(
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
.clickable(onClick = {
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, "Hey, checkout this excellent Music Downloader http://github.com/Shabinder/SpotiFlyer")
type = "text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, null)
mainActivity.startActivity(shareIntent)
}),
verticalAlignment = Alignment.CenterVertically
) {
Icon(Icons.Rounded.Share.copy(defaultHeight = 32.dp,defaultWidth = 32.dp)) Icon(Icons.Rounded.Share.copy(defaultHeight = 32.dp,defaultWidth = 32.dp))
Spacer(modifier = Modifier.padding(start = 16.dp)) Spacer(modifier = Modifier.padding(start = 16.dp))
Column { Column {
@ -224,11 +250,11 @@ fun HistoryColumn(
fun DownloadRecordItem(item: DownloadRecord,navController: NavController) { fun DownloadRecordItem(item: DownloadRecord,navController: NavController) {
Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier.fillMaxWidth().padding(end = 8.dp)) { Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier.fillMaxWidth().padding(end = 8.dp)) {
val imgUri = item.coverUrl.toUri().buildUpon().scheme("https").build() val imgUri = item.coverUrl.toUri().buildUpon().scheme("https").build()
GlideImage( CoilImage(
data = imgUri, data = imgUri,
//Loading Placeholder Makes Scrolling very stuttery //Loading Placeholder Makes Scrolling very stuttery
// loading = { Image(vectorResource(id = R.drawable.ic_song_placeholder)) }, // loading = { Image(vectorResource(id = R.drawable.ic_song_placeholder)) },
error = { Image(vectorResource(id = R.drawable.ic_musicplaceholder)) }, error = {Image(vectorResource(id = R.drawable.ic_musicplaceholder))},
contentScale = ContentScale.Inside, contentScale = ContentScale.Inside,
// fadeIn = true, // fadeIn = true,
modifier = Modifier.preferredHeight(75.dp).preferredWidth(90.dp) modifier = Modifier.preferredHeight(75.dp).preferredWidth(90.dp)
@ -246,11 +272,43 @@ fun DownloadRecordItem(item: DownloadRecord,navController: NavController) {
} }
Image( Image(
imageVector = vectorResource(id = R.drawable.ic_share_open), imageVector = vectorResource(id = R.drawable.ic_share_open),
modifier = Modifier.clickable(onClick = { navController.navigateToTrackList(item.link) }) modifier = Modifier.clickable(onClick = {
navController.navigateToTrackList(item.link)
})
) )
} }
} }
private fun startPayment() {
/*
* You need to pass current activity in order to let Razorpay create CheckoutActivity
* */
val co = Checkout().apply {
setKeyID("rzp_live_3ZQeoFYOxjmXye")
setImage(R.drawable.ic_launcher_foreground)
}
try {
val preFill = JSONObject()
val options = JSONObject().apply {
put("name","SpotiFlyer")
put("description","Thanks For the Donation!")
//You can omit the image option to fetch the image from dashboard
//put("image","https://github.com/Shabinder/SpotiFlyer/raw/master/app/SpotifyDownload.png")
put("currency","INR")
put("amount","4900")
put("prefill",preFill)
}
co.open(mainActivity,options)
}catch (e: Exception){
showDialog("Error in payment: "+ e.message)
e.printStackTrace()
}
}
@Composable @Composable
fun AuthenticationBanner(isAuthenticated: Boolean, modifier: Modifier) { fun AuthenticationBanner(isAuthenticated: Boolean, modifier: Modifier) {

View File

@ -10,6 +10,7 @@ import kotlinx.coroutines.withContext
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import kotlinx.coroutines.delay
class HomeViewModel : ViewModel() { class HomeViewModel : ViewModel() {
@ -25,6 +26,7 @@ class HomeViewModel : ViewModel() {
fun getDownloadRecordList() { fun getDownloadRecordList() {
viewModelScope.launch { viewModelScope.launch {
withContext(Dispatchers.IO){ withContext(Dispatchers.IO){
delay(100) //TEMP
downloadRecordList = sharedViewModel.databaseDAO.getRecord() downloadRecordList = sharedViewModel.databaseDAO.getRecord()
} }
} }

View File

@ -2,38 +2,20 @@ package com.shabinder.spotiflyer.utils
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.drawable.Drawable
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.net.NetworkCapabilities import android.net.NetworkCapabilities
import android.os.Build import android.os.Build
import android.util.Log import android.util.Log
import android.widget.ImageView
import android.widget.Toast import android.widget.Toast
import androidx.compose.foundation.Image
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.vectorResource
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.toBitmap
import androidx.core.net.toUri
import com.bumptech.glide.Glide
import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import com.shabinder.spotiflyer.MainActivity import com.shabinder.spotiflyer.MainActivity
import com.shabinder.spotiflyer.R
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.worker.ForegroundService import com.shabinder.spotiflyer.worker.ForegroundService
import dev.chrisbanes.accompanist.glide.GlideImage
import dev.chrisbanes.accompanist.glide.GlideImageDefaults
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 java.io.File import java.io.File
import java.io.IOException
/** /**
* mainActivity Instance to use whereEver Needed , as Its God Activity. * mainActivity Instance to use whereEver Needed , as Its God Activity.

View File

@ -117,7 +117,9 @@ class ForegroundService : Service(){
"query" -> { "query" -> {
val response = Intent().apply { val response = Intent().apply {
action = "query_result" action = "query_result"
putExtra("tracks", allTracksStatus) synchronized(allTracksStatus){
putExtra("tracks", allTracksStatus)
}
} }
sendBroadcast(response) sendBroadcast(response)
} }

View File

@ -23,6 +23,9 @@ buildscript {
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
//Kotlinx-Serialization //Kotlinx-Serialization
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
//Crashlytics & Analytics
classpath 'com.google.gms:google-services:4.3.4'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} }