diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4826897..27268bc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,7 @@ + diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/components/dialogs/NetworkWarningDialog.kt b/app/src/main/kotlin/com/aliucord/manager/ui/components/dialogs/NetworkWarningDialog.kt new file mode 100644 index 0000000..4d67937 --- /dev/null +++ b/app/src/main/kotlin/com/aliucord/manager/ui/components/dialogs/NetworkWarningDialog.kt @@ -0,0 +1,46 @@ +package com.aliucord.manager.ui.components.dialogs + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Warning +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import com.aliucord.manager.R + +@Composable +fun NetworkWarningDialog( + onConfirm: () -> Unit, + onDismiss: () -> Unit, +) { + AlertDialog( + onDismissRequest = onDismiss, + confirmButton = { + FilledTonalButton( + onClick = onConfirm, + colors = ButtonDefaults.filledTonalButtonColors( + containerColor = MaterialTheme.colorScheme.error, + contentColor = MaterialTheme.colorScheme.onError, + ), + ) { + Text(stringResource(R.string.action_confirm)) + } + }, + dismissButton = { + TextButton( + onClick = onDismiss, + colors = ButtonDefaults.textButtonColors( + contentColor = MaterialTheme.colorScheme.onErrorContainer + ), + ) { + Text(stringResource(R.string.action_cancel)) + } + }, + title = { Text(stringResource(R.string.network_warning_title)) }, + text = { Text(stringResource(R.string.network_warning_body)) }, + icon = { Icon(Icons.Filled.Warning, contentDescription = null) }, + containerColor = MaterialTheme.colorScheme.errorContainer, + iconContentColor = MaterialTheme.colorScheme.onErrorContainer, + titleContentColor = MaterialTheme.colorScheme.onErrorContainer, + textContentColor = MaterialTheme.colorScheme.onErrorContainer, + ) +} diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeModel.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeModel.kt index a3f1827..e524a13 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeModel.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeModel.kt @@ -3,11 +3,15 @@ package com.aliucord.manager.ui.screens.home import android.app.Application import android.content.Intent import android.content.pm.PackageManager +import android.net.ConnectivityManager import android.provider.Settings +import android.telephony.TelephonyManager import android.util.Log +import android.widget.Toast import androidx.compose.runtime.* import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.painter.BitmapPainter +import androidx.core.content.getSystemService import androidx.core.graphics.drawable.toBitmap import androidx.core.net.toUri import cafe.adriel.voyager.core.model.ScreenModel @@ -55,6 +59,41 @@ class HomeModel( application.startActivity(launchIntent) } + fun showMultiInstallToast() { + Toast.makeText(application, "Multi-install support is coming soon!", Toast.LENGTH_SHORT).show() + } + + /** + * Check whether the device is connected on a metered WIFI connection or through any type of mobile data, + * to avoid unknowingly downloading a lot of stuff through a potentially metered network. + */ + @Suppress("DEPRECATION") + fun isNetworkDangerous(): Boolean { + val connectivity = application.getSystemService() + ?: error("Unable to get system connectivity service") + + if (connectivity.isActiveNetworkMetered) return true + + when (val info = connectivity.activeNetworkInfo) { + null -> return false + else -> { + if (info.isRoaming) return true + if (info.type == ConnectivityManager.TYPE_WIFI) return false + } + } + + val telephony = application.getSystemService() + ?: error("Unable to get system telephony service") + + val dangerousMobileDataStates = arrayOf( + /* TelephonyManager.DATA_DISCONNECTING */ 4, + TelephonyManager.DATA_CONNECTED, + TelephonyManager.DATA_CONNECTING, + ) + + return dangerousMobileDataStates.contains(telephony.dataState) + } + private fun fetchInstallations() = screenModelScope.launchBlock { try { val packageManager = application.packageManager diff --git a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeScreen.kt b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeScreen.kt index d0142a1..36b4d04 100644 --- a/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeScreen.kt +++ b/app/src/main/kotlin/com/aliucord/manager/ui/screens/home/HomeScreen.kt @@ -27,6 +27,7 @@ import cafe.adriel.voyager.navigator.currentOrThrow import com.aliucord.manager.R import com.aliucord.manager.ui.components.ProjectHeader import com.aliucord.manager.ui.components.dialogs.InstallerDialog +import com.aliucord.manager.ui.components.dialogs.NetworkWarningDialog import com.aliucord.manager.ui.screens.home.components.* import com.aliucord.manager.ui.screens.install.InstallScreen import com.aliucord.manager.ui.screens.plugins.PluginsScreen @@ -42,7 +43,33 @@ class HomeScreen : Screen { val navigator = LocalNavigator.currentOrThrow val model = getScreenModel() + var showNetworkWarningDialog by remember { mutableStateOf(false) } var showInstallerDialog by remember { mutableStateOf(false) } + + val onClickInstall: () -> Unit = remember { + { + if ((model.installations as? InstallsState.Fetched)?.data?.isNotEmpty() == false) { + model.showMultiInstallToast() + } else if (model.isNetworkDangerous()) { + showNetworkWarningDialog = true + } else { + showInstallerDialog = true + } + } + } + + if (showNetworkWarningDialog) { + NetworkWarningDialog( + onConfirm = { + showNetworkWarningDialog = false + showInstallerDialog = true + }, + onDismiss = { + showNetworkWarningDialog = false + }, + ) + } + if (showInstallerDialog) { InstallerDialog( onDismiss = { showInstallerDialog = false }, @@ -72,9 +99,7 @@ class HomeScreen : Screen { item(key = "ADD_INSTALL_BUTTON") { InstallButton( - // TODO: install options screen to configure pkg name - enabled = (model.installations as? InstallsState.Fetched)?.data?.isEmpty() ?: false, - onClick = { showInstallerDialog = true }, + onClick = onClickInstall, modifier = Modifier .fillMaxWidth() .padding(top = 10.dp) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8f26dd7..73b21c8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -80,6 +80,8 @@ §name§%1$s§ §middle§authored§ §commit§%2$s§ Failed to load + Metered network + It appears you are connected to mobile data or a potentially metered network. In order to continue with the installation, several hundred megabytes could be downloaded. Are you sure you want to continue? Package: Discord version: