Network/Permissions Dialogs Anim.

This commit is contained in:
shabinder 2021-02-26 15:11:25 +05:30
parent bf6463a3e1
commit 65427793fc
11 changed files with 158 additions and 141 deletions

2
.gitignore vendored
View File

@ -117,3 +117,5 @@
/common/list/build/
/common/main/build/
/common/root/build/
/android/release/
/android/google-services.json

View File

@ -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 {

View File

@ -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
)
}
}

View File

@ -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) {

View File

@ -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()
}

View File

@ -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()
}
/**

View File

@ -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) {

View File

@ -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?,

View File

@ -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
}

View File

@ -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(

View File

@ -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) {