From 7741394c9c57d0e41aafd1e89ca12dbffa0a97c4 Mon Sep 17 00:00:00 2001 From: Ushie Date: Wed, 1 Nov 2023 20:54:06 +0300 Subject: [PATCH] feat(NotificationCard): rewrite & consistent usage (#1426) --- .../manager/ui/component/NotificationCard.kt | 156 +++++++++++++++--- .../component/bundle/BundlePatchesDialog.kt | 13 +- .../manager/ui/screen/InstalledAppsScreen.kt | 22 +-- .../manager/ui/screen/SettingsScreen.kt | 43 +---- .../settings/update/UpdatesSettingsScreen.kt | 45 +---- app/src/main/res/values/strings.xml | 4 +- 6 files changed, 163 insertions(+), 120 deletions(-) diff --git a/app/src/main/java/app/revanced/manager/ui/component/NotificationCard.kt b/app/src/main/java/app/revanced/manager/ui/component/NotificationCard.kt index a4e2129716..e5d5074bbf 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/NotificationCard.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/NotificationCard.kt @@ -1,59 +1,171 @@ package app.revanced.manager.ui.component -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Close import androidx.compose.material3.Card -import androidx.compose.material3.CardColors import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import app.revanced.manager.R @Composable fun NotificationCard( - color: Color, + isWarning: Boolean = false, + title: String? = null, + text: String, icon: ImageVector, + actions: (@Composable () -> Unit)? +) { + NotificationCardInstance(isWarning = isWarning) { + Column( + modifier = Modifier.padding(if (title != null) 20.dp else 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + if (title != null) { + Icon( + modifier = Modifier.size(36.dp), + imageVector = icon, + contentDescription = null, + tint = if (isWarning) MaterialTheme.colorScheme.onError else MaterialTheme.colorScheme.onPrimaryContainer + ) + Column( + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = title, + style = MaterialTheme.typography.titleLarge, + color = if (isWarning) MaterialTheme.colorScheme.onError else MaterialTheme.colorScheme.onPrimaryContainer + ) + Text( + text = text, + style = MaterialTheme.typography.bodyMedium, + color = if (isWarning) MaterialTheme.colorScheme.onError else MaterialTheme.colorScheme.onPrimaryContainer + ) + } + } else { + Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) { + Icon( + modifier = Modifier.size(24.dp), + imageVector = icon, + contentDescription = null, + tint = if (isWarning) MaterialTheme.colorScheme.onError else MaterialTheme.colorScheme.onPrimaryContainer + ) + Text( + text = text, + style = MaterialTheme.typography.bodyMedium, + color = if (isWarning) MaterialTheme.colorScheme.onError else MaterialTheme.colorScheme.onPrimaryContainer + ) + } + } + actions?.invoke() + } + } +} + +@Composable +fun NotificationCard( + isWarning: Boolean = false, + title: String? = null, text: String, - content: (@Composable () -> Unit)? = null, + icon: ImageVector, + onDismiss: (() -> Unit)? = null, + primaryAction: (() -> Unit)? = null ) { - Card( - colors = CardDefaults.cardColors(containerColor = color), - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(28.dp)) - ) { + NotificationCardInstance(isWarning = isWarning, onClick = primaryAction) { Row( modifier = Modifier .fillMaxWidth() .padding(16.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy( - 16.dp, - Alignment.Start - ) + horizontalArrangement = Arrangement.spacedBy(16.dp), ) { Icon( + modifier = Modifier.size(if (title != null) 36.dp else 24.dp), imageVector = icon, contentDescription = null, + tint = if (isWarning) MaterialTheme.colorScheme.onError else MaterialTheme.colorScheme.onPrimaryContainer ) - Text( - modifier = if (content != null) Modifier.width(220.dp) else Modifier, - text = text, - style = MaterialTheme.typography.bodyMedium - ) - content?.invoke() + if (title != null) { + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(6.dp) + ) { + Text( + text = title, + style = MaterialTheme.typography.titleLarge, + color = if (isWarning) MaterialTheme.colorScheme.onError else MaterialTheme.colorScheme.onPrimaryContainer + ) + Text( + text = text, + style = MaterialTheme.typography.bodyMedium, + color = if (isWarning) MaterialTheme.colorScheme.onError else MaterialTheme.colorScheme.onPrimaryContainer + ) + } + } else { + Text( + modifier = Modifier.weight(1f), + text = text, + style = MaterialTheme.typography.bodyMedium, + color = if (isWarning) MaterialTheme.colorScheme.onError else MaterialTheme.colorScheme.onPrimaryContainer + ) + } + if (onDismiss != null) { + IconButton(onClick = onDismiss) { + Icon( + imageVector = Icons.Outlined.Close, + contentDescription = stringResource(R.string.close), + tint = if (isWarning) MaterialTheme.colorScheme.onError else MaterialTheme.colorScheme.onPrimaryContainer + ) + } + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun NotificationCardInstance( + isWarning: Boolean = false, + onClick: (() -> Unit)? = null, + content: (@Composable () -> Unit), +) { + if (onClick != null) { + Card( + onClick = onClick, + colors = CardDefaults.cardColors(containerColor = (if (isWarning) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primaryContainer)), + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + .clip(RoundedCornerShape(24.dp)) + ) { + content.invoke() + } + } else { + Card( + colors = CardDefaults.cardColors(containerColor = (if (isWarning) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primaryContainer)), + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + .clip(RoundedCornerShape(24.dp)) + ) { + content.invoke() } } } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundlePatchesDialog.kt b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundlePatchesDialog.kt index 2ff2a555ab..a78cbb5931 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/bundle/BundlePatchesDialog.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/bundle/BundlePatchesDialog.kt @@ -70,17 +70,10 @@ fun BundlePatchesDialog( item { AnimatedVisibility(visible = informationCardVisible) { NotificationCard( - color = MaterialTheme.colorScheme.secondaryContainer, icon = Icons.Outlined.Lightbulb, - text = stringResource(R.string.tap_on_patches) - ) { - IconButton(onClick = { informationCardVisible = false }) { - Icon( - imageVector = Icons.Outlined.Close, - contentDescription = stringResource(R.string.close), - ) - } - } + text = stringResource(R.string.tap_on_patches), + onDismiss = { informationCardVisible = false } + ) } } diff --git a/app/src/main/java/app/revanced/manager/ui/screen/InstalledAppsScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/InstalledAppsScreen.kt index 2a2a2b8951..c7535a6a58 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/InstalledAppsScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/InstalledAppsScreen.kt @@ -2,10 +2,8 @@ package app.revanced.manager.ui.screen import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -18,7 +16,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -40,16 +37,15 @@ fun InstalledAppsScreen( val installedApps by viewModel.apps.collectAsStateWithLifecycle(initialValue = null) Column { - if (!Aapt.supportsDevice()) - Box(modifier = Modifier.padding(16.dp)) { - NotificationCard( - color = MaterialTheme.colorScheme.errorContainer, - icon = Icons.Outlined.WarningAmber, - text = stringResource( - R.string.unsupported_architecture_warning - ), - ) - } + if (!Aapt.supportsDevice()) { + NotificationCard( + isWarning = true, + icon = Icons.Outlined.WarningAmber, + text = stringResource( + R.string.unsupported_architecture_warning + ), + ) + } LazyColumn( modifier = Modifier.fillMaxSize(), diff --git a/app/src/main/java/app/revanced/manager/ui/screen/SettingsScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/SettingsScreen.kt index 6c26d84fa3..dc57665a46 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/SettingsScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/SettingsScreen.kt @@ -7,8 +7,6 @@ import android.net.Uri import android.os.PowerManager import android.provider.Settings import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -16,9 +14,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.BatteryAlert @@ -29,14 +25,13 @@ 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.draw.clip import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import app.revanced.manager.R import app.revanced.manager.ui.component.AppTopBar +import app.revanced.manager.ui.component.NotificationCard import app.revanced.manager.ui.destination.SettingsDestination import app.revanced.manager.ui.screen.settings.* import app.revanced.manager.ui.screen.settings.update.ManagerUpdateChangelog @@ -161,40 +156,18 @@ fun SettingsScreen( .verticalScroll(rememberScrollState()) ) { AnimatedVisibility(visible = showBatteryButton) { - Card( - onClick = { + NotificationCard( + isWarning = true, + icon = Icons.Default.BatteryAlert, + text = stringResource(R.string.battery_optimization_notification), + primaryAction = { context.startActivity(Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).apply { data = Uri.parse("package:${context.packageName}") }) showBatteryButton = !pm.isIgnoringBatteryOptimizations(context.packageName) - }, - modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - .clip(RoundedCornerShape(24.dp)) - .background(MaterialTheme.colorScheme.tertiaryContainer), - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - Icon( - imageVector = Icons.Default.BatteryAlert, - contentDescription = null, - tint = MaterialTheme.colorScheme.onTertiaryContainer, - modifier = Modifier.size(24.dp) - ) - Text( - text = stringResource(R.string.battery_optimization_notification), - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onTertiaryContainer - ) } - } + ) } settingsSections.forEach { (titleDescIcon, destination) -> SettingsListItem( @@ -209,4 +182,4 @@ fun SettingsScreen( } } } -} +} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/manager/ui/screen/settings/update/UpdatesSettingsScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/settings/update/UpdatesSettingsScreen.kt index 65ebe35b34..cac4acdd25 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/settings/update/UpdatesSettingsScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/settings/update/UpdatesSettingsScreen.kt @@ -1,33 +1,26 @@ package app.revanced.manager.ui.screen.settings.update -import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Update import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import app.revanced.manager.R import app.revanced.manager.ui.component.AppTopBar +import app.revanced.manager.ui.component.NotificationCard import app.revanced.manager.ui.component.SettingsListItem @OptIn(ExperimentalMaterial3Api::class) @@ -70,8 +63,10 @@ fun UpdatesSettingsScreen( .padding(paddingValues) .verticalScroll(rememberScrollState()) ) { - UpdateNotification( - onClick = onUpdateClick + NotificationCard( + text = stringResource(R.string.update_notification), + icon = Icons.Default.Update, + primaryAction = onUpdateClick ) listItems.forEach { (title, description, onClick) -> @@ -86,32 +81,4 @@ fun UpdatesSettingsScreen( } } } -} - -@Composable -fun UpdateNotification( - onClick: () -> Unit -) { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - .clip(RoundedCornerShape(24.dp)) - .background(MaterialTheme.colorScheme.secondaryContainer) - .clickable { onClick() }, - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - Icon(imageVector = Icons.Default.Update, contentDescription = null) - Text( - text = stringResource(R.string.update_notification), - style = MaterialTheme.typography.bodyMedium - ) - } - } -} +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 23f491594f..0f6c6edac6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -254,6 +254,7 @@ More Continue + Dismiss Do not show this again Donate Website @@ -281,7 +282,7 @@ Loading changelog Failed to download changelog: %s Check out the latest changes in this update - Battery optimization must be turned off in order for ReVanced Manager to work correctly in the background. Tap here to turn off. + Battery optimization must be turned off in order for ReVanced Manager to work correctly in the background. Click here to turn off. Installing update… Downloading update… Failed to download update: %s @@ -289,4 +290,5 @@ Save Update Tap on Update when prompted. \n ReVanced Manager will close when updating. + Disable battery optimization \ No newline at end of file