Build:0.3.0,UI optimisations ,Anim fixes.

This commit is contained in:
shabinder 2021-02-25 03:28:02 +05:30
parent 1f548e82e0
commit ec1402ef2e
16 changed files with 196 additions and 76 deletions

View File

@ -25,9 +25,12 @@ import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.extensions.compose.jetbrains.rootComponent import com.arkivanov.decompose.extensions.compose.jetbrains.rootComponent
import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory
import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory
import com.razorpay.Checkout
import com.razorpay.PaymentResultListener
import com.shabinder.android.utils.checkIfLatestVersion import com.shabinder.android.utils.checkIfLatestVersion
import com.shabinder.android.utils.disableDozeMode import com.shabinder.android.utils.disableDozeMode
import com.shabinder.android.utils.requestStoragePermission import com.shabinder.android.utils.requestStoragePermission
import com.shabinder.common.database.activityContext
import com.shabinder.common.di.Dir import com.shabinder.common.di.Dir
import com.shabinder.common.di.FetchPlatformQueryResult import com.shabinder.common.di.FetchPlatformQueryResult
import com.shabinder.common.di.createDirectories import com.shabinder.common.di.createDirectories
@ -38,6 +41,7 @@ import com.shabinder.common.root.SpotiFlyerRootContent
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
import com.shabinder.common.ui.SpotiFlyerTheme import com.shabinder.common.ui.SpotiFlyerTheme
import com.shabinder.common.ui.colorOffWhite import com.shabinder.common.ui.colorOffWhite
import com.shabinder.common.ui.showPopUpMessage
import com.shabinder.database.Database import com.shabinder.database.Database
import com.tonyodev.fetch2.Status import com.tonyodev.fetch2.Status
import kotlinx.coroutines.* import kotlinx.coroutines.*
@ -46,7 +50,7 @@ import org.koin.android.ext.android.inject
const val disableDozeCode = 1223 const val disableDozeCode = 1223
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity(), PaymentResultListener {
private val database: Database by inject() private val database: Database by inject()
private val fetcher: FetchPlatformQueryResult by inject() private val fetcher: FetchPlatformQueryResult by inject()
@ -77,7 +81,6 @@ class MainActivity : ComponentActivity() {
insets insets
} }
} }
root = SpotiFlyerRootContent(rootComponent(::spotiFlyerRoot),statusBarHeight) root = SpotiFlyerRootContent(rootComponent(::spotiFlyerRoot),statusBarHeight)
} }
} }
@ -90,6 +93,7 @@ class MainActivity : ComponentActivity() {
requestStoragePermission() requestStoragePermission()
disableDozeMode(disableDozeCode) disableDozeMode(disableDozeCode)
dir.createDirectories() dir.createDirectories()
Checkout.preload(applicationContext)
} }
private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot = private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot =
@ -208,4 +212,24 @@ class MainActivity : ComponentActivity() {
} }
} }
override fun onPaymentError(errorCode: Int, response: String?) {
try{
showPopUpMessage("Payment Failed, Response:$response")
}catch (e: Exception){
Log.d("Razorpay Payment","Exception in onPaymentSuccess $response")
}
}
override fun onPaymentSuccess(razorpayPaymentId: String?) {
try{
showPopUpMessage("Payment Successful, ThankYou!")
}catch (e: Exception){
showPopUpMessage("Razorpay Payment, Error Occurred.")
Log.d("Razorpay Payment","Exception in onPaymentSuccess, ${e.message}")
}
}
init {
activityContext = this
}
} }

View File

@ -1,7 +1,7 @@
@file:Suppress("MayBeConstant", "SpellCheckingInspection") @file:Suppress("MayBeConstant", "SpellCheckingInspection")
object Versions { object Versions {
const val versionName = "2.2" const val versionName = "2.2.0"
const val kotlinVersion = "1.4.30" const val kotlinVersion = "1.4.30"
const val coroutinesVersion = "1.4.2" const val coroutinesVersion = "1.4.2"
@ -67,7 +67,7 @@ object JetBrains {
object Compose { object Compose {
// __LATEST_COMPOSE_RELEASE_VERSION__ // __LATEST_COMPOSE_RELEASE_VERSION__
const val VERSION = "0.3.0-build152" const val VERSION = "0.3.0"
const val gradlePlugin = "org.jetbrains.compose:compose-gradle-plugin:$VERSION" const val gradlePlugin = "org.jetbrains.compose:compose-gradle-plugin:$VERSION"
} }
} }
@ -122,7 +122,7 @@ object Extras {
const val mp3agic = "com.mpatric:mp3agic:0.9.1" const val mp3agic = "com.mpatric:mp3agic:0.9.1"
const val kermit = "co.touchlab:kermit:${Versions.kermit}" const val kermit = "co.touchlab:kermit:${Versions.kermit}"
object Android { object Android {
val razorpay = "com.razorpay:checkout:1.6.4" val razorpay = "com.razorpay:checkout:1.6.5"
val fetch = "androidx.tonyodev.fetch2:xfetch2:3.1.6" val fetch = "androidx.tonyodev.fetch2:xfetch2:3.1.6"
val appUpdator = "com.github.amitbd1508:AppUpdater:4.1.0" val appUpdator = "com.github.amitbd1508:AppUpdater:4.1.0"
} }

View File

@ -2,9 +2,11 @@
package com.shabinder.common.ui package com.shabinder.common.ui
import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.vectorResource import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.Font
@ -76,4 +78,7 @@ actual fun YoutubeLogo() = vectorResource(R.drawable.ic_youtube)
actual fun YoutubeMusicLogo() = vectorResource(R.drawable.ic_youtube_music_logo) actual fun YoutubeMusicLogo() = vectorResource(R.drawable.ic_youtube_music_logo)
@Composable @Composable
actual fun GithubLogo() = vectorResource(R.drawable.ic_github) actual fun GithubLogo() = vectorResource(R.drawable.ic_github)
@Composable
fun vectorResource(@DrawableRes id: Int) = ImageVector.Companion.vectorResource(id)

View File

@ -42,7 +42,7 @@ fun SpotiFlyerListContent(
} }
}else{ }else{
LazyColumn( LazyColumn(
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(12.dp),
content = { content = {
item { item {
CoverImage(result.title, result.coverUrl, coroutineScope,component::loadImage) CoverImage(result.title, result.coverUrl, coroutineScope,component::loadImage)
@ -71,17 +71,14 @@ fun TrackCard(
downloadTrack:()->Unit, downloadTrack:()->Unit,
loadImage:suspend (String)-> ImageBitmap? loadImage:suspend (String)-> ImageBitmap?
) { ) {
/*val status = remember { mutableStateOf(track.downloaded.name()) }
LaunchedEffect(track.downloaded.name()){
status.value = track.downloaded.name()
}*/
Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp)) { Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier.fillMaxWidth().padding(horizontal = 8.dp)) {
ImageLoad( ImageLoad(
{loadImage(track.albumArtURL)}, track.albumArtURL,
loadImage,
"Album Art", "Album Art",
modifier = Modifier modifier = Modifier
.width(75.dp) .width(70.dp)
.height(90.dp) .height(70.dp)
.clip(MaterialTheme.shapes.medium) .clip(MaterialTheme.shapes.medium)
) )
Column(modifier = Modifier.padding(horizontal = 8.dp).height(60.dp).weight(1f),verticalArrangement = Arrangement.SpaceEvenly) { Column(modifier = Modifier.padding(horizontal = 8.dp).height(60.dp).weight(1f),verticalArrangement = Arrangement.SpaceEvenly) {
@ -133,11 +130,13 @@ fun CoverImage(
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
ImageLoad( ImageLoad(
{ loadImage(coverURL) }, coverURL,
loadImage,
"Cover Image", "Cover Image",
modifier = Modifier modifier = Modifier
.width(210.dp) .padding(12.dp)
.height(230.dp) .width(190.dp)
.height(210.dp)
.clip(MaterialTheme.shapes.medium) .clip(MaterialTheme.shapes.medium)
) )
Text( Text(

View File

@ -10,6 +10,7 @@ import androidx.compose.material.*
import androidx.compose.material.Icon import androidx.compose.material.Icon
import androidx.compose.material.TabRowDefaults.tabIndicatorOffset import androidx.compose.material.TabRowDefaults.tabIndicatorOffset
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.TextFieldDefaults.textFieldColors
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.History import androidx.compose.material.icons.outlined.History
import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.outlined.Info
@ -17,6 +18,7 @@ import androidx.compose.material.icons.rounded.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.ImageBitmap
@ -130,10 +132,12 @@ fun SearchPanel(
BorderStroke(2.dp, Brush.horizontalGradient(listOf(colorPrimary, colorAccent))), BorderStroke(2.dp, Brush.horizontalGradient(listOf(colorPrimary, colorAccent))),
RoundedCornerShape(30.dp) RoundedCornerShape(30.dp)
), ),
backgroundColor = Color.Black,
shape = RoundedCornerShape(size = 30.dp), shape = RoundedCornerShape(size = 30.dp),
activeColor = transparent, colors = textFieldColors(
inactiveColor = transparent, focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
backgroundColor = Color.Black
)
) )
OutlinedButton( OutlinedButton(
modifier = Modifier.padding(12.dp).wrapContentWidth(), modifier = Modifier.padding(12.dp).wrapContentWidth(),
@ -171,28 +175,28 @@ fun AboutColumn(modifier: Modifier = Modifier) {
imageVector = SpotifyLogo(), imageVector = SpotifyLogo(),
"Open Spotify", "Open Spotify",
tint = Color.Unspecified, tint = Color.Unspecified,
modifier = Modifier.clickable( modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
onClick = { openPlatform("com.spotify.music","http://open.spotify.com") }) onClick = { openPlatform("com.spotify.music","http://open.spotify.com") })
) )
Spacer(modifier = modifier.padding(start = 16.dp)) Spacer(modifier = modifier.padding(start = 16.dp))
Icon(imageVector = GaanaLogo(), Icon(imageVector = GaanaLogo(),
"Open Gaana", "Open Gaana",
tint = Color.Unspecified, tint = Color.Unspecified,
modifier = Modifier.clickable( modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
onClick = { openPlatform("com.gaana","http://gaana.com") }) onClick = { openPlatform("com.gaana","http://gaana.com") })
) )
Spacer(modifier = modifier.padding(start = 16.dp)) Spacer(modifier = modifier.padding(start = 16.dp))
Icon(imageVector = YoutubeLogo(), Icon(imageVector = YoutubeLogo(),
"Open Youtube", "Open Youtube",
tint = Color.Unspecified, tint = Color.Unspecified,
modifier = Modifier.clickable( modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
onClick = { openPlatform("com.google.android.youtube","http://m.youtube.com") }) onClick = { openPlatform("com.google.android.youtube","http://m.youtube.com") })
) )
Spacer(modifier = modifier.padding(start = 12.dp)) Spacer(modifier = modifier.padding(start = 12.dp))
Icon(imageVector = YoutubeMusicLogo(), Icon(imageVector = YoutubeMusicLogo(),
"Open Youtube Music", "Open Youtube Music",
tint = Color.Unspecified, tint = Color.Unspecified,
modifier = Modifier.clickable( modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
onClick = { openPlatform("com.google.android.apps.youtube.music","https://music.youtube.com/") }) onClick = { openPlatform("com.google.android.apps.youtube.music","https://music.youtube.com/") })
) )
} }
@ -251,7 +255,7 @@ fun AboutColumn(modifier: Modifier = Modifier) {
.clickable(onClick = { giveDonation() }), .clickable(onClick = { giveDonation() }),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Icon(Icons.Rounded.MailOutline,"Support Developer") Icon(Icons.Rounded.CardGiftcard,"Support Developer")
Spacer(modifier = Modifier.padding(start = 16.dp)) Spacer(modifier = Modifier.padding(start = 16.dp))
Column { Column {
Text( Text(
@ -296,7 +300,7 @@ fun HistoryColumn(
onItemClicked: (String) -> Unit onItemClicked: (String) -> Unit
) { ) {
LazyColumn( LazyColumn(
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(12.dp),
content = { content = {
items(list.distinctBy { it.coverUrl }) { items(list.distinctBy { it.coverUrl }) {
DownloadRecordItem( DownloadRecordItem(
@ -318,9 +322,10 @@ fun DownloadRecordItem(
) { ) {
Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier.fillMaxWidth().padding(end = 8.dp)) { Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier.fillMaxWidth().padding(end = 8.dp)) {
ImageLoad( ImageLoad(
{ loadImage(item.coverUrl) }, item.coverUrl,
loadImage,
"Album Art", "Album Art",
modifier = Modifier.height(75.dp).width(90.dp) modifier = Modifier.height(70.dp).width(70.dp).clip(SpotiFlyerShapes.medium)
) )
Column(modifier = Modifier.padding(horizontal = 8.dp).height(60.dp).weight(1f),verticalArrangement = Arrangement.SpaceEvenly) { Column(modifier = Modifier.padding(horizontal = 8.dp).height(60.dp).weight(1f),verticalArrangement = Arrangement.SpaceEvenly) {
Text(item.name,maxLines = 1,overflow = TextOverflow.Ellipsis,style = SpotiFlyerTypography.h6,color = colorAccent) Text(item.name,maxLines = 1,overflow = TextOverflow.Ellipsis,style = SpotiFlyerTypography.h6,color = colorAccent)

View File

@ -9,18 +9,19 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@Composable @Composable
fun ImageLoad(loader: suspend () -> ImageBitmap?, desc: String = "Album Art", modifier:Modifier = Modifier, placeholder:ImageVector = PlaceHolderImage()) { fun ImageLoad(link:String,loader:suspend (String) ->ImageBitmap?, desc: String = "Album Art", modifier:Modifier = Modifier, placeholder:ImageVector = PlaceHolderImage()) {
var pic by remember { mutableStateOf<ImageBitmap?>(null) } var pic by remember(link) { mutableStateOf<ImageBitmap?>(null) }
LaunchedEffect(loader){ LaunchedEffect(link){
withContext(dispatcherIO) { withContext(dispatcherIO) {
pic = loader() pic = loader(link)
} }
} }
Crossfade(pic){ Crossfade(pic){
if(pic == null) Image(placeholder, desc, modifier) else Image(pic!!, desc, modifier) if(it == null) Image(placeholder, desc, modifier,contentScale = ContentScale.Crop) else Image(it, desc, modifier,contentScale = ContentScale.Crop)
} }
} }

View File

@ -14,8 +14,8 @@
~ along with this program. If not, see <https://www.gnu.org/licenses/>. ~ along with this program. If not, see <https://www.gnu.org/licenses/>.
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="36dp" <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="40dp"
android:height="32dp" android:viewportWidth="512" android:viewportHeight="512"> android:height="38dp" android:viewportWidth="512" android:viewportHeight="512">
<path android:fillColor="#516AEC" android:pathData="m296,288 l60,-60c7.73,-7.73 17.86,-11.6 28,-11.6 10.055,0 20.101,3.806 27.806,11.407 15.612,15.402 15.207,41.18 -0.3,56.687l-134.293,134.293c-11.716,11.716 -30.711,11.716 -42.426,0l-134.787,-134.787c-7.73,-7.73 -11.6,-17.86 -11.6,-28 0,-10.055 3.806,-20.101 11.407,-27.806 15.402,-15.612 41.18,-15.207 56.687,0.3l59.506,59.506v-232c0,-22.091 17.909,-40 40,-40 22.091,0 40,17.909 40,40z"/> <path android:fillColor="#516AEC" android:pathData="m296,288 l60,-60c7.73,-7.73 17.86,-11.6 28,-11.6 10.055,0 20.101,3.806 27.806,11.407 15.612,15.402 15.207,41.18 -0.3,56.687l-134.293,134.293c-11.716,11.716 -30.711,11.716 -42.426,0l-134.787,-134.787c-7.73,-7.73 -11.6,-17.86 -11.6,-28 0,-10.055 3.806,-20.101 11.407,-27.806 15.402,-15.612 41.18,-15.207 56.687,0.3l59.506,59.506v-232c0,-22.091 17.909,-40 40,-40 22.091,0 40,17.909 40,40z"/>
<path android:fillColor="#EC7EBA" android:pathData="m411.51,284.49 l-134.3,134.3c-11.71,11.71 -30.71,11.71 -42.42,0l-12.74,-12.74c10.69,4.06 23.23,1.77 31.84,-6.84l134.29,-134.29c12.51,-12.51 15.19,-31.7 7.57,-46.74 5.86,1.81 11.39,5.03 16.06,9.63 15.61,15.4 15.2,41.18 -0.3,56.68z"/> <path android:fillColor="#EC7EBA" android:pathData="m411.51,284.49 l-134.3,134.3c-11.71,11.71 -30.71,11.71 -42.42,0l-12.74,-12.74c10.69,4.06 23.23,1.77 31.84,-6.84l134.29,-134.29c12.51,-12.51 15.19,-31.7 7.57,-46.74 5.86,1.81 11.39,5.03 16.06,9.63 15.61,15.4 15.2,41.18 -0.3,56.68z"/>
<path android:fillColor="#EC7EBA" android:pathData="m251.88,27.72c-3.46,-3.46 -7.55,-6.29 -12.08,-8.3 4.95,-2.2 10.43,-3.42 16.2,-3.42 11.04,0 21.04,4.48 28.28,11.72s11.72,17.24 11.72,28.28v232l-15.329,15.329c-6.3,6.3 -17.071,1.838 -17.071,-7.071v-240.258c0,-11.04 -4.48,-21.04 -11.72,-28.28z"/> <path android:fillColor="#EC7EBA" android:pathData="m251.88,27.72c-3.46,-3.46 -7.55,-6.29 -12.08,-8.3 4.95,-2.2 10.43,-3.42 16.2,-3.42 11.04,0 21.04,4.48 28.28,11.72s11.72,17.24 11.72,28.28v232l-15.329,15.329c-6.3,6.3 -17.071,1.838 -17.071,-7.071v-240.258c0,-11.04 -4.48,-21.04 -11.72,-28.28z"/>

View File

@ -15,7 +15,7 @@
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt" <vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
android:width="38dp" android:height="38dp" android:width="40dp" android:height="40dp"
android:viewportWidth="512" android:viewportHeight="512"> android:viewportWidth="512" android:viewportHeight="512">
<path android:pathData="m512,256c0,141.387 -114.613,256 -256,256s-256,-114.613 -256,-256 114.613,-256 256,-256 256,114.613 256,256zM512,256"> <path android:pathData="m512,256c0,141.387 -114.613,256 -256,256s-256,-114.613 -256,-256 114.613,-256 256,-256 256,114.613 256,256zM512,256">
<aapt:attr name="android:fillColor"> <aapt:attr name="android:fillColor">

View File

@ -14,8 +14,8 @@
~ along with this program. If not, see <https://www.gnu.org/licenses/>. ~ along with this program. If not, see <https://www.gnu.org/licenses/>.
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="38dp" <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="34dp"
android:height="38dp" android:viewportWidth="512" android:viewportHeight="512"> android:height="34dp" android:viewportWidth="512" android:viewportHeight="512">
<path android:fillColor="#4EA4FF" android:pathData="M255.968,5.329C114.624,5.329 0,120.401 0,262.353c0,113.536 73.344,209.856 175.104,243.872c12.8,2.368 17.472,-5.568 17.472,-12.384c0,-6.112 -0.224,-22.272 -0.352,-43.712c-71.2,15.52 -86.24,-34.464 -86.24,-34.464c-11.616,-29.696 -28.416,-37.6 -28.416,-37.6c-23.264,-15.936 1.728,-15.616 1.728,-15.616c25.696,1.824 39.2,26.496 39.2,26.496c22.848,39.264 59.936,27.936 74.528,21.344c2.304,-16.608 8.928,-27.936 16.256,-34.368c-56.832,-6.496 -116.608,-28.544 -116.608,-127.008c0,-28.064 9.984,-51.008 26.368,-68.992c-2.656,-6.496 -11.424,-32.64 2.496,-68c0,0 21.504,-6.912 70.4,26.336c20.416,-5.696 42.304,-8.544 64.096,-8.64c21.728,0.128 43.648,2.944 64.096,8.672c48.864,-33.248 70.336,-26.336 70.336,-26.336c13.952,35.392 5.184,61.504 2.56,68c16.416,17.984 26.304,40.928 26.304,68.992c0,98.72 -59.84,120.448 -116.864,126.816c9.184,7.936 17.376,23.616 17.376,47.584c0,34.368 -0.32,62.08 -0.32,70.496c0,6.88 4.608,14.88 17.6,12.352C438.72,472.145 512,375.857 512,262.353C512,120.401 397.376,5.329 255.968,5.329z"/> <path android:fillColor="#4EA4FF" android:pathData="M255.968,5.329C114.624,5.329 0,120.401 0,262.353c0,113.536 73.344,209.856 175.104,243.872c12.8,2.368 17.472,-5.568 17.472,-12.384c0,-6.112 -0.224,-22.272 -0.352,-43.712c-71.2,15.52 -86.24,-34.464 -86.24,-34.464c-11.616,-29.696 -28.416,-37.6 -28.416,-37.6c-23.264,-15.936 1.728,-15.616 1.728,-15.616c25.696,1.824 39.2,26.496 39.2,26.496c22.848,39.264 59.936,27.936 74.528,21.344c2.304,-16.608 8.928,-27.936 16.256,-34.368c-56.832,-6.496 -116.608,-28.544 -116.608,-127.008c0,-28.064 9.984,-51.008 26.368,-68.992c-2.656,-6.496 -11.424,-32.64 2.496,-68c0,0 21.504,-6.912 70.4,26.336c20.416,-5.696 42.304,-8.544 64.096,-8.64c21.728,0.128 43.648,2.944 64.096,8.672c48.864,-33.248 70.336,-26.336 70.336,-26.336c13.952,35.392 5.184,61.504 2.56,68c16.416,17.984 26.304,40.928 26.304,68.992c0,98.72 -59.84,120.448 -116.864,126.816c9.184,7.936 17.376,23.616 17.376,47.584c0,34.368 -0.32,62.08 -0.32,70.496c0,6.88 4.608,14.88 17.6,12.352C438.72,472.145 512,375.857 512,262.353C512,120.401 397.376,5.329 255.968,5.329z"/>
</vector> </vector>

View File

@ -15,7 +15,7 @@
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt" <vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
android:width="36dp" android:height="36dp" android:width="40dp" android:height="40dp"
android:viewportWidth="512" android:viewportHeight="512"> android:viewportWidth="512" android:viewportHeight="512">
<path android:pathData="m512,256c0,141.387 -114.613,256 -256,256s-256,-114.613 -256,-256 114.613,-256 256,-256 256,114.613 256,256zM512,256"> <path android:pathData="m512,256c0,141.387 -114.613,256 -256,256s-256,-114.613 -256,-256 114.613,-256 256,-256 256,114.613 256,256zM512,256">
<aapt:attr name="android:fillColor"> <aapt:attr name="android:fillColor">

View File

@ -1,5 +1,6 @@
package com.shabinder.common.database package com.shabinder.common.database
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import co.touchlab.kermit.LogcatLogger import co.touchlab.kermit.LogcatLogger
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
@ -8,6 +9,12 @@ import com.squareup.sqldelight.android.AndroidSqliteDriver
lateinit var appContext: Context lateinit var appContext: Context
/*
* As MainActivity is God Activity , hence its active almost throughout App's lifetime
* */
@SuppressLint("StaticFieldLeak")
lateinit var activityContext: Context
actual fun createDatabase(): Database { actual fun createDatabase(): Database {
val driver = AndroidSqliteDriver(Database.Schema, appContext, "Database.db") val driver = AndroidSqliteDriver(Database.Schema, appContext, "Database.db")
return Database(driver) return Database(driver)

View File

@ -34,6 +34,7 @@ kotlin {
implementation(Ktor.clientAndroid) implementation(Ktor.clientAndroid)
implementation(Extras.Android.fetch) implementation(Extras.Android.fetch)
implementation(Koin.android) implementation(Koin.android)
implementation(Extras.Android.razorpay)
//api(files("$rootDir/libs/mobile-ffmpeg.aar")) //api(files("$rootDir/libs/mobile-ffmpeg.aar"))
} }
} }

View File

@ -1,5 +1,6 @@
package com.shabinder.common.di package com.shabinder.common.di
import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.net.Uri import android.net.Uri
@ -7,22 +8,25 @@ import androidx.core.content.ContextCompat
import com.github.kiulian.downloader.model.YoutubeVideo import com.github.kiulian.downloader.model.YoutubeVideo
import com.github.kiulian.downloader.model.formats.Format import com.github.kiulian.downloader.model.formats.Format
import com.github.kiulian.downloader.model.quality.AudioQuality import com.github.kiulian.downloader.model.quality.AudioQuality
import com.shabinder.common.database.appContext import com.razorpay.Checkout
import com.shabinder.common.database.activityContext
import com.shabinder.common.di.worker.ForegroundService import com.shabinder.common.di.worker.ForegroundService
import com.shabinder.common.models.TrackDetails import com.shabinder.common.models.TrackDetails
import com.shabinder.common.ui.R
import org.json.JSONObject
actual fun openPlatform(packageID:String, platformLink:String){ actual fun openPlatform(packageID:String, platformLink:String){
val manager: PackageManager = appContext.packageManager val manager: PackageManager = activityContext.packageManager
try { try {
val intent = manager.getLaunchIntentForPackage(packageID) val intent = manager.getLaunchIntentForPackage(packageID)
?: throw PackageManager.NameNotFoundException() ?: throw PackageManager.NameNotFoundException()
intent.addCategory(Intent.CATEGORY_LAUNCHER) intent.addCategory(Intent.CATEGORY_LAUNCHER)
appContext.startActivity(intent) activityContext.startActivity(intent)
} catch (e: PackageManager.NameNotFoundException) { } catch (e: PackageManager.NameNotFoundException) {
val uri: Uri = val uri: Uri =
Uri.parse(platformLink) Uri.parse(platformLink)
val intent = Intent(Intent.ACTION_VIEW, uri) val intent = Intent(Intent.ACTION_VIEW, uri)
appContext.startActivity(intent) activityContext.startActivity(intent)
} }
} }
@ -34,18 +38,44 @@ actual fun shareApp(){
} }
val shareIntent = Intent.createChooser(sendIntent, null) val shareIntent = Intent.createChooser(sendIntent, null)
appContext.startActivity(shareIntent) activityContext.startActivity(shareIntent)
} }
actual fun giveDonation(){ actual fun giveDonation() = startPayment()
//TODO
}
private fun startPayment(mainActivity: Activity = activityContext as Activity) {
/*
* 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_spotiflyer_logo)
}
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){
//showPop("Error in payment: "+ e.message)
e.printStackTrace()
}
}
actual fun queryActiveTracks() { actual fun queryActiveTracks() {
val serviceIntent = Intent(appContext, ForegroundService::class.java).apply { val serviceIntent = Intent(activityContext, ForegroundService::class.java).apply {
action = "query" action = "query"
} }
ContextCompat.startForegroundService(appContext, serviceIntent) ContextCompat.startForegroundService(activityContext, serviceIntent)
} }
actual suspend fun downloadTracks( actual suspend fun downloadTracks(
@ -54,9 +84,9 @@ actual suspend fun downloadTracks(
saveFileWithMetaData:suspend (mp3ByteArray:ByteArray, trackDetails: TrackDetails) -> Unit saveFileWithMetaData:suspend (mp3ByteArray:ByteArray, trackDetails: TrackDetails) -> Unit
){ ){
if(!list.isNullOrEmpty()){ if(!list.isNullOrEmpty()){
val serviceIntent = Intent(appContext, ForegroundService::class.java) val serviceIntent = Intent(activityContext, ForegroundService::class.java)
serviceIntent.putParcelableArrayListExtra("object",ArrayList<TrackDetails>(list)) serviceIntent.putParcelableArrayListExtra("object",ArrayList<TrackDetails>(list))
appContext.let { ContextCompat.startForegroundService(it, serviceIntent) } activityContext.let { ContextCompat.startForegroundService(it, serviceIntent) }
} }
} }

View File

@ -32,6 +32,7 @@ import androidx.core.app.NotificationCompat
import androidx.core.net.toUri import androidx.core.net.toUri
import co.touchlab.kermit.Kermit import co.touchlab.kermit.Kermit
import com.github.kiulian.downloader.YoutubeDownloader import com.github.kiulian.downloader.YoutubeDownloader
import com.github.kiulian.downloader.model.formats.Format
import com.shabinder.common.di.Dir import com.shabinder.common.di.Dir
import com.shabinder.common.di.FetchPlatformQueryResult import com.shabinder.common.di.FetchPlatformQueryResult
import com.shabinder.common.di.getData import com.shabinder.common.di.getData
@ -178,37 +179,37 @@ class ForegroundService : Service(),CoroutineScope{
private fun downloadTrack(videoID:String, track: TrackDetails){ private fun downloadTrack(videoID:String, track: TrackDetails){
launch { launch {
try { try {
/*val audioData = ytDownloader.getVideo(videoID).getData()
audioData?.let {
val url: String = it.url()
logger.d("DHelper Link Found") { url }
}*/
val url = fetcher.youtubeMp3.getMp3DownloadLink(videoID) val url = fetcher.youtubeMp3.getMp3DownloadLink(videoID)
if (url == null){ if (url == null){
sendTrackBroadcast(Status.FAILED.name,track) val audioData:Format = ytDownloader.getVideo(videoID).getData() ?: throw Exception("Java YT Dependency Error")
allTracksStatus[track.title] = DownloadStatus.Failed val ytUrl: String = audioData.url()
} else{ enqueueDownload(ytUrl,track)
val request= Request(url, track.outputFilePath).apply{ } else enqueueDownload(url,track)
priority = Priority.NORMAL }catch (e: Exception){
networkType = NetworkType.ALL
}
fetch.enqueue(request,
{ request1 ->
requestMap[request1] = track
logger.d(tag){"Enqueuing Download"}
},
{ error ->
logger.d(tag){"Enqueuing Error:${error.throwable.toString()}"}
}
)
}
}catch (e: java.lang.Exception){
logger.d("Service YT Error"){e.message.toString()} logger.d("Service YT Error"){e.message.toString()}
sendTrackBroadcast(Status.FAILED.name,track)
allTracksStatus[track.title] = DownloadStatus.Failed
} }
} }
} }
private fun enqueueDownload(url:String,track:TrackDetails){
val request= Request(url, track.outputFilePath).apply{
priority = Priority.NORMAL
networkType = NetworkType.ALL
}
fetch.enqueue(request,
{ request1 ->
requestMap[request1] = track
logger.d(tag){"Enqueuing Download"}
},
{ error ->
logger.d(tag){"Enqueuing Error:${error.throwable.toString()}"}
}
)
}
/** /**
* Fetch Listener/ Responsible for Fetch Behaviour * Fetch Listener/ Responsible for Fetch Behaviour
**/ **/

View File

@ -49,7 +49,7 @@ suspend fun downloadFile(url: String): Flow<DownloadResult> {
} }
} }
fun getNameURL(url: String): String { fun getNameURL(url: String): String {
return url.substring(url.lastIndexOf('/') + 1, url.length) return url.substring(url.lastIndexOf('/',url.lastIndexOf('/')-1) + 1, url.length).replace('/','_')
} }
/* /*
* Call this function at startup! * Call this function at startup!

View File

@ -0,0 +1,47 @@
<!--
~ Copyright (c) 2021 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 android:height="150dp" android:viewportHeight="512"
android:viewportWidth="512" android:width="150dp"
xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:pathData="M256,256m-256,0a256,256 0,1 1,512 0a256,256 0,1 1,-512 0">
<aapt:attr name="android:fillColor">
<gradient android:endX="437.019" android:endY="74.981"
android:startX="74.981" android:startY="437.019" android:type="linear">
<item android:color="#FF736BFD" android:offset="0"/>
<item android:color="#FFF54187" android:offset="1"/>
</gradient>
</aapt:attr>
</path>
<path android:fillColor="#FF000000" android:pathData="M377,356.7c-68.9,-45.4 -155.6,-56.4 -257.6,-32.7c-20.5,4.8 -13.6,35.8 7.3,31.2C290.7,317 351.6,386 368.2,386C384,386 390.2,365.4 377,356.7z"/>
<path android:fillColor="#FF000000" android:pathData="M112.1,275.1C203.9,253.4 308.1,266 384,308c18.5,10.2 34,-17.8 15.5,-28c-82.7,-45.7 -195.6,-59.5 -294.7,-36C84.2,248.8 91.5,280 112.1,275.1L112.1,275.1z"/>
<path android:fillColor="#FF000000" android:pathData="M100,191.9c96.6,-29.6 232.2,-13.4 308.7,36.9c17.6,11.5 35.3,-15.1 17.6,-26.7c-84.9,-55.8 -229.2,-73.3 -335.6,-40.8C70.4,167.5 79.9,198.1 100,191.9L100,191.9z"/>
<path android:pathData="M507.8,438.2c-1.6,97.2 -141.9,97.1 -143.5,0C365.9,341 506.2,341 507.8,438.2z">
<aapt:attr name="android:fillColor">
<gradient android:endX="384.197" android:endY="490.009"
android:startX="487.832" android:startY="386.374" android:type="linear">
<item android:color="#FF736BFD" android:offset="0"/>
<item android:color="#FFF54187" android:offset="1"/>
</gradient>
</aapt:attr>
</path>
<path android:fillColor="#FF000000"
android:pathData="M486.8,456.8c-0.6,-2.4 -6.9,-1 -8.5,-1.4c11.5,-82 -82.4,-86.7 -87.1,-22.2c0.3,1.8 -1,6.7 2.2,6.6c0,0 8.6,0 8.6,0c3.1,0.1 2,-4.7 2.2,-6.6c0.1,-23.3 35,-23.3 35.2,0c0,0 0,6.9 0,6.9c-0.1,2.8 4.4,2.8 4.3,0c5,-35.2 -43.8,-40.1 -43.8,-4.7h-4.3c-1.6,-53.7 77.2,-55.9 78.4,-2.2c0,0 0,24.4 0,24.4c-0.1,2.9 3.8,2.1 5.6,2.2l-20.7,21l-20.7,-21c1.8,-0.1 5.6,0.7 5.6,-2.2c0,0 0,-8.8 0,-8.8c0,-2.8 -4.4,-2.8 -4.3,0c0,0 0,6.6 0,6.6c-2.2,0.2 -11.3,-1.3 -8,3.7c0,0 25.9,26.3 25.9,26.3c0.8,0.9 2.2,0.9 3.1,0C460.6,484.4 489.4,458.3 486.8,456.8z"
android:strokeColor="#000" android:strokeWidth=".75"/>
<path android:fillColor="#00000000"
android:pathData="M510,437.5c-1.7,96.2 -142.1,96.2 -143.8,0C367.9,341.3 508.4,341.3 510,437.5z"
android:strokeColor="#000" android:strokeWidth="6"/>
</vector>