mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-12-22 20:57:54 +01:00
Network/Permissions Dialogs Anim.
This commit is contained in:
parent
bf6463a3e1
commit
65427793fc
2
.gitignore
vendored
2
.gitignore
vendored
@ -117,3 +117,5 @@
|
||||
/common/list/build/
|
||||
/common/main/build/
|
||||
/common/root/build/
|
||||
/android/release/
|
||||
/android/google-services.json
|
||||
|
@ -13,6 +13,8 @@ import android.os.PowerManager
|
||||
import android.util.Log
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.*
|
||||
@ -53,6 +55,7 @@ import org.koin.android.ext.android.inject
|
||||
|
||||
const val disableDozeCode = 1223
|
||||
|
||||
@ExperimentalAnimationApi
|
||||
class MainActivity : ComponentActivity(), PaymentResultListener {
|
||||
|
||||
private val database: Database by inject()
|
||||
@ -76,30 +79,22 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
||||
Surface(contentColor = colorOffWhite) {
|
||||
|
||||
var statusBarHeight by remember { mutableStateOf(27.dp) }
|
||||
var askForPermission by remember { mutableStateOf(false) }
|
||||
permissionGranted = remember { mutableStateOf(true) }
|
||||
val view = LocalView.current
|
||||
|
||||
LaunchedEffect(view){
|
||||
permissionGranted.value = (ContextCompat
|
||||
.checkSelfPermission(this@MainActivity,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
|
||||
&&
|
||||
ContextCompat.checkSelfPermission(this@MainActivity,
|
||||
Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) == PackageManager.PERMISSION_GRANTED)
|
||||
|
||||
permissionGranted.value = checkPermissions()
|
||||
view.setOnApplyWindowInsetsListener { _, insets ->
|
||||
statusBarHeight = insets.systemWindowInsetTop.dp
|
||||
insets
|
||||
}
|
||||
delay(2000)
|
||||
askForPermission = true
|
||||
}
|
||||
|
||||
if(askForPermission && !permissionGranted.value) permissionDialog()
|
||||
root = SpotiFlyerRootContent(rememberRootComponent(::spotiFlyerRoot),statusBarHeight)
|
||||
|
||||
|
||||
NetworkDialog()
|
||||
root = SpotiFlyerRootContent(rememberRootComponent(::spotiFlyerRoot),statusBarHeight)
|
||||
PermissionDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -112,6 +107,11 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
||||
Checkout.preload(applicationContext)
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
permissionGranted.value = checkPermissions()
|
||||
}
|
||||
|
||||
private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot =
|
||||
SpotiFlyerRoot(
|
||||
componentContext,
|
||||
@ -247,64 +247,65 @@ class MainActivity : ComponentActivity(), PaymentResultListener {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun permissionDialog(){
|
||||
AlertDialog(
|
||||
onDismissRequest = {},
|
||||
buttons = {
|
||||
TextButton({
|
||||
requestStoragePermission()
|
||||
disableDozeMode(disableDozeCode)
|
||||
permissionGranted.value = (ContextCompat
|
||||
.checkSelfPermission(this@MainActivity,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
|
||||
&&
|
||||
ContextCompat.checkSelfPermission(this@MainActivity,Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) == PackageManager.PERMISSION_GRANTED)
|
||||
},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,
|
||||
)
|
||||
}
|
||||
private fun PermissionDialog(){
|
||||
var askForPermission by remember { mutableStateOf(false) }
|
||||
LaunchedEffect(Unit){
|
||||
delay(2000)
|
||||
askForPermission = true
|
||||
}
|
||||
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)
|
||||
}
|
||||
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,
|
||||
)
|
||||
},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 {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.shabinder.spotiflyer.utils
|
||||
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.AlertDialog
|
||||
@ -14,13 +15,13 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.shabinder.common.di.isInternetAvailable
|
||||
import com.shabinder.common.di.isInternetAvailableState
|
||||
import com.shabinder.common.uikit.SpotiFlyerShapes
|
||||
import com.shabinder.common.uikit.SpotiFlyerTypography
|
||||
import com.shabinder.common.uikit.colorOffWhite
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
@ExperimentalAnimationApi
|
||||
@Composable
|
||||
fun NetworkDialog(
|
||||
networkAvailability: State<Boolean?> = isInternetAvailableState()
|
||||
@ -31,43 +32,41 @@ fun NetworkDialog(
|
||||
delay(2600)
|
||||
visible = true
|
||||
}
|
||||
if(networkAvailability.value == false){
|
||||
Crossfade(visible){
|
||||
if(it){
|
||||
AlertDialog(
|
||||
onDismissRequest = {},
|
||||
buttons = {
|
||||
/* TextButton({
|
||||
//Retry Network Connection
|
||||
},
|
||||
Modifier.padding(bottom = 16.dp,start = 16.dp,end = 16.dp).fillMaxWidth().background(Color(0xFFFC5C7D),shape = RoundedCornerShape(size = 8.dp)).padding(horizontal = 8.dp),
|
||||
){
|
||||
Text("Retry",color = Color.Black,fontSize = 18.sp,textAlign = TextAlign.Center)
|
||||
Icon(Icons.Rounded.SyncProblem,"Check Network Connection Again")
|
||||
}
|
||||
*/},
|
||||
title = { Text("No Internet Connection!",
|
||||
style = SpotiFlyerTypography.h5,
|
||||
textAlign = TextAlign.Center) },
|
||||
backgroundColor = Color.DarkGray,
|
||||
text = {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally,verticalArrangement = Arrangement.Center){
|
||||
Spacer(modifier = Modifier.padding(8.dp))
|
||||
Row(verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||
) {
|
||||
Image(Icons.Rounded.CloudOff,"No Internet.",Modifier.size(42.dp),colorFilter = ColorFilter.tint(
|
||||
colorOffWhite))
|
||||
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||
Text(
|
||||
text = "Please Check Your Network Connection.",
|
||||
style = SpotiFlyerTypography.subtitle1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility(networkAvailability.value == false && visible){
|
||||
AlertDialog(
|
||||
onDismissRequest = {},
|
||||
buttons = {
|
||||
/* TextButton({
|
||||
//Retry Network Connection
|
||||
},
|
||||
Modifier.padding(bottom = 16.dp,start = 16.dp,end = 16.dp).fillMaxWidth().background(Color(0xFFFC5C7D),shape = RoundedCornerShape(size = 8.dp)).padding(horizontal = 8.dp),
|
||||
){
|
||||
Text("Retry",color = Color.Black,fontSize = 18.sp,textAlign = TextAlign.Center)
|
||||
Icon(Icons.Rounded.SyncProblem,"Check Network Connection Again")
|
||||
}
|
||||
,shape = SpotiFlyerShapes.medium)
|
||||
*/},
|
||||
title = { Text("No Internet Connection!",
|
||||
style = SpotiFlyerTypography.h5,
|
||||
textAlign = TextAlign.Center) },
|
||||
backgroundColor = Color.DarkGray,
|
||||
text = {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally,verticalArrangement = Arrangement.Center){
|
||||
Spacer(modifier = Modifier.padding(8.dp))
|
||||
Row(verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth().padding(vertical = 6.dp)
|
||||
) {
|
||||
Image(Icons.Rounded.CloudOff,"No Internet.",Modifier.size(42.dp),colorFilter = ColorFilter.tint(
|
||||
colorOffWhite))
|
||||
Spacer(modifier = Modifier.padding(start = 16.dp))
|
||||
Text(
|
||||
text = "Please Check Your Network Connection.",
|
||||
style = SpotiFlyerTypography.subtitle1
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
,shape = SpotiFlyerShapes.medium
|
||||
)
|
||||
}
|
||||
}
|
@ -5,10 +5,12 @@ import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import android.provider.Settings
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.github.javiersantos.appupdater.AppUpdater
|
||||
import com.github.javiersantos.appupdater.enums.Display
|
||||
import com.github.javiersantos.appupdater.enums.UpdateFrom
|
||||
@ -23,6 +25,17 @@ fun Activity.checkIfLatestVersion() {
|
||||
start()
|
||||
}
|
||||
}
|
||||
|
||||
fun Activity.checkPermissions():Boolean{
|
||||
return (ContextCompat
|
||||
.checkSelfPermission(this,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
|
||||
&&
|
||||
ContextCompat.checkSelfPermission(this,
|
||||
Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) == PackageManager.PERMISSION_GRANTED)
|
||||
|
||||
}
|
||||
|
||||
@SuppressLint("BatteryLife", "ObsoleteSdkInt")
|
||||
fun Activity.disableDozeMode(requestCode:Int) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
|
@ -4,19 +4,13 @@ import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.contentColorFor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.github.kiulian.downloader.model.YoutubeVideo
|
||||
import com.github.kiulian.downloader.model.formats.Format
|
||||
import com.github.kiulian.downloader.model.quality.AudioQuality
|
||||
import com.razorpay.Checkout
|
||||
import com.shabinder.common.database.R
|
||||
import com.shabinder.common.database.activityContext
|
||||
import com.shabinder.common.database.appContext
|
||||
import com.shabinder.common.di.worker.ForegroundService
|
||||
@ -49,6 +43,9 @@ actual fun Toast(
|
||||
//We Have Android's Implementation of Toast so its just Empty
|
||||
}
|
||||
|
||||
actual val isInternetAvailable:Boolean
|
||||
get() = internetAvailability.value ?: true
|
||||
|
||||
actual fun showPopUpMessage(text: String){
|
||||
android.widget.Toast.makeText(appContext,text, android.widget.Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
@ -22,11 +22,11 @@ import javax.net.SocketFactory
|
||||
|
||||
const val TAG = "C-Manager"
|
||||
|
||||
val isInternetAvailable by lazy { ConnectionLiveData(appContext) }
|
||||
val internetAvailability by lazy { ConnectionLiveData(appContext) }
|
||||
|
||||
@Composable
|
||||
fun isInternetAvailableState(): State<Boolean?>{
|
||||
return isInternetAvailable.observeAsState()
|
||||
return internetAvailability.observeAsState()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,20 +44,6 @@ val kotlinxSerializer = KotlinxSerializer( Json {
|
||||
isLenient = true
|
||||
ignoreUnknownKeys = true
|
||||
})
|
||||
/*
|
||||
* Refactor This
|
||||
* */
|
||||
suspend fun isInternetAvailable(): Boolean {
|
||||
return withContext(dispatcherIO) {
|
||||
try {
|
||||
ktorHttpClient.head<String>("http://google.com")
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
println(e.message)
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createHttpClient(enableNetworkLogs: Boolean = false,serializer: KotlinxSerializer = kotlinxSerializer) = HttpClient {
|
||||
install(JsonFeature) {
|
||||
|
@ -13,6 +13,8 @@ expect fun showPopUpMessage(text: String)
|
||||
|
||||
expect val dispatcherIO: CoroutineDispatcher
|
||||
|
||||
expect val isInternetAvailable:Boolean
|
||||
|
||||
expect suspend fun downloadTracks(
|
||||
list: List<TrackDetails>,
|
||||
getYTIDBestMatch:suspend (String,TrackDetails)->String?,
|
||||
|
@ -12,7 +12,7 @@ import io.ktor.client.request.forms.*
|
||||
import io.ktor.http.*
|
||||
|
||||
suspend fun authenticateSpotify(): TokenData? {
|
||||
return if(isInternetAvailable()) spotifyAuthClient.post("https://accounts.spotify.com/api/token"){
|
||||
return if(isInternetAvailable) spotifyAuthClient.post("https://accounts.spotify.com/api/token"){
|
||||
body = FormDataContent(Parameters.build { append("grant_type","client_credentials") })
|
||||
} else null
|
||||
}
|
||||
|
@ -11,8 +11,12 @@ import com.github.kiulian.downloader.model.quality.AudioQuality
|
||||
import com.shabinder.common.models.DownloadResult
|
||||
import com.shabinder.common.models.DownloadStatus
|
||||
import com.shabinder.common.models.TrackDetails
|
||||
import io.ktor.client.request.*
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
actual fun openPlatform(packageID:String, platformLink:String){
|
||||
//TODO
|
||||
@ -26,21 +30,31 @@ actual fun giveDonation(){
|
||||
//TODO
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
actual fun AlertDialog(
|
||||
onDismissRequest: () -> Unit,
|
||||
buttons: @Composable () -> Unit,
|
||||
modifier: Modifier,
|
||||
title: (@Composable () -> Unit)?,
|
||||
text: @Composable (() -> Unit)?,
|
||||
shape: Shape,
|
||||
backgroundColor: Color,
|
||||
contentColor: Color,
|
||||
){}
|
||||
|
||||
actual fun queryActiveTracks(){}
|
||||
|
||||
/*
|
||||
* 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(){
|
||||
var result = false
|
||||
val job = GlobalScope.launch { result = isInternetAvailable() }
|
||||
while(job.isActive){}
|
||||
return result
|
||||
}
|
||||
|
||||
val DownloadProgressFlow: MutableSharedFlow<HashMap<String,DownloadStatus>> = MutableSharedFlow(1)
|
||||
|
||||
actual suspend fun downloadTracks(
|
||||
|
@ -3,6 +3,8 @@ package com.shabinder.common.main.integration
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import com.arkivanov.decompose.ComponentContext
|
||||
import com.arkivanov.mvikotlin.extensions.coroutines.states
|
||||
import com.shabinder.common.di.isInternetAvailable
|
||||
import com.shabinder.common.di.showPopUpMessage
|
||||
import com.shabinder.common.main.SpotiFlyerMain
|
||||
import com.shabinder.common.main.SpotiFlyerMain.*
|
||||
import com.shabinder.common.main.store.SpotiFlyerMainStore.Intent
|
||||
@ -26,7 +28,8 @@ internal class SpotiFlyerMainImpl(
|
||||
override val models: Flow<State> = store.states
|
||||
|
||||
override fun onLinkSearch(link: String) {
|
||||
mainOutput.callback(Output.Search(link = link))
|
||||
if(isInternetAvailable) mainOutput.callback(Output.Search(link = link))
|
||||
else showPopUpMessage("Check Network Connection Please")
|
||||
}
|
||||
|
||||
override fun onInputLinkChanged(link: String) {
|
||||
|
Loading…
Reference in New Issue
Block a user