mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-11-22 01:04:31 +01:00
Removed Static Variables, Thorough Code Cleanup, Code Refactoring
This commit is contained in:
parent
9f9a160e88
commit
ff7acc9558
@ -46,6 +46,7 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileSdkVersion(29)
|
compileSdkVersion(29)
|
||||||
buildToolsVersion = "30.0.3"
|
buildToolsVersion = "30.0.3"
|
||||||
|
|
||||||
@ -104,14 +105,14 @@ dependencies {
|
|||||||
implementation(Koin.android)
|
implementation(Koin.android)
|
||||||
implementation(Koin.compose)
|
implementation(Koin.compose)
|
||||||
|
|
||||||
implementation("com.google.accompanist:accompanist-insets:0.7.1")
|
implementation("com.google.accompanist:accompanist-insets:0.8.1")
|
||||||
|
|
||||||
// DECOMPOSE
|
// DECOMPOSE
|
||||||
implementation(Decompose.decompose)
|
implementation(Decompose.decompose)
|
||||||
implementation(Decompose.extensionsCompose)
|
implementation(Decompose.extensionsCompose)
|
||||||
|
|
||||||
// Firebase
|
// Firebase
|
||||||
implementation(platform("com.google.firebase:firebase-bom:27.0.0"))
|
implementation(platform("com.google.firebase:firebase-bom:27.1.0"))
|
||||||
implementation("com.google.firebase:firebase-analytics-ktx")
|
implementation("com.google.firebase:firebase-analytics-ktx")
|
||||||
implementation("com.google.firebase:firebase-crashlytics-ktx")
|
implementation("com.google.firebase:firebase-crashlytics-ktx")
|
||||||
implementation("com.google.firebase:firebase-perf-ktx")
|
implementation("com.google.firebase:firebase-perf-ktx")
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
package com.shabinder.spotiflyer
|
package com.shabinder.spotiflyer
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import com.shabinder.common.database.appContext
|
|
||||||
import com.shabinder.common.di.initKoin
|
import com.shabinder.common.di.initKoin
|
||||||
import com.shabinder.spotiflyer.di.appModule
|
import com.shabinder.spotiflyer.di.appModule
|
||||||
import org.koin.android.ext.koin.androidContext
|
import org.koin.android.ext.koin.androidContext
|
||||||
@ -29,7 +28,6 @@ class App: Application(), KoinComponent {
|
|||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
appContext = this
|
|
||||||
val loggingEnabled = true
|
val loggingEnabled = true
|
||||||
|
|
||||||
initKoin(loggingEnabled) {
|
initKoin(loggingEnabled) {
|
||||||
|
@ -17,10 +17,14 @@
|
|||||||
package com.shabinder.spotiflyer
|
package com.shabinder.spotiflyer
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.media.MediaScannerConnection
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
@ -31,18 +35,10 @@ import androidx.compose.animation.*
|
|||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.rounded.SdStorage
|
|
||||||
import androidx.compose.material.icons.rounded.SystemSecurityUpdate
|
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.arkivanov.decompose.ComponentContext
|
import com.arkivanov.decompose.ComponentContext
|
||||||
@ -57,21 +53,27 @@ import com.google.accompanist.insets.statusBarsHeight
|
|||||||
import com.google.accompanist.insets.statusBarsPadding
|
import com.google.accompanist.insets.statusBarsPadding
|
||||||
import com.razorpay.Checkout
|
import com.razorpay.Checkout
|
||||||
import com.razorpay.PaymentResultListener
|
import com.razorpay.PaymentResultListener
|
||||||
import com.shabinder.common.database.activityContext
|
|
||||||
import com.shabinder.common.database.appContext
|
|
||||||
import com.shabinder.common.di.*
|
import com.shabinder.common.di.*
|
||||||
|
import com.shabinder.common.di.worker.ForegroundService
|
||||||
|
import com.shabinder.common.models.Actions
|
||||||
|
import com.shabinder.common.models.AllPlatforms
|
||||||
import com.shabinder.common.models.DownloadStatus
|
import com.shabinder.common.models.DownloadStatus
|
||||||
|
import com.shabinder.common.models.PlatformActions
|
||||||
|
import com.shabinder.common.models.PlatformActions.Companion.SharedPreferencesKey
|
||||||
import com.shabinder.common.models.TrackDetails
|
import com.shabinder.common.models.TrackDetails
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot
|
import com.shabinder.common.root.SpotiFlyerRoot
|
||||||
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
||||||
import com.shabinder.common.uikit.*
|
import com.shabinder.common.uikit.*
|
||||||
import com.shabinder.spotiflyer.utils.*
|
import com.shabinder.spotiflyer.utils.*
|
||||||
import com.shabinder.common.models.Status
|
import com.shabinder.common.models.Status
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
|
import com.shabinder.spotiflyer.ui.NetworkDialog
|
||||||
|
import com.shabinder.spotiflyer.ui.PermissionDialog
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
|
import org.json.JSONObject
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import com.shabinder.common.uikit.showPopUpMessage as uikitShowPopUpMessage
|
|
||||||
|
|
||||||
const val disableDozeCode = 1223
|
const val disableDozeCode = 1223
|
||||||
|
|
||||||
@ -87,6 +89,7 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
|||||||
private var permissionGranted = mutableStateOf(true)
|
private var permissionGranted = mutableStateOf(true)
|
||||||
private lateinit var updateUIReceiver: BroadcastReceiver
|
private lateinit var updateUIReceiver: BroadcastReceiver
|
||||||
private lateinit var queryReceiver: BroadcastReceiver
|
private lateinit var queryReceiver: BroadcastReceiver
|
||||||
|
private val internetAvailability by lazy { ConnectionLiveData(applicationContext) }
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -116,8 +119,12 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
|||||||
LaunchedEffect(view) {
|
LaunchedEffect(view) {
|
||||||
permissionGranted.value = checkPermissions()
|
permissionGranted.value = checkPermissions()
|
||||||
}
|
}
|
||||||
NetworkDialog()
|
NetworkDialog(isInternetAvailableState())
|
||||||
PermissionDialog()
|
PermissionDialog(
|
||||||
|
permissionGranted.value,
|
||||||
|
{ requestStoragePermission() },
|
||||||
|
{ disableDozeMode(disableDozeCode) }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,10 +134,13 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
|||||||
|
|
||||||
private fun initialise() {
|
private fun initialise() {
|
||||||
checkIfLatestVersion()
|
checkIfLatestVersion()
|
||||||
dir.createDirectories()
|
|
||||||
Checkout.preload(applicationContext)
|
Checkout.preload(applicationContext)
|
||||||
handleIntentFromExternalActivity()
|
handleIntentFromExternalActivity()
|
||||||
Log.i("Download Path",dir.defaultDir())
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun isInternetAvailableState(): State<Boolean?> {
|
||||||
|
return internetAvailability.observeAsState()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@ -140,7 +150,7 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
|||||||
.withActivity(this)
|
.withActivity(this)
|
||||||
.withFragmentManager(fragmentManager)
|
.withFragmentManager(fragmentManager)
|
||||||
.withMemoryBar(true)
|
.withMemoryBar(true)
|
||||||
.setTheme(StorageChooser.Theme(appContext).apply {
|
.setTheme(StorageChooser.Theme(applicationContext).apply {
|
||||||
scheme = applicationContext.resources.getIntArray(R.array.default_dark)
|
scheme = applicationContext.resources.getIntArray(R.array.default_dark)
|
||||||
})
|
})
|
||||||
.setDialogTitle("Set Download Directory")
|
.setDialogTitle("Set Download Directory")
|
||||||
@ -155,11 +165,11 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
|||||||
if (f.canWrite()) {
|
if (f.canWrite()) {
|
||||||
// hell yeah :)
|
// hell yeah :)
|
||||||
dir.setDownloadDirectory(path)
|
dir.setDownloadDirectory(path)
|
||||||
com.shabinder.common.uikit.showPopUpMessage(
|
showPopUpMessage(
|
||||||
"Download Directory Set to:\n${dir.defaultDir()} "
|
"Download Directory Set to:\n${dir.defaultDir()} "
|
||||||
)
|
)
|
||||||
}else{
|
}else{
|
||||||
com.shabinder.common.uikit.showPopUpMessage(
|
showPopUpMessage(
|
||||||
"NO WRITE ACCESS on \n$path ,\nReverting Back to Previous"
|
"NO WRITE ACCESS on \n$path ,\nReverting Back to Previous"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -169,6 +179,14 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
|||||||
chooser.show()
|
chooser.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showPopUpMessage(string: String, long: Boolean = false) {
|
||||||
|
android.widget.Toast.makeText(
|
||||||
|
applicationContext,
|
||||||
|
string,
|
||||||
|
if(long) android.widget.Toast.LENGTH_LONG else android.widget.Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
permissionGranted.value = checkPermissions()
|
permissionGranted.value = checkPermissions()
|
||||||
@ -182,9 +200,74 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
|||||||
override val database = this@MainActivity.dir.db
|
override val database = this@MainActivity.dir.db
|
||||||
override val fetchPlatformQueryResult = this@MainActivity.fetcher
|
override val fetchPlatformQueryResult = this@MainActivity.fetcher
|
||||||
override val directories: Dir = this@MainActivity.dir
|
override val directories: Dir = this@MainActivity.dir
|
||||||
override val showPopUpMessage: (String) -> Unit = ::uikitShowPopUpMessage
|
|
||||||
override val downloadProgressReport: MutableSharedFlow<HashMap<String, DownloadStatus>> = trackStatusFlow
|
override val downloadProgressReport: MutableSharedFlow<HashMap<String, DownloadStatus>> = trackStatusFlow
|
||||||
override val setDownloadDirectoryAction: () -> Unit = ::setUpOnPrefClickListener
|
override val actions = object: Actions {
|
||||||
|
|
||||||
|
override val platformActions = object : PlatformActions {
|
||||||
|
override val imageCacheDir: String = applicationContext.cacheDir.absolutePath + File.separator
|
||||||
|
override val sharedPreferences = applicationContext.getSharedPreferences(SharedPreferencesKey,
|
||||||
|
MODE_PRIVATE
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun addToLibrary(path: String) {
|
||||||
|
MediaScannerConnection.scanFile(
|
||||||
|
applicationContext,
|
||||||
|
listOf(path).toTypedArray(), null, null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sendTracksToService(array: ArrayList<TrackDetails>) {
|
||||||
|
for (list in array.chunked(50)){
|
||||||
|
val serviceIntent = Intent(this@MainActivity, ForegroundService::class.java)
|
||||||
|
serviceIntent.putParcelableArrayListExtra("object", list as ArrayList)
|
||||||
|
ContextCompat.startForegroundService(this@MainActivity, serviceIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showPopUpMessage(string: String, long: Boolean) = this@MainActivity.showPopUpMessage(string,long)
|
||||||
|
|
||||||
|
override fun setDownloadDirectoryAction() = setUpOnPrefClickListener()
|
||||||
|
|
||||||
|
override fun queryActiveTracks() {
|
||||||
|
val serviceIntent = Intent(this@MainActivity, ForegroundService::class.java).apply {
|
||||||
|
action = "query"
|
||||||
|
}
|
||||||
|
ContextCompat.startForegroundService(this@MainActivity, serviceIntent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun giveDonation() = startPayment(this@MainActivity)
|
||||||
|
|
||||||
|
override fun shareApp() {
|
||||||
|
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)
|
||||||
|
startActivity(shareIntent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun openPlatform(packageID: String, platformLink: String) {
|
||||||
|
val manager: PackageManager = applicationContext.packageManager
|
||||||
|
try {
|
||||||
|
val intent = manager.getLaunchIntentForPackage(packageID)
|
||||||
|
?: throw PackageManager.NameNotFoundException()
|
||||||
|
intent.addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
|
startActivity(intent)
|
||||||
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
|
val uri: Uri =
|
||||||
|
Uri.parse(platformLink)
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val isInternetAvailable get() = internetAvailability.value ?: true
|
||||||
|
override val dispatcherIO = Dispatchers.IO
|
||||||
|
override val currentPlatform = AllPlatforms.Jvm
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -208,6 +291,9 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Broadcast Handlers
|
||||||
|
* */
|
||||||
private fun initializeBroadcast(){
|
private fun initializeBroadcast(){
|
||||||
val intentFilter = IntentFilter().apply {
|
val intentFilter = IntentFilter().apply {
|
||||||
addAction(Status.QUEUED.name)
|
addAction(Status.QUEUED.name)
|
||||||
@ -292,7 +378,7 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
|||||||
while(!this@MainActivity::root.isInitialized){
|
while(!this@MainActivity::root.isInitialized){
|
||||||
delay(100)
|
delay(100)
|
||||||
}
|
}
|
||||||
if(isInternetAvailable)callBacks.searchLink(link)
|
if(methods.isInternetAvailable)callBacks.searchLink(link)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -301,7 +387,7 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
|||||||
|
|
||||||
override fun onPaymentError(errorCode: Int, response: String?) {
|
override fun onPaymentError(errorCode: Int, response: String?) {
|
||||||
try{
|
try{
|
||||||
uikitShowPopUpMessage("Payment Failed, Response:$response")
|
showPopUpMessage("Payment Failed, Response:$response")
|
||||||
}catch (e: Exception){
|
}catch (e: Exception){
|
||||||
Log.d("Razorpay Payment","Exception in onPaymentSuccess $response")
|
Log.d("Razorpay Payment","Exception in onPaymentSuccess $response")
|
||||||
}
|
}
|
||||||
@ -309,82 +395,39 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
|||||||
|
|
||||||
override fun onPaymentSuccess(razorpayPaymentId: String?) {
|
override fun onPaymentSuccess(razorpayPaymentId: String?) {
|
||||||
try{
|
try{
|
||||||
uikitShowPopUpMessage("Payment Successful, ThankYou!")
|
showPopUpMessage("Payment Successful, ThankYou!")
|
||||||
}catch (e: Exception){
|
}catch (e: Exception){
|
||||||
uikitShowPopUpMessage("Razorpay Payment, Error Occurred.")
|
showPopUpMessage("Razorpay Payment, Error Occurred.")
|
||||||
Log.d("Razorpay Payment","Exception in onPaymentSuccess, ${e.message}")
|
Log.d("Razorpay Payment","Exception in onPaymentSuccess, ${e.message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
/*
|
||||||
private fun PermissionDialog(){
|
* RazorPay Payment
|
||||||
var askForPermission by remember { mutableStateOf(false) }
|
* */
|
||||||
LaunchedEffect(Unit){
|
private fun startPayment(mainActivity: Activity) {
|
||||||
delay(2000)
|
val co = Checkout().apply {
|
||||||
askForPermission = true
|
setKeyID("rzp_live_3ZQeoFYOxjmXye")
|
||||||
|
setImage(com.shabinder.common.di.R.drawable.ic_spotiflyer_logo)
|
||||||
}
|
}
|
||||||
AnimatedVisibility(
|
|
||||||
askForPermission && !permissionGranted.value
|
|
||||||
){
|
|
||||||
AlertDialog(
|
|
||||||
onDismissRequest = {},
|
|
||||||
buttons = {
|
|
||||||
TextButton(
|
|
||||||
{
|
|
||||||
requestStoragePermission()
|
|
||||||
disableDozeMode(disableDozeCode)
|
|
||||||
},
|
|
||||||
Modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp).fillMaxWidth()
|
|
||||||
.background(colorPrimary, shape = SpotiFlyerShapes.medium)
|
|
||||||
.padding(horizontal = 8.dp),
|
|
||||||
){
|
|
||||||
Text("Grant Permissions",color = Color.Black,fontSize = 18.sp,textAlign = TextAlign.Center)
|
|
||||||
}
|
|
||||||
},title = {Text("Required Permissions:",style = SpotiFlyerTypography.h5,textAlign = TextAlign.Center)},
|
|
||||||
backgroundColor = Color.DarkGray,
|
|
||||||
text = {
|
|
||||||
Column{
|
|
||||||
Spacer(modifier = Modifier.padding(8.dp))
|
|
||||||
Row(verticalAlignment = Alignment.CenterVertically,
|
|
||||||
modifier = Modifier.fillMaxWidth().padding(vertical = 6.dp)
|
|
||||||
) {
|
|
||||||
Icon(Icons.Rounded.SdStorage,"Storage Permission.")
|
|
||||||
Spacer(modifier = Modifier.padding(start = 16.dp))
|
|
||||||
Column {
|
|
||||||
Text(
|
|
||||||
text = "Storage Permission.",
|
|
||||||
style = SpotiFlyerTypography.h6.copy(fontWeight = FontWeight.SemiBold)
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = "To download your favourite songs to this device.",
|
|
||||||
style = SpotiFlyerTypography.subtitle2,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.fillMaxWidth().padding(top = 6.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Icon(Icons.Rounded.SystemSecurityUpdate,"Allow Background Running")
|
|
||||||
Spacer(modifier = Modifier.padding(start = 16.dp))
|
|
||||||
Column {
|
|
||||||
Text(
|
|
||||||
text = "Background Running.",
|
|
||||||
style = SpotiFlyerTypography.h6.copy(fontWeight = FontWeight.SemiBold)
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = "To download all songs in background without any System Interruptions",
|
|
||||||
style = SpotiFlyerTypography.subtitle2,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
try {
|
||||||
activityContext = this
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.shabinder.spotiflyer.utils
|
package com.shabinder.spotiflyer.ui
|
||||||
|
|
||||||
import androidx.compose.animation.*
|
import androidx.compose.animation.*
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
@ -30,7 +30,6 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.shabinder.common.di.isInternetAvailableState
|
|
||||||
import com.shabinder.common.uikit.SpotiFlyerShapes
|
import com.shabinder.common.uikit.SpotiFlyerShapes
|
||||||
import com.shabinder.common.uikit.SpotiFlyerTypography
|
import com.shabinder.common.uikit.SpotiFlyerTypography
|
||||||
import com.shabinder.common.uikit.colorOffWhite
|
import com.shabinder.common.uikit.colorOffWhite
|
||||||
@ -39,7 +38,7 @@ import kotlinx.coroutines.delay
|
|||||||
@ExperimentalAnimationApi
|
@ExperimentalAnimationApi
|
||||||
@Composable
|
@Composable
|
||||||
fun NetworkDialog(
|
fun NetworkDialog(
|
||||||
networkAvailability: State<Boolean?> = isInternetAvailableState()
|
networkAvailability: State<Boolean?>
|
||||||
){
|
){
|
||||||
var visible by remember { mutableStateOf(false) }
|
var visible by remember { mutableStateOf(false) }
|
||||||
|
|
@ -0,0 +1,107 @@
|
|||||||
|
package com.shabinder.spotiflyer.ui
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.AlertDialog
|
||||||
|
import androidx.compose.material.Icon
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.material.TextButton
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.SdStorage
|
||||||
|
import androidx.compose.material.icons.rounded.SystemSecurityUpdate
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.shabinder.common.uikit.SpotiFlyerShapes
|
||||||
|
import com.shabinder.common.uikit.SpotiFlyerTypography
|
||||||
|
import com.shabinder.common.uikit.colorPrimary
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
|
@ExperimentalAnimationApi
|
||||||
|
@Composable
|
||||||
|
fun PermissionDialog(
|
||||||
|
permissionGranted: Boolean,
|
||||||
|
requestStoragePermission:() -> Unit,
|
||||||
|
disableDozeMode:() -> Unit
|
||||||
|
){
|
||||||
|
var askForPermission by remember { mutableStateOf(false) }
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
delay(2000)
|
||||||
|
askForPermission = true
|
||||||
|
}
|
||||||
|
AnimatedVisibility(
|
||||||
|
askForPermission && !permissionGranted
|
||||||
|
) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = {},
|
||||||
|
buttons = {
|
||||||
|
TextButton(
|
||||||
|
{
|
||||||
|
requestStoragePermission()
|
||||||
|
disableDozeMode()
|
||||||
|
},
|
||||||
|
Modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp).fillMaxWidth()
|
||||||
|
.background(colorPrimary, shape = SpotiFlyerShapes.medium)
|
||||||
|
.padding(horizontal = 8.dp),
|
||||||
|
){
|
||||||
|
Text("Grant Permissions",color = Color.Black,fontSize = 18.sp,textAlign = TextAlign.Center)
|
||||||
|
}
|
||||||
|
},title = { Text("Required Permissions:",style = SpotiFlyerTypography.h5,textAlign = TextAlign.Center) },
|
||||||
|
backgroundColor = Color.DarkGray,
|
||||||
|
text = {
|
||||||
|
Column{
|
||||||
|
Spacer(modifier = Modifier.padding(8.dp))
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||||
|
) {
|
||||||
|
Icon(Icons.Rounded.SdStorage,"Storage Permission.")
|
||||||
|
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||||
|
Column {
|
||||||
|
Text(
|
||||||
|
text = "Storage Permission.",
|
||||||
|
style = SpotiFlyerTypography.h6.copy(fontWeight = FontWeight.SemiBold)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "To download your favourite songs to this device.",
|
||||||
|
style = SpotiFlyerTypography.subtitle2,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(top = 6.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(Icons.Rounded.SystemSecurityUpdate,"Allow Background Running")
|
||||||
|
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||||
|
Column {
|
||||||
|
Text(
|
||||||
|
text = "Background Running.",
|
||||||
|
style = SpotiFlyerTypography.h6.copy(fontWeight = FontWeight.SemiBold)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "To download all songs in background without any System Interruptions",
|
||||||
|
style = SpotiFlyerTypography.subtitle2,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -36,11 +36,12 @@ object Versions {
|
|||||||
// Internet
|
// Internet
|
||||||
const val ktor = "1.5.3"
|
const val ktor = "1.5.3"
|
||||||
|
|
||||||
const val kotlinxSerialization = "1.1.0"
|
const val kotlinxSerialization = "1.2.0"
|
||||||
// Database
|
|
||||||
const val sqlDelight = "1.4.4"
|
|
||||||
|
|
||||||
const val sqliteJdbcDriver = "3.30.1"
|
// Database
|
||||||
|
const val sqlDelight = "1.5.0"
|
||||||
|
|
||||||
|
const val sqliteJdbcDriver = "3.34.0"
|
||||||
const val slf4j = "1.7.30"
|
const val slf4j = "1.7.30"
|
||||||
|
|
||||||
// Android
|
// Android
|
||||||
|
@ -35,9 +35,8 @@ import androidx.compose.ui.text.font.Font
|
|||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import com.shabinder.common.database.R
|
import com.shabinder.common.database.R
|
||||||
import com.shabinder.common.database.appContext
|
|
||||||
import com.shabinder.common.di.Picture
|
import com.shabinder.common.di.Picture
|
||||||
import com.shabinder.common.di.dispatcherIO
|
import com.shabinder.common.models.methods
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -51,7 +50,7 @@ actual fun ImageLoad(
|
|||||||
var pic by remember(link) { mutableStateOf<ImageBitmap?>(null) }
|
var pic by remember(link) { mutableStateOf<ImageBitmap?>(null) }
|
||||||
|
|
||||||
LaunchedEffect(link) {
|
LaunchedEffect(link) {
|
||||||
withContext(dispatcherIO) {
|
withContext(methods.dispatcherIO) {
|
||||||
pic = loader(link).image
|
pic = loader(link).image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,7 +136,3 @@ actual fun Toast(
|
|||||||
) {
|
) {
|
||||||
// We Have Android's Implementation of Toast so its just Empty
|
// We Have Android's Implementation of Toast so its just Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun showPopUpMessage(text: String) {
|
|
||||||
android.widget.Toast.makeText(appContext, text, android.widget.Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
|
@ -50,6 +50,7 @@ import com.shabinder.common.di.Picture
|
|||||||
import com.shabinder.common.list.SpotiFlyerList
|
import com.shabinder.common.list.SpotiFlyerList
|
||||||
import com.shabinder.common.models.DownloadStatus
|
import com.shabinder.common.models.DownloadStatus
|
||||||
import com.shabinder.common.models.TrackDetails
|
import com.shabinder.common.models.TrackDetails
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -62,7 +63,7 @@ fun SpotiFlyerListContent(
|
|||||||
LaunchedEffect(model.errorOccurred) {
|
LaunchedEffect(model.errorOccurred) {
|
||||||
/*Handle if Any Exception Occurred*/
|
/*Handle if Any Exception Occurred*/
|
||||||
model.errorOccurred?.let {
|
model.errorOccurred?.let {
|
||||||
showPopUpMessage(it.message ?: "An Error Occurred, Check your Link / Connection")
|
methods.showPopUpMessage(it.message ?: "An Error Occurred, Check your Link / Connection")
|
||||||
component.onBackPressed()
|
component.onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,12 +73,10 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.shabinder.common.di.Picture
|
import com.shabinder.common.di.Picture
|
||||||
import com.shabinder.common.di.giveDonation
|
|
||||||
import com.shabinder.common.di.openPlatform
|
|
||||||
import com.shabinder.common.di.shareApp
|
|
||||||
import com.shabinder.common.main.SpotiFlyerMain
|
import com.shabinder.common.main.SpotiFlyerMain
|
||||||
import com.shabinder.common.main.SpotiFlyerMain.HomeCategory
|
import com.shabinder.common.main.SpotiFlyerMain.HomeCategory
|
||||||
import com.shabinder.common.models.DownloadRecord
|
import com.shabinder.common.models.DownloadRecord
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SpotiFlyerMainContent(component: SpotiFlyerMain) {
|
fun SpotiFlyerMainContent(component: SpotiFlyerMain) {
|
||||||
@ -195,7 +193,7 @@ fun SearchPanel(
|
|||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
modifier = Modifier.padding(12.dp).wrapContentWidth(),
|
modifier = Modifier.padding(12.dp).wrapContentWidth(),
|
||||||
onClick = {
|
onClick = {
|
||||||
if (link.isBlank()) showPopUpMessage("Enter A Link!")
|
if (link.isBlank()) methods.showPopUpMessage("Enter A Link!")
|
||||||
else {
|
else {
|
||||||
// TODO if(!isOnline(ctx)) showPopUpMessage("Check Your Internet Connection") else
|
// TODO if(!isOnline(ctx)) showPopUpMessage("Check Your Internet Connection") else
|
||||||
onSearch(link)
|
onSearch(link)
|
||||||
@ -237,7 +235,7 @@ fun AboutColumn(modifier: Modifier = Modifier) {
|
|||||||
"Open Spotify",
|
"Open Spotify",
|
||||||
tint = Color.Unspecified,
|
tint = Color.Unspecified,
|
||||||
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
||||||
onClick = { openPlatform("com.spotify.music", "http://open.spotify.com") }
|
onClick = { methods.openPlatform("com.spotify.music", "http://open.spotify.com") }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
Spacer(modifier = modifier.padding(start = 16.dp))
|
Spacer(modifier = modifier.padding(start = 16.dp))
|
||||||
@ -246,7 +244,7 @@ fun AboutColumn(modifier: Modifier = Modifier) {
|
|||||||
"Open Gaana",
|
"Open Gaana",
|
||||||
tint = Color.Unspecified,
|
tint = Color.Unspecified,
|
||||||
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
||||||
onClick = { openPlatform("com.gaana", "http://gaana.com") }
|
onClick = { methods.openPlatform("com.gaana", "http://gaana.com") }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
Spacer(modifier = modifier.padding(start = 16.dp))
|
Spacer(modifier = modifier.padding(start = 16.dp))
|
||||||
@ -255,7 +253,7 @@ fun AboutColumn(modifier: Modifier = Modifier) {
|
|||||||
"Open Youtube",
|
"Open Youtube",
|
||||||
tint = Color.Unspecified,
|
tint = Color.Unspecified,
|
||||||
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
||||||
onClick = { openPlatform("com.google.android.youtube", "http://m.youtube.com") }
|
onClick = { methods.openPlatform("com.google.android.youtube", "http://m.youtube.com") }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
Spacer(modifier = modifier.padding(start = 12.dp))
|
Spacer(modifier = modifier.padding(start = 12.dp))
|
||||||
@ -264,7 +262,7 @@ fun AboutColumn(modifier: Modifier = Modifier) {
|
|||||||
"Open Youtube Music",
|
"Open Youtube Music",
|
||||||
tint = Color.Unspecified,
|
tint = Color.Unspecified,
|
||||||
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
modifier = Modifier.clip(SpotiFlyerShapes.small).clickable(
|
||||||
onClick = { openPlatform("com.google.android.apps.youtube.music", "https://music.youtube.com/") }
|
onClick = { methods.openPlatform("com.google.android.apps.youtube.music", "https://music.youtube.com/") }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -285,7 +283,7 @@ fun AboutColumn(modifier: Modifier = Modifier) {
|
|||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
modifier = Modifier.fillMaxWidth().clickable(
|
modifier = Modifier.fillMaxWidth().clickable(
|
||||||
onClick = { openPlatform("", "http://github.com/Shabinder/SpotiFlyer") }
|
onClick = { methods.openPlatform("", "http://github.com/Shabinder/SpotiFlyer") }
|
||||||
)
|
)
|
||||||
.padding(vertical = 6.dp)
|
.padding(vertical = 6.dp)
|
||||||
) {
|
) {
|
||||||
@ -304,7 +302,7 @@ fun AboutColumn(modifier: Modifier = Modifier) {
|
|||||||
}
|
}
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||||
.clickable(onClick = { openPlatform("", "http://github.com/Shabinder/SpotiFlyer") }),
|
.clickable(onClick = { methods.openPlatform("", "http://github.com/Shabinder/SpotiFlyer") }),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Icon(Icons.Rounded.Flag, "Help Translate", Modifier.size(32.dp))
|
Icon(Icons.Rounded.Flag, "Help Translate", Modifier.size(32.dp))
|
||||||
@ -322,7 +320,7 @@ fun AboutColumn(modifier: Modifier = Modifier) {
|
|||||||
}
|
}
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||||
.clickable(onClick = { giveDonation() }),
|
.clickable(onClick = { methods.giveDonation() }),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Icon(Icons.Rounded.CardGiftcard, "Support Developer")
|
Icon(Icons.Rounded.CardGiftcard, "Support Developer")
|
||||||
@ -342,7 +340,7 @@ fun AboutColumn(modifier: Modifier = Modifier) {
|
|||||||
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
modifier = modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||||
.clickable(
|
.clickable(
|
||||||
onClick = {
|
onClick = {
|
||||||
shareApp()
|
methods.shareApp()
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
@ -24,8 +24,6 @@ enum class ToastDuration(val value: Int) {
|
|||||||
Short(1000), Long(3000)
|
Short(1000), Long(3000)
|
||||||
}
|
}
|
||||||
|
|
||||||
expect fun showPopUpMessage(text: String)
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
expect fun Toast(
|
expect fun Toast(
|
||||||
text: String,
|
text: String,
|
||||||
|
@ -28,8 +28,6 @@ import androidx.compose.runtime.setValue
|
|||||||
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.painter.Painter
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
|
||||||
import androidx.compose.ui.graphics.vector.VectorPainter
|
|
||||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.res.vectorXmlResource
|
import androidx.compose.ui.res.vectorXmlResource
|
||||||
@ -37,7 +35,7 @@ import androidx.compose.ui.text.font.FontFamily
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.platform.Font
|
import androidx.compose.ui.text.platform.Font
|
||||||
import com.shabinder.common.di.Picture
|
import com.shabinder.common.di.Picture
|
||||||
import com.shabinder.common.di.dispatcherIO
|
import com.shabinder.common.models.methods
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -50,7 +48,7 @@ actual fun ImageLoad(
|
|||||||
) {
|
) {
|
||||||
var pic by remember(link) { mutableStateOf<ImageBitmap?>(null) }
|
var pic by remember(link) { mutableStateOf<ImageBitmap?>(null) }
|
||||||
LaunchedEffect(link) {
|
LaunchedEffect(link) {
|
||||||
withContext(dispatcherIO) {
|
withContext(methods.dispatcherIO) {
|
||||||
pic = loader(link).image
|
pic = loader(link).image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ import kotlinx.coroutines.launch
|
|||||||
private val message: MutableState<String> = mutableStateOf("")
|
private val message: MutableState<String> = mutableStateOf("")
|
||||||
private val state: MutableState<Boolean> = mutableStateOf(false)
|
private val state: MutableState<Boolean> = mutableStateOf(false)
|
||||||
|
|
||||||
actual fun showPopUpMessage(text: String) {
|
fun showToast(text: String) {
|
||||||
message.value = text
|
message.value = text
|
||||||
state.value = true
|
state.value = true
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,15 @@ kotlin {
|
|||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api("dev.icerock.moko:parcelize:0.6.0")
|
api("dev.icerock.moko:parcelize:0.6.1")
|
||||||
api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0")
|
api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0")
|
||||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3-native-mt")
|
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3-native-mt")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(HostOS.isMac){
|
||||||
|
val iosMain by getting {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.shabinder.common.models
|
||||||
|
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
|
||||||
|
actual interface PlatformActions {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val SharedPreferencesKey = "configurations"
|
||||||
|
}
|
||||||
|
|
||||||
|
val imageCacheDir: String
|
||||||
|
|
||||||
|
val sharedPreferences: SharedPreferences
|
||||||
|
|
||||||
|
fun addToLibrary(path: String)
|
||||||
|
|
||||||
|
fun sendTracksToService(array: ArrayList<TrackDetails>)
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package com.shabinder.common.models
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Holder to call platform actions from anywhere
|
||||||
|
* */
|
||||||
|
lateinit var methods: Actions
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interface Having All Platform Dependent Functions
|
||||||
|
* */
|
||||||
|
interface Actions {
|
||||||
|
|
||||||
|
// Platform Specific Actions
|
||||||
|
val platformActions: PlatformActions
|
||||||
|
|
||||||
|
// Show Toast
|
||||||
|
fun showPopUpMessage(string: String, long: Boolean = false)
|
||||||
|
|
||||||
|
// Change Download Directory
|
||||||
|
fun setDownloadDirectoryAction()
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query Downloading Tracks
|
||||||
|
* ex- Get Tracks from android service etc
|
||||||
|
* */
|
||||||
|
fun queryActiveTracks()
|
||||||
|
|
||||||
|
// Donate Money
|
||||||
|
fun giveDonation()
|
||||||
|
|
||||||
|
// Share SpotiFlyer App
|
||||||
|
fun shareApp()
|
||||||
|
|
||||||
|
// Open / Redirect to another Platform
|
||||||
|
fun openPlatform(packageID: String, platformLink: String)
|
||||||
|
|
||||||
|
// IO-Dispatcher
|
||||||
|
val dispatcherIO: CoroutineDispatcher
|
||||||
|
|
||||||
|
// Internet Connectivity Check
|
||||||
|
val isInternetAvailable: Boolean
|
||||||
|
|
||||||
|
// Current Platform Info
|
||||||
|
val currentPlatform: AllPlatforms
|
||||||
|
}
|
@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.shabinder.common.models
|
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class Optional<T>(val value: T?)
|
|
@ -0,0 +1,3 @@
|
|||||||
|
package com.shabinder.common.models
|
||||||
|
|
||||||
|
expect interface PlatformActions
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.shabinder.common.models
|
||||||
|
|
||||||
|
actual interface PlatformActions {
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.shabinder.common.models
|
||||||
|
|
||||||
|
actual interface PlatformActions {
|
||||||
|
}
|
@ -35,6 +35,9 @@ kotlin {
|
|||||||
implementation(SqlDelight.runtime)
|
implementation(SqlDelight.runtime)
|
||||||
implementation(SqlDelight.coroutineExtensions)
|
implementation(SqlDelight.coroutineExtensions)
|
||||||
api(Extras.kermit)
|
api(Extras.kermit)
|
||||||
|
// koin
|
||||||
|
api(Koin.core)
|
||||||
|
api(Koin.test)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,24 +16,17 @@
|
|||||||
|
|
||||||
package com.shabinder.common.database
|
package com.shabinder.common.database
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Context
|
|
||||||
import co.touchlab.kermit.LogcatLogger
|
import co.touchlab.kermit.LogcatLogger
|
||||||
import co.touchlab.kermit.Logger
|
import co.touchlab.kermit.Logger
|
||||||
import com.shabinder.database.Database
|
import com.shabinder.database.Database
|
||||||
import com.squareup.sqldelight.android.AndroidSqliteDriver
|
import com.squareup.sqldelight.android.AndroidSqliteDriver
|
||||||
|
import org.koin.dsl.module
|
||||||
lateinit var appContext: Context
|
|
||||||
|
|
||||||
/*
|
|
||||||
* As MainActivity is God Activity , hence its active almost throughout App's lifetime
|
|
||||||
* */
|
|
||||||
@SuppressLint("StaticFieldLeak")
|
|
||||||
lateinit var activityContext: Context
|
|
||||||
|
|
||||||
@Suppress("RedundantNullableReturnType")
|
@Suppress("RedundantNullableReturnType")
|
||||||
actual fun createDatabase(): Database? {
|
actual fun databaseModule() = module {
|
||||||
val driver = AndroidSqliteDriver(Database.Schema, appContext, "Database.db")
|
single {
|
||||||
return Database(driver)
|
val driver = AndroidSqliteDriver(Database.Schema, get(), "Database.db")
|
||||||
|
SpotiFlyerDatabase(Database(driver))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
actual fun getLogger(): Logger = LogcatLogger()
|
actual fun getLogger(): Logger = LogcatLogger()
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
package com.shabinder.common.database
|
package com.shabinder.common.database
|
||||||
|
|
||||||
import co.touchlab.kermit.Logger
|
import co.touchlab.kermit.Logger
|
||||||
import com.shabinder.database.Database
|
import org.koin.core.module.Module
|
||||||
|
|
||||||
expect fun createDatabase(): Database?
|
expect fun databaseModule(): Module
|
||||||
expect fun getLogger(): Logger
|
expect fun getLogger(): Logger
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.shabinder.common.database
|
||||||
|
|
||||||
|
import com.shabinder.database.Database
|
||||||
|
|
||||||
|
/* Database Wrapper */
|
||||||
|
class SpotiFlyerDatabase(val instance: Database?)
|
@ -20,13 +20,17 @@ import co.touchlab.kermit.CommonLogger
|
|||||||
import co.touchlab.kermit.Logger
|
import co.touchlab.kermit.Logger
|
||||||
import com.shabinder.database.Database
|
import com.shabinder.database.Database
|
||||||
import com.squareup.sqldelight.sqlite.driver.JdbcSqliteDriver
|
import com.squareup.sqldelight.sqlite.driver.JdbcSqliteDriver
|
||||||
|
import org.koin.dsl.module
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@Suppress("RedundantNullableReturnType")
|
@Suppress("RedundantNullableReturnType")
|
||||||
actual fun createDatabase(): Database? {
|
actual fun databaseModule() = module {
|
||||||
val databasePath = File(System.getProperty("java.io.tmpdir"), "Database.db")
|
single {
|
||||||
val driver = JdbcSqliteDriver(url = "jdbc:sqlite:${databasePath.absolutePath}")
|
val databasePath = File(System.getProperty("user.home") + File.separator + "SpotiFlyer" + File.separator + "Database", "Database.db")
|
||||||
.also { Database.Schema.create(it) }
|
databasePath.parentFile.mkdirs()
|
||||||
return Database(driver)
|
val driver = JdbcSqliteDriver(url = "jdbc:sqlite:${databasePath.absolutePath}")
|
||||||
|
.also { Database.Schema.create(it) }
|
||||||
|
SpotiFlyerDatabase(Database(driver))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
actual fun getLogger(): Logger = CommonLogger()
|
actual fun getLogger(): Logger = CommonLogger()
|
||||||
|
@ -3,12 +3,15 @@ package com.shabinder.common.database
|
|||||||
import co.touchlab.kermit.Logger
|
import co.touchlab.kermit.Logger
|
||||||
import co.touchlab.kermit.NSLogLogger
|
import co.touchlab.kermit.NSLogLogger
|
||||||
import com.shabinder.database.Database
|
import com.shabinder.database.Database
|
||||||
|
import org.koin.dsl.module
|
||||||
import com.squareup.sqldelight.drivers.native.NativeSqliteDriver
|
import com.squareup.sqldelight.drivers.native.NativeSqliteDriver
|
||||||
|
|
||||||
@Suppress("RedundantNullableReturnType")
|
@Suppress("RedundantNullableReturnType")
|
||||||
actual fun createDatabase(): Database? {
|
actual fun databaseModule(): Module {
|
||||||
val driver = NativeSqliteDriver(Database.Schema, "Database.db")
|
single {
|
||||||
return Database(driver)
|
val driver = NativeSqliteDriver(Database.Schema, "Database.db")
|
||||||
|
SpotiFlyerDatabase(Database(driver))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun getLogger(): Logger = NSLogLogger()
|
actual fun getLogger(): Logger = NSLogLogger()
|
@ -19,6 +19,7 @@ package com.shabinder.common.database
|
|||||||
import co.touchlab.kermit.CommonLogger
|
import co.touchlab.kermit.CommonLogger
|
||||||
import co.touchlab.kermit.Logger
|
import co.touchlab.kermit.Logger
|
||||||
import com.shabinder.database.Database
|
import com.shabinder.database.Database
|
||||||
|
import org.koin.dsl.module
|
||||||
|
|
||||||
actual fun createDatabase(): Database? = null
|
actual fun databaseModule() = module { single { SpotiFlyerDatabase(null) } }
|
||||||
actual fun getLogger(): Logger = CommonLogger()
|
actual fun getLogger(): Logger = CommonLogger()
|
||||||
|
@ -52,24 +52,21 @@ kotlin {
|
|||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0")
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.2.0")
|
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.2.0")
|
||||||
implementation("com.shabinder.fuzzywuzzy:fuzzywuzzy:1.0")
|
implementation("com.shabinder.fuzzywuzzy:fuzzywuzzy:1.0")
|
||||||
implementation(Ktor.clientCore)
|
api(Ktor.clientCore)
|
||||||
implementation(Ktor.clientSerialization)
|
api(Ktor.clientSerialization)
|
||||||
implementation(Ktor.clientLogging)
|
api(Ktor.clientLogging)
|
||||||
implementation(Ktor.clientJson)
|
api(Ktor.clientJson)
|
||||||
implementation(Ktor.auth)
|
api(Ktor.auth)
|
||||||
api(Extras.youtubeDownloader)
|
api(Extras.youtubeDownloader)
|
||||||
// koin
|
|
||||||
api(Koin.core)
|
|
||||||
api(Koin.test)
|
|
||||||
api(Extras.kermit)
|
api(Extras.kermit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
androidMain {
|
androidMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(compose.materialIconsExtended)
|
implementation(compose.materialIconsExtended)
|
||||||
implementation(Koin.android)
|
api(Koin.android)
|
||||||
implementation(Ktor.clientAndroid)
|
api(Ktor.clientAndroid)
|
||||||
implementation(Extras.Android.razorpay)
|
api(Extras.Android.razorpay)
|
||||||
api(Extras.mp3agic)
|
api(Extras.mp3agic)
|
||||||
api(Extras.jaudioTagger)
|
api(Extras.jaudioTagger)
|
||||||
api("com.github.shabinder:storage-chooser:2.0.4.45")
|
api("com.github.shabinder:storage-chooser:2.0.4.45")
|
||||||
@ -79,18 +76,18 @@ kotlin {
|
|||||||
desktopMain {
|
desktopMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(compose.materialIconsExtended)
|
implementation(compose.materialIconsExtended)
|
||||||
implementation(Ktor.clientApache)
|
api(Ktor.clientApache)
|
||||||
implementation(Ktor.slf4j)
|
api(Ktor.slf4j)
|
||||||
api(Extras.mp3agic)
|
api(Extras.mp3agic)
|
||||||
api(Extras.jaudioTagger)
|
api(Extras.jaudioTagger)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jsMain {
|
jsMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":common:data-models"))
|
|
||||||
implementation(Ktor.clientJs)
|
|
||||||
implementation(npm("browser-id3-writer", "4.4.0"))
|
implementation(npm("browser-id3-writer", "4.4.0"))
|
||||||
implementation(npm("file-saver", "2.0.4"))
|
implementation(npm("file-saver", "2.0.4"))
|
||||||
|
implementation(project(":common:data-models"))
|
||||||
|
api(Ktor.clientJs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,90 +16,8 @@
|
|||||||
|
|
||||||
package com.shabinder.common.di
|
package com.shabinder.common.di
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.net.Uri
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import com.razorpay.Checkout
|
|
||||||
import com.shabinder.common.database.activityContext
|
|
||||||
import com.shabinder.common.di.worker.ForegroundService
|
|
||||||
import com.shabinder.common.models.AllPlatforms
|
|
||||||
import com.shabinder.common.models.TrackDetails
|
import com.shabinder.common.models.TrackDetails
|
||||||
import kotlinx.coroutines.Dispatchers
|
import com.shabinder.common.models.methods
|
||||||
import org.json.JSONObject
|
|
||||||
import com.codekidlabs.storagechooser.StorageChooser
|
|
||||||
import com.codekidlabs.storagechooser.StorageChooser.OnSelectListener
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
actual fun openPlatform(packageID: String, platformLink: String) {
|
|
||||||
val manager: PackageManager = activityContext.packageManager
|
|
||||||
try {
|
|
||||||
val intent = manager.getLaunchIntentForPackage(packageID)
|
|
||||||
?: throw PackageManager.NameNotFoundException()
|
|
||||||
intent.addCategory(Intent.CATEGORY_LAUNCHER)
|
|
||||||
activityContext.startActivity(intent)
|
|
||||||
} catch (e: PackageManager.NameNotFoundException) {
|
|
||||||
val uri: Uri =
|
|
||||||
Uri.parse(platformLink)
|
|
||||||
val intent = Intent(Intent.ACTION_VIEW, uri)
|
|
||||||
activityContext.startActivity(intent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actual val dispatcherIO = Dispatchers.IO
|
|
||||||
actual val currentPlatform: AllPlatforms = AllPlatforms.Jvm
|
|
||||||
|
|
||||||
actual val isInternetAvailable: Boolean
|
|
||||||
get() = internetAvailability.value ?: true
|
|
||||||
|
|
||||||
actual fun shareApp() {
|
|
||||||
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)
|
|
||||||
activityContext.startActivity(shareIntent)
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun giveDonation() = startPayment()
|
|
||||||
|
|
||||||
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() {
|
|
||||||
val serviceIntent = Intent(activityContext, ForegroundService::class.java).apply {
|
|
||||||
action = "query"
|
|
||||||
}
|
|
||||||
ContextCompat.startForegroundService(activityContext, serviceIntent)
|
|
||||||
}
|
|
||||||
|
|
||||||
actual suspend fun downloadTracks(
|
actual suspend fun downloadTracks(
|
||||||
list: List<TrackDetails>,
|
list: List<TrackDetails>,
|
||||||
@ -107,8 +25,6 @@ actual suspend fun downloadTracks(
|
|||||||
dir: Dir
|
dir: Dir
|
||||||
) {
|
) {
|
||||||
if (!list.isNullOrEmpty()) {
|
if (!list.isNullOrEmpty()) {
|
||||||
val serviceIntent = Intent(activityContext, ForegroundService::class.java)
|
methods.platformActions.sendTracksToService(ArrayList(list))
|
||||||
serviceIntent.putParcelableArrayListExtra("object", ArrayList<TrackDetails>(list))
|
|
||||||
activityContext.let { ContextCompat.startForegroundService(it, serviceIntent) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,19 +16,16 @@
|
|||||||
|
|
||||||
package com.shabinder.common.di
|
package com.shabinder.common.di
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Context.MODE_PRIVATE
|
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.media.MediaScannerConnection
|
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.compose.ui.graphics.asImageBitmap
|
import androidx.compose.ui.graphics.asImageBitmap
|
||||||
import co.touchlab.kermit.Kermit
|
import co.touchlab.kermit.Kermit
|
||||||
import com.mpatric.mp3agic.Mp3File
|
import com.mpatric.mp3agic.Mp3File
|
||||||
import com.shabinder.common.database.appContext
|
import com.shabinder.common.database.SpotiFlyerDatabase
|
||||||
import com.shabinder.common.models.TrackDetails
|
import com.shabinder.common.models.TrackDetails
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
import com.shabinder.database.Database
|
import com.shabinder.database.Database
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -40,19 +37,13 @@ import java.net.URL
|
|||||||
|
|
||||||
actual class Dir actual constructor(
|
actual class Dir actual constructor(
|
||||||
private val logger: Kermit,
|
private val logger: Kermit,
|
||||||
private val database: Database?,
|
private val spotiFlyerDatabase: SpotiFlyerDatabase,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
const val SharedPreferencesKey = "configurations"
|
|
||||||
const val DirKey = "downloadDir"
|
const val DirKey = "downloadDir"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val context: Context
|
private val sharedPreferences:SharedPreferences by lazy { methods.platformActions.sharedPreferences }
|
||||||
get() = appContext
|
|
||||||
|
|
||||||
private val sharedPreferences:SharedPreferences by lazy {
|
|
||||||
context.getSharedPreferences(SharedPreferencesKey,MODE_PRIVATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setDownloadDirectory(newBasePath:String){
|
fun setDownloadDirectory(newBasePath:String){
|
||||||
sharedPreferences.edit().putString(DirKey,newBasePath).apply()
|
sharedPreferences.edit().putString(DirKey,newBasePath).apply()
|
||||||
@ -63,7 +54,7 @@ actual class Dir actual constructor(
|
|||||||
|
|
||||||
actual fun fileSeparator(): String = File.separator
|
actual fun fileSeparator(): String = File.separator
|
||||||
|
|
||||||
actual fun imageCacheDir(): String = context.cacheDir.absolutePath + File.separator
|
actual fun imageCacheDir(): String = methods.platformActions.imageCacheDir
|
||||||
|
|
||||||
// fun call in order to always access Updated Value
|
// fun call in order to always access Updated Value
|
||||||
actual fun defaultDir(): String = sharedPreferences.getString(DirKey,defaultBaseDir)!! + File.separator +
|
actual fun defaultDir(): String = sharedPreferences.getString(DirKey,defaultBaseDir)!! + File.separator +
|
||||||
@ -158,13 +149,7 @@ actual class Dir actual constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun addToLibrary(path: String) {
|
actual fun addToLibrary(path: String) = methods.platformActions.addToLibrary(path)
|
||||||
logger.d { "Scanning File" }
|
|
||||||
MediaScannerConnection.scanFile(
|
|
||||||
appContext,
|
|
||||||
listOf(path).toTypedArray(), null, null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
actual suspend fun loadImage(url: String): Picture = withContext(Dispatchers.IO){
|
actual suspend fun loadImage(url: String): Picture = withContext(Dispatchers.IO){
|
||||||
val cachePath = imageCacheDir() + getNameURL(url)
|
val cachePath = imageCacheDir() + getNameURL(url)
|
||||||
@ -214,5 +199,5 @@ actual class Dir actual constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual val db: Database? = database
|
actual val db: Database? = spotiFlyerDatabase.instance
|
||||||
}
|
}
|
||||||
|
@ -23,10 +23,7 @@ import android.net.Network
|
|||||||
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
|
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
|
||||||
import android.net.NetworkRequest
|
import android.net.NetworkRequest
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.State
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import com.shabinder.common.database.appContext
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
@ -34,13 +31,6 @@ import java.net.InetSocketAddress
|
|||||||
|
|
||||||
const val TAG = "C-Manager"
|
const val TAG = "C-Manager"
|
||||||
|
|
||||||
val internetAvailability by lazy { ConnectionLiveData(appContext) }
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun isInternetAvailableState(): State<Boolean?> {
|
|
||||||
return internetAvailability.observeAsState()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save all available networks with an internet connection to a set (@validNetworks).
|
* Save all available networks with an internet connection to a set (@validNetworks).
|
||||||
* As long as the size of the set > 0, this LiveData emits true.
|
* As long as the size of the set > 0, this LiveData emits true.
|
||||||
@ -49,7 +39,7 @@ fun isInternetAvailableState(): State<Boolean?> {
|
|||||||
* Inspired by:
|
* Inspired by:
|
||||||
* https://github.com/AlexSheva-mason/Rick-Morty-Database/blob/master/app/src/main/java/com/shevaalex/android/rickmortydatabase/utils/networking/ConnectionLiveData.kt
|
* https://github.com/AlexSheva-mason/Rick-Morty-Database/blob/master/app/src/main/java/com/shevaalex/android/rickmortydatabase/utils/networking/ConnectionLiveData.kt
|
||||||
*/
|
*/
|
||||||
class ConnectionLiveData(context: Context = appContext) : LiveData<Boolean>() {
|
class ConnectionLiveData(context: Context) : LiveData<Boolean>() {
|
||||||
|
|
||||||
private lateinit var networkCallback: ConnectivityManager.NetworkCallback
|
private lateinit var networkCallback: ConnectivityManager.NetworkCallback
|
||||||
private val cm = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
|
private val cm = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
package com.shabinder.common.di
|
package com.shabinder.common.di
|
||||||
|
|
||||||
import co.touchlab.kermit.Kermit
|
import co.touchlab.kermit.Kermit
|
||||||
import com.shabinder.common.database.createDatabase
|
import com.shabinder.common.database.databaseModule
|
||||||
import com.shabinder.common.database.getLogger
|
import com.shabinder.common.database.getLogger
|
||||||
import com.shabinder.common.di.providers.GaanaProvider
|
import com.shabinder.common.di.providers.GaanaProvider
|
||||||
import com.shabinder.common.di.providers.SpotifyProvider
|
import com.shabinder.common.di.providers.SpotifyProvider
|
||||||
@ -39,12 +39,12 @@ import org.koin.dsl.module
|
|||||||
fun initKoin(enableNetworkLogs: Boolean = false, appDeclaration: KoinAppDeclaration = {}) =
|
fun initKoin(enableNetworkLogs: Boolean = false, appDeclaration: KoinAppDeclaration = {}) =
|
||||||
startKoin {
|
startKoin {
|
||||||
appDeclaration()
|
appDeclaration()
|
||||||
modules(commonModule(enableNetworkLogs = enableNetworkLogs))
|
modules(commonModule(enableNetworkLogs = enableNetworkLogs), databaseModule())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun commonModule(enableNetworkLogs: Boolean) = module {
|
fun commonModule(enableNetworkLogs: Boolean) = module {
|
||||||
single { createHttpClient(enableNetworkLogs = enableNetworkLogs) }
|
single { createHttpClient(enableNetworkLogs = enableNetworkLogs) }
|
||||||
single { Dir(get(), createDatabase()) }
|
single { Dir(get(), get()) }
|
||||||
single { Kermit(getLogger()) }
|
single { Kermit(getLogger()) }
|
||||||
single { TokenStore(get(), get()) }
|
single { TokenStore(get(), get()) }
|
||||||
single { YoutubeMusic(get(), get()) }
|
single { YoutubeMusic(get(), get()) }
|
||||||
|
@ -17,26 +17,22 @@
|
|||||||
package com.shabinder.common.di
|
package com.shabinder.common.di
|
||||||
|
|
||||||
import co.touchlab.kermit.Kermit
|
import co.touchlab.kermit.Kermit
|
||||||
import com.shabinder.common.database.createDatabase
|
import com.shabinder.common.database.SpotiFlyerDatabase
|
||||||
import com.shabinder.common.di.utils.removeIllegalChars
|
import com.shabinder.common.di.utils.removeIllegalChars
|
||||||
import com.shabinder.common.models.DownloadResult
|
import com.shabinder.common.models.DownloadResult
|
||||||
import com.shabinder.common.models.TrackDetails
|
import com.shabinder.common.models.TrackDetails
|
||||||
import com.shabinder.database.Database
|
import com.shabinder.database.Database
|
||||||
import com.shabinder.downloader.exceptions.YoutubeException
|
|
||||||
import io.ktor.client.*
|
|
||||||
import io.ktor.client.features.*
|
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
import io.ktor.client.statement.HttpStatement
|
import io.ktor.client.statement.HttpStatement
|
||||||
import io.ktor.http.contentLength
|
import io.ktor.http.contentLength
|
||||||
import io.ktor.http.isSuccess
|
import io.ktor.http.isSuccess
|
||||||
import io.ktor.utils.io.errors.*
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
expect class Dir (
|
expect class Dir (
|
||||||
logger: Kermit,
|
logger: Kermit,
|
||||||
database: Database? = createDatabase(),
|
spotiFlyerDatabase: SpotiFlyerDatabase,
|
||||||
) {
|
) {
|
||||||
val db: Database?
|
val db: Database?
|
||||||
fun isPresent(path: String): Boolean
|
fun isPresent(path: String): Boolean
|
||||||
|
@ -16,37 +16,19 @@
|
|||||||
|
|
||||||
package com.shabinder.common.di
|
package com.shabinder.common.di
|
||||||
|
|
||||||
import com.shabinder.common.models.AllPlatforms
|
|
||||||
import com.shabinder.common.models.TrackDetails
|
import com.shabinder.common.models.TrackDetails
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
expect fun openPlatform(packageID: String, platformLink: String)
|
|
||||||
|
|
||||||
expect fun shareApp()
|
|
||||||
|
|
||||||
expect fun giveDonation()
|
|
||||||
|
|
||||||
expect val dispatcherIO: CoroutineDispatcher
|
|
||||||
|
|
||||||
expect val isInternetAvailable: Boolean
|
|
||||||
|
|
||||||
expect val currentPlatform: AllPlatforms
|
|
||||||
|
|
||||||
expect suspend fun downloadTracks(
|
expect suspend fun downloadTracks(
|
||||||
list: List<TrackDetails>,
|
list: List<TrackDetails>,
|
||||||
fetcher: FetchPlatformQueryResult,
|
fetcher: FetchPlatformQueryResult,
|
||||||
dir: Dir
|
dir: Dir
|
||||||
)
|
)
|
||||||
|
|
||||||
expect fun queryActiveTracks()
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Refactor This
|
|
||||||
* */
|
|
||||||
suspend fun isInternetAccessible(): Boolean {
|
suspend fun isInternetAccessible(): Boolean {
|
||||||
return withContext(dispatcherIO) {
|
return withContext(methods.dispatcherIO) {
|
||||||
try {
|
try {
|
||||||
ktorHttpClient.head<String>("http://google.com")
|
ktorHttpClient.head<String>("http://google.com")
|
||||||
true
|
true
|
||||||
|
@ -26,12 +26,12 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class FetchPlatformQueryResult(
|
class FetchPlatformQueryResult(
|
||||||
private val gaanaProvider: GaanaProvider,
|
val gaanaProvider: GaanaProvider,
|
||||||
private val spotifyProvider: SpotifyProvider,
|
val spotifyProvider: SpotifyProvider,
|
||||||
val youtubeProvider: YoutubeProvider,
|
val youtubeProvider: YoutubeProvider,
|
||||||
val youtubeMusic: YoutubeMusic,
|
val youtubeMusic: YoutubeMusic,
|
||||||
val youtubeMp3: YoutubeMp3,
|
val youtubeMp3: YoutubeMp3,
|
||||||
private val dir: Dir
|
val dir: Dir
|
||||||
) {
|
) {
|
||||||
private val db: DownloadRecordDatabaseQueries?
|
private val db: DownloadRecordDatabaseQueries?
|
||||||
get() = dir.db?.downloadRecordDatabaseQueries
|
get() = dir.db?.downloadRecordDatabaseQueries
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.shabinder.common.di.gaana
|
package com.shabinder.common.di.gaana
|
||||||
|
|
||||||
import com.shabinder.common.di.currentPlatform
|
|
||||||
import com.shabinder.common.models.AllPlatforms
|
import com.shabinder.common.models.AllPlatforms
|
||||||
import com.shabinder.common.models.corsProxy
|
import com.shabinder.common.models.corsProxy
|
||||||
import com.shabinder.common.models.gaana.GaanaAlbum
|
import com.shabinder.common.models.gaana.GaanaAlbum
|
||||||
@ -24,10 +23,11 @@ import com.shabinder.common.models.gaana.GaanaArtistDetails
|
|||||||
import com.shabinder.common.models.gaana.GaanaArtistTracks
|
import com.shabinder.common.models.gaana.GaanaArtistTracks
|
||||||
import com.shabinder.common.models.gaana.GaanaPlaylist
|
import com.shabinder.common.models.gaana.GaanaPlaylist
|
||||||
import com.shabinder.common.models.gaana.GaanaSong
|
import com.shabinder.common.models.gaana.GaanaSong
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
|
|
||||||
val corsApi get() = if (currentPlatform is AllPlatforms.Js) {
|
val corsApi get() = if (methods.currentPlatform is AllPlatforms.Js) {
|
||||||
corsProxy.url
|
corsProxy.url
|
||||||
} // "https://spotiflyer-cors.azurewebsites.net/" //"https://spotiflyer-cors.herokuapp.com/"//"https://cors.bridged.cc/"
|
} // "https://spotiflyer-cors.azurewebsites.net/" //"https://spotiflyer-cors.herokuapp.com/"//"https://cors.bridged.cc/"
|
||||||
else ""
|
else ""
|
||||||
|
@ -19,7 +19,6 @@ package com.shabinder.common.di.providers
|
|||||||
import co.touchlab.kermit.Kermit
|
import co.touchlab.kermit.Kermit
|
||||||
import com.shabinder.common.di.Dir
|
import com.shabinder.common.di.Dir
|
||||||
import com.shabinder.common.di.TokenStore
|
import com.shabinder.common.di.TokenStore
|
||||||
import com.shabinder.common.di.currentPlatform
|
|
||||||
import com.shabinder.common.di.finalOutputDir
|
import com.shabinder.common.di.finalOutputDir
|
||||||
import com.shabinder.common.di.kotlinxSerializer
|
import com.shabinder.common.di.kotlinxSerializer
|
||||||
import com.shabinder.common.di.spotify.SpotifyRequests
|
import com.shabinder.common.di.spotify.SpotifyRequests
|
||||||
@ -27,6 +26,7 @@ import com.shabinder.common.di.spotify.authenticateSpotify
|
|||||||
import com.shabinder.common.models.AllPlatforms
|
import com.shabinder.common.models.AllPlatforms
|
||||||
import com.shabinder.common.models.PlatformQueryResult
|
import com.shabinder.common.models.PlatformQueryResult
|
||||||
import com.shabinder.common.models.TrackDetails
|
import com.shabinder.common.models.TrackDetails
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
import com.shabinder.common.models.spotify.Album
|
import com.shabinder.common.models.spotify.Album
|
||||||
import com.shabinder.common.models.spotify.Image
|
import com.shabinder.common.models.spotify.Image
|
||||||
import com.shabinder.common.models.spotify.Source
|
import com.shabinder.common.models.spotify.Source
|
||||||
@ -45,14 +45,14 @@ class SpotifyProvider(
|
|||||||
private val dir: Dir,
|
private val dir: Dir,
|
||||||
) : SpotifyRequests {
|
) : SpotifyRequests {
|
||||||
|
|
||||||
init {
|
/* init {
|
||||||
logger.d { "Creating Spotify Provider" }
|
logger.d { "Creating Spotify Provider" }
|
||||||
GlobalScope.launch(Dispatchers.Default) {
|
GlobalScope.launch(Dispatchers.Default) {
|
||||||
if (currentPlatform is AllPlatforms.Js) {
|
if (methods.currentPlatform is AllPlatforms.Js) {
|
||||||
authenticateSpotifyClient(override = true)
|
authenticateSpotifyClient(override = true)
|
||||||
} else authenticateSpotifyClient()
|
} else authenticateSpotifyClient()
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
override suspend fun authenticateSpotifyClient(override: Boolean): HttpClient? {
|
override suspend fun authenticateSpotifyClient(override: Boolean): HttpClient? {
|
||||||
val token = if (override) authenticateSpotify() else tokenStore.getToken()
|
val token = if (override) authenticateSpotify() else tokenStore.getToken()
|
||||||
|
@ -18,9 +18,9 @@ package com.shabinder.common.di.providers
|
|||||||
|
|
||||||
import co.touchlab.kermit.Kermit
|
import co.touchlab.kermit.Kermit
|
||||||
import com.shabinder.common.di.Dir
|
import com.shabinder.common.di.Dir
|
||||||
import com.shabinder.common.di.currentPlatform
|
|
||||||
import com.shabinder.common.di.youtubeMp3.Yt1sMp3
|
import com.shabinder.common.di.youtubeMp3.Yt1sMp3
|
||||||
import com.shabinder.common.models.AllPlatforms
|
import com.shabinder.common.models.AllPlatforms
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
|
|
||||||
class YoutubeMp3(
|
class YoutubeMp3(
|
||||||
@ -31,7 +31,7 @@ class YoutubeMp3(
|
|||||||
suspend fun getMp3DownloadLink(videoID: String): String? = try {
|
suspend fun getMp3DownloadLink(videoID: String): String? = try {
|
||||||
getLinkFromYt1sMp3(videoID)?.let {
|
getLinkFromYt1sMp3(videoID)?.let {
|
||||||
logger.i { "Download Link: $it" }
|
logger.i { "Download Link: $it" }
|
||||||
if (currentPlatform is AllPlatforms.Js/* && corsProxy !is CorsProxy.PublicProxyWithExtension*/)
|
if (methods.currentPlatform is AllPlatforms.Js/* && corsProxy !is CorsProxy.PublicProxyWithExtension*/)
|
||||||
"https://kind-grasshopper-73.telebit.io/cors/$it"
|
"https://kind-grasshopper-73.telebit.io/cors/$it"
|
||||||
// "https://spotiflyer.azurewebsites.net/$it" // Data OUT Limit issue
|
// "https://spotiflyer.azurewebsites.net/$it" // Data OUT Limit issue
|
||||||
else it
|
else it
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
package com.shabinder.common.di.spotify
|
package com.shabinder.common.di.spotify
|
||||||
|
|
||||||
import com.shabinder.common.di.isInternetAvailable
|
|
||||||
import com.shabinder.common.di.kotlinxSerializer
|
import com.shabinder.common.di.kotlinxSerializer
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
import com.shabinder.common.models.spotify.TokenData
|
import com.shabinder.common.models.spotify.TokenData
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.features.auth.Auth
|
import io.ktor.client.features.auth.Auth
|
||||||
@ -29,7 +29,7 @@ import io.ktor.http.Parameters
|
|||||||
|
|
||||||
suspend fun authenticateSpotify(): TokenData? {
|
suspend fun authenticateSpotify(): TokenData? {
|
||||||
return try {
|
return try {
|
||||||
if (isInternetAvailable) spotifyAuthClient.post("https://accounts.spotify.com/api/token") {
|
if (methods.isInternetAvailable) spotifyAuthClient.post("https://accounts.spotify.com/api/token") {
|
||||||
body = FormDataContent(Parameters.build { append("grant_type", "client_credentials") })
|
body = FormDataContent(Parameters.build { append("grant_type", "client_credentials") })
|
||||||
} else null
|
} else null
|
||||||
}catch (e:Exception) {
|
}catch (e:Exception) {
|
||||||
|
@ -21,7 +21,7 @@ package com.shabinder.common.di.utils
|
|||||||
// implementation("org.jetbrains.kotlinx:atomicfu:0.14.4")
|
// implementation("org.jetbrains.kotlinx:atomicfu:0.14.4")
|
||||||
// Gist: https://gist.github.com/fluidsonic/ba32de21c156bbe8424c8d5fc20dcd8e
|
// Gist: https://gist.github.com/fluidsonic/ba32de21c156bbe8424c8d5fc20dcd8e
|
||||||
|
|
||||||
import com.shabinder.common.di.dispatcherIO
|
import com.shabinder.common.models.methods
|
||||||
import io.ktor.utils.io.core.Closeable
|
import io.ktor.utils.io.core.Closeable
|
||||||
import kotlinx.atomicfu.atomic
|
import kotlinx.atomicfu.atomic
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
@ -37,7 +37,7 @@ import kotlinx.coroutines.withContext
|
|||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
class ParallelExecutor(
|
class ParallelExecutor(
|
||||||
parentContext: CoroutineContext = dispatcherIO,
|
parentContext: CoroutineContext = methods.dispatcherIO,
|
||||||
) : Closeable {
|
) : Closeable {
|
||||||
|
|
||||||
private val concurrentOperationLimit = atomic(4)
|
private val concurrentOperationLimit = atomic(4)
|
||||||
|
@ -17,43 +17,13 @@
|
|||||||
package com.shabinder.common.di
|
package com.shabinder.common.di
|
||||||
|
|
||||||
import com.shabinder.common.di.utils.ParallelExecutor
|
import com.shabinder.common.di.utils.ParallelExecutor
|
||||||
import com.shabinder.common.models.AllPlatforms
|
|
||||||
import com.shabinder.common.models.DownloadResult
|
import com.shabinder.common.models.DownloadResult
|
||||||
import com.shabinder.common.models.DownloadStatus
|
import com.shabinder.common.models.DownloadStatus
|
||||||
import com.shabinder.common.models.TrackDetails
|
import com.shabinder.common.models.TrackDetails
|
||||||
import com.shabinder.downloader.YoutubeDownloader
|
import com.shabinder.downloader.YoutubeDownloader
|
||||||
import io.ktor.client.request.head
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
actual fun openPlatform(packageID: String, platformLink: String) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
actual val currentPlatform: AllPlatforms = AllPlatforms.Jvm
|
|
||||||
|
|
||||||
actual val dispatcherIO = Dispatchers.IO
|
|
||||||
|
|
||||||
actual fun shareApp() {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun giveDonation() {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun queryActiveTracks() {}
|
|
||||||
|
|
||||||
actual val isInternetAvailable: Boolean
|
|
||||||
get() {
|
|
||||||
var result = false
|
|
||||||
val job = GlobalScope.launch { result = isInternetAccessible() }
|
|
||||||
while (job.isActive) {}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
val DownloadProgressFlow: MutableSharedFlow<HashMap<String, DownloadStatus>> = MutableSharedFlow(1)
|
val DownloadProgressFlow: MutableSharedFlow<HashMap<String, DownloadStatus>> = MutableSharedFlow(1)
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import androidx.compose.ui.graphics.ImageBitmap
|
|||||||
import androidx.compose.ui.graphics.asImageBitmap
|
import androidx.compose.ui.graphics.asImageBitmap
|
||||||
import co.touchlab.kermit.Kermit
|
import co.touchlab.kermit.Kermit
|
||||||
import com.mpatric.mp3agic.Mp3File
|
import com.mpatric.mp3agic.Mp3File
|
||||||
|
import com.shabinder.common.database.SpotiFlyerDatabase
|
||||||
import com.shabinder.common.models.TrackDetails
|
import com.shabinder.common.models.TrackDetails
|
||||||
import com.shabinder.database.Database
|
import com.shabinder.database.Database
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -38,7 +39,7 @@ import javax.imageio.ImageIO
|
|||||||
|
|
||||||
actual class Dir actual constructor(
|
actual class Dir actual constructor(
|
||||||
private val logger: Kermit,
|
private val logger: Kermit,
|
||||||
private val database: Database?,
|
private val spotiFlyerDatabase: SpotiFlyerDatabase,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -137,9 +138,9 @@ actual class Dir actual constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual val db: Database?
|
actual val db: Database? get() = spotiFlyerDatabase.instance
|
||||||
get() = database
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun BufferedImage.toImageBitmap() = Image.makeFromEncoded(
|
fun BufferedImage.toImageBitmap() = Image.makeFromEncoded(
|
||||||
toByteArray(this)
|
toByteArray(this)
|
||||||
).asImageBitmap()
|
).asImageBitmap()
|
||||||
|
@ -12,7 +12,7 @@ import cocoapods.TagLibIOS.TLAudio
|
|||||||
|
|
||||||
actual class Dir actual constructor(
|
actual class Dir actual constructor(
|
||||||
private val logger: Kermit,
|
private val logger: Kermit,
|
||||||
private val database: Database?
|
private val spotiFlyerDatabase: SpotiFlyerDatabase,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -142,5 +142,5 @@ actual class Dir actual constructor(
|
|||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
actual val db: Database? = database
|
actual val db: Database? = spotiFlyerDatabase.instance
|
||||||
}
|
}
|
@ -16,55 +16,14 @@
|
|||||||
|
|
||||||
package com.shabinder.common.di
|
package com.shabinder.common.di
|
||||||
|
|
||||||
import com.shabinder.common.models.AllPlatforms
|
|
||||||
import com.shabinder.common.models.DownloadResult
|
import com.shabinder.common.models.DownloadResult
|
||||||
import com.shabinder.common.models.DownloadStatus
|
import com.shabinder.common.models.DownloadStatus
|
||||||
import com.shabinder.common.models.TrackDetails
|
import com.shabinder.common.models.TrackDetails
|
||||||
import io.ktor.client.request.head
|
import com.shabinder.common.models.methods
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
actual val currentPlatform: AllPlatforms = AllPlatforms.Js
|
|
||||||
|
|
||||||
actual fun openPlatform(packageID: String, platformLink: String) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun shareApp() {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun giveDonation() {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
actual fun queryActiveTracks() {}
|
|
||||||
|
|
||||||
actual val dispatcherIO: CoroutineDispatcher = Dispatchers.Default
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Refactor This
|
|
||||||
* */
|
|
||||||
private suspend fun isInternetAvailable(): Boolean {
|
|
||||||
return withContext(dispatcherIO) {
|
|
||||||
try {
|
|
||||||
ktorHttpClient.head<String>("http://google.com")
|
|
||||||
true
|
|
||||||
} catch (e: Exception) {
|
|
||||||
println(e.message)
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
actual val isInternetAvailable: Boolean
|
|
||||||
get() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
val DownloadProgressFlow: MutableSharedFlow<HashMap<String, DownloadStatus>> = MutableSharedFlow(1)
|
val DownloadProgressFlow: MutableSharedFlow<HashMap<String, DownloadStatus>> = MutableSharedFlow(1)
|
||||||
// Error:https://github.com/Kotlin/kotlinx.atomicfu/issues/182
|
// Error:https://github.com/Kotlin/kotlinx.atomicfu/issues/182
|
||||||
// val DownloadScope = ParallelExecutor(Dispatchers.Default) //Download Pool of 4 parallel
|
// val DownloadScope = ParallelExecutor(Dispatchers.Default) //Download Pool of 4 parallel
|
||||||
@ -76,7 +35,7 @@ actual suspend fun downloadTracks(
|
|||||||
dir: Dir
|
dir: Dir
|
||||||
) {
|
) {
|
||||||
list.forEach {
|
list.forEach {
|
||||||
withContext(dispatcherIO) {
|
withContext(methods.dispatcherIO) {
|
||||||
allTracksStatus[it.title] = DownloadStatus.Queued
|
allTracksStatus[it.title] = DownloadStatus.Queued
|
||||||
if (!it.videoID.isNullOrBlank()) { // Video ID already known!
|
if (!it.videoID.isNullOrBlank()) { // Video ID already known!
|
||||||
downloadTrack(it.videoID!!, it, fetcher, dir)
|
downloadTrack(it.videoID!!, it, fetcher, dir)
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package com.shabinder.common.di
|
package com.shabinder.common.di
|
||||||
|
|
||||||
import co.touchlab.kermit.Kermit
|
import co.touchlab.kermit.Kermit
|
||||||
|
import com.shabinder.common.database.SpotiFlyerDatabase
|
||||||
import com.shabinder.common.di.gaana.corsApi
|
import com.shabinder.common.di.gaana.corsApi
|
||||||
import com.shabinder.common.di.utils.removeIllegalChars
|
import com.shabinder.common.di.utils.removeIllegalChars
|
||||||
import com.shabinder.common.models.DownloadResult
|
import com.shabinder.common.models.DownloadResult
|
||||||
@ -32,7 +33,7 @@ import org.w3c.dom.ImageBitmap
|
|||||||
|
|
||||||
actual class Dir actual constructor(
|
actual class Dir actual constructor(
|
||||||
private val logger: Kermit,
|
private val logger: Kermit,
|
||||||
private val database: Database?,
|
private val spotiFlyerDatabase: SpotiFlyerDatabase,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/*init {
|
/*init {
|
||||||
@ -112,8 +113,7 @@ actual class Dir actual constructor(
|
|||||||
|
|
||||||
private suspend fun freshImage(url: String): ImageBitmap? = null
|
private suspend fun freshImage(url: String): ImageBitmap? = null
|
||||||
|
|
||||||
actual val db: Database?
|
actual val db: Database? get() = spotiFlyerDatabase.instance
|
||||||
get() = database
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ByteArray.toArrayBuffer(): ArrayBuffer {
|
fun ByteArray.toArrayBuffer(): ArrayBuffer {
|
||||||
|
@ -64,7 +64,6 @@ interface SpotiFlyerList {
|
|||||||
val dir: Dir
|
val dir: Dir
|
||||||
val link: String
|
val link: String
|
||||||
val listOutput: Consumer<Output>
|
val listOutput: Consumer<Output>
|
||||||
val showPopUpMessage: (String) -> Unit
|
|
||||||
val downloadProgressFlow: MutableSharedFlow<HashMap<String, DownloadStatus>>
|
val downloadProgressFlow: MutableSharedFlow<HashMap<String, DownloadStatus>>
|
||||||
}
|
}
|
||||||
sealed class Output {
|
sealed class Output {
|
||||||
|
@ -40,8 +40,7 @@ internal class SpotiFlyerListImpl(
|
|||||||
storeFactory = storeFactory,
|
storeFactory = storeFactory,
|
||||||
fetchQuery = fetchQuery,
|
fetchQuery = fetchQuery,
|
||||||
downloadProgressFlow = downloadProgressFlow,
|
downloadProgressFlow = downloadProgressFlow,
|
||||||
link = link,
|
link = link
|
||||||
showPopUpMessage = showPopUpMessage
|
|
||||||
).provide()
|
).provide()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,12 +25,12 @@ import com.shabinder.common.database.getLogger
|
|||||||
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.downloadTracks
|
import com.shabinder.common.di.downloadTracks
|
||||||
import com.shabinder.common.di.queryActiveTracks
|
|
||||||
import com.shabinder.common.list.SpotiFlyerList.State
|
import com.shabinder.common.list.SpotiFlyerList.State
|
||||||
import com.shabinder.common.list.store.SpotiFlyerListStore.Intent
|
import com.shabinder.common.list.store.SpotiFlyerListStore.Intent
|
||||||
import com.shabinder.common.models.DownloadStatus
|
import com.shabinder.common.models.DownloadStatus
|
||||||
import com.shabinder.common.models.PlatformQueryResult
|
import com.shabinder.common.models.PlatformQueryResult
|
||||||
import com.shabinder.common.models.TrackDetails
|
import com.shabinder.common.models.TrackDetails
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
|
||||||
@ -39,7 +39,6 @@ internal class SpotiFlyerListStoreProvider(
|
|||||||
private val storeFactory: StoreFactory,
|
private val storeFactory: StoreFactory,
|
||||||
private val fetchQuery: FetchPlatformQueryResult,
|
private val fetchQuery: FetchPlatformQueryResult,
|
||||||
private val link: String,
|
private val link: String,
|
||||||
private val showPopUpMessage: (String) -> Unit,
|
|
||||||
private val downloadProgressFlow: MutableSharedFlow<HashMap<String, DownloadStatus>>
|
private val downloadProgressFlow: MutableSharedFlow<HashMap<String, DownloadStatus>>
|
||||||
) {
|
) {
|
||||||
val logger = getLogger()
|
val logger = getLogger()
|
||||||
@ -93,7 +92,7 @@ internal class SpotiFlyerListStoreProvider(
|
|||||||
is Intent.StartDownloadAll -> {
|
is Intent.StartDownloadAll -> {
|
||||||
val finalList =
|
val finalList =
|
||||||
intent.trackList.filter { it.downloaded == DownloadStatus.NotDownloaded }
|
intent.trackList.filter { it.downloaded == DownloadStatus.NotDownloaded }
|
||||||
if (finalList.isNullOrEmpty()) showPopUpMessage("All Songs are Processed")
|
if (finalList.isNullOrEmpty()) methods.showPopUpMessage("All Songs are Processed")
|
||||||
else downloadTracks(finalList, fetchQuery, dir)
|
else downloadTracks(finalList, fetchQuery, dir)
|
||||||
|
|
||||||
val list = intent.trackList.map {
|
val list = intent.trackList.map {
|
||||||
@ -107,7 +106,7 @@ internal class SpotiFlyerListStoreProvider(
|
|||||||
downloadTracks(listOf(intent.track), fetchQuery, dir)
|
downloadTracks(listOf(intent.track), fetchQuery, dir)
|
||||||
dispatch(Result.UpdateTrackItem(intent.track.copy(downloaded = DownloadStatus.Queued)))
|
dispatch(Result.UpdateTrackItem(intent.track.copy(downloaded = DownloadStatus.Queued)))
|
||||||
}
|
}
|
||||||
is Intent.RefreshTracksStatuses -> queryActiveTracks()
|
is Intent.RefreshTracksStatuses -> methods.queryActiveTracks()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,6 @@ interface SpotiFlyerMain {
|
|||||||
val storeFactory: StoreFactory
|
val storeFactory: StoreFactory
|
||||||
val database: Database?
|
val database: Database?
|
||||||
val dir: Dir
|
val dir: Dir
|
||||||
val showPopUpMessage: (String) -> Unit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class Output {
|
sealed class Output {
|
||||||
|
@ -19,7 +19,6 @@ package com.shabinder.common.main.integration
|
|||||||
import com.arkivanov.decompose.ComponentContext
|
import com.arkivanov.decompose.ComponentContext
|
||||||
import com.arkivanov.mvikotlin.extensions.coroutines.states
|
import com.arkivanov.mvikotlin.extensions.coroutines.states
|
||||||
import com.shabinder.common.di.Picture
|
import com.shabinder.common.di.Picture
|
||||||
import com.shabinder.common.di.isInternetAvailable
|
|
||||||
import com.shabinder.common.main.SpotiFlyerMain
|
import com.shabinder.common.main.SpotiFlyerMain
|
||||||
import com.shabinder.common.main.SpotiFlyerMain.Dependencies
|
import com.shabinder.common.main.SpotiFlyerMain.Dependencies
|
||||||
import com.shabinder.common.main.SpotiFlyerMain.HomeCategory
|
import com.shabinder.common.main.SpotiFlyerMain.HomeCategory
|
||||||
@ -28,6 +27,7 @@ import com.shabinder.common.main.SpotiFlyerMain.State
|
|||||||
import com.shabinder.common.main.store.SpotiFlyerMainStore.Intent
|
import com.shabinder.common.main.store.SpotiFlyerMainStore.Intent
|
||||||
import com.shabinder.common.main.store.SpotiFlyerMainStoreProvider
|
import com.shabinder.common.main.store.SpotiFlyerMainStoreProvider
|
||||||
import com.shabinder.common.main.store.getStore
|
import com.shabinder.common.main.store.getStore
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
internal class SpotiFlyerMainImpl(
|
internal class SpotiFlyerMainImpl(
|
||||||
@ -39,16 +39,15 @@ internal class SpotiFlyerMainImpl(
|
|||||||
instanceKeeper.getStore {
|
instanceKeeper.getStore {
|
||||||
SpotiFlyerMainStoreProvider(
|
SpotiFlyerMainStoreProvider(
|
||||||
storeFactory = storeFactory,
|
storeFactory = storeFactory,
|
||||||
database = database,
|
database = database
|
||||||
showPopUpMessage = showPopUpMessage
|
|
||||||
).provide()
|
).provide()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val models: Flow<State> = store.states
|
override val models: Flow<State> = store.states
|
||||||
|
|
||||||
override fun onLinkSearch(link: String) {
|
override fun onLinkSearch(link: String) {
|
||||||
if (isInternetAvailable) mainOutput.callback(Output.Search(link = link))
|
if (methods.isInternetAvailable) mainOutput.callback(Output.Search(link = link))
|
||||||
else showPopUpMessage("Check Network Connection Please")
|
else methods.showPopUpMessage("Check Network Connection Please")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onInputLinkChanged(link: String) {
|
override fun onInputLinkChanged(link: String) {
|
||||||
|
@ -21,13 +21,11 @@ import com.arkivanov.mvikotlin.core.store.SimpleBootstrapper
|
|||||||
import com.arkivanov.mvikotlin.core.store.Store
|
import com.arkivanov.mvikotlin.core.store.Store
|
||||||
import com.arkivanov.mvikotlin.core.store.StoreFactory
|
import com.arkivanov.mvikotlin.core.store.StoreFactory
|
||||||
import com.arkivanov.mvikotlin.extensions.coroutines.SuspendExecutor
|
import com.arkivanov.mvikotlin.extensions.coroutines.SuspendExecutor
|
||||||
import com.shabinder.common.di.giveDonation
|
|
||||||
import com.shabinder.common.di.openPlatform
|
|
||||||
import com.shabinder.common.di.shareApp
|
|
||||||
import com.shabinder.common.main.SpotiFlyerMain
|
import com.shabinder.common.main.SpotiFlyerMain
|
||||||
import com.shabinder.common.main.SpotiFlyerMain.State
|
import com.shabinder.common.main.SpotiFlyerMain.State
|
||||||
import com.shabinder.common.main.store.SpotiFlyerMainStore.Intent
|
import com.shabinder.common.main.store.SpotiFlyerMainStore.Intent
|
||||||
import com.shabinder.common.models.DownloadRecord
|
import com.shabinder.common.models.DownloadRecord
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
import com.shabinder.database.Database
|
import com.shabinder.database.Database
|
||||||
import com.squareup.sqldelight.runtime.coroutines.asFlow
|
import com.squareup.sqldelight.runtime.coroutines.asFlow
|
||||||
import com.squareup.sqldelight.runtime.coroutines.mapToList
|
import com.squareup.sqldelight.runtime.coroutines.mapToList
|
||||||
@ -38,7 +36,6 @@ import kotlinx.coroutines.flow.map
|
|||||||
|
|
||||||
internal class SpotiFlyerMainStoreProvider(
|
internal class SpotiFlyerMainStoreProvider(
|
||||||
private val storeFactory: StoreFactory,
|
private val storeFactory: StoreFactory,
|
||||||
private val showPopUpMessage: (String) -> Unit,
|
|
||||||
private val database: Database?
|
private val database: Database?
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@ -81,9 +78,9 @@ internal class SpotiFlyerMainStoreProvider(
|
|||||||
|
|
||||||
override suspend fun executeIntent(intent: Intent, getState: () -> State) {
|
override suspend fun executeIntent(intent: Intent, getState: () -> State) {
|
||||||
when (intent) {
|
when (intent) {
|
||||||
is Intent.OpenPlatform -> openPlatform(intent.platformID, intent.platformLink)
|
is Intent.OpenPlatform -> methods.openPlatform(intent.platformID, intent.platformLink)
|
||||||
is Intent.GiveDonation -> giveDonation()
|
is Intent.GiveDonation -> methods.giveDonation()
|
||||||
is Intent.ShareApp -> shareApp()
|
is Intent.ShareApp -> methods.shareApp()
|
||||||
is Intent.SetLink -> dispatch(Result.LinkChanged(link = intent.link))
|
is Intent.SetLink -> dispatch(Result.LinkChanged(link = intent.link))
|
||||||
is Intent.SelectCategory -> dispatch(Result.CategoryChanged(intent.category))
|
is Intent.SelectCategory -> dispatch(Result.CategoryChanged(intent.category))
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import com.shabinder.common.di.Dir
|
|||||||
import com.shabinder.common.di.FetchPlatformQueryResult
|
import com.shabinder.common.di.FetchPlatformQueryResult
|
||||||
import com.shabinder.common.list.SpotiFlyerList
|
import com.shabinder.common.list.SpotiFlyerList
|
||||||
import com.shabinder.common.main.SpotiFlyerMain
|
import com.shabinder.common.main.SpotiFlyerMain
|
||||||
|
import com.shabinder.common.models.Actions
|
||||||
import com.shabinder.common.models.DownloadStatus
|
import com.shabinder.common.models.DownloadStatus
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot.Dependencies
|
import com.shabinder.common.root.SpotiFlyerRoot.Dependencies
|
||||||
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
||||||
@ -47,9 +48,8 @@ interface SpotiFlyerRoot {
|
|||||||
val database: Database?
|
val database: Database?
|
||||||
val fetchPlatformQueryResult: FetchPlatformQueryResult
|
val fetchPlatformQueryResult: FetchPlatformQueryResult
|
||||||
val directories: Dir
|
val directories: Dir
|
||||||
val showPopUpMessage: (String) -> Unit
|
|
||||||
val downloadProgressReport: MutableSharedFlow<HashMap<String, DownloadStatus>>
|
val downloadProgressReport: MutableSharedFlow<HashMap<String, DownloadStatus>>
|
||||||
val setDownloadDirectoryAction:()->Unit
|
val actions:Actions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,16 +28,31 @@ import com.arkivanov.decompose.value.Value
|
|||||||
import com.shabinder.common.di.Dir
|
import com.shabinder.common.di.Dir
|
||||||
import com.shabinder.common.list.SpotiFlyerList
|
import com.shabinder.common.list.SpotiFlyerList
|
||||||
import com.shabinder.common.main.SpotiFlyerMain
|
import com.shabinder.common.main.SpotiFlyerMain
|
||||||
|
import com.shabinder.common.models.Actions
|
||||||
|
import com.shabinder.common.models.AllPlatforms
|
||||||
import com.shabinder.common.models.Consumer
|
import com.shabinder.common.models.Consumer
|
||||||
|
import com.shabinder.common.models.methods
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot
|
import com.shabinder.common.root.SpotiFlyerRoot
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot.Child
|
import com.shabinder.common.root.SpotiFlyerRoot.Child
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot.Dependencies
|
import com.shabinder.common.root.SpotiFlyerRoot.Dependencies
|
||||||
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
internal class SpotiFlyerRootImpl(
|
internal class SpotiFlyerRootImpl(
|
||||||
componentContext: ComponentContext,
|
componentContext: ComponentContext,
|
||||||
dependencies: Dependencies,
|
dependencies: Dependencies,
|
||||||
) : SpotiFlyerRoot, ComponentContext by componentContext, Dependencies by dependencies {
|
) : SpotiFlyerRoot, ComponentContext by componentContext, Dependencies by dependencies, Actions by dependencies.actions {
|
||||||
|
|
||||||
|
init {
|
||||||
|
methods = actions
|
||||||
|
GlobalScope.launch {
|
||||||
|
/*Authenticate Spotify Client*/
|
||||||
|
if (methods.currentPlatform is AllPlatforms.Js) {
|
||||||
|
fetchPlatformQueryResult.spotifyProvider.authenticateSpotifyClient(override = true)
|
||||||
|
} else fetchPlatformQueryResult.spotifyProvider.authenticateSpotifyClient()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val router =
|
private val router =
|
||||||
router<Configuration, Child>(
|
router<Configuration, Child>(
|
||||||
|
@ -38,6 +38,7 @@ kotlin {
|
|||||||
implementation(project(":common:database"))
|
implementation(project(":common:database"))
|
||||||
implementation(project(":common:dependency-injection"))
|
implementation(project(":common:dependency-injection"))
|
||||||
implementation(project(":common:compose"))
|
implementation(project(":common:compose"))
|
||||||
|
implementation(project(":common:data-models"))
|
||||||
implementation(project(":common:root"))
|
implementation(project(":common:root"))
|
||||||
implementation(Decompose.decompose)
|
implementation(Decompose.decompose)
|
||||||
implementation(Decompose.extensionsCompose)
|
implementation(Decompose.extensionsCompose)
|
||||||
|
@ -29,14 +29,21 @@ import com.shabinder.common.di.Dir
|
|||||||
import com.shabinder.common.di.DownloadProgressFlow
|
import com.shabinder.common.di.DownloadProgressFlow
|
||||||
import com.shabinder.common.di.FetchPlatformQueryResult
|
import com.shabinder.common.di.FetchPlatformQueryResult
|
||||||
import com.shabinder.common.di.initKoin
|
import com.shabinder.common.di.initKoin
|
||||||
|
import com.shabinder.common.di.isInternetAccessible
|
||||||
|
import com.shabinder.common.models.Actions
|
||||||
|
import com.shabinder.common.models.AllPlatforms
|
||||||
|
import com.shabinder.common.models.PlatformActions
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot
|
import com.shabinder.common.root.SpotiFlyerRoot
|
||||||
import com.shabinder.common.uikit.SpotiFlyerColors
|
import com.shabinder.common.uikit.SpotiFlyerColors
|
||||||
import com.shabinder.common.uikit.SpotiFlyerRootContent
|
import com.shabinder.common.uikit.SpotiFlyerRootContent
|
||||||
import com.shabinder.common.uikit.SpotiFlyerShapes
|
import com.shabinder.common.uikit.SpotiFlyerShapes
|
||||||
import com.shabinder.common.uikit.SpotiFlyerTypography
|
import com.shabinder.common.uikit.SpotiFlyerTypography
|
||||||
import com.shabinder.common.uikit.colorOffWhite
|
import com.shabinder.common.uikit.colorOffWhite
|
||||||
|
import com.shabinder.common.uikit.showToast
|
||||||
import com.shabinder.database.Database
|
import com.shabinder.database.Database
|
||||||
import com.shabinder.common.uikit.showPopUpMessage as uikitShowPopUpMessage
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
private val koin = initKoin(enableNetworkLogs = true).koin
|
private val koin = initKoin(enableNetworkLogs = true).koin
|
||||||
|
|
||||||
@ -70,7 +77,33 @@ private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot =
|
|||||||
override val fetchPlatformQueryResult: FetchPlatformQueryResult = koin.get()
|
override val fetchPlatformQueryResult: FetchPlatformQueryResult = koin.get()
|
||||||
override val directories: Dir = koin.get()
|
override val directories: Dir = koin.get()
|
||||||
override val database: Database? = directories.db
|
override val database: Database? = directories.db
|
||||||
override val showPopUpMessage: (String) -> Unit = ::uikitShowPopUpMessage
|
|
||||||
override val downloadProgressReport = DownloadProgressFlow
|
override val downloadProgressReport = DownloadProgressFlow
|
||||||
|
override val actions = object: Actions {
|
||||||
|
override val platformActions = object : PlatformActions {}
|
||||||
|
|
||||||
|
override fun showPopUpMessage(string: String, long: Boolean) = showToast(string)
|
||||||
|
|
||||||
|
override fun setDownloadDirectoryAction() {}
|
||||||
|
|
||||||
|
override fun queryActiveTracks() {}
|
||||||
|
|
||||||
|
override fun giveDonation() {}
|
||||||
|
|
||||||
|
override fun shareApp() {}
|
||||||
|
|
||||||
|
override fun openPlatform(packageID: String, platformLink: String) {}
|
||||||
|
|
||||||
|
override val dispatcherIO = Dispatchers.IO
|
||||||
|
|
||||||
|
override val isInternetAvailable: Boolean
|
||||||
|
get() {
|
||||||
|
var result = false
|
||||||
|
val job = GlobalScope.launch { result = isInternetAccessible() }
|
||||||
|
while (job.isActive) {/*TODO Better Way*/}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override val currentPlatform = AllPlatforms.Jvm
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -22,9 +22,13 @@ import com.arkivanov.mvikotlin.core.store.StoreFactory
|
|||||||
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.shabinder.common.di.DownloadProgressFlow
|
import com.shabinder.common.di.DownloadProgressFlow
|
||||||
|
import com.shabinder.common.models.Actions
|
||||||
|
import com.shabinder.common.models.AllPlatforms
|
||||||
|
import com.shabinder.common.models.PlatformActions
|
||||||
import com.shabinder.common.root.SpotiFlyerRoot
|
import com.shabinder.common.root.SpotiFlyerRoot
|
||||||
import com.shabinder.database.Database
|
import com.shabinder.database.Database
|
||||||
import extras.renderableChild
|
import extras.renderableChild
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import react.RBuilder
|
import react.RBuilder
|
||||||
import react.RComponent
|
import react.RComponent
|
||||||
import react.RProps
|
import react.RProps
|
||||||
@ -50,14 +54,33 @@ class App(props: AppProps): RComponent<AppProps, RState>(props) {
|
|||||||
private val dependencies = props.dependencies
|
private val dependencies = props.dependencies
|
||||||
|
|
||||||
private val root = SpotiFlyerRoot(ctx,
|
private val root = SpotiFlyerRoot(ctx,
|
||||||
object : SpotiFlyerRoot.Dependencies{
|
object : SpotiFlyerRoot.Dependencies {
|
||||||
override val storeFactory: StoreFactory = LoggingStoreFactory(DefaultStoreFactory)
|
override val storeFactory: StoreFactory = LoggingStoreFactory(DefaultStoreFactory)
|
||||||
override val fetchPlatformQueryResult = dependencies.fetchPlatformQueryResult
|
override val fetchPlatformQueryResult = dependencies.fetchPlatformQueryResult
|
||||||
override val directories = dependencies.directories
|
override val directories = dependencies.directories
|
||||||
override val database: Database? = directories.db
|
override val database: Database? = directories.db
|
||||||
override val showPopUpMessage: (String) -> Unit = {}//TODO
|
|
||||||
override val downloadProgressReport = DownloadProgressFlow
|
override val downloadProgressReport = DownloadProgressFlow
|
||||||
|
override val actions = object : Actions {
|
||||||
|
override val platformActions = object : PlatformActions {}
|
||||||
|
|
||||||
|
override fun showPopUpMessage(string: String, long: Boolean) {
|
||||||
|
/*TODO("Not yet implemented")*/
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setDownloadDirectoryAction() {}
|
||||||
|
|
||||||
|
override fun queryActiveTracks() {}
|
||||||
|
|
||||||
|
override fun giveDonation() {}
|
||||||
|
|
||||||
|
override fun shareApp() {}
|
||||||
|
|
||||||
|
override fun openPlatform(packageID: String, platformLink: String) {}
|
||||||
|
|
||||||
|
override val dispatcherIO = Dispatchers.Default
|
||||||
|
override val isInternetAvailable: Boolean = true
|
||||||
|
override val currentPlatform = AllPlatforms.Js
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user